aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media')
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/atomisp/Makefile1
-rw-r--r--drivers/staging/media/atomisp/TODO5
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c57
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc2235.c37
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c6
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c120
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2680.c36
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2722.c28
-rw-r--r--drivers/staging/media/atomisp/i2c/mt9m114.h6
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2680.h10
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_acc.c12
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.c52
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.h161
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.c1202
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.c28
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_file.c14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.c18
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c68
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.h9
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_tpg.c12
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c6
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c2089
-rw-r--r--drivers/staging/media/av7110/Kconfig94
-rw-r--r--drivers/staging/media/av7110/Makefile22
-rw-r--r--drivers/staging/media/av7110/TODO3
-rw-r--r--drivers/staging/media/av7110/audio-bilingual-channel-select.rst58
-rw-r--r--drivers/staging/media/av7110/audio-channel-select.rst57
-rw-r--r--drivers/staging/media/av7110/audio-clear-buffer.rst48
-rw-r--r--drivers/staging/media/av7110/audio-continue.rst48
-rw-r--r--drivers/staging/media/av7110/audio-fclose.rst51
-rw-r--r--drivers/staging/media/av7110/audio-fopen.rst103
-rw-r--r--drivers/staging/media/av7110/audio-fwrite.rst79
-rw-r--r--drivers/staging/media/av7110/audio-get-capabilities.rst54
-rw-r--r--drivers/staging/media/av7110/audio-get-status.rst54
-rw-r--r--drivers/staging/media/av7110/audio-pause.rst49
-rw-r--r--drivers/staging/media/av7110/audio-play.rst48
-rw-r--r--drivers/staging/media/av7110/audio-select-source.rst56
-rw-r--r--drivers/staging/media/av7110/audio-set-av-sync.rst58
-rw-r--r--drivers/staging/media/av7110/audio-set-bypass-mode.rst62
-rw-r--r--drivers/staging/media/av7110/audio-set-id.rst59
-rw-r--r--drivers/staging/media/av7110/audio-set-mixer.rst53
-rw-r--r--drivers/staging/media/av7110/audio-set-mute.rst62
-rw-r--r--drivers/staging/media/av7110/audio-set-streamtype.rst66
-rw-r--r--drivers/staging/media/av7110/audio-stop.rst48
-rw-r--r--drivers/staging/media/av7110/audio.h101
-rw-r--r--drivers/staging/media/av7110/audio.rst27
-rw-r--r--drivers/staging/media/av7110/audio_data_types.rst116
-rw-r--r--drivers/staging/media/av7110/audio_function_calls.rst30
-rw-r--r--drivers/staging/media/av7110/av7110.c2919
-rw-r--r--drivers/staging/media/av7110/av7110.h316
-rw-r--r--drivers/staging/media/av7110/av7110_av.c1681
-rw-r--r--drivers/staging/media/av7110/av7110_av.h32
-rw-r--r--drivers/staging/media/av7110/av7110_ca.c380
-rw-r--r--drivers/staging/media/av7110/av7110_ca.h15
-rw-r--r--drivers/staging/media/av7110/av7110_hw.c1204
-rw-r--r--drivers/staging/media/av7110/av7110_hw.h496
-rw-r--r--drivers/staging/media/av7110/av7110_ipack.c404
-rw-r--r--drivers/staging/media/av7110/av7110_ipack.h13
-rw-r--r--drivers/staging/media/av7110/av7110_ir.c158
-rw-r--r--drivers/staging/media/av7110/av7110_v4l.c952
-rw-r--r--drivers/staging/media/av7110/budget-patch.c665
-rw-r--r--drivers/staging/media/av7110/dvb_filter.c115
-rw-r--r--drivers/staging/media/av7110/dvb_filter.h242
-rw-r--r--drivers/staging/media/av7110/osd.h181
-rw-r--r--drivers/staging/media/av7110/sp8870.c609
-rw-r--r--drivers/staging/media/av7110/sp8870.h37
-rw-r--r--drivers/staging/media/av7110/video-clear-buffer.rst54
-rw-r--r--drivers/staging/media/av7110/video-command.rst96
-rw-r--r--drivers/staging/media/av7110/video-continue.rst57
-rw-r--r--drivers/staging/media/av7110/video-fast-forward.rst72
-rw-r--r--drivers/staging/media/av7110/video-fclose.rst51
-rw-r--r--drivers/staging/media/av7110/video-fopen.rst111
-rw-r--r--drivers/staging/media/av7110/video-freeze.rst61
-rw-r--r--drivers/staging/media/av7110/video-fwrite.rst79
-rw-r--r--drivers/staging/media/av7110/video-get-capabilities.rst61
-rw-r--r--drivers/staging/media/av7110/video-get-event.rst105
-rw-r--r--drivers/staging/media/av7110/video-get-frame-count.rst65
-rw-r--r--drivers/staging/media/av7110/video-get-pts.rst69
-rw-r--r--drivers/staging/media/av7110/video-get-size.rst69
-rw-r--r--drivers/staging/media/av7110/video-get-status.rst72
-rw-r--r--drivers/staging/media/av7110/video-play.rst57
-rw-r--r--drivers/staging/media/av7110/video-select-source.rst76
-rw-r--r--drivers/staging/media/av7110/video-set-blank.rst64
-rw-r--r--drivers/staging/media/av7110/video-set-display-format.rst60
-rw-r--r--drivers/staging/media/av7110/video-set-format.rst82
-rw-r--r--drivers/staging/media/av7110/video-set-streamtype.rst61
-rw-r--r--drivers/staging/media/av7110/video-slowmotion.rst72
-rw-r--r--drivers/staging/media/av7110/video-stillpicture.rst61
-rw-r--r--drivers/staging/media/av7110/video-stop.rst74
-rw-r--r--drivers/staging/media/av7110/video-try-command.rst66
-rw-r--r--drivers/staging/media/av7110/video.h220
-rw-r--r--drivers/staging/media/av7110/video.rst36
-rw-r--r--drivers/staging/media/av7110/video_function_calls.rst35
-rw-r--r--drivers/staging/media/av7110/video_types.rst248
-rw-r--r--drivers/staging/media/hantro/Kconfig10
-rw-r--r--drivers/staging/media/hantro/Makefile15
-rw-r--r--drivers/staging/media/hantro/hantro.h13
-rw-r--r--drivers/staging/media/hantro/hantro_drv.c185
-rw-r--r--drivers/staging/media/hantro/hantro_g1.c39
-rw-r--r--drivers/staging/media/hantro/hantro_g1_h264_dec.c10
-rw-r--r--drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c119
-rw-r--r--drivers/staging/media/hantro/hantro_g1_vp8_dec.c6
-rw-r--r--drivers/staging/media/hantro/hantro_g2_hevc_dec.c586
-rw-r--r--drivers/staging/media/hantro/hantro_g2_regs.h198
-rw-r--r--drivers/staging/media/hantro/hantro_h1_jpeg_enc.c4
-rw-r--r--drivers/staging/media/hantro/hantro_hevc.c333
-rw-r--r--drivers/staging/media/hantro/hantro_hw.h101
-rw-r--r--drivers/staging/media/hantro/hantro_mpeg2.c2
-rw-r--r--drivers/staging/media/hantro/hantro_postproc.c14
-rw-r--r--drivers/staging/media/hantro/hantro_v4l2.c14
-rw-r--r--drivers/staging/media/hantro/imx8m_vpu_hw.c79
-rw-r--r--drivers/staging/media/hantro/rk3288_vpu_hw.c236
-rw-r--r--drivers/staging/media/hantro/rk3399_vpu_hw.c222
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c (renamed from drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c)32
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_mpeg2_dec.c (renamed from drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c)123
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c (renamed from drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c)6
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_regs.h (renamed from drivers/staging/media/hantro/rk3399_vpu_regs.h)6
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu_hw.c526
-rw-r--r--drivers/staging/media/hantro/sama5d4_vdec_hw.c117
-rw-r--r--drivers/staging/media/imx/imx-ic-prp.c19
-rw-r--r--drivers/staging/media/imx/imx-ic-prpencvf.c31
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c96
-rw-r--r--drivers/staging/media/imx/imx-media-utils.c4
-rw-r--r--drivers/staging/media/imx/imx-media-vdic.c24
-rw-r--r--drivers/staging/media/imx/imx-media.h2
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c12
-rw-r--r--drivers/staging/media/imx/imx7-media-csi.c33
-rw-r--r--drivers/staging/media/imx/imx7-mipi-csis.c1020
-rw-r--r--drivers/staging/media/ipu3/include/uapi/intel-ipu3.h (renamed from drivers/staging/media/ipu3/include/intel-ipu3.h)13
-rw-r--r--drivers/staging/media/ipu3/ipu3-abi.h2
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-pool.h1
-rw-r--r--drivers/staging/media/ipu3/ipu3-v4l2.c26
-rw-r--r--drivers/staging/media/ipu3/ipu3.c3
-rw-r--r--drivers/staging/media/meson/vdec/vdec_helpers.c2
-rw-r--r--drivers/staging/media/omap4iss/iss.h3
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c37
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.c37
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.c47
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.c39
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c4
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.c12
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c16
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.h6
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_dec.c12
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h265.c16
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c97
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_video.c14
-rw-r--r--drivers/staging/media/tegra-vde/vde.c22
-rw-r--r--drivers/staging/media/tegra-video/csi.c13
-rw-r--r--drivers/staging/media/tegra-video/vi.c31
-rw-r--r--drivers/staging/media/zoran/zoran.h1
-rw-r--r--drivers/staging/media/zoran/zoran_card.c7
-rw-r--r--drivers/staging/media/zoran/zoran_device.c65
-rw-r--r--drivers/staging/media/zoran/zoran_device.h2
-rw-r--r--drivers/staging/media/zoran/zoran_driver.c6
-rw-r--r--drivers/staging/media/zoran/zr36016.c3
-rw-r--r--drivers/staging/media/zoran/zr36050.c5
-rw-r--r--drivers/staging/media/zoran/zr36057.h14
-rw-r--r--drivers/staging/media/zoran/zr36060.c3
164 files changed, 18727 insertions, 4224 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index ca59986b20f8..e3aaae920847 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -42,4 +42,6 @@ source "drivers/staging/media/tegra-video/Kconfig"
source "drivers/staging/media/ipu3/Kconfig"
+source "drivers/staging/media/av7110/Kconfig"
+
endif
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 716929a1a313..5b5afc5b03a0 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_TEGRA_VDE) += tegra-vde/
obj-$(CONFIG_VIDEO_HANTRO) += hantro/
obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_DVB_AV7110) += av7110/
diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile
index 51498b2e85b8..606b7754fdfd 100644
--- a/drivers/staging/media/atomisp/Makefile
+++ b/drivers/staging/media/atomisp/Makefile
@@ -16,7 +16,6 @@ atomisp-objs += \
pci/atomisp_acc.o \
pci/atomisp_cmd.o \
pci/atomisp_compat_css20.o \
- pci/atomisp_compat_ioctl32.o \
pci/atomisp_csi2.o \
pci/atomisp_drvfs.o \
pci/atomisp_file.o \
diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO
index 6987bb2d32cf..2d1ef9eb262a 100644
--- a/drivers/staging/media/atomisp/TODO
+++ b/drivers/staging/media/atomisp/TODO
@@ -120,6 +120,11 @@ TODO
for this driver until the other work is done, as there will be a lot
of code churn until this driver becomes functional again.
+16. Fix private ioctls to not need a compat_ioctl handler for running
+ 32-bit tasks. The compat code has been removed because of bugs,
+ and should not be needed for modern drivers. Fixing this properly
+ unfortunately means an incompatible ABI change.
+
Limitations
===========
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
index d170d0adfea4..687888d643df 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
@@ -300,7 +300,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
/* pixel clock calculattion */
dev->vt_pix_clk_freq_mhz = 14400000; // 16.8MHz
buf->vt_pix_clk_freq_mhz = dev->vt_pix_clk_freq_mhz;
- pr_info("vt_pix_clk_freq_mhz=%d\n", buf->vt_pix_clk_freq_mhz);
+ dev_dbg(&client->dev, "vt_pix_clk_freq_mhz=%d\n", buf->vt_pix_clk_freq_mhz);
/* get integration time */
buf->coarse_integration_time_min = GC0310_COARSE_INTG_TIME_MIN;
@@ -326,7 +326,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
if (ret)
return ret;
buf->crop_horizontal_start = val | (reg_val & 0xFF);
- pr_info("crop_horizontal_start=%d\n", buf->crop_horizontal_start);
+ dev_dbg(&client->dev, "crop_horizontal_start=%d\n", buf->crop_horizontal_start);
/* Getting crop_vertical_start */
ret = gc0310_read_reg(client, GC0310_8BIT,
@@ -339,7 +339,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
if (ret)
return ret;
buf->crop_vertical_start = val | (reg_val & 0xFF);
- pr_info("crop_vertical_start=%d\n", buf->crop_vertical_start);
+ dev_dbg(&client->dev, "crop_vertical_start=%d\n", buf->crop_vertical_start);
/* Getting output_width */
ret = gc0310_read_reg(client, GC0310_8BIT,
@@ -352,7 +352,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
if (ret)
return ret;
buf->output_width = val | (reg_val & 0xFF);
- pr_info("output_width=%d\n", buf->output_width);
+ dev_dbg(&client->dev, "output_width=%d\n", buf->output_width);
/* Getting output_height */
ret = gc0310_read_reg(client, GC0310_8BIT,
@@ -365,12 +365,12 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
if (ret)
return ret;
buf->output_height = val | (reg_val & 0xFF);
- pr_info("output_height=%d\n", buf->output_height);
+ dev_dbg(&client->dev, "output_height=%d\n", buf->output_height);
buf->crop_horizontal_end = buf->crop_horizontal_start + buf->output_width - 1;
buf->crop_vertical_end = buf->crop_vertical_start + buf->output_height - 1;
- pr_info("crop_horizontal_end=%d\n", buf->crop_horizontal_end);
- pr_info("crop_vertical_end=%d\n", buf->crop_vertical_end);
+ dev_dbg(&client->dev, "crop_horizontal_end=%d\n", buf->crop_horizontal_end);
+ dev_dbg(&client->dev, "crop_vertical_end=%d\n", buf->crop_vertical_end);
/* Getting line_length_pck */
ret = gc0310_read_reg(client, GC0310_8BIT,
@@ -389,7 +389,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
return ret;
sh_delay = reg_val;
buf->line_length_pck = buf->output_width + hori_blanking + sh_delay + 4;
- pr_info("hori_blanking=%d sh_delay=%d line_length_pck=%d\n", hori_blanking,
+ dev_dbg(&client->dev, "hori_blanking=%d sh_delay=%d line_length_pck=%d\n", hori_blanking,
sh_delay, buf->line_length_pck);
/* Getting frame_length_lines */
@@ -404,7 +404,7 @@ static int gc0310_get_intg_factor(struct i2c_client *client,
return ret;
vert_blanking = val | (reg_val & 0xFF);
buf->frame_length_lines = buf->output_height + vert_blanking;
- pr_info("vert_blanking=%d frame_length_lines=%d\n", vert_blanking,
+ dev_dbg(&client->dev, "vert_blanking=%d frame_length_lines=%d\n", vert_blanking,
buf->frame_length_lines);
buf->binning_factor_x = res->bin_factor_x ?
@@ -434,7 +434,7 @@ static int gc0310_set_gain(struct v4l2_subdev *sd, int gain)
dgain = gain / 2;
}
- pr_info("gain=0x%x again=0x%x dgain=0x%x\n", gain, again, dgain);
+ dev_dbg(&client->dev, "gain=0x%x again=0x%x dgain=0x%x\n", gain, again, dgain);
/* set analog gain */
ret = gc0310_write_reg(client, GC0310_8BIT,
@@ -458,7 +458,7 @@ static int __gc0310_set_exposure(struct v4l2_subdev *sd, int coarse_itg,
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
- pr_info("coarse_itg=%d gain=%d digitgain=%d\n", coarse_itg, gain, digitgain);
+ dev_dbg(&client->dev, "coarse_itg=%d gain=%d digitgain=%d\n", coarse_itg, gain, digitgain);
/* set exposure */
ret = gc0310_write_reg(client, GC0310_8BIT,
@@ -718,7 +718,6 @@ static int gc0310_init(struct v4l2_subdev *sd)
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct gc0310_device *dev = to_gc0310_sensor(sd);
- pr_info("%s S\n", __func__);
mutex_lock(&dev->input_lock);
/* set initial registers */
@@ -730,7 +729,6 @@ static int gc0310_init(struct v4l2_subdev *sd)
mutex_unlock(&dev->input_lock);
- pr_info("%s E\n", __func__);
return ret;
}
@@ -796,7 +794,6 @@ static int power_up(struct v4l2_subdev *sd)
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
- pr_info("%s S\n", __func__);
if (!dev->platform_data) {
dev_err(&client->dev,
"no camera_sensor_platform_data");
@@ -823,7 +820,6 @@ static int power_up(struct v4l2_subdev *sd)
msleep(100);
- pr_info("%s E\n", __func__);
return 0;
fail_gpio:
@@ -959,20 +955,17 @@ static int startup(struct v4l2_subdev *sd)
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret = 0;
- pr_info("%s S\n", __func__);
-
ret = gc0310_write_reg_array(client, gc0310_res[dev->fmt_idx].regs);
if (ret) {
dev_err(&client->dev, "gc0310 write register err.\n");
return ret;
}
- pr_info("%s E\n", __func__);
return ret;
}
static int gc0310_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -982,8 +975,6 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd,
int ret = 0;
int idx = 0;
- pr_info("%s S\n", __func__);
-
if (format->pad)
return -EINVAL;
@@ -1008,7 +999,7 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd,
fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
@@ -1020,8 +1011,8 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd,
return -EINVAL;
}
- printk("%s: before gc0310_write_reg_array %s\n", __func__,
- gc0310_res[dev->fmt_idx].desc);
+ dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n",
+ __func__, gc0310_res[dev->fmt_idx].desc);
ret = startup(sd);
if (ret) {
dev_err(&client->dev, "gc0310 startup err\n");
@@ -1035,14 +1026,13 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd,
goto err;
}
- pr_info("%s E\n", __func__);
err:
mutex_unlock(&dev->input_lock);
return ret;
}
static int gc0310_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -1068,7 +1058,6 @@ static int gc0310_detect(struct i2c_client *client)
int ret;
u16 id;
- pr_info("%s S\n", __func__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -1085,7 +1074,7 @@ static int gc0310_detect(struct i2c_client *client)
return -ENODEV;
}
id = ((((u16)high) << 8) | (u16)low);
- pr_info("sensor ID = 0x%x\n", id);
+ dev_dbg(&client->dev, "sensor ID = 0x%x\n", id);
if (id != GC0310_ID) {
dev_err(&client->dev, "sensor ID error, read id = 0x%x, target id = 0x%x\n", id,
@@ -1095,8 +1084,6 @@ static int gc0310_detect(struct i2c_client *client)
dev_dbg(&client->dev, "detect gc0310 success\n");
- pr_info("%s E\n", __func__);
-
return 0;
}
@@ -1106,7 +1093,7 @@ static int gc0310_s_stream(struct v4l2_subdev *sd, int enable)
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
- pr_info("%s S enable=%d\n", __func__, enable);
+ dev_dbg(&client->dev, "%s S enable=%d\n", __func__, enable);
mutex_lock(&dev->input_lock);
if (enable) {
@@ -1142,7 +1129,6 @@ static int gc0310_s_stream(struct v4l2_subdev *sd, int enable)
}
mutex_unlock(&dev->input_lock);
- pr_info("%s E\n", __func__);
return ret;
}
@@ -1153,7 +1139,6 @@ static int gc0310_s_config(struct v4l2_subdev *sd,
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret = 0;
- pr_info("%s S\n", __func__);
if (!platform_data)
return -ENODEV;
@@ -1196,7 +1181,6 @@ static int gc0310_s_config(struct v4l2_subdev *sd,
}
mutex_unlock(&dev->input_lock);
- pr_info("%s E\n", __func__);
return 0;
fail_csi_cfg:
@@ -1221,7 +1205,7 @@ static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
}
static int gc0310_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= MAX_FMTS)
@@ -1232,7 +1216,7 @@ static int gc0310_enum_mbus_code(struct v4l2_subdev *sd,
}
static int gc0310_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
int index = fse->index;
@@ -1365,7 +1349,6 @@ static int gc0310_probe(struct i2c_client *client)
if (ret)
gc0310_remove(client);
- pr_info("%s E\n", __func__);
return ret;
out_free:
v4l2_device_unregister_subdev(&dev->sd);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
index 78147ffb6099..9363c1a52ae9 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
@@ -171,8 +171,8 @@ static int __gc2235_buf_reg_array(struct i2c_client *client,
}
static int __gc2235_write_reg_is_consecutive(struct i2c_client *client,
- struct gc2235_write_ctrl *ctrl,
- const struct gc2235_reg *next)
+ struct gc2235_write_ctrl *ctrl,
+ const struct gc2235_reg *next)
{
if (ctrl->index == 0)
return 1;
@@ -228,7 +228,7 @@ static int gc2235_g_focal(struct v4l2_subdev *sd, s32 *val)
static int gc2235_g_fnumber(struct v4l2_subdev *sd, s32 *val)
{
- /*const f number for imx*/
+ /* const f number for imx */
*val = (GC2235_F_NUMBER_DEFAULT_NUM << 16) | GC2235_F_NUMBER_DEM;
return 0;
}
@@ -427,7 +427,8 @@ static long gc2235_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return 0;
}
-/* This returns the exposure time being used. This should only be used
+/*
+ * This returns the exposure time being used. This should only be used
* for filling in EXIF data, not for actual image processing.
*/
static int gc2235_q_exposure(struct v4l2_subdev *sd, s32 *value)
@@ -658,9 +659,9 @@ static int gc2235_s_power(struct v4l2_subdev *sd, int on)
{
int ret;
- if (on == 0)
+ if (on == 0) {
ret = power_down(sd);
- else {
+ } else {
ret = power_up(sd);
if (!ret)
ret = __gc2235_init(sd);
@@ -746,11 +747,12 @@ static int startup(struct v4l2_subdev *sd)
int ret = 0;
if (is_init == 0) {
- /* force gc2235 to do a reset in res change, otherwise it
- * can not output normal after switching res. and it is not
- * necessary for first time run up after power on, for the sack
- * of performance
- */
+ /*
+ * force gc2235 to do a reset in res change, otherwise it
+ * can not output normal after switching res. and it is not
+ * necessary for first time run up after power on, for the sack
+ * of performance
+ */
power_down(sd);
power_up(sd);
gc2235_write_reg_array(client, gc2235_init_settings);
@@ -767,7 +769,7 @@ static int startup(struct v4l2_subdev *sd)
}
static int gc2235_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -796,7 +798,7 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd,
}
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
@@ -825,7 +827,7 @@ err:
}
static int gc2235_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -904,7 +906,8 @@ static int gc2235_s_config(struct v4l2_subdev *sd,
(struct camera_sensor_platform_data *)platform_data;
mutex_lock(&dev->input_lock);
- /* power off the module, then power on it in future
+ /*
+ * power off the module, then power on it in future
* as first power on by board may not fulfill the
* power on sequqence needed by the module
*/
@@ -963,7 +966,7 @@ static int gc2235_g_frame_interval(struct v4l2_subdev *sd,
}
static int gc2235_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= MAX_FMTS)
@@ -974,7 +977,7 @@ static int gc2235_enum_mbus_code(struct v4l2_subdev *sd,
}
static int gc2235_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
int index = fse->index;
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c b/drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c
index b93c80471f22..7a20d918a9d5 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c
@@ -50,14 +50,16 @@ struct tbd_data_record_header {
static int set_msr_configuration(struct i2c_client *client, uint8_t *bufptr,
unsigned int size)
{
- /* The configuration data contains any number of sequences where
+ /*
+ * The configuration data contains any number of sequences where
* the first byte (that is, uint8_t) that marks the number of bytes
* in the sequence to follow, is indeed followed by the indicated
* number of bytes of actual data to be written to sensor.
* By convention, the first two bytes of actual data should be
* understood as an address in the sensor address space (hibyte
* followed by lobyte) where the remaining data in the sequence
- * will be written. */
+ * will be written.
+ */
u8 *ptr = bufptr;
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
index f5de81132177..11196180a206 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
@@ -475,10 +475,12 @@ static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
if (!dev || !dev->platform_data)
return -ENODEV;
- /* Note: current modules wire only one GPIO signal (RESET#),
+ /*
+ * Note: current modules wire only one GPIO signal (RESET#),
* but the schematic wires up two to the connector. BIOS
* versions have been unfortunately inconsistent with which
- * ACPI index RESET# is on, so hit both */
+ * ACPI index RESET# is on, so hit both
+ */
if (flag) {
ret = dev->platform_data->gpio0_ctrl(sd, 0);
@@ -560,7 +562,7 @@ static int power_down(struct v4l2_subdev *sd)
if (ret)
dev_err(&client->dev, "vprog failed.\n");
- /*according to DS, 20ms is needed after power down*/
+ /* according to DS, 20ms is needed after power down */
msleep(20);
return ret;
@@ -568,9 +570,9 @@ static int power_down(struct v4l2_subdev *sd)
static int mt9m114_s_power(struct v4l2_subdev *sd, int power)
{
- if (power == 0)
+ if (power == 0) {
return power_down(sd);
- else {
+ } else {
if (power_up(sd))
return -EINVAL;
@@ -801,7 +803,7 @@ static int mt9m114_get_intg_factor(struct i2c_client *client,
}
static int mt9m114_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -822,7 +824,7 @@ static int mt9m114_get_fmt(struct v4l2_subdev *sd,
}
static int mt9m114_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -846,7 +848,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd,
mt9m114_try_res(&width, &height);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
return 0;
}
res_index = mt9m114_to_res(width, height);
@@ -947,7 +949,7 @@ static int mt9m114_g_focal(struct v4l2_subdev *sd, s32 *val)
static int mt9m114_g_fnumber(struct v4l2_subdev *sd, s32 *val)
{
- /*const f number for mt9m114*/
+ /* const f number for mt9m114 */
*val = (MT9M114_F_NUMBER_DEFAULT_NUM << 16) | MT9M114_F_NUMBER_DEM;
return 0;
}
@@ -998,44 +1000,48 @@ static long mt9m114_s_exposure(struct v4l2_subdev *sd,
struct mt9m114_device *dev = to_mt9m114_sensor(sd);
int ret = 0;
unsigned int coarse_integration = 0;
- unsigned int FLines = 0;
- unsigned int FrameLengthLines = 0; /* ExposureTime.FrameLengthLines; */
- unsigned int AnalogGain, DigitalGain;
- u32 AnalogGainToWrite = 0;
+ unsigned int f_lines = 0;
+ unsigned int frame_len_lines = 0; /* ExposureTime.FrameLengthLines; */
+ unsigned int analog_gain, digital_gain;
+ u32 analog_gain_to_write = 0;
dev_dbg(&client->dev, "%s(0x%X 0x%X 0x%X)\n", __func__,
exposure->integration_time[0], exposure->gain[0],
exposure->gain[1]);
coarse_integration = exposure->integration_time[0];
- /* fine_integration = ExposureTime.FineIntegrationTime; */
- /* FrameLengthLines = ExposureTime.FrameLengthLines; */
- FLines = mt9m114_res[dev->res].lines_per_frame;
- AnalogGain = exposure->gain[0];
- DigitalGain = exposure->gain[1];
+ /*
+ * fine_integration = ExposureTime.FineIntegrationTime;
+ * frame_len_lines = ExposureTime.FrameLengthLines;
+ */
+ f_lines = mt9m114_res[dev->res].lines_per_frame;
+ analog_gain = exposure->gain[0];
+ digital_gain = exposure->gain[1];
if (!dev->streamon) {
/*Save the first exposure values while stream is off*/
dev->first_exp = coarse_integration;
- dev->first_gain = AnalogGain;
- dev->first_diggain = DigitalGain;
+ dev->first_gain = analog_gain;
+ dev->first_diggain = digital_gain;
}
- /* DigitalGain = 0x400 * (((u16) DigitalGain) >> 8) +
- ((unsigned int)(0x400 * (((u16) DigitalGain) & 0xFF)) >>8); */
+ /* digital_gain = 0x400 * (((u16) digital_gain) >> 8) + */
+ /* ((unsigned int)(0x400 * (((u16) digital_gain) & 0xFF)) >>8); */
/* set frame length */
- if (FLines < coarse_integration + 6)
- FLines = coarse_integration + 6;
- if (FLines < FrameLengthLines)
- FLines = FrameLengthLines;
- ret = mt9m114_write_reg(client, MISENSOR_16BIT, 0x300A, FLines);
+ if (f_lines < coarse_integration + 6)
+ f_lines = coarse_integration + 6;
+ if (f_lines < frame_len_lines)
+ f_lines = frame_len_lines;
+ ret = mt9m114_write_reg(client, MISENSOR_16BIT, 0x300A, f_lines);
if (ret) {
- v4l2_err(client, "%s: fail to set FLines\n", __func__);
+ v4l2_err(client, "%s: fail to set f_lines\n", __func__);
return -EINVAL;
}
/* set coarse integration */
- /* 3A provide real exposure time.
- should not translate to any value here. */
+ /*
+ * 3A provide real exposure time.
+ * should not translate to any value here.
+ */
ret = mt9m114_write_reg(client, MISENSOR_16BIT,
REG_EXPO_COARSE, (u16)(coarse_integration));
if (ret) {
@@ -1044,38 +1050,40 @@ static long mt9m114_s_exposure(struct v4l2_subdev *sd,
}
/*
- // set analog/digital gain
- switch(AnalogGain)
+ * set analog/digital gain
+ switch(analog_gain)
{
case 0:
- AnalogGainToWrite = 0x0;
+ analog_gain_to_write = 0x0;
break;
case 1:
- AnalogGainToWrite = 0x20;
+ analog_gain_to_write = 0x20;
break;
case 2:
- AnalogGainToWrite = 0x60;
+ analog_gain_to_write = 0x60;
break;
case 4:
- AnalogGainToWrite = 0xA0;
+ analog_gain_to_write = 0xA0;
break;
case 8:
- AnalogGainToWrite = 0xE0;
+ analog_gain_to_write = 0xE0;
break;
default:
- AnalogGainToWrite = 0x20;
+ analog_gain_to_write = 0x20;
break;
}
*/
- if (DigitalGain >= 16 || DigitalGain <= 1)
- DigitalGain = 1;
- /* AnalogGainToWrite =
- (u16)((DigitalGain << 12) | AnalogGainToWrite); */
- AnalogGainToWrite = (u16)((DigitalGain << 12) | (u16)AnalogGain);
+ if (digital_gain >= 16 || digital_gain <= 1)
+ digital_gain = 1;
+ /*
+ * analog_gain_to_write = (u16)((digital_gain << 12)
+ * | analog_gain_to_write);
+ */
+ analog_gain_to_write = (u16)((digital_gain << 12) | (u16)analog_gain);
ret = mt9m114_write_reg(client, MISENSOR_16BIT,
- REG_GAIN, AnalogGainToWrite);
+ REG_GAIN, analog_gain_to_write);
if (ret) {
- v4l2_err(client, "%s: fail to set AnalogGainToWrite\n",
+ v4l2_err(client, "%s: fail to set analog_gain_to_write\n",
__func__);
return -EINVAL;
}
@@ -1095,8 +1103,10 @@ static long mt9m114_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return 0;
}
-/* This returns the exposure time being used. This should only be used
- for filling in EXIF data, not for actual image processing. */
+/*
+ * This returns the exposure time being used. This should only be used
+ * for filling in EXIF data, not for actual image processing.
+ */
static int mt9m114_g_exposure(struct v4l2_subdev *sd, s32 *value)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -1158,7 +1168,7 @@ static int mt9m114_s_exposure_metering(struct v4l2_subdev *sd, s32 val)
* This function is for touch exposure feature.
*/
static int mt9m114_s_exposure_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -1247,7 +1257,8 @@ static int mt9m114_s_ev(struct v4l2_subdev *sd, s32 val)
s32 luma = 0x37;
int err;
- /* EV value only support -2 to 2
+ /*
+ * EV value only support -2 to 2
* 0: 0x37, 1:0x47, 2:0x57, -1:0x27, -2:0x17
*/
if (val < -2 || val > 2)
@@ -1295,9 +1306,10 @@ static int mt9m114_g_ev(struct v4l2_subdev *sd, s32 *val)
return 0;
}
-/* Fake interface
+/*
+ * Fake interface
* mt9m114 now can not support 3a_lock
-*/
+ */
static int mt9m114_s_3a_lock(struct v4l2_subdev *sd, s32 val)
{
aaalock = val;
@@ -1719,7 +1731,7 @@ static int mt9m114_s_stream(struct v4l2_subdev *sd, int enable)
}
static int mt9m114_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index)
@@ -1730,7 +1742,7 @@ static int mt9m114_enum_mbus_code(struct v4l2_subdev *sd,
}
static int mt9m114_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
unsigned int index = fse->index;
@@ -1843,7 +1855,7 @@ static int mt9m114_probe(struct i2c_client *client)
return ret;
}
- /*TODO add format code here*/
+ /* TODO add format code here */
dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
dev->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
index c90730513438..2111e4a478c1 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
@@ -127,7 +127,7 @@ static int ov2680_g_focal(struct v4l2_subdev *sd, s32 *val)
static int ov2680_g_fnumber(struct v4l2_subdev *sd, s32 *val)
{
- /*const f number for ov2680*/
+ /* const f number for ov2680 */
*val = (OV2680_F_NUMBER_DEFAULT_NUM << 16) | OV2680_F_NUMBER_DEM;
return 0;
@@ -399,7 +399,8 @@ static long ov2680_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return 0;
}
-/* This returns the exposure time being used. This should only be used
+/*
+ * This returns the exposure time being used. This should only be used
* for filling in EXIF data, not for actual image processing.
*/
static int ov2680_q_exposure(struct v4l2_subdev *sd, s32 *value)
@@ -461,11 +462,11 @@ static int ov2680_v_flip(struct v4l2_subdev *sd, s32 value)
ret = ov2680_read_reg(client, 1, OV2680_FLIP_REG, &val);
if (ret)
return ret;
- if (value) {
+ if (value)
val |= OV2680_FLIP_MIRROR_BIT_ENABLE;
- } else {
+ else
val &= ~OV2680_FLIP_MIRROR_BIT_ENABLE;
- }
+
ret = ov2680_write_reg(client, 1,
OV2680_FLIP_REG, val);
if (ret)
@@ -727,11 +728,13 @@ static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
if (!dev || !dev->platform_data)
return -ENODEV;
- /* The OV2680 documents only one GPIO input (#XSHUTDN), but
+ /*
+ * The OV2680 documents only one GPIO input (#XSHUTDN), but
* existing integrations often wire two (reset/power_down)
* because that is the way other sensors work. There is no
* way to tell how it is wired internally, so existing
- * firmwares expose both and we drive them symmetrically. */
+ * firmwares expose both and we drive them symmetrically.
+ */
if (flag) {
ret = dev->platform_data->gpio0_ctrl(sd, 1);
usleep_range(10000, 15000);
@@ -911,7 +914,7 @@ static int get_resolution_index(int w, int h)
}
static int ov2680_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -948,7 +951,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
}
fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
@@ -977,7 +980,8 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
goto err;
}
- /*recall flip functions to avoid flip registers
+ /*
+ * recall flip functions to avoid flip registers
* were overridden by default setting
*/
if (h_flag)
@@ -987,7 +991,8 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
v4l2_info(client, "\n%s idx %d\n", __func__, dev->fmt_idx);
- /*ret = startup(sd);
+ /*
+ * ret = startup(sd);
* if (ret)
* dev_err(&client->dev, "ov2680 startup err\n");
*/
@@ -997,7 +1002,7 @@ err:
}
static int ov2680_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -1096,7 +1101,8 @@ static int ov2680_s_config(struct v4l2_subdev *sd,
(struct camera_sensor_platform_data *)platform_data;
mutex_lock(&dev->input_lock);
- /* power off the module, then power on it in future
+ /*
+ * power off the module, then power on it in future
* as first power on by board may not fulfill the
* power on sequqence needed by the module
*/
@@ -1155,7 +1161,7 @@ static int ov2680_g_frame_interval(struct v4l2_subdev *sd,
}
static int ov2680_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= MAX_FMTS)
@@ -1166,7 +1172,7 @@ static int ov2680_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ov2680_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
int index = fse->index;
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
index 1209492c1826..90d0871a78a3 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
@@ -49,8 +49,8 @@ static int ov2722_read_reg(struct i2c_client *client,
return -ENODEV;
}
- if (data_length != OV2722_8BIT && data_length != OV2722_16BIT
- && data_length != OV2722_32BIT) {
+ if (data_length != OV2722_8BIT && data_length != OV2722_16BIT &&
+ data_length != OV2722_32BIT) {
dev_err(&client->dev, "%s error, invalid data length\n",
__func__);
return -EINVAL;
@@ -212,8 +212,8 @@ static int __ov2722_buf_reg_array(struct i2c_client *client,
}
static int __ov2722_write_reg_is_consecutive(struct i2c_client *client,
- struct ov2722_write_ctrl *ctrl,
- const struct ov2722_reg *next)
+ struct ov2722_write_ctrl *ctrl,
+ const struct ov2722_reg *next)
{
if (ctrl->index == 0)
return 1;
@@ -774,11 +774,11 @@ static int ov2722_s_power(struct v4l2_subdev *sd, int on)
if (on == 0)
return power_down(sd);
- else {
- ret = power_up(sd);
- if (!ret)
- return ov2722_init(sd);
- }
+
+ ret = power_up(sd);
+ if (!ret)
+ return ov2722_init(sd);
+
return ret;
}
@@ -876,7 +876,7 @@ static int startup(struct v4l2_subdev *sd)
}
static int ov2722_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -906,7 +906,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd,
}
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
@@ -961,7 +961,7 @@ err:
}
static int ov2722_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -1104,7 +1104,7 @@ static int ov2722_g_frame_interval(struct v4l2_subdev *sd,
}
static int ov2722_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= MAX_FMTS)
@@ -1115,7 +1115,7 @@ static int ov2722_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ov2722_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
int index = fse->index;
diff --git a/drivers/staging/media/atomisp/i2c/mt9m114.h b/drivers/staging/media/atomisp/i2c/mt9m114.h
index 787bbf59e895..bcce18b65fa6 100644
--- a/drivers/staging/media/atomisp/i2c/mt9m114.h
+++ b/drivers/staging/media/atomisp/i2c/mt9m114.h
@@ -764,8 +764,10 @@ static struct misensor_reg const mt9m114_common[] = {
{MISENSOR_8BIT, 0xC85C, 0x03}, /* cam_crop_cropmode = 3 */
{MISENSOR_16BIT, 0xC868, 0x0280}, /* cam_output_width = 952 */
{MISENSOR_16BIT, 0xC86A, 0x01E0}, /* cam_output_height = 538 */
- /* LOAD = Step3-Recommended
- * Patch,Errata and Sensor optimization Setting */
+ /*
+ * LOAD = Step3-Recommended
+ * Patch, Errata and Sensor optimization Setting
+ */
{MISENSOR_16BIT, 0x316A, 0x8270}, /* DAC_TXLO_ROW */
{MISENSOR_16BIT, 0x316C, 0x8270}, /* DAC_TXLO */
{MISENSOR_16BIT, 0x3ED0, 0x2305}, /* DAC_LD_4_5 */
diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
index 49920245e064..4d43b45915e5 100644
--- a/drivers/staging/media/atomisp/i2c/ov2680.h
+++ b/drivers/staging/media/atomisp/i2c/ov2680.h
@@ -459,8 +459,8 @@ static struct ov2680_reg const ov2680_656x496_30fps[] = {
};
/*
-* 800x600 30fps VBlanking 1lane 10Bit (binning)
-*/
+ * 800x600 30fps VBlanking 1lane 10Bit (binning)
+ */
static struct ov2680_reg const ov2680_720x592_30fps[] = {
{0x3086, 0x01},
{0x3501, 0x26},
@@ -504,8 +504,8 @@ static struct ov2680_reg const ov2680_720x592_30fps[] = {
};
/*
-* 800x600 30fps VBlanking 1lane 10Bit (binning)
-*/
+ * 800x600 30fps VBlanking 1lane 10Bit (binning)
+ */
static struct ov2680_reg const ov2680_800x600_30fps[] = {
{0x3086, 0x01},
{0x3501, 0x26},
@@ -634,7 +634,7 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = {
/*
* 1456*1096 30fps VBlanking 1lane 10bit(no-scaling)
-*/
+ */
static struct ov2680_reg const ov2680_1456x1096_30fps[] = {
{0x3086, 0x00},
{0x3501, 0x48},
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
index e698b63d6cb7..0828ca9ab6f2 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
@@ -1577,7 +1577,7 @@ static int startup(struct v4l2_subdev *sd)
}
static int ov5693_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -1608,7 +1608,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
@@ -1676,7 +1676,7 @@ err:
}
static int ov5693_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -1825,7 +1825,7 @@ static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
}
static int ov5693_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= MAX_FMTS)
@@ -1836,7 +1836,7 @@ static int ov5693_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ov5693_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
int index = fse->index;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_acc.c b/drivers/staging/media/atomisp/pci/atomisp_acc.c
index f638d0bd09fe..9a1751895ab0 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_acc.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_acc.c
@@ -77,8 +77,8 @@ acc_get_fw(struct atomisp_sub_device *asd, unsigned int handle)
struct atomisp_acc_fw *acc_fw;
list_for_each_entry(acc_fw, &asd->acc.fw, list)
- if (acc_fw->handle == handle)
- return acc_fw;
+ if (acc_fw->handle == handle)
+ return acc_fw;
return NULL;
}
@@ -464,9 +464,11 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
continue;
for (i = 0; i < ARRAY_SIZE(acc_flag_to_pipe); i++) {
- /* QoS (ACC pipe) acceleration stages are currently
- * allowed only in continuous mode. Skip them for
- * all other modes. */
+ /*
+ * QoS (ACC pipe) acceleration stages are
+ * currently allowed only in continuous mode.
+ * Skip them for all other modes.
+ */
if (!continuous &&
acc_flag_to_pipe[i].flag ==
ATOMISP_ACC_FW_LOAD_FL_ACC)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 14abc1ca00e8..366161cff560 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -1138,9 +1138,10 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
asd->frame_status[vb->i] =
ATOMISP_FRAME_STATUS_OK;
}
- } else
+ } else {
asd->frame_status[vb->i] =
ATOMISP_FRAME_STATUS_OK;
+ }
} else {
asd->frame_status[vb->i] = ATOMISP_FRAME_STATUS_OK;
}
@@ -4841,6 +4842,9 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = {
+ .pads = &pad_cfg
+ };
struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
@@ -4876,7 +4880,7 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
snr_mbus_fmt->width, snr_mbus_fmt->height);
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, set_fmt, &pad_cfg, &format);
+ pad, set_fmt, &pad_state, &format);
if (ret)
return ret;
@@ -4941,9 +4945,9 @@ atomisp_try_fmt_file(struct atomisp_device *isp, struct v4l2_format *f)
depth = get_pixel_depth(pixelformat);
- if (field == V4L2_FIELD_ANY)
+ if (field == V4L2_FIELD_ANY) {
field = V4L2_FIELD_NONE;
- else if (field != V4L2_FIELD_NONE) {
+ } else if (field != V4L2_FIELD_NONE) {
dev_err(isp->dev, "Wrong output field\n");
return -EINVAL;
}
@@ -5251,11 +5255,11 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
atomisp_output_fmts[] in atomisp_v4l2.c */
vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420;
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SOURCE_VF,
V4L2_SEL_TGT_COMPOSE, 0, &vf_size);
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt);
asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12;
@@ -5492,6 +5496,9 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
const struct atomisp_format_bridge *format;
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = {
+ .pads = &pad_cfg
+ };
struct v4l2_subdev_format vformat = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
@@ -5530,7 +5537,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) {
vformat.which = V4L2_SUBDEV_FORMAT_TRY;
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, set_fmt, &pad_cfg, &vformat);
+ pad, set_fmt, &pad_state, &vformat);
if (ret)
return ret;
if (ffmt->width < req_ffmt->width ||
@@ -5568,7 +5575,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
asd->params.video_dis_en = false;
}
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, ffmt);
@@ -5647,7 +5654,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
}
atomisp_subdev_set_selection(
- &asd->subdev, fh.pad,
+ &asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE, source_pad,
V4L2_SEL_TGT_COMPOSE, 0, &r);
@@ -5777,7 +5784,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
ATOMISP_SUBDEV_PAD_SINK);
isp_source_fmt.code = format_bridge->mbus_code;
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
source_pad, &isp_source_fmt);
@@ -5896,13 +5903,13 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
isp_sink_crop.height = f->fmt.pix.height;
}
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK,
V4L2_SEL_TGT_CROP,
V4L2_SEL_FLAG_KEEP_CONFIG,
&isp_sink_crop);
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
source_pad, V4L2_SEL_TGT_COMPOSE,
0, &isp_sink_crop);
@@ -5921,7 +5928,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
f->fmt.pix.height);
}
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
source_pad,
V4L2_SEL_TGT_COMPOSE, 0,
@@ -5955,14 +5962,14 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
f->fmt.pix.width,
ATOM_ISP_STEP_HEIGHT);
}
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK,
V4L2_SEL_TGT_CROP,
V4L2_SEL_FLAG_KEEP_CONFIG,
&sink_crop);
}
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
source_pad,
V4L2_SEL_TGT_COMPOSE, 0,
@@ -6053,7 +6060,8 @@ int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f)
ffmt.height = f->fmt.pix.height;
ffmt.code = format_bridge->mbus_code;
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad, V4L2_SUBDEV_FORMAT_ACTIVE,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
+ V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, &ffmt);
return 0;
@@ -6564,17 +6572,17 @@ static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe)
{
struct atomisp_sub_device *asd = pipe->asd;
- if (ATOMISP_USE_YUVPP(asd))
+ if (ATOMISP_USE_YUVPP(asd)) {
return IA_CSS_PIPE_ID_YUVPP;
- else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
+ } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
return IA_CSS_PIPE_ID_VIDEO;
- else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT)
+ } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
return IA_CSS_PIPE_ID_CAPTURE;
- else if (pipe == &asd->video_out_video_capture)
+ } else if (pipe == &asd->video_out_video_capture) {
return IA_CSS_PIPE_ID_VIDEO;
- else if (pipe == &asd->video_out_vf)
+ } else if (pipe == &asd->video_out_vf) {
return IA_CSS_PIPE_ID_CAPTURE;
- else if (pipe == &asd->video_out_preview) {
+ } else if (pipe == &asd->video_out_preview) {
if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
return IA_CSS_PIPE_ID_VIDEO;
else
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h
index 412baeb91944..e8bdd264d31b 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h
@@ -49,9 +49,7 @@ struct ia_css_frame;
/* FIXME: check if can go */
extern int atomisp_punit_hpll_freq;
-/*
- * Helper function
- */
+/* Helper function */
void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr,
unsigned int size);
struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd);
@@ -65,9 +63,7 @@ bool atomisp_buffers_queued(struct atomisp_sub_device *asd);
/* ISP2401 */
bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe);
-/*
- * Interrupt functions
- */
+/* Interrupt functions */
void atomisp_msi_irq_init(struct atomisp_device *isp);
void atomisp_msi_irq_uninit(struct atomisp_device *isp);
void atomisp_wdt_work(struct work_struct *work);
@@ -82,15 +78,10 @@ int atomisp_get_frame_pgnr(struct atomisp_device *isp,
const struct ia_css_frame *frame, u32 *p_pgnr);
void atomisp_delayed_init_work(struct work_struct *work);
-/*
- * Get internal fmt according to V4L2 fmt
- */
-
+/* Get internal fmt according to V4L2 fmt */
bool atomisp_is_viewfinder_support(struct atomisp_device *isp);
-/*
- * ISP features control function
- */
+/* ISP features control function */
/*
* Function to set sensor runmode by user when
@@ -105,9 +96,7 @@ int atomisp_set_sensor_runmode(struct atomisp_sub_device *asd,
int atomisp_gdc_cac(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function to enable/disable low light mode (including ANR)
- */
+/* Function to enable/disable low light mode (including ANR) */
int atomisp_low_light(struct atomisp_sub_device *asd, int flag,
__s32 *value);
@@ -120,91 +109,63 @@ int atomisp_xnr(struct atomisp_sub_device *asd, int flag, int *arg);
int atomisp_formats(struct atomisp_sub_device *asd, int flag,
struct atomisp_formats_config *config);
-/*
- * Function to configure noise reduction
- */
+/* Function to configure noise reduction */
int atomisp_nr(struct atomisp_sub_device *asd, int flag,
struct atomisp_nr_config *config);
-/*
- * Function to configure temporal noise reduction (TNR)
- */
+/* Function to configure temporal noise reduction (TNR) */
int atomisp_tnr(struct atomisp_sub_device *asd, int flag,
struct atomisp_tnr_config *config);
-/*
- * Function to configure black level compensation
- */
+/* Function to configure black level compensation */
int atomisp_black_level(struct atomisp_sub_device *asd, int flag,
struct atomisp_ob_config *config);
-/*
- * Function to configure edge enhancement
- */
+/* Function to configure edge enhancement */
int atomisp_ee(struct atomisp_sub_device *asd, int flag,
struct atomisp_ee_config *config);
-/*
- * Function to update Gamma table for gamma, brightness and contrast config
- */
+/* Function to update Gamma table for gamma, brightness and contrast config */
int atomisp_gamma(struct atomisp_sub_device *asd, int flag,
struct atomisp_gamma_table *config);
-/*
- * Function to update Ctc table for Chroma Enhancement
- */
+
+/* Function to update Ctc table for Chroma Enhancement */
int atomisp_ctc(struct atomisp_sub_device *asd, int flag,
struct atomisp_ctc_table *config);
-/*
- * Function to update gamma correction parameters
- */
+/* Function to update gamma correction parameters */
int atomisp_gamma_correction(struct atomisp_sub_device *asd, int flag,
struct atomisp_gc_config *config);
-/*
- * Function to update Gdc table for gdc
- */
+/* Function to update Gdc table for gdc */
int atomisp_gdc_cac_table(struct atomisp_sub_device *asd, int flag,
struct atomisp_morph_table *config);
-/*
- * Function to update table for macc
- */
+/* Function to update table for macc */
int atomisp_macc_table(struct atomisp_sub_device *asd, int flag,
struct atomisp_macc_config *config);
-/*
- * Function to get DIS statistics.
- */
+
+/* Function to get DIS statistics. */
int atomisp_get_dis_stat(struct atomisp_sub_device *asd,
struct atomisp_dis_statistics *stats);
-/*
- * Function to get DVS2 BQ resolution settings
- */
+/* Function to get DVS2 BQ resolution settings */
int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd,
struct atomisp_dvs2_bq_resolutions *bq_res);
-/*
- * Function to set the DIS coefficients.
- */
+/* Function to set the DIS coefficients. */
int atomisp_set_dis_coefs(struct atomisp_sub_device *asd,
struct atomisp_dis_coefficients *coefs);
-/*
- * Function to set the DIS motion vector.
- */
+/* Function to set the DIS motion vector. */
int atomisp_set_dis_vector(struct atomisp_sub_device *asd,
struct atomisp_dis_vector *vector);
-/*
- * Function to set/get 3A stat from isp
- */
+/* Function to set/get 3A stat from isp */
int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag,
struct atomisp_3a_statistics *config);
-/*
- * Function to get metadata from isp
- */
+/* Function to get metadata from isp */
int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag,
struct atomisp_metadata *config);
@@ -213,84 +174,59 @@ int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag,
int atomisp_set_parameters(struct video_device *vdev,
struct atomisp_parameters *arg);
-/*
- * Function to set/get isp parameters to isp
- */
+
+/* Function to set/get isp parameters to isp */
int atomisp_param(struct atomisp_sub_device *asd, int flag,
struct atomisp_parm *config);
-/*
- * Function to configure color effect of the image
- */
+/* Function to configure color effect of the image */
int atomisp_color_effect(struct atomisp_sub_device *asd, int flag,
__s32 *effect);
-/*
- * Function to configure bad pixel correction
- */
+/* Function to configure bad pixel correction */
int atomisp_bad_pixel(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function to configure bad pixel correction params
- */
+/* Function to configure bad pixel correction params */
int atomisp_bad_pixel_param(struct atomisp_sub_device *asd, int flag,
struct atomisp_dp_config *config);
-/*
- * Function to enable/disable video image stablization
- */
+/* Function to enable/disable video image stablization */
int atomisp_video_stable(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function to configure fixed pattern noise
- */
+/* Function to configure fixed pattern noise */
int atomisp_fixed_pattern(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function to configure fixed pattern noise table
- */
+/* Function to configure fixed pattern noise table */
int atomisp_fixed_pattern_table(struct atomisp_sub_device *asd,
struct v4l2_framebuffer *config);
-/*
- * Function to configure false color correction
- */
+/* Function to configure false color correction */
int atomisp_false_color(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function to configure false color correction params
- */
+/* Function to configure false color correction params */
int atomisp_false_color_param(struct atomisp_sub_device *asd, int flag,
struct atomisp_de_config *config);
-/*
- * Function to configure white balance params
- */
+/* Function to configure white balance params */
int atomisp_white_balance_param(struct atomisp_sub_device *asd, int flag,
struct atomisp_wb_config *config);
int atomisp_3a_config_param(struct atomisp_sub_device *asd, int flag,
struct atomisp_3a_config *config);
-/*
- * Function to setup digital zoom
- */
+/* Function to setup digital zoom */
int atomisp_digital_zoom(struct atomisp_sub_device *asd, int flag,
__s32 *value);
-/*
- * Function set camera_prefiles.xml current sensor pixel array size
- */
+/* Function set camera_prefiles.xml current sensor pixel array size */
int atomisp_set_array_res(struct atomisp_sub_device *asd,
struct atomisp_resolution *config);
-/*
- * Function to calculate real zoom region for every pipe
- */
+/* Function to calculate real zoom region for every pipe */
int atomisp_calculate_real_zoom_region(struct atomisp_sub_device *asd,
struct ia_css_dz_config *dz_config,
enum ia_css_pipe_id css_pipe_id);
@@ -371,9 +307,7 @@ void atomisp_css_flush(struct atomisp_device *isp);
int atomisp_source_pad_to_stream_id(struct atomisp_sub_device *asd,
uint16_t source_pad);
-/*
- * Events. Only one event has to be exported for now.
- */
+/* Events. Only one event has to be exported for now. */
void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id);
enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
@@ -389,34 +323,25 @@ void atomisp_free_css_parameters(struct atomisp_css_params *css_param);
void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe);
void atomisp_flush_params_queue(struct atomisp_video_pipe *asd);
-/*
- * Function to do Raw Buffer related operation, after enable Lock Unlock Raw Buffer
- */
+
+/* Function to do Raw Buffer related operation, after enable Lock Unlock Raw Buffer */
int atomisp_exp_id_unlock(struct atomisp_sub_device *asd, int *exp_id);
int atomisp_exp_id_capture(struct atomisp_sub_device *asd, int *exp_id);
-/*
- * Function to update Raw Buffer bitmap
- */
+/* Function to update Raw Buffer bitmap */
int atomisp_set_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id);
void atomisp_init_raw_buffer_bitmap(struct atomisp_sub_device *asd);
-/*
- * Function to enable/disable zoom for capture pipe
- */
+/* Function to enable/disable zoom for capture pipe */
int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd,
unsigned int *enable);
-/*
- * Function to get metadata type bu pipe id
- */
+/* Function to get metadata type bu pipe id */
enum atomisp_metadata_type
atomisp_get_metadata_type(struct atomisp_sub_device *asd,
enum ia_css_pipe_id pipe_id);
-/*
- * Function for HAL to inject a fake event to wake up poll thread
- */
+/* Function for HAL to inject a fake event to wake up poll thread */
int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event);
/*
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
index ce3165291eec..f60198bb8a1a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
@@ -2782,9 +2782,9 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
int stream_index;
struct atomisp_device *isp = asd->isp;
- if (ATOMISP_SOC_CAMERA(asd))
+ if (ATOMISP_SOC_CAMERA(asd)) {
stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
- else {
+ } else {
stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
ATOMISP_INPUT_STREAM_VIDEO :
atomisp_source_pad_to_stream_id(asd, source_pad);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.c b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.c
deleted file mode 100644
index e5553df5bad4..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.c
+++ /dev/null
@@ -1,1202 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- *
- * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- */
-#ifdef CONFIG_COMPAT
-#include <linux/compat.h>
-
-#include <linux/videodev2.h>
-
-#include "atomisp_internal.h"
-#include "atomisp_compat.h"
-#include "atomisp_ioctl.h"
-#include "atomisp_compat_ioctl32.h"
-
-/* Macros borrowed from v4l2-compat-ioctl32.c */
-
-#define get_user_cast(__x, __ptr) \
-({ \
- get_user(__x, (typeof(*__ptr) __user *)(__ptr)); \
-})
-
-#define put_user_force(__x, __ptr) \
-({ \
- put_user((typeof(*__x) __force *)(__x), __ptr); \
-})
-
-/* Use the same argument order as copy_in_user */
-#define assign_in_user(to, from) \
-({ \
- typeof(*from) __assign_tmp; \
- \
- get_user_cast(__assign_tmp, from) || put_user(__assign_tmp, to);\
-})
-
-static int get_atomisp_histogram32(struct atomisp_histogram __user *kp,
- struct atomisp_histogram32 __user *up)
-{
- compat_uptr_t tmp;
-
- if (!access_ok(up, sizeof(struct atomisp_histogram32)) ||
- assign_in_user(&kp->num_elements, &up->num_elements) ||
- get_user(tmp, &up->data) ||
- put_user(compat_ptr(tmp), &kp->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_histogram32(struct atomisp_histogram __user *kp,
- struct atomisp_histogram32 __user *up)
-{
- void __user *tmp;
-
- if (!access_ok(up, sizeof(struct atomisp_histogram32)) ||
- assign_in_user(&up->num_elements, &kp->num_elements) ||
- get_user(tmp, &kp->data) ||
- put_user(ptr_to_compat(tmp), &up->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
- struct v4l2_framebuffer32 __user *up)
-{
- compat_uptr_t tmp;
-
- if (!access_ok(up, sizeof(struct v4l2_framebuffer32)) ||
- get_user(tmp, &up->base) ||
- put_user_force(compat_ptr(tmp), &kp->base) ||
- assign_in_user(&kp->capability, &up->capability) ||
- assign_in_user(&kp->flags, &up->flags) ||
- copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_dis_statistics32(struct atomisp_dis_statistics __user *kp,
- struct atomisp_dis_statistics32 __user *up)
-{
- compat_uptr_t hor_prod_odd_real;
- compat_uptr_t hor_prod_odd_imag;
- compat_uptr_t hor_prod_even_real;
- compat_uptr_t hor_prod_even_imag;
- compat_uptr_t ver_prod_odd_real;
- compat_uptr_t ver_prod_odd_imag;
- compat_uptr_t ver_prod_even_real;
- compat_uptr_t ver_prod_even_imag;
-
- if (!access_ok(up, sizeof(struct atomisp_dis_statistics32)) ||
- copy_in_user(kp, up, sizeof(struct atomisp_dvs_grid_info)) ||
- get_user(hor_prod_odd_real,
- &up->dvs2_stat.hor_prod.odd_real) ||
- get_user(hor_prod_odd_imag,
- &up->dvs2_stat.hor_prod.odd_imag) ||
- get_user(hor_prod_even_real,
- &up->dvs2_stat.hor_prod.even_real) ||
- get_user(hor_prod_even_imag,
- &up->dvs2_stat.hor_prod.even_imag) ||
- get_user(ver_prod_odd_real,
- &up->dvs2_stat.ver_prod.odd_real) ||
- get_user(ver_prod_odd_imag,
- &up->dvs2_stat.ver_prod.odd_imag) ||
- get_user(ver_prod_even_real,
- &up->dvs2_stat.ver_prod.even_real) ||
- get_user(ver_prod_even_imag,
- &up->dvs2_stat.ver_prod.even_imag) ||
- assign_in_user(&kp->exp_id, &up->exp_id) ||
- put_user(compat_ptr(hor_prod_odd_real),
- &kp->dvs2_stat.hor_prod.odd_real) ||
- put_user(compat_ptr(hor_prod_odd_imag),
- &kp->dvs2_stat.hor_prod.odd_imag) ||
- put_user(compat_ptr(hor_prod_even_real),
- &kp->dvs2_stat.hor_prod.even_real) ||
- put_user(compat_ptr(hor_prod_even_imag),
- &kp->dvs2_stat.hor_prod.even_imag) ||
- put_user(compat_ptr(ver_prod_odd_real),
- &kp->dvs2_stat.ver_prod.odd_real) ||
- put_user(compat_ptr(ver_prod_odd_imag),
- &kp->dvs2_stat.ver_prod.odd_imag) ||
- put_user(compat_ptr(ver_prod_even_real),
- &kp->dvs2_stat.ver_prod.even_real) ||
- put_user(compat_ptr(ver_prod_even_imag),
- &kp->dvs2_stat.ver_prod.even_imag))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_dis_statistics32(struct atomisp_dis_statistics __user *kp,
- struct atomisp_dis_statistics32 __user *up)
-{
- void __user *hor_prod_odd_real;
- void __user *hor_prod_odd_imag;
- void __user *hor_prod_even_real;
- void __user *hor_prod_even_imag;
- void __user *ver_prod_odd_real;
- void __user *ver_prod_odd_imag;
- void __user *ver_prod_even_real;
- void __user *ver_prod_even_imag;
-
- if (!!access_ok(up, sizeof(struct atomisp_dis_statistics32)) ||
- copy_in_user(up, kp, sizeof(struct atomisp_dvs_grid_info)) ||
- get_user(hor_prod_odd_real,
- &kp->dvs2_stat.hor_prod.odd_real) ||
- get_user(hor_prod_odd_imag,
- &kp->dvs2_stat.hor_prod.odd_imag) ||
- get_user(hor_prod_even_real,
- &kp->dvs2_stat.hor_prod.even_real) ||
- get_user(hor_prod_even_imag,
- &kp->dvs2_stat.hor_prod.even_imag) ||
- get_user(ver_prod_odd_real,
- &kp->dvs2_stat.ver_prod.odd_real) ||
- get_user(ver_prod_odd_imag,
- &kp->dvs2_stat.ver_prod.odd_imag) ||
- get_user(ver_prod_even_real,
- &kp->dvs2_stat.ver_prod.even_real) ||
- get_user(ver_prod_even_imag,
- &kp->dvs2_stat.ver_prod.even_imag) ||
- put_user(ptr_to_compat(hor_prod_odd_real),
- &up->dvs2_stat.hor_prod.odd_real) ||
- put_user(ptr_to_compat(hor_prod_odd_imag),
- &up->dvs2_stat.hor_prod.odd_imag) ||
- put_user(ptr_to_compat(hor_prod_even_real),
- &up->dvs2_stat.hor_prod.even_real) ||
- put_user(ptr_to_compat(hor_prod_even_imag),
- &up->dvs2_stat.hor_prod.even_imag) ||
- put_user(ptr_to_compat(ver_prod_odd_real),
- &up->dvs2_stat.ver_prod.odd_real) ||
- put_user(ptr_to_compat(ver_prod_odd_imag),
- &up->dvs2_stat.ver_prod.odd_imag) ||
- put_user(ptr_to_compat(ver_prod_even_real),
- &up->dvs2_stat.ver_prod.even_real) ||
- put_user(ptr_to_compat(ver_prod_even_imag),
- &up->dvs2_stat.ver_prod.even_imag) ||
- assign_in_user(&up->exp_id, &kp->exp_id))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_dis_coefficients32(struct atomisp_dis_coefficients __user *kp,
- struct atomisp_dis_coefficients32 __user *up)
-{
- compat_uptr_t hor_coefs_odd_real;
- compat_uptr_t hor_coefs_odd_imag;
- compat_uptr_t hor_coefs_even_real;
- compat_uptr_t hor_coefs_even_imag;
- compat_uptr_t ver_coefs_odd_real;
- compat_uptr_t ver_coefs_odd_imag;
- compat_uptr_t ver_coefs_even_real;
- compat_uptr_t ver_coefs_even_imag;
-
- if (!access_ok(up, sizeof(struct atomisp_dis_coefficients32)) ||
- copy_in_user(kp, up, sizeof(struct atomisp_dvs_grid_info)) ||
- get_user(hor_coefs_odd_real, &up->hor_coefs.odd_real) ||
- get_user(hor_coefs_odd_imag, &up->hor_coefs.odd_imag) ||
- get_user(hor_coefs_even_real, &up->hor_coefs.even_real) ||
- get_user(hor_coefs_even_imag, &up->hor_coefs.even_imag) ||
- get_user(ver_coefs_odd_real, &up->ver_coefs.odd_real) ||
- get_user(ver_coefs_odd_imag, &up->ver_coefs.odd_imag) ||
- get_user(ver_coefs_even_real, &up->ver_coefs.even_real) ||
- get_user(ver_coefs_even_imag, &up->ver_coefs.even_imag) ||
- put_user(compat_ptr(hor_coefs_odd_real),
- &kp->hor_coefs.odd_real) ||
- put_user(compat_ptr(hor_coefs_odd_imag),
- &kp->hor_coefs.odd_imag) ||
- put_user(compat_ptr(hor_coefs_even_real),
- &kp->hor_coefs.even_real) ||
- put_user(compat_ptr(hor_coefs_even_imag),
- &kp->hor_coefs.even_imag) ||
- put_user(compat_ptr(ver_coefs_odd_real),
- &kp->ver_coefs.odd_real) ||
- put_user(compat_ptr(ver_coefs_odd_imag),
- &kp->ver_coefs.odd_imag) ||
- put_user(compat_ptr(ver_coefs_even_real),
- &kp->ver_coefs.even_real) ||
- put_user(compat_ptr(ver_coefs_even_imag),
- &kp->ver_coefs.even_imag))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_dvs_6axis_config32(struct atomisp_dvs_6axis_config __user *kp,
- struct atomisp_dvs_6axis_config32 __user *up)
-{
- compat_uptr_t xcoords_y;
- compat_uptr_t ycoords_y;
- compat_uptr_t xcoords_uv;
- compat_uptr_t ycoords_uv;
-
- if (!access_ok(up, sizeof(struct atomisp_dvs_6axis_config32)) ||
- assign_in_user(&kp->exp_id, &up->exp_id) ||
- assign_in_user(&kp->width_y, &up->width_y) ||
- assign_in_user(&kp->height_y, &up->height_y) ||
- assign_in_user(&kp->width_uv, &up->width_uv) ||
- assign_in_user(&kp->height_uv, &up->height_uv) ||
- get_user(xcoords_y, &up->xcoords_y) ||
- get_user(ycoords_y, &up->ycoords_y) ||
- get_user(xcoords_uv, &up->xcoords_uv) ||
- get_user(ycoords_uv, &up->ycoords_uv) ||
- put_user_force(compat_ptr(xcoords_y), &kp->xcoords_y) ||
- put_user_force(compat_ptr(ycoords_y), &kp->ycoords_y) ||
- put_user_force(compat_ptr(xcoords_uv), &kp->xcoords_uv) ||
- put_user_force(compat_ptr(ycoords_uv), &kp->ycoords_uv))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_3a_statistics32(struct atomisp_3a_statistics __user *kp,
- struct atomisp_3a_statistics32 __user *up)
-{
- compat_uptr_t data;
- compat_uptr_t rgby_data;
-
- if (!access_ok(up, sizeof(struct atomisp_3a_statistics32)) ||
- copy_in_user(kp, up, sizeof(struct atomisp_grid_info)) ||
- get_user(rgby_data, &up->rgby_data) ||
- put_user(compat_ptr(rgby_data), &kp->rgby_data) ||
- get_user(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data) ||
- assign_in_user(&kp->exp_id, &up->exp_id) ||
- assign_in_user(&kp->isp_config_id, &up->isp_config_id))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_3a_statistics32(struct atomisp_3a_statistics __user *kp,
- struct atomisp_3a_statistics32 __user *up)
-{
- void __user *data;
- void __user *rgby_data;
-
- if (!access_ok(up, sizeof(struct atomisp_3a_statistics32)) ||
- copy_in_user(up, kp, sizeof(struct atomisp_grid_info)) ||
- get_user(rgby_data, &kp->rgby_data) ||
- put_user(ptr_to_compat(rgby_data), &up->rgby_data) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data) ||
- assign_in_user(&up->exp_id, &kp->exp_id) ||
- assign_in_user(&up->isp_config_id, &kp->isp_config_id))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_metadata_stat32(struct atomisp_metadata __user *kp,
- struct atomisp_metadata32 __user *up)
-{
- compat_uptr_t data;
- compat_uptr_t effective_width;
-
- if (!access_ok(up, sizeof(struct atomisp_metadata32)) ||
- get_user(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data) ||
- assign_in_user(&kp->width, &up->width) ||
- assign_in_user(&kp->height, &up->height) ||
- assign_in_user(&kp->stride, &up->stride) ||
- assign_in_user(&kp->exp_id, &up->exp_id) ||
- get_user(effective_width, &up->effective_width) ||
- put_user_force(compat_ptr(effective_width), &kp->effective_width))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_metadata_stat32(struct atomisp_metadata __user *kp,
- struct atomisp_metadata32 __user *up)
-{
- void __user *data;
- void *effective_width;
-
- if (!access_ok(up, sizeof(struct atomisp_metadata32)) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data) ||
- assign_in_user(&up->width, &kp->width) ||
- assign_in_user(&up->height, &kp->height) ||
- assign_in_user(&up->stride, &kp->stride) ||
- assign_in_user(&up->exp_id, &kp->exp_id) ||
- get_user(effective_width, &kp->effective_width) ||
- put_user(ptr_to_compat((void __user *)effective_width),
- &up->effective_width))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-put_atomisp_metadata_by_type_stat32(struct atomisp_metadata_with_type __user *kp,
- struct atomisp_metadata_with_type32 __user *up)
-{
- void __user *data;
- u32 *effective_width;
-
- if (!access_ok(up, sizeof(struct atomisp_metadata_with_type32)) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data) ||
- assign_in_user(&up->width, &kp->width) ||
- assign_in_user(&up->height, &kp->height) ||
- assign_in_user(&up->stride, &kp->stride) ||
- assign_in_user(&up->exp_id, &kp->exp_id) ||
- get_user(effective_width, &kp->effective_width) ||
- put_user(ptr_to_compat((void __user *)effective_width),
- &up->effective_width) ||
- assign_in_user(&up->type, &kp->type))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_metadata_by_type_stat32(struct atomisp_metadata_with_type __user *kp,
- struct atomisp_metadata_with_type32 __user *up)
-{
- compat_uptr_t data;
- compat_uptr_t effective_width;
-
- if (!access_ok(up, sizeof(struct atomisp_metadata_with_type32)) ||
- get_user(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data) ||
- assign_in_user(&kp->width, &up->width) ||
- assign_in_user(&kp->height, &up->height) ||
- assign_in_user(&kp->stride, &up->stride) ||
- assign_in_user(&kp->exp_id, &up->exp_id) ||
- get_user(effective_width, &up->effective_width) ||
- put_user_force(compat_ptr(effective_width), &kp->effective_width) ||
- assign_in_user(&kp->type, &up->type))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_morph_table32(struct atomisp_morph_table __user *kp,
- struct atomisp_morph_table32 __user *up)
-{
- unsigned int n = ATOMISP_MORPH_TABLE_NUM_PLANES;
-
- if (!access_ok(up, sizeof(struct atomisp_morph_table32)) ||
- assign_in_user(&kp->enabled, &up->enabled) ||
- assign_in_user(&kp->width, &up->width) ||
- assign_in_user(&kp->height, &up->height))
- return -EFAULT;
-
- while (n-- > 0) {
- compat_uptr_t coord_kp;
-
- if (get_user(coord_kp, &up->coordinates_x[n]) ||
- put_user(compat_ptr(coord_kp), &kp->coordinates_x[n]) ||
- get_user(coord_kp, &up->coordinates_y[n]) ||
- put_user(compat_ptr(coord_kp), &kp->coordinates_y[n]))
- return -EFAULT;
- }
- return 0;
-}
-
-static int put_atomisp_morph_table32(struct atomisp_morph_table __user *kp,
- struct atomisp_morph_table32 __user *up)
-{
- unsigned int n = ATOMISP_MORPH_TABLE_NUM_PLANES;
-
- if (!access_ok(up, sizeof(struct atomisp_morph_table32)) ||
- assign_in_user(&up->enabled, &kp->enabled) ||
- assign_in_user(&up->width, &kp->width) ||
- assign_in_user(&up->height, &kp->height))
- return -EFAULT;
-
- while (n-- > 0) {
- void __user *coord_kp;
-
- if (get_user(coord_kp, &kp->coordinates_x[n]) ||
- put_user(ptr_to_compat(coord_kp), &up->coordinates_x[n]) ||
- get_user(coord_kp, &kp->coordinates_y[n]) ||
- put_user(ptr_to_compat(coord_kp), &up->coordinates_y[n]))
- return -EFAULT;
- }
- return 0;
-}
-
-static int get_atomisp_overlay32(struct atomisp_overlay __user *kp,
- struct atomisp_overlay32 __user *up)
-{
- compat_uptr_t frame;
-
- if (!access_ok(up, sizeof(struct atomisp_overlay32)) ||
- get_user(frame, &up->frame) ||
- put_user_force(compat_ptr(frame), &kp->frame) ||
- assign_in_user(&kp->bg_y, &up->bg_y) ||
- assign_in_user(&kp->bg_u, &up->bg_u) ||
- assign_in_user(&kp->bg_v, &up->bg_v) ||
- assign_in_user(&kp->blend_input_perc_y,
- &up->blend_input_perc_y) ||
- assign_in_user(&kp->blend_input_perc_u,
- &up->blend_input_perc_u) ||
- assign_in_user(&kp->blend_input_perc_v,
- &up->blend_input_perc_v) ||
- assign_in_user(&kp->blend_overlay_perc_y,
- &up->blend_overlay_perc_y) ||
- assign_in_user(&kp->blend_overlay_perc_u,
- &up->blend_overlay_perc_u) ||
- assign_in_user(&kp->blend_overlay_perc_v,
- &up->blend_overlay_perc_v) ||
- assign_in_user(&kp->overlay_start_x, &up->overlay_start_x) ||
- assign_in_user(&kp->overlay_start_y, &up->overlay_start_y))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_overlay32(struct atomisp_overlay __user *kp,
- struct atomisp_overlay32 __user *up)
-{
- void *frame;
-
- if (!access_ok(up, sizeof(struct atomisp_overlay32)) ||
- get_user(frame, &kp->frame) ||
- put_user(ptr_to_compat((void __user *)frame), &up->frame) ||
- assign_in_user(&up->bg_y, &kp->bg_y) ||
- assign_in_user(&up->bg_u, &kp->bg_u) ||
- assign_in_user(&up->bg_v, &kp->bg_v) ||
- assign_in_user(&up->blend_input_perc_y,
- &kp->blend_input_perc_y) ||
- assign_in_user(&up->blend_input_perc_u,
- &kp->blend_input_perc_u) ||
- assign_in_user(&up->blend_input_perc_v,
- &kp->blend_input_perc_v) ||
- assign_in_user(&up->blend_overlay_perc_y,
- &kp->blend_overlay_perc_y) ||
- assign_in_user(&up->blend_overlay_perc_u,
- &kp->blend_overlay_perc_u) ||
- assign_in_user(&up->blend_overlay_perc_v,
- &kp->blend_overlay_perc_v) ||
- assign_in_user(&up->overlay_start_x, &kp->overlay_start_x) ||
- assign_in_user(&up->overlay_start_y, &kp->overlay_start_y))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_calibration_group32(struct atomisp_calibration_group __user *kp,
- struct atomisp_calibration_group32 __user *up)
-{
- compat_uptr_t calb_grp_values;
-
- if (!access_ok(up, sizeof(struct atomisp_calibration_group32)) ||
- assign_in_user(&kp->size, &up->size) ||
- assign_in_user(&kp->type, &up->type) ||
- get_user(calb_grp_values, &up->calb_grp_values) ||
- put_user_force(compat_ptr(calb_grp_values), &kp->calb_grp_values))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-put_atomisp_calibration_group32(struct atomisp_calibration_group __user *kp,
- struct atomisp_calibration_group32 __user *up)
-{
- void *calb_grp_values;
-
- if (!access_ok(up, sizeof(struct atomisp_calibration_group32)) ||
- assign_in_user(&up->size, &kp->size) ||
- assign_in_user(&up->type, &kp->type) ||
- get_user(calb_grp_values, &kp->calb_grp_values) ||
- put_user(ptr_to_compat((void __user *)calb_grp_values),
- &up->calb_grp_values))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_acc_fw_load32(struct atomisp_acc_fw_load __user *kp,
- struct atomisp_acc_fw_load32 __user *up)
-{
- compat_uptr_t data;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_load32)) ||
- assign_in_user(&kp->size, &up->size) ||
- assign_in_user(&kp->fw_handle, &up->fw_handle) ||
- get_user_cast(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_acc_fw_load32(struct atomisp_acc_fw_load __user *kp,
- struct atomisp_acc_fw_load32 __user *up)
-{
- void __user *data;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_load32)) ||
- assign_in_user(&up->size, &kp->size) ||
- assign_in_user(&up->fw_handle, &kp->fw_handle) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_acc_fw_arg32(struct atomisp_acc_fw_arg __user *kp,
- struct atomisp_acc_fw_arg32 __user *up)
-{
- compat_uptr_t value;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_arg32)) ||
- assign_in_user(&kp->fw_handle, &up->fw_handle) ||
- assign_in_user(&kp->index, &up->index) ||
- get_user(value, &up->value) ||
- put_user(compat_ptr(value), &kp->value) ||
- assign_in_user(&kp->size, &up->size))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_acc_fw_arg32(struct atomisp_acc_fw_arg __user *kp,
- struct atomisp_acc_fw_arg32 __user *up)
-{
- void __user *value;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_arg32)) ||
- assign_in_user(&up->fw_handle, &kp->fw_handle) ||
- assign_in_user(&up->index, &kp->index) ||
- get_user(value, &kp->value) ||
- put_user(ptr_to_compat(value), &up->value) ||
- assign_in_user(&up->size, &kp->size))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_v4l2_private_int_data32(struct v4l2_private_int_data __user *kp,
- struct v4l2_private_int_data32 __user *up)
-{
- compat_uptr_t data;
-
- if (!access_ok(up, sizeof(struct v4l2_private_int_data32)) ||
- assign_in_user(&kp->size, &up->size) ||
- get_user(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data) ||
- assign_in_user(&kp->reserved[0], &up->reserved[0]) ||
- assign_in_user(&kp->reserved[1], &up->reserved[1]))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_v4l2_private_int_data32(struct v4l2_private_int_data __user *kp,
- struct v4l2_private_int_data32 __user *up)
-{
- void __user *data;
-
- if (!access_ok(up, sizeof(struct v4l2_private_int_data32)) ||
- assign_in_user(&up->size, &kp->size) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data) ||
- assign_in_user(&up->reserved[0], &kp->reserved[0]) ||
- assign_in_user(&up->reserved[1], &kp->reserved[1]))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_shading_table32(struct atomisp_shading_table __user *kp,
- struct atomisp_shading_table32 __user *up)
-{
- unsigned int n = ATOMISP_NUM_SC_COLORS;
-
- if (!access_ok(up, sizeof(struct atomisp_shading_table32)) ||
- assign_in_user(&kp->enable, &up->enable) ||
- assign_in_user(&kp->sensor_width, &up->sensor_width) ||
- assign_in_user(&kp->sensor_height, &up->sensor_height) ||
- assign_in_user(&kp->width, &up->width) ||
- assign_in_user(&kp->height, &up->height) ||
- assign_in_user(&kp->fraction_bits, &up->fraction_bits))
- return -EFAULT;
-
- while (n-- > 0) {
- compat_uptr_t tmp;
-
- if (get_user(tmp, &up->data[n]) ||
- put_user_force(compat_ptr(tmp), &kp->data[n]))
- return -EFAULT;
- }
- return 0;
-}
-
-static int get_atomisp_acc_map32(struct atomisp_acc_map __user *kp,
- struct atomisp_acc_map32 __user *up)
-{
- compat_uptr_t user_ptr;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_map32)) ||
- assign_in_user(&kp->flags, &up->flags) ||
- assign_in_user(&kp->length, &up->length) ||
- get_user(user_ptr, &up->user_ptr) ||
- put_user(compat_ptr(user_ptr), &kp->user_ptr) ||
- assign_in_user(&kp->css_ptr, &up->css_ptr) ||
- assign_in_user(&kp->reserved[0], &up->reserved[0]) ||
- assign_in_user(&kp->reserved[1], &up->reserved[1]) ||
- assign_in_user(&kp->reserved[2], &up->reserved[2]) ||
- assign_in_user(&kp->reserved[3], &up->reserved[3]))
- return -EFAULT;
-
- return 0;
-}
-
-static int put_atomisp_acc_map32(struct atomisp_acc_map __user *kp,
- struct atomisp_acc_map32 __user *up)
-{
- void __user *user_ptr;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_map32)) ||
- assign_in_user(&up->flags, &kp->flags) ||
- assign_in_user(&up->length, &kp->length) ||
- get_user(user_ptr, &kp->user_ptr) ||
- put_user(ptr_to_compat(user_ptr), &up->user_ptr) ||
- assign_in_user(&up->css_ptr, &kp->css_ptr) ||
- assign_in_user(&up->reserved[0], &kp->reserved[0]) ||
- assign_in_user(&up->reserved[1], &kp->reserved[1]) ||
- assign_in_user(&up->reserved[2], &kp->reserved[2]) ||
- assign_in_user(&up->reserved[3], &kp->reserved[3]))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_acc_s_mapped_arg32(struct atomisp_acc_s_mapped_arg __user *kp,
- struct atomisp_acc_s_mapped_arg32 __user *up)
-{
- if (!access_ok(up, sizeof(struct atomisp_acc_s_mapped_arg32)) ||
- assign_in_user(&kp->fw_handle, &up->fw_handle) ||
- assign_in_user(&kp->memory, &up->memory) ||
- assign_in_user(&kp->length, &up->length) ||
- assign_in_user(&kp->css_ptr, &up->css_ptr))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-put_atomisp_acc_s_mapped_arg32(struct atomisp_acc_s_mapped_arg __user *kp,
- struct atomisp_acc_s_mapped_arg32 __user *up)
-{
- if (!access_ok(up, sizeof(struct atomisp_acc_s_mapped_arg32)) ||
- assign_in_user(&up->fw_handle, &kp->fw_handle) ||
- assign_in_user(&up->memory, &kp->memory) ||
- assign_in_user(&up->length, &kp->length) ||
- assign_in_user(&up->css_ptr, &kp->css_ptr))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_atomisp_parameters32(struct atomisp_parameters __user *kp,
- struct atomisp_parameters32 __user *up)
-{
- int n = offsetof(struct atomisp_parameters32, output_frame) /
- sizeof(compat_uptr_t);
- compat_uptr_t stp, mtp, dcp, dscp;
- struct {
- struct atomisp_shading_table shading_table;
- struct atomisp_morph_table morph_table;
- struct atomisp_dis_coefficients dvs2_coefs;
- struct atomisp_dvs_6axis_config dvs_6axis_config;
- } __user *karg = (void __user *)(kp + 1);
-
- if (!access_ok(up, sizeof(struct atomisp_parameters32)))
- return -EFAULT;
-
- while (n >= 0) {
- compat_uptr_t __user *src = (compat_uptr_t __user *)up + n;
- void * __user *dst = (void * __user *)kp + n;
- compat_uptr_t tmp;
-
- if (get_user_cast(tmp, src) || put_user_force(compat_ptr(tmp), dst))
- return -EFAULT;
- n--;
- }
-
- if (assign_in_user(&kp->isp_config_id, &up->isp_config_id) ||
- assign_in_user(&kp->per_frame_setting, &up->per_frame_setting) ||
- get_user(stp, &up->shading_table) ||
- get_user(mtp, &up->morph_table) ||
- get_user(dcp, &up->dvs2_coefs) ||
- get_user(dscp, &up->dvs_6axis_config))
- return -EFAULT;
-
- /* handle shading table */
- if (stp && (get_atomisp_shading_table32(&karg->shading_table,
- compat_ptr(stp)) ||
- put_user_force(&karg->shading_table, &kp->shading_table)))
- return -EFAULT;
-
- /* handle morph table */
- if (mtp && (get_atomisp_morph_table32(&karg->morph_table,
- compat_ptr(mtp)) ||
- put_user_force(&karg->morph_table, &kp->morph_table)))
- return -EFAULT;
-
- /* handle dvs2 coefficients */
- if (dcp && (get_atomisp_dis_coefficients32(&karg->dvs2_coefs,
- compat_ptr(dcp)) ||
- put_user_force(&karg->dvs2_coefs, &kp->dvs2_coefs)))
- return -EFAULT;
-
- /* handle dvs 6axis configuration */
- if (dscp &&
- (get_atomisp_dvs_6axis_config32(&karg->dvs_6axis_config,
- compat_ptr(dscp)) ||
- put_user_force(&karg->dvs_6axis_config, &kp->dvs_6axis_config)))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_acc_fw_load_to_pipe32(struct atomisp_acc_fw_load_to_pipe __user *kp,
- struct atomisp_acc_fw_load_to_pipe32 __user *up)
-{
- compat_uptr_t data;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_load_to_pipe32)) ||
- assign_in_user(&kp->flags, &up->flags) ||
- assign_in_user(&kp->fw_handle, &up->fw_handle) ||
- assign_in_user(&kp->size, &up->size) ||
- assign_in_user(&kp->type, &up->type) ||
- assign_in_user(&kp->reserved[0], &up->reserved[0]) ||
- assign_in_user(&kp->reserved[1], &up->reserved[1]) ||
- assign_in_user(&kp->reserved[2], &up->reserved[2]) ||
- get_user(data, &up->data) ||
- put_user(compat_ptr(data), &kp->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-put_atomisp_acc_fw_load_to_pipe32(struct atomisp_acc_fw_load_to_pipe __user *kp,
- struct atomisp_acc_fw_load_to_pipe32 __user *up)
-{
- void __user *data;
-
- if (!access_ok(up, sizeof(struct atomisp_acc_fw_load_to_pipe32)) ||
- assign_in_user(&up->flags, &kp->flags) ||
- assign_in_user(&up->fw_handle, &kp->fw_handle) ||
- assign_in_user(&up->size, &kp->size) ||
- assign_in_user(&up->type, &kp->type) ||
- assign_in_user(&up->reserved[0], &kp->reserved[0]) ||
- assign_in_user(&up->reserved[1], &kp->reserved[1]) ||
- assign_in_user(&up->reserved[2], &kp->reserved[2]) ||
- get_user(data, &kp->data) ||
- put_user(ptr_to_compat(data), &up->data))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-get_atomisp_sensor_ae_bracketing_lut(struct atomisp_sensor_ae_bracketing_lut __user *kp,
- struct atomisp_sensor_ae_bracketing_lut32 __user *up)
-{
- compat_uptr_t lut;
-
- if (!access_ok(up, sizeof(struct atomisp_sensor_ae_bracketing_lut32)) ||
- assign_in_user(&kp->lut_size, &up->lut_size) ||
- get_user(lut, &up->lut) ||
- put_user_force(compat_ptr(lut), &kp->lut))
- return -EFAULT;
-
- return 0;
-}
-
-static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- long ret = -ENOIOCTLCMD;
-
- if (file->f_op->unlocked_ioctl)
- ret = file->f_op->unlocked_ioctl(file, cmd, arg);
-
- return ret;
-}
-
-static long atomisp_do_compat_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- union {
- struct atomisp_histogram his;
- struct atomisp_dis_statistics dis_s;
- struct atomisp_dis_coefficients dis_c;
- struct atomisp_dvs_6axis_config dvs_c;
- struct atomisp_3a_statistics s3a_s;
- struct atomisp_morph_table mor_t;
- struct v4l2_framebuffer v4l2_buf;
- struct atomisp_overlay overlay;
- struct atomisp_calibration_group cal_grp;
- struct atomisp_acc_fw_load acc_fw_load;
- struct atomisp_acc_fw_arg acc_fw_arg;
- struct v4l2_private_int_data v4l2_pri_data;
- struct atomisp_shading_table shd_tbl;
- struct atomisp_acc_map acc_map;
- struct atomisp_acc_s_mapped_arg acc_map_arg;
- struct atomisp_parameters param;
- struct atomisp_acc_fw_load_to_pipe acc_fw_to_pipe;
- struct atomisp_metadata md;
- struct atomisp_metadata_with_type md_with_type;
- struct atomisp_sensor_ae_bracketing_lut lut;
- } __user *karg;
- void __user *up = compat_ptr(arg);
- long err = -ENOIOCTLCMD;
-
- karg = compat_alloc_user_space(
- sizeof(*karg) + (cmd == ATOMISP_IOC_S_PARAMETERS32 ?
- sizeof(struct atomisp_shading_table) +
- sizeof(struct atomisp_morph_table) +
- sizeof(struct atomisp_dis_coefficients) +
- sizeof(struct atomisp_dvs_6axis_config) : 0));
- if (!karg)
- return -ENOMEM;
-
- /* First, convert the command. */
- switch (cmd) {
- case ATOMISP_IOC_G_HISTOGRAM32:
- cmd = ATOMISP_IOC_G_HISTOGRAM;
- break;
- case ATOMISP_IOC_S_HISTOGRAM32:
- cmd = ATOMISP_IOC_S_HISTOGRAM;
- break;
- case ATOMISP_IOC_G_DIS_STAT32:
- cmd = ATOMISP_IOC_G_DIS_STAT;
- break;
- case ATOMISP_IOC_S_DIS_COEFS32:
- cmd = ATOMISP_IOC_S_DIS_COEFS;
- break;
- case ATOMISP_IOC_S_DIS_VECTOR32:
- cmd = ATOMISP_IOC_S_DIS_VECTOR;
- break;
- case ATOMISP_IOC_G_3A_STAT32:
- cmd = ATOMISP_IOC_G_3A_STAT;
- break;
- case ATOMISP_IOC_G_ISP_GDC_TAB32:
- cmd = ATOMISP_IOC_G_ISP_GDC_TAB;
- break;
- case ATOMISP_IOC_S_ISP_GDC_TAB32:
- cmd = ATOMISP_IOC_S_ISP_GDC_TAB;
- break;
- case ATOMISP_IOC_S_ISP_FPN_TABLE32:
- cmd = ATOMISP_IOC_S_ISP_FPN_TABLE;
- break;
- case ATOMISP_IOC_G_ISP_OVERLAY32:
- cmd = ATOMISP_IOC_G_ISP_OVERLAY;
- break;
- case ATOMISP_IOC_S_ISP_OVERLAY32:
- cmd = ATOMISP_IOC_S_ISP_OVERLAY;
- break;
- case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP32:
- cmd = ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP;
- break;
- case ATOMISP_IOC_ACC_LOAD32:
- cmd = ATOMISP_IOC_ACC_LOAD;
- break;
- case ATOMISP_IOC_ACC_S_ARG32:
- cmd = ATOMISP_IOC_ACC_S_ARG;
- break;
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA32:
- cmd = ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA;
- break;
- case ATOMISP_IOC_S_ISP_SHD_TAB32:
- cmd = ATOMISP_IOC_S_ISP_SHD_TAB;
- break;
- case ATOMISP_IOC_ACC_DESTAB32:
- cmd = ATOMISP_IOC_ACC_DESTAB;
- break;
- case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA32:
- cmd = ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA;
- break;
- case ATOMISP_IOC_ACC_MAP32:
- cmd = ATOMISP_IOC_ACC_MAP;
- break;
- case ATOMISP_IOC_ACC_UNMAP32:
- cmd = ATOMISP_IOC_ACC_UNMAP;
- break;
- case ATOMISP_IOC_ACC_S_MAPPED_ARG32:
- cmd = ATOMISP_IOC_ACC_S_MAPPED_ARG;
- break;
- case ATOMISP_IOC_S_PARAMETERS32:
- cmd = ATOMISP_IOC_S_PARAMETERS;
- break;
- case ATOMISP_IOC_ACC_LOAD_TO_PIPE32:
- cmd = ATOMISP_IOC_ACC_LOAD_TO_PIPE;
- break;
- case ATOMISP_IOC_G_METADATA32:
- cmd = ATOMISP_IOC_G_METADATA;
- break;
- case ATOMISP_IOC_G_METADATA_BY_TYPE32:
- cmd = ATOMISP_IOC_G_METADATA_BY_TYPE;
- break;
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT32:
- cmd = ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT;
- break;
- }
-
- switch (cmd) {
- case ATOMISP_IOC_G_HISTOGRAM:
- case ATOMISP_IOC_S_HISTOGRAM:
- err = get_atomisp_histogram32(&karg->his, up);
- break;
- case ATOMISP_IOC_G_DIS_STAT:
- err = get_atomisp_dis_statistics32(&karg->dis_s, up);
- break;
- case ATOMISP_IOC_S_DIS_COEFS:
- err = get_atomisp_dis_coefficients32(&karg->dis_c, up);
- break;
- case ATOMISP_IOC_S_DIS_VECTOR:
- err = get_atomisp_dvs_6axis_config32(&karg->dvs_c, up);
- break;
- case ATOMISP_IOC_G_3A_STAT:
- err = get_atomisp_3a_statistics32(&karg->s3a_s, up);
- break;
- case ATOMISP_IOC_G_ISP_GDC_TAB:
- case ATOMISP_IOC_S_ISP_GDC_TAB:
- err = get_atomisp_morph_table32(&karg->mor_t, up);
- break;
- case ATOMISP_IOC_S_ISP_FPN_TABLE:
- err = get_v4l2_framebuffer32(&karg->v4l2_buf, up);
- break;
- case ATOMISP_IOC_G_ISP_OVERLAY:
- case ATOMISP_IOC_S_ISP_OVERLAY:
- err = get_atomisp_overlay32(&karg->overlay, up);
- break;
- case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP:
- err = get_atomisp_calibration_group32(&karg->cal_grp, up);
- break;
- case ATOMISP_IOC_ACC_LOAD:
- err = get_atomisp_acc_fw_load32(&karg->acc_fw_load, up);
- break;
- case ATOMISP_IOC_ACC_S_ARG:
- case ATOMISP_IOC_ACC_DESTAB:
- err = get_atomisp_acc_fw_arg32(&karg->acc_fw_arg, up);
- break;
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
- case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA:
- err = get_v4l2_private_int_data32(&karg->v4l2_pri_data, up);
- break;
- case ATOMISP_IOC_S_ISP_SHD_TAB:
- err = get_atomisp_shading_table32(&karg->shd_tbl, up);
- break;
- case ATOMISP_IOC_ACC_MAP:
- case ATOMISP_IOC_ACC_UNMAP:
- err = get_atomisp_acc_map32(&karg->acc_map, up);
- break;
- case ATOMISP_IOC_ACC_S_MAPPED_ARG:
- err = get_atomisp_acc_s_mapped_arg32(&karg->acc_map_arg, up);
- break;
- case ATOMISP_IOC_S_PARAMETERS:
- err = get_atomisp_parameters32(&karg->param, up);
- break;
- case ATOMISP_IOC_ACC_LOAD_TO_PIPE:
- err = get_atomisp_acc_fw_load_to_pipe32(&karg->acc_fw_to_pipe,
- up);
- break;
- case ATOMISP_IOC_G_METADATA:
- err = get_atomisp_metadata_stat32(&karg->md, up);
- break;
- case ATOMISP_IOC_G_METADATA_BY_TYPE:
- err = get_atomisp_metadata_by_type_stat32(&karg->md_with_type,
- up);
- break;
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT:
- err = get_atomisp_sensor_ae_bracketing_lut(&karg->lut, up);
- break;
- }
- if (err)
- return err;
-
- err = native_ioctl(file, cmd, (unsigned long)karg);
- if (err)
- return err;
-
- switch (cmd) {
- case ATOMISP_IOC_G_HISTOGRAM:
- err = put_atomisp_histogram32(&karg->his, up);
- break;
- case ATOMISP_IOC_G_DIS_STAT:
- err = put_atomisp_dis_statistics32(&karg->dis_s, up);
- break;
- case ATOMISP_IOC_G_3A_STAT:
- err = put_atomisp_3a_statistics32(&karg->s3a_s, up);
- break;
- case ATOMISP_IOC_G_ISP_GDC_TAB:
- err = put_atomisp_morph_table32(&karg->mor_t, up);
- break;
- case ATOMISP_IOC_G_ISP_OVERLAY:
- err = put_atomisp_overlay32(&karg->overlay, up);
- break;
- case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP:
- err = put_atomisp_calibration_group32(&karg->cal_grp, up);
- break;
- case ATOMISP_IOC_ACC_LOAD:
- err = put_atomisp_acc_fw_load32(&karg->acc_fw_load, up);
- break;
- case ATOMISP_IOC_ACC_S_ARG:
- case ATOMISP_IOC_ACC_DESTAB:
- err = put_atomisp_acc_fw_arg32(&karg->acc_fw_arg, up);
- break;
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
- case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA:
- err = put_v4l2_private_int_data32(&karg->v4l2_pri_data, up);
- break;
- case ATOMISP_IOC_ACC_MAP:
- case ATOMISP_IOC_ACC_UNMAP:
- err = put_atomisp_acc_map32(&karg->acc_map, up);
- break;
- case ATOMISP_IOC_ACC_S_MAPPED_ARG:
- err = put_atomisp_acc_s_mapped_arg32(&karg->acc_map_arg, up);
- break;
- case ATOMISP_IOC_ACC_LOAD_TO_PIPE:
- err = put_atomisp_acc_fw_load_to_pipe32(&karg->acc_fw_to_pipe,
- up);
- break;
- case ATOMISP_IOC_G_METADATA:
- err = put_atomisp_metadata_stat32(&karg->md, up);
- break;
- case ATOMISP_IOC_G_METADATA_BY_TYPE:
- err = put_atomisp_metadata_by_type_stat32(&karg->md_with_type,
- up);
- break;
- }
-
- return err;
-}
-
-long atomisp_compat_ioctl32(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct video_device *vdev = video_devdata(file);
- struct atomisp_device *isp = video_get_drvdata(vdev);
- long ret = -ENOIOCTLCMD;
-
- if (!file->f_op->unlocked_ioctl)
- return ret;
-
- switch (cmd) {
- case ATOMISP_IOC_G_XNR:
- case ATOMISP_IOC_S_XNR:
- case ATOMISP_IOC_G_NR:
- case ATOMISP_IOC_S_NR:
- case ATOMISP_IOC_G_TNR:
- case ATOMISP_IOC_S_TNR:
- case ATOMISP_IOC_G_BLACK_LEVEL_COMP:
- case ATOMISP_IOC_S_BLACK_LEVEL_COMP:
- case ATOMISP_IOC_G_EE:
- case ATOMISP_IOC_S_EE:
- case ATOMISP_IOC_S_DIS_VECTOR:
- case ATOMISP_IOC_G_ISP_PARM:
- case ATOMISP_IOC_S_ISP_PARM:
- case ATOMISP_IOC_G_ISP_GAMMA:
- case ATOMISP_IOC_S_ISP_GAMMA:
- case ATOMISP_IOC_ISP_MAKERNOTE:
- case ATOMISP_IOC_G_ISP_MACC:
- case ATOMISP_IOC_S_ISP_MACC:
- case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION:
- case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION:
- case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION:
- case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION:
- case ATOMISP_IOC_G_ISP_CTC:
- case ATOMISP_IOC_S_ISP_CTC:
- case ATOMISP_IOC_G_ISP_WHITE_BALANCE:
- case ATOMISP_IOC_S_ISP_WHITE_BALANCE:
- case ATOMISP_IOC_CAMERA_BRIDGE:
- case ATOMISP_IOC_G_SENSOR_MODE_DATA:
- case ATOMISP_IOC_S_EXPOSURE:
- case ATOMISP_IOC_G_3A_CONFIG:
- case ATOMISP_IOC_S_3A_CONFIG:
- case ATOMISP_IOC_ACC_UNLOAD:
- case ATOMISP_IOC_ACC_START:
- case ATOMISP_IOC_ACC_WAIT:
- case ATOMISP_IOC_ACC_ABORT:
- case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION:
- case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION:
- case ATOMISP_IOC_S_CONT_CAPTURE_CONFIG:
- case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS:
- case ATOMISP_IOC_EXT_ISP_CTRL:
- case ATOMISP_IOC_EXP_ID_UNLOCK:
- case ATOMISP_IOC_EXP_ID_CAPTURE:
- case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE:
- case ATOMISP_IOC_G_FORMATS_CONFIG:
- case ATOMISP_IOC_S_FORMATS_CONFIG:
- case ATOMISP_IOC_S_EXPOSURE_WINDOW:
- case ATOMISP_IOC_S_ACC_STATE:
- case ATOMISP_IOC_G_ACC_STATE:
- case ATOMISP_IOC_INJECT_A_FAKE_EVENT:
- case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO:
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE:
- case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE:
- case ATOMISP_IOC_G_INVALID_FRAME_NUM:
- case ATOMISP_IOC_S_ARRAY_RESOLUTION:
- case ATOMISP_IOC_S_SENSOR_RUNMODE:
- case ATOMISP_IOC_G_UPDATE_EXPOSURE:
- ret = native_ioctl(file, cmd, arg);
- break;
-
- case ATOMISP_IOC_G_HISTOGRAM32:
- case ATOMISP_IOC_S_HISTOGRAM32:
- case ATOMISP_IOC_G_DIS_STAT32:
- case ATOMISP_IOC_S_DIS_COEFS32:
- case ATOMISP_IOC_S_DIS_VECTOR32:
- case ATOMISP_IOC_G_3A_STAT32:
- case ATOMISP_IOC_G_ISP_GDC_TAB32:
- case ATOMISP_IOC_S_ISP_GDC_TAB32:
- case ATOMISP_IOC_S_ISP_FPN_TABLE32:
- case ATOMISP_IOC_G_ISP_OVERLAY32:
- case ATOMISP_IOC_S_ISP_OVERLAY32:
- case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP32:
- case ATOMISP_IOC_ACC_LOAD32:
- case ATOMISP_IOC_ACC_S_ARG32:
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA32:
- case ATOMISP_IOC_S_ISP_SHD_TAB32:
- case ATOMISP_IOC_ACC_DESTAB32:
- case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA32:
- case ATOMISP_IOC_ACC_MAP32:
- case ATOMISP_IOC_ACC_UNMAP32:
- case ATOMISP_IOC_ACC_S_MAPPED_ARG32:
- case ATOMISP_IOC_S_PARAMETERS32:
- case ATOMISP_IOC_ACC_LOAD_TO_PIPE32:
- case ATOMISP_IOC_G_METADATA32:
- case ATOMISP_IOC_G_METADATA_BY_TYPE32:
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT32:
- ret = atomisp_do_compat_ioctl(file, cmd, arg);
- break;
-
- default:
- dev_warn(isp->dev,
- "%s: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
- __func__, _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd),
- cmd);
- break;
- }
- return ret;
-}
-#endif /* CONFIG_COMPAT */
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
index 060b8765ae96..56456e59bf89 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
@@ -25,13 +25,13 @@
static struct v4l2_mbus_framefmt *__csi2_get_format(struct
atomisp_mipi_csi2_device
* csi2,
- struct
- v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
enum
v4l2_subdev_format_whence
which, unsigned int pad) {
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csi2->subdev, cfg, pad);
+ return v4l2_subdev_get_try_format(&csi2->subdev, sd_state,
+ pad);
else
return &csi2->formats[pad];
}
@@ -44,7 +44,7 @@ static struct v4l2_mbus_framefmt *__csi2_get_format(struct
* return -EINVAL or zero on success
*/
static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
const struct atomisp_in_fmt_conv *ic = atomisp_in_fmt_conv;
@@ -70,13 +70,13 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
* return -EINVAL or zero on success
*/
static int csi2_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __csi2_get_format(csi2, cfg, fmt->which, fmt->pad);
+ format = __csi2_get_format(csi2, sd_state, fmt->which, fmt->pad);
fmt->format = *format;
@@ -84,12 +84,14 @@ static int csi2_get_format(struct v4l2_subdev *sd,
}
int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int which, uint16_t pad,
struct v4l2_mbus_framefmt *ffmt)
{
struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *actual_ffmt = __csi2_get_format(csi2, cfg, which, pad);
+ struct v4l2_mbus_framefmt *actual_ffmt = __csi2_get_format(csi2,
+ sd_state,
+ which, pad);
if (pad == CSI2_PAD_SINK) {
const struct atomisp_in_fmt_conv *ic;
@@ -110,12 +112,14 @@ int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
tmp_ffmt = *ffmt = *actual_ffmt;
- return atomisp_csi2_set_ffmt(sd, cfg, which, CSI2_PAD_SOURCE,
+ return atomisp_csi2_set_ffmt(sd, sd_state, which,
+ CSI2_PAD_SOURCE,
&tmp_ffmt);
}
/* FIXME: DPCM decompression */
- *actual_ffmt = *ffmt = *__csi2_get_format(csi2, cfg, which, CSI2_PAD_SINK);
+ *actual_ffmt = *ffmt = *__csi2_get_format(csi2, sd_state, which,
+ CSI2_PAD_SINK);
return 0;
}
@@ -129,10 +133,10 @@ int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
* return -EINVAL or zero on success
*/
static int csi2_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- return atomisp_csi2_set_ffmt(sd, cfg, fmt->which, fmt->pad,
+ return atomisp_csi2_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
&fmt->format);
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
index 59261e8f1a1a..e35711be8a37 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
@@ -44,7 +44,7 @@ struct atomisp_mipi_csi2_device {
};
int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int which, uint16_t pad,
struct v4l2_mbus_framefmt *ffmt);
int atomisp_mipi_csi2_init(struct atomisp_device *isp);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_file.c b/drivers/staging/media/atomisp/pci/atomisp_file.c
index e568ca99c45a..4570a9ab100b 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_file.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_file.c
@@ -80,7 +80,7 @@ static int file_input_s_stream(struct v4l2_subdev *sd, int enable)
}
static int file_input_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -104,16 +104,16 @@ static int file_input_get_fmt(struct v4l2_subdev *sd,
}
static int file_input_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
if (format->pad)
return -EINVAL;
- file_input_get_fmt(sd, cfg, format);
+ file_input_get_fmt(sd, sd_state, format);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
return 0;
}
@@ -130,7 +130,7 @@ static int file_input_s_power(struct v4l2_subdev *sd, int on)
}
static int file_input_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
/*to fake*/
@@ -138,7 +138,7 @@ static int file_input_enum_mbus_code(struct v4l2_subdev *sd,
}
static int file_input_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
/*to fake*/
@@ -146,7 +146,7 @@ static int file_input_enum_frame_size(struct v4l2_subdev *sd,
}
static int file_input_enum_frame_ival(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval_enum
*fie)
{
diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index f1e6b2597853..f82bf082aa79 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -837,7 +837,7 @@ dev_init:
}
/* runtime power management, turn on ISP */
- ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+ ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
dev_err(isp->dev, "Failed to power on device\n");
goto error;
@@ -881,9 +881,9 @@ done:
css_error:
atomisp_css_uninit(isp);
+ pm_runtime_put(vdev->v4l2_dev->dev);
error:
hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
- pm_runtime_put(vdev->v4l2_dev->dev);
rt_mutex_unlock(&isp->mutex);
return ret;
}
@@ -963,7 +963,7 @@ static int atomisp_release(struct file *file)
if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
}
@@ -975,7 +975,7 @@ subdev_uninit:
if (isp->sw_contex.file_input && asd->fmt_auto->val) {
struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
- atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
+ atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
}
@@ -1016,7 +1016,7 @@ subdev_uninit:
done:
if (!acc_node) {
- atomisp_subdev_set_selection(&asd->subdev, fh.pad,
+ atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
atomisp_subdev_source_pad(vdev),
V4L2_SEL_TGT_COMPOSE, 0,
@@ -1283,7 +1283,8 @@ const struct v4l2_file_operations atomisp_fops = {
.unlocked_ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
/*
- * There are problems with this code. Disable this for now.
+ * this was removed because of bugs, the interface
+ * needs to be made safe for compat tasks instead.
.compat_ioctl32 = atomisp_compat_ioctl32,
*/
#endif
@@ -1297,10 +1298,7 @@ const struct v4l2_file_operations atomisp_file_fops = {
.mmap = atomisp_file_mmap,
.unlocked_ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
- /*
- * There are problems with this code. Disable this for now.
- .compat_ioctl32 = atomisp_compat_ioctl32,
- */
+ /* .compat_ioctl32 = atomisp_compat_ioctl32, */
#endif
.poll = atomisp_poll,
};
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c
index 2ef5f44e4b6b..12f22ad007c7 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c
@@ -213,7 +213,7 @@ static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
* return -EINVAL or zero on success
*/
static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
@@ -246,7 +246,7 @@ static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
}
struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
u32 which, uint32_t pad,
uint32_t target)
{
@@ -255,9 +255,9 @@ struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
if (which == V4L2_SUBDEV_FORMAT_TRY) {
switch (target) {
case V4L2_SEL_TGT_CROP:
- return v4l2_subdev_get_try_crop(sd, cfg, pad);
+ return v4l2_subdev_get_try_crop(sd, sd_state, pad);
case V4L2_SEL_TGT_COMPOSE:
- return v4l2_subdev_get_try_compose(sd, cfg, pad);
+ return v4l2_subdev_get_try_compose(sd, sd_state, pad);
}
}
@@ -273,19 +273,20 @@ struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt
*atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
+ struct v4l2_subdev_state *sd_state, uint32_t which,
uint32_t pad)
{
struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(sd, cfg, pad);
+ return v4l2_subdev_get_try_format(sd, sd_state, pad);
return &isp_sd->fmt[pad].fmt;
}
static void isp_get_fmt_rect(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
+ struct v4l2_subdev_state *sd_state,
+ uint32_t which,
struct v4l2_mbus_framefmt **ffmt,
struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
@@ -293,16 +294,16 @@ static void isp_get_fmt_rect(struct v4l2_subdev *sd,
unsigned int i;
for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
- ffmt[i] = atomisp_subdev_get_ffmt(sd, cfg, which, i);
- crop[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
+ ffmt[i] = atomisp_subdev_get_ffmt(sd, sd_state, which, i);
+ crop[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
V4L2_SEL_TGT_CROP);
- comp[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
+ comp[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
V4L2_SEL_TGT_COMPOSE);
}
}
static void isp_subdev_propagate(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
u32 which, uint32_t pad, uint32_t target,
uint32_t flags)
{
@@ -313,7 +314,7 @@ static void isp_subdev_propagate(struct v4l2_subdev *sd,
if (flags & V4L2_SEL_FLAG_KEEP_CONFIG)
return;
- isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
+ isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
switch (pad) {
case ATOMISP_SUBDEV_PAD_SINK: {
@@ -323,7 +324,7 @@ static void isp_subdev_propagate(struct v4l2_subdev *sd,
r.width = ffmt[pad]->width;
r.height = ffmt[pad]->height;
- atomisp_subdev_set_selection(sd, cfg, which, pad,
+ atomisp_subdev_set_selection(sd, sd_state, which, pad,
target, flags, &r);
break;
}
@@ -331,7 +332,7 @@ static void isp_subdev_propagate(struct v4l2_subdev *sd,
}
static int isp_subdev_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct v4l2_rect *rec;
@@ -340,7 +341,7 @@ static int isp_subdev_get_selection(struct v4l2_subdev *sd,
if (rval)
return rval;
- rec = atomisp_subdev_get_rect(sd, cfg, sel->which, sel->pad,
+ rec = atomisp_subdev_get_rect(sd, sd_state, sel->which, sel->pad,
sel->target);
if (!rec)
return -EINVAL;
@@ -365,7 +366,7 @@ static const char *atomisp_pad_str(unsigned int pad)
}
int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
u32 which, uint32_t pad, uint32_t target,
u32 flags, struct v4l2_rect *r)
{
@@ -382,7 +383,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
- isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
+ isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
dev_dbg(isp->dev,
"sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
@@ -450,7 +451,8 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
struct v4l2_rect tmp = *crop[pad];
atomisp_subdev_set_selection(
- sd, cfg, which, i, V4L2_SEL_TGT_COMPOSE,
+ sd, sd_state, which, i,
+ V4L2_SEL_TGT_COMPOSE,
flags, &tmp);
}
}
@@ -472,9 +474,9 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
* when dvs is disabled.
*/
dvs_w = dvs_h = 12;
- } else
+ } else {
dvs_w = dvs_h = 0;
-
+ }
atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
atomisp_css_input_set_effective_resolution(isp_sd, stream_id,
crop[pad]->width, crop[pad]->height);
@@ -551,9 +553,9 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
ffmt[pad]->height = comp[pad]->height;
}
- if (!atomisp_subdev_get_rect(sd, cfg, which, pad, target))
+ if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target))
return -EINVAL;
- *r = *atomisp_subdev_get_rect(sd, cfg, which, pad, target);
+ *r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target);
dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
r->left, r->top, r->width, r->height);
@@ -562,7 +564,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
}
static int isp_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
@@ -570,7 +572,8 @@ static int isp_subdev_set_selection(struct v4l2_subdev *sd,
if (rval)
return rval;
- return atomisp_subdev_set_selection(sd, cfg, sel->which, sel->pad,
+ return atomisp_subdev_set_selection(sd, sd_state, sel->which,
+ sel->pad,
sel->target, sel->flags, &sel->r);
}
@@ -609,13 +612,14 @@ static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd)
}
void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
+ struct v4l2_subdev_state *sd_state,
+ uint32_t which,
u32 pad, struct v4l2_mbus_framefmt *ffmt)
{
struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
struct atomisp_device *isp = isp_sd->isp;
struct v4l2_mbus_framefmt *__ffmt =
- atomisp_subdev_get_ffmt(sd, cfg, which, pad);
+ atomisp_subdev_get_ffmt(sd, sd_state, which, pad);
u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
enum atomisp_input_stream_id stream_id;
@@ -640,7 +644,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
*__ffmt = *ffmt;
- isp_subdev_propagate(sd, cfg, which, pad,
+ isp_subdev_propagate(sd, sd_state, which, pad,
V4L2_SEL_TGT_CROP, 0);
if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
@@ -679,10 +683,11 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
* to the format type.
*/
static int isp_subdev_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- fmt->format = *atomisp_subdev_get_ffmt(sd, cfg, fmt->which, fmt->pad);
+ fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which,
+ fmt->pad);
return 0;
}
@@ -698,10 +703,11 @@ static int isp_subdev_get_format(struct v4l2_subdev *sd,
* to the format type.
*/
static int isp_subdev_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- atomisp_subdev_set_ffmt(sd, cfg, fmt->which, fmt->pad, &fmt->format);
+ atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
+ &fmt->format);
return 0;
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h
index 330a77eed8aa..d6fcfab6352d 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h
@@ -437,19 +437,20 @@ uint16_t atomisp_subdev_source_pad(struct video_device *vdev);
/* Get pointer to appropriate format */
struct v4l2_mbus_framefmt
*atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
+ struct v4l2_subdev_state *sd_state, uint32_t which,
uint32_t pad);
struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
u32 which, uint32_t pad,
uint32_t target);
int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
u32 which, uint32_t pad, uint32_t target,
u32 flags, struct v4l2_rect *r);
/* Actually set the format */
void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
+ struct v4l2_subdev_state *sd_state,
+ uint32_t which,
u32 pad, struct v4l2_mbus_framefmt *ffmt);
int atomisp_update_run_mode(struct atomisp_sub_device *asd);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_tpg.c b/drivers/staging/media/atomisp/pci/atomisp_tpg.c
index 1def80bab180..e29a96da5f98 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_tpg.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_tpg.c
@@ -29,7 +29,7 @@ static int tpg_s_stream(struct v4l2_subdev *sd, int enable)
}
static int tpg_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
/*to fake*/
@@ -37,7 +37,7 @@ static int tpg_get_fmt(struct v4l2_subdev *sd,
}
static int tpg_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *fmt = &format->format;
@@ -47,7 +47,7 @@ static int tpg_set_fmt(struct v4l2_subdev *sd,
/* only raw8 grbg is supported by TPG */
fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- cfg->try_fmt = *fmt;
+ sd_state->pads->try_fmt = *fmt;
return 0;
}
return 0;
@@ -65,7 +65,7 @@ static int tpg_s_power(struct v4l2_subdev *sd, int on)
}
static int tpg_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
/*to fake*/
@@ -73,7 +73,7 @@ static int tpg_enum_mbus_code(struct v4l2_subdev *sd,
}
static int tpg_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
/*to fake*/
@@ -81,7 +81,7 @@ static int tpg_enum_frame_size(struct v4l2_subdev *sd,
}
static int tpg_enum_frame_ival(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval_enum *fie)
{
/*to fake*/
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 0295e2e32d79..948769ca6539 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -1178,7 +1178,7 @@ static void atomisp_unregister_entities(struct atomisp_device *isp)
atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);
list_for_each_entry_safe(sd, next, &isp->v4l2_dev.subdevs, list)
- v4l2_device_unregister_subdev(sd);
+ v4l2_device_unregister_subdev(sd);
v4l2_device_unregister(&isp->v4l2_dev);
media_device_unregister(&isp->media_dev);
@@ -1500,9 +1500,9 @@ static int init_atomisp_wdts(struct atomisp_device *isp)
for (i = 0; i < isp->num_of_streams; i++) {
struct atomisp_sub_device *asd = &isp->asd[i];
- if (!IS_ISP2401)
+ if (!IS_ISP2401) {
timer_setup(&asd->wdt, atomisp_wdt, 0);
- else {
+ } else {
timer_setup(&asd->video_out_capture.wdt,
atomisp_wdt, 0);
timer_setup(&asd->video_out_preview.wdt,
diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
index 27dd8ce8ba0a..d26b1301eeb7 100644
--- a/drivers/staging/media/atomisp/pci/sh_css.c
+++ b/drivers/staging/media/atomisp/pci/sh_css.c
@@ -239,8 +239,8 @@ ia_css_reset_defaults(struct sh_css *css);
static void
sh_css_init_host_sp_control_vars(void);
-static int set_num_primary_stages(unsigned int *num,
- enum ia_css_pipe_version version);
+static int
+set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version);
static bool
need_capture_pp(const struct ia_css_pipe *pipe);
@@ -308,8 +308,7 @@ sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
const void *acc_fw);
static int
-alloc_continuous_frames(
- struct ia_css_pipe *pipe, bool init_time);
+alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time);
static void
pipe_global_init(void);
@@ -413,7 +412,6 @@ aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
static void
sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
{
- assert(pipe);
if (!pipe) {
IA_CSS_ERROR("NULL input parameter");
return;
@@ -453,15 +451,15 @@ static enum ia_css_frame_format yuv422_copy_formats[] = {
* by the copy binary given the stream format.
* */
static int
-verify_copy_out_frame_format(struct ia_css_pipe *pipe) {
+verify_copy_out_frame_format(struct ia_css_pipe *pipe)
+{
enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
unsigned int i, found = 0;
assert(pipe);
assert(pipe->stream);
- switch (pipe->stream->config.input_config.format)
- {
+ switch (pipe->stream->config.input_config.format) {
case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
case ATOMISP_INPUT_FORMAT_YUV420_8:
for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
@@ -528,7 +526,8 @@ ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
#if !defined(ISP2401)
static int
-sh_css_config_input_network(struct ia_css_stream *stream) {
+sh_css_config_input_network(struct ia_css_stream *stream)
+{
unsigned int fmt_type;
struct ia_css_pipe *pipe = stream->last_pipe;
struct ia_css_binary *binary = NULL;
@@ -554,8 +553,7 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
stream->config.mode);
if ((binary && (binary->online || stream->config.continuous)) ||
- pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
- {
+ pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
err = ia_css_ifmtr_configure(&stream->config,
binary);
if (err)
@@ -563,8 +561,7 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
}
if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
- stream->config.mode == IA_CSS_INPUT_MODE_PRBS)
- {
+ stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
unsigned int hblank_cycles = 100,
vblank_lines = 6,
width,
@@ -723,35 +720,32 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
switch (stream_cfg->mode) {
case IA_CSS_INPUT_MODE_TPG:
- if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
+ if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
- } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
+ else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
- } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
+ else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
- }
break;
case IA_CSS_INPUT_MODE_PRBS:
- if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
+ if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
- } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
+ else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
- } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
+ else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2)
isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
- }
break;
case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
- if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
+ if (stream_cfg->source.port.port == MIPI_PORT0_ID)
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
- } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
+ else if (stream_cfg->source.port.port == MIPI_PORT1_ID)
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
- } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
+ else if (stream_cfg->source.port.port == MIPI_PORT2_ID)
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
- }
break;
default:
@@ -804,15 +798,14 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
rc = true;
switch (stream_cfg->mode) {
case IA_CSS_INPUT_MODE_TPG:
- if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
+ if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP)
isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
- } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
+ else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD)
isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
- } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
+ else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO)
isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
- } else {
+ else
rc = false;
- }
/*
* TODO
@@ -951,12 +944,12 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
- UNCOMPRESSED_BITS_PER_PIXEL_10) {
+ UNCOMPRESSED_BITS_PER_PIXEL_10)
fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
- } else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
- UNCOMPRESSED_BITS_PER_PIXEL_12) {
+ else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
+ UNCOMPRESSED_BITS_PER_PIXEL_12)
fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
- } else
+ else
return false;
}
@@ -1045,7 +1038,8 @@ static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
}
static int
-sh_css_config_input_network(struct ia_css_stream *stream) {
+sh_css_config_input_network(struct ia_css_stream *stream)
+{
bool rc;
ia_css_isys_descr_t isys_stream_descr;
unsigned int sp_thread_id;
@@ -1060,19 +1054,16 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"sh_css_config_input_network() enter 0x%p:\n", stream);
- if (stream->config.continuous)
- {
- if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
+ if (stream->config.continuous) {
+ if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)
pipe = stream->last_pipe;
- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
+ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP)
pipe = stream->last_pipe;
- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
+ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
+ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO)
pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
- }
- } else
- {
+ } else {
pipe = stream->last_pipe;
if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
/*
@@ -1087,7 +1078,6 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
}
}
- assert(pipe);
if (!pipe)
return -EINVAL;
@@ -1095,8 +1085,7 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
if (pipe->pipeline.stages->binary)
binary = pipe->pipeline.stages->binary;
- if (binary)
- {
+ if (binary) {
/* this was being done in ifmtr in 2400.
* online and cont bypass the init_in_frameinfo_memory_defaults
* so need to do it here
@@ -1111,8 +1100,7 @@ sh_css_config_input_network(struct ia_css_stream *stream) {
/* get the target input terminal */
sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
- for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
- {
+ for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
/* initialization */
memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
@@ -1210,11 +1198,10 @@ static inline struct ia_css_pipe *stream_get_target_pipe(
struct ia_css_pipe *target_pipe;
/* get the pipe that consumes the stream */
- if (stream->config.continuous) {
+ if (stream->config.continuous)
target_pipe = stream_get_copy_pipe(stream);
- } else {
+ else
target_pipe = stream_get_last_pipe(stream);
- }
return target_pipe;
}
@@ -1388,10 +1375,9 @@ start_binary(struct ia_css_pipe *pipe,
/* start the copy function on the SP */
static int
start_copy_on_sp(struct ia_css_pipe *pipe,
- struct ia_css_frame *out_frame) {
+ struct ia_css_frame *out_frame)
+{
(void)out_frame;
- assert(pipe);
- assert(pipe->stream);
if ((!pipe) || (!pipe->stream))
return -EINVAL;
@@ -1406,8 +1392,7 @@ start_copy_on_sp(struct ia_css_pipe *pipe,
sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
#if !defined(ISP2401)
- if (pipe->stream->reconfigure_css_rx)
- {
+ if (pipe->stream->reconfigure_css_rx) {
ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
pipe->stream->config.mode);
pipe->stream->reconfigure_css_rx = false;
@@ -1596,7 +1581,8 @@ ia_css_reset_defaults(struct sh_css *css)
int
ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
- const struct ia_css_fw *fw) {
+ const struct ia_css_fw *fw)
+{
int err;
if (!env)
@@ -1607,16 +1593,14 @@ ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
/* make sure we initialize my_css */
- if (my_css.flush != env->cpu_mem_env.flush)
- {
+ if (my_css.flush != env->cpu_mem_env.flush) {
ia_css_reset_defaults(&my_css);
my_css.flush = env->cpu_mem_env.flush;
}
ia_css_unload_firmware(); /* in case we are called twice */
err = sh_css_load_firmware(dev, fw->data, fw->bytes);
- if (!err)
- {
+ if (!err) {
err = ia_css_binary_init_infos();
if (!err)
fw_explicitly_loaded = true;
@@ -1630,7 +1614,8 @@ int
ia_css_init(struct device *dev, const struct ia_css_env *env,
const struct ia_css_fw *fw,
u32 mmu_l1_base,
- enum ia_css_irq_type irq_type) {
+ enum ia_css_irq_type irq_type)
+{
int err;
ia_css_spctrl_cfg spctrl_cfg;
@@ -1704,16 +1689,14 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
my_css.flush = flush_func;
err = ia_css_rmgr_init();
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
IA_CSS_LOG("init: %d", my_css_save_initialized);
- if (!my_css_save_initialized)
- {
+ if (!my_css_save_initialized) {
my_css_save_initialized = true;
my_css_save.mode = sh_css_mode_working;
memset(my_css_save.stream_seeds, 0,
@@ -1741,19 +1724,16 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
err = ia_css_refcount_init(REFCOUNT_SIZE);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
err = sh_css_params_init();
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
- if (fw)
- {
+ if (fw) {
ia_css_unload_firmware(); /* in case we already had firmware loaded */
err = sh_css_load_firmware(dev, fw->data, fw->bytes);
if (err) {
@@ -1774,23 +1754,20 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
return -EINVAL;
err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
#if WITH_PC_MONITORING
- if (!thread_alive)
- {
+ if (!thread_alive) {
thread_alive++;
sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
__func__);
spying_thread_create();
}
#endif
- if (!sh_css_hrt_system_is_idle())
- {
+ if (!sh_css_hrt_system_is_idle()) {
IA_CSS_LEAVE_ERR(-EBUSY);
return -EBUSY;
}
@@ -1823,7 +1800,8 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
}
int
-ia_css_enable_isys_event_queue(bool enable) {
+ia_css_enable_isys_event_queue(bool enable)
+{
if (sh_css_sp_is_running())
return -EBUSY;
sh_css_sp_enable_isys_event_queue(enable);
@@ -1844,7 +1822,8 @@ sh_css_flush(struct ia_css_acc_fw *fw)
* doing it from stream_create since we could run out of sp threads due to
* allocation on inactive pipelines. */
static int
-map_sp_threads(struct ia_css_stream *stream, bool map) {
+map_sp_threads(struct ia_css_stream *stream, bool map)
+{
struct ia_css_pipe *main_pipe = NULL;
struct ia_css_pipe *copy_pipe = NULL;
struct ia_css_pipe *capture_pipe = NULL;
@@ -1852,12 +1831,10 @@ map_sp_threads(struct ia_css_stream *stream, bool map) {
int err = 0;
enum ia_css_pipe_id pipe_id;
- assert(stream);
IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
stream, map ? "true" : "false");
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -1867,8 +1844,7 @@ map_sp_threads(struct ia_css_stream *stream, bool map) {
ia_css_pipeline_map(main_pipe->pipe_num, map);
- switch (pipe_id)
- {
+ switch (pipe_id) {
case IA_CSS_PIPE_ID_PREVIEW:
copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
@@ -1887,23 +1863,17 @@ map_sp_threads(struct ia_css_stream *stream, bool map) {
}
if (acc_pipe)
- {
ia_css_pipeline_map(acc_pipe->pipe_num, map);
- }
if (capture_pipe)
- {
ia_css_pipeline_map(capture_pipe->pipe_num, map);
- }
/* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
if (copy_pipe)
- {
ia_css_pipeline_map(copy_pipe->pipe_num, map);
- }
+
/* DH regular multi pipe - not continuous mode: map the next pipes too */
- if (!stream->config.continuous)
- {
+ if (!stream->config.continuous) {
int i;
for (i = 1; i < stream->num_pipes; i++)
@@ -1917,7 +1887,8 @@ map_sp_threads(struct ia_css_stream *stream, bool map) {
/* creates a host pipeline skeleton for all pipes in a stream. Called during
* stream_create. */
static int
-create_host_pipeline_structure(struct ia_css_stream *stream) {
+create_host_pipeline_structure(struct ia_css_stream *stream)
+{
struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
struct ia_css_pipe *acc_pipe = NULL;
enum ia_css_pipe_id pipe_id;
@@ -1926,27 +1897,22 @@ create_host_pipeline_structure(struct ia_css_stream *stream) {
unsigned int copy_pipe_delay = 0,
capture_pipe_delay = 0;
- assert(stream);
IA_CSS_ENTER_PRIVATE("stream = %p", stream);
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
main_pipe = stream->last_pipe;
- assert(main_pipe);
- if (!main_pipe)
- {
+ if (!main_pipe) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
pipe_id = main_pipe->mode;
- switch (pipe_id)
- {
+ switch (pipe_id) {
case IA_CSS_PIPE_ID_PREVIEW:
copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
copy_pipe_delay = main_pipe->dvs_frame_delay;
@@ -1986,30 +1952,23 @@ create_host_pipeline_structure(struct ia_css_stream *stream) {
}
if (!(err) && copy_pipe)
- {
err = ia_css_pipeline_create(&copy_pipe->pipeline,
copy_pipe->mode,
copy_pipe->pipe_num,
copy_pipe_delay);
- }
if (!(err) && capture_pipe)
- {
err = ia_css_pipeline_create(&capture_pipe->pipeline,
capture_pipe->mode,
capture_pipe->pipe_num,
capture_pipe_delay);
- }
if (!(err) && acc_pipe)
- {
err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
- }
/* DH regular multi pipe - not continuous mode: create the next pipelines too */
- if (!stream->config.continuous)
- {
+ if (!stream->config.continuous) {
int i;
for (i = 1; i < stream->num_pipes && 0 == err; i++) {
@@ -2028,7 +1987,8 @@ create_host_pipeline_structure(struct ia_css_stream *stream) {
/* creates a host pipeline for all pipes in a stream. Called during
* stream_start. */
static int
-create_host_pipeline(struct ia_css_stream *stream) {
+create_host_pipeline(struct ia_css_stream *stream)
+{
struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
struct ia_css_pipe *acc_pipe = NULL;
enum ia_css_pipe_id pipe_id;
@@ -2037,8 +1997,7 @@ create_host_pipeline(struct ia_css_stream *stream) {
unsigned int max_input_width = 0;
IA_CSS_ENTER_PRIVATE("stream = %p", stream);
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -2049,8 +2008,7 @@ create_host_pipeline(struct ia_css_stream *stream) {
/* No continuous frame allocation for capture pipe. It uses the
* "main" pipe's frames. */
if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
- (pipe_id == IA_CSS_PIPE_ID_VIDEO))
- {
+ (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
/* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
* The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
* based input frames) there is no continuous mode and thus no need for allocated continuous frames
@@ -2068,24 +2026,21 @@ create_host_pipeline(struct ia_css_stream *stream) {
#if !defined(ISP2401)
/* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
- if (pipe_id != IA_CSS_PIPE_ID_ACC)
- {
+ if (pipe_id != IA_CSS_PIPE_ID_ACC) {
err = allocate_mipi_frames(main_pipe, &stream->info);
if (err)
goto ERR;
}
#elif defined(ISP2401)
if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
- (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY))
- {
+ (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
err = allocate_mipi_frames(main_pipe, &stream->info);
if (err)
goto ERR;
}
#endif
- switch (pipe_id)
- {
+ switch (pipe_id) {
case IA_CSS_PIPE_ID_PREVIEW:
copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
@@ -2135,31 +2090,27 @@ create_host_pipeline(struct ia_css_stream *stream) {
if (err)
goto ERR;
- if (copy_pipe)
- {
+ if (copy_pipe) {
err = create_host_copy_pipeline(copy_pipe, max_input_width,
main_pipe->continuous_frames[0]);
if (err)
goto ERR;
}
- if (capture_pipe)
- {
+ if (capture_pipe) {
err = create_host_capture_pipeline(capture_pipe);
if (err)
goto ERR;
}
- if (acc_pipe)
- {
+ if (acc_pipe) {
err = create_host_acc_pipeline(acc_pipe);
if (err)
goto ERR;
}
/* DH regular multi pipe - not continuous mode: create the next pipelines too */
- if (!stream->config.continuous)
- {
+ if (!stream->config.continuous) {
int i;
for (i = 1; i < stream->num_pipes && 0 == err; i++) {
@@ -2201,10 +2152,9 @@ static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
static int
init_pipe_defaults(enum ia_css_pipe_mode mode,
struct ia_css_pipe *pipe,
- bool copy_pipe) {
-
- if (!pipe)
- {
+ bool copy_pipe)
+{
+ if (!pipe) {
IA_CSS_ERROR("NULL pipe parameter");
return -EINVAL;
}
@@ -2213,18 +2163,17 @@ init_pipe_defaults(enum ia_css_pipe_mode mode,
memcpy(pipe, &default_pipe, sizeof(default_pipe));
/* TODO: JB should not be needed, but temporary backward reference */
- switch (mode)
- {
+ switch (mode) {
case IA_CSS_PIPE_MODE_PREVIEW:
pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview));
break;
case IA_CSS_PIPE_MODE_CAPTURE:
- if (copy_pipe) {
+ if (copy_pipe)
pipe->mode = IA_CSS_PIPE_ID_COPY;
- } else {
+ else
pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
- }
+
memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture));
break;
case IA_CSS_PIPE_MODE_VIDEO:
@@ -2254,27 +2203,25 @@ pipe_global_init(void)
u8 i;
my_css.pipe_counter = 0;
- for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
+ for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
my_css.all_pipes[i] = NULL;
- }
}
static int
pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
- unsigned int *pipe_number) {
+ unsigned int *pipe_number)
+{
const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
u8 pipe_num = INVALID_PIPE_NUM;
u8 i;
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_ERROR("NULL pipe parameter");
return -EINVAL;
}
/* Assign a new pipe_num .... search for empty place */
- for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
- {
+ for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
if (!my_css.all_pipes[i]) {
/*position is reserved */
my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
@@ -2282,8 +2229,7 @@ pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
break;
}
}
- if (pipe_num == INVALID_PIPE_NUM)
- {
+ if (pipe_num == INVALID_PIPE_NUM) {
/* Max number of pipes already allocated */
IA_CSS_ERROR("Max number of pipes already created");
return -ENOSPC;
@@ -2309,12 +2255,12 @@ pipe_release_pipe_num(unsigned int pipe_num)
static int
create_pipe(enum ia_css_pipe_mode mode,
struct ia_css_pipe **pipe,
- bool copy_pipe) {
+ bool copy_pipe)
+{
int err = 0;
struct ia_css_pipe *me;
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_ERROR("NULL pipe parameter");
return -EINVAL;
}
@@ -2324,15 +2270,13 @@ create_pipe(enum ia_css_pipe_mode mode,
return -ENOMEM;
err = init_pipe_defaults(mode, me, copy_pipe);
- if (err)
- {
+ if (err) {
kfree(me);
return err;
}
err = pipe_generate_pipe_num(me, &me->pipe_num);
- if (err)
- {
+ if (err) {
kfree(me);
return err;
}
@@ -2361,7 +2305,6 @@ static void sh_css_pipe_free_acc_binaries(
struct ia_css_pipeline *pipeline;
struct ia_css_pipeline_stage *stage;
- assert(pipe);
if (!pipe) {
IA_CSS_ERROR("NULL input pointer");
return;
@@ -2378,26 +2321,24 @@ static void sh_css_pipe_free_acc_binaries(
}
int
-ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
+ia_css_pipe_destroy(struct ia_css_pipe *pipe)
+{
int err = 0;
IA_CSS_ENTER("pipe = %p", pipe);
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- if (pipe->stream)
- {
+ if (pipe->stream) {
IA_CSS_LOG("ia_css_stream_destroy not called!");
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- switch (pipe->config.mode)
- {
+ switch (pipe->config.mode) {
case IA_CSS_PIPE_MODE_PREVIEW:
/* need to take into account that this function is also called
on the internal copy pipe */
@@ -2461,9 +2402,8 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
/* Temporarily, not every sh_css_pipe has an acc_extension. */
if (pipe->config.acc_extension)
- {
ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
- }
+
kfree(pipe);
IA_CSS_LEAVE("err = %d", err);
return err;
@@ -2493,9 +2433,9 @@ ia_css_uninit(void)
ifmtr_set_if_blocking_mode_reset = true;
#endif
- if (!fw_explicitly_loaded) {
+ if (!fw_explicitly_loaded)
ia_css_unload_firmware();
- }
+
ia_css_spctrl_unload_fw(SP0_ID);
sh_css_sp_set_sp_running(false);
/* check and free any remaining mipi frames */
@@ -2681,8 +2621,8 @@ static int load_copy_binary(
}
static int
-alloc_continuous_frames(
- struct ia_css_pipe *pipe, bool init_time) {
+alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time)
+{
int err = 0;
struct ia_css_frame_info ref_info;
enum ia_css_pipe_id pipe_id;
@@ -2692,8 +2632,7 @@ alloc_continuous_frames(
IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
- if ((!pipe) || (!pipe->stream))
- {
+ if ((!pipe) || (!pipe->stream)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -2701,26 +2640,22 @@ alloc_continuous_frames(
pipe_id = pipe->mode;
continuous = pipe->stream->config.continuous;
- if (continuous)
- {
+ if (continuous) {
if (init_time) {
num_frames = pipe->stream->config.init_num_cont_raw_buf;
pipe->stream->continuous_pipe = pipe;
- } else
+ } else {
num_frames = pipe->stream->config.target_num_cont_raw_buf;
- } else
- {
+ }
+ } else {
num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
}
- if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
- {
+ if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
- } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
- {
+ } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
- } else
- {
+ } else {
/* should not happen */
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
@@ -2736,8 +2671,7 @@ alloc_continuous_frames(
#endif
#if !defined(HAS_NO_PACKED_RAW_PIXELS)
- if (pipe->stream->config.pack_raw_pixels)
- {
+ if (pipe->stream->config.pack_raw_pixels) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
@@ -2766,8 +2700,7 @@ alloc_continuous_frames(
else
idx = pipe->stream->config.init_num_cont_raw_buf;
- for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++)
- {
+ for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
/* free previous frame */
if (pipe->continuous_frames[i]) {
ia_css_frame_free(pipe->continuous_frames[i]);
@@ -2797,14 +2730,16 @@ alloc_continuous_frames(
}
int
-ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) {
+ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
+{
if (!stream)
return -EINVAL;
return alloc_continuous_frames(stream->continuous_pipe, false);
}
static int
-load_preview_binaries(struct ia_css_pipe *pipe) {
+load_preview_binaries(struct ia_css_pipe *pipe)
+{
struct ia_css_frame_info prev_in_info,
prev_bds_out_info,
prev_out_info,
@@ -2912,8 +2847,7 @@ load_preview_binaries(struct ia_css_pipe *pipe) {
* then the preview binary selection is done again.
*/
if (need_vf_pp &&
- (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE))
- {
+ (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
/* Preview step 2 */
if (pipe->vf_yuv_ds_input_info.res.width)
prev_vf_info = pipe->vf_yuv_ds_input_info;
@@ -2938,8 +2872,7 @@ load_preview_binaries(struct ia_css_pipe *pipe) {
return err;
}
- if (need_vf_pp)
- {
+ if (need_vf_pp) {
struct ia_css_binary_descr vf_pp_descr;
/* Viewfinder post-processing */
@@ -2970,8 +2903,7 @@ load_preview_binaries(struct ia_css_pipe *pipe) {
#endif
/* Copy */
- if (need_isp_copy_binary)
- {
+ if (need_isp_copy_binary) {
err = load_copy_binary(pipe,
&mycs->copy_binary,
&mycs->preview_binary);
@@ -2979,8 +2911,7 @@ load_preview_binaries(struct ia_css_pipe *pipe) {
return err;
}
- if (pipe->shading_table)
- {
+ if (pipe->shading_table) {
ia_css_shading_table_free(pipe->shading_table);
pipe->shading_table = NULL;
}
@@ -2995,11 +2926,11 @@ ia_css_binary_unload(struct ia_css_binary *binary)
}
static int
-unload_preview_binaries(struct ia_css_pipe *pipe) {
+unload_preview_binaries(struct ia_css_pipe *pipe)
+{
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
- {
+ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -3052,20 +2983,19 @@ static int add_firmwares(
struct ia_css_frame *in = NULL;
struct ia_css_frame *vf = NULL;
- if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
+ if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0))
out[0] = out_frame;
- }
- if (fw->info.isp.sp.enable.in_frame != 0) {
+
+ if (fw->info.isp.sp.enable.in_frame != 0)
in = in_frame;
- }
- if (fw->info.isp.sp.enable.out_frame != 0) {
+
+ if (fw->info.isp.sp.enable.out_frame != 0)
vf = vf_frame;
- }
+
ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
out, in, vf, fw, binary_mode);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &extra_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &extra_stage);
if (err)
return err;
if (fw->info.isp.sp.enable.output != 0)
@@ -3173,9 +3103,8 @@ static int add_yuv_scaler_stage(
ia_css_pipe_get_generic_stage_desc(&stage_desc,
yuv_scaler_binary, out_frames, in_frame, vf_frame);
}
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- pre_vf_pp_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ pre_vf_pp_stage);
if (err)
return err;
in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
@@ -3233,9 +3162,8 @@ static int add_capture_pp_stage(
ia_css_pipe_get_generic_stage_desc(&stage_desc,
capture_pp_binary, out_frames, NULL, vf_frame);
}
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- capture_pp_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ capture_pp_stage);
if (err)
return err;
err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
@@ -3274,7 +3202,8 @@ static void sh_css_setup_queues(void)
static int
init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
- struct ia_css_frame *vf_frame, unsigned int idx) {
+ struct ia_css_frame *vf_frame, unsigned int idx)
+{
int err = 0;
unsigned int thread_id;
enum sh_css_queue_id queue_id;
@@ -3439,7 +3368,8 @@ ia_css_get_crop_offsets(
static int
init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
- struct ia_css_frame *frame, enum ia_css_frame_format format) {
+ struct ia_css_frame *frame, enum ia_css_frame_format format)
+{
struct ia_css_frame *in_frame;
int err = 0;
unsigned int thread_id;
@@ -3480,7 +3410,8 @@ init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
static int
init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
- struct ia_css_frame *out_frame, unsigned int idx) {
+ struct ia_css_frame *out_frame, unsigned int idx)
+{
int err = 0;
unsigned int thread_id;
enum sh_css_queue_id queue_id;
@@ -3587,9 +3518,8 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe)
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
out_frames, NULL, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &copy_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &copy_stage);
if (err)
goto ERR;
in_frame = me->stages->args.out_frame[0];
@@ -3616,9 +3546,8 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe)
ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
out_frames, in_frame, vf_frame);
}
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &video_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &video_stage);
if (err)
goto ERR;
@@ -3681,13 +3610,10 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe)
struct ia_css_frame *tmp_out_frame = NULL;
for (i = 0; i < num_yuv_scaler; i++) {
- if (is_output_stage[i]) {
- tmp_out_frame = out_frame;
- } else {
- tmp_out_frame = NULL;
- }
- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
- NULL,
+ tmp_out_frame = is_output_stage[i] ? out_frame : NULL;
+
+ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
+ tmp_out_frame, NULL,
&yuv_scaler_binary[i],
&yuv_scaler_stage);
@@ -3711,14 +3637,14 @@ ERR:
}
static int
-create_host_acc_pipeline(struct ia_css_pipe *pipe) {
+create_host_acc_pipeline(struct ia_css_pipe *pipe)
+{
int err = 0;
const struct ia_css_fw_info *fw;
unsigned int i;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (!pipe->stream))
- {
+ if ((!pipe) || (!pipe->stream)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -3729,15 +3655,13 @@ create_host_acc_pipeline(struct ia_css_pipe *pipe) {
pipe->pipeline.pipe_qos_config = 0;
fw = pipe->vf_stage;
- for (i = 0; fw; fw = fw->next)
- {
+ for (i = 0; fw; fw = fw->next) {
err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
if (err)
goto ERR;
}
- for (i = 0; i < pipe->config.num_acc_stages; i++)
- {
+ for (i = 0; i < pipe->config.num_acc_stages; i++) {
struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
@@ -3754,7 +3678,8 @@ ERR:
/* Create stages for preview */
static int
-create_host_preview_pipeline(struct ia_css_pipe *pipe) {
+create_host_preview_pipeline(struct ia_css_pipe *pipe)
+{
struct ia_css_pipeline_stage *copy_stage = NULL;
struct ia_css_pipeline_stage *preview_stage = NULL;
struct ia_css_pipeline_stage *vf_pp_stage = NULL;
@@ -3774,8 +3699,7 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) {
#endif
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
- {
+ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -3803,16 +3727,14 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) {
/* Construct in_frame info (only in case we have dynamic input */
need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
#endif
- if (need_in_frameinfo_memory)
- {
+ if (need_in_frameinfo_memory) {
err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
IA_CSS_FRAME_FORMAT_RAW);
if (err)
goto ERR;
in_frame = &me->in_frame;
- } else
- {
+ } else {
in_frame = NULL;
}
@@ -3826,14 +3748,12 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) {
if (pipe->pipe_settings.preview.vf_pp_binary.info)
vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
- if (pipe->pipe_settings.preview.copy_binary.info)
- {
+ if (pipe->pipe_settings.preview.copy_binary.info) {
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
out_frames, NULL, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &copy_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &copy_stage);
if (err)
goto ERR;
in_frame = me->stages->args.out_frame[0];
@@ -3842,42 +3762,37 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) {
/* When continuous is enabled, configure in_frame with the
* last pipe, which is the copy pipe.
*/
- if (continuous || !online) {
+ if (continuous || !online)
in_frame = pipe->stream->last_pipe->continuous_frames[0];
- }
+
#else
in_frame = pipe->continuous_frames[0];
#endif
}
- if (vf_pp_binary)
- {
+ if (vf_pp_binary) {
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
out_frames, in_frame, NULL);
- } else
- {
+ } else {
ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
out_frames, in_frame, NULL);
}
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &preview_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &preview_stage);
if (err)
goto ERR;
/* If we use copy iso preview, the input must be yuv iso raw */
preview_stage->args.copy_vf =
preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
preview_stage->args.copy_output = !preview_stage->args.copy_vf;
- if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame)
- {
+ if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
/* in case of copy, use the vf frame as output frame */
preview_stage->args.out_vf_frame =
preview_stage->args.out_frame[0];
}
- if (vf_pp_binary)
- {
+ if (vf_pp_binary) {
if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
in_frame = preview_stage->args.out_vf_frame;
else
@@ -3917,7 +3832,8 @@ static void send_raw_frames(struct ia_css_pipe *pipe)
}
static int
-preview_start(struct ia_css_pipe *pipe) {
+preview_start(struct ia_css_pipe *pipe)
+{
int err = 0;
struct ia_css_pipe *copy_pipe, *capture_pipe;
struct ia_css_pipe *acc_pipe;
@@ -3927,8 +3843,7 @@ preview_start(struct ia_css_pipe *pipe) {
const struct ia_css_isp_parameters *params = NULL;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
- {
+ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -3955,8 +3870,7 @@ preview_start(struct ia_css_pipe *pipe) {
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
copy_ovrd = 1 << thread_id;
- if (pipe->stream->cont_capt)
- {
+ if (pipe->stream->cont_capt) {
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
&thread_id);
copy_ovrd |= 1 << thread_id;
@@ -3969,8 +3883,7 @@ preview_start(struct ia_css_pipe *pipe) {
}
/* Construct and load the copy pipe */
- if (pipe->stream->config.continuous)
- {
+ if (pipe->stream->config.continuous) {
sh_css_sp_init_pipeline(&copy_pipe->pipeline,
IA_CSS_PIPE_ID_COPY,
(uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
@@ -3991,8 +3904,7 @@ preview_start(struct ia_css_pipe *pipe) {
}
/* Construct and load the capture pipe */
- if (pipe->stream->cont_capt)
- {
+ if (pipe->stream->cont_capt) {
sh_css_sp_init_pipeline(&capture_pipe->pipeline,
IA_CSS_PIPE_ID_CAPTURE,
(uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
@@ -4010,8 +3922,7 @@ preview_start(struct ia_css_pipe *pipe) {
params);
}
- if (acc_pipe)
- {
+ if (acc_pipe) {
sh_css_sp_init_pipeline(&acc_pipe->pipeline,
IA_CSS_PIPE_ID_ACC,
(uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
@@ -4037,7 +3948,8 @@ preview_start(struct ia_css_pipe *pipe) {
int
ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
- const struct ia_css_buffer *buffer) {
+ const struct ia_css_buffer *buffer)
+{
int return_err = 0;
unsigned int thread_id;
enum sh_css_queue_id queue_id;
@@ -4052,8 +3964,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
- if ((!pipe) || (!buffer))
- {
+ if ((!pipe) || (!buffer)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
@@ -4062,8 +3973,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
/* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
is removed */
#if 0
- if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
- {
+ if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
bool found_pipe = false;
for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
@@ -4077,8 +3987,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
if (!found_pipe)
return -EINVAL;
}
- if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
- {
+ if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
bool found_pipe = false;
for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
@@ -4099,36 +4008,31 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
assert(pipe_id < IA_CSS_PIPE_ID_NUM);
assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
- if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
- (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
- (pipe_id >= IA_CSS_PIPE_ID_NUM))
- {
+ if (buf_type == IA_CSS_BUFFER_TYPE_INVALID ||
+ buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE ||
+ pipe_id >= IA_CSS_PIPE_ID_NUM) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
- if (!ret_err)
- {
+ if (!ret_err) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
- if (!ret_err)
- {
+ if (!ret_err) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
- {
+ if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- if (!sh_css_sp_is_running())
- {
+ if (!sh_css_sp_is_running()) {
IA_CSS_LOG("SP is not running!");
IA_CSS_LEAVE_ERR(-EBUSY);
/* SP is not running. The queues are not valid */
@@ -4146,36 +4050,32 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
ddr_buffer.cookie_ptr = buffer->driver_cookie;
ddr_buffer.timing_data = buffer->timing_data;
- if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
- {
+ if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
if (!buffer->data.stats_3a) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
ddr_buffer.payload.s3a = *buffer->data.stats_3a;
- } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
- {
+ } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
if (!buffer->data.stats_dvs) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
ddr_buffer.payload.dis = *buffer->data.stats_dvs;
- } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA)
- {
+ } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
if (!buffer->data.metadata) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
ddr_buffer.payload.metadata = *buffer->data.metadata;
- } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME))
- {
+ } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) {
if (!buffer->data.frame) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
@@ -4207,22 +4107,17 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
/* TODO: change next to correct pool for optimization */
ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
- assert(h_vbuf);
- assert(h_vbuf->vptr != 0x0);
-
- if ((!h_vbuf) || (h_vbuf->vptr == 0x0))
- {
+ if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
hmm_store(h_vbuf->vptr,
- (void *)(&ddr_buffer),
- sizeof(struct sh_css_hmm_buffer));
- if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
- || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
- || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS))
- {
+ (void *)(&ddr_buffer),
+ sizeof(struct sh_css_hmm_buffer));
+ if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS ||
+ buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS ||
+ buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS) {
if (!pipeline) {
ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
IA_CSS_LOG("pipeline is empty!");
@@ -4240,19 +4135,18 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
(uint32_t)h_vbuf->vptr);
}
}
- } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
- || (buf_type == IA_CSS_BUFFER_TYPE_METADATA))
- {
+ } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
return_err = ia_css_bufq_enqueue_buffer(thread_id,
queue_id,
(uint32_t)h_vbuf->vptr);
#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
- if (!(return_err) &&
- (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) {
+ if (!return_err &&
+ buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
ddr_buffer.payload.frame.frame_data,
queue_id, thread_id);
@@ -4260,8 +4154,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
#endif
}
- if (!return_err)
- {
+ if (!return_err) {
if (sh_css_hmm_buffer_record_acquire(
h_vbuf, buf_type,
HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
@@ -4276,8 +4169,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
* Tell the SP which queues are not empty,
* by sending the software event.
*/
- if (!return_err)
- {
+ if (!return_err) {
if (!sh_css_sp_is_running()) {
/* SP is not running. The queues are not valid */
IA_CSS_LOG("SP is not running!");
@@ -4289,8 +4181,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
(uint8_t)thread_id,
queue_id,
0);
- } else
- {
+ } else {
ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
IA_CSS_ERROR("buffer not enqueued");
}
@@ -4305,7 +4196,8 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
*/
int
ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
- struct ia_css_buffer *buffer) {
+ struct ia_css_buffer *buffer)
+{
int return_err;
enum sh_css_queue_id queue_id;
ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
@@ -4318,8 +4210,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
- if ((!pipe) || (!buffer))
- {
+ if ((!pipe) || (!buffer)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
@@ -4333,27 +4224,23 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
ddr_buffer.kernel_ptr = 0;
ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
- if (!ret_err)
- {
+ if (!ret_err) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
- if (!ret_err)
- {
+ if (!ret_err) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
- {
+ if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
- if (!sh_css_sp_is_running())
- {
+ if (!sh_css_sp_is_running()) {
IA_CSS_LOG("SP is not running!");
IA_CSS_LEAVE_ERR(-EBUSY);
/* SP is not running. The queues are not valid */
@@ -4363,8 +4250,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
return_err = ia_css_bufq_dequeue_buffer(queue_id,
(uint32_t *)&ddr_buffer_addr);
- if (!return_err)
- {
+ if (!return_err) {
struct ia_css_frame *frame;
struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
@@ -4389,8 +4275,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
}
hmm_load(ddr_buffer_addr,
- &ddr_buffer,
- sizeof(struct sh_css_hmm_buffer));
+ &ddr_buffer,
+ sizeof(struct sh_css_hmm_buffer));
/* if the kernel_ptr is 0 or an invalid, return an error.
* do not access the buffer via the kernal_ptr.
@@ -4412,8 +4298,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
buffer->driver_cookie = ddr_buffer.cookie_ptr;
buffer->timing_data = ddr_buffer.timing_data;
- if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
- (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
+ if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
+ buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
}
@@ -4506,8 +4392,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
* Tell the SP which queues are not full,
* by sending the software event.
*/
- if (!return_err)
- {
+ if (!return_err) {
if (!sh_css_sp_is_running()) {
IA_CSS_LOG("SP is not running!");
IA_CSS_LEAVE_ERR(-EBUSY);
@@ -4556,12 +4441,14 @@ static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
};
int
-ia_css_dequeue_event(struct ia_css_event *event) {
+ia_css_dequeue_event(struct ia_css_event *event)
+{
return ia_css_dequeue_psys_event(event);
}
int
-ia_css_dequeue_psys_event(struct ia_css_event *event) {
+ia_css_dequeue_psys_event(struct ia_css_event *event)
+{
enum ia_css_pipe_id pipe_id = 0;
u8 payload[4] = {0, 0, 0, 0};
int ret_err;
@@ -4576,11 +4463,9 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) {
if (!event)
return -EINVAL;
+ /* SP is not running. The queues are not valid */
if (!sh_css_sp_is_running())
- {
- /* SP is not running. The queues are not valid */
return -EBUSY;
- }
/* dequeue the event (if any) from the psys event queue */
ret_err = ia_css_bufq_dequeue_psys_event(payload);
@@ -4607,8 +4492,7 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) {
event->timer_code = 0;
event->timer_subcode = 0;
- if (event->type == IA_CSS_EVENT_TYPE_TIMER)
- {
+ if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
/* timer event ??? get the 2nd event and decode the data into the event struct */
u32 tmp_data;
/* 1st event: LSB 16-bit timer data and code */
@@ -4632,37 +4516,32 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) {
tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
event->timer_data |= (tmp_data << 16);
event->timer_subcode = payload[2];
- }
+ } else {
/* It's a non timer event. So clear first half of the timer event data.
* If the second part of the TIMER event is not received, we discard
* the first half of the timer data and process the non timer event without
* affecting the flow. So the non timer event falls through
* the code. */
- else {
event->timer_data = 0;
event->timer_code = 0;
event->timer_subcode = 0;
IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
}
}
- if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF)
- {
+ if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
event->port = (enum mipi_port_id)payload[1];
event->exp_id = payload[3];
- } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING)
- {
+ } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
event->fw_warning = (enum ia_css_fw_warning)payload[1];
/* exp_id is only available in these warning types */
if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
event->exp_id = payload[3];
- } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT)
- {
+ } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
event->fw_assert_module_id = payload[1]; /* module */
event->fw_assert_line_no = (payload[2] << 8) + payload[3];
/* payload[2] is line_no>>8, payload[3] is line_no&0xff */
- } else if (event->type != IA_CSS_EVENT_TYPE_TIMER)
- {
+ } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
/* pipe related events.
* payload[1] contains the pipe_num,
* payload[2] contains the pipe_id. These are different. */
@@ -4712,7 +4591,8 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) {
}
int
-ia_css_dequeue_isys_event(struct ia_css_event *event) {
+ia_css_dequeue_isys_event(struct ia_css_event *event)
+{
u8 payload[4] = {0, 0, 0, 0};
int err = 0;
@@ -4722,11 +4602,9 @@ ia_css_dequeue_isys_event(struct ia_css_event *event) {
if (!event)
return -EINVAL;
+ /* SP is not running. The queues are not valid */
if (!sh_css_sp_is_running())
- {
- /* SP is not running. The queues are not valid */
return -EBUSY;
- }
err = ia_css_bufq_dequeue_isys_event(payload);
if (err)
@@ -4759,7 +4637,8 @@ acc_start(struct ia_css_pipe *pipe)
}
static int
-sh_css_pipe_start(struct ia_css_stream *stream) {
+sh_css_pipe_start(struct ia_css_stream *stream)
+{
int err = 0;
struct ia_css_pipe *pipe;
@@ -4768,22 +4647,19 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
IA_CSS_ENTER_PRIVATE("stream = %p", stream);
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
pipe = stream->last_pipe;
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
pipe_id = pipe->mode;
- if (stream->started)
- {
+ if (stream->started) {
IA_CSS_WARNING("Cannot start stream that is already started");
IA_CSS_LEAVE_ERR(err);
return err;
@@ -4791,8 +4667,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
pipe->stop_requested = false;
- switch (pipe_id)
- {
+ switch (pipe_id) {
case IA_CSS_PIPE_ID_PREVIEW:
err = preview_start(pipe);
break;
@@ -4812,8 +4687,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
err = -EINVAL;
}
/* DH regular multi pipe - not continuous mode: start the next pipes too */
- if (!stream->config.continuous)
- {
+ if (!stream->config.continuous) {
int i;
for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
@@ -4843,8 +4717,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
}
}
}
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
@@ -4854,8 +4727,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
* don't use ISP parameters anyway. So this should be okay.
* The SP binary (jpeg) copy does not use any parameters.
*/
- if (!copy_on_sp(pipe))
- {
+ if (!copy_on_sp(pipe)) {
sh_css_invalidate_params(stream);
err = sh_css_param_update_isp_params(pipe,
stream->isp_params_configs, true, NULL);
@@ -4869,8 +4741,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
- if (!sh_css_sp_is_running())
- {
+ if (!sh_css_sp_is_running()) {
IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
/* SP is not running. The queues are not valid */
return -EBUSY;
@@ -4879,8 +4750,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
(uint8_t)thread_id, 0, 0);
/* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
- if (!stream->config.continuous)
- {
+ if (!stream->config.continuous) {
int i;
for (i = 1; i < stream->num_pipes; i++) {
@@ -4894,8 +4764,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
}
/* in case of continuous capture mode, we also start capture thread and copy thread*/
- if (pipe->stream->config.continuous)
- {
+ if (pipe->stream->config.continuous) {
struct ia_css_pipe *copy_pipe = NULL;
if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
@@ -4914,8 +4783,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
IA_CSS_PSYS_SW_EVENT_START_STREAM,
(uint8_t)thread_id, 0, 0);
}
- if (pipe->stream->cont_capt)
- {
+ if (pipe->stream->cont_capt) {
struct ia_css_pipe *capture_pipe = NULL;
if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
@@ -4936,8 +4804,7 @@ sh_css_pipe_start(struct ia_css_stream *stream) {
}
/* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
- if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
- {
+ if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
struct ia_css_pipe *acc_pipe = NULL;
acc_pipe = pipe->pipe_settings.preview.acc_pipe;
@@ -4988,7 +4855,8 @@ sh_css_continuous_is_enabled(uint8_t pipe_num)
/* ISP2400 */
int
ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
- int *buffer_depth) {
+ int *buffer_depth)
+{
if (!buffer_depth)
return -EINVAL;
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
@@ -4998,7 +4866,8 @@ ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
}
int
-ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
+ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
+{
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
(void)stream;
if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
@@ -5012,7 +4881,8 @@ ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
/* ISP2401 */
int
ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
- int *buffer_depth) {
+ int *buffer_depth)
+{
if (!buffer_depth)
return -EINVAL;
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
@@ -5036,18 +4906,14 @@ sh_css_pipes_stop(struct ia_css_stream *stream)
enum ia_css_pipe_id main_pipe_id;
int i;
- assert(stream);
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LOG("stream does NOT exist!");
err = -EINVAL;
goto ERR;
}
main_pipe = stream->last_pipe;
- assert(main_pipe);
- if (!main_pipe)
- {
+ if (!main_pipe) {
IA_CSS_LOG("main_pipe does NOT exist!");
err = -EINVAL;
goto ERR;
@@ -5060,11 +4926,10 @@ sh_css_pipes_stop(struct ia_css_stream *stream)
* Stop all "ia_css_pipe" instances in this target
* "ia_css_stream" instance.
*/
- for (i = 0; i < stream->num_pipes; i++)
- {
+ for (i = 0; i < stream->num_pipes; i++) {
/* send the "stop" request to the "ia_css_pipe" instance */
IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
- stream->pipes[i]->pipeline.pipe_id);
+ stream->pipes[i]->pipeline.pipe_id);
err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
/*
@@ -5095,8 +4960,7 @@ sh_css_pipes_stop(struct ia_css_stream *stream)
*
* We need to stop this "Copy Pipe", as well.
*/
- if (main_pipe->stream->config.continuous)
- {
+ if (main_pipe->stream->config.continuous) {
struct ia_css_pipe *copy_pipe = NULL;
/* get the reference to "Copy Pipe" */
@@ -5106,7 +4970,6 @@ sh_css_pipes_stop(struct ia_css_stream *stream)
copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
/* return the error code if "Copy Pipe" does NOT exist */
- assert(copy_pipe);
if (!copy_pipe) {
IA_CSS_LOG("Copy Pipe does NOT exist!");
err = -EINVAL;
@@ -5115,7 +4978,7 @@ sh_css_pipes_stop(struct ia_css_stream *stream)
/* send the "stop" request to "Copy Pipe" */
IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
- copy_pipe->pipeline.pipe_id);
+ copy_pipe->pipeline.pipe_id);
err = ia_css_pipeline_request_stop(&copy_pipe->pipeline);
}
@@ -5141,7 +5004,6 @@ sh_css_pipes_have_stopped(struct ia_css_stream *stream)
int i;
- assert(stream);
if (!stream) {
IA_CSS_LOG("stream does NOT exist!");
rval = false;
@@ -5149,7 +5011,6 @@ sh_css_pipes_have_stopped(struct ia_css_stream *stream)
}
main_pipe = stream->last_pipe;
- assert(main_pipe);
if (!main_pipe) {
IA_CSS_LOG("main_pipe does NOT exist!");
@@ -5190,7 +5051,6 @@ sh_css_pipes_have_stopped(struct ia_css_stream *stream)
copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
/* return if "Copy Pipe" does NOT exist */
- assert(copy_pipe);
if (!copy_pipe) {
IA_CSS_LOG("Copy Pipe does NOT exist!");
@@ -5272,8 +5132,7 @@ sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
binary = ia_css_pipe_get_shading_correction_binary(pipe);
- if (binary)
- {
+ if (binary) {
err = ia_css_binary_get_shading_info(binary,
IA_CSS_SHADING_CORRECTION_TYPE_1,
pipe->required_bds_factor,
@@ -5283,8 +5142,7 @@ sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
/* Other function calls can be added here when other shading correction types will be added
* in the future.
*/
- } else
- {
+ } else {
/* When the pipe does not have a binary which has the shading
* correction, this function does not need to fill the shading
* information. It is not a error case, and then
@@ -5297,7 +5155,8 @@ sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
static int
sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
- struct ia_css_grid_info *info) {
+ struct ia_css_grid_info *info)
+{
int err = 0;
struct ia_css_binary *binary = NULL;
@@ -5308,30 +5167,27 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
binary = ia_css_pipe_get_s3a_binary(pipe);
- if (binary)
- {
+ if (binary) {
err = ia_css_binary_3a_grid_info(binary, info, pipe);
if (err)
goto ERR;
- } else
+ } else {
memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
+ }
binary = ia_css_pipe_get_sdis_binary(pipe);
- if (binary)
- {
+ if (binary) {
ia_css_binary_dvs_grid_info(binary, info, pipe);
ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
- } else
- {
+ } else {
memset(&info->dvs_grid.dvs_grid_info, 0,
sizeof(info->dvs_grid.dvs_grid_info));
memset(&info->dvs_grid.dvs_stat_grid_info, 0,
sizeof(info->dvs_grid.dvs_stat_grid_info));
}
- if (binary)
- {
+ if (binary) {
/* copy pipe does not have ISP binary*/
info->isp_in_width = binary->internal_frame_info.res.width;
info->isp_in_height = binary->internal_frame_info.res.height;
@@ -5351,7 +5207,8 @@ ERR :
*/
static int
ia_css_pipe_check_format(struct ia_css_pipe *pipe,
- enum ia_css_frame_format format) {
+ enum ia_css_frame_format format)
+{
const enum ia_css_frame_format *supported_formats;
int number_of_formats;
int found = 0;
@@ -5359,8 +5216,7 @@ ia_css_pipe_check_format(struct ia_css_pipe *pipe,
IA_CSS_ENTER_PRIVATE("");
- if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info)
- {
+ if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
IA_CSS_ERROR("Pipe or binary info is not set");
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
@@ -5369,23 +5225,19 @@ ia_css_pipe_check_format(struct ia_css_pipe *pipe,
supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
- for (i = 0; i < number_of_formats && !found; i++)
- {
+ for (i = 0; i < number_of_formats && !found; i++) {
if (supported_formats[i] == format) {
found = 1;
break;
}
}
- if (!found)
- {
+ if (!found) {
IA_CSS_ERROR("Requested format is not supported by binary");
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
- } else
- {
- IA_CSS_LEAVE_ERR_PRIVATE(0);
- return 0;
}
+ IA_CSS_LEAVE_ERR_PRIVATE(0);
+ return 0;
}
static int load_video_binaries(struct ia_css_pipe *pipe)
@@ -5528,10 +5380,10 @@ static int load_video_binaries(struct ia_css_pipe *pipe)
&mycs->video_binary);
if (err) {
- if (video_vf_info) {
- /* This will do another video binary lookup later for YUV_LINE format*/
+ /* This will do another video binary lookup later for YUV_LINE format*/
+ if (video_vf_info)
need_vf_pp = true;
- } else
+ else
return err;
} else if (video_vf_info) {
/* The first video binary lookup is successful, but we may
@@ -5694,13 +5546,13 @@ static int load_video_binaries(struct ia_css_pipe *pipe)
}
static int
-unload_video_binaries(struct ia_css_pipe *pipe) {
+unload_video_binaries(struct ia_css_pipe *pipe)
+{
unsigned int i;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO))
- {
+ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -5850,31 +5702,29 @@ static int
sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
unsigned int height, unsigned int min_width,
enum ia_css_frame_format format,
- unsigned int idx) {
+ unsigned int idx)
+{
int err = 0;
IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
pipe, width, height, min_width, format, idx);
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
err = ia_css_util_check_res(width, height);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
if (pipe->vf_output_info[idx].res.width != width ||
pipe->vf_output_info[idx].res.height != height ||
pipe->vf_output_info[idx].format != format)
- {
ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
format, min_width);
- }
+
IA_CSS_LEAVE_ERR_PRIVATE(0);
return 0;
}
@@ -5955,7 +5805,7 @@ static bool need_capt_ldc(
}
static int set_num_primary_stages(unsigned int *num,
- enum ia_css_pipe_version version)
+ enum ia_css_pipe_version version)
{
int err = 0;
@@ -6155,10 +6005,13 @@ static int load_primary_binaries(
capt_pp_in_info = &prim_out_info;
ia_css_pipe_get_capturepp_binarydesc(pipe,
- &capture_pp_descr, capt_pp_in_info,
- &capt_pp_out_info, &vf_info);
+ &capture_pp_descr,
+ capt_pp_in_info,
+ &capt_pp_out_info,
+ &vf_info);
+
err = ia_css_binary_find(&capture_pp_descr,
- &mycs->capture_pp_binary);
+ &mycs->capture_pp_binary);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -6168,11 +6021,12 @@ static int load_primary_binaries(
struct ia_css_binary_descr capt_ldc_descr;
ia_css_pipe_get_ldc_binarydesc(pipe,
- &capt_ldc_descr, &prim_out_info,
- &capt_ldc_out_info);
+ &capt_ldc_descr,
+ &prim_out_info,
+ &capt_ldc_out_info);
err = ia_css_binary_find(&capt_ldc_descr,
- &mycs->capture_ldc_binary);
+ &mycs->capture_ldc_binary);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -6189,8 +6043,9 @@ static int load_primary_binaries(
if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
(i == mycs->num_primary_stage - 1))
local_vf_info = &vf_info;
- ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info,
- &prim_out_info, local_vf_info, i);
+ ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i],
+ &prim_in_info, &prim_out_info,
+ local_vf_info, i);
err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -6242,8 +6097,8 @@ static int load_primary_binaries(
/* ISP Copy */
if (need_isp_copy_binary) {
err = load_copy_binary(pipe,
- &mycs->copy_binary,
- &mycs->primary_binary[0]);
+ &mycs->copy_binary,
+ &mycs->primary_binary[0]);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -6254,7 +6109,8 @@ static int load_primary_binaries(
}
static int
-allocate_delay_frames(struct ia_css_pipe *pipe) {
+allocate_delay_frames(struct ia_css_pipe *pipe)
+{
unsigned int num_delay_frames = 0, i = 0;
unsigned int dvs_frame_delay = 0;
struct ia_css_frame_info ref_info;
@@ -6264,8 +6120,7 @@ allocate_delay_frames(struct ia_css_pipe *pipe) {
IA_CSS_ENTER_PRIVATE("");
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_ERROR("Invalid args - pipe %p", pipe);
return -EINVAL;
}
@@ -6276,8 +6131,7 @@ allocate_delay_frames(struct ia_css_pipe *pipe) {
if (dvs_frame_delay > 0)
num_delay_frames = dvs_frame_delay + 1;
- switch (mode)
- {
+ switch (mode) {
case IA_CSS_PIPE_ID_CAPTURE: {
struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
(void)mycs_capture;
@@ -6329,8 +6183,7 @@ allocate_delay_frames(struct ia_css_pipe *pipe) {
ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
- for (i = 0; i < num_delay_frames; i++)
- {
+ for (i = 0; i < num_delay_frames; i++) {
err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
if (err)
return err;
@@ -6339,8 +6192,8 @@ allocate_delay_frames(struct ia_css_pipe *pipe) {
return 0;
}
-static int load_advanced_binaries(
- struct ia_css_pipe *pipe) {
+static int load_advanced_binaries(struct ia_css_pipe *pipe)
+{
struct ia_css_frame_info pre_in_info, gdc_in_info,
post_in_info, post_out_info,
vf_info, *vf_pp_in_info, *pipe_out_info,
@@ -6353,7 +6206,7 @@ static int load_advanced_binaries(
assert(pipe);
assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
- pipe->mode == IA_CSS_PIPE_ID_COPY);
+ pipe->mode == IA_CSS_PIPE_ID_COPY);
if (pipe->pipe_settings.capture.pre_isp_binary.info)
return 0;
pipe_out_info = &pipe->output_info[0];
@@ -6366,17 +6219,18 @@ static int load_advanced_binaries(
need_pp = need_capture_pp(pipe);
ia_css_frame_info_set_format(&vf_info,
- IA_CSS_FRAME_FORMAT_YUV_LINE);
+ IA_CSS_FRAME_FORMAT_YUV_LINE);
/* we build up the pipeline starting at the end */
/* Capture post-processing */
if (need_pp) {
struct ia_css_binary_descr capture_pp_descr;
- ia_css_pipe_get_capturepp_binarydesc(pipe,
- &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
+ ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
+ &post_out_info,
+ pipe_out_info, &vf_info);
err = ia_css_binary_find(&capture_pp_descr,
- &pipe->pipe_settings.capture.capture_pp_binary);
+ &pipe->pipe_settings.capture.capture_pp_binary);
if (err)
return err;
} else {
@@ -6387,10 +6241,11 @@ static int load_advanced_binaries(
{
struct ia_css_binary_descr post_gdc_descr;
- ia_css_pipe_get_post_gdc_binarydesc(pipe,
- &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
+ ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr,
+ &post_in_info,
+ &post_out_info, &vf_info);
err = ia_css_binary_find(&post_gdc_descr,
- &pipe->pipe_settings.capture.post_isp_binary);
+ &pipe->pipe_settings.capture.post_isp_binary);
if (err)
return err;
}
@@ -6400,9 +6255,9 @@ static int load_advanced_binaries(
struct ia_css_binary_descr gdc_descr;
ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
- &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
+ &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
err = ia_css_binary_find(&gdc_descr,
- &pipe->pipe_settings.capture.anr_gdc_binary);
+ &pipe->pipe_settings.capture.anr_gdc_binary);
if (err)
return err;
}
@@ -6414,9 +6269,9 @@ static int load_advanced_binaries(
struct ia_css_binary_descr pre_gdc_descr;
ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
- &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
+ &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
err = ia_css_binary_find(&pre_gdc_descr,
- &pipe->pipe_settings.capture.pre_isp_binary);
+ &pipe->pipe_settings.capture.pre_isp_binary);
if (err)
return err;
}
@@ -6438,7 +6293,7 @@ static int load_advanced_binaries(
ia_css_pipe_get_vfpp_binarydesc(pipe,
&vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
err = ia_css_binary_find(&vf_pp_descr,
- &pipe->pipe_settings.capture.vf_pp_binary);
+ &pipe->pipe_settings.capture.vf_pp_binary);
if (err)
return err;
}
@@ -6450,14 +6305,14 @@ static int load_advanced_binaries(
#endif
if (need_isp_copy)
load_copy_binary(pipe,
- &pipe->pipe_settings.capture.copy_binary,
- &pipe->pipe_settings.capture.pre_isp_binary);
+ &pipe->pipe_settings.capture.copy_binary,
+ &pipe->pipe_settings.capture.pre_isp_binary);
return err;
}
-static int load_bayer_isp_binaries(
- struct ia_css_pipe *pipe) {
+static int load_bayer_isp_binaries(struct ia_css_pipe *pipe)
+{
struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
int err = 0;
struct ia_css_binary_descr pre_de_descr;
@@ -6465,7 +6320,7 @@ static int load_bayer_isp_binaries(
IA_CSS_ENTER_PRIVATE("");
assert(pipe);
assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
- pipe->mode == IA_CSS_PIPE_ID_COPY);
+ pipe->mode == IA_CSS_PIPE_ID_COPY);
pipe_out_info = &pipe->output_info[0];
if (pipe->pipe_settings.capture.pre_isp_binary.info)
@@ -6476,17 +6331,17 @@ static int load_bayer_isp_binaries(
return err;
ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
- &pre_isp_in_info,
- pipe_out_info);
+ &pre_isp_in_info,
+ pipe_out_info);
err = ia_css_binary_find(&pre_de_descr,
- &pipe->pipe_settings.capture.pre_isp_binary);
+ &pipe->pipe_settings.capture.pre_isp_binary);
return err;
}
-static int load_low_light_binaries(
- struct ia_css_pipe *pipe) {
+static int load_low_light_binaries(struct ia_css_pipe *pipe)
+{
struct ia_css_frame_info pre_in_info, anr_in_info,
post_in_info, post_out_info,
vf_info, *pipe_vf_out_info, *pipe_out_info,
@@ -6498,7 +6353,7 @@ static int load_low_light_binaries(
IA_CSS_ENTER_PRIVATE("");
assert(pipe);
assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
- pipe->mode == IA_CSS_PIPE_ID_COPY);
+ pipe->mode == IA_CSS_PIPE_ID_COPY);
if (pipe->pipe_settings.capture.pre_isp_binary.info)
return 0;
@@ -6513,17 +6368,18 @@ static int load_low_light_binaries(
need_pp = need_capture_pp(pipe);
ia_css_frame_info_set_format(&vf_info,
- IA_CSS_FRAME_FORMAT_YUV_LINE);
+ IA_CSS_FRAME_FORMAT_YUV_LINE);
/* we build up the pipeline starting at the end */
/* Capture post-processing */
if (need_pp) {
struct ia_css_binary_descr capture_pp_descr;
- ia_css_pipe_get_capturepp_binarydesc(pipe,
- &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
+ ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
+ &post_out_info,
+ pipe_out_info, &vf_info);
err = ia_css_binary_find(&capture_pp_descr,
- &pipe->pipe_settings.capture.capture_pp_binary);
+ &pipe->pipe_settings.capture.capture_pp_binary);
if (err)
return err;
} else {
@@ -6537,7 +6393,7 @@ static int load_low_light_binaries(
ia_css_pipe_get_post_anr_binarydesc(pipe,
&post_anr_descr, &post_in_info, &post_out_info, &vf_info);
err = ia_css_binary_find(&post_anr_descr,
- &pipe->pipe_settings.capture.post_isp_binary);
+ &pipe->pipe_settings.capture.post_isp_binary);
if (err)
return err;
}
@@ -6547,9 +6403,9 @@ static int load_low_light_binaries(
struct ia_css_binary_descr anr_descr;
ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
- &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
+ &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
err = ia_css_binary_find(&anr_descr,
- &pipe->pipe_settings.capture.anr_gdc_binary);
+ &pipe->pipe_settings.capture.anr_gdc_binary);
if (err)
return err;
}
@@ -6561,9 +6417,9 @@ static int load_low_light_binaries(
struct ia_css_binary_descr pre_anr_descr;
ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
- &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
+ &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
err = ia_css_binary_find(&pre_anr_descr,
- &pipe->pipe_settings.capture.pre_isp_binary);
+ &pipe->pipe_settings.capture.pre_isp_binary);
if (err)
return err;
}
@@ -6582,10 +6438,10 @@ static int load_low_light_binaries(
{
struct ia_css_binary_descr vf_pp_descr;
- ia_css_pipe_get_vfpp_binarydesc(pipe,
- &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
+ ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
+ vf_pp_in_info, pipe_vf_out_info);
err = ia_css_binary_find(&vf_pp_descr,
- &pipe->pipe_settings.capture.vf_pp_binary);
+ &pipe->pipe_settings.capture.vf_pp_binary);
if (err)
return err;
}
@@ -6597,8 +6453,8 @@ static int load_low_light_binaries(
#endif
if (need_isp_copy)
err = load_copy_binary(pipe,
- &pipe->pipe_settings.capture.copy_binary,
- &pipe->pipe_settings.capture.pre_isp_binary);
+ &pipe->pipe_settings.capture.copy_binary,
+ &pipe->pipe_settings.capture.pre_isp_binary);
return err;
}
@@ -6623,15 +6479,15 @@ static bool copy_on_sp(struct ia_css_pipe *pipe)
return rval;
}
-static int load_capture_binaries(
- struct ia_css_pipe *pipe) {
+static int load_capture_binaries(struct ia_css_pipe *pipe)
+{
int err = 0;
bool must_be_raw;
IA_CSS_ENTER_PRIVATE("");
assert(pipe);
assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
- pipe->mode == IA_CSS_PIPE_ID_COPY);
+ pipe->mode == IA_CSS_PIPE_ID_COPY);
if (pipe->pipe_settings.capture.primary_binary[0].info) {
IA_CSS_LEAVE_ERR_PRIVATE(0);
@@ -6692,13 +6548,14 @@ static int load_capture_binaries(
}
static int
-unload_capture_binaries(struct ia_css_pipe *pipe) {
+unload_capture_binaries(struct ia_css_pipe *pipe)
+{
unsigned int i;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY)))
- {
+ if (!pipe || (pipe->mode != IA_CSS_PIPE_ID_CAPTURE &&
+ pipe->mode != IA_CSS_PIPE_ID_COPY)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -6726,7 +6583,8 @@ unload_capture_binaries(struct ia_css_pipe *pipe) {
static bool
need_downscaling(const struct ia_css_resolution in_res,
- const struct ia_css_resolution out_res) {
+ const struct ia_css_resolution out_res)
+{
if (in_res.width > out_res.width || in_res.height > out_res.height)
return true;
@@ -6734,7 +6592,8 @@ need_downscaling(const struct ia_css_resolution in_res,
}
static bool
-need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
+need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
+{
unsigned int i;
struct ia_css_resolution in_res, out_res;
@@ -6773,10 +6632,11 @@ need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
/* which has some hard-coded knowledge which prevents reuse of the function. */
/* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
static int ia_css_pipe_create_cas_scaler_desc_single_output(
- struct ia_css_frame_info *cas_scaler_in_info,
- struct ia_css_frame_info *cas_scaler_out_info,
- struct ia_css_frame_info *cas_scaler_vf_info,
- struct ia_css_cas_binary_descr *descr) {
+ struct ia_css_frame_info *cas_scaler_in_info,
+ struct ia_css_frame_info *cas_scaler_out_info,
+ struct ia_css_frame_info *cas_scaler_vf_info,
+ struct ia_css_cas_binary_descr *descr)
+{
unsigned int i;
unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
int err = 0;
@@ -6794,9 +6654,9 @@ static int ia_css_pipe_create_cas_scaler_desc_single_output(
descr->num_output_stage = 1;
hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
- cas_scaler_out_info->res.width);
+ cas_scaler_out_info->res.width);
ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
- cas_scaler_out_info->res.height);
+ cas_scaler_out_info->res.height);
/* use the same horizontal and vertical downscaling factor for simplicity */
assert(hor_ds_factor == ver_ds_factor);
@@ -6806,31 +6666,36 @@ static int ia_css_pipe_create_cas_scaler_desc_single_output(
i *= max_scale_factor_per_stage;
}
- descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
- GFP_KERNEL);
+ descr->in_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->in_info) {
err = -ENOMEM;
goto ERR;
}
- descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
- struct ia_css_frame_info), GFP_KERNEL);
+ descr->internal_out_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->internal_out_info) {
err = -ENOMEM;
goto ERR;
}
- descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
- GFP_KERNEL);
+ descr->out_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->out_info) {
err = -ENOMEM;
goto ERR;
}
- descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
- GFP_KERNEL);
+ descr->vf_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->vf_info) {
err = -ENOMEM;
goto ERR;
}
- descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
+ descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
+ GFP_KERNEL);
if (!descr->is_output_stage) {
err = -ENOMEM;
goto ERR;
@@ -6874,9 +6739,9 @@ static int ia_css_pipe_create_cas_scaler_desc_single_output(
max_scale_factor_per_stage;
descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
ia_css_frame_info_init(&descr->internal_out_info[i],
- tmp_in_info.res.width / max_scale_factor_per_stage,
- tmp_in_info.res.height / max_scale_factor_per_stage,
- IA_CSS_FRAME_FORMAT_YUV420, 0);
+ tmp_in_info.res.width / max_scale_factor_per_stage,
+ tmp_in_info.res.height / max_scale_factor_per_stage,
+ IA_CSS_FRAME_FORMAT_YUV420, 0);
descr->out_info[i].res.width = 0;
descr->out_info[i].res.height = 0;
descr->vf_info[i].res.width = 0;
@@ -6892,9 +6757,10 @@ ERR:
}
/* FIXME: merge most of this and single output version */
-static int ia_css_pipe_create_cas_scaler_desc(
- struct ia_css_pipe *pipe,
- struct ia_css_cas_binary_descr *descr) {
+static int
+ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
+ struct ia_css_cas_binary_descr *descr)
+{
struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
@@ -6951,30 +6817,35 @@ static int ia_css_pipe_create_cas_scaler_desc(
descr->num_stage = num_stages;
descr->in_info = kmalloc_array(descr->num_stage,
- sizeof(struct ia_css_frame_info), GFP_KERNEL);
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->in_info) {
err = -ENOMEM;
goto ERR;
}
- descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
- struct ia_css_frame_info), GFP_KERNEL);
+ descr->internal_out_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->internal_out_info) {
err = -ENOMEM;
goto ERR;
}
- descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
- GFP_KERNEL);
+ descr->out_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->out_info) {
err = -ENOMEM;
goto ERR;
}
- descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
- GFP_KERNEL);
+ descr->vf_info = kmalloc(descr->num_stage *
+ sizeof(struct ia_css_frame_info),
+ GFP_KERNEL);
if (!descr->vf_info) {
err = -ENOMEM;
goto ERR;
}
- descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
+ descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
+ GFP_KERNEL);
if (!descr->is_output_stage) {
err = -ENOMEM;
goto ERR;
@@ -6984,7 +6855,7 @@ static int ia_css_pipe_create_cas_scaler_desc(
if (out_info[i]) {
if (i > 0) {
assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
- (out_info[i - 1]->res.height >= out_info[i]->res.height));
+ (out_info[i - 1]->res.height >= out_info[i]->res.height));
}
}
}
@@ -7032,9 +6903,9 @@ static int ia_css_pipe_create_cas_scaler_desc(
max_scale_factor_per_stage;
descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
ia_css_frame_info_init(&descr->internal_out_info[i],
- tmp_in_info.res.width / max_scale_factor_per_stage,
- tmp_in_info.res.height / max_scale_factor_per_stage,
- IA_CSS_FRAME_FORMAT_YUV420, 0);
+ tmp_in_info.res.width / max_scale_factor_per_stage,
+ tmp_in_info.res.height / max_scale_factor_per_stage,
+ IA_CSS_FRAME_FORMAT_YUV420, 0);
descr->out_info[i].res.width = 0;
descr->out_info[i].res.height = 0;
descr->vf_info[i].res.width = 0;
@@ -7050,7 +6921,8 @@ ERR:
}
static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
- *descr) {
+ *descr)
+{
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
kfree(descr->in_info);
@@ -7068,7 +6940,8 @@ static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
}
static int
-load_yuvpp_binaries(struct ia_css_pipe *pipe) {
+load_yuvpp_binaries(struct ia_css_pipe *pipe)
+{
int err = 0;
bool need_scaler = false;
struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
@@ -7093,8 +6966,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
mycs = &pipe->pipe_settings.yuvpp;
- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
- {
+ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
if (pipe->vf_output_info[i].res.width != 0) {
err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
&pipe->vf_output_info[i]);
@@ -7108,18 +6980,18 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
/* we build up the pipeline starting at the end */
/* Capture post-processing */
- if (need_scaler)
- {
+ if (need_scaler) {
struct ia_css_binary_descr yuv_scaler_descr;
err = ia_css_pipe_create_cas_scaler_desc(pipe,
- &cas_scaler_descr);
+ &cas_scaler_descr);
if (err)
goto ERR;
mycs->num_output = cas_scaler_descr.num_output_stage;
mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
- sizeof(struct ia_css_binary), GFP_KERNEL);
+ sizeof(struct ia_css_binary),
+ GFP_KERNEL);
if (!mycs->yuv_scaler_binary) {
err = -ENOMEM;
goto ERR;
@@ -7133,28 +7005,25 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
for (i = 0; i < cas_scaler_descr.num_stage; i++) {
mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
ia_css_pipe_get_yuvscaler_binarydesc(pipe,
- &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
- &cas_scaler_descr.out_info[i],
- &cas_scaler_descr.internal_out_info[i],
- &cas_scaler_descr.vf_info[i]);
+ &yuv_scaler_descr,
+ &cas_scaler_descr.in_info[i],
+ &cas_scaler_descr.out_info[i],
+ &cas_scaler_descr.internal_out_info[i],
+ &cas_scaler_descr.vf_info[i]);
err = ia_css_binary_find(&yuv_scaler_descr,
- &mycs->yuv_scaler_binary[i]);
+ &mycs->yuv_scaler_binary[i]);
if (err)
goto ERR;
}
ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
- } else
- {
+ } else {
mycs->num_output = 1;
}
if (need_scaler)
- {
next_binary = &mycs->yuv_scaler_binary[0];
- } else
- {
+ else
next_binary = NULL;
- }
#if defined(ISP2401)
/*
@@ -7180,11 +7049,10 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
need_isp_copy_binary = true;
#endif /* ISP2401 */
- if (need_isp_copy_binary)
- {
+ if (need_isp_copy_binary) {
err = load_copy_binary(pipe,
- &mycs->copy_binary,
- next_binary);
+ &mycs->copy_binary,
+ next_binary);
if (err)
goto ERR;
@@ -7211,8 +7079,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
}
/* Viewfinder post-processing */
- if (need_scaler)
- {
+ if (need_scaler) {
for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
if (mycs->is_output_stage[i]) {
assert(j < 2);
@@ -7222,19 +7089,18 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
}
}
mycs->num_vf_pp = j;
- } else
- {
+ } else {
vf_pp_in_info[0] =
&mycs->copy_binary.vf_frame_info;
- for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
+ for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
vf_pp_in_info[i] = NULL;
- }
+
mycs->num_vf_pp = 1;
}
- mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
- GFP_KERNEL);
- if (!mycs->vf_pp_binary)
- {
+ mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp *
+ sizeof(struct ia_css_binary),
+ GFP_KERNEL);
+ if (!mycs->vf_pp_binary) {
err = -ENOMEM;
goto ERR;
}
@@ -7242,8 +7108,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
{
struct ia_css_binary_descr vf_pp_descr;
- for (i = 0; i < mycs->num_vf_pp; i++)
- {
+ for (i = 0; i < mycs->num_vf_pp; i++) {
if (pipe->vf_output_info[i].res.width != 0) {
ia_css_pipe_get_vfpp_binarydesc(pipe,
&vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
@@ -7259,34 +7124,31 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) {
ERR:
if (need_scaler)
- {
ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
- }
+
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
err);
return err;
}
static int
-unload_yuvpp_binaries(struct ia_css_pipe *pipe) {
+unload_yuvpp_binaries(struct ia_css_pipe *pipe)
+{
unsigned int i;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
- {
+ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
- {
ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
- }
+
for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
- {
ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
- }
+
kfree(pipe->pipe_settings.yuvpp.is_output_stage);
pipe->pipe_settings.yuvpp.is_output_stage = NULL;
kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
@@ -7336,25 +7198,23 @@ static int yuvpp_start(struct ia_css_pipe *pipe)
}
static int
-sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
+sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
+{
int err = 0;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
/* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
- if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
- {
+ if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
IA_CSS_LEAVE_ERR_PRIVATE(0);
return 0;
}
- switch (pipe->mode)
- {
+ switch (pipe->mode) {
case IA_CSS_PIPE_ID_PREVIEW:
err = unload_preview_binaries(pipe);
break;
@@ -7375,7 +7235,8 @@ sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
}
static int
-sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
+sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
+{
int err = 0;
assert(pipe);
@@ -7385,8 +7246,7 @@ sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
return err;
- switch (pipe->mode)
- {
+ switch (pipe->mode) {
case IA_CSS_PIPE_ID_PREVIEW:
err = load_preview_binaries(pipe);
break;
@@ -7405,8 +7265,7 @@ sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
err = -EINVAL;
break;
}
- if (err)
- {
+ if (err) {
if (sh_css_pipe_unload_binaries(pipe)) {
/* currently css does not support multiple error returns in a single function,
* using -EINVAL in this case */
@@ -7417,7 +7276,8 @@ sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
}
static int
-create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
+create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
+{
struct ia_css_pipeline *me;
int err = 0;
struct ia_css_pipeline_stage *vf_pp_stage = NULL,
@@ -7444,15 +7304,13 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
#endif
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
- {
+ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
me = &pipe->pipeline;
ia_css_pipeline_clean(me);
- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
- {
+ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
out_frame[i] = NULL;
vf_frame[i] = NULL;
}
@@ -7480,8 +7338,7 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
/* the input frame can come from:
* a) memory: connect yuvscaler to me->in_frame
* b) sensor, via copy binary: connect yuvscaler to copy binary later on */
- if (need_in_frameinfo_memory)
- {
+ if (need_in_frameinfo_memory) {
/* TODO: improve for different input formats. */
/*
@@ -7530,13 +7387,11 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
}
in_frame = &me->in_frame;
- } else
- {
+ } else {
in_frame = NULL;
}
- for (i = 0; i < num_output_stage; i++)
- {
+ for (i = 0; i < num_output_stage; i++) {
assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
if (pipe->output_info[i].res.width != 0) {
err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
@@ -7563,8 +7418,7 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
need_scaler = need_yuv_scaler_stage(pipe);
- if (pipe->pipe_settings.yuvpp.copy_binary.info)
- {
+ if (pipe->pipe_settings.yuvpp.copy_binary.info) {
struct ia_css_frame *in_frame_local = NULL;
#ifdef ISP2401
@@ -7574,18 +7428,26 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
#endif
if (need_scaler) {
- ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- bin_out_frame, in_frame_local, NULL);
+ ia_css_pipe_util_set_output_frames(bin_out_frame,
+ 0, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ bin_out_frame,
+ in_frame_local,
+ NULL);
} else {
- ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- bin_out_frame, in_frame_local, NULL);
+ ia_css_pipe_util_set_output_frames(bin_out_frame,
+ 0, out_frame[0]);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ bin_out_frame,
+ in_frame_local,
+ NULL);
}
err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &copy_stage);
+ &stage_desc,
+ &copy_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -7602,8 +7464,7 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
}
}
- if (need_scaler)
- {
+ if (need_scaler) {
struct ia_css_frame *tmp_out_frame = NULL;
struct ia_css_frame *tmp_vf_frame = NULL;
struct ia_css_frame *tmp_in_frame = in_frame;
@@ -7618,10 +7479,11 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
tmp_vf_frame = NULL;
}
- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
- NULL,
- &yuv_scaler_binary[i],
- &yuv_scaler_stage);
+ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
+ tmp_out_frame,
+ NULL,
+ &yuv_scaler_binary[i],
+ &yuv_scaler_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -7632,8 +7494,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
in_frame = yuv_scaler_stage->args.out_vf_frame;
- err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
- &vf_pp_stage);
+ err = add_vf_pp_stage(pipe, in_frame,
+ tmp_vf_frame,
+ &vf_pp_binary[j],
+ &vf_pp_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -7643,12 +7507,11 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
j++;
}
}
- } else if (copy_stage)
- {
+ } else if (copy_stage) {
if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
in_frame = copy_stage->args.out_vf_frame;
- err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
- &vf_pp_stage);
+ err = add_vf_pp_stage(pipe, in_frame, vf_frame[0],
+ &vf_pp_binary[0], &vf_pp_stage);
}
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -7656,7 +7519,8 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
}
}
- ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
+ ia_css_pipeline_finalize_stages(&pipe->pipeline,
+ pipe->stream->config.continuous);
IA_CSS_LEAVE_ERR_PRIVATE(0);
@@ -7665,8 +7529,9 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
static int
create_host_copy_pipeline(struct ia_css_pipe *pipe,
- unsigned int max_input_width,
- struct ia_css_frame *out_frame) {
+ unsigned int max_input_width,
+ struct ia_css_frame *out_frame)
+{
struct ia_css_pipeline *me;
int err = 0;
struct ia_css_pipeline_stage_desc stage_desc;
@@ -7683,16 +7548,10 @@ create_host_copy_pipeline(struct ia_css_pipe *pipe,
out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
if (copy_on_sp(pipe) &&
- pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
- {
- ia_css_frame_info_init(
- &out_frame->info,
- JPEG_BYTES,
- 1,
- IA_CSS_FRAME_FORMAT_BINARY_8,
- 0);
- } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW)
- {
+ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
+ ia_css_frame_info_init(&out_frame->info, JPEG_BYTES, 1,
+ IA_CSS_FRAME_FORMAT_BINARY_8, 0);
+ } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) {
out_frame->info.raw_bit_depth =
ia_css_pipe_util_pipe_input_format_bpp(pipe);
}
@@ -7702,12 +7561,12 @@ create_host_copy_pipeline(struct ia_css_pipe *pipe,
pipe->mode = IA_CSS_PIPE_ID_COPY;
ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
- IA_CSS_PIPELINE_RAW_COPY, max_input_width);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- NULL);
+ IA_CSS_PIPELINE_RAW_COPY,
+ max_input_width);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL);
- ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
+ ia_css_pipeline_finalize_stages(&pipe->pipeline,
+ pipe->stream->config.continuous);
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"create_host_copy_pipeline() leave:\n");
@@ -7716,7 +7575,8 @@ create_host_copy_pipeline(struct ia_css_pipe *pipe,
}
static int
-create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
+create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
+{
struct ia_css_pipeline *me = &pipe->pipeline;
int err = 0;
struct ia_css_pipeline_stage_desc stage_desc;
@@ -7745,9 +7605,10 @@ create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
- IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
+ IA_CSS_PIPELINE_ISYS_COPY,
+ max_input_width);
err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc, &out_stage);
+ &stage_desc, &out_stage);
if (err)
return err;
@@ -7760,7 +7621,8 @@ create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
}
static int
-create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
+create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
+{
struct ia_css_pipeline *me;
int err = 0;
enum ia_css_capture_mode mode;
@@ -7798,7 +7660,8 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
IA_CSS_ENTER_PRIVATE("");
assert(pipe);
assert(pipe->stream);
- assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
+ assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
+ pipe->mode == IA_CSS_PIPE_ID_COPY);
me = &pipe->pipeline;
mode = pipe->config.default_capture_config.mode;
@@ -7824,8 +7687,7 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
/* Construct in_frame info (only in case we have dynamic input */
need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
#endif
- if (need_in_frameinfo_memory)
- {
+ if (need_in_frameinfo_memory) {
err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
IA_CSS_FRAME_FORMAT_RAW);
if (err) {
@@ -7834,22 +7696,19 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
}
in_frame = &me->in_frame;
- } else
- {
+ } else {
in_frame = NULL;
}
err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
out_frame = &me->out_frame[0];
/* Construct vf_frame info (only in case we have VF) */
- if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
- {
+ if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
/* These modes don't support viewfinder output */
vf_frame = NULL;
@@ -7857,22 +7716,20 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
vf_frame = &me->vf_frame[0];
}
- } else
- {
+ } else {
vf_frame = NULL;
}
copy_binary = &pipe->pipe_settings.capture.copy_binary;
num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
- if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY))
- {
+ if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
+
for (i = 0; i < num_primary_stage; i++)
- {
primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
- }
+
vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
@@ -7889,43 +7746,51 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
- if (pipe->pipe_settings.capture.copy_binary.info)
- {
+ if (pipe->pipe_settings.capture.copy_binary.info) {
if (raw) {
ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
#if defined(ISP2401)
if (!continuous) {
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- out_frames, in_frame, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ in_frame,
+ NULL);
} else {
in_frame = pipe->stream->last_pipe->continuous_frames[0];
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- out_frames, in_frame, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ in_frame,
+ NULL);
}
#else
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- out_frames, NULL, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ NULL, NULL);
#endif
} else {
- ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
- out_frames, NULL, NULL);
+ ia_css_pipe_util_set_output_frames(out_frames, 0,
+ in_frame);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ NULL, NULL);
}
err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &current_stage);
+ &stage_desc,
+ &current_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- } else if (pipe->stream->config.continuous)
- {
+ } else if (pipe->stream->config.continuous) {
in_frame = pipe->stream->last_pipe->continuous_frames[0];
}
- if (mode == IA_CSS_CAPTURE_MODE_PRIMARY)
- {
+ if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
struct ia_css_frame *local_in_frame = NULL;
struct ia_css_frame *local_out_frame = NULL;
@@ -7953,11 +7818,14 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
* Proper investigation should be done to come up with the clean
* solution.
* */
- ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
- out_frames, local_in_frame, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ primary_binary[i],
+ out_frames,
+ local_in_frame,
+ NULL);
err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &current_stage);
+ &stage_desc,
+ &current_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -7970,22 +7838,21 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
IA_CSS_BINARY_MODE_COPY;
current_stage->args.copy_output = current_stage->args.copy_vf;
} else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
- mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT)
- {
+ mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
- out_frames, in_frame, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc, NULL);
+ out_frames, in_frame, NULL);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ NULL);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
- out_frames, NULL, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc, NULL);
+ out_frames, NULL, NULL);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ NULL);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -7993,28 +7860,31 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
if (need_pp) {
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
- out_frames, NULL, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ post_isp_binary,
+ out_frames,
+ NULL, NULL);
} else {
- ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
- out_frames, NULL, NULL);
+ ia_css_pipe_util_set_output_frames(out_frames, 0,
+ out_frame);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ post_isp_binary,
+ out_frames,
+ NULL, NULL);
}
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc, &current_stage);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ &current_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- } else if (mode == IA_CSS_CAPTURE_MODE_BAYER)
- {
+ } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
- out_frames, in_frame, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- NULL);
+ out_frames, in_frame, NULL);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ NULL);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -8022,49 +7892,48 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
}
#ifndef ISP2401
- if (need_pp && current_stage)
- {
+ if (need_pp && current_stage) {
struct ia_css_frame *local_in_frame = NULL;
local_in_frame = current_stage->args.out_frame[0];
if (need_ldc) {
ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
- ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
- out_frames, local_in_frame, NULL);
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ capture_ldc_binary,
+ out_frames,
+ local_in_frame,
+ NULL);
err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- &current_stage);
+ &stage_desc,
+ &current_stage);
local_in_frame = current_stage->args.out_frame[0];
}
err = add_capture_pp_stage(pipe, me, local_in_frame,
- need_yuv_pp ? NULL : out_frame,
+ need_yuv_pp ? NULL : out_frame,
#else
/* ldc and capture_pp not supported in same pipeline */
- if (need_ldc && current_stage)
- {
+ if (need_ldc && current_stage) {
in_frame = current_stage->args.out_frame[0];
ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
- out_frames, in_frame, NULL);
- err = ia_css_pipeline_create_and_add_stage(me,
- &stage_desc,
- NULL);
- } else if (need_pp && current_stage)
- {
+ out_frames, in_frame, NULL);
+ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
+ NULL);
+ } else if (need_pp && current_stage) {
in_frame = current_stage->args.out_frame[0];
- err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
+ err = add_capture_pp_stage(pipe, me, in_frame,
+ need_yuv_pp ? NULL : out_frame,
#endif
- capture_pp_binary,
- &current_stage);
+ capture_pp_binary,
+ &current_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
}
- if (need_yuv_pp && current_stage)
- {
+ if (need_yuv_pp && current_stage) {
struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
struct ia_css_frame *tmp_out_frame = NULL;
@@ -8074,10 +7943,10 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
else
tmp_out_frame = NULL;
- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
- NULL,
- &yuv_scaler_binary[i],
- &yuv_scaler_stage);
+ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
+ tmp_out_frame, NULL,
+ &yuv_scaler_binary[i],
+ &yuv_scaler_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -8096,11 +7965,12 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
* should not be considered as a clean solution. Proper
* investigation should be done to come up with the clean solution.
* */
- if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame)
- {
+ if (mode != IA_CSS_CAPTURE_MODE_RAW &&
+ mode != IA_CSS_CAPTURE_MODE_BAYER &&
+ current_stage && vf_frame) {
in_frame = current_stage->args.out_vf_frame;
err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
- &current_stage);
+ &current_stage);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -8115,7 +7985,8 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
}
static int
-create_host_capture_pipeline(struct ia_css_pipe *pipe) {
+create_host_capture_pipeline(struct ia_css_pipe *pipe)
+{
int err = 0;
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
@@ -8124,8 +7995,7 @@ create_host_capture_pipeline(struct ia_css_pipe *pipe) {
err = create_host_isyscopy_capture_pipeline(pipe);
else
err = create_host_regular_capture_pipeline(pipe);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
@@ -8135,8 +8005,8 @@ create_host_capture_pipeline(struct ia_css_pipe *pipe) {
return err;
}
-static int capture_start(
- struct ia_css_pipe *pipe) {
+static int capture_start(struct ia_css_pipe *pipe)
+{
struct ia_css_pipeline *me;
int err = 0;
@@ -8151,7 +8021,7 @@ static int capture_start(
me = &pipe->pipeline;
if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
- pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
+ pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
(pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
if (copy_on_sp(pipe)) {
err = start_copy_on_sp(pipe, &me->out_frame[0]);
@@ -8195,7 +8065,7 @@ static int capture_start(
if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
pipe->stream->reconfigure_css_rx) {
ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
- pipe->stream->config.mode);
+ pipe->stream->config.mode);
pipe->stream->reconfigure_css_rx = false;
}
#endif
@@ -8206,8 +8076,9 @@ static int capture_start(
static int
sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
- struct ia_css_frame_info *info,
- unsigned int idx) {
+ struct ia_css_frame_info *info,
+ unsigned int idx)
+{
assert(pipe);
assert(info);
@@ -8216,8 +8087,7 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
*info = pipe->output_info[idx];
if (copy_on_sp(pipe) &&
- pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
- {
+ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
ia_css_frame_info_init(
info,
JPEG_BYTES,
@@ -8225,8 +8095,7 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
IA_CSS_FRAME_FORMAT_BINARY_8,
0);
} else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
- info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
- {
+ info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
info->raw_bit_depth =
ia_css_pipe_util_pipe_input_format_bpp(pipe);
}
@@ -8238,9 +8107,10 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
void
ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
- const unsigned short *data,
- unsigned int width,
- unsigned int height) {
+ const unsigned short *data,
+ unsigned int width,
+ unsigned int height)
+{
assert(stream);
ia_css_inputfifo_send_input_frame(
@@ -8251,7 +8121,8 @@ ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
}
void
-ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
+ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
+{
assert(stream);
ia_css_inputfifo_start_frame(
@@ -8262,21 +8133,23 @@ ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
void
ia_css_stream_send_input_line(const struct ia_css_stream *stream,
- const unsigned short *data,
- unsigned int width,
- const unsigned short *data2,
- unsigned int width2) {
+ const unsigned short *data,
+ unsigned int width,
+ const unsigned short *data2,
+ unsigned int width2)
+{
assert(stream);
ia_css_inputfifo_send_line(stream->config.channel_id,
- data, width, data2, width2);
+ data, width, data2, width2);
}
void
ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
- enum atomisp_input_format format,
- const unsigned short *data,
- unsigned int width) {
+ enum atomisp_input_format format,
+ const unsigned short *data,
+ unsigned int width)
+{
assert(stream);
if (!data || width == 0)
return;
@@ -8285,14 +8158,16 @@ ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
}
void
-ia_css_stream_end_input_frame(const struct ia_css_stream *stream) {
+ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
+{
assert(stream);
ia_css_inputfifo_end_frame(stream->config.channel_id);
}
static void
-append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
+append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
+{
IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
if (!l) {
IA_CSS_ERROR("NULL fw_info");
@@ -8307,7 +8182,8 @@ append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
}
static void
-remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
+remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
+{
assert(*l);
assert(firmware);
(void)l;
@@ -8349,12 +8225,12 @@ static int upload_isp_code(struct ia_css_fw_info *firmware)
}
static int
-acc_load_extension(struct ia_css_fw_info *firmware) {
+acc_load_extension(struct ia_css_fw_info *firmware)
+{
int err;
struct ia_css_fw_info *hd = firmware;
- while (hd)
- {
+ while (hd) {
err = upload_isp_code(hd);
if (err)
return err;
@@ -8368,7 +8244,8 @@ acc_load_extension(struct ia_css_fw_info *firmware) {
}
static void
-acc_unload_extension(struct ia_css_fw_info *firmware) {
+acc_unload_extension(struct ia_css_fw_info *firmware)
+{
struct ia_css_fw_info *hd = firmware;
struct ia_css_fw_info *hdn = NULL;
@@ -8392,13 +8269,13 @@ acc_unload_extension(struct ia_css_fw_info *firmware) {
/* Load firmware for extension */
static int
ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
- struct ia_css_fw_info *firmware) {
+ struct ia_css_fw_info *firmware)
+{
int err = 0;
IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
- if ((!firmware) || (!pipe))
- {
+ if ((!firmware) || (!pipe)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -8416,7 +8293,8 @@ ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
/* Unload firmware for extension */
static void
ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
- struct ia_css_fw_info *firmware) {
+ struct ia_css_fw_info *firmware)
+{
IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
if ((!firmware) || (!pipe)) {
@@ -8435,7 +8313,8 @@ ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
}
bool
-ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
+ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
+{
struct ia_css_pipeline_stage *stage;
assert(me);
@@ -8456,7 +8335,8 @@ ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
static int
sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
- const void *acc_fw) {
+ const void *acc_fw)
+{
struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
/* In QoS case, load_extension already called, so skipping */
int err = 0;
@@ -8468,14 +8348,13 @@ sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
"sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
pipeline, acc_fw);
- if (!err)
- {
+ if (!err) {
struct ia_css_pipeline_stage_desc stage_desc;
ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
err = ia_css_pipeline_create_and_add_stage(pipeline,
- &stage_desc,
- NULL);
+ &stage_desc,
+ NULL);
}
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
@@ -8488,7 +8367,8 @@ sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
* Refer to "sh_css_internal.h" for details.
*/
int ia_css_stream_capture_frame(struct ia_css_stream *stream,
- unsigned int exp_id) {
+ unsigned int exp_id)
+{
struct sh_css_tag_descr tag_descr;
u32 encoded_tag_descr;
int err;
@@ -8526,11 +8406,9 @@ int ia_css_stream_capture_frame(struct ia_css_stream *stream,
* @brief Configure the continuous capture.
* Refer to "sh_css_internal.h" for details.
*/
-int ia_css_stream_capture(
- struct ia_css_stream *stream,
- int num_captures,
- unsigned int skip,
- int offset) {
+int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures,
+ unsigned int skip, int offset)
+{
struct sh_css_tag_descr tag_descr;
unsigned int encoded_tag_descr;
int return_err;
@@ -8593,8 +8471,9 @@ void ia_css_stream_request_flash(struct ia_css_stream *stream)
ia_css_debug_dump_sp_sw_debug_info();
ia_css_debug_dump_debug_info(NULL);
}
- } else
+ } else {
IA_CSS_LOG("SP is not running!");
+ }
#endif
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
@@ -8602,7 +8481,8 @@ void ia_css_stream_request_flash(struct ia_css_stream *stream)
}
static void
-sh_css_init_host_sp_control_vars(void) {
+sh_css_init_host_sp_control_vars(void)
+{
const struct ia_css_fw_info *fw;
unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
@@ -8643,22 +8523,22 @@ sh_css_init_host_sp_control_vars(void) {
(void)HIVE_ADDR_host_sp_com;
sp_dmem_store_uint32(SP0_ID,
- (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
- (uint32_t)(0));
+ (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
+ (uint32_t)(0));
sp_dmem_store_uint32(SP0_ID,
- (unsigned int)sp_address_of(host_sp_queues_initialized),
- (uint32_t)(0));
+ (unsigned int)sp_address_of(host_sp_queues_initialized),
+ (uint32_t)(0));
sp_dmem_store_uint32(SP0_ID,
- (unsigned int)sp_address_of(sp_sleep_mode),
- (uint32_t)(0));
+ (unsigned int)sp_address_of(sp_sleep_mode),
+ (uint32_t)(0));
sp_dmem_store_uint32(SP0_ID,
- (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
- (uint32_t)(false));
+ (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
+ (uint32_t)(false));
#ifndef ISP2401
sp_dmem_store_uint32(SP0_ID,
- (unsigned int)sp_address_of(sp_stop_copy_preview),
- my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
+ (unsigned int)sp_address_of(sp_stop_copy_preview),
+ my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
#endif
store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
@@ -8685,8 +8565,8 @@ void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
}
void
-ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
- *extra_config) {
+ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
+{
if (!extra_config) {
IA_CSS_ERROR("NULL input parameter");
return;
@@ -8716,11 +8596,11 @@ void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
}
static int
-ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
+ia_css_acc_pipe_create(struct ia_css_pipe *pipe)
+{
int err = 0;
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_ERROR("NULL input parameter");
return -EINVAL;
}
@@ -8730,9 +8610,7 @@ ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
pipe->config.acc_num_execs = 1;
if (pipe->config.acc_extension)
- {
err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
- }
return err;
}
@@ -8751,9 +8629,8 @@ int ia_css_pipe_create(const struct ia_css_pipe_config *config,
err = ia_css_pipe_create_extra(config, NULL, pipe);
- if (err == 0) {
+ if (err == 0)
IA_CSS_LOG("pipe created successfully = %p", *pipe);
- }
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -8762,8 +8639,9 @@ int ia_css_pipe_create(const struct ia_css_pipe_config *config,
int
ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
- const struct ia_css_pipe_extra_config *extra_config,
- struct ia_css_pipe **pipe) {
+ const struct ia_css_pipe_extra_config *extra_config,
+ struct ia_css_pipe **pipe)
+{
int err = -EINVAL;
struct ia_css_pipe *internal_pipe = NULL;
unsigned int i;
@@ -8771,14 +8649,12 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
/* do not allow to create more than the maximum limit */
- if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX)
- {
+ if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
return -EINVAL;
}
- if ((!pipe) || (!config))
- {
+ if ((!pipe) || (!config)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -8787,8 +8663,7 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
ia_css_debug_dump_pipe_extra_config(extra_config);
err = create_pipe(config->mode, &internal_pipe, false);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
@@ -8800,8 +8675,7 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
else
ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
- if (config->mode == IA_CSS_PIPE_MODE_ACC)
- {
+ if (config->mode == IA_CSS_PIPE_MODE_ACC) {
/* Temporary hack to migrate acceleration to CSS 2.0.
* In the future the code for all pipe types should be
* unified. */
@@ -8828,15 +8702,13 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
sensor output) or use default decimation factor 1. */
if (internal_pipe->extra_config.enable_raw_binning &&
- internal_pipe->config.bayer_ds_out_res.width)
- {
+ internal_pipe->config.bayer_ds_out_res.width) {
/* fill some code here, if no code is needed, please remove it during integration */
}
/* YUV downscaling */
if ((internal_pipe->config.vf_pp_in_res.width ||
- internal_pipe->config.capt_pp_in_res.width))
- {
+ internal_pipe->config.capt_pp_in_res.width)) {
enum ia_css_frame_format format;
if (internal_pipe->config.vf_pp_in_res.width) {
@@ -8857,8 +8729,7 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
}
}
if (internal_pipe->config.vf_pp_in_res.width &&
- internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
- {
+ internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
ia_css_frame_info_init(
&internal_pipe->vf_yuv_ds_input_info,
internal_pipe->config.vf_pp_in_res.width,
@@ -8866,8 +8737,7 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
}
/* handle bayer downscaling output info */
- if (internal_pipe->config.bayer_ds_out_res.width)
- {
+ if (internal_pipe->config.bayer_ds_out_res.width) {
ia_css_frame_info_init(
&internal_pipe->bds_output_info,
internal_pipe->config.bayer_ds_out_res.width,
@@ -8876,8 +8746,7 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
}
/* handle output info, assume always needed */
- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
- {
+ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
if (internal_pipe->config.output_info[i].res.width) {
err = sh_css_pipe_configure_output(
internal_pipe,
@@ -8913,10 +8782,9 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
}
}
}
- if (internal_pipe->config.acc_extension)
- {
+ if (internal_pipe->config.acc_extension) {
err = ia_css_pipe_load_extension(internal_pipe,
- internal_pipe->config.acc_extension);
+ internal_pipe->config.acc_extension);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
kvfree(internal_pipe);
@@ -8934,18 +8802,16 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
int
ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
- struct ia_css_pipe_info *pipe_info) {
+ struct ia_css_pipe_info *pipe_info)
+{
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_pipe_get_info()\n");
- assert(pipe_info);
- if (!pipe_info)
- {
+ if (!pipe_info) {
ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
"ia_css_pipe_get_info: pipe_info cannot be NULL\n");
return -EINVAL;
}
- if (!pipe || !pipe->stream)
- {
+ if (!pipe || !pipe->stream) {
ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
"ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
return -EINVAL;
@@ -8972,41 +8838,37 @@ bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
int
ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
- int pin_index,
- enum ia_css_frame_format new_format) {
+ int pin_index,
+ enum ia_css_frame_format new_format)
+{
int err = 0;
IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
- if (!pipe)
- {
+ if (!pipe) {
IA_CSS_ERROR("pipe is not set");
err = -EINVAL;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- if (0 != pin_index && 1 != pin_index)
- {
+ if (0 != pin_index && 1 != pin_index) {
IA_CSS_ERROR("pin index is not valid");
err = -EINVAL;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY)
- {
+ if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) {
IA_CSS_ERROR("new format is not valid");
err = -EINVAL;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
- } else
- {
+ } else {
err = ia_css_pipe_check_format(pipe, new_format);
if (!err) {
- if (pin_index == 0) {
+ if (pin_index == 0)
pipe->output_info[0].format = new_format;
- } else {
+ else
pipe->vf_output_info[0].format = new_format;
- }
}
}
IA_CSS_LEAVE_ERR_PRIVATE(err);
@@ -9016,7 +8878,8 @@ ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
#if !defined(ISP2401)
/* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
static int
-ia_css_stream_configure_rx(struct ia_css_stream *stream) {
+ia_css_stream_configure_rx(struct ia_css_stream *stream)
+{
struct ia_css_input_port *config;
assert(stream);
@@ -9045,11 +8908,10 @@ ia_css_stream_configure_rx(struct ia_css_stream *stream) {
if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
else
- {
/* not implemented yet, requires extension of the rx_cfg_t
* struct */
return -EINVAL;
- }
+
stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
stream->reconfigure_css_rx = true;
return 0;
@@ -9057,10 +8919,9 @@ ia_css_stream_configure_rx(struct ia_css_stream *stream) {
#endif
static struct ia_css_pipe *
-find_pipe(struct ia_css_pipe *pipes[],
- unsigned int num_pipes,
- enum ia_css_pipe_mode mode,
- bool copy_pipe) {
+find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes,
+ enum ia_css_pipe_mode mode, bool copy_pipe)
+{
unsigned int i;
assert(pipes);
@@ -9076,24 +8937,21 @@ find_pipe(struct ia_css_pipe *pipes[],
}
static int
-ia_css_acc_stream_create(struct ia_css_stream *stream) {
+ia_css_acc_stream_create(struct ia_css_stream *stream)
+{
int i;
int err = 0;
- assert(stream);
IA_CSS_ENTER_PRIVATE("stream = %p", stream);
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
- for (i = 0; i < stream->num_pipes; i++)
- {
+ for (i = 0; i < stream->num_pipes; i++) {
struct ia_css_pipe *pipe = stream->pipes[i];
- assert(pipe);
if (!pipe) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
@@ -9104,14 +8962,12 @@ ia_css_acc_stream_create(struct ia_css_stream *stream) {
/* Map SP threads before doing anything. */
err = map_sp_threads(stream, true);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- for (i = 0; i < stream->num_pipes; i++)
- {
+ for (i = 0; i < stream->num_pipes; i++) {
struct ia_css_pipe *pipe = stream->pipes[i];
assert(pipe);
@@ -9119,8 +8975,7 @@ ia_css_acc_stream_create(struct ia_css_stream *stream) {
}
err = create_host_pipeline_structure(stream);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
@@ -9134,7 +8989,8 @@ ia_css_acc_stream_create(struct ia_css_stream *stream) {
static int
metadata_info_init(const struct ia_css_metadata_config *mdc,
- struct ia_css_metadata_info *md) {
+ struct ia_css_metadata_info *md)
+{
/* Either both width and height should be set or neither */
if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
return -EINVAL;
@@ -9161,7 +9017,7 @@ static int check_pipe_resolutions(const struct ia_css_pipe *pipe)
}
if (ia_css_util_check_res(pipe->config.input_effective_res.width,
- pipe->config.input_effective_res.height) != 0) {
+ pipe->config.input_effective_res.height) != 0) {
IA_CSS_ERROR("effective resolution not supported");
err = -EINVAL;
goto EXIT;
@@ -9169,7 +9025,7 @@ static int check_pipe_resolutions(const struct ia_css_pipe *pipe)
if (!ia_css_util_resolution_is_zero(
pipe->stream->config.input_config.input_res)) {
if (!ia_css_util_res_leq(pipe->config.input_effective_res,
- pipe->stream->config.input_config.input_res)) {
+ pipe->stream->config.input_config.input_res)) {
IA_CSS_ERROR("effective resolution is larger than input resolution");
err = -EINVAL;
goto EXIT;
@@ -9192,9 +9048,10 @@ EXIT:
int
ia_css_stream_create(const struct ia_css_stream_config *stream_config,
- int num_pipes,
- struct ia_css_pipe *pipes[],
- struct ia_css_stream **stream) {
+ int num_pipes,
+ struct ia_css_pipe *pipes[],
+ struct ia_css_stream **stream)
+{
struct ia_css_pipe *curr_pipe;
struct ia_css_stream *curr_stream = NULL;
bool spcopyonly;
@@ -9213,8 +9070,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* some checks */
if (num_pipes == 0 ||
!stream ||
- !pipes)
- {
+ !pipes) {
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
return err;
@@ -9223,8 +9079,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
#if !defined(ISP2401)
/* We don't support metadata for JPEG stream, since they both use str2mem */
if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
- stream_config->metadata_config.resolution.height > 0)
- {
+ stream_config->metadata_config.resolution.height > 0) {
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
return err;
@@ -9232,8 +9087,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
#endif
#ifdef ISP2401
- if (stream_config->online && stream_config->pack_raw_pixels)
- {
+ if (stream_config->online && stream_config->pack_raw_pixels) {
IA_CSS_LOG("online and pack raw is invalid on input system 2401");
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
@@ -9288,16 +9142,14 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* Currently we only supported metadata up to a certain size. */
err = metadata_info_init(&stream_config->metadata_config, &md_info);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
/* allocate the stream instance */
curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
- if (!curr_stream)
- {
+ if (!curr_stream) {
err = -ENOMEM;
IA_CSS_LEAVE_ERR(err);
return err;
@@ -9308,8 +9160,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* allocate pipes */
curr_stream->num_pipes = num_pipes;
curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
- if (!curr_stream->pipes)
- {
+ if (!curr_stream->pipes) {
curr_stream->num_pipes = 0;
kfree(curr_stream);
curr_stream = NULL;
@@ -9332,8 +9183,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
#endif
#ifdef ISP2401
- if (curr_stream->config.online)
- {
+ if (curr_stream->config.online) {
curr_stream->config.source.port.num_lanes =
stream_config->source.port.num_lanes;
curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
@@ -9351,8 +9201,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
curr_stream->config.lock_all);
/* copy mode specific stuff */
- switch (curr_stream->config.mode)
- {
+ switch (curr_stream->config.mode) {
case IA_CSS_INPUT_MODE_SENSOR:
case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
#if !defined(ISP2401)
@@ -9362,11 +9211,11 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
case IA_CSS_INPUT_MODE_TPG:
#if !defined(ISP2401)
IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
- curr_stream->config.source.tpg.x_mask,
- curr_stream->config.source.tpg.y_mask,
- curr_stream->config.source.tpg.x_delta,
- curr_stream->config.source.tpg.y_delta,
- curr_stream->config.source.tpg.xy_mask);
+ curr_stream->config.source.tpg.x_mask,
+ curr_stream->config.source.tpg.y_mask,
+ curr_stream->config.source.tpg.x_delta,
+ curr_stream->config.source.tpg.y_delta,
+ curr_stream->config.source.tpg.xy_mask);
sh_css_sp_configure_tpg(
curr_stream->config.source.tpg.x_mask,
@@ -9391,17 +9240,14 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
}
#ifdef ISP2401
- err = aspect_ratio_crop_init(curr_stream,
- pipes,
- &aspect_ratio_crop_enabled);
- if (err)
- {
+ err = aspect_ratio_crop_init(curr_stream, pipes,
+ &aspect_ratio_crop_enabled);
+ if (err) {
IA_CSS_LEAVE_ERR(err);
goto ERR;
}
#endif
- for (i = 0; i < num_pipes; i++)
- {
+ for (i = 0; i < num_pipes; i++) {
struct ia_css_resolution effective_res;
curr_pipe = pipes[i];
@@ -9432,8 +9278,8 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
curr_pipe->config.input_effective_res = effective_res;
}
IA_CSS_LOG("effective_res=%dx%d",
- effective_res.width,
- effective_res.height);
+ effective_res.width,
+ effective_res.height);
}
if (IS_ISP2401) {
@@ -9441,9 +9287,8 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
err = check_pipe_resolutions(pipes[i]);
- if (err) {
+ if (err)
goto ERR;
- }
}
}
}
@@ -9453,32 +9298,28 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
goto ERR;
IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
- if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC)
- {
+ if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) {
*stream = curr_stream;
err = ia_css_acc_stream_create(curr_stream);
goto ERR;
}
/* sensor binning */
- if (!spcopyonly)
- {
+ if (!spcopyonly) {
sensor_binning_changed =
sh_css_params_set_binning_factor(curr_stream,
- curr_stream->config.sensor_binning_factor);
- } else
- {
+ curr_stream->config.sensor_binning_factor);
+ } else {
sensor_binning_changed = false;
}
IA_CSS_LOG("sensor_binning=%d, changed=%d",
- curr_stream->config.sensor_binning_factor, sensor_binning_changed);
+ curr_stream->config.sensor_binning_factor, sensor_binning_changed);
/* loop over pipes */
IA_CSS_LOG("num_pipes=%d", num_pipes);
curr_stream->cont_capt = false;
/* Temporary hack: we give the preview pipe a reference to the capture
* pipe in continuous capture mode. */
- if (curr_stream->config.continuous)
- {
+ if (curr_stream->config.continuous) {
/* Search for the preview pipe and create the copy pipe */
struct ia_css_pipe *preview_pipe;
struct ia_css_pipe *video_pipe;
@@ -9496,17 +9337,18 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* Create copy pipe here, since it may not be exposed to the driver */
preview_pipe = find_pipe(pipes, num_pipes,
- IA_CSS_PIPE_MODE_PREVIEW, false);
+ IA_CSS_PIPE_MODE_PREVIEW, false);
video_pipe = find_pipe(pipes, num_pipes,
- IA_CSS_PIPE_MODE_VIDEO, false);
- acc_pipe = find_pipe(pipes, num_pipes,
- IA_CSS_PIPE_MODE_ACC, false);
+ IA_CSS_PIPE_MODE_VIDEO, false);
+ acc_pipe = find_pipe(pipes, num_pipes, IA_CSS_PIPE_MODE_ACC,
+ false);
if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt)
curr_stream->cont_capt =
false; /* preview + QoS case will not need cont_capt switch */
if (curr_stream->cont_capt) {
capture_pipe = find_pipe(pipes, num_pipes,
- IA_CSS_PIPE_MODE_CAPTURE, false);
+ IA_CSS_PIPE_MODE_CAPTURE,
+ false);
if (!capture_pipe) {
err = -EINVAL;
goto ERR;
@@ -9526,9 +9368,9 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
copy_pipe->stream = curr_stream;
}
- if (preview_pipe && curr_stream->cont_capt) {
+ if (preview_pipe && curr_stream->cont_capt)
preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
- }
+
if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, &copy_pipe, true);
if (err)
@@ -9537,15 +9379,13 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
copy_pipe->stream = curr_stream;
}
- if (video_pipe && curr_stream->cont_capt) {
+ if (video_pipe && curr_stream->cont_capt)
video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
- }
- if (preview_pipe && acc_pipe) {
+
+ if (preview_pipe && acc_pipe)
preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
- }
}
- for (i = 0; i < num_pipes; i++)
- {
+ for (i = 0; i < num_pipes; i++) {
curr_pipe = pipes[i];
/* set current stream */
curr_pipe->stream = curr_stream;
@@ -9566,8 +9406,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
}
/* now pipes have been configured, info should be available */
- for (i = 0; i < num_pipes; i++)
- {
+ for (i = 0; i < num_pipes; i++) {
struct ia_css_pipe_info *pipe_info = NULL;
curr_pipe = pipes[i];
@@ -9591,10 +9430,12 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
if (!spcopyonly) {
if (!IS_ISP2401)
err = sh_css_pipe_get_shading_info(curr_pipe,
- &pipe_info->shading_info, NULL);
+ &pipe_info->shading_info,
+ NULL);
else
err = sh_css_pipe_get_shading_info(curr_pipe,
- &pipe_info->shading_info, &curr_pipe->config);
+ &pipe_info->shading_info,
+ &curr_pipe->config);
if (err)
goto ERR;
@@ -9604,7 +9445,8 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
goto ERR;
for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
- &pipe_info->vf_output_info[j], j);
+ &pipe_info->vf_output_info[j],
+ j);
if (err)
goto ERR;
}
@@ -9617,22 +9459,19 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* Map SP threads before doing anything. */
err = map_sp_threads(curr_stream, true);
- if (err)
- {
+ if (err) {
IA_CSS_LOG("map_sp_threads: return_err=%d", err);
goto ERR;
}
- for (i = 0; i < num_pipes; i++)
- {
+ for (i = 0; i < num_pipes; i++) {
curr_pipe = pipes[i];
ia_css_pipe_map_queue(curr_pipe, true);
}
/* Create host side pipeline objects without stages */
err = create_host_pipeline_structure(curr_stream);
- if (err)
- {
+ if (err) {
IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
goto ERR;
}
@@ -9670,13 +9509,13 @@ ERR:
}
int
-ia_css_stream_destroy(struct ia_css_stream *stream) {
+ia_css_stream_destroy(struct ia_css_stream *stream)
+{
int i;
int err = 0;
IA_CSS_ENTER_PRIVATE("stream = %p", stream);
- if (!stream)
- {
+ if (!stream) {
err = -EINVAL;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
@@ -9685,8 +9524,7 @@ ia_css_stream_destroy(struct ia_css_stream *stream) {
ia_css_stream_isp_parameters_uninit(stream);
if ((stream->last_pipe) &&
- ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num))
- {
+ ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
#if defined(ISP2401)
bool free_mpi;
@@ -9748,8 +9586,7 @@ ia_css_stream_destroy(struct ia_css_stream *stream) {
}
/* remove references from pipes to stream */
- for (i = 0; i < stream->num_pipes; i++)
- {
+ for (i = 0; i < stream->num_pipes; i++) {
struct ia_css_pipe *entry = stream->pipes[i];
assert(entry);
@@ -9778,8 +9615,7 @@ ia_css_stream_destroy(struct ia_css_stream *stream) {
/* working mode: take out of the seed list */
if (my_css_save.mode == sh_css_mode_working) {
for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
- if (my_css_save.stream_seeds[i].stream == stream)
- {
+ if (my_css_save.stream_seeds[i].stream == stream) {
IA_CSS_LOG("took out stream %d", i);
my_css_save.stream_seeds[i].stream = NULL;
break;
@@ -9795,7 +9631,8 @@ ia_css_stream_destroy(struct ia_css_stream *stream) {
int
ia_css_stream_get_info(const struct ia_css_stream *stream,
- struct ia_css_stream_info *stream_info) {
+ struct ia_css_stream_info *stream_info)
+{
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
assert(stream);
assert(stream_info);
@@ -9811,59 +9648,58 @@ ia_css_stream_get_info(const struct ia_css_stream *stream,
* The stream handle is used to identify the correct entry in the css_save struct
*/
int
-ia_css_stream_load(struct ia_css_stream *stream) {
- if (!IS_ISP2401) {
- int i;
- int err;
-
- assert(stream);
- ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
- for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
- {
- if (my_css_save.stream_seeds[i].stream == stream) {
- int j;
-
- for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
- if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
- &my_css_save.stream_seeds[i].pipes[j])) != 0) {
- if (j) {
- int k;
+ia_css_stream_load(struct ia_css_stream *stream)
+{
+ int i, j, err;
- for (k = 0; k < j; k++)
- ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
- }
- return err;
- }
- }
- err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
- my_css_save.stream_seeds[i].num_pipes,
- my_css_save.stream_seeds[i].pipes,
- &my_css_save.stream_seeds[i].stream);
- if (err) {
- ia_css_stream_destroy(stream);
- for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
- ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
- return err;
- }
- break;
- }
- }
- ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
- return 0;
- } else {
+ if (IS_ISP2401) {
/* TODO remove function - DEPRECATED */
(void)stream;
return -ENOTSUPP;
}
+
+ assert(stream);
+ ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
+ for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
+ if (my_css_save.stream_seeds[i].stream != stream)
+ continue;
+
+ for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
+ int k;
+
+ err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
+ &my_css_save.stream_seeds[i].pipes[j]);
+ if (!err)
+ continue;
+
+ for (k = 0; k < j; k++)
+ ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
+ return err;
+ }
+ err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
+ my_css_save.stream_seeds[i].num_pipes,
+ my_css_save.stream_seeds[i].pipes,
+ &my_css_save.stream_seeds[i].stream);
+ if (!err)
+ break;
+
+ ia_css_stream_destroy(stream);
+ for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
+ ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
+ return err;
+ }
+
+ ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
+ return 0;
}
int
-ia_css_stream_start(struct ia_css_stream *stream) {
+ia_css_stream_start(struct ia_css_stream *stream)
+{
int err = 0;
IA_CSS_ENTER("stream = %p", stream);
- if ((!stream) || (!stream->last_pipe))
- {
+ if ((!stream) || (!stream->last_pipe)) {
IA_CSS_LEAVE_ERR(-EINVAL);
return -EINVAL;
}
@@ -9873,8 +9709,7 @@ ia_css_stream_start(struct ia_css_stream *stream) {
/* Create host side pipeline. */
err = create_host_pipeline(stream);
- if (err)
- {
+ if (err) {
IA_CSS_LEAVE_ERR(err);
return err;
}
@@ -9887,8 +9722,7 @@ ia_css_stream_start(struct ia_css_stream *stream) {
#if !defined(ISP2401)
/* Initialize mipi size checks */
- if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
- {
+ if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
unsigned int idx;
unsigned int port = (unsigned int)(stream->config.source.port.port);
@@ -9899,8 +9733,7 @@ ia_css_stream_start(struct ia_css_stream *stream) {
}
#endif
- if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)
- {
+ if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
err = sh_css_config_input_network(stream);
if (err)
return err;
@@ -9912,7 +9745,8 @@ ia_css_stream_start(struct ia_css_stream *stream) {
}
int
-ia_css_stream_stop(struct ia_css_stream *stream) {
+ia_css_stream_stop(struct ia_css_stream *stream)
+{
int err = 0;
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
@@ -9923,22 +9757,19 @@ ia_css_stream_stop(struct ia_css_stream *stream) {
#if !defined(ISP2401)
/* De-initialize mipi size checks */
- if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
- {
+ if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
unsigned int idx;
unsigned int port = (unsigned int)(stream->config.source.port.port);
- for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
+ for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++)
sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
- }
}
#endif
- if (!IS_ISP2401) {
+ if (!IS_ISP2401)
err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
- } else {
+ else
err = sh_css_pipes_stop(stream);
- }
if (err)
return err;
@@ -9951,16 +9782,16 @@ ia_css_stream_stop(struct ia_css_stream *stream) {
}
bool
-ia_css_stream_has_stopped(struct ia_css_stream *stream) {
+ia_css_stream_has_stopped(struct ia_css_stream *stream)
+{
bool stopped;
assert(stream);
- if (!IS_ISP2401) {
+ if (!IS_ISP2401)
stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
- } else {
+ else
stopped = sh_css_pipes_have_stopped(stream);
- }
return stopped;
}
@@ -9971,7 +9802,8 @@ ia_css_stream_has_stopped(struct ia_css_stream *stream) {
* The stream handle is used to identify the correct entry in the css_save struct
*/
int
-ia_css_stream_unload(struct ia_css_stream *stream) {
+ia_css_stream_unload(struct ia_css_stream *stream)
+{
int i;
assert(stream);
@@ -9979,8 +9811,7 @@ ia_css_stream_unload(struct ia_css_stream *stream) {
/* some checks */
assert(stream);
for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
- if (my_css_save.stream_seeds[i].stream == stream)
- {
+ if (my_css_save.stream_seeds[i].stream == stream) {
int j;
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
@@ -10000,7 +9831,8 @@ ia_css_stream_unload(struct ia_css_stream *stream) {
int
ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
- enum ia_css_pipe_id *pipe_id) {
+ enum ia_css_pipe_id *pipe_id)
+{
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
if (pipe)
*pipe_id = pipe->mode;
@@ -10011,18 +9843,21 @@ ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
}
enum atomisp_input_format
-ia_css_stream_get_format(const struct ia_css_stream *stream) {
+ia_css_stream_get_format(const struct ia_css_stream *stream)
+{
return stream->config.input_config.format;
}
bool
-ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) {
+ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
+{
return (stream->config.pixels_per_clock == 2);
}
struct ia_css_binary *
ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
- *stream) {
+ *stream)
+{
struct ia_css_pipe *pipe;
assert(stream);
@@ -10040,7 +9875,8 @@ ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
}
struct ia_css_binary *
-ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
+ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
+{
int i;
struct ia_css_pipe *video_pipe = NULL;
@@ -10059,7 +9895,8 @@ ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
}
struct ia_css_binary *
-ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
+ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
+{
struct ia_css_pipe *pipe;
struct ia_css_binary *s3a_binary = NULL;
@@ -10081,7 +9918,8 @@ ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
int
ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
- unsigned int output_padded_width) {
+ unsigned int output_padded_width)
+{
struct ia_css_pipe *pipe;
assert(stream);
@@ -10098,7 +9936,8 @@ ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
}
static struct ia_css_binary *
-ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
+{
struct ia_css_binary *binary = NULL;
assert(pipe);
@@ -10143,7 +9982,8 @@ ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
}
static struct ia_css_binary *
-ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
+{
struct ia_css_binary *binary = NULL;
assert(pipe);
@@ -10166,9 +10006,9 @@ ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
}
}
} else if (pipe->config.default_capture_config.mode ==
- IA_CSS_CAPTURE_MODE_BAYER)
+ IA_CSS_CAPTURE_MODE_BAYER) {
binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
- else if (pipe->config.default_capture_config.mode ==
+ } else if (pipe->config.default_capture_config.mode ==
IA_CSS_CAPTURE_MODE_ADVANCED ||
pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
@@ -10190,7 +10030,8 @@ ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
}
static struct ia_css_binary *
-ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
+{
struct ia_css_binary *binary = NULL;
assert(pipe);
@@ -10210,14 +10051,16 @@ ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
}
struct ia_css_pipeline *
-ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
+{
assert(pipe);
return (struct ia_css_pipeline *)&pipe->pipeline;
}
unsigned int
-ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
+{
assert(pipe);
/* KW was not sure this function was not returning a value
@@ -10234,7 +10077,8 @@ ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
}
unsigned int
-ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
+ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
+{
assert(pipe);
return (unsigned int)pipe->config.isp_pipe_version;
@@ -10243,7 +10087,8 @@ ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
#define SP_START_TIMEOUT_US 30000000
int
-ia_css_start_sp(void) {
+ia_css_start_sp(void)
+{
unsigned long timeout;
int err = 0;
@@ -10252,13 +10097,11 @@ ia_css_start_sp(void) {
/* waiting for the SP is completely started */
timeout = SP_START_TIMEOUT_US;
- while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout)
- {
+ while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
timeout--;
udelay(1);
}
- if (timeout == 0)
- {
+ if (timeout == 0) {
IA_CSS_ERROR("timeout during SP initialization");
return -EINVAL;
}
@@ -10286,14 +10129,14 @@ ia_css_start_sp(void) {
#define SP_SHUTDOWN_TIMEOUT_US 200000
int
-ia_css_stop_sp(void) {
+ia_css_stop_sp(void)
+{
unsigned long timeout;
int err = 0;
IA_CSS_ENTER("void");
- if (!sh_css_sp_is_running())
- {
+ if (!sh_css_sp_is_running()) {
err = -EINVAL;
IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
@@ -10305,8 +10148,7 @@ ia_css_stop_sp(void) {
if (!IS_ISP2401) {
sh_css_write_host2sp_command(host2sp_cmd_terminate);
} else {
- if (!sh_css_write_host2sp_command(host2sp_cmd_terminate))
- {
+ if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
ia_css_debug_dump_sp_sw_debug_info();
ia_css_debug_dump_debug_info(NULL);
@@ -10316,27 +10158,23 @@ ia_css_stop_sp(void) {
sh_css_sp_set_sp_running(false);
timeout = SP_SHUTDOWN_TIMEOUT_US;
- while (!ia_css_spctrl_is_idle(SP0_ID) && timeout)
- {
+ while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
timeout--;
udelay(1);
}
if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
IA_CSS_WARNING("SP has not terminated (SW)");
- if (timeout == 0)
- {
+ if (timeout == 0) {
IA_CSS_WARNING("SP is not idle");
ia_css_debug_dump_sp_sw_debug_info();
}
timeout = SP_SHUTDOWN_TIMEOUT_US;
- while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout)
- {
+ while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
timeout--;
udelay(1);
}
- if (timeout == 0)
- {
+ if (timeout == 0) {
IA_CSS_WARNING("ISP is not idle");
ia_css_debug_dump_sp_sw_debug_info();
}
@@ -10351,7 +10189,8 @@ ia_css_stop_sp(void) {
}
int
-ia_css_update_continuous_frames(struct ia_css_stream *stream) {
+ia_css_update_continuous_frames(struct ia_css_stream *stream)
+{
struct ia_css_pipe *pipe;
unsigned int i;
@@ -10359,8 +10198,7 @@ ia_css_update_continuous_frames(struct ia_css_stream *stream) {
IA_CSS_DEBUG_TRACE,
"sh_css_update_continuous_frames() enter:\n");
- if (!stream)
- {
+ if (!stream) {
ia_css_debug_dtrace(
IA_CSS_DEBUG_TRACE,
"sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
@@ -10371,10 +10209,9 @@ ia_css_update_continuous_frames(struct ia_css_stream *stream) {
for (i = stream->config.init_num_cont_raw_buf;
i < stream->config.target_num_cont_raw_buf; i++)
- {
sh_css_update_host2sp_offline_frame(i,
pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
- }
+
sh_css_update_host2sp_cont_num_raw_frames
(stream->config.target_num_cont_raw_buf, true);
ia_css_debug_dtrace(
@@ -10500,7 +10337,8 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
#if CONFIG_ON_FRAME_ENQUEUE()
static int set_config_on_frame_enqueue(struct ia_css_frame_info
- *info, struct frame_data_wrapper *frame) {
+ *info, struct frame_data_wrapper *frame)
+{
frame->config_on_frame_enqueue.padded_width = 0;
/* currently we support configuration on frame enqueue only on YUV formats */
@@ -10508,11 +10346,11 @@ static int set_config_on_frame_enqueue(struct ia_css_frame_info
switch (info->format) {
case IA_CSS_FRAME_FORMAT_YUV420:
case IA_CSS_FRAME_FORMAT_NV12:
- if (info->padded_width > info->res.width) {
+ if (info->padded_width > info->res.width)
frame->config_on_frame_enqueue.padded_width = info->padded_width;
- } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) {
+ else if ((info->padded_width < info->res.width) && (info->padded_width > 0))
return -EINVAL;
- }
+
/* nothing to do if width == padded width or padded width is zeroed (the same) */
break;
default:
@@ -10524,22 +10362,21 @@ static int set_config_on_frame_enqueue(struct ia_css_frame_info
#endif
int
-ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
+ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
+{
int ret;
IA_CSS_ENTER("");
/* Only continuous streams have a tagger to which we can send the
* unlock message. */
- if (!stream || !stream->config.continuous)
- {
+ if (!stream || !stream->config.continuous) {
IA_CSS_ERROR("invalid stream pointer");
return -EINVAL;
}
if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
- exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID)
- {
+ exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
return -EINVAL;
}
@@ -10558,7 +10395,8 @@ ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
*/
int
ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
- bool enable) {
+ bool enable)
+{
unsigned int thread_id;
struct ia_css_pipeline_stage *stage;
int err = 0;
@@ -10566,20 +10404,16 @@ ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
IA_CSS_ENTER("");
/* Parameter Check */
- if (!pipe || !pipe->stream)
- {
+ if (!pipe || !pipe->stream) {
IA_CSS_ERROR("Invalid Pipe.");
err = -EINVAL;
- } else if (!(pipe->config.acc_extension))
- {
+ } else if (!(pipe->config.acc_extension)) {
IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
err = -EINVAL;
- } else if (!sh_css_sp_is_running())
- {
+ } else if (!sh_css_sp_is_running()) {
IA_CSS_ERROR("Leaving: queue unavailable.");
err = -EBUSY;
- } else
- {
+ } else {
/* Query the threadid and stage_num for the Extension firmware*/
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
@@ -10607,7 +10441,8 @@ ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
*/
int
ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
- bool *enable) {
+ bool *enable)
+{
struct ia_css_pipeline_stage *stage;
unsigned int thread_id;
int err = 0;
@@ -10615,20 +10450,16 @@ ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
IA_CSS_ENTER("");
/* Parameter Check */
- if (!pipe || !pipe->stream)
- {
+ if (!pipe || !pipe->stream) {
IA_CSS_ERROR("Invalid Pipe.");
err = -EINVAL;
- } else if (!(pipe->config.acc_extension))
- {
+ } else if (!(pipe->config.acc_extension)) {
IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
err = -EINVAL;
- } else if (!sh_css_sp_is_running())
- {
+ } else if (!sh_css_sp_is_running()) {
IA_CSS_ERROR("Leaving: queue unavailable.");
err = -EBUSY;
- } else
- {
+ } else {
/* Query the threadid and stage_num corresponding to the Extension firmware*/
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
@@ -10646,9 +10477,10 @@ ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
/* ISP2401 */
int
ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
- u32 fw_handle,
- struct ia_css_isp_param_css_segments *css_seg,
- struct ia_css_isp_param_isp_segments *isp_seg) {
+ u32 fw_handle,
+ struct ia_css_isp_param_css_segments *css_seg,
+ struct ia_css_isp_param_isp_segments *isp_seg)
+{
unsigned int HIVE_ADDR_sp_group;
static struct sh_css_sp_group sp_group;
static struct sh_css_sp_stage sp_stage;
@@ -10666,27 +10498,23 @@ ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
fw = &sh_css_sp_fw;
/* Parameter Check */
- if (!pipe || !pipe->stream)
- {
+ if (!pipe || !pipe->stream) {
IA_CSS_ERROR("Invalid Pipe.");
err = -EINVAL;
- } else if (!(pipe->config.acc_extension))
- {
+ } else if (!(pipe->config.acc_extension)) {
IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
err = -EINVAL;
- } else if (!sh_css_sp_is_running())
- {
+ } else if (!sh_css_sp_is_running()) {
IA_CSS_ERROR("Leaving: queue unavailable.");
err = -EBUSY;
- } else
- {
+ } else {
/* Query the thread_id and stage_num corresponding to the Extension firmware */
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
if (!err) {
/* Get the Extension State */
enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
- stage->stage_num)) ? true : false;
+ stage->stage_num)) ? true : false;
/* Update mapped arg only when extension stage is not enabled */
if (enabled) {
IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
@@ -10696,13 +10524,14 @@ ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
HIVE_ADDR_sp_group = fw->info.sp.group;
sp_dmem_load(SP0_ID,
- (unsigned int)sp_address_of(sp_group),
- &sp_group, sizeof(struct sh_css_sp_group));
+ (unsigned int)sp_address_of(sp_group),
+ &sp_group,
+ sizeof(struct sh_css_sp_group));
hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
- &sp_stage, sizeof(struct sh_css_sp_stage));
+ &sp_stage, sizeof(struct sh_css_sp_stage));
hmm_load(sp_stage.isp_stage_addr,
- &isp_stage, sizeof(struct sh_css_isp_stage));
+ &isp_stage, sizeof(struct sh_css_isp_stage));
for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
@@ -10718,7 +10547,8 @@ ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
}
hmm_store(sp_stage.isp_stage_addr,
- &isp_stage, sizeof(struct sh_css_isp_stage));
+ &isp_stage,
+ sizeof(struct sh_css_isp_stage));
}
}
}
@@ -10729,8 +10559,9 @@ ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
#ifdef ISP2401
static int
aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
- struct ia_css_pipe *pipes[],
- bool *do_crop_status) {
+ struct ia_css_pipe *pipes[],
+ bool *do_crop_status)
+{
int err = 0;
int i;
struct ia_css_pipe *curr_pipe;
@@ -10739,15 +10570,13 @@ aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
if ((!curr_stream) ||
(curr_stream->num_pipes == 0) ||
(!pipes) ||
- (!do_crop_status))
- {
+ (!do_crop_status)) {
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
return err;
}
- for (i = 0; i < curr_stream->num_pipes; i++)
- {
+ for (i = 0; i < curr_stream->num_pipes; i++) {
curr_pipe = pipes[i];
pipe_mask |= (1 << curr_pipe->config.mode);
}
@@ -10761,7 +10590,8 @@ aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
}
static bool
-aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
+aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe)
+{
bool status = false;
if ((curr_pipe) && enabled) {
@@ -10776,7 +10606,8 @@ aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
static int
aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
- struct ia_css_resolution *effective_res) {
+ struct ia_css_resolution *effective_res)
+{
int err = 0;
struct ia_css_resolution crop_res;
struct ia_css_resolution *in_res = NULL;
@@ -10786,8 +10617,7 @@ aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
bool use_capt_pp_in_res = false;
if ((!curr_pipe) ||
- (!effective_res))
- {
+ (!effective_res)) {
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
return err;
@@ -10795,8 +10625,7 @@ aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
(curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
- (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE))
- {
+ (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) {
err = -EINVAL;
IA_CSS_LEAVE_ERR(err);
return err;
@@ -10817,8 +10646,7 @@ aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
in_res = &curr_pipe->stream->config.input_config.effective_res;
out_res = &curr_pipe->output_info[0].res;
- switch (curr_pipe->config.mode)
- {
+ switch (curr_pipe->config.mode) {
case IA_CSS_PIPE_MODE_PREVIEW:
if (use_bds_output_info)
out_res = &curr_pipe->bds_output_info.res;
@@ -10838,27 +10666,26 @@ aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
case IA_CSS_PIPE_MODE_YUVPP:
default:
IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
- curr_pipe->config.mode);
+ curr_pipe->config.mode);
assert(0);
break;
}
err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
if (!err)
- {
*effective_res = crop_res;
- } else
- {
+ else
/* in case of error fallback to default
* effective resolution from driver. */
IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
- }
+
return err;
}
#endif
static void
-sh_css_hmm_buffer_record_init(void) {
+sh_css_hmm_buffer_record_init(void)
+{
int i;
for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
@@ -10866,7 +10693,8 @@ sh_css_hmm_buffer_record_init(void) {
}
static void
-sh_css_hmm_buffer_record_uninit(void) {
+sh_css_hmm_buffer_record_uninit(void)
+{
int i;
struct sh_css_hmm_buffer_record *buffer_record = NULL;
@@ -10882,7 +10710,8 @@ sh_css_hmm_buffer_record_uninit(void) {
}
static void
-sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
+sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
+{
assert(buffer_record);
buffer_record->in_use = false;
buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
@@ -10893,14 +10722,15 @@ sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
static struct sh_css_hmm_buffer_record
*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
enum ia_css_buffer_type type,
- hrt_address kernel_ptr) {
+ hrt_address kernel_ptr)
+{
int i;
struct sh_css_hmm_buffer_record *buffer_record = NULL;
struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
assert(h_vbuf);
assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
- (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
+ (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
assert(kernel_ptr != 0);
buffer_record = &hmm_buffer_record[0];
@@ -10921,7 +10751,8 @@ static struct sh_css_hmm_buffer_record
static struct sh_css_hmm_buffer_record
*sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
- enum ia_css_buffer_type type) {
+ enum ia_css_buffer_type type)
+{
int i;
struct sh_css_hmm_buffer_record *buffer_record = NULL;
bool found_record = false;
diff --git a/drivers/staging/media/av7110/Kconfig b/drivers/staging/media/av7110/Kconfig
new file mode 100644
index 000000000000..9faf9d2d4001
--- /dev/null
+++ b/drivers/staging/media/av7110/Kconfig
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config DVB_AV7110_IR
+ bool
+ depends on RC_CORE=y || RC_CORE = DVB_AV7110
+ default DVB_AV7110
+
+config DVB_AV7110
+ tristate "AV7110 cards"
+ depends on DVB_CORE && PCI && I2C
+ select TTPCI_EEPROM
+ select VIDEO_SAA7146_VV
+ depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
+ select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_SP8870 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+ help
+ Support for SAA7146 and AV7110 based DVB cards as produced
+ by Fujitsu-Siemens, Technotrend, Hauppauge and others.
+
+ This driver only supports the fullfeatured cards with
+ onboard MPEG2 decoder.
+
+ This driver needs an external firmware. Please use the script
+ "<kerneldir>/scripts/get_dvb_firmware av7110" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
+ Alternatively, you can download the file and use the kernel's
+ EXTRA_FIRMWARE configuration option to build it into your
+ kernel image by adding the filename to the EXTRA_FIRMWARE
+ configuration option string.
+
+ Say Y if you own such a card and want to use it.
+
+config DVB_AV7110_OSD
+ bool "AV7110 OSD support"
+ depends on DVB_AV7110
+ default y if DVB_AV7110=y || DVB_AV7110=m
+ help
+ The AV7110 firmware provides some code to generate an OnScreenDisplay
+ on the video output. This is kind of nonstandard and not guaranteed to
+ be maintained.
+
+ Anyway, some popular DVB software like VDR uses this OSD to render
+ its menus, so say Y if you want to use this software.
+
+ All other people say N.
+
+config DVB_BUDGET_PATCH
+ tristate "AV7110 cards with Budget Patch"
+ depends on DVB_BUDGET_CORE && I2C
+ depends on DVB_AV7110
+ select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
+ help
+ Support for Budget Patch (full TS) modification on
+ SAA7146+AV7110 based cards (DVB-S cards). This
+ driver doesn't use onboard MPEG2 decoder. The
+ card is driven in Budget-only mode. Card is
+ required to have loaded firmware to tune properly.
+ Firmware can be loaded by insertion and removal of
+ standard AV7110 driver prior to loading this
+ driver.
+
+ Say Y if you own such a card and want to use it.
+
+ To compile this driver as a module, choose M here: the
+ module will be called budget-patch.
+
+if DVB_AV7110
+
+# Frontend driver that it is used only by AV7110 driver
+# While technically independent, it doesn't make sense to keep
+# it if we drop support for AV7110, as no other driver will use it.
+
+config DVB_SP8870
+ tristate "Spase sp8870 based"
+ depends on DVB_CORE && I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
+
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/scripts/get_dvb_firmware sp8870" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
+endif
diff --git a/drivers/staging/media/av7110/Makefile b/drivers/staging/media/av7110/Makefile
new file mode 100644
index 000000000000..307b267598ea
--- /dev/null
+++ b/drivers/staging/media/av7110/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the AV7110 DVB device driver
+#
+
+dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o \
+ av7110_ipack.o dvb_filter.o
+
+ifdef CONFIG_DVB_AV7110_IR
+dvb-ttpci-objs += av7110_ir.o
+endif
+
+obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
+
+obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
+
+obj-$(CONFIG_DVB_SP8870) += sp8870.o
+
+ccflags-y += -I $(srctree)/drivers/media/dvb-frontends
+ccflags-y += -I $(srctree)/drivers/media/tuners
+ccflags-y += -I $(srctree)/drivers/media/pci/ttpci
+ccflags-y += -I $(srctree)/drivers/media/common
diff --git a/drivers/staging/media/av7110/TODO b/drivers/staging/media/av7110/TODO
new file mode 100644
index 000000000000..60062d8441b3
--- /dev/null
+++ b/drivers/staging/media/av7110/TODO
@@ -0,0 +1,3 @@
+- This driver is too old and relies on a different API.
+ Drop it from Kernel on a couple of versions.
+- Cleanup patches for the drivers here won't be accepted.
diff --git a/drivers/staging/media/av7110/audio-bilingual-channel-select.rst b/drivers/staging/media/av7110/audio-bilingual-channel-select.rst
new file mode 100644
index 000000000000..33b5363317f1
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-bilingual-channel-select.rst
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_BILINGUAL_CHANNEL_SELECT:
+
+==============================
+AUDIO_BILINGUAL_CHANNEL_SELECT
+==============================
+
+Name
+----
+
+AUDIO_BILINGUAL_CHANNEL_SELECT
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_BILINGUAL_CHANNEL_SELECT
+
+``int ioctl(int fd, AUDIO_BILINGUAL_CHANNEL_SELECT, struct audio_channel_select *select)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - audio_channel_select_t ch
+
+ - Select the output format of the audio (mono left/right, stereo).
+
+Description
+-----------
+
+This ioctl is obsolete. Do not use in new drivers. It has been replaced
+by the V4L2 ``V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK`` control
+for MPEG decoders controlled through V4L2.
+
+This ioctl call asks the Audio Device to select the requested channel
+for bilingual streams if possible.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-channel-select.rst b/drivers/staging/media/av7110/audio-channel-select.rst
new file mode 100644
index 000000000000..74093df92a68
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-channel-select.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_CHANNEL_SELECT:
+
+====================
+AUDIO_CHANNEL_SELECT
+====================
+
+Name
+----
+
+AUDIO_CHANNEL_SELECT
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_CHANNEL_SELECT
+
+``int ioctl(int fd, AUDIO_CHANNEL_SELECT, struct audio_channel_select *select)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - audio_channel_select_t ch
+
+ - Select the output format of the audio (mono left/right, stereo).
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 ``V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK`` control instead.
+
+This ioctl call asks the Audio Device to select the requested channel if
+possible.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-clear-buffer.rst b/drivers/staging/media/av7110/audio-clear-buffer.rst
new file mode 100644
index 000000000000..a0ebb0278260
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-clear-buffer.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_CLEAR_BUFFER:
+
+==================
+AUDIO_CLEAR_BUFFER
+==================
+
+Name
+----
+
+AUDIO_CLEAR_BUFFER
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_CLEAR_BUFFER
+
+``int ioctl(int fd, AUDIO_CLEAR_BUFFER)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to clear all software and hardware
+buffers of the audio decoder device.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-continue.rst b/drivers/staging/media/av7110/audio-continue.rst
new file mode 100644
index 000000000000..a2e9850f37f2
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-continue.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_CONTINUE:
+
+==============
+AUDIO_CONTINUE
+==============
+
+Name
+----
+
+AUDIO_CONTINUE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_CONTINUE
+
+``int ioctl(int fd, AUDIO_CONTINUE)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This ioctl restarts the decoding and playing process previously paused
+with AUDIO_PAUSE command.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-fclose.rst b/drivers/staging/media/av7110/audio-fclose.rst
new file mode 100644
index 000000000000..77857d578e83
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-fclose.rst
@@ -0,0 +1,51 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _audio_fclose:
+
+========================
+Digital TV audio close()
+========================
+
+Name
+----
+
+Digital TV audio close()
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:function:: int close(int fd)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This system call closes a previously opened audio device.
+
+Return Value
+------------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EBADF``
+
+ - fd is not a valid open file descriptor.
diff --git a/drivers/staging/media/av7110/audio-fopen.rst b/drivers/staging/media/av7110/audio-fopen.rst
new file mode 100644
index 000000000000..774daaab3bad
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-fopen.rst
@@ -0,0 +1,103 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _audio_fopen:
+
+=======================
+Digital TV audio open()
+=======================
+
+Name
+----
+
+Digital TV audio open()
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:function:: int open(const char *deviceName, int flags)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - const char \*deviceName
+
+ - Name of specific audio device.
+
+ - .. row 2
+
+ - int flags
+
+ - A bit-wise OR of the following flags:
+
+ - .. row 3
+
+ -
+ - O_RDONLY read-only access
+
+ - .. row 4
+
+ -
+ - O_RDWR read/write access
+
+ - .. row 5
+
+ -
+ - O_NONBLOCK open in non-blocking mode
+
+ - .. row 6
+
+ -
+ - (blocking mode is the default)
+
+Description
+-----------
+
+This system call opens a named audio device (e.g.
+/dev/dvb/adapter0/audio0) for subsequent use. When an open() call has
+succeeded, the device will be ready for use. The significance of
+blocking or non-blocking mode is described in the documentation for
+functions where there is a difference. It does not affect the semantics
+of the open() call itself. A device opened in blocking mode can later be
+put into non-blocking mode (and vice versa) using the F_SETFL command
+of the fcntl system call. This is a standard system call, documented in
+the Linux manual page for fcntl. Only one user can open the Audio Device
+in O_RDWR mode. All other attempts to open the device in this mode will
+fail, and an error code will be returned. If the Audio Device is opened
+in O_RDONLY mode, the only ioctl call that can be used is
+AUDIO_GET_STATUS. All other call will return with an error code.
+
+Return Value
+------------
+
+.. tabularcolumns:: |p{2.5cm}|p{15.0cm}|
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``ENODEV``
+
+ - Device driver not loaded/available.
+
+ - .. row 2
+
+ - ``EBUSY``
+
+ - Device or resource busy.
+
+ - .. row 3
+
+ - ``EINVAL``
+
+ - Invalid argument.
diff --git a/drivers/staging/media/av7110/audio-fwrite.rst b/drivers/staging/media/av7110/audio-fwrite.rst
new file mode 100644
index 000000000000..7b096ac2b6c4
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-fwrite.rst
@@ -0,0 +1,79 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _audio_fwrite:
+
+=========================
+Digital TV audio write()
+=========================
+
+Name
+----
+
+Digital TV audio write()
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:function:: size_t write(int fd, const void *buf, size_t count)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - void \*buf
+
+ - Pointer to the buffer containing the PES data.
+
+ - .. row 3
+
+ - size_t count
+
+ - Size of buf.
+
+Description
+-----------
+
+This system call can only be used if AUDIO_SOURCE_MEMORY is selected
+in the ioctl call AUDIO_SELECT_SOURCE. The data provided shall be in
+PES format. If O_NONBLOCK is not specified the function will block
+until buffer space is available. The amount of data to be transferred is
+implied by count.
+
+Return Value
+------------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EPERM``
+
+ - Mode AUDIO_SOURCE_MEMORY not selected.
+
+ - .. row 2
+
+ - ``ENOMEM``
+
+ - Attempted to write more data than the internal buffer can hold.
+
+ - .. row 3
+
+ - ``EBADF``
+
+ - fd is not a valid open file descriptor.
diff --git a/drivers/staging/media/av7110/audio-get-capabilities.rst b/drivers/staging/media/av7110/audio-get-capabilities.rst
new file mode 100644
index 000000000000..6d9eb71dad17
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-get-capabilities.rst
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_GET_CAPABILITIES:
+
+======================
+AUDIO_GET_CAPABILITIES
+======================
+
+Name
+----
+
+AUDIO_GET_CAPABILITIES
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_GET_CAPABILITIES
+
+``int ioctl(int fd, AUDIO_GET_CAPABILITIES, unsigned int *cap)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - unsigned int \*cap
+
+ - Returns a bit array of supported sound formats.
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to tell us about the decoding
+capabilities of the audio hardware.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-get-status.rst b/drivers/staging/media/av7110/audio-get-status.rst
new file mode 100644
index 000000000000..7ae8db2e65e9
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-get-status.rst
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_GET_STATUS:
+
+================
+AUDIO_GET_STATUS
+================
+
+Name
+----
+
+AUDIO_GET_STATUS
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_GET_STATUS
+
+``int ioctl(int fd, AUDIO_GET_STATUS, struct audio_status *status)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - struct audio_status \*status
+
+ - Returns the current state of Audio Device.
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to return the current state of the
+Audio Device.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-pause.rst b/drivers/staging/media/av7110/audio-pause.rst
new file mode 100644
index 000000000000..d37d1ddce4df
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-pause.rst
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_PAUSE:
+
+===========
+AUDIO_PAUSE
+===========
+
+Name
+----
+
+AUDIO_PAUSE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_PAUSE
+
+``int ioctl(int fd, AUDIO_PAUSE)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This ioctl call suspends the audio stream being played. Decoding and
+playing are paused. It is then possible to restart again decoding and
+playing process of the audio stream using AUDIO_CONTINUE command.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-play.rst b/drivers/staging/media/av7110/audio-play.rst
new file mode 100644
index 000000000000..e591930b6ca7
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-play.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_PLAY:
+
+==========
+AUDIO_PLAY
+==========
+
+Name
+----
+
+AUDIO_PLAY
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_PLAY
+
+``int ioctl(int fd, AUDIO_PLAY)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to start playing an audio stream
+from the selected source.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-select-source.rst b/drivers/staging/media/av7110/audio-select-source.rst
new file mode 100644
index 000000000000..6a0c0f365eb1
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-select-source.rst
@@ -0,0 +1,56 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SELECT_SOURCE:
+
+===================
+AUDIO_SELECT_SOURCE
+===================
+
+Name
+----
+
+AUDIO_SELECT_SOURCE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SELECT_SOURCE
+
+``int ioctl(int fd, AUDIO_SELECT_SOURCE, struct audio_stream_source *source)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - audio_stream_source_t source
+
+ - Indicates the source that shall be used for the Audio stream.
+
+Description
+-----------
+
+This ioctl call informs the audio device which source shall be used for
+the input data. The possible sources are demux or memory. If
+AUDIO_SOURCE_MEMORY is selected, the data is fed to the Audio Device
+through the write command.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-av-sync.rst b/drivers/staging/media/av7110/audio-set-av-sync.rst
new file mode 100644
index 000000000000..85a8016bf025
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-av-sync.rst
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_AV_SYNC:
+
+=================
+AUDIO_SET_AV_SYNC
+=================
+
+Name
+----
+
+AUDIO_SET_AV_SYNC
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_AV_SYNC
+
+``int ioctl(int fd, AUDIO_SET_AV_SYNC, boolean state)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - boolean state
+
+ - Tells the Digital TV subsystem if A/V synchronization shall be ON or OFF.
+
+ TRUE: AV-sync ON
+
+ FALSE: AV-sync OFF
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to turn ON or OFF A/V
+synchronization.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-bypass-mode.rst b/drivers/staging/media/av7110/audio-set-bypass-mode.rst
new file mode 100644
index 000000000000..80d551a2053a
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-bypass-mode.rst
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_BYPASS_MODE:
+
+=====================
+AUDIO_SET_BYPASS_MODE
+=====================
+
+Name
+----
+
+AUDIO_SET_BYPASS_MODE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_BYPASS_MODE
+
+``int ioctl(int fd, AUDIO_SET_BYPASS_MODE, boolean mode)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - boolean mode
+
+ - Enables or disables the decoding of the current Audio stream in
+ the Digital TV subsystem.
+
+ TRUE: Bypass is disabled
+
+ FALSE: Bypass is enabled
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to bypass the Audio decoder and
+forward the stream without decoding. This mode shall be used if streams
+that can't be handled by the Digital TV system shall be decoded. Dolby
+DigitalTM streams are automatically forwarded by the Digital TV subsystem if
+the hardware can handle it.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-id.rst b/drivers/staging/media/av7110/audio-set-id.rst
new file mode 100644
index 000000000000..39ad846d412d
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-id.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_ID:
+
+============
+AUDIO_SET_ID
+============
+
+Name
+----
+
+AUDIO_SET_ID
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_ID
+
+``int ioctl(int fd, AUDIO_SET_ID, int id)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - int id
+
+ - audio sub-stream id
+
+Description
+-----------
+
+This ioctl selects which sub-stream is to be decoded if a program or
+system stream is sent to the video device. If no audio stream type is
+set the id has to be in [0xC0,0xDF] for MPEG sound, in [0x80,0x87] for
+AC3 and in [0xA0,0xA7] for LPCM. More specifications may follow for
+other stream types. If the stream type is set the id just specifies the
+substream id of the audio stream and only the first 5 bits are
+recognized.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-mixer.rst b/drivers/staging/media/av7110/audio-set-mixer.rst
new file mode 100644
index 000000000000..45dbdf4801e0
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-mixer.rst
@@ -0,0 +1,53 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_MIXER:
+
+===============
+AUDIO_SET_MIXER
+===============
+
+Name
+----
+
+AUDIO_SET_MIXER
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_MIXER
+
+``int ioctl(int fd, AUDIO_SET_MIXER, struct audio_mixer *mix)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - audio_mixer_t \*mix
+
+ - mixer settings.
+
+Description
+-----------
+
+This ioctl lets you adjust the mixer settings of the audio decoder.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-mute.rst b/drivers/staging/media/av7110/audio-set-mute.rst
new file mode 100644
index 000000000000..987751f92967
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-mute.rst
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_MUTE:
+
+==============
+AUDIO_SET_MUTE
+==============
+
+Name
+----
+
+AUDIO_SET_MUTE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_MUTE
+
+``int ioctl(int fd, AUDIO_SET_MUTE, boolean state)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - boolean state
+
+ - Indicates if audio device shall mute or not.
+
+ TRUE: Audio Mute
+
+ FALSE: Audio Un-mute
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 :ref:`VIDIOC_DECODER_CMD` with the
+``V4L2_DEC_CMD_START_MUTE_AUDIO`` flag instead.
+
+This ioctl call asks the audio device to mute the stream that is
+currently being played.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio-set-streamtype.rst b/drivers/staging/media/av7110/audio-set-streamtype.rst
new file mode 100644
index 000000000000..77d73c74882f
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-set-streamtype.rst
@@ -0,0 +1,66 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_SET_STREAMTYPE:
+
+====================
+AUDIO_SET_STREAMTYPE
+====================
+
+Name
+----
+
+AUDIO_SET_STREAMTYPE
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_SET_STREAMTYPE
+
+``int ioctl(fd, AUDIO_SET_STREAMTYPE, int type)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ -
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ -
+
+ - int type
+
+ - stream type
+
+Description
+-----------
+
+This ioctl tells the driver which kind of audio stream to expect. This
+is useful if the stream offers several audio sub-streams like LPCM and
+AC3.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EINVAL``
+
+ - type is not a valid or supported stream type.
diff --git a/drivers/staging/media/av7110/audio-stop.rst b/drivers/staging/media/av7110/audio-stop.rst
new file mode 100644
index 000000000000..d77f786fd797
--- /dev/null
+++ b/drivers/staging/media/av7110/audio-stop.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.audio
+
+.. _AUDIO_STOP:
+
+==========
+AUDIO_STOP
+==========
+
+Name
+----
+
+AUDIO_STOP
+
+.. attention:: This ioctl is deprecated
+
+Synopsis
+--------
+
+.. c:macro:: AUDIO_STOP
+
+``int ioctl(int fd, AUDIO_STOP)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This ioctl call asks the Audio Device to stop playing the current
+stream.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/audio.h b/drivers/staging/media/av7110/audio.h
new file mode 100644
index 000000000000..2f869da69171
--- /dev/null
+++ b/drivers/staging/media/av7110/audio.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * audio.h - DEPRECATED MPEG-TS audio decoder API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ * for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _DVBAUDIO_H_
+#define _DVBAUDIO_H_
+
+#include <linux/types.h>
+
+typedef enum {
+ AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
+ AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
+} audio_stream_source_t;
+
+
+typedef enum {
+ AUDIO_STOPPED, /* Device is stopped */
+ AUDIO_PLAYING, /* Device is currently playing */
+ AUDIO_PAUSED /* Device is paused */
+} audio_play_state_t;
+
+
+typedef enum {
+ AUDIO_STEREO,
+ AUDIO_MONO_LEFT,
+ AUDIO_MONO_RIGHT,
+ AUDIO_MONO,
+ AUDIO_STEREO_SWAPPED
+} audio_channel_select_t;
+
+
+typedef struct audio_mixer {
+ unsigned int volume_left;
+ unsigned int volume_right;
+ /* what else do we need? bass, pass-through, ... */
+} audio_mixer_t;
+
+
+typedef struct audio_status {
+ int AV_sync_state; /* sync audio and video? */
+ int mute_state; /* audio is muted */
+ audio_play_state_t play_state; /* current playback state */
+ audio_stream_source_t stream_source; /* current stream source */
+ audio_channel_select_t channel_select; /* currently selected channel */
+ int bypass_mode; /* pass on audio data to */
+ audio_mixer_t mixer_state; /* current mixer state */
+} audio_status_t; /* separate decoder hardware */
+
+
+/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
+#define AUDIO_CAP_DTS 1
+#define AUDIO_CAP_LPCM 2
+#define AUDIO_CAP_MP1 4
+#define AUDIO_CAP_MP2 8
+#define AUDIO_CAP_MP3 16
+#define AUDIO_CAP_AAC 32
+#define AUDIO_CAP_OGG 64
+#define AUDIO_CAP_SDDS 128
+#define AUDIO_CAP_AC3 256
+
+#define AUDIO_STOP _IO('o', 1)
+#define AUDIO_PLAY _IO('o', 2)
+#define AUDIO_PAUSE _IO('o', 3)
+#define AUDIO_CONTINUE _IO('o', 4)
+#define AUDIO_SELECT_SOURCE _IO('o', 5)
+#define AUDIO_SET_MUTE _IO('o', 6)
+#define AUDIO_SET_AV_SYNC _IO('o', 7)
+#define AUDIO_SET_BYPASS_MODE _IO('o', 8)
+#define AUDIO_CHANNEL_SELECT _IO('o', 9)
+#define AUDIO_GET_STATUS _IOR('o', 10, audio_status_t)
+
+#define AUDIO_GET_CAPABILITIES _IOR('o', 11, unsigned int)
+#define AUDIO_CLEAR_BUFFER _IO('o', 12)
+#define AUDIO_SET_ID _IO('o', 13)
+#define AUDIO_SET_MIXER _IOW('o', 14, audio_mixer_t)
+#define AUDIO_SET_STREAMTYPE _IO('o', 15)
+#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
+
+#endif /* _DVBAUDIO_H_ */
diff --git a/drivers/staging/media/av7110/audio.rst b/drivers/staging/media/av7110/audio.rst
new file mode 100644
index 000000000000..aa753336b31f
--- /dev/null
+++ b/drivers/staging/media/av7110/audio.rst
@@ -0,0 +1,27 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _dvb_audio:
+
+#######################
+Digital TV Audio Device
+#######################
+
+The Digital TV audio device controls the MPEG2 audio decoder of the Digital
+TV hardware. It can be accessed through ``/dev/dvb/adapter?/audio?``. Data
+types and ioctl definitions can be accessed by including
+``linux/dvb/audio.h`` in your application.
+
+Please note that some Digital TV cards don't have their own MPEG decoder, which
+results in the omission of the audio and video device.
+
+These ioctls were also used by V4L2 to control MPEG decoders implemented
+in V4L2. The use of these ioctls for that purpose has been made obsolete
+and proper V4L2 ioctls or controls have been created to replace that
+functionality.
+
+
+.. toctree::
+ :maxdepth: 1
+
+ audio_data_types
+ audio_function_calls
diff --git a/drivers/staging/media/av7110/audio_data_types.rst b/drivers/staging/media/av7110/audio_data_types.rst
new file mode 100644
index 000000000000..4744529136a8
--- /dev/null
+++ b/drivers/staging/media/av7110/audio_data_types.rst
@@ -0,0 +1,116 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _audio_data_types:
+
+****************
+Audio Data Types
+****************
+
+This section describes the structures, data types and defines used when
+talking to the audio device.
+
+.. c:type:: audio_stream_source
+
+The audio stream source is set through the AUDIO_SELECT_SOURCE call
+and can take the following values, depending on whether we are replaying
+from an internal (demux) or external (user write) source.
+
+
+.. code-block:: c
+
+ typedef enum {
+ AUDIO_SOURCE_DEMUX,
+ AUDIO_SOURCE_MEMORY
+ } audio_stream_source_t;
+
+AUDIO_SOURCE_DEMUX selects the demultiplexer (fed either by the
+frontend or the DVR device) as the source of the video stream. If
+AUDIO_SOURCE_MEMORY is selected the stream comes from the application
+through the ``write()`` system call.
+
+
+.. c:type:: audio_play_state
+
+The following values can be returned by the AUDIO_GET_STATUS call
+representing the state of audio playback.
+
+
+.. code-block:: c
+
+ typedef enum {
+ AUDIO_STOPPED,
+ AUDIO_PLAYING,
+ AUDIO_PAUSED
+ } audio_play_state_t;
+
+
+.. c:type:: audio_channel_select
+
+The audio channel selected via AUDIO_CHANNEL_SELECT is determined by
+the following values.
+
+
+.. code-block:: c
+
+ typedef enum {
+ AUDIO_STEREO,
+ AUDIO_MONO_LEFT,
+ AUDIO_MONO_RIGHT,
+ AUDIO_MONO,
+ AUDIO_STEREO_SWAPPED
+ } audio_channel_select_t;
+
+
+.. c:type:: audio_status
+
+The AUDIO_GET_STATUS call returns the following structure informing
+about various states of the playback operation.
+
+
+.. code-block:: c
+
+ typedef struct audio_status {
+ boolean AV_sync_state;
+ boolean mute_state;
+ audio_play_state_t play_state;
+ audio_stream_source_t stream_source;
+ audio_channel_select_t channel_select;
+ boolean bypass_mode;
+ audio_mixer_t mixer_state;
+ } audio_status_t;
+
+
+.. c:type:: audio_mixer
+
+The following structure is used by the AUDIO_SET_MIXER call to set the
+audio volume.
+
+
+.. code-block:: c
+
+ typedef struct audio_mixer {
+ unsigned int volume_left;
+ unsigned int volume_right;
+ } audio_mixer_t;
+
+
+.. _audio_encodings:
+
+audio encodings
+===============
+
+A call to AUDIO_GET_CAPABILITIES returns an unsigned integer with the
+following bits set according to the hardwares capabilities.
+
+
+.. code-block:: c
+
+ #define AUDIO_CAP_DTS 1
+ #define AUDIO_CAP_LPCM 2
+ #define AUDIO_CAP_MP1 4
+ #define AUDIO_CAP_MP2 8
+ #define AUDIO_CAP_MP3 16
+ #define AUDIO_CAP_AAC 32
+ #define AUDIO_CAP_OGG 64
+ #define AUDIO_CAP_SDDS 128
+ #define AUDIO_CAP_AC3 256
diff --git a/drivers/staging/media/av7110/audio_function_calls.rst b/drivers/staging/media/av7110/audio_function_calls.rst
new file mode 100644
index 000000000000..fa5ba9539caf
--- /dev/null
+++ b/drivers/staging/media/av7110/audio_function_calls.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _audio_function_calls:
+
+********************
+Audio Function Calls
+********************
+
+.. toctree::
+ :maxdepth: 1
+
+ audio-fopen
+ audio-fclose
+ audio-fwrite
+ audio-stop
+ audio-play
+ audio-pause
+ audio-continue
+ audio-select-source
+ audio-set-mute
+ audio-set-av-sync
+ audio-set-bypass-mode
+ audio-channel-select
+ audio-bilingual-channel-select
+ audio-get-status
+ audio-get-capabilities
+ audio-clear-buffer
+ audio-set-id
+ audio-set-mixer
+ audio-set-streamtype
diff --git a/drivers/staging/media/av7110/av7110.c b/drivers/staging/media/av7110/av7110.c
new file mode 100644
index 000000000000..d74ee0ecfb36
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110.c
@@ -0,0 +1,2919 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB)
+ * av7110.c: initialization and demux stuff
+ *
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * originally based on code by:
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/poll.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/crc32.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+
+#include <linux/dvb/frontend.h>
+
+#include <media/dvb_frontend.h>
+
+#include "ttpci-eeprom.h"
+#include "av7110.h"
+#include "av7110_hw.h"
+#include "av7110_av.h"
+#include "av7110_ca.h"
+#include "av7110_ipack.h"
+
+#include "bsbe1.h"
+#include "lnbp21.h"
+#include "bsru6.h"
+
+#define TS_WIDTH 376
+#define TS_HEIGHT 512
+#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
+#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
+
+
+int av7110_debug;
+
+static int vidmode = CVBS_RGB_OUT;
+static int pids_off;
+static int adac = DVB_ADAC_TI;
+static int hw_sections;
+static int rgb_on;
+static int volume = 255;
+static int budgetpatch;
+static int wss_cfg_4_3 = 0x4008;
+static int wss_cfg_16_9 = 0x0007;
+static int tv_standard;
+static int full_ts;
+
+module_param_named(debug, av7110_debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
+module_param(vidmode, int, 0444);
+MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
+module_param(pids_off, int, 0444);
+MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
+module_param(adac, int, 0444);
+MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
+module_param(hw_sections, int, 0444);
+MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
+module_param(rgb_on, int, 0444);
+MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
+module_param(volume, int, 0444);
+MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
+module_param(budgetpatch, int, 0444);
+MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
+module_param(full_ts, int, 0444);
+MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
+module_param(wss_cfg_4_3, int, 0444);
+MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(wss_cfg_16_9, int, 0444);
+MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(tv_standard, int, 0444);
+MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static void restart_feeds(struct av7110 *av7110);
+static int budget_start_feed(struct dvb_demux_feed *feed);
+static int budget_stop_feed(struct dvb_demux_feed *feed);
+
+static int av7110_num;
+
+#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
+{\
+ if (fe_func != NULL) { \
+ av7110_copy = fe_func; \
+ fe_func = av7110_func; \
+ } \
+}
+
+
+static void init_av7110_av(struct av7110 *av7110)
+{
+ int ret;
+ struct saa7146_dev *dev = av7110->dev;
+
+ /* set internal volume control to maximum */
+ av7110->adac_type = DVB_ADAC_TI;
+ ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
+ if (ret < 0)
+ printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
+
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
+ 1, (u16) av7110->display_ar);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to set aspect ratio\n");
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
+ 1, av7110->display_panscan);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to set pan scan\n");
+
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to configure 4:3 wss\n");
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to configure 16:9 wss\n");
+
+ ret = av7710_set_video_mode(av7110, vidmode);
+ if (ret < 0)
+ printk("dvb-ttpci:cannot set video mode:%d\n",ret);
+
+ /* handle different card types */
+ /* remaining inits according to card and frontend type */
+ av7110->analog_tuner_flags = 0;
+ av7110->current_input = 0;
+ if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
+ av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
+ if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+ printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_CRYSTAL;
+ i2c_writereg(av7110, 0x20, 0x01, 0xd2);
+ i2c_writereg(av7110, 0x20, 0x02, 0x49);
+ i2c_writereg(av7110, 0x20, 0x03, 0x00);
+ i2c_writereg(av7110, 0x20, 0x04, 0x00);
+
+ /**
+ * some special handling for the Siemens DVB-C cards...
+ */
+ } else if (0 == av7110_init_analog_module(av7110)) {
+ /* done. */
+ }
+ else if (dev->pci->subsystem_vendor == 0x110a) {
+ printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_NONE;
+ }
+ else {
+ av7110->adac_type = adac;
+ printk("dvb-ttpci: adac type set to %d @ card %d\n",
+ av7110->adac_type, av7110->dvb_adapter.num);
+ }
+
+ if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
+ // switch DVB SCART on
+ ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
+ if (ret < 0)
+ printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
+ ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
+ if (ret < 0)
+ printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
+ if (rgb_on &&
+ ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
+ (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
+ (av7110->dev->pci->subsystem_device == 0x0000)) {
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
+ //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
+ }
+ }
+
+ if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
+ av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
+
+ ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
+ if (ret < 0)
+ printk("dvb-ttpci:cannot set volume :%d\n",ret);
+}
+
+static void recover_arm(struct av7110 *av7110)
+{
+ dprintk(4, "%p\n",av7110);
+
+ av7110_bootarm(av7110);
+ msleep(100);
+
+ init_av7110_av(av7110);
+
+ /* card-specific recovery */
+ if (av7110->recover)
+ av7110->recover(av7110);
+
+ restart_feeds(av7110);
+
+#if IS_ENABLED(CONFIG_DVB_AV7110_IR)
+ av7110_set_ir_config(av7110);
+#endif
+}
+
+static void av7110_arm_sync(struct av7110 *av7110)
+{
+ if (av7110->arm_thread)
+ kthread_stop(av7110->arm_thread);
+
+ av7110->arm_thread = NULL;
+}
+
+static int arm_thread(void *data)
+{
+ struct av7110 *av7110 = data;
+ u16 newloops = 0;
+ int timeout;
+
+ dprintk(4, "%p\n",av7110);
+
+ for (;;) {
+ timeout = wait_event_interruptible_timeout(av7110->arm_wait,
+ kthread_should_stop(), 5 * HZ);
+
+ if (-ERESTARTSYS == timeout || kthread_should_stop()) {
+ /* got signal or told to quit*/
+ break;
+ }
+
+ if (!av7110->arm_ready)
+ continue;
+
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ break;
+ newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
+ mutex_unlock(&av7110->dcomlock);
+
+ if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
+ printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
+ av7110->dvb_adapter.num);
+
+ recover_arm(av7110);
+
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ break;
+ newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
+ mutex_unlock(&av7110->dcomlock);
+ }
+ av7110->arm_loops = newloops;
+ av7110->arm_errors = 0;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * IRQ handling
+ ****************************************************************************/
+
+static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
+ u8 *buffer2, size_t buffer2_len,
+ struct dvb_demux_filter *dvbdmxfilter,
+ struct av7110 *av7110)
+{
+ if (!dvbdmxfilter->feed->demux->dmx.frontend)
+ return 0;
+ if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
+ return 0;
+
+ switch (dvbdmxfilter->type) {
+ case DMX_TYPE_SEC:
+ if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
+ return 0;
+ if (dvbdmxfilter->doneq) {
+ struct dmx_section_filter *filter = &dvbdmxfilter->filter;
+ int i;
+ u8 xor, neq = 0;
+
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
+ xor = filter->filter_value[i] ^ buffer1[i];
+ neq |= dvbdmxfilter->maskandnotmode[i] & xor;
+ }
+ if (!neq)
+ return 0;
+ }
+ return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
+ buffer2, buffer2_len,
+ &dvbdmxfilter->filter, NULL);
+ case DMX_TYPE_TS:
+ if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
+ return 0;
+ if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
+ return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
+ buffer2, buffer2_len,
+ &dvbdmxfilter->feed->feed.ts,
+ NULL);
+ else
+ av7110_p2t_write(buffer1, buffer1_len,
+ dvbdmxfilter->feed->pid,
+ &av7110->p2t_filter[dvbdmxfilter->index]);
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+//#define DEBUG_TIMING
+static inline void print_time(char *s)
+{
+#ifdef DEBUG_TIMING
+ struct timespec64 ts;
+ ktime_get_real_ts64(&ts);
+ printk("%s: %lld.%09ld\n", s, (s64)ts.tv_sec, ts.tv_nsec);
+#endif
+}
+
+#define DEBI_READ 0
+#define DEBI_WRITE 1
+static inline void start_debi_dma(struct av7110 *av7110, int dir,
+ unsigned long addr, unsigned int len)
+{
+ dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
+ if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ return;
+ }
+
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
+ SAA7146_IER_ENABLE(av7110->dev, MASK_19);
+ if (len < 5)
+ len = 5; /* we want a real DEBI DMA */
+ if (dir == DEBI_WRITE)
+ iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
+ else
+ irdebi(av7110, DEBISWAB, addr, 0, len);
+}
+
+static void debiirq(struct tasklet_struct *t)
+{
+ struct av7110 *av7110 = from_tasklet(av7110, t, debi_tasklet);
+ int type = av7110->debitype;
+ int handle = (type >> 8) & 0x1f;
+ unsigned int xfer = 0;
+
+ print_time("debi");
+ dprintk(4, "type 0x%04x\n", type);
+
+ if (type == -1) {
+ printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
+ jiffies, saa7146_read(av7110->dev, PSR),
+ saa7146_read(av7110->dev, SSR));
+ goto debi_done;
+ }
+ av7110->debitype = -1;
+
+ switch (type & 0xff) {
+
+ case DATA_TS_RECORD:
+ dvb_dmx_swfilter_packets(&av7110->demux,
+ (const u8 *) av7110->debi_virt,
+ av7110->debilen / 188);
+ xfer = RX_BUFF;
+ break;
+
+ case DATA_PES_RECORD:
+ if (av7110->demux.recording)
+ av7110_record_cb(&av7110->p2t[handle],
+ (u8 *) av7110->debi_virt,
+ av7110->debilen);
+ xfer = RX_BUFF;
+ break;
+
+ case DATA_IPMPE:
+ case DATA_FSECTION:
+ case DATA_PIPING:
+ if (av7110->handle2filter[handle])
+ DvbDmxFilterCallback((u8 *)av7110->debi_virt,
+ av7110->debilen, NULL, 0,
+ av7110->handle2filter[handle],
+ av7110);
+ xfer = RX_BUFF;
+ break;
+
+ case DATA_CI_GET:
+ {
+ u8 *data = av7110->debi_virt;
+ u8 data_0 = data[0];
+
+ if (data_0 < 2 && data[2] == 0xff) {
+ int flags = 0;
+ if (data[5] > 0)
+ flags |= CA_CI_MODULE_PRESENT;
+ if (data[5] > 5)
+ flags |= CA_CI_MODULE_READY;
+ av7110->ci_slot[data_0].flags = flags;
+ } else
+ ci_get_data(&av7110->ci_rbuffer,
+ av7110->debi_virt,
+ av7110->debilen);
+ xfer = RX_BUFF;
+ break;
+ }
+
+ case DATA_COMMON_INTERFACE:
+ CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
+ xfer = RX_BUFF;
+ break;
+
+ case DATA_DEBUG_MESSAGE:
+ ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
+ printk("%s\n", (s8 *) av7110->debi_virt);
+ xfer = RX_BUFF;
+ break;
+
+ case DATA_CI_PUT:
+ dprintk(4, "debi DATA_CI_PUT\n");
+ xfer = TX_BUFF;
+ break;
+ case DATA_MPEG_PLAY:
+ dprintk(4, "debi DATA_MPEG_PLAY\n");
+ xfer = TX_BUFF;
+ break;
+ case DATA_BMP_LOAD:
+ dprintk(4, "debi DATA_BMP_LOAD\n");
+ xfer = TX_BUFF;
+ break;
+ default:
+ break;
+ }
+debi_done:
+ spin_lock(&av7110->debilock);
+ if (xfer)
+ iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
+ ARM_ClearMailBox(av7110);
+ spin_unlock(&av7110->debilock);
+}
+
+/* irq from av7110 firmware writing the mailbox register in the DPRAM */
+static void gpioirq(struct tasklet_struct *t)
+{
+ struct av7110 *av7110 = from_tasklet(av7110, t, gpio_tasklet);
+ u32 rxbuf, txbuf;
+ int len;
+
+ if (av7110->debitype != -1)
+ /* we shouldn't get any irq while a debi xfer is running */
+ printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
+ jiffies, saa7146_read(av7110->dev, PSR),
+ saa7146_read(av7110->dev, SSR));
+
+ if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ BUG(); /* maybe we should try resetting the debi? */
+ }
+
+ spin_lock(&av7110->debilock);
+ ARM_ClearIrq(av7110);
+
+ /* see what the av7110 wants */
+ av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
+ av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ len = (av7110->debilen + 3) & ~3;
+
+ print_time("gpio");
+ dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
+
+ switch (av7110->debitype & 0xff) {
+
+ case DATA_TS_PLAY:
+ case DATA_PES_PLAY:
+ break;
+
+ case DATA_MPEG_VIDEO_EVENT:
+ {
+ u32 h_ar;
+ struct video_event event;
+
+ av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
+ h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
+
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+
+ av7110->video_size.h = h_ar & 0xfff;
+
+ event.type = VIDEO_EVENT_SIZE_CHANGED;
+ event.u.size.w = av7110->video_size.w;
+ event.u.size.h = av7110->video_size.h;
+ switch ((h_ar >> 12) & 0xf)
+ {
+ case 3:
+ av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
+ event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
+ av7110->videostate.video_format = VIDEO_FORMAT_16_9;
+ break;
+ case 4:
+ av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
+ event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
+ av7110->videostate.video_format = VIDEO_FORMAT_221_1;
+ break;
+ default:
+ av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
+ event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
+ av7110->videostate.video_format = VIDEO_FORMAT_4_3;
+ }
+
+ dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
+ av7110->video_size.w, av7110->video_size.h,
+ av7110->video_size.aspect_ratio);
+
+ dvb_video_add_event(av7110, &event);
+ break;
+ }
+
+ case DATA_CI_PUT:
+ {
+ int avail;
+ struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
+
+ avail = dvb_ringbuffer_avail(cibuf);
+ if (avail <= 2) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
+ len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
+ if (avail < len + 2) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ DVB_RINGBUFFER_SKIP(cibuf, 2);
+
+ dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
+
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ dprintk(8, "DMA: CI\n");
+ start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
+ spin_unlock(&av7110->debilock);
+ wake_up(&cibuf->queue);
+ return;
+ }
+
+ case DATA_MPEG_PLAY:
+ if (!av7110->playing) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ len = 0;
+ if (av7110->debitype & 0x100) {
+ spin_lock(&av7110->aout.lock);
+ len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
+ spin_unlock(&av7110->aout.lock);
+ }
+ if (len <= 0 && (av7110->debitype & 0x200)
+ &&av7110->videostate.play_state != VIDEO_FREEZED) {
+ spin_lock(&av7110->avout.lock);
+ len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
+ spin_unlock(&av7110->avout.lock);
+ }
+ if (len <= 0) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ dprintk(8, "DMA: MPEG_PLAY\n");
+ start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_BMP_LOAD:
+ len = av7110->debilen;
+ dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
+ if (!len) {
+ av7110->bmp_state = BMP_LOADED;
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ wake_up(&av7110->bmpq);
+ dprintk(8, "gpio DATA_BMP_LOAD done\n");
+ break;
+ }
+ if (len > av7110->bmplen)
+ len = av7110->bmplen;
+ if (len > 2 * 1024)
+ len = 2 * 1024;
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
+ av7110->bmpp += len;
+ av7110->bmplen -= len;
+ dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
+ start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_CI_GET:
+ case DATA_COMMON_INTERFACE:
+ case DATA_FSECTION:
+ case DATA_IPMPE:
+ case DATA_PIPING:
+ if (!len || len > 4 * 1024) {
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
+ }
+ fallthrough;
+
+ case DATA_TS_RECORD:
+ case DATA_PES_RECORD:
+ dprintk(8, "DMA: TS_REC etc.\n");
+ start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_DEBUG_MESSAGE:
+ if (!len || len > 0xff) {
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
+ }
+ start_debi_dma(av7110, DEBI_READ, Reserved, len);
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_IRCOMMAND:
+#if IS_ENABLED(CONFIG_DVB_AV7110_IR)
+ av7110_ir_handler(av7110,
+ swahw32(irdebi(av7110, DEBINOSWAP, Reserved,
+ 0, 4)));
+#endif
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
+
+ default:
+ printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
+ av7110->debitype, av7110->debilen);
+ break;
+ }
+ av7110->debitype = -1;
+ ARM_ClearMailBox(av7110);
+ spin_unlock(&av7110->debilock);
+}
+
+
+#ifdef CONFIG_DVB_AV7110_OSD
+static int dvb_osd_ioctl(struct file *file,
+ unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (cmd == OSD_SEND_CMD)
+ return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
+ if (cmd == OSD_GET_CAPABILITY)
+ return av7110_osd_capability(av7110, (osd_cap_t *) parg);
+
+ return -EINVAL;
+}
+
+
+static const struct file_operations dvb_osd_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dvb_generic_ioctl,
+ .open = dvb_generic_open,
+ .release = dvb_generic_release,
+ .llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_osd = {
+ .priv = NULL,
+ .users = 1,
+ .writers = 1,
+ .fops = &dvb_osd_fops,
+ .kernel_ioctl = dvb_osd_ioctl,
+};
+#endif /* CONFIG_DVB_AV7110_OSD */
+
+
+static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
+ u16 subpid, u16 pcrpid)
+{
+ u16 aflags = 0;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (vpid == 0x1fff || apid == 0x1fff ||
+ ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
+ vpid = apid = ttpid = subpid = pcrpid = 0;
+ av7110->pids[DMX_PES_VIDEO] = 0;
+ av7110->pids[DMX_PES_AUDIO] = 0;
+ av7110->pids[DMX_PES_TELETEXT] = 0;
+ av7110->pids[DMX_PES_PCR] = 0;
+ }
+
+ if (av7110->audiostate.bypass_mode)
+ aflags |= 0x8000;
+
+ return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
+ pcrpid, vpid, apid, ttpid, subpid, aflags);
+}
+
+int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
+ u16 subpid, u16 pcrpid)
+{
+ int ret = 0;
+ dprintk(4, "%p\n", av7110);
+
+ if (mutex_lock_interruptible(&av7110->pid_mutex))
+ return -ERESTARTSYS;
+
+ if (!(vpid & 0x8000))
+ av7110->pids[DMX_PES_VIDEO] = vpid;
+ if (!(apid & 0x8000))
+ av7110->pids[DMX_PES_AUDIO] = apid;
+ if (!(ttpid & 0x8000))
+ av7110->pids[DMX_PES_TELETEXT] = ttpid;
+ if (!(pcrpid & 0x8000))
+ av7110->pids[DMX_PES_PCR] = pcrpid;
+
+ av7110->pids[DMX_PES_SUBTITLE] = 0;
+
+ if (av7110->fe_synced) {
+ pcrpid = av7110->pids[DMX_PES_PCR];
+ ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
+ }
+
+ mutex_unlock(&av7110->pid_mutex);
+ return ret;
+}
+
+
+/******************************************************************************
+ * hardware filter functions
+ ******************************************************************************/
+
+static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+{
+ struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
+ struct av7110 *av7110 = dvbdmxfeed->demux->priv;
+ u16 buf[20];
+ int ret, i;
+ u16 handle;
+// u16 mode = 0x0320;
+ u16 mode = 0xb96a;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (av7110->full_ts)
+ return 0;
+
+ if (dvbdmxfilter->type == DMX_TYPE_SEC) {
+ if (hw_sections) {
+ buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
+ dvbdmxfilter->maskandmode[0];
+ for (i = 3; i < 18; i++)
+ buf[i + 4 - 2] =
+ (dvbdmxfilter->filter.filter_value[i] << 8) |
+ dvbdmxfilter->maskandmode[i];
+ mode = 4;
+ }
+ } else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
+ !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
+ av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
+ }
+
+ buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
+ buf[1] = 16;
+ buf[2] = dvbdmxfeed->pid;
+ buf[3] = mode;
+
+ ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
+ if (ret != 0 || handle >= 32) {
+ printk(KERN_ERR "dvb-ttpci: %s error buf %04x %04x %04x %04x ret %d handle %04x\n",
+ __func__, buf[0], buf[1], buf[2], buf[3],
+ ret, handle);
+ dvbdmxfilter->hw_handle = 0xffff;
+ if (!ret)
+ ret = -1;
+ return ret;
+ }
+
+ av7110->handle2filter[handle] = dvbdmxfilter;
+ dvbdmxfilter->hw_handle = handle;
+
+ return ret;
+}
+
+static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+{
+ struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
+ u16 buf[3];
+ u16 answ[2];
+ int ret;
+ u16 handle;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (av7110->full_ts)
+ return 0;
+
+ handle = dvbdmxfilter->hw_handle;
+ if (handle >= 32) {
+ printk("%s tried to stop invalid filter %04x, filter type = %x\n",
+ __func__, handle, dvbdmxfilter->type);
+ return -EINVAL;
+ }
+
+ av7110->handle2filter[handle] = NULL;
+
+ buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
+ buf[1] = 1;
+ buf[2] = handle;
+ ret = av7110_fw_request(av7110, buf, 3, answ, 2);
+ if (ret != 0 || answ[1] != handle) {
+ printk(KERN_ERR "dvb-ttpci: %s error cmd %04x %04x %04x ret %x resp %04x %04x pid %d\n",
+ __func__, buf[0], buf[1], buf[2], ret,
+ answ[0], answ[1], dvbdmxfilter->feed->pid);
+ if (!ret)
+ ret = -1;
+ }
+ return ret;
+}
+
+
+static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ struct av7110 *av7110 = dvbdmx->priv;
+ u16 *pid = dvbdmx->pids, npids[5];
+ int i;
+ int ret = 0;
+
+ dprintk(4, "%p\n", av7110);
+
+ npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
+ i = dvbdmxfeed->pes_type;
+ npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
+ if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
+ npids[i] = 0;
+ ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+ if (!ret)
+ ret = StartHWFilter(dvbdmxfeed->filter);
+ return ret;
+ }
+ if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
+ ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+ if (ret)
+ return ret;
+ }
+
+ if (dvbdmxfeed->pes_type < 2 && npids[0])
+ if (av7110->fe_synced)
+ {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+ if (ret)
+ return ret;
+ }
+
+ if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
+ if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
+ ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
+ if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
+ ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
+ }
+ return ret;
+}
+
+static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ struct av7110 *av7110 = dvbdmx->priv;
+ u16 *pid = dvbdmx->pids, npids[5];
+ int i;
+
+ int ret = 0;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (dvbdmxfeed->pes_type <= 1) {
+ ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
+ if (ret)
+ return ret;
+ if (!av7110->rec_mode)
+ dvbdmx->recording = 0;
+ if (!av7110->playing)
+ dvbdmx->playing = 0;
+ }
+ npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
+ i = dvbdmxfeed->pes_type;
+ switch (i) {
+ case 2: //teletext
+ if (dvbdmxfeed->ts_type & TS_PACKET)
+ ret = StopHWFilter(dvbdmxfeed->filter);
+ npids[2] = 0;
+ break;
+ case 0:
+ case 1:
+ case 4:
+ if (!pids_off)
+ return 0;
+ npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
+ break;
+ }
+ if (!ret)
+ ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+ return ret;
+}
+
+static int av7110_start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct av7110 *av7110 = demux->priv;
+ int ret = 0;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (!demux->dmx.frontend)
+ return -EINVAL;
+
+ if (!av7110->full_ts && feed->pid > 0x1fff)
+ return -EINVAL;
+
+ if (feed->type == DMX_TYPE_TS) {
+ if ((feed->ts_type & TS_DECODER) &&
+ (feed->pes_type <= DMX_PES_PCR)) {
+ switch (demux->dmx.frontend->source) {
+ case DMX_MEMORY_FE:
+ if (feed->ts_type & TS_DECODER)
+ if (feed->pes_type < 2 &&
+ !(demux->pids[0] & 0x8000) &&
+ !(demux->pids[1] & 0x8000)) {
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ ret = av7110_av_start_play(av7110,RP_AV);
+ if (!ret)
+ demux->playing = 1;
+ }
+ break;
+ default:
+ ret = dvb_feed_start_pid(feed);
+ break;
+ }
+ } else if ((feed->ts_type & TS_PACKET) &&
+ (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
+ ret = StartHWFilter(feed->filter);
+ }
+ }
+
+ if (av7110->full_ts) {
+ budget_start_feed(feed);
+ return ret;
+ }
+
+ if (feed->type == DMX_TYPE_SEC) {
+ int i;
+
+ for (i = 0; i < demux->filternum; i++) {
+ if (demux->filter[i].state != DMX_STATE_READY)
+ continue;
+ if (demux->filter[i].type != DMX_TYPE_SEC)
+ continue;
+ if (demux->filter[i].filter.parent != &feed->feed.sec)
+ continue;
+ demux->filter[i].state = DMX_STATE_GO;
+ if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
+ ret = StartHWFilter(&demux->filter[i]);
+ if (ret)
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+static int av7110_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct av7110 *av7110 = demux->priv;
+ int i, rc, ret = 0;
+ dprintk(4, "%p\n", av7110);
+
+ if (feed->type == DMX_TYPE_TS) {
+ if (feed->ts_type & TS_DECODER) {
+ if (feed->pes_type >= DMX_PES_OTHER ||
+ !demux->pesfilter[feed->pes_type])
+ return -EINVAL;
+ demux->pids[feed->pes_type] |= 0x8000;
+ demux->pesfilter[feed->pes_type] = NULL;
+ }
+ if (feed->ts_type & TS_DECODER &&
+ feed->pes_type < DMX_PES_OTHER) {
+ ret = dvb_feed_stop_pid(feed);
+ } else
+ if ((feed->ts_type & TS_PACKET) &&
+ (demux->dmx.frontend->source != DMX_MEMORY_FE))
+ ret = StopHWFilter(feed->filter);
+ }
+
+ if (av7110->full_ts) {
+ budget_stop_feed(feed);
+ return ret;
+ }
+
+ if (feed->type == DMX_TYPE_SEC) {
+ for (i = 0; i<demux->filternum; i++) {
+ if (demux->filter[i].state == DMX_STATE_GO &&
+ demux->filter[i].filter.parent == &feed->feed.sec) {
+ demux->filter[i].state = DMX_STATE_READY;
+ if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
+ rc = StopHWFilter(&demux->filter[i]);
+ if (!ret)
+ ret = rc;
+ /* keep going, stop as many filters as possible */
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+static void restart_feeds(struct av7110 *av7110)
+{
+ struct dvb_demux *dvbdmx = &av7110->demux;
+ struct dvb_demux_feed *feed;
+ int mode;
+ int feeding;
+ int i, j;
+
+ dprintk(4, "%p\n", av7110);
+
+ mode = av7110->playing;
+ av7110->playing = 0;
+ av7110->rec_mode = 0;
+
+ feeding = av7110->feeding1; /* full_ts mod */
+
+ for (i = 0; i < dvbdmx->feednum; i++) {
+ feed = &dvbdmx->feed[i];
+ if (feed->state == DMX_STATE_GO) {
+ if (feed->type == DMX_TYPE_SEC) {
+ for (j = 0; j < dvbdmx->filternum; j++) {
+ if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
+ continue;
+ if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
+ continue;
+ if (dvbdmx->filter[j].state == DMX_STATE_GO)
+ dvbdmx->filter[j].state = DMX_STATE_READY;
+ }
+ }
+ av7110_start_feed(feed);
+ }
+ }
+
+ av7110->feeding1 = feeding; /* full_ts mod */
+
+ if (mode)
+ av7110_av_start_play(av7110, mode);
+}
+
+static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
+ uint64_t *stc, unsigned int *base)
+{
+ int ret;
+ u16 fwstc[4];
+ u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
+ struct dvb_demux *dvbdemux;
+ struct av7110 *av7110;
+
+ /* pointer casting paranoia... */
+ BUG_ON(!demux);
+ dvbdemux = demux->priv;
+ BUG_ON(!dvbdemux);
+ av7110 = dvbdemux->priv;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (num != 0)
+ return -EINVAL;
+
+ ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
+ if (ret) {
+ printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
+ return ret;
+ }
+ dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
+ fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
+
+ *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
+ (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
+ *base = 1;
+
+ dprintk(4, "stc = %lu\n", (unsigned long)*stc);
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * SEC device file operations
+ ******************************************************************************/
+
+
+static int av7110_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ return Set22K(av7110, 1);
+
+ case SEC_TONE_OFF:
+ return Set22K(av7110, 0);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd* cmd)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
+}
+
+static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
+ enum fe_sec_mini_cmd minicmd)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ return av7110_diseqc_send(av7110, 0, NULL, minicmd);
+}
+
+/* simplified code from budget-core.c */
+static int stop_ts_capture(struct av7110 *budget)
+{
+ dprintk(2, "budget: %p\n", budget);
+
+ if (--budget->feeding1)
+ return budget->feeding1;
+ saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */
+ SAA7146_IER_DISABLE(budget->dev, MASK_10);
+ SAA7146_ISR_CLEAR(budget->dev, MASK_10);
+ return 0;
+}
+
+static int start_ts_capture(struct av7110 *budget)
+{
+ unsigned y;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ if (budget->feeding1)
+ return ++budget->feeding1;
+ for (y = 0; y < TS_HEIGHT; y++)
+ memset(budget->grabbing + y * TS_WIDTH, 0x00, TS_WIDTH);
+ budget->ttbp = 0;
+ SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
+ SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
+ saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
+ return ++budget->feeding1;
+}
+
+static int budget_start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct av7110 *budget = demux->priv;
+ int status;
+
+ dprintk(2, "av7110: %p\n", budget);
+
+ spin_lock(&budget->feedlock1);
+ feed->pusi_seen = false; /* have a clean section start */
+ status = start_ts_capture(budget);
+ spin_unlock(&budget->feedlock1);
+ return status;
+}
+
+static int budget_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct av7110 *budget = demux->priv;
+ int status;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ spin_lock(&budget->feedlock1);
+ status = stop_ts_capture(budget);
+ spin_unlock(&budget->feedlock1);
+ return status;
+}
+
+static void vpeirq(struct tasklet_struct *t)
+{
+ struct av7110 *budget = from_tasklet(budget, t, vpe_tasklet);
+ u8 *mem = (u8 *) (budget->grabbing);
+ u32 olddma = budget->ttbp;
+ u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+ struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
+
+ /* nearest lower position divisible by 188 */
+ newdma -= newdma % 188;
+
+ if (newdma >= TS_BUFLEN)
+ return;
+
+ budget->ttbp = newdma;
+
+ if (!budget->feeding1 || (newdma == olddma))
+ return;
+
+ /* Ensure streamed PCI data is synced to CPU */
+ dma_sync_sg_for_cpu(&budget->dev->pci->dev, budget->pt.slist,
+ budget->pt.nents, DMA_FROM_DEVICE);
+
+#if 0
+ /* track rps1 activity */
+ printk("vpeirq: %02x Event Counter 1 0x%04x\n",
+ mem[olddma],
+ saa7146_read(budget->dev, EC1R) & 0x3fff);
+#endif
+
+ if (newdma > olddma)
+ /* no wraparound, dump olddma..newdma */
+ dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
+ else {
+ /* wraparound, dump olddma..buflen and 0..newdma */
+ dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+ dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
+ }
+}
+
+static int av7110_register(struct av7110 *av7110)
+{
+ int ret, i;
+ struct dvb_demux *dvbdemux = &av7110->demux;
+ struct dvb_demux *dvbdemux1 = &av7110->demux1;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (av7110->registered)
+ return -1;
+
+ av7110->registered = 1;
+
+ dvbdemux->priv = (void *) av7110;
+
+ for (i = 0; i < 32; i++)
+ av7110->handle2filter[i] = NULL;
+
+ dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
+ dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
+ dvbdemux->start_feed = av7110_start_feed;
+ dvbdemux->stop_feed = av7110_stop_feed;
+ dvbdemux->write_to_decoder = av7110_write_to_decoder;
+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING);
+
+ dvb_dmx_init(&av7110->demux);
+ av7110->demux.dmx.get_stc = dvb_get_stc;
+
+ av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
+ av7110->dmxdev.demux = &dvbdemux->dmx;
+ av7110->dmxdev.capabilities = 0;
+
+ dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
+
+ av7110->hw_frontend.source = DMX_FRONTEND_0;
+
+ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
+
+ if (ret < 0)
+ return ret;
+
+ av7110->mem_frontend.source = DMX_MEMORY_FE;
+
+ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
+
+ if (ret < 0)
+ return ret;
+
+ ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
+ &av7110->hw_frontend);
+ if (ret < 0)
+ return ret;
+
+ av7110_av_register(av7110);
+ av7110_ca_register(av7110);
+
+#ifdef CONFIG_DVB_AV7110_OSD
+ dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
+ &dvbdev_osd, av7110, DVB_DEVICE_OSD, 0);
+#endif
+
+ dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
+
+ if (budgetpatch) {
+ /* initialize software demux1 without its own frontend
+ * demux1 hardware is connected to frontend0 of demux0
+ */
+ dvbdemux1->priv = (void *) av7110;
+
+ dvbdemux1->filternum = 256;
+ dvbdemux1->feednum = 256;
+ dvbdemux1->start_feed = budget_start_feed;
+ dvbdemux1->stop_feed = budget_stop_feed;
+ dvbdemux1->write_to_decoder = NULL;
+
+ dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING);
+
+ dvb_dmx_init(&av7110->demux1);
+
+ av7110->dmxdev1.filternum = 256;
+ av7110->dmxdev1.demux = &dvbdemux1->dmx;
+ av7110->dmxdev1.capabilities = 0;
+
+ dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
+
+ dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
+ printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
+ }
+ return 0;
+}
+
+
+static void dvb_unregister(struct av7110 *av7110)
+{
+ struct dvb_demux *dvbdemux = &av7110->demux;
+ struct dvb_demux *dvbdemux1 = &av7110->demux1;
+
+ dprintk(4, "%p\n", av7110);
+
+ if (!av7110->registered)
+ return;
+
+ if (budgetpatch) {
+ dvb_net_release(&av7110->dvb_net1);
+ dvbdemux->dmx.close(&dvbdemux1->dmx);
+ dvb_dmxdev_release(&av7110->dmxdev1);
+ dvb_dmx_release(&av7110->demux1);
+ }
+
+ dvb_net_release(&av7110->dvb_net);
+
+ dvbdemux->dmx.close(&dvbdemux->dmx);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
+
+ dvb_dmxdev_release(&av7110->dmxdev);
+ dvb_dmx_release(&av7110->demux);
+
+ if (av7110->fe != NULL) {
+ dvb_unregister_frontend(av7110->fe);
+ dvb_frontend_detach(av7110->fe);
+ }
+ dvb_unregister_device(av7110->osd_dev);
+ av7110_av_unregister(av7110);
+ av7110_ca_unregister(av7110);
+}
+
+
+/****************************************************************************
+ * I2C client commands
+ ****************************************************************************/
+
+int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
+{
+ u8 msg[2] = { reg, val };
+ struct i2c_msg msgs;
+
+ msgs.flags = 0;
+ msgs.addr = id / 2;
+ msgs.len = 2;
+ msgs.buf = msg;
+ return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
+}
+
+u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
+{
+ u8 mm1[] = {0x00};
+ u8 mm2[] = {0x00};
+ struct i2c_msg msgs[2];
+
+ msgs[0].flags = 0;
+ msgs[1].flags = I2C_M_RD;
+ msgs[0].addr = msgs[1].addr = id / 2;
+ mm1[0] = reg;
+ msgs[0].len = 1; msgs[1].len = 1;
+ msgs[0].buf = mm1; msgs[1].buf = mm2;
+ i2c_transfer(&av7110->i2c_adap, msgs, 2);
+
+ return mm2[0];
+}
+
+/****************************************************************************
+ * INITIALIZATION
+ ****************************************************************************/
+
+
+static int check_firmware(struct av7110* av7110)
+{
+ u32 crc = 0, len = 0;
+ unsigned char *ptr;
+
+ /* check for firmware magic */
+ ptr = av7110->bin_fw;
+ if (ptr[0] != 'A' || ptr[1] != 'V' ||
+ ptr[2] != 'F' || ptr[3] != 'W') {
+ printk("dvb-ttpci: this is not an av7110 firmware\n");
+ return -EINVAL;
+ }
+ ptr += 4;
+
+ /* check dpram file */
+ crc = get_unaligned_be32(ptr);
+ ptr += 4;
+ len = get_unaligned_be32(ptr);
+ ptr += 4;
+ if (len >= 512) {
+ printk("dvb-ttpci: dpram file is way too big.\n");
+ return -EINVAL;
+ }
+ if (crc != crc32_le(0, ptr, len)) {
+ printk("dvb-ttpci: crc32 of dpram file does not match.\n");
+ return -EINVAL;
+ }
+ av7110->bin_dpram = ptr;
+ av7110->size_dpram = len;
+ ptr += len;
+
+ /* check root file */
+ crc = get_unaligned_be32(ptr);
+ ptr += 4;
+ len = get_unaligned_be32(ptr);
+ ptr += 4;
+
+ if (len <= 200000 || len >= 300000 ||
+ len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
+ printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
+ return -EINVAL;
+ }
+ if( crc != crc32_le(0, ptr, len)) {
+ printk("dvb-ttpci: crc32 of root file does not match.\n");
+ return -EINVAL;
+ }
+ av7110->bin_root = ptr;
+ av7110->size_root = len;
+ return 0;
+}
+
+static void put_firmware(struct av7110* av7110)
+{
+ vfree(av7110->bin_fw);
+}
+
+static int get_firmware(struct av7110* av7110)
+{
+ int ret;
+ const struct firmware *fw;
+
+ /* request the av7110 firmware, this will block until someone uploads it */
+ ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
+ if (ret) {
+ if (ret == -ENOENT) {
+ printk(KERN_ERR "dvb-ttpci: could not load firmware, file not found: dvb-ttpci-01.fw\n");
+ printk(KERN_ERR "dvb-ttpci: usually this should be in /usr/lib/hotplug/firmware or /lib/firmware\n");
+ printk(KERN_ERR "dvb-ttpci: and can be downloaded from https://linuxtv.org/download/dvb/firmware/\n");
+ } else
+ printk(KERN_ERR "dvb-ttpci: cannot request firmware (error %i)\n",
+ ret);
+ return -EINVAL;
+ }
+
+ if (fw->size <= 200000) {
+ printk("dvb-ttpci: this firmware is way too small.\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+
+ /* check if the firmware is available */
+ av7110->bin_fw = vmalloc(fw->size);
+ if (NULL == av7110->bin_fw) {
+ dprintk(1, "out of memory\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ memcpy(av7110->bin_fw, fw->data, fw->size);
+ av7110->size_fw = fw->size;
+ if ((ret = check_firmware(av7110)))
+ vfree(av7110->bin_fw);
+
+ release_firmware(fw);
+ return ret;
+}
+
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u8 pwr = 0;
+ u8 buf[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ u32 div = (p->frequency + 479500) / 125;
+
+ if (p->frequency > 2000000)
+ pwr = 3;
+ else if (p->frequency > 1800000)
+ pwr = 2;
+ else if (p->frequency > 1600000)
+ pwr = 1;
+ else if (p->frequency > 1200000)
+ pwr = 0;
+ else if (p->frequency >= 1100000)
+ pwr = 1;
+ else
+ pwr = 2;
+
+ buf[0] = (div >> 8) & 0x7f;
+ buf[1] = div & 0xff;
+ buf[2] = ((div & 0x18000) >> 10) | 0x95;
+ buf[3] = (pwr << 6) | 0x30;
+
+ // NOTE: since we're using a prescaler of 2, we set the
+ // divisor frequency to 62.5kHz and divide by 125 above
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct ves1x93_config alps_bsrv2_config = {
+ .demod_address = 0x08,
+ .xin = 90100000UL,
+ .invert_pwm = 0,
+};
+
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = (p->frequency + 35937500 + 31250) / 62500;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x85 | ((div >> 10) & 0x60);
+ data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct ves1820_config alps_tdbe2_config = {
+ .demod_address = 0x09,
+ .xin = 57840000UL,
+ .invert = 1,
+ .selagc = VES1820_SELAGC_SIGNAMPERR,
+};
+
+
+
+
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = p->frequency / 125;
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x8e;
+ data[3] = 0x00;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct tda8083_config grundig_29504_451_config = {
+ .demod_address = 0x68,
+};
+
+
+
+static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div;
+ u32 f = p->frequency;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = (f + 36125000 + 31250) / 62500;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x8e;
+ data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct ves1820_config philips_cd1516_config = {
+ .demod_address = 0x09,
+ .xin = 57840000UL,
+ .invert = 1,
+ .selagc = VES1820_SELAGC_SIGNAMPERR,
+};
+
+
+
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div, pwr;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = (p->frequency + 36200000) / 166666;
+
+ if (p->frequency <= 782000000)
+ pwr = 1;
+ else
+ pwr = 2;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x85;
+ data[3] = pwr << 6;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+{
+#if IS_ENABLED(CONFIG_DVB_SP8870)
+ struct av7110* av7110 = fe->dvb->priv;
+
+ return request_firmware(fw, name, &av7110->dev->pci->dev);
+#else
+ return -EINVAL;
+#endif
+}
+
+static const struct sp8870_config alps_tdlb7_config = {
+
+ .demod_address = 0x71,
+ .request_firmware = alps_tdlb7_request_firmware,
+};
+
+
+static u8 nexusca_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0x7b,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
+
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
+ struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
+ int i;
+
+ div = (p->frequency + 36150000 + 31250) / 62500;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0xce;
+
+ if (p->frequency < 45000000)
+ return -EINVAL;
+ else if (p->frequency < 137000000)
+ data[3] = 0x01;
+ else if (p->frequency < 403000000)
+ data[3] = 0x02;
+ else if (p->frequency < 860000000)
+ data[3] = 0x04;
+ else
+ return -EINVAL;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
+ printk("nexusca: pll transfer failed!\n");
+ return -EIO;
+ }
+
+ // wait for PLL lock
+ for(i = 0; i < 20; i++) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
+ if (data[0] & 0x40) break;
+ msleep(10);
+ }
+
+ return 0;
+}
+
+static struct stv0297_config nexusca_stv0297_config = {
+
+ .demod_address = 0x1C,
+ .inittab = nexusca_stv0297_inittab,
+ .invert = 1,
+ .stop_during_read = 1,
+};
+
+
+
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct av7110* av7110 = fe->dvb->priv;
+ u32 div;
+ u8 cfg, cpump, band_select;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = (36125000 + p->frequency) / 166666;
+
+ cfg = 0x88;
+
+ if (p->frequency < 175000000)
+ cpump = 2;
+ else if (p->frequency < 390000000)
+ cpump = 1;
+ else if (p->frequency < 470000000)
+ cpump = 2;
+ else if (p->frequency < 750000000)
+ cpump = 1;
+ else
+ cpump = 3;
+
+ if (p->frequency < 175000000)
+ band_select = 0x0e;
+ else if (p->frequency < 470000000)
+ band_select = 0x05;
+ else
+ band_select = 0x03;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = ((div >> 10) & 0x60) | cfg;
+ data[3] = (cpump << 6) | band_select;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
+ return 0;
+}
+
+static struct l64781_config grundig_29504_401_config = {
+ .demod_address = 0x55,
+};
+
+
+
+static int av7110_fe_lock_fix(struct av7110 *av7110, enum fe_status status)
+{
+ int ret = 0;
+ int synced = (status & FE_HAS_LOCK) ? 1 : 0;
+
+ av7110->fe_status = status;
+
+ if (av7110->fe_synced == synced)
+ return 0;
+
+ if (av7110->playing) {
+ av7110->fe_synced = synced;
+ return 0;
+ }
+
+ if (mutex_lock_interruptible(&av7110->pid_mutex))
+ return -ERESTARTSYS;
+
+ if (synced) {
+ ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
+ av7110->pids[DMX_PES_AUDIO],
+ av7110->pids[DMX_PES_TELETEXT], 0,
+ av7110->pids[DMX_PES_PCR]);
+ if (!ret)
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+ } else {
+ ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
+ if (!ret) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
+ if (!ret)
+ ret = av7110_wait_msgstate(av7110, GPMQBusy);
+ }
+ }
+
+ if (!ret)
+ av7110->fe_synced = synced;
+
+ mutex_unlock(&av7110->pid_mutex);
+ return ret;
+}
+
+static int av7110_fe_set_frontend(struct dvb_frontend *fe)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret)
+ ret = av7110->fe_set_frontend(fe);
+
+ return ret;
+}
+
+static int av7110_fe_init(struct dvb_frontend* fe)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret)
+ ret = av7110->fe_init(fe);
+ return ret;
+}
+
+static int av7110_fe_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ /* call the real implementation */
+ int ret = av7110->fe_read_status(fe, status);
+ if (!ret)
+ if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
+ ret = av7110_fe_lock_fix(av7110, *status);
+ return ret;
+}
+
+static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret)
+ ret = av7110->fe_diseqc_reset_overload(fe);
+ return ret;
+}
+
+static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd* cmd)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret) {
+ av7110->saved_master_cmd = *cmd;
+ ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
+ }
+ return ret;
+}
+
+static int av7110_fe_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret) {
+ av7110->saved_minicmd = minicmd;
+ ret = av7110->fe_diseqc_send_burst(fe, minicmd);
+ }
+ return ret;
+}
+
+static int av7110_fe_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret) {
+ av7110->saved_tone = tone;
+ ret = av7110->fe_set_tone(fe, tone);
+ }
+ return ret;
+}
+
+static int av7110_fe_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret) {
+ av7110->saved_voltage = voltage;
+ ret = av7110->fe_set_voltage(fe, voltage);
+ }
+ return ret;
+}
+
+static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
+{
+ struct av7110* av7110 = fe->dvb->priv;
+
+ int ret = av7110_fe_lock_fix(av7110, 0);
+ if (!ret)
+ ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
+ return ret;
+}
+
+static void dvb_s_recover(struct av7110* av7110)
+{
+ av7110_fe_init(av7110->fe);
+
+ av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
+ if (av7110->saved_master_cmd.msg_len) {
+ msleep(20);
+ av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
+ }
+ msleep(20);
+ av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
+ msleep(20);
+ av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
+
+ av7110_fe_set_frontend(av7110->fe);
+}
+
+static u8 read_pwm(struct av7110* av7110)
+{
+ u8 b = 0xff;
+ u8 pwm;
+ struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
+ { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
+
+ if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
+ pwm = 0x48;
+
+ return pwm;
+}
+
+static int frontend_init(struct av7110 *av7110)
+{
+ int ret;
+
+ if (av7110->dev->pci->subsystem_vendor == 0x110a) {
+ switch(av7110->dev->pci->subsystem_device) {
+ case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
+ av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
+ &av7110->i2c_adap, read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+ }
+ break;
+ }
+
+ } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
+ switch(av7110->dev->pci->subsystem_device) {
+ case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
+ case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
+ case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
+
+ // try the ALPS BSRV2 first of all
+ av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ break;
+ }
+
+ // try the ALPS BSRU6 now
+ av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ break;
+ }
+
+ // Try the grundig 29504-451
+ av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ break;
+ }
+
+ /* Try DVB-C cards */
+ switch(av7110->dev->pci->subsystem_device) {
+ case 0x0000:
+ /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
+ av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
+ read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+ }
+ break;
+ case 0x0003:
+ /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
+ av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
+ read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ }
+ break;
+ }
+ break;
+
+ case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
+ {
+ struct dvb_frontend *fe;
+
+ // try ALPS TDLB7 first, then Grundig 29504-401
+ fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+ av7110->fe = fe;
+ break;
+ }
+ }
+ fallthrough;
+
+ case 0x0008: // Hauppauge/TT DVB-T
+ // Grundig 29504-401
+ av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
+ if (av7110->fe)
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+ break;
+
+ case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
+
+ av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ }
+ break;
+
+ case 0x0004: // Galaxis DVB-S rev1.3
+ /* ALPS BSRV2 */
+ av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ }
+ break;
+
+ case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
+ /* Grundig 29504-451 */
+ av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ }
+ break;
+
+ case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
+
+ av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
+
+ /* set TDA9819 into DVB mode */
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
+
+ /* tuner on this needs a slower i2c bus speed */
+ av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
+ break;
+ }
+ break;
+
+ case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
+ /* ALPS BSBE1 */
+ av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+ av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+ if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
+ printk("dvb-ttpci: LNBP21 not found!\n");
+ if (av7110->fe->ops.release)
+ av7110->fe->ops.release(av7110->fe);
+ av7110->fe = NULL;
+ } else {
+ av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
+ av7110->recover = dvb_s_recover;
+ }
+ }
+ break;
+ }
+ }
+
+ if (!av7110->fe) {
+ /* FIXME: propagate the failure code from the lower layers */
+ ret = -ENOMEM;
+ printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ av7110->dev->pci->vendor,
+ av7110->dev->pci->device,
+ av7110->dev->pci->subsystem_vendor,
+ av7110->dev->pci->subsystem_device);
+ } else {
+ FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
+
+ ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
+ if (ret < 0) {
+ printk("av7110: Frontend registration failed!\n");
+ dvb_frontend_detach(av7110->fe);
+ av7110->fe = NULL;
+ }
+ }
+ return ret;
+}
+
+/* Budgetpatch note:
+ * Original hardware design by Roberto Deza:
+ * There is a DVB_Wiki at
+ * https://linuxtv.org
+ *
+ * New software triggering design by Emard that works on
+ * original Roberto Deza's hardware:
+ *
+ * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
+ * GPIO3 is in budget-patch hardware connectd to port B VSYNC
+ * HS is an internal event of 7146, accessible with RPS
+ * and temporarily raised high every n lines
+ * (n in defined in the RPS_THRESH1 counter threshold)
+ * I think HS is raised high on the beginning of the n-th line
+ * and remains high until this n-th line that triggered
+ * it is completely received. When the reception of n-th line
+ * ends, HS is lowered.
+ *
+ * To transmit data over DMA, 7146 needs changing state at
+ * port B VSYNC pin. Any changing of port B VSYNC will
+ * cause some DMA data transfer, with more or less packets loss.
+ * It depends on the phase and frequency of VSYNC and
+ * the way of 7146 is instructed to trigger on port B (defined
+ * in DD1_INIT register, 3rd nibble from the right valid
+ * numbers are 0-7, see datasheet)
+ *
+ * The correct triggering can minimize packet loss,
+ * dvbtraffic should give this stable bandwidths:
+ * 22k transponder = 33814 kbit/s
+ * 27.5k transponder = 38045 kbit/s
+ * by experiment it is found that the best results
+ * (stable bandwidths and almost no packet loss)
+ * are obtained using DD1_INIT triggering number 2
+ * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
+ * and a VSYNC phase that occurs in the middle of DMA transfer
+ * (about byte 188*512=96256 in the DMA window).
+ *
+ * Phase of HS is still not clear to me how to control,
+ * It just happens to be so. It can be seen if one enables
+ * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
+ * time RPS_INTERRUPT is called, the Event Counter 1 will
+ * increment. That's how the 7146 is programmed to do event
+ * counting in this budget-patch.c
+ * I *think* HPS setting has something to do with the phase
+ * of HS but I can't be 100% sure in that.
+ *
+ * hardware debug note: a working budget card (including budget patch)
+ * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
+ * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
+ * and that means 3*25=75 Hz of interrupt frequency, as seen by
+ * watch cat /proc/interrupts
+ *
+ * If this frequency is 3x lower (and data received in the DMA
+ * buffer don't start with 0x47, but in the middle of packets,
+ * whose lengths appear to be like 188 292 188 104 etc.
+ * this means VSYNC line is not connected in the hardware.
+ * (check soldering pcb and pins)
+ * The same behaviour of missing VSYNC can be duplicated on budget
+ * cards, by setting DD1_INIT trigger mode 7 in 3rd nibble.
+ */
+static int av7110_attach(struct saa7146_dev* dev,
+ struct saa7146_pci_extension_data *pci_ext)
+{
+ const int length = TS_WIDTH * TS_HEIGHT;
+ struct pci_dev *pdev = dev->pci;
+ struct av7110 *av7110;
+ struct task_struct *thread;
+ int ret, count = 0;
+
+ dprintk(4, "dev: %p\n", dev);
+
+ /* Set RPS_IRQ to 1 to track rps1 activity.
+ * Enabling this won't send any interrupt to PC CPU.
+ */
+#define RPS_IRQ 0
+
+ if (budgetpatch == 1) {
+ budgetpatch = 0;
+ /* autodetect the presence of budget patch
+ * this only works if saa7146 has been recently
+ * reset with with MASK_31 to MC1
+ *
+ * will wait for VBI_B event (vertical blank at port B)
+ * and will reset GPIO3 after VBI_B is detected.
+ * (GPIO3 should be raised high by CPU to
+ * test if GPIO3 will generate vertical blank signal
+ * in budget patch GPIO3 is connected to VSYNC_B
+ */
+
+ /* RESET SAA7146 */
+ saa7146_write(dev, MC1, MASK_31);
+ /* autodetection success seems to be time-dependend after reset */
+
+ /* Fix VSYNC level */
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ /* set vsync_b triggering */
+ saa7146_write(dev, DD1_STREAM_B, 0);
+ /* port B VSYNC at rising edge */
+ saa7146_write(dev, DD1_INIT, 0x00000200);
+ saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
+ saa7146_write(dev, MC2,
+ 1 * (MASK_08 | MASK_24) | // BRS control
+ 0 * (MASK_09 | MASK_25) | // a
+ 1 * (MASK_10 | MASK_26) | // b
+ 0 * (MASK_06 | MASK_22) | // HPS_CTRL1
+ 0 * (MASK_05 | MASK_21) | // HPS_CTRL2
+ 0 * (MASK_01 | MASK_15) // DEBI
+ );
+
+ /* start writing RPS1 code from beginning */
+ count = 0;
+ /* Disable RPS1 */
+ saa7146_write(dev, MC1, MASK_29);
+ /* RPS1 timeout disable */
+ saa7146_write(dev, RPS_TOV1, 0);
+ WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
+#if RPS_IRQ
+ /* issue RPS1 interrupt to increment counter */
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ WRITE_RPS1(CMD_STOP);
+ /* Jump to begin of RPS program as safety measure (p37) */
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
+
+#if RPS_IRQ
+ /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
+ * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
+ * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
+ */
+ saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
+ /* set event counter 1 threshold to maximum allowed value (rEC p55) */
+ saa7146_write(dev, ECT1R, 0x3fff );
+#endif
+ /* Set RPS1 Address register to point to RPS code (r108 p42) */
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+ /* Enable RPS1, (rFC p33) */
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
+
+ mdelay(10);
+ /* now send VSYNC_B to rps1 by rising GPIO3 */
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ mdelay(10);
+ /* if rps1 responded by lowering the GPIO3,
+ * then we have budgetpatch hardware
+ */
+ if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
+ budgetpatch = 1;
+ printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
+ }
+ /* Disable RPS1 */
+ saa7146_write(dev, MC1, ( MASK_29 ));
+#if RPS_IRQ
+ printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
+#endif
+ }
+
+ /* prepare the av7110 device struct */
+ av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
+ if (!av7110) {
+ dprintk(1, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ av7110->card_name = (char*) pci_ext->ext_priv;
+ av7110->dev = dev;
+ dev->ext_priv = av7110;
+
+ ret = get_firmware(av7110);
+ if (ret < 0)
+ goto err_kfree_0;
+
+ ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
+ THIS_MODULE, &dev->pci->dev, adapter_nr);
+ if (ret < 0)
+ goto err_put_firmware_1;
+
+ /* the Siemens DVB needs this if you want to have the i2c chips
+ get recognized before the main driver is fully loaded */
+ saa7146_write(dev, GPIO_CTRL, 0x500000);
+
+ strscpy(av7110->i2c_adap.name, pci_ext->ext_priv,
+ sizeof(av7110->i2c_adap.name));
+
+ saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
+
+ ret = i2c_add_adapter(&av7110->i2c_adap);
+ if (ret < 0)
+ goto err_dvb_unregister_adapter_2;
+
+ ttpci_eeprom_parse_mac(&av7110->i2c_adap,
+ av7110->dvb_adapter.proposed_mac);
+ ret = -ENOMEM;
+
+ /* full-ts mod? */
+ if (full_ts)
+ av7110->full_ts = true;
+
+ /* check for full-ts flag in eeprom */
+ if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
+ u8 flags = i2c_readreg(av7110, 0xaa, 2);
+ if (flags != 0xff && (flags & 0x01))
+ av7110->full_ts = true;
+ }
+
+ if (av7110->full_ts) {
+ printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
+ spin_lock_init(&av7110->feedlock1);
+ av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+ &av7110->pt);
+ if (!av7110->grabbing)
+ goto err_i2c_del_3;
+
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, MC2, (MASK_10 | MASK_26));
+
+ saa7146_write(dev, DD1_INIT, 0x00000600);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, MC2, MASK_08 | MASK_24);
+
+ /* dma3 */
+ saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, 0);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, PITCH3, TS_WIDTH);
+ saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
+ saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
+ saa7146_write(dev, MC2, MASK_04 | MASK_20);
+
+ tasklet_setup(&av7110->vpe_tasklet, vpeirq);
+
+ } else if (budgetpatch) {
+ spin_lock_init(&av7110->feedlock1);
+ av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+ &av7110->pt);
+ if (!av7110->grabbing)
+ goto err_i2c_del_3;
+
+ saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_INIT, 0x03000200);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, 0);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
+
+ saa7146_write(dev, PITCH3, TS_WIDTH);
+ saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
+
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
+#if RPS_IRQ
+ /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
+ * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
+ * use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
+ */
+ saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
+ /* set event counter 1 threshold to maximum allowed value (rEC p55) */
+ saa7146_write(dev, ECT1R, 0x3fff );
+#endif
+ /* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
+ count = 0;
+
+ /* Wait Source Line Counter Threshold (p36) */
+ WRITE_RPS1(CMD_PAUSE | EVT_HS);
+ /* Set GPIO3=1 (p42) */
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
+#if RPS_IRQ
+ /* issue RPS1 interrupt */
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ /* Wait reset Source Line Counter Threshold (p36) */
+ WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
+ /* Set GPIO3=0 (p42) */
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
+#if RPS_IRQ
+ /* issue RPS1 interrupt */
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ /* Jump to begin of RPS program (p37) */
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
+
+ /* Fix VSYNC level */
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ /* Set RPS1 Address register to point to RPS code (r108 p42) */
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+ /* Set Source Line Counter Threshold, using BRS (rCC p43)
+ * It generates HS event every TS_HEIGHT lines
+ * this is related to TS_WIDTH set in register
+ * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
+ * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
+ * then RPS_THRESH1 should be set to trigger
+ * every TS_HEIGHT (512) lines.
+ */
+ saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
+
+ /* Enable RPS1 (rFC p33) */
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
+ /* end of budgetpatch register initialization */
+ tasklet_setup(&av7110->vpe_tasklet, vpeirq);
+ } else {
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_INIT, 0x03000000);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
+ }
+
+ tasklet_setup(&av7110->debi_tasklet, debiirq);
+ tasklet_setup(&av7110->gpio_tasklet, gpioirq);
+
+ mutex_init(&av7110->pid_mutex);
+
+ /* locks for data transfers from/to AV7110 */
+ spin_lock_init(&av7110->debilock);
+ mutex_init(&av7110->dcomlock);
+ av7110->debitype = -1;
+
+ /* default OSD window */
+ av7110->osdwin = 1;
+ mutex_init(&av7110->osd_mutex);
+
+ /* TV standard */
+ av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
+ : AV7110_VIDEO_MODE_PAL;
+
+ /* ARM "watchdog" */
+ init_waitqueue_head(&av7110->arm_wait);
+ av7110->arm_thread = NULL;
+
+ /* allocate and init buffers */
+ av7110->debi_virt = dma_alloc_coherent(&pdev->dev, 8192,
+ &av7110->debi_bus, GFP_KERNEL);
+ if (!av7110->debi_virt)
+ goto err_saa71466_vfree_4;
+
+
+ av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
+ if (!av7110->iobuf)
+ goto err_pci_free_5;
+
+ ret = av7110_av_init(av7110);
+ if (ret < 0)
+ goto err_iobuf_vfree_6;
+
+ /* init BMP buffer */
+ av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
+ init_waitqueue_head(&av7110->bmpq);
+
+ ret = av7110_ca_init(av7110);
+ if (ret < 0)
+ goto err_av7110_av_exit_7;
+
+ /* load firmware into AV7110 cards */
+ ret = av7110_bootarm(av7110);
+ if (ret < 0)
+ goto err_av7110_ca_exit_8;
+
+ ret = av7110_firmversion(av7110);
+ if (ret < 0)
+ goto err_stop_arm_9;
+
+ if (FW_VERSION(av7110->arm_app)<0x2501)
+ printk(KERN_WARNING
+ "dvb-ttpci: Warning, firmware version 0x%04x is too old. System might be unstable!\n",
+ FW_VERSION(av7110->arm_app));
+
+ thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
+ if (IS_ERR(thread)) {
+ ret = PTR_ERR(thread);
+ goto err_stop_arm_9;
+ }
+ av7110->arm_thread = thread;
+
+ /* set initial volume in mixer struct */
+ av7110->mixer.volume_left = volume;
+ av7110->mixer.volume_right = volume;
+
+ ret = av7110_register(av7110);
+ if (ret < 0)
+ goto err_arm_thread_stop_10;
+
+ init_av7110_av(av7110);
+
+ /* special case DVB-C: these cards have an analog tuner
+ plus need some special handling, so we have separate
+ saa7146_ext_vv data for these... */
+ ret = av7110_init_v4l(av7110);
+ if (ret < 0)
+ goto err_av7110_unregister_11;
+
+ av7110->dvb_adapter.priv = av7110;
+ ret = frontend_init(av7110);
+ if (ret < 0)
+ goto err_av7110_exit_v4l_12;
+
+ mutex_init(&av7110->ioctl_mutex);
+
+#if IS_ENABLED(CONFIG_DVB_AV7110_IR)
+ av7110_ir_init(av7110);
+#endif
+ printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
+ av7110_num++;
+out:
+ return ret;
+
+err_av7110_exit_v4l_12:
+ av7110_exit_v4l(av7110);
+err_av7110_unregister_11:
+ dvb_unregister(av7110);
+err_arm_thread_stop_10:
+ av7110_arm_sync(av7110);
+err_stop_arm_9:
+ /* Nothing to do. Rejoice. */
+err_av7110_ca_exit_8:
+ av7110_ca_exit(av7110);
+err_av7110_av_exit_7:
+ av7110_av_exit(av7110);
+err_iobuf_vfree_6:
+ vfree(av7110->iobuf);
+err_pci_free_5:
+ dma_free_coherent(&pdev->dev, 8192, av7110->debi_virt,
+ av7110->debi_bus);
+err_saa71466_vfree_4:
+ if (av7110->grabbing)
+ saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
+err_i2c_del_3:
+ i2c_del_adapter(&av7110->i2c_adap);
+err_dvb_unregister_adapter_2:
+ dvb_unregister_adapter(&av7110->dvb_adapter);
+err_put_firmware_1:
+ put_firmware(av7110);
+err_kfree_0:
+ kfree(av7110);
+ goto out;
+}
+
+static int av7110_detach(struct saa7146_dev* saa)
+{
+ struct av7110 *av7110 = saa->ext_priv;
+ dprintk(4, "%p\n", av7110);
+
+#if IS_ENABLED(CONFIG_DVB_AV7110_IR)
+ av7110_ir_exit(av7110);
+#endif
+ if (budgetpatch || av7110->full_ts) {
+ if (budgetpatch) {
+ /* Disable RPS1 */
+ saa7146_write(saa, MC1, MASK_29);
+ /* VSYNC LOW (inactive) */
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+ }
+ saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
+ SAA7146_IER_DISABLE(saa, MASK_10);
+ SAA7146_ISR_CLEAR(saa, MASK_10);
+ msleep(50);
+ tasklet_kill(&av7110->vpe_tasklet);
+ saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
+ }
+ av7110_exit_v4l(av7110);
+
+ av7110_arm_sync(av7110);
+
+ tasklet_kill(&av7110->debi_tasklet);
+ tasklet_kill(&av7110->gpio_tasklet);
+
+ dvb_unregister(av7110);
+
+ SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
+ SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
+
+ av7110_ca_exit(av7110);
+ av7110_av_exit(av7110);
+
+ vfree(av7110->iobuf);
+ dma_free_coherent(&saa->pci->dev, 8192, av7110->debi_virt,
+ av7110->debi_bus);
+
+ i2c_del_adapter(&av7110->i2c_adap);
+
+ dvb_unregister_adapter (&av7110->dvb_adapter);
+
+ av7110_num--;
+
+ put_firmware(av7110);
+
+ kfree(av7110);
+
+ saa->ext_priv = NULL;
+
+ return 0;
+}
+
+
+static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
+{
+ struct av7110 *av7110 = dev->ext_priv;
+
+ //print_time("av7110_irq");
+
+ /* Note: Don't try to handle the DEBI error irq (MASK_18), in
+ * intel mode the timeout is asserted all the time...
+ */
+
+ if (*isr & MASK_19) {
+ //printk("av7110_irq: DEBI\n");
+ /* Note 1: The DEBI irq is level triggered: We must enable it
+ * only after we started a DMA xfer, and disable it here
+ * immediately, or it will be signalled all the time while
+ * DEBI is idle.
+ * Note 2: You would think that an irq which is masked is
+ * not signalled by the hardware. Not so for the SAA7146:
+ * An irq is signalled as long as the corresponding bit
+ * in the ISR is set, and disabling irqs just prevents the
+ * hardware from setting the ISR bit. This means a) that we
+ * must clear the ISR *after* disabling the irq (which is why
+ * we must do it here even though saa7146_core did it already),
+ * and b) that if we were to disable an edge triggered irq
+ * (like the gpio irqs sadly are) temporarily we would likely
+ * loose some. This sucks :-(
+ */
+ SAA7146_IER_DISABLE(av7110->dev, MASK_19);
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
+ tasklet_schedule(&av7110->debi_tasklet);
+ }
+
+ if (*isr & MASK_03) {
+ //printk("av7110_irq: GPIO\n");
+ tasklet_schedule(&av7110->gpio_tasklet);
+ }
+
+ if (*isr & MASK_10)
+ tasklet_schedule(&av7110->vpe_tasklet);
+}
+
+
+static struct saa7146_extension av7110_extension_driver;
+
+#define MAKE_AV7110_INFO(x_var,x_name) \
+static struct saa7146_pci_extension_data x_var = { \
+ .ext_priv = x_name, \
+ .ext = &av7110_extension_driver }
+
+MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
+MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
+MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
+MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
+MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
+MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
+MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
+MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
+MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
+MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
+MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
+
+static const struct pci_device_id pci_tbl[] = {
+ MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
+ MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
+ MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
+ MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
+ MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
+ MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
+ MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
+ MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
+ MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
+ MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
+ MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
+
+/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
+/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
+
+ {
+ .vendor = 0,
+ }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+
+static struct saa7146_extension av7110_extension_driver = {
+ .name = "av7110",
+ .flags = SAA7146_USE_I2C_IRQ,
+
+ .module = THIS_MODULE,
+ .pci_tbl = &pci_tbl[0],
+ .attach = av7110_attach,
+ .detach = av7110_detach,
+
+ .irq_mask = MASK_19 | MASK_03 | MASK_10,
+ .irq_func = av7110_irq,
+};
+
+
+static int __init av7110_init(void)
+{
+ return saa7146_register_extension(&av7110_extension_driver);
+}
+
+
+static void __exit av7110_exit(void)
+{
+ saa7146_unregister_extension(&av7110_extension_driver);
+}
+
+module_init(av7110_init);
+module_exit(av7110_exit);
+
+MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by Siemens, Technotrend, Hauppauge");
+MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/av7110/av7110.h b/drivers/staging/media/av7110/av7110.h
new file mode 100644
index 000000000000..b8e8fc8ddbe9
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110.h
@@ -0,0 +1,316 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AV7110_H_
+#define _AV7110_H_
+
+#include <linux/interrupt.h>
+#include <linux/socket.h>
+#include <linux/netdevice.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/time.h>
+
+#include "video.h"
+#include "audio.h"
+#include "osd.h"
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/ca.h>
+#include <linux/dvb/net.h>
+#include <linux/mutex.h>
+
+#include <media/dvbdev.h>
+#include <media/demux.h>
+#include <media/dvb_demux.h>
+#include <media/dmxdev.h>
+#include "dvb_filter.h"
+#include <media/dvb_net.h>
+#include <media/dvb_ringbuffer.h>
+#include <media/dvb_frontend.h>
+#include "ves1820.h"
+#include "ves1x93.h"
+#include "stv0299.h"
+#include "tda8083.h"
+#include "sp8870.h"
+#include "stv0297.h"
+#include "l64781.h"
+
+#include <media/drv-intf/saa7146_vv.h>
+
+
+#define ANALOG_TUNER_VES1820 1
+#define ANALOG_TUNER_STV0297 2
+
+extern int av7110_debug;
+
+#define dprintk(level, fmt, arg...) do { \
+ if (level & av7110_debug) \
+ printk(KERN_DEBUG KBUILD_MODNAME ": %s(): " fmt, \
+ __func__, ##arg); \
+} while (0)
+
+#define MAXFILT 32
+
+enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
+
+enum av7110_video_mode {
+ AV7110_VIDEO_MODE_PAL = 0,
+ AV7110_VIDEO_MODE_NTSC = 1
+};
+
+struct av7110_p2t {
+ u8 pes[TS_SIZE];
+ u8 counter;
+ long int pos;
+ int frags;
+ struct dvb_demux_feed *feed;
+};
+
+/* video MPEG decoder events: */
+/* (code copied from dvb_frontend.c, should maybe be factored out...) */
+#define MAX_VIDEO_EVENT 8
+struct dvb_video_events {
+ struct video_event events[MAX_VIDEO_EVENT];
+ int eventw;
+ int eventr;
+ int overflow;
+ wait_queue_head_t wait_queue;
+ spinlock_t lock;
+};
+
+
+struct av7110;
+
+/* infrared remote control */
+struct infrared {
+ struct rc_dev *rcdev;
+ char input_phys[32];
+ u32 ir_config;
+};
+
+/* place to store all the necessary device information */
+struct av7110 {
+
+ /* devices */
+
+ struct dvb_device dvb_dev;
+ struct dvb_net dvb_net;
+
+ struct video_device v4l_dev;
+ struct video_device vbi_dev;
+
+ struct saa7146_dev *dev;
+
+ struct i2c_adapter i2c_adap;
+
+ char *card_name;
+
+ /* support for analog module of dvb-c */
+ int analog_tuner_flags;
+ int current_input;
+ u32 current_freq;
+
+ struct tasklet_struct debi_tasklet;
+ struct tasklet_struct gpio_tasklet;
+
+ int adac_type; /* audio DAC type */
+#define DVB_ADAC_TI 0
+#define DVB_ADAC_CRYSTAL 1
+#define DVB_ADAC_MSP34x0 2
+#define DVB_ADAC_MSP34x5 3
+#define DVB_ADAC_NONE -1
+
+
+ /* buffers */
+
+ void *iobuf; /* memory for all buffers */
+ struct dvb_ringbuffer avout; /* buffer for video or A/V mux */
+#define AVOUTLEN (128*1024)
+ struct dvb_ringbuffer aout; /* buffer for audio */
+#define AOUTLEN (64*1024)
+ void *bmpbuf;
+#define BMPLEN (8*32768+1024)
+
+ /* bitmap buffers and states */
+
+ int bmpp;
+ int bmplen;
+ volatile int bmp_state;
+#define BMP_NONE 0
+#define BMP_LOADING 1
+#define BMP_LOADED 2
+ wait_queue_head_t bmpq;
+
+
+ /* DEBI and polled command interface */
+
+ spinlock_t debilock;
+ struct mutex dcomlock;
+ volatile int debitype;
+ volatile int debilen;
+
+
+ /* Recording and playback flags */
+
+ int rec_mode;
+ int playing;
+#define RP_NONE 0
+#define RP_VIDEO 1
+#define RP_AUDIO 2
+#define RP_AV 3
+
+
+ /* OSD */
+
+ int osdwin; /* currently active window */
+ u16 osdbpp[8];
+ struct mutex osd_mutex;
+
+ /* CA */
+
+ struct ca_slot_info ci_slot[2];
+
+ enum av7110_video_mode vidmode;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+
+ /* for budget mode demux1 */
+ struct dmxdev dmxdev1;
+ struct dvb_demux demux1;
+ struct dvb_net dvb_net1;
+ spinlock_t feedlock1;
+ int feeding1;
+ u32 ttbp;
+ unsigned char *grabbing;
+ struct saa7146_pgtable pt;
+ struct tasklet_struct vpe_tasklet;
+ bool full_ts;
+
+ int fe_synced;
+ struct mutex pid_mutex;
+
+ int video_blank;
+ struct video_status videostate;
+ u16 display_panscan;
+ int display_ar;
+ int trickmode;
+#define TRICK_NONE 0
+#define TRICK_FAST 1
+#define TRICK_SLOW 2
+#define TRICK_FREEZE 3
+ struct audio_status audiostate;
+
+ struct dvb_demux_filter *handle2filter[32];
+ struct av7110_p2t p2t_filter[MAXFILT];
+ struct dvb_filter_pes2ts p2t[2];
+ struct ipack ipack[2];
+ u8 *kbuf[2];
+
+ int sinfo;
+ int feeding;
+
+ int arm_errors;
+ int registered;
+
+
+ /* AV711X */
+
+ u32 arm_fw;
+ u32 arm_rtsl;
+ u32 arm_vid;
+ u32 arm_app;
+ u32 avtype;
+ int arm_ready;
+ struct task_struct *arm_thread;
+ wait_queue_head_t arm_wait;
+ u16 arm_loops;
+
+ void *debi_virt;
+ dma_addr_t debi_bus;
+
+ u16 pids[DMX_PES_OTHER];
+
+ struct dvb_ringbuffer ci_rbuffer;
+ struct dvb_ringbuffer ci_wbuffer;
+
+ struct audio_mixer mixer;
+
+ struct dvb_adapter dvb_adapter;
+ struct dvb_device *video_dev;
+ struct dvb_device *audio_dev;
+ struct dvb_device *ca_dev;
+ struct dvb_device *osd_dev;
+
+ struct dvb_video_events video_events;
+ video_size_t video_size;
+
+ u16 wssMode;
+ u16 wssData;
+
+ struct infrared ir;
+
+ /* firmware stuff */
+ unsigned char *bin_fw;
+ unsigned long size_fw;
+
+ unsigned char *bin_dpram;
+ unsigned long size_dpram;
+
+ unsigned char *bin_root;
+ unsigned long size_root;
+
+ struct dvb_frontend* fe;
+ enum fe_status fe_status;
+
+ struct mutex ioctl_mutex;
+
+ /* crash recovery */
+ void (*recover)(struct av7110* av7110);
+ enum fe_sec_voltage saved_voltage;
+ enum fe_sec_tone_mode saved_tone;
+ struct dvb_diseqc_master_cmd saved_master_cmd;
+ enum fe_sec_mini_cmd saved_minicmd;
+
+ int (*fe_init)(struct dvb_frontend* fe);
+ int (*fe_read_status)(struct dvb_frontend *fe, enum fe_status *status);
+ int (*fe_diseqc_reset_overload)(struct dvb_frontend *fe);
+ int (*fe_diseqc_send_master_cmd)(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *cmd);
+ int (*fe_diseqc_send_burst)(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd);
+ int (*fe_set_tone)(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone);
+ int (*fe_set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
+ int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend *fe,
+ unsigned long cmd);
+ int (*fe_set_frontend)(struct dvb_frontend *fe);
+};
+
+
+extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
+ u16 subpid, u16 pcrpid);
+
+void av7110_ir_handler(struct av7110 *av7110, u32 ircom);
+int av7110_set_ir_config(struct av7110 *av7110);
+int av7110_ir_init(struct av7110 *av7110);
+void av7110_ir_exit(struct av7110 *av7110);
+
+/* msp3400 i2c subaddresses */
+#define MSP_WR_DEM 0x10
+#define MSP_RD_DEM 0x11
+#define MSP_WR_DSP 0x12
+#define MSP_RD_DSP 0x13
+
+extern int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val);
+extern u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg);
+extern int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val);
+
+
+extern int av7110_init_analog_module(struct av7110 *av7110);
+extern int av7110_init_v4l(struct av7110 *av7110);
+extern int av7110_exit_v4l(struct av7110 *av7110);
+
+#endif /* _AV7110_H_ */
diff --git a/drivers/staging/media/av7110/av7110_av.c b/drivers/staging/media/av7110/av7110_av.c
new file mode 100644
index 000000000000..91f4866c7e59
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_av.c
@@ -0,0 +1,1681 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * av7110_av.c: audio and video MPEG decoder stuff
+ *
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * originally based on code by:
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+#include <linux/ethtool.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+
+#include "av7110.h"
+#include "av7110_hw.h"
+#include "av7110_av.h"
+#include "av7110_ipack.h"
+
+/* MPEG-2 (ISO 13818 / H.222.0) stream types */
+#define PROG_STREAM_MAP 0xBC
+#define PRIVATE_STREAM1 0xBD
+#define PADDING_STREAM 0xBE
+#define PRIVATE_STREAM2 0xBF
+#define AUDIO_STREAM_S 0xC0
+#define AUDIO_STREAM_E 0xDF
+#define VIDEO_STREAM_S 0xE0
+#define VIDEO_STREAM_E 0xEF
+#define ECM_STREAM 0xF0
+#define EMM_STREAM 0xF1
+#define DSM_CC_STREAM 0xF2
+#define ISO13522_STREAM 0xF3
+#define PROG_STREAM_DIR 0xFF
+
+#define PTS_DTS_FLAGS 0xC0
+
+//pts_dts flags
+#define PTS_ONLY 0x80
+#define PTS_DTS 0xC0
+#define TS_SIZE 188
+#define TRANS_ERROR 0x80
+#define PAY_START 0x40
+#define TRANS_PRIO 0x20
+#define PID_MASK_HI 0x1F
+//flags
+#define TRANS_SCRMBL1 0x80
+#define TRANS_SCRMBL2 0x40
+#define ADAPT_FIELD 0x20
+#define PAYLOAD 0x10
+#define COUNT_MASK 0x0F
+
+// adaptation flags
+#define DISCON_IND 0x80
+#define RAND_ACC_IND 0x40
+#define ES_PRI_IND 0x20
+#define PCR_FLAG 0x10
+#define OPCR_FLAG 0x08
+#define SPLICE_FLAG 0x04
+#define TRANS_PRIV 0x02
+#define ADAP_EXT_FLAG 0x01
+
+// adaptation extension flags
+#define LTW_FLAG 0x80
+#define PIECE_RATE 0x40
+#define SEAM_SPLICE 0x20
+
+
+static void p_to_t(u8 const *buf, long int length, u16 pid,
+ u8 *counter, struct dvb_demux_feed *feed);
+static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len);
+
+
+int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
+{
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
+
+ if (!(dvbdmxfeed->ts_type & TS_PACKET))
+ return 0;
+ if (buf[3] == 0xe0) // video PES do not have a length in TS
+ buf[4] = buf[5] = 0;
+ if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
+ return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
+ &dvbdmxfeed->feed.ts, NULL);
+ else
+ return dvb_filter_pes2ts(p2t, buf, len, 1);
+}
+
+static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
+{
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
+
+ dvbdmxfeed->cb.ts(data, 188, NULL, 0,
+ &dvbdmxfeed->feed.ts, NULL);
+ return 0;
+}
+
+int av7110_av_start_record(struct av7110 *av7110, int av,
+ struct dvb_demux_feed *dvbdmxfeed)
+{
+ int ret = 0;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+ dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
+
+ if (av7110->playing || (av7110->rec_mode & av))
+ return -EBUSY;
+ av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+ dvbdmx->recording = 1;
+ av7110->rec_mode |= av;
+
+ switch (av7110->rec_mode) {
+ case RP_AUDIO:
+ dvb_filter_pes2ts_init(&av7110->p2t[0],
+ dvbdmx->pesfilter[0]->pid,
+ dvb_filter_pes2ts_cb,
+ (void *) dvbdmx->pesfilter[0]);
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+ break;
+
+ case RP_VIDEO:
+ dvb_filter_pes2ts_init(&av7110->p2t[1],
+ dvbdmx->pesfilter[1]->pid,
+ dvb_filter_pes2ts_cb,
+ (void *) dvbdmx->pesfilter[1]);
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+ break;
+
+ case RP_AV:
+ dvb_filter_pes2ts_init(&av7110->p2t[0],
+ dvbdmx->pesfilter[0]->pid,
+ dvb_filter_pes2ts_cb,
+ (void *) dvbdmx->pesfilter[0]);
+ dvb_filter_pes2ts_init(&av7110->p2t[1],
+ dvbdmx->pesfilter[1]->pid,
+ dvb_filter_pes2ts_cb,
+ (void *) dvbdmx->pesfilter[1]);
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
+ break;
+ }
+ return ret;
+}
+
+int av7110_av_start_play(struct av7110 *av7110, int av)
+{
+ int ret = 0;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (av7110->rec_mode)
+ return -EBUSY;
+ if (av7110->playing & av)
+ return -EBUSY;
+
+ av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+
+ if (av7110->playing == RP_NONE) {
+ av7110_ipack_reset(&av7110->ipack[0]);
+ av7110_ipack_reset(&av7110->ipack[1]);
+ }
+
+ av7110->playing |= av;
+ switch (av7110->playing) {
+ case RP_AUDIO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+ break;
+ case RP_VIDEO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+ av7110->sinfo = 0;
+ break;
+ case RP_AV:
+ av7110->sinfo = 0;
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
+ break;
+ }
+ return ret;
+}
+
+int av7110_av_stop(struct av7110 *av7110, int av)
+{
+ int ret = 0;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (!(av7110->playing & av) && !(av7110->rec_mode & av))
+ return 0;
+ av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+ if (av7110->playing) {
+ av7110->playing &= ~av;
+ switch (av7110->playing) {
+ case RP_AUDIO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+ break;
+ case RP_VIDEO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+ break;
+ case RP_NONE:
+ ret = av7110_set_vidmode(av7110, av7110->vidmode);
+ break;
+ }
+ } else {
+ av7110->rec_mode &= ~av;
+ switch (av7110->rec_mode) {
+ case RP_AUDIO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+ break;
+ case RP_VIDEO:
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+ break;
+ case RP_NONE:
+ break;
+ }
+ }
+ return ret;
+}
+
+
+int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
+{
+ int len;
+ u32 sync;
+ u16 blen;
+
+ if (!dlen) {
+ wake_up(&buf->queue);
+ return -1;
+ }
+ while (1) {
+ len = dvb_ringbuffer_avail(buf);
+ if (len < 6) {
+ wake_up(&buf->queue);
+ return -1;
+ }
+ sync = DVB_RINGBUFFER_PEEK(buf, 0) << 24;
+ sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16;
+ sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8;
+ sync |= DVB_RINGBUFFER_PEEK(buf, 3);
+
+ if (((sync &~ 0x0f) == 0x000001e0) ||
+ ((sync &~ 0x1f) == 0x000001c0) ||
+ (sync == 0x000001bd))
+ break;
+ printk("resync\n");
+ DVB_RINGBUFFER_SKIP(buf, 1);
+ }
+ blen = DVB_RINGBUFFER_PEEK(buf, 4) << 8;
+ blen |= DVB_RINGBUFFER_PEEK(buf, 5);
+ blen += 6;
+ if (len < blen || blen > dlen) {
+ //printk("buffer empty - avail %d blen %u dlen %d\n", len, blen, dlen);
+ wake_up(&buf->queue);
+ return -1;
+ }
+
+ dvb_ringbuffer_read(buf, dest, (size_t) blen);
+
+ dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
+ (unsigned long) buf->pread, (unsigned long) buf->pwrite);
+ wake_up(&buf->queue);
+ return blen;
+}
+
+
+int av7110_set_volume(struct av7110 *av7110, unsigned int volleft,
+ unsigned int volright)
+{
+ unsigned int vol, val, balance = 0;
+ int err;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ av7110->mixer.volume_left = volleft;
+ av7110->mixer.volume_right = volright;
+
+ switch (av7110->adac_type) {
+ case DVB_ADAC_TI:
+ volleft = (volleft * 256) / 1036;
+ volright = (volright * 256) / 1036;
+ if (volleft > 0x3f)
+ volleft = 0x3f;
+ if (volright > 0x3f)
+ volright = 0x3f;
+ if ((err = SendDAC(av7110, 3, 0x80 + volleft)))
+ return err;
+ return SendDAC(av7110, 4, volright);
+
+ case DVB_ADAC_CRYSTAL:
+ volleft = 127 - volleft / 2;
+ volright = 127 - volright / 2;
+ i2c_writereg(av7110, 0x20, 0x03, volleft);
+ i2c_writereg(av7110, 0x20, 0x04, volright);
+ return 0;
+
+ case DVB_ADAC_MSP34x0:
+ vol = (volleft > volright) ? volleft : volright;
+ val = (vol * 0x73 / 255) << 8;
+ if (vol > 0)
+ balance = ((volright - volleft) * 127) / vol;
+ msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
+ msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */
+ return 0;
+
+ case DVB_ADAC_MSP34x5:
+ vol = (volleft > volright) ? volleft : volright;
+ val = (vol * 0x73 / 255) << 8;
+ if (vol > 0)
+ balance = ((volright - volleft) * 127) / vol;
+ msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
+ return 0;
+ }
+
+ return 0;
+}
+
+int av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode)
+{
+ int ret;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
+
+ if (!ret && !av7110->playing) {
+ ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
+ av7110->pids[DMX_PES_AUDIO],
+ av7110->pids[DMX_PES_TELETEXT],
+ 0, av7110->pids[DMX_PES_PCR]);
+ if (!ret)
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+ }
+ return ret;
+}
+
+
+static enum av7110_video_mode sw2mode[16] = {
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
+ AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_PAL,
+ AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_NTSC,
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
+ AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
+};
+
+static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
+{
+ int i;
+ int hsize, vsize;
+ int sw;
+ u8 *p;
+ int ret = 0;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (av7110->sinfo)
+ return 0;
+ for (i = 7; i < count - 10; i++) {
+ p = buf + i;
+ if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3)
+ continue;
+ p += 4;
+ hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4);
+ vsize = ((p[1] &0x0F) << 8) | (p[2]);
+ sw = (p[3] & 0x0F);
+ ret = av7110_set_vidmode(av7110, sw2mode[sw]);
+ if (!ret) {
+ dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
+ av7110->sinfo = 1;
+ }
+ break;
+ }
+ return ret;
+}
+
+
+/****************************************************************************
+ * I/O buffer management and control
+ ****************************************************************************/
+
+static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf,
+ const u8 *buf, unsigned long count)
+{
+ unsigned long todo = count;
+ int free;
+
+ while (todo > 0) {
+ if (dvb_ringbuffer_free(rbuf) < 2048) {
+ if (wait_event_interruptible(rbuf->queue,
+ (dvb_ringbuffer_free(rbuf) >= 2048)))
+ return count - todo;
+ }
+ free = dvb_ringbuffer_free(rbuf);
+ if (free > todo)
+ free = todo;
+ dvb_ringbuffer_write(rbuf, buf, free);
+ todo -= free;
+ buf += free;
+ }
+
+ return count - todo;
+}
+
+static void play_video_cb(u8 *buf, int count, void *priv)
+{
+ struct av7110 *av7110 = (struct av7110 *) priv;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if ((buf[3] & 0xe0) == 0xe0) {
+ get_video_format(av7110, buf, count);
+ aux_ring_buffer_write(&av7110->avout, buf, count);
+ } else
+ aux_ring_buffer_write(&av7110->aout, buf, count);
+}
+
+static void play_audio_cb(u8 *buf, int count, void *priv)
+{
+ struct av7110 *av7110 = (struct av7110 *) priv;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ aux_ring_buffer_write(&av7110->aout, buf, count);
+}
+
+
+#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096)
+
+static ssize_t ts_play(struct av7110 *av7110, const char __user *buf,
+ unsigned long count, int nonblock, int type)
+{
+ struct dvb_ringbuffer *rb;
+ u8 *kb;
+ unsigned long todo = count;
+
+ dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count);
+
+ rb = (type) ? &av7110->avout : &av7110->aout;
+ kb = av7110->kbuf[type];
+
+ if (!kb)
+ return -ENOBUFS;
+
+ if (nonblock && !FREE_COND_TS)
+ return -EWOULDBLOCK;
+
+ while (todo >= TS_SIZE) {
+ if (!FREE_COND_TS) {
+ if (nonblock)
+ return count - todo;
+ if (wait_event_interruptible(rb->queue, FREE_COND_TS))
+ return count - todo;
+ }
+ if (copy_from_user(kb, buf, TS_SIZE))
+ return -EFAULT;
+ write_ts_to_decoder(av7110, type, kb, TS_SIZE);
+ todo -= TS_SIZE;
+ buf += TS_SIZE;
+ }
+
+ return count - todo;
+}
+
+
+#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
+ dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
+
+static ssize_t dvb_play(struct av7110 *av7110, const char __user *buf,
+ unsigned long count, int nonblock, int type)
+{
+ unsigned long todo = count, n;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (!av7110->kbuf[type])
+ return -ENOBUFS;
+
+ if (nonblock && !FREE_COND)
+ return -EWOULDBLOCK;
+
+ while (todo > 0) {
+ if (!FREE_COND) {
+ if (nonblock)
+ return count - todo;
+ if (wait_event_interruptible(av7110->avout.queue,
+ FREE_COND))
+ return count - todo;
+ }
+ n = todo;
+ if (n > IPACKS * 2)
+ n = IPACKS * 2;
+ if (copy_from_user(av7110->kbuf[type], buf, n))
+ return -EFAULT;
+ av7110_ipack_instant_repack(av7110->kbuf[type], n,
+ &av7110->ipack[type]);
+ todo -= n;
+ buf += n;
+ }
+ return count - todo;
+}
+
+static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf,
+ unsigned long count, int nonblock, int type)
+{
+ unsigned long todo = count, n;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (!av7110->kbuf[type])
+ return -ENOBUFS;
+
+ if (nonblock && !FREE_COND)
+ return -EWOULDBLOCK;
+
+ while (todo > 0) {
+ if (!FREE_COND) {
+ if (nonblock)
+ return count - todo;
+ if (wait_event_interruptible(av7110->avout.queue,
+ FREE_COND))
+ return count - todo;
+ }
+ n = todo;
+ if (n > IPACKS * 2)
+ n = IPACKS * 2;
+ av7110_ipack_instant_repack(buf, n, &av7110->ipack[type]);
+ todo -= n;
+ buf += n;
+ }
+ return count - todo;
+}
+
+static ssize_t dvb_aplay(struct av7110 *av7110, const char __user *buf,
+ unsigned long count, int nonblock, int type)
+{
+ unsigned long todo = count, n;
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (!av7110->kbuf[type])
+ return -ENOBUFS;
+ if (nonblock && dvb_ringbuffer_free(&av7110->aout) < 20 * 1024)
+ return -EWOULDBLOCK;
+
+ while (todo > 0) {
+ if (dvb_ringbuffer_free(&av7110->aout) < 20 * 1024) {
+ if (nonblock)
+ return count - todo;
+ if (wait_event_interruptible(av7110->aout.queue,
+ (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)))
+ return count-todo;
+ }
+ n = todo;
+ if (n > IPACKS * 2)
+ n = IPACKS * 2;
+ if (copy_from_user(av7110->kbuf[type], buf, n))
+ return -EFAULT;
+ av7110_ipack_instant_repack(av7110->kbuf[type], n,
+ &av7110->ipack[type]);
+ todo -= n;
+ buf += n;
+ }
+ return count - todo;
+}
+
+void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed)
+{
+ memset(p->pes, 0, TS_SIZE);
+ p->counter = 0;
+ p->pos = 0;
+ p->frags = 0;
+ if (feed)
+ p->feed = feed;
+}
+
+static void clear_p2t(struct av7110_p2t *p)
+{
+ memset(p->pes, 0, TS_SIZE);
+// p->counter = 0;
+ p->pos = 0;
+ p->frags = 0;
+}
+
+
+static int find_pes_header(u8 const *buf, long int length, int *frags)
+{
+ int c = 0;
+ int found = 0;
+
+ *frags = 0;
+
+ while (c < length - 3 && !found) {
+ if (buf[c] == 0x00 && buf[c + 1] == 0x00 &&
+ buf[c + 2] == 0x01) {
+ switch ( buf[c + 3] ) {
+ case PROG_STREAM_MAP:
+ case PRIVATE_STREAM2:
+ case PROG_STREAM_DIR:
+ case ECM_STREAM :
+ case EMM_STREAM :
+ case PADDING_STREAM :
+ case DSM_CC_STREAM :
+ case ISO13522_STREAM:
+ case PRIVATE_STREAM1:
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ found = 1;
+ break;
+
+ default:
+ c++;
+ break;
+ }
+ } else
+ c++;
+ }
+ if (c == length - 3 && !found) {
+ if (buf[length - 1] == 0x00)
+ *frags = 1;
+ if (buf[length - 2] == 0x00 &&
+ buf[length - 1] == 0x00)
+ *frags = 2;
+ if (buf[length - 3] == 0x00 &&
+ buf[length - 2] == 0x00 &&
+ buf[length - 1] == 0x01)
+ *frags = 3;
+ return -1;
+ }
+
+ return c;
+}
+
+void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p)
+{
+ int c, c2, l, add;
+ int check, rest;
+
+ c = 0;
+ c2 = 0;
+ if (p->frags){
+ check = 0;
+ switch(p->frags) {
+ case 1:
+ if (buf[c] == 0x00 && buf[c + 1] == 0x01) {
+ check = 1;
+ c += 2;
+ }
+ break;
+ case 2:
+ if (buf[c] == 0x01) {
+ check = 1;
+ c++;
+ }
+ break;
+ case 3:
+ check = 1;
+ }
+ if (check) {
+ switch (buf[c]) {
+ case PROG_STREAM_MAP:
+ case PRIVATE_STREAM2:
+ case PROG_STREAM_DIR:
+ case ECM_STREAM :
+ case EMM_STREAM :
+ case PADDING_STREAM :
+ case DSM_CC_STREAM :
+ case ISO13522_STREAM:
+ case PRIVATE_STREAM1:
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ p->pes[0] = 0x00;
+ p->pes[1] = 0x00;
+ p->pes[2] = 0x01;
+ p->pes[3] = buf[c];
+ p->pos = 4;
+ memcpy(p->pes + p->pos, buf + c, (TS_SIZE - 4) - p->pos);
+ c += (TS_SIZE - 4) - p->pos;
+ p_to_t(p->pes, (TS_SIZE - 4), pid, &p->counter, p->feed);
+ clear_p2t(p);
+ break;
+
+ default:
+ c = 0;
+ break;
+ }
+ }
+ p->frags = 0;
+ }
+
+ if (p->pos) {
+ c2 = find_pes_header(buf + c, length - c, &p->frags);
+ if (c2 >= 0 && c2 < (TS_SIZE - 4) - p->pos)
+ l = c2+c;
+ else
+ l = (TS_SIZE - 4) - p->pos;
+ memcpy(p->pes + p->pos, buf, l);
+ c += l;
+ p->pos += l;
+ p_to_t(p->pes, p->pos, pid, &p->counter, p->feed);
+ clear_p2t(p);
+ }
+
+ add = 0;
+ while (c < length) {
+ c2 = find_pes_header(buf + c + add, length - c - add, &p->frags);
+ if (c2 >= 0) {
+ c2 += c + add;
+ if (c2 > c){
+ p_to_t(buf + c, c2 - c, pid, &p->counter, p->feed);
+ c = c2;
+ clear_p2t(p);
+ add = 0;
+ } else
+ add = 1;
+ } else {
+ l = length - c;
+ rest = l % (TS_SIZE - 4);
+ l -= rest;
+ p_to_t(buf + c, l, pid, &p->counter, p->feed);
+ memcpy(p->pes, buf + c + l, rest);
+ p->pos = rest;
+ c = length;
+ }
+ }
+}
+
+
+static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
+{
+ int i;
+ int c = 0;
+ int fill;
+ u8 tshead[4] = { 0x47, 0x00, 0x00, 0x10 };
+
+ fill = (TS_SIZE - 4) - length;
+ if (pes_start)
+ tshead[1] = 0x40;
+ if (fill)
+ tshead[3] = 0x30;
+ tshead[1] |= (u8)((pid & 0x1F00) >> 8);
+ tshead[2] |= (u8)(pid & 0x00FF);
+ tshead[3] |= ((*counter)++ & 0x0F);
+ memcpy(buf, tshead, 4);
+ c += 4;
+
+ if (fill) {
+ buf[4] = fill - 1;
+ c++;
+ if (fill > 1) {
+ buf[5] = 0x00;
+ c++;
+ }
+ for (i = 6; i < fill + 4; i++) {
+ buf[i] = 0xFF;
+ c++;
+ }
+ }
+
+ return c;
+}
+
+
+static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
+ struct dvb_demux_feed *feed)
+{
+ int l, pes_start;
+ u8 obuf[TS_SIZE];
+ long c = 0;
+
+ pes_start = 0;
+ if (length > 3 &&
+ buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
+ switch (buf[3]) {
+ case PROG_STREAM_MAP:
+ case PRIVATE_STREAM2:
+ case PROG_STREAM_DIR:
+ case ECM_STREAM :
+ case EMM_STREAM :
+ case PADDING_STREAM :
+ case DSM_CC_STREAM :
+ case ISO13522_STREAM:
+ case PRIVATE_STREAM1:
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ pes_start = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ while (c < length) {
+ memset(obuf, 0, TS_SIZE);
+ if (length - c >= (TS_SIZE - 4)){
+ l = write_ts_header2(pid, counter, pes_start,
+ obuf, (TS_SIZE - 4));
+ memcpy(obuf + l, buf + c, TS_SIZE - l);
+ c += TS_SIZE - l;
+ } else {
+ l = write_ts_header2(pid, counter, pes_start,
+ obuf, length - c);
+ memcpy(obuf + l, buf + c, TS_SIZE - l);
+ c = length;
+ }
+ feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, NULL);
+ pes_start = 0;
+ }
+}
+
+
+static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len)
+{
+ struct ipack *ipack = &av7110->ipack[type];
+
+ if (buf[1] & TRANS_ERROR) {
+ av7110_ipack_reset(ipack);
+ return -1;
+ }
+
+ if (!(buf[3] & PAYLOAD))
+ return -1;
+
+ if (buf[1] & PAY_START)
+ av7110_ipack_flush(ipack);
+
+ if (buf[3] & ADAPT_FIELD) {
+ len -= buf[4] + 1;
+ buf += buf[4] + 1;
+ if (!len)
+ return 0;
+ }
+
+ av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
+ return 0;
+}
+
+
+int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct av7110 *av7110 = (struct av7110 *) demux->priv;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE)
+ return 0;
+
+ switch (feed->pes_type) {
+ case 0:
+ if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
+ return -EINVAL;
+ break;
+ case 1:
+ if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
+ return -EINVAL;
+ break;
+ default:
+ return -1;
+ }
+
+ return write_ts_to_decoder(av7110, feed->pes_type, buf, len);
+}
+
+
+
+/******************************************************************************
+ * Video MPEG decoder events
+ ******************************************************************************/
+void dvb_video_add_event(struct av7110 *av7110, struct video_event *event)
+{
+ struct dvb_video_events *events = &av7110->video_events;
+ int wp;
+
+ spin_lock_bh(&events->lock);
+
+ wp = (events->eventw + 1) % MAX_VIDEO_EVENT;
+ if (wp == events->eventr) {
+ events->overflow = 1;
+ events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
+ }
+
+ //FIXME: timestamp?
+ memcpy(&events->events[events->eventw], event, sizeof(struct video_event));
+ events->eventw = wp;
+
+ spin_unlock_bh(&events->lock);
+
+ wake_up_interruptible(&events->wait_queue);
+}
+
+
+static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags)
+{
+ struct dvb_video_events *events = &av7110->video_events;
+
+ if (events->overflow) {
+ events->overflow = 0;
+ return -EOVERFLOW;
+ }
+ if (events->eventw == events->eventr) {
+ int ret;
+
+ if (flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
+
+ ret = wait_event_interruptible(events->wait_queue,
+ events->eventw != events->eventr);
+ if (ret < 0)
+ return ret;
+ }
+
+ spin_lock_bh(&events->lock);
+
+ memcpy(event, &events->events[events->eventr],
+ sizeof(struct video_event));
+ events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
+
+ spin_unlock_bh(&events->lock);
+
+ return 0;
+}
+
+/******************************************************************************
+ * DVB device file operations
+ ******************************************************************************/
+
+static __poll_t dvb_video_poll(struct file *file, poll_table *wait)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ __poll_t mask = 0;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ poll_wait(file, &av7110->avout.queue, wait);
+
+ poll_wait(file, &av7110->video_events.wait_queue, wait);
+
+ if (av7110->video_events.eventw != av7110->video_events.eventr)
+ mask = EPOLLPRI;
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if (av7110->playing) {
+ if (FREE_COND)
+ mask |= (EPOLLOUT | EPOLLWRNORM);
+ } else {
+ /* if not playing: may play if asked for */
+ mask |= (EPOLLOUT | EPOLLWRNORM);
+ }
+ }
+
+ return mask;
+}
+
+static ssize_t dvb_video_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ unsigned char c;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+ return -EPERM;
+
+ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)
+ return -EPERM;
+
+ if (get_user(c, buf))
+ return -EFAULT;
+ if (c == 0x47 && count % TS_SIZE == 0)
+ return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
+ else
+ return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
+}
+
+static __poll_t dvb_audio_poll(struct file *file, poll_table *wait)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ __poll_t mask = 0;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ poll_wait(file, &av7110->aout.queue, wait);
+
+ if (av7110->playing) {
+ if (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
+ mask |= (EPOLLOUT | EPOLLWRNORM);
+ } else /* if not playing: may play if asked for */
+ mask = (EPOLLOUT | EPOLLWRNORM);
+
+ return mask;
+}
+
+static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ unsigned char c;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {
+ printk(KERN_ERR "not audio source memory\n");
+ return -EPERM;
+ }
+
+ if (get_user(c, buf))
+ return -EFAULT;
+ if (c == 0x47 && count % TS_SIZE == 0)
+ return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
+ else
+ return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
+}
+
+static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
+
+#define MIN_IFRAME 400000
+
+static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
+{
+ unsigned i, n;
+ int progressive = 0;
+ int match = 0;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (len == 0)
+ return 0;
+
+ if (!(av7110->playing & RP_VIDEO)) {
+ if (av7110_av_start_play(av7110, RP_VIDEO) < 0)
+ return -EBUSY;
+ }
+
+ /* search in buf for instances of 00 00 01 b5 1? */
+ for (i = 0; i < len; i++) {
+ unsigned char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (match == 5) {
+ progressive = c & 0x08;
+ match = 0;
+ }
+ if (c == 0x00) {
+ match = (match == 1 || match == 2) ? 2 : 1;
+ continue;
+ }
+ switch (match++) {
+ case 2: if (c == 0x01)
+ continue;
+ break;
+ case 3: if (c == 0xb5)
+ continue;
+ break;
+ case 4: if ((c & 0xf0) == 0x10)
+ continue;
+ break;
+ }
+ match = 0;
+ }
+
+ /* setting n always > 1, fixes problems when playing stillframes
+ consisting of I- and P-Frames */
+ n = MIN_IFRAME / len + 1;
+
+ /* FIXME: nonblock? */
+ dvb_play_kernel(av7110, iframe_header, sizeof(iframe_header), 0, 1);
+
+ for (i = 0; i < n; i++)
+ dvb_play(av7110, buf, len, 0, 1);
+
+ av7110_ipack_flush(&av7110->ipack[1]);
+
+ if (progressive)
+ return vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
+ else
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_video_still_picture {
+ compat_uptr_t iFrame;
+ int32_t size;
+};
+#define VIDEO_STILLPICTURE32 _IOW('o', 30, struct compat_video_still_picture)
+
+struct compat_video_event {
+ __s32 type;
+ /* unused, make sure to use atomic time for y2038 if it ever gets used */
+ compat_long_t timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+};
+#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event)
+
+static int dvb_compat_video_get_event(struct av7110 *av7110,
+ struct compat_video_event *event, int flags)
+{
+ struct video_event ev;
+ int ret;
+
+ ret = dvb_video_get_event(av7110, &ev, flags);
+
+ *event = (struct compat_video_event) {
+ .type = ev.type,
+ .timestamp = ev.timestamp,
+ .u.size = ev.u.size,
+ };
+
+ return ret;
+}
+#endif
+
+static int dvb_video_ioctl(struct file *file,
+ unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ unsigned long arg = (unsigned long) parg;
+ int ret = 0;
+
+ dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
+
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
+ cmd != VIDEO_GET_SIZE ) {
+ return -EPERM;
+ }
+ }
+
+ if (mutex_lock_interruptible(&av7110->ioctl_mutex))
+ return -ERESTARTSYS;
+
+ switch (cmd) {
+ case VIDEO_STOP:
+ av7110->videostate.play_state = VIDEO_STOPPED;
+ if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
+ ret = av7110_av_stop(av7110, RP_VIDEO);
+ else
+ ret = vidcom(av7110, AV_VIDEO_CMD_STOP,
+ av7110->videostate.video_blank ? 0 : 1);
+ if (!ret)
+ av7110->trickmode = TRICK_NONE;
+ break;
+
+ case VIDEO_PLAY:
+ av7110->trickmode = TRICK_NONE;
+ if (av7110->videostate.play_state == VIDEO_FREEZED) {
+ av7110->videostate.play_state = VIDEO_PLAYING;
+ ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
+ if (ret)
+ break;
+ }
+ if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
+ if (av7110->playing == RP_AV) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+ if (ret)
+ break;
+ av7110->playing &= ~RP_VIDEO;
+ }
+ ret = av7110_av_start_play(av7110, RP_VIDEO);
+ }
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
+ if (!ret)
+ av7110->videostate.play_state = VIDEO_PLAYING;
+ break;
+
+ case VIDEO_FREEZE:
+ av7110->videostate.play_state = VIDEO_FREEZED;
+ if (av7110->playing & RP_VIDEO)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
+ else
+ ret = vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
+ if (!ret)
+ av7110->trickmode = TRICK_FREEZE;
+ break;
+
+ case VIDEO_CONTINUE:
+ if (av7110->playing & RP_VIDEO)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
+ if (!ret) {
+ av7110->videostate.play_state = VIDEO_PLAYING;
+ av7110->trickmode = TRICK_NONE;
+ }
+ break;
+
+ case VIDEO_SELECT_SOURCE:
+ av7110->videostate.stream_source = (video_stream_source_t) arg;
+ break;
+
+ case VIDEO_SET_BLANK:
+ av7110->videostate.video_blank = (int) arg;
+ break;
+
+ case VIDEO_GET_STATUS:
+ memcpy(parg, &av7110->videostate, sizeof(struct video_status));
+ break;
+
+#ifdef CONFIG_COMPAT
+ case VIDEO_GET_EVENT32:
+ ret = dvb_compat_video_get_event(av7110, parg, file->f_flags);
+ break;
+#endif
+
+ case VIDEO_GET_EVENT:
+ ret = dvb_video_get_event(av7110, parg, file->f_flags);
+ break;
+
+ case VIDEO_GET_SIZE:
+ memcpy(parg, &av7110->video_size, sizeof(video_size_t));
+ break;
+
+ case VIDEO_SET_DISPLAY_FORMAT:
+ {
+ video_displayformat_t format = (video_displayformat_t) arg;
+ switch (format) {
+ case VIDEO_PAN_SCAN:
+ av7110->display_panscan = VID_PAN_SCAN_PREF;
+ break;
+ case VIDEO_LETTER_BOX:
+ av7110->display_panscan = VID_VC_AND_PS_PREF;
+ break;
+ case VIDEO_CENTER_CUT_OUT:
+ av7110->display_panscan = VID_CENTRE_CUT_PREF;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (ret < 0)
+ break;
+ av7110->videostate.display_format = format;
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
+ 1, av7110->display_panscan);
+ break;
+ }
+
+ case VIDEO_SET_FORMAT:
+ if (arg > 1) {
+ ret = -EINVAL;
+ break;
+ }
+ av7110->display_ar = arg;
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
+ 1, (u16) arg);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case VIDEO_STILLPICTURE32:
+ {
+ struct compat_video_still_picture *pic =
+ (struct compat_video_still_picture *) parg;
+ av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY;
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ ret = play_iframe(av7110, compat_ptr(pic->iFrame),
+ pic->size, file->f_flags & O_NONBLOCK);
+ break;
+ }
+#endif
+
+ case VIDEO_STILLPICTURE:
+ {
+ struct video_still_picture *pic =
+ (struct video_still_picture *) parg;
+ av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY;
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ ret = play_iframe(av7110, pic->iFrame, pic->size,
+ file->f_flags & O_NONBLOCK);
+ break;
+ }
+
+ case VIDEO_FAST_FORWARD:
+ //note: arg is ignored by firmware
+ if (av7110->playing & RP_VIDEO)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+ __Scan_I, 2, AV_PES, 0);
+ else
+ ret = vidcom(av7110, AV_VIDEO_CMD_FFWD, arg);
+ if (!ret) {
+ av7110->trickmode = TRICK_FAST;
+ av7110->videostate.play_state = VIDEO_PLAYING;
+ }
+ break;
+
+ case VIDEO_SLOWMOTION:
+ if (av7110->playing&RP_VIDEO) {
+ if (av7110->trickmode != TRICK_SLOW)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
+ } else {
+ ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 0);
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
+ }
+ if (!ret) {
+ av7110->trickmode = TRICK_SLOW;
+ av7110->videostate.play_state = VIDEO_PLAYING;
+ }
+ break;
+
+ case VIDEO_GET_CAPABILITIES:
+ *(int *)parg = VIDEO_CAP_MPEG1 | VIDEO_CAP_MPEG2 |
+ VIDEO_CAP_SYS | VIDEO_CAP_PROG;
+ break;
+
+ case VIDEO_CLEAR_BUFFER:
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ av7110_ipack_reset(&av7110->ipack[1]);
+ if (av7110->playing == RP_AV) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+ __Play, 2, AV_PES, 0);
+ if (ret)
+ break;
+ if (av7110->trickmode == TRICK_FAST)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+ __Scan_I, 2, AV_PES, 0);
+ if (av7110->trickmode == TRICK_SLOW) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+ __Slow, 2, 0, 0);
+ if (!ret)
+ ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
+ }
+ if (av7110->trickmode == TRICK_FREEZE)
+ ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 1);
+ }
+ break;
+
+ case VIDEO_SET_STREAMTYPE:
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ mutex_unlock(&av7110->ioctl_mutex);
+ return ret;
+}
+
+static int dvb_audio_ioctl(struct file *file,
+ unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ unsigned long arg = (unsigned long) parg;
+ int ret = 0;
+
+ dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
+
+ if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
+ (cmd != AUDIO_GET_STATUS))
+ return -EPERM;
+
+ if (mutex_lock_interruptible(&av7110->ioctl_mutex))
+ return -ERESTARTSYS;
+
+ switch (cmd) {
+ case AUDIO_STOP:
+ if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
+ ret = av7110_av_stop(av7110, RP_AUDIO);
+ else
+ ret = audcom(av7110, AUDIO_CMD_MUTE);
+ if (!ret)
+ av7110->audiostate.play_state = AUDIO_STOPPED;
+ break;
+
+ case AUDIO_PLAY:
+ if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
+ ret = av7110_av_start_play(av7110, RP_AUDIO);
+ if (!ret)
+ ret = audcom(av7110, AUDIO_CMD_UNMUTE);
+ if (!ret)
+ av7110->audiostate.play_state = AUDIO_PLAYING;
+ break;
+
+ case AUDIO_PAUSE:
+ ret = audcom(av7110, AUDIO_CMD_MUTE);
+ if (!ret)
+ av7110->audiostate.play_state = AUDIO_PAUSED;
+ break;
+
+ case AUDIO_CONTINUE:
+ if (av7110->audiostate.play_state == AUDIO_PAUSED) {
+ av7110->audiostate.play_state = AUDIO_PLAYING;
+ ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16);
+ }
+ break;
+
+ case AUDIO_SELECT_SOURCE:
+ av7110->audiostate.stream_source = (audio_stream_source_t) arg;
+ break;
+
+ case AUDIO_SET_MUTE:
+ {
+ ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
+ if (!ret)
+ av7110->audiostate.mute_state = (int) arg;
+ break;
+ }
+
+ case AUDIO_SET_AV_SYNC:
+ av7110->audiostate.AV_sync_state = (int) arg;
+ ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
+ break;
+
+ case AUDIO_SET_BYPASS_MODE:
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ ret = -EINVAL;
+ av7110->audiostate.bypass_mode = (int)arg;
+ break;
+
+ case AUDIO_CHANNEL_SELECT:
+ av7110->audiostate.channel_select = (audio_channel_select_t) arg;
+ switch(av7110->audiostate.channel_select) {
+ case AUDIO_STEREO:
+ ret = audcom(av7110, AUDIO_CMD_STEREO);
+ if (!ret) {
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x49);
+ else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
+ }
+ break;
+ case AUDIO_MONO_LEFT:
+ ret = audcom(av7110, AUDIO_CMD_MONO_L);
+ if (!ret) {
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x4a);
+ else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
+ }
+ break;
+ case AUDIO_MONO_RIGHT:
+ ret = audcom(av7110, AUDIO_CMD_MONO_R);
+ if (!ret) {
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x45);
+ else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
+
+ case AUDIO_GET_STATUS:
+ memcpy(parg, &av7110->audiostate, sizeof(struct audio_status));
+ break;
+
+ case AUDIO_GET_CAPABILITIES:
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ else
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
+ AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ break;
+
+ case AUDIO_CLEAR_BUFFER:
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ av7110_ipack_reset(&av7110->ipack[0]);
+ if (av7110->playing == RP_AV)
+ ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+ __Play, 2, AV_PES, 0);
+ break;
+
+ case AUDIO_SET_ID:
+ break;
+
+ case AUDIO_SET_MIXER:
+ {
+ struct audio_mixer *amix = (struct audio_mixer *)parg;
+ ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
+ break;
+ }
+
+ case AUDIO_SET_STREAMTYPE:
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+
+ mutex_unlock(&av7110->ioctl_mutex);
+ return ret;
+}
+
+
+static int dvb_video_open(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ int err;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if ((err = dvb_generic_open(inode, file)) < 0)
+ return err;
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ av7110->video_blank = 1;
+ av7110->audiostate.AV_sync_state = 1;
+ av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
+
+ /* empty event queue */
+ av7110->video_events.eventr = av7110->video_events.eventw = 0;
+ }
+
+ return 0;
+}
+
+static int dvb_video_release(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ av7110_av_stop(av7110, RP_VIDEO);
+ }
+
+ return dvb_generic_release(inode, file);
+}
+
+static int dvb_audio_open(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ int err = dvb_generic_open(inode, file);
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ if (err < 0)
+ return err;
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
+ return 0;
+}
+
+static int dvb_audio_release(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+
+ dprintk(2, "av7110:%p, \n", av7110);
+
+ av7110_av_stop(av7110, RP_AUDIO);
+ return dvb_generic_release(inode, file);
+}
+
+
+
+/******************************************************************************
+ * driver registration
+ ******************************************************************************/
+
+static const struct file_operations dvb_video_fops = {
+ .owner = THIS_MODULE,
+ .write = dvb_video_write,
+ .unlocked_ioctl = dvb_generic_ioctl,
+ .compat_ioctl = dvb_generic_ioctl,
+ .open = dvb_video_open,
+ .release = dvb_video_release,
+ .poll = dvb_video_poll,
+ .llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_video = {
+ .priv = NULL,
+ .users = 6,
+ .readers = 5, /* arbitrary */
+ .writers = 1,
+ .fops = &dvb_video_fops,
+ .kernel_ioctl = dvb_video_ioctl,
+};
+
+static const struct file_operations dvb_audio_fops = {
+ .owner = THIS_MODULE,
+ .write = dvb_audio_write,
+ .unlocked_ioctl = dvb_generic_ioctl,
+ .compat_ioctl = dvb_generic_ioctl,
+ .open = dvb_audio_open,
+ .release = dvb_audio_release,
+ .poll = dvb_audio_poll,
+ .llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_audio = {
+ .priv = NULL,
+ .users = 1,
+ .writers = 1,
+ .fops = &dvb_audio_fops,
+ .kernel_ioctl = dvb_audio_ioctl,
+};
+
+
+int av7110_av_register(struct av7110 *av7110)
+{
+ av7110->audiostate.AV_sync_state = 0;
+ av7110->audiostate.mute_state = 0;
+ av7110->audiostate.play_state = AUDIO_STOPPED;
+ av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
+ av7110->audiostate.channel_select = AUDIO_STEREO;
+ av7110->audiostate.bypass_mode = 0;
+
+ av7110->videostate.video_blank = 0;
+ av7110->videostate.play_state = VIDEO_STOPPED;
+ av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
+ av7110->videostate.video_format = VIDEO_FORMAT_4_3;
+ av7110->videostate.display_format = VIDEO_LETTER_BOX;
+ av7110->display_ar = VIDEO_FORMAT_4_3;
+ av7110->display_panscan = VID_VC_AND_PS_PREF;
+
+ init_waitqueue_head(&av7110->video_events.wait_queue);
+ spin_lock_init(&av7110->video_events.lock);
+ av7110->video_events.eventw = av7110->video_events.eventr = 0;
+ av7110->video_events.overflow = 0;
+ memset(&av7110->video_size, 0, sizeof (video_size_t));
+
+ dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
+ &dvbdev_video, av7110, DVB_DEVICE_VIDEO, 0);
+
+ dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
+ &dvbdev_audio, av7110, DVB_DEVICE_AUDIO, 0);
+
+ return 0;
+}
+
+void av7110_av_unregister(struct av7110 *av7110)
+{
+ dvb_unregister_device(av7110->audio_dev);
+ dvb_unregister_device(av7110->video_dev);
+}
+
+int av7110_av_init(struct av7110 *av7110)
+{
+ void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
+ int i, ret;
+
+ for (i = 0; i < 2; i++) {
+ struct ipack *ipack = av7110->ipack + i;
+
+ ret = av7110_ipack_init(ipack, IPACKS, play[i]);
+ if (ret < 0) {
+ if (i)
+ av7110_ipack_free(--ipack);
+ goto out;
+ }
+ ipack->data = av7110;
+ }
+
+ dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
+ dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN);
+
+ av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN);
+ av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS;
+out:
+ return ret;
+}
+
+void av7110_av_exit(struct av7110 *av7110)
+{
+ av7110_ipack_free(&av7110->ipack[0]);
+ av7110_ipack_free(&av7110->ipack[1]);
+}
diff --git a/drivers/staging/media/av7110/av7110_av.h b/drivers/staging/media/av7110/av7110_av.h
new file mode 100644
index 000000000000..71bbd4391f57
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_av.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AV7110_AV_H_
+#define _AV7110_AV_H_
+
+struct av7110;
+
+extern int av7110_set_vidmode(struct av7110 *av7110,
+ enum av7110_video_mode mode);
+
+extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len);
+extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen);
+extern int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len);
+
+extern int av7110_set_volume(struct av7110 *av7110, unsigned int volleft,
+ unsigned int volright);
+extern int av7110_av_stop(struct av7110 *av7110, int av);
+extern int av7110_av_start_record(struct av7110 *av7110, int av,
+ struct dvb_demux_feed *dvbdmxfeed);
+extern int av7110_av_start_play(struct av7110 *av7110, int av);
+
+extern void dvb_video_add_event(struct av7110 *av7110, struct video_event *event);
+
+extern void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed);
+extern void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p);
+
+extern int av7110_av_register(struct av7110 *av7110);
+extern void av7110_av_unregister(struct av7110 *av7110);
+extern int av7110_av_init(struct av7110 *av7110);
+extern void av7110_av_exit(struct av7110 *av7110);
+
+
+#endif /* _AV7110_AV_H_ */
diff --git a/drivers/staging/media/av7110/av7110_ca.c b/drivers/staging/media/av7110/av7110_ca.c
new file mode 100644
index 000000000000..c1338e074a3d
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_ca.c
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * av7110_ca.c: CA and CI stuff
+ *
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * originally based on code by:
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/poll.h>
+#include <linux/gfp.h>
+
+#include "av7110.h"
+#include "av7110_hw.h"
+#include "av7110_ca.h"
+
+
+void CI_handle(struct av7110 *av7110, u8 *data, u16 len)
+{
+ dprintk(8, "av7110:%p\n",av7110);
+
+ if (len < 3)
+ return;
+ switch (data[0]) {
+ case CI_MSG_CI_INFO:
+ if (data[2] != 1 && data[2] != 2)
+ break;
+ switch (data[1]) {
+ case 0:
+ av7110->ci_slot[data[2] - 1].flags = 0;
+ break;
+ case 1:
+ av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_PRESENT;
+ break;
+ case 2:
+ av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_READY;
+ break;
+ }
+ break;
+ case CI_SWITCH_PRG_REPLY:
+ //av7110->ci_stat=data[1];
+ break;
+ default:
+ break;
+ }
+}
+
+
+void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
+{
+ if (dvb_ringbuffer_free(cibuf) < len + 2)
+ return;
+
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf, len >> 8);
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf, len & 0xff);
+ dvb_ringbuffer_write(cibuf, data, len);
+ wake_up_interruptible(&cibuf->queue);
+}
+
+
+/******************************************************************************
+ * CI link layer file ops
+ ******************************************************************************/
+
+static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
+{
+ struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p;
+ void *data;
+
+ for (p = tab; *p; p++) {
+ data = vmalloc(size);
+ if (!data) {
+ while (p-- != tab) {
+ vfree(p[0]->data);
+ p[0]->data = NULL;
+ }
+ return -ENOMEM;
+ }
+ dvb_ringbuffer_init(*p, data, size);
+ }
+ return 0;
+}
+
+static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
+{
+ dvb_ringbuffer_flush_spinlock_wakeup(cirbuf);
+ dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf);
+}
+
+static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
+{
+ vfree(cirbuf->data);
+ cirbuf->data = NULL;
+ vfree(ciwbuf->data);
+ ciwbuf->data = NULL;
+}
+
+static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
+ int slots, struct ca_slot_info *slot)
+{
+ int i;
+ int len = 0;
+ u8 msg[8] = { 0x00, 0x06, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00 };
+
+ for (i = 0; i < 2; i++) {
+ if (slots & (1 << i))
+ len += 8;
+ }
+
+ if (dvb_ringbuffer_free(cibuf) < len)
+ return -EBUSY;
+
+ for (i = 0; i < 2; i++) {
+ if (slots & (1 << i)) {
+ msg[2] = i;
+ dvb_ringbuffer_write(cibuf, msg, 8);
+ slot[i].flags = 0;
+ }
+ }
+
+ return 0;
+}
+
+static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ int free;
+ int non_blocking = file->f_flags & O_NONBLOCK;
+ u8 *page = (u8 *)__get_free_page(GFP_USER);
+ int res;
+
+ if (!page)
+ return -ENOMEM;
+
+ res = -EINVAL;
+ if (count > 2048)
+ goto out;
+
+ res = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ free = dvb_ringbuffer_free(cibuf);
+ if (count + 2 > free) {
+ res = -EWOULDBLOCK;
+ if (non_blocking)
+ goto out;
+ res = -ERESTARTSYS;
+ if (wait_event_interruptible(cibuf->queue,
+ (dvb_ringbuffer_free(cibuf) >= count + 2)))
+ goto out;
+ }
+
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf, count >> 8);
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf, count & 0xff);
+
+ res = dvb_ringbuffer_write(cibuf, page, count);
+out:
+ free_page((unsigned long)page);
+ return res;
+}
+
+static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ int avail;
+ int non_blocking = file->f_flags & O_NONBLOCK;
+ ssize_t len;
+
+ if (!cibuf->data || !count)
+ return 0;
+ if (non_blocking && (dvb_ringbuffer_empty(cibuf)))
+ return -EWOULDBLOCK;
+ if (wait_event_interruptible(cibuf->queue,
+ !dvb_ringbuffer_empty(cibuf)))
+ return -ERESTARTSYS;
+ avail = dvb_ringbuffer_avail(cibuf);
+ if (avail < 4)
+ return 0;
+ len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
+ len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
+ if (avail < len + 2 || count < len)
+ return -EINVAL;
+ DVB_RINGBUFFER_SKIP(cibuf, 2);
+
+ return dvb_ringbuffer_read_user(cibuf, buf, len);
+}
+
+static int dvb_ca_open(struct inode *inode, struct file *file)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ int err = dvb_generic_open(inode, file);
+
+ dprintk(8, "av7110:%p\n",av7110);
+
+ if (err < 0)
+ return err;
+ ci_ll_flush(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
+ return 0;
+}
+
+static __poll_t dvb_ca_poll (struct file *file, poll_table *wait)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer;
+ struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
+ __poll_t mask = 0;
+
+ dprintk(8, "av7110:%p\n",av7110);
+
+ poll_wait(file, &rbuf->queue, wait);
+ poll_wait(file, &wbuf->queue, wait);
+
+ if (!dvb_ringbuffer_empty(rbuf))
+ mask |= (EPOLLIN | EPOLLRDNORM);
+
+ if (dvb_ringbuffer_free(wbuf) > 1024)
+ mask |= (EPOLLOUT | EPOLLWRNORM);
+
+ return mask;
+}
+
+static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+ unsigned long arg = (unsigned long) parg;
+ int ret = 0;
+
+ dprintk(8, "av7110:%p\n",av7110);
+
+ if (mutex_lock_interruptible(&av7110->ioctl_mutex))
+ return -ERESTARTSYS;
+
+ switch (cmd) {
+ case CA_RESET:
+ ret = ci_ll_reset(&av7110->ci_wbuffer, file, arg,
+ &av7110->ci_slot[0]);
+ break;
+ case CA_GET_CAP:
+ {
+ struct ca_caps cap;
+
+ cap.slot_num = 2;
+ cap.slot_type = (FW_CI_LL_SUPPORT(av7110->arm_app) ?
+ CA_CI_LINK : CA_CI) | CA_DESCR;
+ cap.descr_num = 16;
+ cap.descr_type = CA_ECD;
+ memcpy(parg, &cap, sizeof(cap));
+ break;
+ }
+
+ case CA_GET_SLOT_INFO:
+ {
+ struct ca_slot_info *info=(struct ca_slot_info *)parg;
+
+ if (info->num < 0 || info->num > 1) {
+ mutex_unlock(&av7110->ioctl_mutex);
+ return -EINVAL;
+ }
+ av7110->ci_slot[info->num].num = info->num;
+ av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
+ CA_CI_LINK : CA_CI;
+ memcpy(info, &av7110->ci_slot[info->num], sizeof(struct ca_slot_info));
+ break;
+ }
+
+ case CA_GET_MSG:
+ break;
+
+ case CA_SEND_MSG:
+ break;
+
+ case CA_GET_DESCR_INFO:
+ {
+ struct ca_descr_info info;
+
+ info.num = 16;
+ info.type = CA_ECD;
+ memcpy(parg, &info, sizeof (info));
+ break;
+ }
+
+ case CA_SET_DESCR:
+ {
+ struct ca_descr *descr = (struct ca_descr*) parg;
+
+ if (descr->index >= 16 || descr->parity > 1) {
+ mutex_unlock(&av7110->ioctl_mutex);
+ return -EINVAL;
+ }
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetDescr, 5,
+ (descr->index<<8)|descr->parity,
+ (descr->cw[0]<<8)|descr->cw[1],
+ (descr->cw[2]<<8)|descr->cw[3],
+ (descr->cw[4]<<8)|descr->cw[5],
+ (descr->cw[6]<<8)|descr->cw[7]);
+ break;
+ }
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&av7110->ioctl_mutex);
+ return ret;
+}
+
+static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+
+ dprintk(8, "av7110:%p\n",av7110);
+ return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
+}
+
+static ssize_t dvb_ca_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct av7110 *av7110 = dvbdev->priv;
+
+ dprintk(8, "av7110:%p\n",av7110);
+ return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
+}
+
+static const struct file_operations dvb_ca_fops = {
+ .owner = THIS_MODULE,
+ .read = dvb_ca_read,
+ .write = dvb_ca_write,
+ .unlocked_ioctl = dvb_generic_ioctl,
+ .open = dvb_ca_open,
+ .release = dvb_generic_release,
+ .poll = dvb_ca_poll,
+ .llseek = default_llseek,
+};
+
+static struct dvb_device dvbdev_ca = {
+ .priv = NULL,
+ .users = 1,
+ .writers = 1,
+ .fops = &dvb_ca_fops,
+ .kernel_ioctl = dvb_ca_ioctl,
+};
+
+
+int av7110_ca_register(struct av7110 *av7110)
+{
+ return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
+ &dvbdev_ca, av7110, DVB_DEVICE_CA, 0);
+}
+
+void av7110_ca_unregister(struct av7110 *av7110)
+{
+ dvb_unregister_device(av7110->ca_dev);
+}
+
+int av7110_ca_init(struct av7110* av7110)
+{
+ return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192);
+}
+
+void av7110_ca_exit(struct av7110* av7110)
+{
+ ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
+}
diff --git a/drivers/staging/media/av7110/av7110_ca.h b/drivers/staging/media/av7110/av7110_ca.h
new file mode 100644
index 000000000000..a6e3f2955730
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_ca.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AV7110_CA_H_
+#define _AV7110_CA_H_
+
+struct av7110;
+
+extern void CI_handle(struct av7110 *av7110, u8 *data, u16 len);
+extern void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len);
+
+extern int av7110_ca_register(struct av7110 *av7110);
+extern void av7110_ca_unregister(struct av7110 *av7110);
+extern int av7110_ca_init(struct av7110* av7110);
+extern void av7110_ca_exit(struct av7110* av7110);
+
+#endif /* _AV7110_CA_H_ */
diff --git a/drivers/staging/media/av7110/av7110_hw.c b/drivers/staging/media/av7110/av7110_hw.c
new file mode 100644
index 000000000000..93ca31e38ddd
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_hw.c
@@ -0,0 +1,1204 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * av7110_hw.c: av7110 low level hardware access and firmware interface
+ *
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * originally based on code by:
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+/* for debugging ARM communication: */
+//#define COM_DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+
+#include "av7110.h"
+#include "av7110_hw.h"
+
+#define _NOHANDSHAKE
+
+/*
+ * Max transfer size done by av7110_fw_cmd()
+ *
+ * The maximum size passed to this function is 6 bytes. The buffer also
+ * uses two additional ones for type and size. So, 8 bytes is enough.
+ */
+#define MAX_XFER_SIZE 8
+
+/****************************************************************************
+ * DEBI functions
+ ****************************************************************************/
+
+/* This DEBI code is based on the Stradis driver
+ by Nathan Laredo <laredo@gnu.org> */
+
+int av7110_debiwrite(struct av7110 *av7110, u32 config,
+ int addr, u32 val, unsigned int count)
+{
+ struct saa7146_dev *dev = av7110->dev;
+
+ if (count > 32764) {
+ printk("%s: invalid count %d\n", __func__, count);
+ return -1;
+ }
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+ printk("%s: wait_for_debi_done failed\n", __func__);
+ return -1;
+ }
+ saa7146_write(dev, DEBI_CONFIG, config);
+ if (count <= 4) /* immediate transfer */
+ saa7146_write(dev, DEBI_AD, val);
+ else /* block transfer */
+ saa7146_write(dev, DEBI_AD, av7110->debi_bus);
+ saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
+ saa7146_write(dev, MC2, (2 << 16) | 2);
+ return 0;
+}
+
+u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, unsigned int count)
+{
+ struct saa7146_dev *dev = av7110->dev;
+ u32 result = 0;
+
+ if (count > 32764) {
+ printk("%s: invalid count %d\n", __func__, count);
+ return 0;
+ }
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+ printk("%s: wait_for_debi_done #1 failed\n", __func__);
+ return 0;
+ }
+ saa7146_write(dev, DEBI_AD, av7110->debi_bus);
+ saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
+
+ saa7146_write(dev, DEBI_CONFIG, config);
+ saa7146_write(dev, MC2, (2 << 16) | 2);
+ if (count > 4)
+ return count;
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+ printk("%s: wait_for_debi_done #2 failed\n", __func__);
+ return 0;
+ }
+
+ result = saa7146_read(dev, DEBI_AD);
+ result &= (0xffffffffUL >> ((4 - count) * 8));
+ return result;
+}
+
+
+
+/* av7110 ARM core boot stuff */
+#if 0
+void av7110_reset_arm(struct av7110 *av7110)
+{
+ saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
+
+ /* Disable DEBI and GPIO irq */
+ SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
+
+ saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
+ msleep(30); /* the firmware needs some time to initialize */
+
+ ARM_ResetMailBox(av7110);
+
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
+ SAA7146_IER_ENABLE(av7110->dev, MASK_03);
+
+ av7110->arm_ready = 1;
+ dprintk(1, "reset ARM\n");
+}
+#endif /* 0 */
+
+static int waitdebi(struct av7110 *av7110, int adr, int state)
+{
+ int k;
+
+ dprintk(4, "%p\n", av7110);
+
+ for (k = 0; k < 100; k++) {
+ if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
+ return 0;
+ udelay(5);
+ }
+ return -ETIMEDOUT;
+}
+
+static int load_dram(struct av7110 *av7110, u32 *data, int len)
+{
+ int i;
+ int blocks, rest;
+ u32 base, bootblock = AV7110_BOOT_BLOCK;
+
+ dprintk(4, "%p\n", av7110);
+
+ blocks = len / AV7110_BOOT_MAX_SIZE;
+ rest = len % AV7110_BOOT_MAX_SIZE;
+ base = DRAM_START_CODE;
+
+ for (i = 0; i < blocks; i++) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
+ return -ETIMEDOUT;
+ }
+ dprintk(4, "writing DRAM block %d\n", i);
+ mwdebi(av7110, DEBISWAB, bootblock,
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
+ bootblock ^= 0x1400;
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ base += AV7110_BOOT_MAX_SIZE;
+ }
+
+ if (rest > 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
+ return -ETIMEDOUT;
+ }
+ if (rest > 4)
+ mwdebi(av7110, DEBISWAB, bootblock,
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest);
+ else
+ mwdebi(av7110, DEBISWAB, bootblock,
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
+
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ }
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
+ return -ETIMEDOUT;
+ }
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
+ printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+
+/* we cannot write av7110 DRAM directly, so load a bootloader into
+ * the DPRAM which implements a simple boot protocol */
+int av7110_bootarm(struct av7110 *av7110)
+{
+ const struct firmware *fw;
+ const char *fw_name = "av7110/bootcode.bin";
+ struct saa7146_dev *dev = av7110->dev;
+ u32 ret;
+ int i;
+
+ dprintk(4, "%p\n", av7110);
+
+ av7110->arm_ready = 0;
+
+ saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
+
+ /* Disable DEBI and GPIO irq */
+ SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
+
+ /* enable DEBI */
+ saa7146_write(av7110->dev, MC1, 0x08800880);
+ saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ /* test DEBI */
+ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
+ /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
+ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
+
+ if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
+ printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: %08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
+ ret, 0x10325476);
+ return -1;
+ }
+ for (i = 0; i < 8192; i += 4)
+ iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
+ dprintk(2, "debi test OK\n");
+
+ /* boot */
+ dprintk(1, "load boot code\n");
+ saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
+ //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
+ //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
+
+ ret = request_firmware(&fw, fw_name, &dev->pci->dev);
+ if (ret) {
+ printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n",
+ fw_name);
+ return ret;
+ }
+
+ mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size);
+ release_firmware(fw);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+
+ if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
+ printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out\n");
+ return -ETIMEDOUT;
+ }
+ saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
+ mdelay(1);
+
+ dprintk(1, "load dram code\n");
+ if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
+ printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): load_dram() failed\n");
+ return -1;
+ }
+
+ saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
+ mdelay(1);
+
+ dprintk(1, "load dpram code\n");
+ mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
+
+ if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
+ printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out after loading DRAM\n");
+ return -ETIMEDOUT;
+ }
+ saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
+ msleep(30); /* the firmware needs some time to initialize */
+
+ //ARM_ClearIrq(av7110);
+ ARM_ResetMailBox(av7110);
+ SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
+ SAA7146_IER_ENABLE(av7110->dev, MASK_03);
+
+ av7110->arm_errors = 0;
+ av7110->arm_ready = 1;
+ return 0;
+}
+MODULE_FIRMWARE("av7110/bootcode.bin");
+
+/****************************************************************************
+ * DEBI command polling
+ ****************************************************************************/
+
+int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
+{
+ unsigned long start;
+ u32 stat;
+ int err;
+
+ if (FW_VERSION(av7110->arm_app) <= 0x261c) {
+ /* not supported by old firmware */
+ msleep(50);
+ return 0;
+ }
+
+ /* new firmware */
+ start = jiffies;
+ for (;;) {
+ err = time_after(jiffies, start + ARM_WAIT_FREE);
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ return -ERESTARTSYS;
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ mutex_unlock(&av7110->dcomlock);
+ if ((stat & flags) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
+ __func__, stat & flags);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+ return 0;
+}
+
+static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+{
+ int i;
+ unsigned long start;
+ char *type = NULL;
+ u16 flags[2] = {0, 0};
+ u32 stat;
+ int err;
+
+// dprintk(4, "%p\n", av7110);
+
+ if (!av7110->arm_ready) {
+ dprintk(1, "arm not ready.\n");
+ return -ENXIO;
+ }
+
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_FREE);
+ if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
+ av7110->arm_errors++;
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
+
+#ifndef _NOHANDSHAKE
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_SHAKE);
+ if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+#endif
+
+ switch ((buf[0] >> 8) & 0xff) {
+ case COMTYPE_PIDFILTER:
+ case COMTYPE_ENCODER:
+ case COMTYPE_REC_PLAY:
+ case COMTYPE_MPEGDECODER:
+ type = "MSG";
+ flags[0] = GPMQOver;
+ flags[1] = GPMQFull;
+ break;
+ case COMTYPE_OSD:
+ type = "OSD";
+ flags[0] = OSDQOver;
+ flags[1] = OSDQFull;
+ break;
+ case COMTYPE_MISC:
+ if (FW_VERSION(av7110->arm_app) >= 0x261d) {
+ type = "MSG";
+ flags[0] = GPMQOver;
+ flags[1] = GPMQBusy;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (type != NULL) {
+ /* non-immediate COMMAND type */
+ start = jiffies;
+ for (;;) {
+ err = time_after(jiffies, start + ARM_WAIT_FREE);
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & flags[0]) {
+ printk(KERN_ERR "%s: %s QUEUE overflow\n",
+ __func__, type);
+ return -1;
+ }
+ if ((stat & flags[1]) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
+ __func__, type);
+ av7110->arm_errors++;
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+ }
+
+ for (i = 2; i < length; i++)
+ wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
+
+ if (length)
+ wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
+ else
+ wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
+
+ wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
+
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
+
+#ifdef COM_DEBUG
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_FREE);
+ if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
+ __func__, (buf[0] >> 8) & 0xff);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & GPMQOver) {
+ printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
+ return -ENOSPC;
+ }
+ else if (stat & OSDQOver) {
+ printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
+ return -ENOSPC;
+ }
+#endif
+
+ return 0;
+}
+
+static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+{
+ int ret;
+
+// dprintk(4, "%p\n", av7110);
+
+ if (!av7110->arm_ready) {
+ dprintk(1, "arm not ready.\n");
+ return -1;
+ }
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ return -ERESTARTSYS;
+
+ ret = __av7110_send_fw_cmd(av7110, buf, length);
+ mutex_unlock(&av7110->dcomlock);
+ if (ret && ret!=-ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
+ __func__, ret);
+ return ret;
+}
+
+int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
+{
+ va_list args;
+ u16 buf[MAX_XFER_SIZE];
+ int i, ret;
+
+// dprintk(4, "%p\n", av7110);
+
+ if (2 + num > ARRAY_SIZE(buf)) {
+ printk(KERN_WARNING
+ "%s: %s len=%d is too big!\n",
+ KBUILD_MODNAME, __func__, num);
+ return -EINVAL;
+ }
+
+ buf[0] = ((type << 8) | com);
+ buf[1] = num;
+
+ if (num) {
+ va_start(args, num);
+ for (i = 0; i < num; i++)
+ buf[i + 2] = va_arg(args, u32);
+ va_end(args);
+ }
+
+ ret = av7110_send_fw_cmd(av7110, buf, num + 2);
+ if (ret && ret != -ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
+ return ret;
+}
+
+#if 0
+int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
+{
+ int i, ret;
+ u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ dprintk(4, "%p\n", av7110);
+
+ for(i = 0; i < len && i < 32; i++)
+ {
+ if(i % 2 == 0)
+ cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
+ else
+ cmd[(i / 2) + 2] |= buf[i];
+ }
+
+ ret = av7110_send_fw_cmd(av7110, cmd, 18);
+ if (ret && ret != -ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
+ return ret;
+}
+#endif /* 0 */
+
+int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ int request_buf_len, u16 *reply_buf, int reply_buf_len)
+{
+ int err;
+ s16 i;
+ unsigned long start;
+#ifdef COM_DEBUG
+ u32 stat;
+#endif
+
+ dprintk(4, "%p\n", av7110);
+
+ if (!av7110->arm_ready) {
+ dprintk(1, "arm not ready.\n");
+ return -1;
+ }
+
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ return -ERESTARTSYS;
+
+ if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
+ mutex_unlock(&av7110->dcomlock);
+ printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
+ return err;
+ }
+
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_FREE);
+ if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+#ifdef _NOHANDSHAKE
+ msleep(1);
+#endif
+ }
+
+#ifndef _NOHANDSHAKE
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_SHAKE);
+ if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+#endif
+
+#ifdef COM_DEBUG
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & GPMQOver) {
+ printk(KERN_ERR "%s: GPMQOver\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -1;
+ }
+ else if (stat & OSDQOver) {
+ printk(KERN_ERR "%s: OSDQOver\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -1;
+ }
+#endif
+
+ for (i = 0; i < reply_buf_len; i++)
+ reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
+
+ mutex_unlock(&av7110->dcomlock);
+ return 0;
+}
+
+static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
+{
+ int ret;
+ ret = av7110_fw_request(av7110, &tag, 0, buf, length);
+ if (ret)
+ printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
+ return ret;
+}
+
+
+/****************************************************************************
+ * Firmware commands
+ ****************************************************************************/
+
+/* get version of the firmware ROM, RTSL, video ucode and ARM application */
+int av7110_firmversion(struct av7110 *av7110)
+{
+ u16 buf[20];
+ u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
+
+ dprintk(4, "%p\n", av7110);
+
+ if (av7110_fw_query(av7110, tag, buf, 16)) {
+ printk("dvb-ttpci: failed to boot firmware @ card %d\n",
+ av7110->dvb_adapter.num);
+ return -EIO;
+ }
+
+ av7110->arm_fw = (buf[0] << 16) + buf[1];
+ av7110->arm_rtsl = (buf[2] << 16) + buf[3];
+ av7110->arm_vid = (buf[4] << 16) + buf[5];
+ av7110->arm_app = (buf[6] << 16) + buf[7];
+ av7110->avtype = (buf[8] << 16) + buf[9];
+
+ printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
+ av7110->dvb_adapter.num, av7110->arm_fw,
+ av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
+
+ /* print firmware capabilities */
+ if (FW_CI_LL_SUPPORT(av7110->arm_app))
+ printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
+ av7110->dvb_adapter.num);
+ else
+ printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
+ av7110->dvb_adapter.num);
+
+ return 0;
+}
+
+
+int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
+{
+ int i, ret;
+ u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ dprintk(4, "%p\n", av7110);
+
+ if (len > 10)
+ len = 10;
+
+ buf[1] = len + 2;
+ buf[2] = len;
+
+ if (burst != -1)
+ buf[3] = burst ? 0x01 : 0x00;
+ else
+ buf[3] = 0xffff;
+
+ for (i = 0; i < len; i++)
+ buf[i + 4] = msg[i];
+
+ ret = av7110_send_fw_cmd(av7110, buf, 18);
+ if (ret && ret!=-ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
+ return ret;
+}
+
+
+#ifdef CONFIG_DVB_AV7110_OSD
+
+static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
+}
+
+static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
+ enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
+ windownr, colordepth, index, blending);
+}
+
+static inline int SetColor_(struct av7110 *av7110, u8 windownr,
+ enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
+ windownr, colordepth, index, colorhi, colorlo);
+}
+
+static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
+ u16 colorfg, u16 colorbg)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
+ windownr, fontsize, colorfg, colorbg);
+}
+
+static int FlushText(struct av7110 *av7110)
+{
+ unsigned long start;
+ int err;
+
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ return -ERESTARTSYS;
+ start = jiffies;
+ while (1) {
+ err = time_after(jiffies, start + ARM_WAIT_OSD);
+ if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
+ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+ mutex_unlock(&av7110->dcomlock);
+ return 0;
+}
+
+static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
+{
+ int i, ret;
+ unsigned long start;
+ int length = strlen(buf) + 1;
+ u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
+
+ if (mutex_lock_interruptible(&av7110->dcomlock))
+ return -ERESTARTSYS;
+
+ start = jiffies;
+ while (1) {
+ ret = time_after(jiffies, start + ARM_WAIT_OSD);
+ if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
+ break;
+ if (ret) {
+ printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
+ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+#ifndef _NOHANDSHAKE
+ start = jiffies;
+ while (1) {
+ ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
+ if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ break;
+ if (ret) {
+ printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
+ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+#endif
+ for (i = 0; i < length / 2; i++)
+ wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
+ swab16(*(u16 *)(buf + 2 * i)), 2);
+ if (length & 1)
+ wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
+ ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
+ mutex_unlock(&av7110->dcomlock);
+ if (ret && ret!=-ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
+ return ret;
+}
+
+static inline int DrawLine(struct av7110 *av7110, u8 windownr,
+ u16 x, u16 y, u16 dx, u16 dy, u16 color)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
+ windownr, x, y, dx, dy, color);
+}
+
+static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
+ u16 x, u16 y, u16 dx, u16 dy, u16 color)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
+ windownr, x, y, dx, dy, color);
+}
+
+static inline int HideWindow(struct av7110 *av7110, u8 windownr)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
+}
+
+static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
+}
+
+static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
+}
+
+static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
+}
+
+static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
+ osd_raw_window_t disptype,
+ u16 width, u16 height)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
+ windownr, disptype, width, height);
+}
+
+
+static enum av7110_osd_palette_type bpp2pal[8] = {
+ Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
+};
+static osd_raw_window_t bpp2bit[8] = {
+ OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
+};
+
+static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
+{
+ int ret = wait_event_timeout(av7110->bmpq,
+ av7110->bmp_state != BMP_LOADING, 10*HZ);
+ if (ret == 0) {
+ printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
+ ret, av7110->bmp_state);
+ av7110->bmp_state = BMP_NONE;
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static inline int LoadBitmap(struct av7110 *av7110,
+ u16 dx, u16 dy, int inc, u8 __user * data)
+{
+ u16 format;
+ int bpp;
+ int i;
+ int d, delta;
+ u8 c;
+ int ret;
+
+ dprintk(4, "%p\n", av7110);
+
+ format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
+
+ av7110->bmp_state = BMP_LOADING;
+ if (format == OSD_BITMAP8) {
+ bpp=8; delta = 1;
+ } else if (format == OSD_BITMAP4) {
+ bpp=4; delta = 2;
+ } else if (format == OSD_BITMAP2) {
+ bpp=2; delta = 4;
+ } else if (format == OSD_BITMAP1) {
+ bpp=1; delta = 8;
+ } else {
+ av7110->bmp_state = BMP_NONE;
+ return -EINVAL;
+ }
+ av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
+ av7110->bmpp = 0;
+ if (av7110->bmplen > 32768) {
+ av7110->bmp_state = BMP_NONE;
+ return -EINVAL;
+ }
+ for (i = 0; i < dy; i++) {
+ if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
+ av7110->bmp_state = BMP_NONE;
+ return -EINVAL;
+ }
+ }
+ if (format != OSD_BITMAP8) {
+ for (i = 0; i < dx * dy / delta; i++) {
+ c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
+ for (d = delta - 2; d >= 0; d--) {
+ c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
+ << ((delta - d - 1) * bpp));
+ ((u8 *)av7110->bmpbuf)[1024 + i] = c;
+ }
+ }
+ }
+ av7110->bmplen += 1024;
+ dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
+ ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
+ if (!ret)
+ ret = WaitUntilBmpLoaded(av7110);
+ return ret;
+}
+
+static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
+{
+ dprintk(4, "%p\n", av7110);
+
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
+}
+
+static inline int ReleaseBitmap(struct av7110 *av7110)
+{
+ dprintk(4, "%p\n", av7110);
+
+ if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
+ return -1;
+ if (av7110->bmp_state == BMP_LOADING)
+ dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
+ av7110->bmp_state = BMP_NONE;
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
+}
+
+static u32 RGB2YUV(u16 R, u16 G, u16 B)
+{
+ u16 y, u, v;
+ u16 Y, Cr, Cb;
+
+ y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */
+ u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */
+ v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */
+
+ Y = y / 256;
+ Cb = u / 16;
+ Cr = v / 16;
+
+ return Cr | (Cb << 16) | (Y << 8);
+}
+
+static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
+{
+ int ret;
+
+ u16 ch, cl;
+ u32 yuv;
+
+ yuv = blend ? RGB2YUV(r,g,b) : 0;
+ cl = (yuv & 0xffff);
+ ch = ((yuv >> 16) & 0xffff);
+ ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
+ color, ch, cl);
+ if (!ret)
+ ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
+ color, ((blend >> 4) & 0x0f));
+ return ret;
+}
+
+static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
+{
+ int i;
+ int length = last - first + 1;
+
+ if (length * 4 > DATA_BUFF3_SIZE)
+ return -EINVAL;
+
+ for (i = 0; i < length; i++) {
+ u32 color, blend, yuv;
+
+ if (get_user(color, colors + i))
+ return -EFAULT;
+ blend = (color & 0xF0000000) >> 4;
+ yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
+ (color >> 16) & 0xFF) | blend : 0;
+ yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
+ wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
+ }
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
+ av7110->osdwin,
+ bpp2pal[av7110->osdbpp[av7110->osdwin]],
+ first, last);
+}
+
+static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
+ int x1, int y1, int inc, u8 __user * data)
+{
+ uint w, h, bpp, bpl, size, lpb, bnum, brest;
+ int i;
+ int rc,release_rc;
+
+ w = x1 - x0 + 1;
+ h = y1 - y0 + 1;
+ if (inc <= 0)
+ inc = w;
+ if (w <= 0 || w > 720 || h <= 0 || h > 576)
+ return -EINVAL;
+ bpp = av7110->osdbpp[av7110->osdwin] + 1;
+ bpl = ((w * bpp + 7) & ~7) / 8;
+ size = h * bpl;
+ lpb = (32 * 1024) / bpl;
+ bnum = size / (lpb * bpl);
+ brest = size - bnum * lpb * bpl;
+
+ if (av7110->bmp_state == BMP_LOADING) {
+ /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
+ BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
+ rc = WaitUntilBmpLoaded(av7110);
+ if (rc)
+ return rc;
+ /* just continue. This should work for all fw versions
+ * if bnum==1 && !brest && LoadBitmap was successful
+ */
+ }
+
+ rc = 0;
+ for (i = 0; i < bnum; i++) {
+ rc = LoadBitmap(av7110, w, lpb, inc, data);
+ if (rc)
+ break;
+ rc = BlitBitmap(av7110, x0, y0 + i * lpb);
+ if (rc)
+ break;
+ data += lpb * inc;
+ }
+ if (!rc && brest) {
+ rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
+ if (!rc)
+ rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
+ }
+ release_rc = ReleaseBitmap(av7110);
+ if (!rc)
+ rc = release_rc;
+ if (rc)
+ dprintk(1,"returns %d\n",rc);
+ return rc;
+}
+
+int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
+{
+ int ret;
+
+ if (mutex_lock_interruptible(&av7110->osd_mutex))
+ return -ERESTARTSYS;
+
+ switch (dc->cmd) {
+ case OSD_Close:
+ ret = DestroyOSDWindow(av7110, av7110->osdwin);
+ break;
+ case OSD_Open:
+ av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
+ ret = CreateOSDWindow(av7110, av7110->osdwin,
+ bpp2bit[av7110->osdbpp[av7110->osdwin]],
+ dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
+ if (ret)
+ break;
+ if (!dc->data) {
+ ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+ if (ret)
+ break;
+ ret = SetColorBlend(av7110, av7110->osdwin);
+ }
+ break;
+ case OSD_Show:
+ ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
+ break;
+ case OSD_Hide:
+ ret = HideWindow(av7110, av7110->osdwin);
+ break;
+ case OSD_Clear:
+ ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
+ break;
+ case OSD_Fill:
+ ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
+ break;
+ case OSD_SetColor:
+ ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
+ break;
+ case OSD_SetPalette:
+ if (FW_VERSION(av7110->arm_app) >= 0x2618)
+ ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
+ else {
+ int i, len = dc->x0-dc->color+1;
+ u8 __user *colors = (u8 __user *)dc->data;
+ u8 r, g = 0, b = 0, blend = 0;
+ ret = 0;
+ for (i = 0; i<len; i++) {
+ if (get_user(r, colors + i * 4) ||
+ get_user(g, colors + i * 4 + 1) ||
+ get_user(b, colors + i * 4 + 2) ||
+ get_user(blend, colors + i * 4 + 3)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
+ if (ret)
+ break;
+ }
+ }
+ break;
+ case OSD_SetPixel:
+ ret = DrawLine(av7110, av7110->osdwin,
+ dc->x0, dc->y0, 0, 0, dc->color);
+ break;
+ case OSD_SetRow:
+ dc->y1 = dc->y0;
+ fallthrough;
+ case OSD_SetBlock:
+ ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
+ break;
+ case OSD_FillRow:
+ ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
+ dc->x1-dc->x0+1, dc->y1, dc->color);
+ break;
+ case OSD_FillBlock:
+ ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
+ dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
+ break;
+ case OSD_Line:
+ ret = DrawLine(av7110, av7110->osdwin,
+ dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
+ break;
+ case OSD_Text:
+ {
+ char textbuf[240];
+
+ if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
+ ret = -EFAULT;
+ break;
+ }
+ textbuf[239] = 0;
+ if (dc->x1 > 3)
+ dc->x1 = 3;
+ ret = SetFont(av7110, av7110->osdwin, dc->x1,
+ (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
+ if (!ret)
+ ret = FlushText(av7110);
+ if (!ret)
+ ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
+ break;
+ }
+ case OSD_SetWindow:
+ if (dc->x0 < 1 || dc->x0 > 7)
+ ret = -EINVAL;
+ else {
+ av7110->osdwin = dc->x0;
+ ret = 0;
+ }
+ break;
+ case OSD_MoveWindow:
+ ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+ if (!ret)
+ ret = SetColorBlend(av7110, av7110->osdwin);
+ break;
+ case OSD_OpenRaw:
+ if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
+ ret = -EINVAL;
+ break;
+ }
+ if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
+ av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
+ else
+ av7110->osdbpp[av7110->osdwin] = 0;
+ ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
+ dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
+ if (ret)
+ break;
+ if (!dc->data) {
+ ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+ if (!ret)
+ ret = SetColorBlend(av7110, av7110->osdwin);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&av7110->osd_mutex);
+ if (ret==-ERESTARTSYS)
+ dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
+ else if (ret)
+ dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
+
+ return ret;
+}
+
+int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
+{
+ switch (cap->cmd) {
+ case OSD_CAP_MEMSIZE:
+ if (FW_4M_SDRAM(av7110->arm_app))
+ cap->val = 1000000;
+ else
+ cap->val = 92000;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+#endif /* CONFIG_DVB_AV7110_OSD */
diff --git a/drivers/staging/media/av7110/av7110_hw.h b/drivers/staging/media/av7110/av7110_hw.h
new file mode 100644
index 000000000000..6380d8950c69
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_hw.h
@@ -0,0 +1,496 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AV7110_HW_H_
+#define _AV7110_HW_H_
+
+#include "av7110.h"
+
+/* DEBI transfer mode defs */
+
+#define DEBINOSWAP 0x000e0000
+#define DEBISWAB 0x001e0000
+#define DEBISWAP 0x002e0000
+
+#define ARM_WAIT_FREE (HZ)
+#define ARM_WAIT_SHAKE (HZ/5)
+#define ARM_WAIT_OSD (HZ)
+
+
+enum av7110_bootstate
+{
+ BOOTSTATE_BUFFER_EMPTY = 0,
+ BOOTSTATE_BUFFER_FULL = 1,
+ BOOTSTATE_AV7110_BOOT_COMPLETE = 2
+};
+
+enum av7110_type_rec_play_format
+{ RP_None,
+ AudioPES,
+ AudioMp2,
+ AudioPCM,
+ VideoPES,
+ AV_PES
+};
+
+enum av7110_osd_palette_type
+{
+ NoPalet = 0, /* No palette */
+ Pal1Bit = 2, /* 2 colors for 1 Bit Palette */
+ Pal2Bit = 4, /* 4 colors for 2 bit palette */
+ Pal4Bit = 16, /* 16 colors for 4 bit palette */
+ Pal8Bit = 256 /* 256 colors for 16 bit palette */
+};
+
+/* switch defines */
+#define SB_GPIO 3
+#define SB_OFF SAA7146_GPIO_OUTLO /* SlowBlank off (TV-Mode) */
+#define SB_ON SAA7146_GPIO_INPUT /* SlowBlank on (AV-Mode) */
+#define SB_WIDE SAA7146_GPIO_OUTHI /* SlowBlank 6V (16/9-Mode) (not implemented) */
+
+#define FB_GPIO 1
+#define FB_OFF SAA7146_GPIO_LO /* FastBlank off (CVBS-Mode) */
+#define FB_ON SAA7146_GPIO_OUTHI /* FastBlank on (RGB-Mode) */
+#define FB_LOOP SAA7146_GPIO_INPUT /* FastBlank loop-through (PC graphics ???) */
+
+enum av7110_video_output_mode
+{
+ NO_OUT = 0, /* disable analog output */
+ CVBS_RGB_OUT = 1,
+ CVBS_YC_OUT = 2,
+ YC_OUT = 3
+};
+
+/* firmware internal msg q status: */
+#define GPMQFull 0x0001 /* Main Message Queue Full */
+#define GPMQOver 0x0002 /* Main Message Queue Overflow */
+#define HPQFull 0x0004 /* High Priority Msg Queue Full */
+#define HPQOver 0x0008
+#define OSDQFull 0x0010 /* OSD Queue Full */
+#define OSDQOver 0x0020
+#define GPMQBusy 0x0040 /* Queue not empty, FW >= 261d */
+#define HPQBusy 0x0080
+#define OSDQBusy 0x0100
+
+/* hw section filter flags */
+#define SECTION_EIT 0x01
+#define SECTION_SINGLE 0x00
+#define SECTION_CYCLE 0x02
+#define SECTION_CONTINUOS 0x04
+#define SECTION_MODE 0x06
+#define SECTION_IPMPE 0x0C /* size up to 4k */
+#define SECTION_HIGH_SPEED 0x1C /* larger buffer */
+#define DATA_PIPING_FLAG 0x20 /* for Data Piping Filter */
+
+#define PBUFSIZE_NONE 0x0000
+#define PBUFSIZE_1P 0x0100
+#define PBUFSIZE_2P 0x0200
+#define PBUFSIZE_1K 0x0300
+#define PBUFSIZE_2K 0x0400
+#define PBUFSIZE_4K 0x0500
+#define PBUFSIZE_8K 0x0600
+#define PBUFSIZE_16K 0x0700
+#define PBUFSIZE_32K 0x0800
+
+
+/* firmware command codes */
+enum av7110_osd_command {
+ WCreate,
+ WDestroy,
+ WMoveD,
+ WMoveA,
+ WHide,
+ WTop,
+ DBox,
+ DLine,
+ DText,
+ Set_Font,
+ SetColor,
+ SetBlend,
+ SetWBlend,
+ SetCBlend,
+ SetNonBlend,
+ LoadBmp,
+ BlitBmp,
+ ReleaseBmp,
+ SetWTrans,
+ SetWNoTrans,
+ Set_Palette
+};
+
+enum av7110_pid_command {
+ MultiPID,
+ VideoPID,
+ AudioPID,
+ InitFilt,
+ FiltError,
+ NewVersion,
+ CacheError,
+ AddPIDFilter,
+ DelPIDFilter,
+ Scan,
+ SetDescr,
+ SetIR,
+ FlushTSQueue
+};
+
+enum av7110_mpeg_command {
+ SelAudChannels
+};
+
+enum av7110_audio_command {
+ AudioDAC,
+ CabADAC,
+ ON22K,
+ OFF22K,
+ MainSwitch,
+ ADSwitch,
+ SendDiSEqC,
+ SetRegister,
+ SpdifSwitch
+};
+
+enum av7110_request_command {
+ AudioState,
+ AudioBuffState,
+ VideoState1,
+ VideoState2,
+ VideoState3,
+ CrashCounter,
+ ReqVersion,
+ ReqVCXO,
+ ReqRegister,
+ ReqSecFilterError,
+ ReqSTC
+};
+
+enum av7110_encoder_command {
+ SetVidMode,
+ SetTestMode,
+ LoadVidCode,
+ SetMonitorType,
+ SetPanScanType,
+ SetFreezeMode,
+ SetWSSConfig
+};
+
+enum av7110_rec_play_state {
+ __Record,
+ __Stop,
+ __Play,
+ __Pause,
+ __Slow,
+ __FF_IP,
+ __Scan_I,
+ __Continue
+};
+
+enum av7110_fw_cmd_misc {
+ AV7110_FW_VIDEO_ZOOM = 1,
+ AV7110_FW_VIDEO_COMMAND,
+ AV7110_FW_AUDIO_COMMAND
+};
+
+enum av7110_command_type {
+ COMTYPE_NOCOM,
+ COMTYPE_PIDFILTER,
+ COMTYPE_MPEGDECODER,
+ COMTYPE_OSD,
+ COMTYPE_BMP,
+ COMTYPE_ENCODER,
+ COMTYPE_AUDIODAC,
+ COMTYPE_REQUEST,
+ COMTYPE_SYSTEM,
+ COMTYPE_REC_PLAY,
+ COMTYPE_COMMON_IF,
+ COMTYPE_PID_FILTER,
+ COMTYPE_PES,
+ COMTYPE_TS,
+ COMTYPE_VIDEO,
+ COMTYPE_AUDIO,
+ COMTYPE_CI_LL,
+ COMTYPE_MISC = 0x80
+};
+
+#define VID_NONE_PREF 0x00 /* No aspect ration processing preferred */
+#define VID_PAN_SCAN_PREF 0x01 /* Pan and Scan Display preferred */
+#define VID_VERT_COMP_PREF 0x02 /* Vertical compression display preferred */
+#define VID_VC_AND_PS_PREF 0x03 /* PanScan and vertical Compression if allowed */
+#define VID_CENTRE_CUT_PREF 0x05 /* PanScan with zero vector */
+
+/* MPEG video decoder commands */
+#define AV_VIDEO_CMD_STOP 0x000e
+#define AV_VIDEO_CMD_PLAY 0x000d
+#define AV_VIDEO_CMD_FREEZE 0x0102
+#define AV_VIDEO_CMD_FFWD 0x0016
+#define AV_VIDEO_CMD_SLOW 0x0022
+
+/* MPEG audio decoder commands */
+#define AUDIO_CMD_MUTE 0x0001
+#define AUDIO_CMD_UNMUTE 0x0002
+#define AUDIO_CMD_PCM16 0x0010
+#define AUDIO_CMD_STEREO 0x0080
+#define AUDIO_CMD_MONO_L 0x0100
+#define AUDIO_CMD_MONO_R 0x0200
+#define AUDIO_CMD_SYNC_OFF 0x000e
+#define AUDIO_CMD_SYNC_ON 0x000f
+
+/* firmware data interface codes */
+#define DATA_NONE 0x00
+#define DATA_FSECTION 0x01
+#define DATA_IPMPE 0x02
+#define DATA_MPEG_RECORD 0x03
+#define DATA_DEBUG_MESSAGE 0x04
+#define DATA_COMMON_INTERFACE 0x05
+#define DATA_MPEG_PLAY 0x06
+#define DATA_BMP_LOAD 0x07
+#define DATA_IRCOMMAND 0x08
+#define DATA_PIPING 0x09
+#define DATA_STREAMING 0x0a
+#define DATA_CI_GET 0x0b
+#define DATA_CI_PUT 0x0c
+#define DATA_MPEG_VIDEO_EVENT 0x0d
+
+#define DATA_PES_RECORD 0x10
+#define DATA_PES_PLAY 0x11
+#define DATA_TS_RECORD 0x12
+#define DATA_TS_PLAY 0x13
+
+/* ancient CI command codes, only two are actually still used
+ * by the link level CI firmware */
+#define CI_CMD_ERROR 0x00
+#define CI_CMD_ACK 0x01
+#define CI_CMD_SYSTEM_READY 0x02
+#define CI_CMD_KEYPRESS 0x03
+#define CI_CMD_ON_TUNED 0x04
+#define CI_CMD_ON_SWITCH_PROGRAM 0x05
+#define CI_CMD_SECTION_ARRIVED 0x06
+#define CI_CMD_SECTION_TIMEOUT 0x07
+#define CI_CMD_TIME 0x08
+#define CI_CMD_ENTER_MENU 0x09
+#define CI_CMD_FAST_PSI 0x0a
+#define CI_CMD_GET_SLOT_INFO 0x0b
+
+#define CI_MSG_NONE 0x00
+#define CI_MSG_CI_INFO 0x01
+#define CI_MSG_MENU 0x02
+#define CI_MSG_LIST 0x03
+#define CI_MSG_TEXT 0x04
+#define CI_MSG_REQUEST_INPUT 0x05
+#define CI_MSG_INPUT_COMPLETE 0x06
+#define CI_MSG_LIST_MORE 0x07
+#define CI_MSG_MENU_MORE 0x08
+#define CI_MSG_CLOSE_MMI_IMM 0x09
+#define CI_MSG_SECTION_REQUEST 0x0a
+#define CI_MSG_CLOSE_FILTER 0x0b
+#define CI_PSI_COMPLETE 0x0c
+#define CI_MODULE_READY 0x0d
+#define CI_SWITCH_PRG_REPLY 0x0e
+#define CI_MSG_TEXT_MORE 0x0f
+
+#define CI_MSG_CA_PMT 0xe0
+#define CI_MSG_ERROR 0xf0
+
+
+/* base address of the dual ported RAM which serves as communication
+ * area between PCI bus and av7110,
+ * as seen by the DEBI bus of the saa7146 */
+#define DPRAM_BASE 0x4000
+
+/* boot protocol area */
+#define AV7110_BOOT_STATE (DPRAM_BASE + 0x3F8)
+#define AV7110_BOOT_SIZE (DPRAM_BASE + 0x3FA)
+#define AV7110_BOOT_BASE (DPRAM_BASE + 0x3FC)
+#define AV7110_BOOT_BLOCK (DPRAM_BASE + 0x400)
+#define AV7110_BOOT_MAX_SIZE 0xc00
+
+/* firmware command protocol area */
+#define IRQ_STATE (DPRAM_BASE + 0x0F4)
+#define IRQ_STATE_EXT (DPRAM_BASE + 0x0F6)
+#define MSGSTATE (DPRAM_BASE + 0x0F8)
+#define COMMAND (DPRAM_BASE + 0x0FC)
+#define COM_BUFF (DPRAM_BASE + 0x100)
+#define COM_BUFF_SIZE 0x20
+
+/* various data buffers */
+#define BUFF1_BASE (DPRAM_BASE + 0x120)
+#define BUFF1_SIZE 0xE0
+
+#define DATA_BUFF0_BASE (DPRAM_BASE + 0x200)
+#define DATA_BUFF0_SIZE 0x0800
+
+#define DATA_BUFF1_BASE (DATA_BUFF0_BASE+DATA_BUFF0_SIZE)
+#define DATA_BUFF1_SIZE 0x0800
+
+#define DATA_BUFF2_BASE (DATA_BUFF1_BASE+DATA_BUFF1_SIZE)
+#define DATA_BUFF2_SIZE 0x0800
+
+#define DATA_BUFF3_BASE (DATA_BUFF2_BASE+DATA_BUFF2_SIZE)
+#define DATA_BUFF3_SIZE 0x0400
+
+#define Reserved (DPRAM_BASE + 0x1E00)
+#define Reserved_SIZE 0x1C0
+
+
+/* firmware status area */
+#define STATUS_BASE (DPRAM_BASE + 0x1FC0)
+#define STATUS_LOOPS (STATUS_BASE + 0x08)
+
+#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C)
+/* ((aspect_ratio & 0xf) << 12) | (height & 0xfff) */
+#define STATUS_MPEG_HEIGHT_AR (STATUS_BASE + 0x0E)
+
+/* firmware data protocol area */
+#define RX_TYPE (DPRAM_BASE + 0x1FE8)
+#define RX_LEN (DPRAM_BASE + 0x1FEA)
+#define TX_TYPE (DPRAM_BASE + 0x1FEC)
+#define TX_LEN (DPRAM_BASE + 0x1FEE)
+
+#define RX_BUFF (DPRAM_BASE + 0x1FF4)
+#define TX_BUFF (DPRAM_BASE + 0x1FF6)
+
+#define HANDSHAKE_REG (DPRAM_BASE + 0x1FF8)
+#define COM_IF_LOCK (DPRAM_BASE + 0x1FFA)
+
+#define IRQ_RX (DPRAM_BASE + 0x1FFC)
+#define IRQ_TX (DPRAM_BASE + 0x1FFE)
+
+/* used by boot protocol to load firmware into av7110 DRAM */
+#define DRAM_START_CODE 0x2e000404
+#define DRAM_MAX_CODE_SIZE 0x00100000
+
+/* saa7146 gpio lines */
+#define RESET_LINE 2
+#define DEBI_DONE_LINE 1
+#define ARM_IRQ_LINE 0
+
+
+
+extern int av7110_bootarm(struct av7110 *av7110);
+extern int av7110_firmversion(struct av7110 *av7110);
+#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
+#define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000)
+#define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF)
+
+extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags);
+extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...);
+extern int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ int request_buf_len, u16 *reply_buf, int reply_buf_len);
+
+
+/* DEBI (saa7146 data extension bus interface) access */
+extern int av7110_debiwrite(struct av7110 *av7110, u32 config,
+ int addr, u32 val, unsigned int count);
+extern u32 av7110_debiread(struct av7110 *av7110, u32 config,
+ int addr, unsigned int count);
+
+
+/* DEBI during interrupt */
+/* single word writes */
+static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count)
+{
+ av7110_debiwrite(av7110, config, addr, val, count);
+}
+
+/* buffer writes */
+static inline void mwdebi(struct av7110 *av7110, u32 config, int addr,
+ const u8 *val, int count)
+{
+ memcpy(av7110->debi_virt, val, count);
+ av7110_debiwrite(av7110, config, addr, 0, count);
+}
+
+static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count)
+{
+ u32 res;
+
+ res=av7110_debiread(av7110, config, addr, count);
+ if (count<=4)
+ memcpy(av7110->debi_virt, (char *) &res, count);
+ return res;
+}
+
+/* DEBI outside interrupts, only for count <= 4! */
+static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&av7110->debilock, flags);
+ av7110_debiwrite(av7110, config, addr, val, count);
+ spin_unlock_irqrestore(&av7110->debilock, flags);
+}
+
+static inline u32 rdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count)
+{
+ unsigned long flags;
+ u32 res;
+
+ spin_lock_irqsave(&av7110->debilock, flags);
+ res=av7110_debiread(av7110, config, addr, count);
+ spin_unlock_irqrestore(&av7110->debilock, flags);
+ return res;
+}
+
+/* handle mailbox registers of the dual ported RAM */
+static inline void ARM_ResetMailBox(struct av7110 *av7110)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&av7110->debilock, flags);
+ av7110_debiread(av7110, DEBINOSWAP, IRQ_RX, 2);
+ av7110_debiwrite(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
+ spin_unlock_irqrestore(&av7110->debilock, flags);
+}
+
+static inline void ARM_ClearMailBox(struct av7110 *av7110)
+{
+ iwdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
+}
+
+static inline void ARM_ClearIrq(struct av7110 *av7110)
+{
+ irdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
+}
+
+/****************************************************************************
+ * Firmware commands
+ ****************************************************************************/
+
+static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);
+}
+
+static inline int av7710_set_video_mode(struct av7110 *av7110, int mode)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
+}
+
+static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_VIDEO_COMMAND, 4,
+ (com>>16), (com&0xffff),
+ (arg>>16), (arg&0xffff));
+}
+
+static inline int audcom(struct av7110 *av7110, u32 com)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 2,
+ (com>>16), (com&0xffff));
+}
+
+static inline int Set22K(struct av7110 *av7110, int state)
+{
+ return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0);
+}
+
+
+extern int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst);
+
+
+#ifdef CONFIG_DVB_AV7110_OSD
+extern int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc);
+extern int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap);
+#endif /* CONFIG_DVB_AV7110_OSD */
+
+
+
+#endif /* _AV7110_HW_H_ */
diff --git a/drivers/staging/media/av7110/av7110_ipack.c b/drivers/staging/media/av7110/av7110_ipack.c
new file mode 100644
index 000000000000..30330ed01ce8
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_ipack.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "dvb_filter.h"
+#include "av7110_ipack.h"
+#include <linux/string.h> /* for memcpy() */
+#include <linux/vmalloc.h>
+
+
+void av7110_ipack_reset(struct ipack *p)
+{
+ p->found = 0;
+ p->cid = 0;
+ p->plength = 0;
+ p->flag1 = 0;
+ p->flag2 = 0;
+ p->hlength = 0;
+ p->mpeg = 0;
+ p->check = 0;
+ p->which = 0;
+ p->done = 0;
+ p->count = 0;
+}
+
+
+int av7110_ipack_init(struct ipack *p, int size,
+ void (*func)(u8 *buf, int size, void *priv))
+{
+ if (!(p->buf = vmalloc(size))) {
+ printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
+ return -ENOMEM;
+ }
+ p->size = size;
+ p->func = func;
+ p->repack_subids = 0;
+ av7110_ipack_reset(p);
+ return 0;
+}
+
+
+void av7110_ipack_free(struct ipack *p)
+{
+ vfree(p->buf);
+}
+
+
+static void send_ipack(struct ipack *p)
+{
+ int off;
+ struct dvb_audio_info ai;
+ int ac3_off = 0;
+ int streamid = 0;
+ int nframes = 0;
+ int f = 0;
+
+ switch (p->mpeg) {
+ case 2:
+ if (p->count < 10)
+ return;
+ p->buf[3] = p->cid;
+ p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
+ p->buf[5] = (u8)((p->count - 6) & 0x00ff);
+ if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
+ off = 9 + p->buf[8];
+ streamid = p->buf[off];
+ if ((streamid & 0xf8) == 0x80) {
+ ai.off = 0;
+ ac3_off = ((p->buf[off + 2] << 8)|
+ p->buf[off + 3]);
+ if (ac3_off < p->count)
+ f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
+ p->count - ac3_off, &ai, 0);
+ if (!f) {
+ nframes = (p->count - off - 3 - ac3_off) /
+ ai.framesize + 1;
+ p->buf[off + 2] = (ac3_off >> 8) & 0xff;
+ p->buf[off + 3] = (ac3_off) & 0xff;
+ p->buf[off + 1] = nframes;
+ ac3_off += nframes * ai.framesize - p->count;
+ }
+ }
+ }
+ p->func(p->buf, p->count, p->data);
+
+ p->buf[6] = 0x80;
+ p->buf[7] = 0x00;
+ p->buf[8] = 0x00;
+ p->count = 9;
+ if (p->repack_subids && p->cid == PRIVATE_STREAM1
+ && (streamid & 0xf8) == 0x80) {
+ p->count += 4;
+ p->buf[9] = streamid;
+ p->buf[10] = (ac3_off >> 8) & 0xff;
+ p->buf[11] = (ac3_off) & 0xff;
+ p->buf[12] = 0;
+ }
+ break;
+
+ case 1:
+ if (p->count < 8)
+ return;
+ p->buf[3] = p->cid;
+ p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
+ p->buf[5] = (u8)((p->count - 6) & 0x00ff);
+ p->func(p->buf, p->count, p->data);
+
+ p->buf[6] = 0x0f;
+ p->count = 7;
+ break;
+ }
+}
+
+
+void av7110_ipack_flush(struct ipack *p)
+{
+ if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
+ return;
+ p->plength = p->found - 6;
+ p->found = 0;
+ send_ipack(p);
+ av7110_ipack_reset(p);
+}
+
+
+static void write_ipack(struct ipack *p, const u8 *data, int count)
+{
+ u8 headr[3] = { 0x00, 0x00, 0x01 };
+
+ if (p->count < 6) {
+ memcpy(p->buf, headr, 3);
+ p->count = 6;
+ }
+
+ if (p->count + count < p->size){
+ memcpy(p->buf+p->count, data, count);
+ p->count += count;
+ } else {
+ int rest = p->size - p->count;
+ memcpy(p->buf+p->count, data, rest);
+ p->count += rest;
+ send_ipack(p);
+ if (count - rest > 0)
+ write_ipack(p, data + rest, count - rest);
+ }
+}
+
+
+int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
+{
+ int l;
+ int c = 0;
+
+ while (c < count && (p->mpeg == 0 ||
+ (p->mpeg == 1 && p->found < 7) ||
+ (p->mpeg == 2 && p->found < 9))
+ && (p->found < 5 || !p->done)) {
+ switch (p->found) {
+ case 0:
+ case 1:
+ if (buf[c] == 0x00)
+ p->found++;
+ else
+ p->found = 0;
+ c++;
+ break;
+ case 2:
+ if (buf[c] == 0x01)
+ p->found++;
+ else if (buf[c] == 0)
+ p->found = 2;
+ else
+ p->found = 0;
+ c++;
+ break;
+ case 3:
+ p->cid = 0;
+ switch (buf[c]) {
+ case PROG_STREAM_MAP:
+ case PRIVATE_STREAM2:
+ case PROG_STREAM_DIR:
+ case ECM_STREAM :
+ case EMM_STREAM :
+ case PADDING_STREAM :
+ case DSM_CC_STREAM :
+ case ISO13522_STREAM:
+ p->done = 1;
+ fallthrough;
+ case PRIVATE_STREAM1:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ p->found++;
+ p->cid = buf[c];
+ c++;
+ break;
+ default:
+ p->found = 0;
+ break;
+ }
+ break;
+
+ case 4:
+ if (count-c > 1) {
+ p->plen[0] = buf[c];
+ c++;
+ p->plen[1] = buf[c];
+ c++;
+ p->found += 2;
+ p->plength = (p->plen[0] << 8) | p->plen[1];
+ } else {
+ p->plen[0] = buf[c];
+ p->found++;
+ return count;
+ }
+ break;
+ case 5:
+ p->plen[1] = buf[c];
+ c++;
+ p->found++;
+ p->plength = (p->plen[0] << 8) | p->plen[1];
+ break;
+ case 6:
+ if (!p->done) {
+ p->flag1 = buf[c];
+ c++;
+ p->found++;
+ if ((p->flag1 & 0xc0) == 0x80)
+ p->mpeg = 2;
+ else {
+ p->hlength = 0;
+ p->which = 0;
+ p->mpeg = 1;
+ p->flag2 = 0;
+ }
+ }
+ break;
+
+ case 7:
+ if (!p->done && p->mpeg == 2) {
+ p->flag2 = buf[c];
+ c++;
+ p->found++;
+ }
+ break;
+
+ case 8:
+ if (!p->done && p->mpeg == 2) {
+ p->hlength = buf[c];
+ c++;
+ p->found++;
+ }
+ break;
+ }
+ }
+
+ if (c == count)
+ return count;
+
+ if (!p->plength)
+ p->plength = MMAX_PLENGTH - 6;
+
+ if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
+ (p->mpeg == 1 && p->found >= 7))) {
+ switch (p->cid) {
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ case PRIVATE_STREAM1:
+ if (p->mpeg == 2 && p->found == 9) {
+ write_ipack(p, &p->flag1, 1);
+ write_ipack(p, &p->flag2, 1);
+ write_ipack(p, &p->hlength, 1);
+ }
+
+ if (p->mpeg == 1 && p->found == 7)
+ write_ipack(p, &p->flag1, 1);
+
+ if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
+ p->found < 14) {
+ while (c < count && p->found < 14) {
+ p->pts[p->found - 9] = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ }
+ if (c == count)
+ return count;
+ }
+
+ if (p->mpeg == 1 && p->which < 2000) {
+
+ if (p->found == 7) {
+ p->check = p->flag1;
+ p->hlength = 1;
+ }
+
+ while (!p->which && c < count &&
+ p->check == 0xff){
+ p->check = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->hlength++;
+ }
+
+ if (c == count)
+ return count;
+
+ if ((p->check & 0xc0) == 0x40 && !p->which) {
+ p->check = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->hlength++;
+
+ p->which = 1;
+ if (c == count)
+ return count;
+ p->check = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->hlength++;
+ p->which = 2;
+ if (c == count)
+ return count;
+ }
+
+ if (p->which == 1) {
+ p->check = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->hlength++;
+ p->which = 2;
+ if (c == count)
+ return count;
+ }
+
+ if ((p->check & 0x30) && p->check != 0xff) {
+ p->flag2 = (p->check & 0xf0) << 2;
+ p->pts[0] = p->check;
+ p->which = 3;
+ }
+
+ if (c == count)
+ return count;
+ if (p->which > 2){
+ if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
+ while (c < count && p->which < 7) {
+ p->pts[p->which - 2] = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->which++;
+ p->hlength++;
+ }
+ if (c == count)
+ return count;
+ } else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
+ while (c < count && p->which < 12) {
+ if (p->which < 7)
+ p->pts[p->which - 2] = buf[c];
+ write_ipack(p, buf + c, 1);
+ c++;
+ p->found++;
+ p->which++;
+ p->hlength++;
+ }
+ if (c == count)
+ return count;
+ }
+ p->which = 2000;
+ }
+
+ }
+
+ while (c < count && p->found < p->plength + 6) {
+ l = count - c;
+ if (l + p->found > p->plength + 6)
+ l = p->plength + 6 - p->found;
+ write_ipack(p, buf + c, l);
+ p->found += l;
+ c += l;
+ }
+ break;
+ }
+
+
+ if (p->done) {
+ if (p->found + count - c < p->plength + 6) {
+ p->found += count - c;
+ c = count;
+ } else {
+ c += p->plength + 6 - p->found;
+ p->found = p->plength + 6;
+ }
+ }
+
+ if (p->plength && p->found == p->plength + 6) {
+ send_ipack(p);
+ av7110_ipack_reset(p);
+ if (c < count)
+ av7110_ipack_instant_repack(buf + c, count - c, p);
+ }
+ }
+ return count;
+}
diff --git a/drivers/staging/media/av7110/av7110_ipack.h b/drivers/staging/media/av7110/av7110_ipack.h
new file mode 100644
index 000000000000..943ec899bb93
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_ipack.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AV7110_IPACK_H_
+#define _AV7110_IPACK_H_
+
+extern int av7110_ipack_init(struct ipack *p, int size,
+ void (*func)(u8 *buf, int size, void *priv));
+
+extern void av7110_ipack_reset(struct ipack *p);
+extern int av7110_ipack_instant_repack(const u8 *buf, int count, struct ipack *p);
+extern void av7110_ipack_free(struct ipack * p);
+extern void av7110_ipack_flush(struct ipack *p);
+
+#endif
diff --git a/drivers/staging/media/av7110/av7110_ir.c b/drivers/staging/media/av7110/av7110_ir.c
new file mode 100644
index 000000000000..a851ba328e4a
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_ir.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for the remote control of SAA7146 based AV7110 cards
+ *
+ * Copyright (C) 1999-2003 Holger Waechtler <holger@convergence.de>
+ * Copyright (C) 2003-2007 Oliver Endriss <o.endriss@gmx.de>
+ * Copyright (C) 2019 Sean Young <sean@mess.org>
+ */
+
+#include <linux/kernel.h>
+#include <media/rc-core.h>
+
+#include "av7110.h"
+#include "av7110_hw.h"
+
+#define IR_RC5 0
+#define IR_RCMM 1
+#define IR_RC5_EXT 2 /* internal only */
+
+/* interrupt handler */
+void av7110_ir_handler(struct av7110 *av7110, u32 ircom)
+{
+ struct rc_dev *rcdev = av7110->ir.rcdev;
+ enum rc_proto proto;
+ u32 command, addr, scancode;
+ u32 toggle;
+
+ dprintk(4, "ir command = %08x\n", ircom);
+
+ if (rcdev) {
+ switch (av7110->ir.ir_config) {
+ case IR_RC5: /* RC5: 5 bits device address, 6 bits command */
+ command = ircom & 0x3f;
+ addr = (ircom >> 6) & 0x1f;
+ scancode = RC_SCANCODE_RC5(addr, command);
+ toggle = ircom & 0x0800;
+ proto = RC_PROTO_RC5;
+ break;
+
+ case IR_RCMM: /* RCMM: 32 bits scancode */
+ scancode = ircom & ~0x8000;
+ toggle = ircom & 0x8000;
+ proto = RC_PROTO_RCMM32;
+ break;
+
+ case IR_RC5_EXT:
+ /*
+ * extended RC5: 5 bits device address, 7 bits command
+ *
+ * Extended RC5 uses only one start bit. The second
+ * start bit is re-assigned bit 6 of the command bit.
+ */
+ command = ircom & 0x3f;
+ addr = (ircom >> 6) & 0x1f;
+ if (!(ircom & 0x1000))
+ command |= 0x40;
+ scancode = RC_SCANCODE_RC5(addr, command);
+ toggle = ircom & 0x0800;
+ proto = RC_PROTO_RC5;
+ break;
+ default:
+ dprintk(2, "unknown ir config %d\n",
+ av7110->ir.ir_config);
+ return;
+ }
+
+ rc_keydown(rcdev, proto, scancode, toggle != 0);
+ }
+}
+
+int av7110_set_ir_config(struct av7110 *av7110)
+{
+ dprintk(4, "ir config = %08x\n", av7110->ir.ir_config);
+
+ return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1,
+ av7110->ir.ir_config);
+}
+
+static int change_protocol(struct rc_dev *rcdev, u64 *rc_type)
+{
+ struct av7110 *av7110 = rcdev->priv;
+ u32 ir_config;
+
+ if (*rc_type & RC_PROTO_BIT_RCMM32) {
+ ir_config = IR_RCMM;
+ *rc_type = RC_PROTO_BIT_RCMM32;
+ } else if (*rc_type & RC_PROTO_BIT_RC5) {
+ if (FW_VERSION(av7110->arm_app) >= 0x2620)
+ ir_config = IR_RC5_EXT;
+ else
+ ir_config = IR_RC5;
+ *rc_type = RC_PROTO_BIT_RC5;
+ } else {
+ return -EINVAL;
+ }
+
+ if (ir_config == av7110->ir.ir_config)
+ return 0;
+
+ av7110->ir.ir_config = ir_config;
+
+ return av7110_set_ir_config(av7110);
+}
+
+int av7110_ir_init(struct av7110 *av7110)
+{
+ struct rc_dev *rcdev;
+ struct pci_dev *pci;
+ int ret;
+
+ rcdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rcdev)
+ return -ENOMEM;
+
+ pci = av7110->dev->pci;
+
+ snprintf(av7110->ir.input_phys, sizeof(av7110->ir.input_phys),
+ "pci-%s/ir0", pci_name(pci));
+
+ rcdev->device_name = av7110->card_name;
+ rcdev->driver_name = KBUILD_MODNAME;
+ rcdev->input_phys = av7110->ir.input_phys;
+ rcdev->input_id.bustype = BUS_PCI;
+ rcdev->input_id.version = 2;
+ if (pci->subsystem_vendor) {
+ rcdev->input_id.vendor = pci->subsystem_vendor;
+ rcdev->input_id.product = pci->subsystem_device;
+ } else {
+ rcdev->input_id.vendor = pci->vendor;
+ rcdev->input_id.product = pci->device;
+ }
+
+ rcdev->dev.parent = &pci->dev;
+ rcdev->allowed_protocols = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RCMM32;
+ rcdev->change_protocol = change_protocol;
+ rcdev->map_name = RC_MAP_HAUPPAUGE;
+ rcdev->priv = av7110;
+
+ av7110->ir.rcdev = rcdev;
+ av7110->ir.ir_config = IR_RC5;
+ av7110_set_ir_config(av7110);
+
+ ret = rc_register_device(rcdev);
+ if (ret) {
+ av7110->ir.rcdev = NULL;
+ rc_free_device(rcdev);
+ }
+
+ return ret;
+}
+
+void av7110_ir_exit(struct av7110 *av7110)
+{
+ rc_unregister_device(av7110->ir.rcdev);
+}
+
+//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
+//MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/av7110/av7110_v4l.c b/drivers/staging/media/av7110/av7110_v4l.c
new file mode 100644
index 000000000000..c89f536f699c
--- /dev/null
+++ b/drivers/staging/media/av7110/av7110_v4l.c
@@ -0,0 +1,952 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * av7110_v4l.c: av7110 video4linux interface for DVB and Siemens DVB-C analog module
+ *
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * originally based on code by:
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/poll.h>
+
+#include "av7110.h"
+#include "av7110_hw.h"
+#include "av7110_av.h"
+
+int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
+{
+ u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
+ struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };
+
+ switch (av7110->adac_type) {
+ case DVB_ADAC_MSP34x0:
+ msgs.addr = 0x40;
+ break;
+ case DVB_ADAC_MSP34x5:
+ msgs.addr = 0x42;
+ break;
+ default:
+ return 0;
+ }
+
+ if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
+ dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
+ av7110->dvb_adapter.num, reg, val);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
+{
+ u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
+ u8 msg2[2];
+ struct i2c_msg msgs[2] = {
+ { .flags = 0 , .len = 3, .buf = msg1 },
+ { .flags = I2C_M_RD, .len = 2, .buf = msg2 }
+ };
+
+ switch (av7110->adac_type) {
+ case DVB_ADAC_MSP34x0:
+ msgs[0].addr = 0x40;
+ msgs[1].addr = 0x40;
+ break;
+ case DVB_ADAC_MSP34x5:
+ msgs[0].addr = 0x42;
+ msgs[1].addr = 0x42;
+ break;
+ default:
+ return 0;
+ }
+
+ if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
+ dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
+ av7110->dvb_adapter.num, reg);
+ return -EIO;
+ }
+ *val = (msg2[0] << 8) | msg2[1];
+ return 0;
+}
+
+static struct v4l2_input inputs[4] = {
+ {
+ .index = 0,
+ .name = "DVB",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 1,
+ .tuner = 0, /* ignored */
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ .capabilities = V4L2_IN_CAP_STD,
+ }, {
+ .index = 1,
+ .name = "Television",
+ .type = V4L2_INPUT_TYPE_TUNER,
+ .audioset = 1,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ .capabilities = V4L2_IN_CAP_STD,
+ }, {
+ .index = 2,
+ .name = "Video",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ .capabilities = V4L2_IN_CAP_STD,
+ }, {
+ .index = 3,
+ .name = "Y/C",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ .capabilities = V4L2_IN_CAP_STD,
+ }
+};
+
+static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
+{
+ struct av7110 *av7110 = dev->ext_priv;
+ u8 buf[] = { 0x00, reg, data };
+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+ dprintk(4, "dev: %p\n", dev);
+
+ if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
+ return -1;
+ return 0;
+}
+
+static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
+{
+ struct av7110 *av7110 = dev->ext_priv;
+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
+
+ dprintk(4, "dev: %p\n", dev);
+
+ if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
+ return -1;
+ return 0;
+}
+
+static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
+{
+ u32 div;
+ u8 config;
+ u8 buf[4];
+
+ dprintk(4, "freq: 0x%08x\n", freq);
+
+ /* magic number: 614. tuning with the frequency given by v4l2
+ is always off by 614*62.5 = 38375 kHz...*/
+ div = freq + 614;
+
+ buf[0] = (div >> 8) & 0x7f;
+ buf[1] = div & 0xff;
+ buf[2] = 0x8e;
+
+ if (freq < 16U * 16825 / 100)
+ config = 0xa0;
+ else if (freq < 16U * 44725 / 100)
+ config = 0x90;
+ else
+ config = 0x30;
+ config &= ~0x02;
+
+ buf[3] = config;
+
+ return tuner_write(dev, 0x61, buf);
+}
+
+static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
+{
+ struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
+ u32 div;
+ u8 data[4];
+
+ div = (freq + 38900000 + 31250) / 62500;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0xce;
+
+ if (freq < 45000000)
+ return -EINVAL;
+ else if (freq < 137000000)
+ data[3] = 0x01;
+ else if (freq < 403000000)
+ data[3] = 0x02;
+ else if (freq < 860000000)
+ data[3] = 0x04;
+ else
+ return -EINVAL;
+
+ if (av7110->fe->ops.i2c_gate_ctrl)
+ av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
+ return tuner_write(dev, 0x63, data);
+}
+
+
+
+static struct saa7146_standard analog_standard[];
+static struct saa7146_standard dvb_standard[];
+static struct saa7146_standard standard[];
+
+static const struct v4l2_audio msp3400_v4l2_audio = {
+ .index = 0,
+ .name = "Television",
+ .capability = V4L2_AUDCAP_STEREO
+};
+
+static int av7110_dvb_c_switch(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
+ u16 adswitch;
+ int source, sync, err;
+
+ dprintk(4, "%p\n", av7110);
+
+ if ((vv->video_status & STATUS_OVERLAY) != 0) {
+ vv->ov_suspend = vv->video_fh;
+ err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
+ if (err != 0) {
+ dprintk(2, "suspending video failed\n");
+ vv->ov_suspend = NULL;
+ }
+ }
+
+ if (0 != av7110->current_input) {
+ dprintk(1, "switching to analog TV:\n");
+ adswitch = 1;
+ source = SAA7146_HPS_SOURCE_PORT_B;
+ sync = SAA7146_HPS_SYNC_PORT_B;
+ memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
+
+ switch (av7110->current_input) {
+ case 1:
+ dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
+
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+ if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
+ dprintk(1, "setting band in demodulator failed\n");
+ } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
+ }
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 2:
+ dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 3:
+ dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ default:
+ dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
+ }
+ } else {
+ adswitch = 0;
+ source = SAA7146_HPS_SOURCE_PORT_A;
+ sync = SAA7146_HPS_SYNC_PORT_A;
+ memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
+ dprintk(1, "switching DVB mode\n");
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
+
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+ if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
+ dprintk(1, "setting band in demodulator failed\n");
+ } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
+ }
+ }
+
+ /* hmm, this does not do anything!? */
+ if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
+ dprintk(1, "ADSwitch error\n");
+
+ saa7146_set_hps_source_and_sync(dev, source, sync);
+
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+ u16 stereo_det;
+ s8 stereo;
+
+ dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
+
+ if (!av7110->analog_tuner_flags || t->index != 0)
+ return -EINVAL;
+
+ memset(t, 0, sizeof(*t));
+ strscpy((char *)t->name, "Television", sizeof(t->name));
+
+ t->type = V4L2_TUNER_ANALOG_TV;
+ t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+ t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
+ t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
+ /* FIXME: add the real signal strength here */
+ t->signal = 0xffff;
+ t->afc = 0;
+
+ /* FIXME: standard / stereo detection is still broken */
+ msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
+ dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
+ msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
+ dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
+ stereo = (s8)(stereo_det >> 8);
+ if (stereo > 0x10) {
+ /* stereo */
+ t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ } else if (stereo < -0x10) {
+ /* bilingual */
+ t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ } else /* mono */
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+ u16 fm_matrix, src;
+ dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
+
+ if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+ return -EINVAL;
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_STEREO:
+ dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
+ fm_matrix = 0x3001; /* stereo */
+ src = 0x0020;
+ break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
+ fm_matrix = 0x3000; /* bilingual */
+ src = 0x0020;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
+ fm_matrix = 0x3000; /* mono */
+ src = 0x0000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
+ fm_matrix = 0x3000; /* mono */
+ src = 0x0010;
+ break;
+ default: /* case V4L2_TUNER_MODE_MONO: */
+ dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
+ fm_matrix = 0x3000; /* mono */
+ src = 0x0030;
+ break;
+ }
+ msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
+ return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
+
+ if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+ return -EINVAL;
+
+ memset(f, 0, sizeof(*f));
+ f->type = V4L2_TUNER_ANALOG_TV;
+ f->frequency = av7110->current_freq;
+ return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
+
+ if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+ return -EINVAL;
+
+ if (V4L2_TUNER_ANALOG_TV != f->type)
+ return -EINVAL;
+
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); /* fast mute */
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
+
+ /* tune in desired frequency */
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820)
+ ves1820_set_tv_freq(dev, f->frequency);
+ else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297)
+ stv0297_set_tv_freq(dev, f->frequency);
+ av7110->current_freq = f->frequency;
+
+ msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); /* start stereo detection */
+ msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); /* loudspeaker + headphone */
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); /* SCART 1 volume */
+ return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
+
+ if (av7110->analog_tuner_flags) {
+ if (i->index >= 4)
+ return -EINVAL;
+ } else {
+ if (i->index != 0)
+ return -EINVAL;
+ }
+
+ memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
+
+ return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ *input = av7110->current_input;
+ dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
+ return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
+
+ if (!av7110->analog_tuner_flags)
+ return input ? -EINVAL : 0;
+
+ if (input >= 4)
+ return -EINVAL;
+
+ av7110->current_input = input;
+ return av7110_dvb_c_switch(fh);
+}
+
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
+ if (a->index != 0)
+ return -EINVAL;
+ *a = msp3400_v4l2_audio;
+ return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
+ if (a->index != 0)
+ return -EINVAL;
+ if (av7110->current_input >= 2)
+ return -EINVAL;
+ *a = msp3400_v4l2_audio;
+ return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
+ if (av7110->current_input >= 2)
+ return -EINVAL;
+ return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
+ struct v4l2_sliced_vbi_cap *cap)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
+ if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
+ return -EINVAL;
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ cap->service_set = V4L2_SLICED_WSS_625;
+ cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+ }
+ return 0;
+}
+
+static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_G_FMT:\n");
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EINVAL;
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ if (av7110->wssMode) {
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
+ }
+ return 0;
+}
+
+static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+ dprintk(2, "VIDIOC_S_FMT\n");
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EINVAL;
+ if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
+ f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
+ memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+ /* WSS controlled by firmware */
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
+ SetWSSConfig, 1, 0);
+ } else {
+ memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
+ /* WSS controlled by userspace */
+ av7110->wssMode = 1;
+ av7110->wssData = 0;
+ }
+ return 0;
+}
+
+static int av7110_vbi_reset(struct file *file)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+ dprintk(2, "%s\n", __func__);
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return 0;
+ else
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+}
+
+static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+ struct v4l2_sliced_vbi_data d;
+ int rc;
+
+ dprintk(2, "%s\n", __func__);
+ if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ return -EINVAL;
+ if (copy_from_user(&d, data, count))
+ return -EFAULT;
+ if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
+ return -EINVAL;
+ if (d.id)
+ av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
+ else
+ av7110->wssData = 0x8000;
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);
+ return (rc < 0) ? rc : count;
+}
+
+/****************************************************************************
+ * INITIALIZATION
+ ****************************************************************************/
+
+static u8 saa7113_init_regs[] = {
+ 0x02, 0xd0,
+ 0x03, 0x23,
+ 0x04, 0x00,
+ 0x05, 0x00,
+ 0x06, 0xe9,
+ 0x07, 0x0d,
+ 0x08, 0x98,
+ 0x09, 0x02,
+ 0x0a, 0x80,
+ 0x0b, 0x40,
+ 0x0c, 0x40,
+ 0x0d, 0x00,
+ 0x0e, 0x01,
+ 0x0f, 0x7c,
+ 0x10, 0x48,
+ 0x11, 0x0c,
+ 0x12, 0x8b,
+ 0x13, 0x1a,
+ 0x14, 0x00,
+ 0x15, 0x00,
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1b, 0x00,
+ 0x1c, 0x00,
+ 0x1d, 0x00,
+ 0x1e, 0x00,
+
+ 0x41, 0x77,
+ 0x42, 0x77,
+ 0x43, 0x77,
+ 0x44, 0x77,
+ 0x45, 0x77,
+ 0x46, 0x77,
+ 0x47, 0x77,
+ 0x48, 0x77,
+ 0x49, 0x77,
+ 0x4a, 0x77,
+ 0x4b, 0x77,
+ 0x4c, 0x77,
+ 0x4d, 0x77,
+ 0x4e, 0x77,
+ 0x4f, 0x77,
+ 0x50, 0x77,
+ 0x51, 0x77,
+ 0x52, 0x77,
+ 0x53, 0x77,
+ 0x54, 0x77,
+ 0x55, 0x77,
+ 0x56, 0x77,
+ 0x57, 0xff,
+
+ 0xff
+};
+
+
+static struct saa7146_ext_vv av7110_vv_data_st;
+static struct saa7146_ext_vv av7110_vv_data_c;
+
+int av7110_init_analog_module(struct av7110 *av7110)
+{
+ u16 version1, version2;
+
+ if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
+ i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_MSP34x0;
+ } else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
+ i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_MSP34x5;
+ } else
+ return -ENODEV;
+
+ msleep(100); // the probing above resets the msp...
+ msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
+ msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
+ dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
+ av7110->dvb_adapter.num, version1, version2);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
+ msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
+
+ if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
+ pr_info("saa7113 not accessible\n");
+ } else {
+ u8 *i = saa7113_init_regs;
+
+ if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
+ /* Fujitsu/Siemens DVB-Cable */
+ av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
+ } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
+ /* Hauppauge/TT DVB-C premium */
+ av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
+ } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
+ /* Hauppauge/TT DVB-C premium */
+ av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
+ }
+
+ /* setup for DVB by default */
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+ if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
+ dprintk(1, "setting band in demodulator failed\n");
+ } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
+ }
+
+ /* init the saa7113 */
+ while (*i != 0xff) {
+ if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
+ dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ }
+ i += 2;
+ }
+ /* setup msp for analog sound: B/G Dual-FM */
+ msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
+ msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
+ msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
+ msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
+ msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
+ msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
+ msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
+ }
+
+ memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
+ /* set dd1 stream a & b */
+ saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
+ saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ return 0;
+}
+
+int av7110_init_v4l(struct av7110 *av7110)
+{
+ struct saa7146_dev* dev = av7110->dev;
+ struct saa7146_ext_vv *vv_data;
+ int ret;
+
+ /* special case DVB-C: these cards have an analog tuner
+ plus need some special handling, so we have separate
+ saa7146_ext_vv data for these... */
+ if (av7110->analog_tuner_flags)
+ vv_data = &av7110_vv_data_c;
+ else
+ vv_data = &av7110_vv_data_st;
+ ret = saa7146_vv_init(dev, vv_data);
+
+ if (ret) {
+ ERR("cannot init capture device. skipping\n");
+ return -ENODEV;
+ }
+ vv_data->vid_ops.vidioc_enum_input = vidioc_enum_input;
+ vv_data->vid_ops.vidioc_g_input = vidioc_g_input;
+ vv_data->vid_ops.vidioc_s_input = vidioc_s_input;
+ vv_data->vid_ops.vidioc_g_tuner = vidioc_g_tuner;
+ vv_data->vid_ops.vidioc_s_tuner = vidioc_s_tuner;
+ vv_data->vid_ops.vidioc_g_frequency = vidioc_g_frequency;
+ vv_data->vid_ops.vidioc_s_frequency = vidioc_s_frequency;
+ vv_data->vid_ops.vidioc_enumaudio = vidioc_enumaudio;
+ vv_data->vid_ops.vidioc_g_audio = vidioc_g_audio;
+ vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
+ vv_data->vid_ops.vidioc_g_fmt_vbi_cap = NULL;
+
+ vv_data->vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
+ vv_data->vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
+ vv_data->vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
+ vv_data->vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
+ vv_data->vbi_ops.vidioc_g_fmt_vbi_cap = NULL;
+ vv_data->vbi_ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
+ vv_data->vbi_ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
+ vv_data->vbi_ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
+
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ vv_data->capabilities &= ~V4L2_CAP_SLICED_VBI_OUTPUT;
+
+ if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_VIDEO)) {
+ ERR("cannot register capture device. skipping\n");
+ saa7146_vv_release(dev);
+ return -ENODEV;
+ }
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
+ ERR("cannot register vbi v4l2 device. skipping\n");
+ }
+ return 0;
+}
+
+int av7110_exit_v4l(struct av7110 *av7110)
+{
+ struct saa7146_dev* dev = av7110->dev;
+
+ saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
+ saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
+
+ saa7146_vv_release(dev);
+
+ return 0;
+}
+
+
+
+/* FIXME: these values are experimental values that look better than the
+ values from the latest "official" driver -- at least for me... (MiHu) */
+static struct saa7146_standard standard[] = {
+ {
+ .name = "PAL", .id = V4L2_STD_PAL_BG,
+ .v_offset = 0x15, .v_field = 288,
+ .h_offset = 0x48, .h_pixels = 708,
+ .v_max_out = 576, .h_max_out = 768,
+ }, {
+ .name = "NTSC", .id = V4L2_STD_NTSC,
+ .v_offset = 0x10, .v_field = 244,
+ .h_offset = 0x40, .h_pixels = 708,
+ .v_max_out = 480, .h_max_out = 640,
+ }
+};
+
+static struct saa7146_standard analog_standard[] = {
+ {
+ .name = "PAL", .id = V4L2_STD_PAL_BG,
+ .v_offset = 0x1b, .v_field = 288,
+ .h_offset = 0x08, .h_pixels = 708,
+ .v_max_out = 576, .h_max_out = 768,
+ }, {
+ .name = "NTSC", .id = V4L2_STD_NTSC,
+ .v_offset = 0x10, .v_field = 244,
+ .h_offset = 0x40, .h_pixels = 708,
+ .v_max_out = 480, .h_max_out = 640,
+ }
+};
+
+static struct saa7146_standard dvb_standard[] = {
+ {
+ .name = "PAL", .id = V4L2_STD_PAL_BG,
+ .v_offset = 0x14, .v_field = 288,
+ .h_offset = 0x48, .h_pixels = 708,
+ .v_max_out = 576, .h_max_out = 768,
+ }, {
+ .name = "NTSC", .id = V4L2_STD_NTSC,
+ .v_offset = 0x10, .v_field = 244,
+ .h_offset = 0x40, .h_pixels = 708,
+ .v_max_out = 480, .h_max_out = 640,
+ }
+};
+
+static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
+{
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+ if (std->id & V4L2_STD_PAL) {
+ av7110->vidmode = AV7110_VIDEO_MODE_PAL;
+ av7110_set_vidmode(av7110, av7110->vidmode);
+ }
+ else if (std->id & V4L2_STD_NTSC) {
+ av7110->vidmode = AV7110_VIDEO_MODE_NTSC;
+ av7110_set_vidmode(av7110, av7110->vidmode);
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+
+static struct saa7146_ext_vv av7110_vv_data_st = {
+ .inputs = 1,
+ .audios = 1,
+ .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
+ .flags = 0,
+
+ .stds = &standard[0],
+ .num_stds = ARRAY_SIZE(standard),
+ .std_callback = &std_callback,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
+};
+
+static struct saa7146_ext_vv av7110_vv_data_c = {
+ .inputs = 1,
+ .audios = 1,
+ .capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
+ .flags = SAA7146_USE_PORT_B_FOR_VBI,
+
+ .stds = &standard[0],
+ .num_stds = ARRAY_SIZE(standard),
+ .std_callback = &std_callback,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
+};
+
diff --git a/drivers/staging/media/av7110/budget-patch.c b/drivers/staging/media/av7110/budget-patch.c
new file mode 100644
index 000000000000..d173c8ade6a7
--- /dev/null
+++ b/drivers/staging/media/av7110/budget-patch.c
@@ -0,0 +1,665 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * budget-patch.c: driver for Budget Patch,
+ * hardware modification of DVB-S cards enabling full TS
+ *
+ * Written by Emard <emard@softhome.net>
+ *
+ * Original idea by Roberto Deza <rdeza@unav.es>
+ *
+ * Special thanks to Holger Waechtler, Michael Hunold, Marian Durkovic
+ * and Metzlerbros
+ *
+ * the project's page is at https://linuxtv.org
+ */
+
+#include "av7110.h"
+#include "av7110_hw.h"
+#include "budget.h"
+#include "stv0299.h"
+#include "ves1x93.h"
+#include "tda8083.h"
+
+#include "bsru6.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define budget_patch budget
+
+static struct saa7146_extension budget_extension;
+
+MAKE_BUDGET_INFO(ttbp, "TT-Budget/Patch DVB-S 1.x PCI", BUDGET_PATCH);
+//MAKE_BUDGET_INFO(satel,"TT-Budget/Patch SATELCO PCI", BUDGET_TT_HW_DISEQC);
+
+static const struct pci_device_id pci_tbl[] = {
+ MAKE_EXTENSION_PCI(ttbp,0x13c2, 0x0000),
+// MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
+ {
+ .vendor = 0,
+ }
+};
+
+/* those lines are for budget-patch to be tried
+** on a true budget card and observe the
+** behaviour of VSYNC generated by rps1.
+** this code was shamelessly copy/pasted from budget.c
+*/
+static void gpio_Set22K (struct budget *budget, int state)
+{
+ struct saa7146_dev *dev=budget->dev;
+ dprintk(2, "budget: %p\n", budget);
+ saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
+}
+
+/* Diseqc functions only for TT Budget card */
+/* taken from the Skyvision DVB driver by
+ Ralph Metzler <rjkm@metzlerbros.de> */
+
+static void DiseqcSendBit (struct budget *budget, int data)
+{
+ struct saa7146_dev *dev=budget->dev;
+ dprintk(2, "budget: %p\n", budget);
+
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ udelay(data ? 500 : 1000);
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ udelay(data ? 1000 : 500);
+}
+
+static void DiseqcSendByte (struct budget *budget, int data)
+{
+ int i, par=1, d;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ for (i=7; i>=0; i--) {
+ d = (data>>i)&1;
+ par ^= d;
+ DiseqcSendBit(budget, d);
+ }
+
+ DiseqcSendBit(budget, par);
+}
+
+static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
+{
+ struct saa7146_dev *dev=budget->dev;
+ int i;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ mdelay(16);
+
+ for (i=0; i<len; i++)
+ DiseqcSendByte(budget, msg[i]);
+
+ mdelay(16);
+
+ if (burst!=-1) {
+ if (burst)
+ DiseqcSendByte(budget, 0xff);
+ else {
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ mdelay(12);
+ udelay(500);
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ }
+ msleep(20);
+ }
+
+ return 0;
+}
+
+/* shamelessly copy/pasted from budget.c */
+static int budget_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
+{
+ struct budget* budget = (struct budget*) fe->dvb->priv;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ gpio_Set22K (budget, 1);
+ break;
+
+ case SEC_TONE_OFF:
+ gpio_Set22K (budget, 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+{
+ struct budget* budget = (struct budget*) fe->dvb->priv;
+
+ SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
+
+ return 0;
+}
+
+static int budget_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
+{
+ struct budget* budget = (struct budget*) fe->dvb->priv;
+
+ SendDiSEqCMsg (budget, 0, NULL, minicmd);
+
+ return 0;
+}
+
+static int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int length)
+{
+ int i;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ for (i = 2; i < length; i++)
+ {
+ ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2*i, 2, (u32) buf[i], 0,0);
+ msleep(5);
+ }
+ if (length)
+ ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, (u32) buf[1], 0,0);
+ else
+ ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, 0, 0,0);
+ msleep(5);
+ ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND, 2, (u32) buf[0], 0,0);
+ msleep(5);
+ return 0;
+}
+
+static void av7110_set22k(struct budget_patch *budget, int state)
+{
+ u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0};
+
+ dprintk(2, "budget: %p\n", budget);
+ budget_av7110_send_fw_cmd(budget, buf, 2);
+}
+
+static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst)
+{
+ int i;
+ u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC),
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ dprintk(2, "budget: %p\n", budget);
+
+ if (len>10)
+ len=10;
+
+ buf[1] = len+2;
+ buf[2] = len;
+
+ if (burst != -1)
+ buf[3]=burst ? 0x01 : 0x00;
+ else
+ buf[3]=0xffff;
+
+ for (i=0; i<len; i++)
+ buf[i+4]=msg[i];
+
+ budget_av7110_send_fw_cmd(budget, buf, 18);
+ return 0;
+}
+
+static int budget_patch_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
+{
+ struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ av7110_set22k (budget, 1);
+ break;
+
+ case SEC_TONE_OFF:
+ av7110_set22k (budget, 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+{
+ struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
+
+ av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
+
+ return 0;
+}
+
+static int budget_patch_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
+{
+ struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
+
+ av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
+
+ return 0;
+}
+
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
+ u8 pwr = 0;
+ u8 buf[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ u32 div = (p->frequency + 479500) / 125;
+
+ if (p->frequency > 2000000)
+ pwr = 3;
+ else if (p->frequency > 1800000)
+ pwr = 2;
+ else if (p->frequency > 1600000)
+ pwr = 1;
+ else if (p->frequency > 1200000)
+ pwr = 0;
+ else if (p->frequency >= 1100000)
+ pwr = 1;
+ else pwr = 2;
+
+ buf[0] = (div >> 8) & 0x7f;
+ buf[1] = div & 0xff;
+ buf[2] = ((div & 0x18000) >> 10) | 0x95;
+ buf[3] = (pwr << 6) | 0x30;
+
+ // NOTE: since we're using a prescaler of 2, we set the
+ // divisor frequency to 62.5kHz and divide by 125 above
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct ves1x93_config alps_bsrv2_config = {
+ .demod_address = 0x08,
+ .xin = 90100000UL,
+ .invert_pwm = 0,
+};
+
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
+ u32 div;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = p->frequency / 125;
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x8e;
+ data[3] = 0x00;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct tda8083_config grundig_29504_451_config = {
+ .demod_address = 0x68,
+};
+
+static void frontend_init(struct budget_patch* budget)
+{
+ switch(budget->dev->pci->subsystem_device) {
+ case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
+ case 0x1013: // SATELCO Multimedia PCI
+
+ // try the ALPS BSRV2 first of all
+ budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_patch_set_tone;
+ break;
+ }
+
+ // try the ALPS BSRU6 now
+ budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
+ break;
+ }
+
+ // Try the grundig 29504-451
+ budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
+ break;
+ }
+ break;
+ }
+
+ if (budget->dvb_frontend == NULL) {
+ printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ budget->dev->pci->vendor,
+ budget->dev->pci->device,
+ budget->dev->pci->subsystem_vendor,
+ budget->dev->pci->subsystem_device);
+ } else {
+ if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
+ printk("budget-av: Frontend registration failed!\n");
+ dvb_frontend_detach(budget->dvb_frontend);
+ budget->dvb_frontend = NULL;
+ }
+ }
+}
+
+/* written by Emard */
+static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
+{
+ struct budget_patch *budget;
+ int err;
+ int count = 0;
+ int detected = 0;
+
+#define PATCH_RESET 0
+#define RPS_IRQ 0
+#define HPS_SETUP 0
+#if PATCH_RESET
+ saa7146_write(dev, MC1, MASK_31);
+ msleep(40);
+#endif
+#if HPS_SETUP
+ // initialize registers. Better to have it like this
+ // than leaving something unconfigured
+ saa7146_write(dev, DD1_STREAM_B, 0);
+ // port B VSYNC at rising edge
+ saa7146_write(dev, DD1_INIT, 0x00000200); // have this in budget-core too!
+ saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI
+
+ // debi config
+ // saa7146_write(dev, DEBI_CONFIG, MASK_30|MASK_28|MASK_18);
+
+ // zero all HPS registers
+ saa7146_write(dev, HPS_H_PRESCALE, 0); // r68
+ saa7146_write(dev, HPS_H_SCALE, 0); // r6c
+ saa7146_write(dev, BCS_CTRL, 0); // r70
+ saa7146_write(dev, HPS_V_SCALE, 0); // r60
+ saa7146_write(dev, HPS_V_GAIN, 0); // r64
+ saa7146_write(dev, CHROMA_KEY_RANGE, 0); // r74
+ saa7146_write(dev, CLIP_FORMAT_CTRL, 0); // r78
+ // Set HPS prescaler for port B input
+ saa7146_write(dev, HPS_CTRL, (1<<30) | (0<<29) | (1<<28) | (0<<12) );
+ saa7146_write(dev, MC2,
+ 0 * (MASK_08 | MASK_24) | // BRS control
+ 0 * (MASK_09 | MASK_25) | // a
+ 0 * (MASK_10 | MASK_26) | // b
+ 1 * (MASK_06 | MASK_22) | // HPS_CTRL1
+ 1 * (MASK_05 | MASK_21) | // HPS_CTRL2
+ 0 * (MASK_01 | MASK_15) // DEBI
+ );
+#endif
+ // Disable RPS1 and RPS0
+ saa7146_write(dev, MC1, ( MASK_29 | MASK_28));
+ // RPS1 timeout disable
+ saa7146_write(dev, RPS_TOV1, 0);
+
+ // code for autodetection
+ // will wait for VBI_B event (vertical blank at port B)
+ // and will reset GPIO3 after VBI_B is detected.
+ // (GPIO3 should be raised high by CPU to
+ // test if GPIO3 will generate vertical blank signal
+ // in budget patch GPIO3 is connected to VSYNC_B
+ count = 0;
+#if 0
+ WRITE_RPS1(CMD_UPLOAD |
+ MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 );
+#endif
+ WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
+#if RPS_IRQ
+ // issue RPS1 interrupt to increment counter
+ WRITE_RPS1(CMD_INTERRUPT);
+ // at least a NOP is neede between two interrupts
+ WRITE_RPS1(CMD_NOP);
+ // interrupt again
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ WRITE_RPS1(CMD_STOP);
+
+#if RPS_IRQ
+ // set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
+ // use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
+ // use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called
+ saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
+ // set event counter 1 threshold to maximum allowed value (rEC p55)
+ saa7146_write(dev, ECT1R, 0x3fff );
+#endif
+ // Fix VSYNC level
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ // Set RPS1 Address register to point to RPS code (r108 p42)
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+ // Enable RPS1, (rFC p33)
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
+
+
+ mdelay(50);
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ mdelay(150);
+
+
+ if( (saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0)
+ detected = 1;
+
+#if RPS_IRQ
+ printk("Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
+#endif
+ // Disable RPS1
+ saa7146_write(dev, MC1, ( MASK_29 ));
+
+ if(detected == 0)
+ printk("budget-patch not detected or saa7146 in non-default state.\n"
+ "try enabling resetting of 7146 with MASK_31 in MC1 register\n");
+
+ else
+ printk("BUDGET-PATCH DETECTED.\n");
+
+
+/* OLD (Original design by Roberto Deza):
+** This code will setup the SAA7146_RPS1 to generate a square
+** wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of
+** TS_WIDTH packets) has been acquired on SAA7146_D1B video port;
+** then, this GPIO3 output which is connected to the D1B_VSYNC
+** input, will trigger the acquisition of the alternate field
+** and so on.
+** Currently, the TT_budget / WinTV_Nova cards have two ICs
+** (74HCT4040, LVC74) for the generation of this VSYNC signal,
+** which seems that can be done perfectly without this :-)).
+*/
+
+/* New design (By Emard)
+** this rps1 code will copy internal HS event to GPIO3 pin.
+** GPIO3 is in budget-patch hardware connected to port B VSYNC
+
+** HS is an internal event of 7146, accessible with RPS
+** and temporarily raised high every n lines
+** (n in defined in the RPS_THRESH1 counter threshold)
+** I think HS is raised high on the beginning of the n-th line
+** and remains high until this n-th line that triggered
+** it is completely received. When the reception of n-th line
+** ends, HS is lowered.
+
+** To transmit data over DMA, 7146 needs changing state at
+** port B VSYNC pin. Any changing of port B VSYNC will
+** cause some DMA data transfer, with more or less packets loss.
+** It depends on the phase and frequency of VSYNC and
+** the way of 7146 is instructed to trigger on port B (defined
+** in DD1_INIT register, 3rd nibble from the right valid
+** numbers are 0-7, see datasheet)
+**
+** The correct triggering can minimize packet loss,
+** dvbtraffic should give this stable bandwidths:
+** 22k transponder = 33814 kbit/s
+** 27.5k transponder = 38045 kbit/s
+** by experiment it is found that the best results
+** (stable bandwidths and almost no packet loss)
+** are obtained using DD1_INIT triggering number 2
+** (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
+** and a VSYNC phase that occurs in the middle of DMA transfer
+** (about byte 188*512=96256 in the DMA window).
+**
+** Phase of HS is still not clear to me how to control,
+** It just happens to be so. It can be seen if one enables
+** RPS_IRQ and print Event Counter 1 in vpeirq(). Every
+** time RPS_INTERRUPT is called, the Event Counter 1 will
+** increment. That's how the 7146 is programmed to do event
+** counting in this budget-patch.c
+** I *think* HPS setting has something to do with the phase
+** of HS but I can't be 100% sure in that.
+
+** hardware debug note: a working budget card (including budget patch)
+** with vpeirq() interrupt setup in mode "0x90" (every 64K) will
+** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
+** and that means 3*25=75 Hz of interrupt frequency, as seen by
+** watch cat /proc/interrupts
+**
+** If this frequency is 3x lower (and data received in the DMA
+** buffer don't start with 0x47, but in the middle of packets,
+** whose lengths appear to be like 188 292 188 104 etc.
+** this means VSYNC line is not connected in the hardware.
+** (check soldering pcb and pins)
+** The same behaviour of missing VSYNC can be duplicated on budget
+** cards, by setting DD1_INIT trigger mode 7 in 3rd nibble.
+*/
+
+ // Setup RPS1 "program" (p35)
+ count = 0;
+
+
+ // Wait Source Line Counter Threshold (p36)
+ WRITE_RPS1(CMD_PAUSE | EVT_HS);
+ // Set GPIO3=1 (p42)
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
+#if RPS_IRQ
+ // issue RPS1 interrupt
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ // Wait reset Source Line Counter Threshold (p36)
+ WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
+ // Set GPIO3=0 (p42)
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
+#if RPS_IRQ
+ // issue RPS1 interrupt
+ WRITE_RPS1(CMD_INTERRUPT);
+#endif
+ // Jump to begin of RPS program (p37)
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
+
+ // Fix VSYNC level
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ // Set RPS1 Address register to point to RPS code (r108 p42)
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+
+ if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
+ if (err) {
+ kfree(budget);
+ return err;
+ }
+
+ // Set Source Line Counter Threshold, using BRS (rCC p43)
+ // It generates HS event every TS_HEIGHT lines
+ // this is related to TS_WIDTH set in register
+ // NUM_LINE_BYTE3 in budget-core.c. If NUM_LINE_BYTE
+ // low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188
+ //,then RPS_THRESH1
+ // should be set to trigger every TS_HEIGHT (512) lines.
+ //
+ saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 );
+
+ // saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
+ // Enable RPS1 (rFC p33)
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
+
+ dev->ext_priv = budget;
+
+ budget->dvb_adapter.priv = budget;
+ frontend_init(budget);
+
+ ttpci_budget_init_hooks(budget);
+
+ return 0;
+}
+
+static int budget_patch_detach (struct saa7146_dev* dev)
+{
+ struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
+ int err;
+
+ if (budget->dvb_frontend) {
+ dvb_unregister_frontend(budget->dvb_frontend);
+ dvb_frontend_detach(budget->dvb_frontend);
+ }
+ err = ttpci_budget_deinit (budget);
+
+ kfree (budget);
+
+ return err;
+}
+
+static int __init budget_patch_init(void)
+{
+ return saa7146_register_extension(&budget_extension);
+}
+
+static void __exit budget_patch_exit(void)
+{
+ saa7146_unregister_extension(&budget_extension);
+}
+
+static struct saa7146_extension budget_extension = {
+ .name = "budget_patch dvb",
+ .flags = 0,
+
+ .module = THIS_MODULE,
+ .pci_tbl = pci_tbl,
+ .attach = budget_patch_attach,
+ .detach = budget_patch_detach,
+
+ .irq_mask = MASK_10,
+ .irq_func = ttpci_budget_irq10_handler,
+};
+
+module_init(budget_patch_init);
+module_exit(budget_patch_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others");
+MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 based so-called Budget Patch cards");
diff --git a/drivers/staging/media/av7110/dvb_filter.c b/drivers/staging/media/av7110/dvb_filter.c
new file mode 100644
index 000000000000..8c2eca5dcdc9
--- /dev/null
+++ b/drivers/staging/media/av7110/dvb_filter.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "dvb_filter.h"
+
+static u32 freq[4] = {480, 441, 320, 0};
+
+static unsigned int ac3_bitrates[32] =
+ {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static u32 ac3_frames[3][32] =
+ {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
+ 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
+ 1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
+ 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+ u8 *headr;
+ int found = 0;
+ int c = 0;
+ u8 frame = 0;
+ int fr = 0;
+
+ while ( !found && c < count){
+ u8 *b = mbuf+c;
+
+ if ( b[0] == 0x0b && b[1] == 0x77 )
+ found = 1;
+ else {
+ c++;
+ }
+ }
+
+ if (!found) return -1;
+ if (pr)
+ printk(KERN_DEBUG "Audiostream: AC3");
+
+ ai->off = c;
+ if (c+5 >= count) return -1;
+
+ ai->layer = 0; // 0 for AC3
+ headr = mbuf+c+2;
+
+ frame = (headr[2]&0x3f);
+ ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
+
+ if (pr)
+ printk(KERN_CONT " BRate: %d kb/s", (int) ai->bit_rate/1000);
+
+ ai->frequency = (headr[2] & 0xc0 ) >> 6;
+ fr = (headr[2] & 0xc0 ) >> 6;
+ ai->frequency = freq[fr]*100;
+ if (pr)
+ printk(KERN_CONT " Freq: %d Hz\n", (int) ai->frequency);
+
+ ai->framesize = ac3_frames[fr][frame >> 1];
+ if ((frame & 1) && (fr == 1)) ai->framesize++;
+ ai->framesize = ai->framesize << 1;
+ if (pr)
+ printk(KERN_DEBUG " Framesize %d\n", (int) ai->framesize);
+
+ return 0;
+}
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+ dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+ unsigned char *buf=p2ts->buf;
+
+ buf[0]=0x47;
+ buf[1]=(pid>>8);
+ buf[2]=pid&0xff;
+ p2ts->cc=0;
+ p2ts->cb=cb;
+ p2ts->priv=priv;
+}
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+ int len, int payload_start)
+{
+ unsigned char *buf=p2ts->buf;
+ int ret=0, rest;
+
+ //len=6+((pes[4]<<8)|pes[5]);
+
+ if (payload_start)
+ buf[1]|=0x40;
+ else
+ buf[1]&=~0x40;
+ while (len>=184) {
+ buf[3]=0x10|((p2ts->cc++)&0x0f);
+ memcpy(buf+4, pes, 184);
+ if ((ret=p2ts->cb(p2ts->priv, buf)))
+ return ret;
+ len-=184; pes+=184;
+ buf[1]&=~0x40;
+ }
+ if (!len)
+ return 0;
+ buf[3]=0x30|((p2ts->cc++)&0x0f);
+ rest=183-len;
+ if (rest) {
+ buf[5]=0x00;
+ if (rest-1)
+ memset(buf+6, 0xff, rest-1);
+ }
+ buf[4]=rest;
+ memcpy(buf+5+rest, pes, len);
+ return p2ts->cb(p2ts->priv, buf);
+}
diff --git a/drivers/staging/media/av7110/dvb_filter.h b/drivers/staging/media/av7110/dvb_filter.h
new file mode 100644
index 000000000000..67a3c6333bca
--- /dev/null
+++ b/drivers/staging/media/av7110/dvb_filter.h
@@ -0,0 +1,242 @@
+/*
+ * dvb_filter.h
+ *
+ * Copyright (C) 2003 Convergence GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DVB_FILTER_H_
+#define _DVB_FILTER_H_
+
+#include <linux/slab.h>
+
+#include <media/demux.h>
+
+typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
+
+struct dvb_filter_pes2ts {
+ unsigned char buf[188];
+ unsigned char cc;
+ dvb_filter_pes2ts_cb_t *cb;
+ void *priv;
+};
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+ dvb_filter_pes2ts_cb_t *cb, void *priv);
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+ int len, int payload_start);
+
+
+#define PROG_STREAM_MAP 0xBC
+#define PRIVATE_STREAM1 0xBD
+#define PADDING_STREAM 0xBE
+#define PRIVATE_STREAM2 0xBF
+#define AUDIO_STREAM_S 0xC0
+#define AUDIO_STREAM_E 0xDF
+#define VIDEO_STREAM_S 0xE0
+#define VIDEO_STREAM_E 0xEF
+#define ECM_STREAM 0xF0
+#define EMM_STREAM 0xF1
+#define DSM_CC_STREAM 0xF2
+#define ISO13522_STREAM 0xF3
+#define PROG_STREAM_DIR 0xFF
+
+#define DVB_PICTURE_START 0x00
+#define DVB_USER_START 0xb2
+#define DVB_SEQUENCE_HEADER 0xb3
+#define DVB_SEQUENCE_ERROR 0xb4
+#define DVB_EXTENSION_START 0xb5
+#define DVB_SEQUENCE_END 0xb7
+#define DVB_GOP_START 0xb8
+#define DVB_EXCEPT_SLICE 0xb0
+
+#define SEQUENCE_EXTENSION 0x01
+#define SEQUENCE_DISPLAY_EXTENSION 0x02
+#define PICTURE_CODING_EXTENSION 0x08
+#define QUANT_MATRIX_EXTENSION 0x03
+#define PICTURE_DISPLAY_EXTENSION 0x07
+
+#define I_FRAME 0x01
+#define B_FRAME 0x02
+#define P_FRAME 0x03
+
+/* Initialize sequence_data */
+#define INIT_HORIZONTAL_SIZE 720
+#define INIT_VERTICAL_SIZE 576
+#define INIT_ASPECT_RATIO 0x02
+#define INIT_FRAME_RATE 0x03
+#define INIT_DISP_HORIZONTAL_SIZE 540
+#define INIT_DISP_VERTICAL_SIZE 576
+
+
+//flags2
+#define PTS_DTS_FLAGS 0xC0
+#define ESCR_FLAG 0x20
+#define ES_RATE_FLAG 0x10
+#define DSM_TRICK_FLAG 0x08
+#define ADD_CPY_FLAG 0x04
+#define PES_CRC_FLAG 0x02
+#define PES_EXT_FLAG 0x01
+
+//pts_dts flags
+#define PTS_ONLY 0x80
+#define PTS_DTS 0xC0
+
+#define TS_SIZE 188
+#define TRANS_ERROR 0x80
+#define PAY_START 0x40
+#define TRANS_PRIO 0x20
+#define PID_MASK_HI 0x1F
+//flags
+#define TRANS_SCRMBL1 0x80
+#define TRANS_SCRMBL2 0x40
+#define ADAPT_FIELD 0x20
+#define PAYLOAD 0x10
+#define COUNT_MASK 0x0F
+
+// adaptation flags
+#define DISCON_IND 0x80
+#define RAND_ACC_IND 0x40
+#define ES_PRI_IND 0x20
+#define PCR_FLAG 0x10
+#define OPCR_FLAG 0x08
+#define SPLICE_FLAG 0x04
+#define TRANS_PRIV 0x02
+#define ADAP_EXT_FLAG 0x01
+
+// adaptation extension flags
+#define LTW_FLAG 0x80
+#define PIECE_RATE 0x40
+#define SEAM_SPLICE 0x20
+
+
+#define MAX_PLENGTH 0xFFFF
+#define MMAX_PLENGTH (256*MAX_PLENGTH)
+
+#ifndef IPACKS
+#define IPACKS 2048
+#endif
+
+struct ipack {
+ int size;
+ int found;
+ u8 *buf;
+ u8 cid;
+ u32 plength;
+ u8 plen[2];
+ u8 flag1;
+ u8 flag2;
+ u8 hlength;
+ u8 pts[5];
+ u16 *pid;
+ int mpeg;
+ u8 check;
+ int which;
+ int done;
+ void *data;
+ void (*func)(u8 *buf, int size, void *priv);
+ int count;
+ int repack_subids;
+};
+
+struct dvb_video_info {
+ u32 horizontal_size;
+ u32 vertical_size;
+ u32 aspect_ratio;
+ u32 framerate;
+ u32 video_format;
+ u32 bit_rate;
+ u32 comp_bit_rate;
+ u32 vbv_buffer_size;
+ s16 vbv_delay;
+ u32 CSPF;
+ u32 off;
+};
+
+#define OFF_SIZE 4
+#define FIRST_FIELD 0
+#define SECOND_FIELD 1
+#define VIDEO_FRAME_PICTURE 0x03
+
+struct mpg_picture {
+ int channel;
+ struct dvb_video_info vinfo;
+ u32 *sequence_gop_header;
+ u32 *picture_header;
+ s32 time_code;
+ int low_delay;
+ int closed_gop;
+ int broken_link;
+ int sequence_header_flag;
+ int gop_flag;
+ int sequence_end_flag;
+
+ u8 profile_and_level;
+ s32 picture_coding_parameter;
+ u32 matrix[32];
+ s8 matrix_change_flag;
+
+ u8 picture_header_parameter;
+ /* bit 0 - 2: bwd f code
+ bit 3 : fpb vector
+ bit 4 - 6: fwd f code
+ bit 7 : fpf vector */
+
+ int mpeg1_flag;
+ int progressive_sequence;
+ int sequence_display_extension_flag;
+ u32 sequence_header_data;
+ s16 last_frame_centre_horizontal_offset;
+ s16 last_frame_centre_vertical_offset;
+
+ u32 pts[2]; /* [0] 1st field, [1] 2nd field */
+ int top_field_first;
+ int repeat_first_field;
+ int progressive_frame;
+ int bank;
+ int forward_bank;
+ int backward_bank;
+ int compress;
+ s16 frame_centre_horizontal_offset[OFF_SIZE];
+ /* [0-2] 1st field, [3] 2nd field */
+ s16 frame_centre_vertical_offset[OFF_SIZE];
+ /* [0-2] 1st field, [3] 2nd field */
+ s16 temporal_reference[2];
+ /* [0] 1st field, [1] 2nd field */
+
+ s8 picture_coding_type[2];
+ /* [0] 1st field, [1] 2nd field */
+ s8 picture_structure[2];
+ /* [0] 1st field, [1] 2nd field */
+ s8 picture_display_extension_flag[2];
+ /* [0] 1st field, [1] 2nd field */
+ /* picture_display_extenion() 0:no 1:exit*/
+ s8 pts_flag[2];
+ /* [0] 1st field, [1] 2nd field */
+};
+
+struct dvb_audio_info {
+ int layer;
+ u32 bit_rate;
+ u32 frequency;
+ u32 mode;
+ u32 mode_extension ;
+ u32 emphasis;
+ u32 framesize;
+ u32 off;
+};
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
+
+
+#endif
diff --git a/drivers/staging/media/av7110/osd.h b/drivers/staging/media/av7110/osd.h
new file mode 100644
index 000000000000..858997c74043
--- /dev/null
+++ b/drivers/staging/media/av7110/osd.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * osd.h - DEPRECATED On Screen Display API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ * for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _DVBOSD_H_
+#define _DVBOSD_H_
+
+#include <linux/compiler.h>
+
+typedef enum {
+ /* All functions return -2 on "not open" */
+ OSD_Close = 1, /* () */
+ /*
+ * Disables OSD and releases the buffers
+ * returns 0 on success
+ */
+ OSD_Open, /* (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) */
+ /*
+ * Opens OSD with this size and bit depth
+ * returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
+ */
+ OSD_Show, /* () */
+ /*
+ * enables OSD mode
+ * returns 0 on success
+ */
+ OSD_Hide, /* () */
+ /*
+ * disables OSD mode
+ * returns 0 on success
+ */
+ OSD_Clear, /* () */
+ /*
+ * Sets all pixel to color 0
+ * returns 0 on success
+ */
+ OSD_Fill, /* (color) */
+ /*
+ * Sets all pixel to color <col>
+ * returns 0 on success
+ */
+ OSD_SetColor, /* (color,R{x0},G{y0},B{x1},opacity{y1}) */
+ /*
+ * set palette entry <num> to <r,g,b>, <mix> and <trans> apply
+ * R,G,B: 0..255
+ * R=Red, G=Green, B=Blue
+ * opacity=0: pixel opacity 0% (only video pixel shows)
+ * opacity=1..254: pixel opacity as specified in header
+ * opacity=255: pixel opacity 100% (only OSD pixel shows)
+ * returns 0 on success, -1 on error
+ */
+ OSD_SetPalette, /* (firstcolor{color},lastcolor{x0},data) */
+ /*
+ * Set a number of entries in the palette
+ * sets the entries "firstcolor" through "lastcolor" from the array "data"
+ * data has 4 byte for each color:
+ * R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
+ */
+ OSD_SetTrans, /* (transparency{color}) */
+ /*
+ * Sets transparency of mixed pixel (0..15)
+ * returns 0 on success
+ */
+ OSD_SetPixel, /* (x0,y0,color) */
+ /*
+ * sets pixel <x>,<y> to color number <col>
+ * returns 0 on success, -1 on error
+ */
+ OSD_GetPixel, /* (x0,y0) */
+ /* returns color number of pixel <x>,<y>, or -1 */
+ OSD_SetRow, /* (x0,y0,x1,data) */
+ /*
+ * fills pixels x0,y through x1,y with the content of data[]
+ * returns 0 on success, -1 on clipping all pixel (no pixel drawn)
+ */
+ OSD_SetBlock, /* (x0,y0,x1,y1,increment{color},data) */
+ /*
+ * fills pixels x0,y0 through x1,y1 with the content of data[]
+ * inc contains the width of one line in the data block,
+ * inc<=0 uses blockwidth as linewidth
+ * returns 0 on success, -1 on clipping all pixel
+ */
+ OSD_FillRow, /* (x0,y0,x1,color) */
+ /*
+ * fills pixels x0,y through x1,y with the color <col>
+ * returns 0 on success, -1 on clipping all pixel
+ */
+ OSD_FillBlock, /* (x0,y0,x1,y1,color) */
+ /*
+ * fills pixels x0,y0 through x1,y1 with the color <col>
+ * returns 0 on success, -1 on clipping all pixel
+ */
+ OSD_Line, /* (x0,y0,x1,y1,color) */
+ /*
+ * draw a line from x0,y0 to x1,y1 with the color <col>
+ * returns 0 on success
+ */
+ OSD_Query, /* (x0,y0,x1,y1,xasp{color}}), yasp=11 */
+ /*
+ * fills parameters with the picture dimensions and the pixel aspect ratio
+ * returns 0 on success
+ */
+ OSD_Test, /* () */
+ /*
+ * draws a test picture. for debugging purposes only
+ * returns 0 on success
+ * TODO: remove "test" in final version
+ */
+ OSD_Text, /* (x0,y0,size,color,text) */
+ OSD_SetWindow, /* (x0) set window with number 0<x0<8 as current */
+ OSD_MoveWindow, /* move current window to (x0, y0) */
+ OSD_OpenRaw, /* Open other types of OSD windows */
+} OSD_Command;
+
+typedef struct osd_cmd_s {
+ OSD_Command cmd;
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+ int color;
+ void __user *data;
+} osd_cmd_t;
+
+/* OSD_OpenRaw: set 'color' to desired window type */
+typedef enum {
+ OSD_BITMAP1, /* 1 bit bitmap */
+ OSD_BITMAP2, /* 2 bit bitmap */
+ OSD_BITMAP4, /* 4 bit bitmap */
+ OSD_BITMAP8, /* 8 bit bitmap */
+ OSD_BITMAP1HR, /* 1 Bit bitmap half resolution */
+ OSD_BITMAP2HR, /* 2 bit bitmap half resolution */
+ OSD_BITMAP4HR, /* 4 bit bitmap half resolution */
+ OSD_BITMAP8HR, /* 8 bit bitmap half resolution */
+ OSD_YCRCB422, /* 4:2:2 YCRCB Graphic Display */
+ OSD_YCRCB444, /* 4:4:4 YCRCB Graphic Display */
+ OSD_YCRCB444HR, /* 4:4:4 YCRCB graphic half resolution */
+ OSD_VIDEOTSIZE, /* True Size Normal MPEG Video Display */
+ OSD_VIDEOHSIZE, /* MPEG Video Display Half Resolution */
+ OSD_VIDEOQSIZE, /* MPEG Video Display Quarter Resolution */
+ OSD_VIDEODSIZE, /* MPEG Video Display Double Resolution */
+ OSD_VIDEOTHSIZE, /* True Size MPEG Video Display Half Resolution */
+ OSD_VIDEOTQSIZE, /* True Size MPEG Video Display Quarter Resolution*/
+ OSD_VIDEOTDSIZE, /* True Size MPEG Video Display Double Resolution */
+ OSD_VIDEONSIZE, /* Full Size MPEG Video Display */
+ OSD_CURSOR /* Cursor */
+} osd_raw_window_t;
+
+typedef struct osd_cap_s {
+ int cmd;
+#define OSD_CAP_MEMSIZE 1 /* memory size */
+ long val;
+} osd_cap_t;
+
+
+#define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t)
+#define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t)
+
+#endif
diff --git a/drivers/staging/media/av7110/sp8870.c b/drivers/staging/media/av7110/sp8870.c
new file mode 100644
index 000000000000..9767159aeb9b
--- /dev/null
+++ b/drivers/staging/media/av7110/sp8870.c
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ Driver for Spase SP8870 demodulator
+
+ Copyright (C) 1999 Juergen Peitz
+
+
+*/
+/*
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/scripts/get_dvb_firmware alps_tdlb7" to
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
+ */
+#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include <media/dvb_frontend.h>
+#include "sp8870.h"
+
+
+struct sp8870_state {
+
+ struct i2c_adapter* i2c;
+
+ const struct sp8870_config* config;
+
+ struct dvb_frontend frontend;
+
+ /* demodulator private data */
+ u8 initialised:1;
+};
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "sp8870: " args); \
+ } while (0)
+
+/* firmware size for sp8870 */
+#define SP8870_FIRMWARE_SIZE 16382
+
+/* starting point for firmware in file 'Sc_main.mc' */
+#define SP8870_FIRMWARE_OFFSET 0x0A
+
+static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
+{
+ u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
+ int err;
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int sp8870_readreg (struct sp8870_state* state, u16 reg)
+{
+ int ret;
+ u8 b0 [] = { reg >> 8 , reg & 0xff };
+ u8 b1 [] = { 0, 0 };
+ struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+ ret = i2c_transfer (state->i2c, msg, 2);
+
+ if (ret != 2) {
+ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+ return -1;
+ }
+
+ return (b1[0] << 8 | b1[1]);
+}
+
+static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
+{
+ struct i2c_msg msg;
+ const char *fw_buf = fw->data;
+ int fw_pos;
+ u8 tx_buf[255];
+ int tx_len;
+ int err = 0;
+
+ dprintk ("%s: ...\n", __func__);
+
+ if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
+ return -EINVAL;
+
+ // system controller stop
+ sp8870_writereg(state, 0x0F00, 0x0000);
+
+ // instruction RAM register hiword
+ sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
+
+ // instruction RAM MWR
+ sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
+
+ // do firmware upload
+ fw_pos = SP8870_FIRMWARE_OFFSET;
+ while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
+ tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
+ // write register 0xCF0A
+ tx_buf[0] = 0xCF;
+ tx_buf[1] = 0x0A;
+ memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
+ msg.addr = state->config->demod_address;
+ msg.flags = 0;
+ msg.buf = tx_buf;
+ msg.len = tx_len + 2;
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk("%s: firmware upload failed!\n", __func__);
+ printk ("%s: i2c error (err == %i)\n", __func__, err);
+ return err;
+ }
+ fw_pos += tx_len;
+ }
+
+ dprintk ("%s: done!\n", __func__);
+ return 0;
+};
+
+static void sp8870_microcontroller_stop (struct sp8870_state* state)
+{
+ sp8870_writereg(state, 0x0F08, 0x000);
+ sp8870_writereg(state, 0x0F09, 0x000);
+
+ // microcontroller STOP
+ sp8870_writereg(state, 0x0F00, 0x000);
+}
+
+static void sp8870_microcontroller_start (struct sp8870_state* state)
+{
+ sp8870_writereg(state, 0x0F08, 0x000);
+ sp8870_writereg(state, 0x0F09, 0x000);
+
+ // microcontroller START
+ sp8870_writereg(state, 0x0F00, 0x001);
+ // not documented but if we don't read 0x0D01 out here
+ // we don't get a correct data valid signal
+ sp8870_readreg(state, 0x0D01);
+}
+
+static int sp8870_read_data_valid_signal(struct sp8870_state* state)
+{
+ return (sp8870_readreg(state, 0x0D02) > 0);
+}
+
+static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
+{
+ int known_parameters = 1;
+
+ *reg0xc05 = 0x000;
+
+ switch (p->modulation) {
+ case QPSK:
+ break;
+ case QAM_16:
+ *reg0xc05 |= (1 << 10);
+ break;
+ case QAM_64:
+ *reg0xc05 |= (2 << 10);
+ break;
+ case QAM_AUTO:
+ known_parameters = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (p->hierarchy) {
+ case HIERARCHY_NONE:
+ break;
+ case HIERARCHY_1:
+ *reg0xc05 |= (1 << 7);
+ break;
+ case HIERARCHY_2:
+ *reg0xc05 |= (2 << 7);
+ break;
+ case HIERARCHY_4:
+ *reg0xc05 |= (3 << 7);
+ break;
+ case HIERARCHY_AUTO:
+ known_parameters = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (p->code_rate_HP) {
+ case FEC_1_2:
+ break;
+ case FEC_2_3:
+ *reg0xc05 |= (1 << 3);
+ break;
+ case FEC_3_4:
+ *reg0xc05 |= (2 << 3);
+ break;
+ case FEC_5_6:
+ *reg0xc05 |= (3 << 3);
+ break;
+ case FEC_7_8:
+ *reg0xc05 |= (4 << 3);
+ break;
+ case FEC_AUTO:
+ known_parameters = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (known_parameters)
+ *reg0xc05 |= (2 << 1); /* use specified parameters */
+ else
+ *reg0xc05 |= (1 << 1); /* enable autoprobing */
+
+ return 0;
+}
+
+static int sp8870_wake_up(struct sp8870_state* state)
+{
+ // enable TS output and interface pins
+ return sp8870_writereg(state, 0xC18, 0x00D);
+}
+
+static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct sp8870_state* state = fe->demodulator_priv;
+ int err;
+ u16 reg0xc05;
+
+ if ((err = configure_reg0xc05(p, &reg0xc05)))
+ return err;
+
+ // system controller stop
+ sp8870_microcontroller_stop(state);
+
+ // set tuner parameters
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ // sample rate correction bit [23..17]
+ sp8870_writereg(state, 0x0319, 0x000A);
+
+ // sample rate correction bit [16..0]
+ sp8870_writereg(state, 0x031A, 0x0AAB);
+
+ // integer carrier offset
+ sp8870_writereg(state, 0x0309, 0x0400);
+
+ // fractional carrier offset
+ sp8870_writereg(state, 0x030A, 0x0000);
+
+ // filter for 6/7/8 Mhz channel
+ if (p->bandwidth_hz == 6000000)
+ sp8870_writereg(state, 0x0311, 0x0002);
+ else if (p->bandwidth_hz == 7000000)
+ sp8870_writereg(state, 0x0311, 0x0001);
+ else
+ sp8870_writereg(state, 0x0311, 0x0000);
+
+ // scan order: 2k first = 0x0000, 8k first = 0x0001
+ if (p->transmission_mode == TRANSMISSION_MODE_2K)
+ sp8870_writereg(state, 0x0338, 0x0000);
+ else
+ sp8870_writereg(state, 0x0338, 0x0001);
+
+ sp8870_writereg(state, 0xc05, reg0xc05);
+
+ // read status reg in order to clear pending irqs
+ err = sp8870_readreg(state, 0x200);
+ if (err < 0)
+ return err;
+
+ // system controller start
+ sp8870_microcontroller_start(state);
+
+ return 0;
+}
+
+static int sp8870_init (struct dvb_frontend* fe)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ const struct firmware *fw = NULL;
+
+ sp8870_wake_up(state);
+ if (state->initialised) return 0;
+ state->initialised = 1;
+
+ dprintk ("%s\n", __func__);
+
+
+ /* request the firmware, this will block until someone uploads it */
+ printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
+ if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
+ printk("sp8870: no firmware upload (timeout or file not found?)\n");
+ return -EIO;
+ }
+
+ if (sp8870_firmware_upload(state, fw)) {
+ printk("sp8870: writing firmware to device failed\n");
+ release_firmware(fw);
+ return -EIO;
+ }
+ release_firmware(fw);
+ printk("sp8870: firmware upload complete\n");
+
+ /* enable TS output and interface pins */
+ sp8870_writereg(state, 0xc18, 0x00d);
+
+ // system controller stop
+ sp8870_microcontroller_stop(state);
+
+ // ADC mode
+ sp8870_writereg(state, 0x0301, 0x0003);
+
+ // Reed Solomon parity bytes passed to output
+ sp8870_writereg(state, 0x0C13, 0x0001);
+
+ // MPEG clock is suppressed if no valid data
+ sp8870_writereg(state, 0x0C14, 0x0001);
+
+ /* bit 0x010: enable data valid signal */
+ sp8870_writereg(state, 0x0D00, 0x010);
+ sp8870_writereg(state, 0x0D01, 0x000);
+
+ return 0;
+}
+
+static int sp8870_read_status(struct dvb_frontend *fe,
+ enum fe_status *fe_status)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ int status;
+ int signal;
+
+ *fe_status = 0;
+
+ status = sp8870_readreg (state, 0x0200);
+ if (status < 0)
+ return -EIO;
+
+ signal = sp8870_readreg (state, 0x0303);
+ if (signal < 0)
+ return -EIO;
+
+ if (signal > 0x0F)
+ *fe_status |= FE_HAS_SIGNAL;
+ if (status & 0x08)
+ *fe_status |= FE_HAS_SYNC;
+ if (status & 0x04)
+ *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
+
+ return 0;
+}
+
+static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ int ret;
+ u32 tmp;
+
+ *ber = 0;
+
+ ret = sp8870_readreg(state, 0xC08);
+ if (ret < 0)
+ return -EIO;
+
+ tmp = ret & 0x3F;
+
+ ret = sp8870_readreg(state, 0xC07);
+ if (ret < 0)
+ return -EIO;
+
+ tmp = ret << 6;
+ if (tmp >= 0x3FFF0)
+ tmp = ~0;
+
+ *ber = tmp;
+
+ return 0;
+}
+
+static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ int ret;
+ u16 tmp;
+
+ *signal = 0;
+
+ ret = sp8870_readreg (state, 0x306);
+ if (ret < 0)
+ return -EIO;
+
+ tmp = ret << 8;
+
+ ret = sp8870_readreg (state, 0x303);
+ if (ret < 0)
+ return -EIO;
+
+ tmp |= ret;
+
+ if (tmp)
+ *signal = 0xFFFF - tmp;
+
+ return 0;
+}
+
+static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ int ret;
+
+ *ublocks = 0;
+
+ ret = sp8870_readreg(state, 0xC0C);
+ if (ret < 0)
+ return -EIO;
+
+ if (ret == 0xFFFF)
+ ret = ~0;
+
+ *ublocks = ret;
+
+ return 0;
+}
+
+/* number of trials to recover from lockup */
+#define MAXTRIALS 5
+/* maximum checks for data valid signal */
+#define MAXCHECKS 100
+
+/* only for debugging: counter for detected lockups */
+static int lockups;
+/* only for debugging: counter for channel switches */
+static int switches;
+
+static int sp8870_set_frontend(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct sp8870_state* state = fe->demodulator_priv;
+
+ /*
+ The firmware of the sp8870 sometimes locks up after setting frontend parameters.
+ We try to detect this by checking the data valid signal.
+ If it is not set after MAXCHECKS we try to recover the lockup by setting
+ the frontend parameters again.
+ */
+
+ int err = 0;
+ int valid = 0;
+ int trials = 0;
+ int check_count = 0;
+
+ dprintk("%s: frequency = %i\n", __func__, p->frequency);
+
+ for (trials = 1; trials <= MAXTRIALS; trials++) {
+
+ err = sp8870_set_frontend_parameters(fe);
+ if (err)
+ return err;
+
+ for (check_count = 0; check_count < MAXCHECKS; check_count++) {
+// valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
+ valid = sp8870_read_data_valid_signal(state);
+ if (valid) {
+ dprintk("%s: delay = %i usec\n",
+ __func__, check_count * 10);
+ break;
+ }
+ udelay(10);
+ }
+ if (valid)
+ break;
+ }
+
+ if (!valid) {
+ printk("%s: firmware crash!!!!!!\n", __func__);
+ return -EIO;
+ }
+
+ if (debug) {
+ if (valid) {
+ if (trials > 1) {
+ printk("%s: firmware lockup!!!\n", __func__);
+ printk("%s: recovered after %i trial(s))\n", __func__, trials - 1);
+ lockups++;
+ }
+ }
+ switches++;
+ printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
+ }
+
+ return 0;
+}
+
+static int sp8870_sleep(struct dvb_frontend* fe)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+
+ // tristate TS output and disable interface pins
+ return sp8870_writereg(state, 0xC18, 0x000);
+}
+
+static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 350;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
+static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return sp8870_writereg(state, 0x206, 0x001);
+ } else {
+ return sp8870_writereg(state, 0x206, 0x000);
+ }
+}
+
+static void sp8870_release(struct dvb_frontend* fe)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static const struct dvb_frontend_ops sp8870_ops;
+
+struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct sp8870_state* state = NULL;
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
+ if (state == NULL) goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->initialised = 0;
+
+ /* check if the demod is there */
+ if (sp8870_readreg(state, 0x0200) < 0) goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+
+static const struct dvb_frontend_ops sp8870_ops = {
+ .delsys = { SYS_DVBT },
+ .info = {
+ .name = "Spase SP8870 DVB-T",
+ .frequency_min_hz = 470 * MHz,
+ .frequency_max_hz = 860 * MHz,
+ .frequency_stepsize_hz = 166666,
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
+ },
+
+ .release = sp8870_release,
+
+ .init = sp8870_init,
+ .sleep = sp8870_sleep,
+ .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
+
+ .set_frontend = sp8870_set_frontend,
+ .get_tune_settings = sp8870_get_tune_settings,
+
+ .read_status = sp8870_read_status,
+ .read_ber = sp8870_read_ber,
+ .read_signal_strength = sp8870_read_signal_strength,
+ .read_ucblocks = sp8870_read_uncorrected_blocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
+MODULE_AUTHOR("Juergen Peitz");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sp8870_attach);
diff --git a/drivers/staging/media/av7110/sp8870.h b/drivers/staging/media/av7110/sp8870.h
new file mode 100644
index 000000000000..5eacf39f425e
--- /dev/null
+++ b/drivers/staging/media/av7110/sp8870.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ Driver for Spase SP8870 demodulator
+
+ Copyright (C) 1999 Juergen Peitz
+
+
+*/
+
+#ifndef SP8870_H
+#define SP8870_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct sp8870_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* request firmware for device */
+ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+#if IS_REACHABLE(CONFIG_DVB_SP8870)
+extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif // CONFIG_DVB_SP8870
+
+#endif // SP8870_H
diff --git a/drivers/staging/media/av7110/video-clear-buffer.rst b/drivers/staging/media/av7110/video-clear-buffer.rst
new file mode 100644
index 000000000000..a7730559bbb2
--- /dev/null
+++ b/drivers/staging/media/av7110/video-clear-buffer.rst
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_CLEAR_BUFFER:
+
+==================
+VIDEO_CLEAR_BUFFER
+==================
+
+Name
+----
+
+VIDEO_CLEAR_BUFFER
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_CLEAR_BUFFER
+
+``int ioctl(fd, VIDEO_CLEAR_BUFFER)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_CLEAR_BUFFER for this command.
+
+Description
+-----------
+
+This ioctl call clears all video buffers in the driver and in the
+decoder hardware.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-command.rst b/drivers/staging/media/av7110/video-command.rst
new file mode 100644
index 000000000000..cae9445eb3af
--- /dev/null
+++ b/drivers/staging/media/av7110/video-command.rst
@@ -0,0 +1,96 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_COMMAND:
+
+=============
+VIDEO_COMMAND
+=============
+
+Name
+----
+
+VIDEO_COMMAND
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_COMMAND
+
+``int ioctl(int fd, VIDEO_COMMAND, struct video_command *cmd)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_COMMAND for this command.
+
+ - .. row 3
+
+ - struct video_command \*cmd
+
+ - Commands the decoder.
+
+Description
+-----------
+
+This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders
+this ioctl has been replaced by the
+:ref:`VIDIOC_DECODER_CMD` ioctl.
+
+This ioctl commands the decoder. The ``video_command`` struct is a
+subset of the ``v4l2_decoder_cmd`` struct, so refer to the
+:ref:`VIDIOC_DECODER_CMD` documentation for
+more information.
+
+.. c:type:: video_command
+
+.. code-block:: c
+
+ /* The structure must be zeroed before use by the application
+ This ensures it can be extended safely in the future. */
+ struct video_command {
+ __u32 cmd;
+ __u32 flags;
+ union {
+ struct {
+ __u64 pts;
+ } stop;
+
+ struct {
+ /* 0 or 1000 specifies normal speed,
+ 1 specifies forward single stepping,
+ -1 specifies backward single stepping,
+ >1: playback at speed/1000 of the normal speed,
+ <-1: reverse playback at (-speed/1000) of the normal speed. */
+ __s32 speed;
+ __u32 format;
+ } play;
+
+ struct {
+ __u32 data[16];
+ } raw;
+ };
+ };
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-continue.rst b/drivers/staging/media/av7110/video-continue.rst
new file mode 100644
index 000000000000..bc34bf3989e4
--- /dev/null
+++ b/drivers/staging/media/av7110/video-continue.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_CONTINUE:
+
+==============
+VIDEO_CONTINUE
+==============
+
+Name
+----
+
+VIDEO_CONTINUE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_CONTINUE
+
+``int ioctl(fd, VIDEO_CONTINUE)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_CONTINUE for this command.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 :ref:`VIDIOC_DECODER_CMD` instead.
+
+This ioctl call restarts decoding and playing processes of the video
+stream which was played before a call to VIDEO_FREEZE was made.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-fast-forward.rst b/drivers/staging/media/av7110/video-fast-forward.rst
new file mode 100644
index 000000000000..e71fa8d6965b
--- /dev/null
+++ b/drivers/staging/media/av7110/video-fast-forward.rst
@@ -0,0 +1,72 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_FAST_FORWARD:
+
+==================
+VIDEO_FAST_FORWARD
+==================
+
+Name
+----
+
+VIDEO_FAST_FORWARD
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_FAST_FORWARD
+
+``int ioctl(fd, VIDEO_FAST_FORWARD, int nFrames)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_FAST_FORWARD for this command.
+
+ - .. row 3
+
+ - int nFrames
+
+ - The number of frames to skip.
+
+Description
+-----------
+
+This ioctl call asks the Video Device to skip decoding of N number of
+I-frames. This call can only be used if VIDEO_SOURCE_MEMORY is
+selected.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EPERM``
+
+ - Mode VIDEO_SOURCE_MEMORY not selected.
diff --git a/drivers/staging/media/av7110/video-fclose.rst b/drivers/staging/media/av7110/video-fclose.rst
new file mode 100644
index 000000000000..01d24d548439
--- /dev/null
+++ b/drivers/staging/media/av7110/video-fclose.rst
@@ -0,0 +1,51 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _video_fclose:
+
+=================
+dvb video close()
+=================
+
+Name
+----
+
+dvb video close()
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:function:: int close(int fd)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+Description
+-----------
+
+This system call closes a previously opened video device.
+
+Return Value
+------------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EBADF``
+
+ - fd is not a valid open file descriptor.
diff --git a/drivers/staging/media/av7110/video-fopen.rst b/drivers/staging/media/av7110/video-fopen.rst
new file mode 100644
index 000000000000..1371b083e4e8
--- /dev/null
+++ b/drivers/staging/media/av7110/video-fopen.rst
@@ -0,0 +1,111 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _video_fopen:
+
+================
+dvb video open()
+================
+
+Name
+----
+
+dvb video open()
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:function:: int open(const char *deviceName, int flags)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - const char \*deviceName
+
+ - Name of specific video device.
+
+ - .. row 2
+
+ - int flags
+
+ - A bit-wise OR of the following flags:
+
+ - .. row 3
+
+ -
+ - O_RDONLY read-only access
+
+ - .. row 4
+
+ -
+ - O_RDWR read/write access
+
+ - .. row 5
+
+ -
+ - O_NONBLOCK open in non-blocking mode
+
+ - .. row 6
+
+ -
+ - (blocking mode is the default)
+
+Description
+-----------
+
+This system call opens a named video device (e.g.
+/dev/dvb/adapter0/video0) for subsequent use.
+
+When an open() call has succeeded, the device will be ready for use. The
+significance of blocking or non-blocking mode is described in the
+documentation for functions where there is a difference. It does not
+affect the semantics of the open() call itself. A device opened in
+blocking mode can later be put into non-blocking mode (and vice versa)
+using the F_SETFL command of the fcntl system call. This is a standard
+system call, documented in the Linux manual page for fcntl. Only one
+user can open the Video Device in O_RDWR mode. All other attempts to
+open the device in this mode will fail, and an error-code will be
+returned. If the Video Device is opened in O_RDONLY mode, the only
+ioctl call that can be used is VIDEO_GET_STATUS. All other call will
+return an error code.
+
+Return Value
+------------
+
+.. tabularcolumns:: |p{2.5cm}|p{15.0cm}|
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``ENODEV``
+
+ - Device driver not loaded/available.
+
+ - .. row 2
+
+ - ``EINTERNAL``
+
+ - Internal error.
+
+ - .. row 3
+
+ - ``EBUSY``
+
+ - Device or resource busy.
+
+ - .. row 4
+
+ - ``EINVAL``
+
+ - Invalid argument.
diff --git a/drivers/staging/media/av7110/video-freeze.rst b/drivers/staging/media/av7110/video-freeze.rst
new file mode 100644
index 000000000000..4321f257cb70
--- /dev/null
+++ b/drivers/staging/media/av7110/video-freeze.rst
@@ -0,0 +1,61 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_FREEZE:
+
+============
+VIDEO_FREEZE
+============
+
+Name
+----
+
+VIDEO_FREEZE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_FREEZE
+
+``int ioctl(fd, VIDEO_FREEZE)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_FREEZE for this command.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 :ref:`VIDIOC_DECODER_CMD` instead.
+
+This ioctl call suspends the live video stream being played. Decoding
+and playing are frozen. It is then possible to restart the decoding and
+playing process of the video stream using the VIDEO_CONTINUE command.
+If VIDEO_SOURCE_MEMORY is selected in the ioctl call
+VIDEO_SELECT_SOURCE, the Digital TV subsystem will not decode any more data
+until the ioctl call VIDEO_CONTINUE or VIDEO_PLAY is performed.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-fwrite.rst b/drivers/staging/media/av7110/video-fwrite.rst
new file mode 100644
index 000000000000..a07fd7d7a40e
--- /dev/null
+++ b/drivers/staging/media/av7110/video-fwrite.rst
@@ -0,0 +1,79 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _video_fwrite:
+
+=================
+dvb video write()
+=================
+
+Name
+----
+
+dvb video write()
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:function:: size_t write(int fd, const void *buf, size_t count)
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - void \*buf
+
+ - Pointer to the buffer containing the PES data.
+
+ - .. row 3
+
+ - size_t count
+
+ - Size of buf.
+
+Description
+-----------
+
+This system call can only be used if VIDEO_SOURCE_MEMORY is selected
+in the ioctl call VIDEO_SELECT_SOURCE. The data provided shall be in
+PES format, unless the capability allows other formats. If O_NONBLOCK
+is not specified the function will block until buffer space is
+available. The amount of data to be transferred is implied by count.
+
+Return Value
+------------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EPERM``
+
+ - Mode VIDEO_SOURCE_MEMORY not selected.
+
+ - .. row 2
+
+ - ``ENOMEM``
+
+ - Attempted to write more data than the internal buffer can hold.
+
+ - .. row 3
+
+ - ``EBADF``
+
+ - fd is not a valid open file descriptor.
diff --git a/drivers/staging/media/av7110/video-get-capabilities.rst b/drivers/staging/media/av7110/video-get-capabilities.rst
new file mode 100644
index 000000000000..01e09f56656c
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-capabilities.rst
@@ -0,0 +1,61 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_CAPABILITIES:
+
+======================
+VIDEO_GET_CAPABILITIES
+======================
+
+Name
+----
+
+VIDEO_GET_CAPABILITIES
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_CAPABILITIES
+
+``int ioctl(fd, VIDEO_GET_CAPABILITIES, unsigned int *cap)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_CAPABILITIES for this command.
+
+ - .. row 3
+
+ - unsigned int \*cap
+
+ - Pointer to a location where to store the capability information.
+
+Description
+-----------
+
+This ioctl call asks the video device about its decoding capabilities.
+On success it returns and integer which has bits set according to the
+defines in section ??.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-get-event.rst b/drivers/staging/media/av7110/video-get-event.rst
new file mode 100644
index 000000000000..90382bc36cfe
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-event.rst
@@ -0,0 +1,105 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_EVENT:
+
+===============
+VIDEO_GET_EVENT
+===============
+
+Name
+----
+
+VIDEO_GET_EVENT
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_EVENT
+
+``int ioctl(fd, VIDEO_GET_EVENT, struct video_event *ev)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_EVENT for this command.
+
+ - .. row 3
+
+ - struct video_event \*ev
+
+ - Points to the location where the event, if any, is to be stored.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To get events from a V4L2 decoder
+use the V4L2 :ref:`VIDIOC_DQEVENT` ioctl instead.
+
+This ioctl call returns an event of type video_event if available. If
+an event is not available, the behavior depends on whether the device is
+in blocking or non-blocking mode. In the latter case, the call fails
+immediately with errno set to ``EWOULDBLOCK``. In the former case, the call
+blocks until an event becomes available. The standard Linux poll()
+and/or select() system calls can be used with the device file descriptor
+to watch for new events. For select(), the file descriptor should be
+included in the exceptfds argument, and for poll(), POLLPRI should be
+specified as the wake-up condition. Read-only permissions are sufficient
+for this ioctl call.
+
+.. c:type:: video_event
+
+.. code-block:: c
+
+ struct video_event {
+ __s32 type;
+ #define VIDEO_EVENT_SIZE_CHANGED 1
+ #define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+ #define VIDEO_EVENT_DECODER_STOPPED 3
+ #define VIDEO_EVENT_VSYNC 4
+ long timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+ };
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EWOULDBLOCK``
+
+ - There is no event pending, and the device is in non-blocking mode.
+
+ - .. row 2
+
+ - ``EOVERFLOW``
+
+ - Overflow in event queue - one or more events were lost.
diff --git a/drivers/staging/media/av7110/video-get-frame-count.rst b/drivers/staging/media/av7110/video-get-frame-count.rst
new file mode 100644
index 000000000000..b48ac8c58a41
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-frame-count.rst
@@ -0,0 +1,65 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_FRAME_COUNT:
+
+=====================
+VIDEO_GET_FRAME_COUNT
+=====================
+
+Name
+----
+
+VIDEO_GET_FRAME_COUNT
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_FRAME_COUNT
+
+``int ioctl(int fd, VIDEO_GET_FRAME_COUNT, __u64 *pts)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_FRAME_COUNT for this command.
+
+ - .. row 3
+
+ - __u64 \*pts
+
+ - Returns the number of frames displayed since the decoder was
+ started.
+
+Description
+-----------
+
+This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders
+this ioctl has been replaced by the ``V4L2_CID_MPEG_VIDEO_DEC_FRAME``
+control.
+
+This ioctl call asks the Video Device to return the number of displayed
+frames since the decoder was started.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-get-pts.rst b/drivers/staging/media/av7110/video-get-pts.rst
new file mode 100644
index 000000000000..fedaff41be0b
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-pts.rst
@@ -0,0 +1,69 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_PTS:
+
+=============
+VIDEO_GET_PTS
+=============
+
+Name
+----
+
+VIDEO_GET_PTS
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_PTS
+
+``int ioctl(int fd, VIDEO_GET_PTS, __u64 *pts)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_PTS for this command.
+
+ - .. row 3
+
+ - __u64 \*pts
+
+ - Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 /
+ ISO/IEC 13818-1.
+
+ The PTS should belong to the currently played frame if possible,
+ but may also be a value close to it like the PTS of the last
+ decoded frame or the last PTS extracted by the PES parser.
+
+Description
+-----------
+
+This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders
+this ioctl has been replaced by the ``V4L2_CID_MPEG_VIDEO_DEC_PTS``
+control.
+
+This ioctl call asks the Video Device to return the current PTS
+timestamp.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-get-size.rst b/drivers/staging/media/av7110/video-get-size.rst
new file mode 100644
index 000000000000..de34331c5bd1
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-size.rst
@@ -0,0 +1,69 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_SIZE:
+
+==============
+VIDEO_GET_SIZE
+==============
+
+Name
+----
+
+VIDEO_GET_SIZE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_SIZE
+
+``int ioctl(int fd, VIDEO_GET_SIZE, video_size_t *size)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_SIZE for this command.
+
+ - .. row 3
+
+ - video_size_t \*size
+
+ - Returns the size and aspect ratio.
+
+Description
+-----------
+
+This ioctl returns the size and aspect ratio.
+
+.. c:type:: video_size_t
+
+.. code-block::c
+
+ typedef struct {
+ int w;
+ int h;
+ video_format_t aspect_ratio;
+ } video_size_t;
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-get-status.rst b/drivers/staging/media/av7110/video-get-status.rst
new file mode 100644
index 000000000000..9b86fbf411d4
--- /dev/null
+++ b/drivers/staging/media/av7110/video-get-status.rst
@@ -0,0 +1,72 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_GET_STATUS:
+
+================
+VIDEO_GET_STATUS
+================
+
+Name
+----
+
+VIDEO_GET_STATUS
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_GET_STATUS
+
+``int ioctl(fd, VIDEO_GET_STATUS, struct video_status *status)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_GET_STATUS for this command.
+
+ - .. row 3
+
+ - struct video_status \*status
+
+ - Returns the current status of the Video Device.
+
+Description
+-----------
+
+This ioctl call asks the Video Device to return the current status of
+the device.
+
+.. c:type:: video_status
+
+.. code-block:: c
+
+ struct video_status {
+ int video_blank; /* blank video on freeze? */
+ video_play_state_t play_state; /* current state of playback */
+ video_stream_source_t stream_source; /* current source (demux/memory) */
+ video_format_t video_format; /* current aspect ratio of stream*/
+ video_displayformat_t display_format;/* selected cropping mode */
+ };
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-play.rst b/drivers/staging/media/av7110/video-play.rst
new file mode 100644
index 000000000000..35ac8b98fdbf
--- /dev/null
+++ b/drivers/staging/media/av7110/video-play.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_PLAY:
+
+==========
+VIDEO_PLAY
+==========
+
+Name
+----
+
+VIDEO_PLAY
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_PLAY
+
+``int ioctl(fd, VIDEO_PLAY)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_PLAY for this command.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 :ref:`VIDIOC_DECODER_CMD` instead.
+
+This ioctl call asks the Video Device to start playing a video stream
+from the selected source.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-select-source.rst b/drivers/staging/media/av7110/video-select-source.rst
new file mode 100644
index 000000000000..929a20985d53
--- /dev/null
+++ b/drivers/staging/media/av7110/video-select-source.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SELECT_SOURCE:
+
+===================
+VIDEO_SELECT_SOURCE
+===================
+
+Name
+----
+
+VIDEO_SELECT_SOURCE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SELECT_SOURCE
+
+``int ioctl(fd, VIDEO_SELECT_SOURCE, video_stream_source_t source)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SELECT_SOURCE for this command.
+
+ - .. row 3
+
+ - video_stream_source_t source
+
+ - Indicates which source shall be used for the Video stream.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. This ioctl was also supported by the
+V4L2 ivtv driver, but that has been replaced by the ivtv-specific
+``IVTV_IOC_PASSTHROUGH_MODE`` ioctl.
+
+This ioctl call informs the video device which source shall be used for
+the input data. The possible sources are demux or memory. If memory is
+selected, the data is fed to the video device through the write command.
+
+.. c:type:: video_stream_source_t
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+ VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+ comes from the user through the write
+ system call */
+ } video_stream_source_t;
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-set-blank.rst b/drivers/staging/media/av7110/video-set-blank.rst
new file mode 100644
index 000000000000..70249a6ba125
--- /dev/null
+++ b/drivers/staging/media/av7110/video-set-blank.rst
@@ -0,0 +1,64 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SET_BLANK:
+
+===============
+VIDEO_SET_BLANK
+===============
+
+Name
+----
+
+VIDEO_SET_BLANK
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SET_BLANK
+
+``int ioctl(fd, VIDEO_SET_BLANK, boolean mode)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SET_BLANK for this command.
+
+ - .. row 3
+
+ - boolean mode
+
+ - TRUE: Blank screen when stop.
+
+ - .. row 4
+
+ -
+ - FALSE: Show last decoded frame.
+
+Description
+-----------
+
+This ioctl call asks the Video Device to blank out the picture.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-set-display-format.rst b/drivers/staging/media/av7110/video-set-display-format.rst
new file mode 100644
index 000000000000..1de4f40ae732
--- /dev/null
+++ b/drivers/staging/media/av7110/video-set-display-format.rst
@@ -0,0 +1,60 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SET_DISPLAY_FORMAT:
+
+========================
+VIDEO_SET_DISPLAY_FORMAT
+========================
+
+Name
+----
+
+VIDEO_SET_DISPLAY_FORMAT
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SET_DISPLAY_FORMAT
+
+``int ioctl(fd, VIDEO_SET_DISPLAY_FORMAT)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SET_DISPLAY_FORMAT for this command.
+
+ - .. row 3
+
+ - video_display_format_t format
+
+ - Selects the video format to be used.
+
+Description
+-----------
+
+This ioctl call asks the Video Device to select the video format to be
+applied by the MPEG chip on the video.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-set-format.rst b/drivers/staging/media/av7110/video-set-format.rst
new file mode 100644
index 000000000000..bb64e37ae081
--- /dev/null
+++ b/drivers/staging/media/av7110/video-set-format.rst
@@ -0,0 +1,82 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SET_FORMAT:
+
+================
+VIDEO_SET_FORMAT
+================
+
+Name
+----
+
+VIDEO_SET_FORMAT
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SET_FORMAT
+
+``int ioctl(fd, VIDEO_SET_FORMAT, video_format_t format)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SET_FORMAT for this command.
+
+ - .. row 3
+
+ - video_format_t format
+
+ - video format of TV as defined in section ??.
+
+Description
+-----------
+
+This ioctl sets the screen format (aspect ratio) of the connected output
+device (TV) so that the output of the decoder can be adjusted
+accordingly.
+
+.. c:type:: video_format_t
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_FORMAT_4_3, /* Select 4:3 format */
+ VIDEO_FORMAT_16_9, /* Select 16:9 format. */
+ VIDEO_FORMAT_221_1 /* 2.21:1 */
+ } video_format_t;
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EINVAL``
+
+ - format is not a valid video format.
diff --git a/drivers/staging/media/av7110/video-set-streamtype.rst b/drivers/staging/media/av7110/video-set-streamtype.rst
new file mode 100644
index 000000000000..1f31c048bdbc
--- /dev/null
+++ b/drivers/staging/media/av7110/video-set-streamtype.rst
@@ -0,0 +1,61 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SET_STREAMTYPE:
+
+====================
+VIDEO_SET_STREAMTYPE
+====================
+
+Name
+----
+
+VIDEO_SET_STREAMTYPE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SET_STREAMTYPE
+
+``int ioctl(fd, VIDEO_SET_STREAMTYPE, int type)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SET_STREAMTYPE for this command.
+
+ - .. row 3
+
+ - int type
+
+ - stream type
+
+Description
+-----------
+
+This ioctl tells the driver which kind of stream to expect being written
+to it. If this call is not used the default of video PES is used. Some
+drivers might not support this call and always expect PES.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-slowmotion.rst b/drivers/staging/media/av7110/video-slowmotion.rst
new file mode 100644
index 000000000000..1478fcc30cb8
--- /dev/null
+++ b/drivers/staging/media/av7110/video-slowmotion.rst
@@ -0,0 +1,72 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_SLOWMOTION:
+
+================
+VIDEO_SLOWMOTION
+================
+
+Name
+----
+
+VIDEO_SLOWMOTION
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_SLOWMOTION
+
+``int ioctl(fd, VIDEO_SLOWMOTION, int nFrames)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_SLOWMOTION for this command.
+
+ - .. row 3
+
+ - int nFrames
+
+ - The number of times to repeat each frame.
+
+Description
+-----------
+
+This ioctl call asks the video device to repeat decoding frames N number
+of times. This call can only be used if VIDEO_SOURCE_MEMORY is
+selected.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - ``EPERM``
+
+ - Mode VIDEO_SOURCE_MEMORY not selected.
diff --git a/drivers/staging/media/av7110/video-stillpicture.rst b/drivers/staging/media/av7110/video-stillpicture.rst
new file mode 100644
index 000000000000..d25384222a20
--- /dev/null
+++ b/drivers/staging/media/av7110/video-stillpicture.rst
@@ -0,0 +1,61 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_STILLPICTURE:
+
+==================
+VIDEO_STILLPICTURE
+==================
+
+Name
+----
+
+VIDEO_STILLPICTURE
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_STILLPICTURE
+
+``int ioctl(fd, VIDEO_STILLPICTURE, struct video_still_picture *sp)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_STILLPICTURE for this command.
+
+ - .. row 3
+
+ - struct video_still_picture \*sp
+
+ - Pointer to a location where an I-frame and size is stored.
+
+Description
+-----------
+
+This ioctl call asks the Video Device to display a still picture
+(I-frame). The input data shall contain an I-frame. If the pointer is
+NULL, then the current displayed still picture is blanked.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-stop.rst b/drivers/staging/media/av7110/video-stop.rst
new file mode 100644
index 000000000000..96f61c5b48a2
--- /dev/null
+++ b/drivers/staging/media/av7110/video-stop.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_STOP:
+
+==========
+VIDEO_STOP
+==========
+
+Name
+----
+
+VIDEO_STOP
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_STOP
+
+``int ioctl(fd, VIDEO_STOP, boolean mode)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_STOP for this command.
+
+ - .. row 3
+
+ - Boolean mode
+
+ - Indicates how the screen shall be handled.
+
+ - .. row 4
+
+ -
+ - TRUE: Blank screen when stop.
+
+ - .. row 5
+
+ -
+ - FALSE: Show last decoded frame.
+
+Description
+-----------
+
+This ioctl is for Digital TV devices only. To control a V4L2 decoder use the
+V4L2 :ref:`VIDIOC_DECODER_CMD` instead.
+
+This ioctl call asks the Video Device to stop playing the current
+stream. Depending on the input parameter, the screen can be blanked out
+or displaying the last decoded frame.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video-try-command.rst b/drivers/staging/media/av7110/video-try-command.rst
new file mode 100644
index 000000000000..79bf3dfb8a32
--- /dev/null
+++ b/drivers/staging/media/av7110/video-try-command.rst
@@ -0,0 +1,66 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: DTV.video
+
+.. _VIDEO_TRY_COMMAND:
+
+=================
+VIDEO_TRY_COMMAND
+=================
+
+Name
+----
+
+VIDEO_TRY_COMMAND
+
+.. attention:: This ioctl is deprecated.
+
+Synopsis
+--------
+
+.. c:macro:: VIDEO_TRY_COMMAND
+
+``int ioctl(int fd, VIDEO_TRY_COMMAND, struct video_command *cmd)``
+
+Arguments
+---------
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ - .. row 1
+
+ - int fd
+
+ - File descriptor returned by a previous call to open().
+
+ - .. row 2
+
+ - int request
+
+ - Equals VIDEO_TRY_COMMAND for this command.
+
+ - .. row 3
+
+ - struct video_command \*cmd
+
+ - Try a decoder command.
+
+Description
+-----------
+
+This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders
+this ioctl has been replaced by the
+:ref:`VIDIOC_TRY_DECODER_CMD <VIDIOC_DECODER_CMD>` ioctl.
+
+This ioctl tries a decoder command. The ``video_command`` struct is a
+subset of the ``v4l2_decoder_cmd`` struct, so refer to the
+:ref:`VIDIOC_TRY_DECODER_CMD <VIDIOC_DECODER_CMD>` documentation
+for more information.
+
+Return Value
+------------
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
diff --git a/drivers/staging/media/av7110/video.h b/drivers/staging/media/av7110/video.h
new file mode 100644
index 000000000000..179f1ec60af6
--- /dev/null
+++ b/drivers/staging/media/av7110/video.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * video.h - DEPRECATED MPEG-TS video decoder API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ * & Ralph Metzler <ralph@convergence.de>
+ * for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _UAPI_DVBVIDEO_H_
+#define _UAPI_DVBVIDEO_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <time.h>
+#endif
+
+typedef enum {
+ VIDEO_FORMAT_4_3, /* Select 4:3 format */
+ VIDEO_FORMAT_16_9, /* Select 16:9 format. */
+ VIDEO_FORMAT_221_1 /* 2.21:1 */
+} video_format_t;
+
+
+typedef enum {
+ VIDEO_PAN_SCAN, /* use pan and scan format */
+ VIDEO_LETTER_BOX, /* use letterbox format */
+ VIDEO_CENTER_CUT_OUT /* use center cut out format */
+} video_displayformat_t;
+
+typedef struct {
+ int w;
+ int h;
+ video_format_t aspect_ratio;
+} video_size_t;
+
+typedef enum {
+ VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+ VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+ comes from the user through the write
+ system call */
+} video_stream_source_t;
+
+
+typedef enum {
+ VIDEO_STOPPED, /* Video is stopped */
+ VIDEO_PLAYING, /* Video is currently playing */
+ VIDEO_FREEZED /* Video is freezed */
+} video_play_state_t;
+
+
+/* Decoder commands */
+#define VIDEO_CMD_PLAY (0)
+#define VIDEO_CMD_STOP (1)
+#define VIDEO_CMD_FREEZE (2)
+#define VIDEO_CMD_CONTINUE (3)
+
+/* Flags for VIDEO_CMD_FREEZE */
+#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
+
+/* Flags for VIDEO_CMD_STOP */
+#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
+#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
+
+/* Play input formats: */
+/* The decoder has no special format requirements */
+#define VIDEO_PLAY_FMT_NONE (0)
+/* The decoder requires full GOPs */
+#define VIDEO_PLAY_FMT_GOP (1)
+
+/* The structure must be zeroed before use by the application
+ This ensures it can be extended safely in the future. */
+struct video_command {
+ __u32 cmd;
+ __u32 flags;
+ union {
+ struct {
+ __u64 pts;
+ } stop;
+
+ struct {
+ /* 0 or 1000 specifies normal speed,
+ 1 specifies forward single stepping,
+ -1 specifies backward single stepping,
+ >1: playback at speed/1000 of the normal speed,
+ <-1: reverse playback at (-speed/1000) of the normal speed. */
+ __s32 speed;
+ __u32 format;
+ } play;
+
+ struct {
+ __u32 data[16];
+ } raw;
+ };
+};
+
+/* FIELD_UNKNOWN can be used if the hardware does not know whether
+ the Vsync is for an odd, even or progressive (i.e. non-interlaced)
+ field. */
+#define VIDEO_VSYNC_FIELD_UNKNOWN (0)
+#define VIDEO_VSYNC_FIELD_ODD (1)
+#define VIDEO_VSYNC_FIELD_EVEN (2)
+#define VIDEO_VSYNC_FIELD_PROGRESSIVE (3)
+
+struct video_event {
+ __s32 type;
+#define VIDEO_EVENT_SIZE_CHANGED 1
+#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+#define VIDEO_EVENT_DECODER_STOPPED 3
+#define VIDEO_EVENT_VSYNC 4
+ /* unused, make sure to use atomic time for y2038 if it ever gets used */
+ long timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+};
+
+
+struct video_status {
+ int video_blank; /* blank video on freeze? */
+ video_play_state_t play_state; /* current state of playback */
+ video_stream_source_t stream_source; /* current source (demux/memory) */
+ video_format_t video_format; /* current aspect ratio of stream*/
+ video_displayformat_t display_format;/* selected cropping mode */
+};
+
+
+struct video_still_picture {
+ char __user *iFrame; /* pointer to a single iframe in memory */
+ __s32 size;
+};
+
+
+typedef __u16 video_attributes_t;
+/* bits: descr. */
+/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
+/* 13-12 TV system (0=525/60, 1=625/50) */
+/* 11-10 Aspect ratio (0=4:3, 3=16:9) */
+/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
+/* 7 line 21-1 data present in GOP (1=yes, 0=no) */
+/* 6 line 21-2 data present in GOP (1=yes, 0=no) */
+/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
+/* 2 source letterboxed (1=yes, 0=no) */
+/* 0 film/camera mode (0=
+ *camera, 1=film (625/50 only)) */
+
+
+/* bit definitions for capabilities: */
+/* can the hardware decode MPEG1 and/or MPEG2? */
+#define VIDEO_CAP_MPEG1 1
+#define VIDEO_CAP_MPEG2 2
+/* can you send a system and/or program stream to video device?
+ (you still have to open the video and the audio device but only
+ send the stream to the video device) */
+#define VIDEO_CAP_SYS 4
+#define VIDEO_CAP_PROG 8
+/* can the driver also handle SPU, NAVI and CSS encoded data?
+ (CSS API is not present yet) */
+#define VIDEO_CAP_SPU 16
+#define VIDEO_CAP_NAVI 32
+#define VIDEO_CAP_CSS 64
+
+
+#define VIDEO_STOP _IO('o', 21)
+#define VIDEO_PLAY _IO('o', 22)
+#define VIDEO_FREEZE _IO('o', 23)
+#define VIDEO_CONTINUE _IO('o', 24)
+#define VIDEO_SELECT_SOURCE _IO('o', 25)
+#define VIDEO_SET_BLANK _IO('o', 26)
+#define VIDEO_GET_STATUS _IOR('o', 27, struct video_status)
+#define VIDEO_GET_EVENT _IOR('o', 28, struct video_event)
+#define VIDEO_SET_DISPLAY_FORMAT _IO('o', 29)
+#define VIDEO_STILLPICTURE _IOW('o', 30, struct video_still_picture)
+#define VIDEO_FAST_FORWARD _IO('o', 31)
+#define VIDEO_SLOWMOTION _IO('o', 32)
+#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int)
+#define VIDEO_CLEAR_BUFFER _IO('o', 34)
+#define VIDEO_SET_STREAMTYPE _IO('o', 36)
+#define VIDEO_SET_FORMAT _IO('o', 37)
+#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t)
+
+/**
+ * VIDEO_GET_PTS
+ *
+ * Read the 33 bit presentation time stamp as defined
+ * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+ *
+ * The PTS should belong to the currently played
+ * frame if possible, but may also be a value close to it
+ * like the PTS of the last decoded frame or the last PTS
+ * extracted by the PES parser.
+ */
+#define VIDEO_GET_PTS _IOR('o', 57, __u64)
+
+/* Read the number of displayed frames since the decoder was started */
+#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64)
+
+#define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
+#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command)
+
+#endif /* _UAPI_DVBVIDEO_H_ */
diff --git a/drivers/staging/media/av7110/video.rst b/drivers/staging/media/av7110/video.rst
new file mode 100644
index 000000000000..808705b769a1
--- /dev/null
+++ b/drivers/staging/media/av7110/video.rst
@@ -0,0 +1,36 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _dvb_video:
+
+#######################
+Digital TV Video Device
+#######################
+
+The Digital TV video device controls the MPEG2 video decoder of the Digital
+TV hardware. It can be accessed through **/dev/dvb/adapter0/video0**. Data
+types and ioctl definitions can be accessed by including
+**linux/dvb/video.h** in your application.
+
+Note that the Digital TV video device only controls decoding of the MPEG video
+stream, not its presentation on the TV or computer screen. On PCs this
+is typically handled by an associated video4linux device, e.g.
+**/dev/video**, which allows scaling and defining output windows.
+
+Some Digital TV cards don't have their own MPEG decoder, which results in the
+omission of the audio and video device as well as the video4linux
+device.
+
+The ioctls that deal with SPUs (sub picture units) and navigation
+packets are only supported on some MPEG decoders made for DVD playback.
+
+These ioctls were also used by V4L2 to control MPEG decoders implemented
+in V4L2. The use of these ioctls for that purpose has been made obsolete
+and proper V4L2 ioctls or controls have been created to replace that
+functionality.
+
+
+.. toctree::
+ :maxdepth: 1
+
+ video_types
+ video_function_calls
diff --git a/drivers/staging/media/av7110/video_function_calls.rst b/drivers/staging/media/av7110/video_function_calls.rst
new file mode 100644
index 000000000000..20a897be5dca
--- /dev/null
+++ b/drivers/staging/media/av7110/video_function_calls.rst
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _video_function_calls:
+
+********************
+Video Function Calls
+********************
+
+.. toctree::
+ :maxdepth: 1
+
+ video-fopen
+ video-fclose
+ video-fwrite
+ video-stop
+ video-play
+ video-freeze
+ video-continue
+ video-select-source
+ video-set-blank
+ video-get-status
+ video-get-frame-count
+ video-get-pts
+ video-get-event
+ video-command
+ video-try-command
+ video-get-size
+ video-set-display-format
+ video-stillpicture
+ video-fast-forward
+ video-slowmotion
+ video-get-capabilities
+ video-clear-buffer
+ video-set-streamtype
+ video-set-format
diff --git a/drivers/staging/media/av7110/video_types.rst b/drivers/staging/media/av7110/video_types.rst
new file mode 100644
index 000000000000..c4557d328b7a
--- /dev/null
+++ b/drivers/staging/media/av7110/video_types.rst
@@ -0,0 +1,248 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _video_types:
+
+****************
+Video Data Types
+****************
+
+
+.. _video-format-t:
+
+video_format_t
+==============
+
+The ``video_format_t`` data type defined by
+
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_FORMAT_4_3, /* Select 4:3 format */
+ VIDEO_FORMAT_16_9, /* Select 16:9 format. */
+ VIDEO_FORMAT_221_1 /* 2.21:1 */
+ } video_format_t;
+
+is used in the VIDEO_SET_FORMAT function (??) to tell the driver which
+aspect ratio the output hardware (e.g. TV) has. It is also used in the
+data structures video_status (??) returned by VIDEO_GET_STATUS (??)
+and video_event (??) returned by VIDEO_GET_EVENT (??) which report
+about the display format of the current video stream.
+
+
+.. _video-displayformat-t:
+
+video_displayformat_t
+=====================
+
+In case the display format of the video stream and of the display
+hardware differ the application has to specify how to handle the
+cropping of the picture. This can be done using the
+VIDEO_SET_DISPLAY_FORMAT call (??) which accepts
+
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_PAN_SCAN, /* use pan and scan format */
+ VIDEO_LETTER_BOX, /* use letterbox format */
+ VIDEO_CENTER_CUT_OUT /* use center cut out format */
+ } video_displayformat_t;
+
+as argument.
+
+
+.. _video-stream-source-t:
+
+video_stream_source_t
+=====================
+
+The video stream source is set through the VIDEO_SELECT_SOURCE call
+and can take the following values, depending on whether we are replaying
+from an internal (demuxer) or external (user write) source.
+
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+ VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+ comes from the user through the write
+ system call */
+ } video_stream_source_t;
+
+VIDEO_SOURCE_DEMUX selects the demultiplexer (fed either by the
+frontend or the DVR device) as the source of the video stream. If
+VIDEO_SOURCE_MEMORY is selected the stream comes from the application
+through the **write()** system call.
+
+
+.. _video-play-state-t:
+
+video_play_state_t
+==================
+
+The following values can be returned by the VIDEO_GET_STATUS call
+representing the state of video playback.
+
+
+.. code-block:: c
+
+ typedef enum {
+ VIDEO_STOPPED, /* Video is stopped */
+ VIDEO_PLAYING, /* Video is currently playing */
+ VIDEO_FREEZED /* Video is freezed */
+ } video_play_state_t;
+
+
+.. c:type:: video_command
+
+struct video_command
+====================
+
+The structure must be zeroed before use by the application This ensures
+it can be extended safely in the future.
+
+
+.. code-block:: c
+
+ struct video_command {
+ __u32 cmd;
+ __u32 flags;
+ union {
+ struct {
+ __u64 pts;
+ } stop;
+
+ struct {
+ /* 0 or 1000 specifies normal speed,
+ 1 specifies forward single stepping,
+ -1 specifies backward single stepping,
+ >>1: playback at speed/1000 of the normal speed,
+ <-1: reverse playback at (-speed/1000) of the normal speed. */
+ __s32 speed;
+ __u32 format;
+ } play;
+
+ struct {
+ __u32 data[16];
+ } raw;
+ };
+ };
+
+
+.. _video-size-t:
+
+video_size_t
+============
+
+
+.. code-block:: c
+
+ typedef struct {
+ int w;
+ int h;
+ video_format_t aspect_ratio;
+ } video_size_t;
+
+
+.. c:type:: video_event
+
+struct video_event
+==================
+
+The following is the structure of a video event as it is returned by the
+VIDEO_GET_EVENT call.
+
+
+.. code-block:: c
+
+ struct video_event {
+ __s32 type;
+ #define VIDEO_EVENT_SIZE_CHANGED 1
+ #define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+ #define VIDEO_EVENT_DECODER_STOPPED 3
+ #define VIDEO_EVENT_VSYNC 4
+ long timestamp;
+ union {
+ video_size_t size;
+ unsigned int frame_rate; /* in frames per 1000sec */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ } u;
+ };
+
+
+.. c:type:: video_status
+
+struct video_status
+===================
+
+The VIDEO_GET_STATUS call returns the following structure informing
+about various states of the playback operation.
+
+
+.. code-block:: c
+
+ struct video_status {
+ int video_blank; /* blank video on freeze? */
+ video_play_state_t play_state; /* current state of playback */
+ video_stream_source_t stream_source; /* current source (demux/memory) */
+ video_format_t video_format; /* current aspect ratio of stream */
+ video_displayformat_t display_format;/* selected cropping mode */
+ };
+
+If video_blank is set video will be blanked out if the channel is
+changed or if playback is stopped. Otherwise, the last picture will be
+displayed. play_state indicates if the video is currently frozen,
+stopped, or being played back. The stream_source corresponds to the
+selected source for the video stream. It can come either from the
+demultiplexer or from memory. The video_format indicates the aspect
+ratio (one of 4:3 or 16:9) of the currently played video stream.
+Finally, display_format corresponds to the selected cropping mode in
+case the source video format is not the same as the format of the output
+device.
+
+
+.. c:type:: video_still_picture
+
+struct video_still_picture
+==========================
+
+An I-frame displayed via the VIDEO_STILLPICTURE call is passed on
+within the following structure.
+
+
+.. code-block:: c
+
+ /* pointer to and size of a single iframe in memory */
+ struct video_still_picture {
+ char *iFrame; /* pointer to a single iframe in memory */
+ int32_t size;
+ };
+
+
+.. _video_caps:
+
+video capabilities
+==================
+
+A call to VIDEO_GET_CAPABILITIES returns an unsigned integer with the
+following bits set according to the hardwares capabilities.
+
+
+.. code-block:: c
+
+ /* bit definitions for capabilities: */
+ /* can the hardware decode MPEG1 and/or MPEG2? */
+ #define VIDEO_CAP_MPEG1 1
+ #define VIDEO_CAP_MPEG2 2
+ /* can you send a system and/or program stream to video device?
+ (you still have to open the video and the audio device but only
+ send the stream to the video device) */
+ #define VIDEO_CAP_SYS 4
+ #define VIDEO_CAP_PROG 8
+ /* can the driver also handle SPU, NAVI and CSS encoded data?
+ (CSS API is not present yet) */
+ #define VIDEO_CAP_SPU 16
+ #define VIDEO_CAP_NAVI 32
+ #define VIDEO_CAP_CSS 64
diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig
index 5b6cf9f62b1a..20b1f6d7b69c 100644
--- a/drivers/staging/media/hantro/Kconfig
+++ b/drivers/staging/media/hantro/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_HANTRO
tristate "Hantro VPU driver"
- depends on ARCH_MXC || ARCH_ROCKCHIP || COMPILE_TEST
+ depends on ARCH_MXC || ARCH_ROCKCHIP || ARCH_AT91 || COMPILE_TEST
depends on VIDEO_DEV && VIDEO_V4L2
select MEDIA_CONTROLLER
select MEDIA_CONTROLLER_REQUEST_API
@@ -24,6 +24,14 @@ config VIDEO_HANTRO_IMX8M
help
Enable support for i.MX8M SoCs.
+config VIDEO_HANTRO_SAMA5D4
+ bool "Hantro VDEC SAMA5D4 support"
+ depends on VIDEO_HANTRO
+ depends on ARCH_AT91 || COMPILE_TEST
+ default y
+ help
+ Enable support for Microchip SAMA5D4 SoCs.
+
config VIDEO_HANTRO_ROCKCHIP
bool "Hantro VPU Rockchip support"
depends on VIDEO_HANTRO
diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile
index 743ce08eb184..287370188d2a 100644
--- a/drivers/staging/media/hantro/Makefile
+++ b/drivers/staging/media/hantro/Makefile
@@ -7,20 +7,25 @@ hantro-vpu-y += \
hantro_v4l2.o \
hantro_postproc.o \
hantro_h1_jpeg_enc.o \
+ hantro_g1.o \
hantro_g1_h264_dec.o \
hantro_g1_mpeg2_dec.o \
+ hantro_g2_hevc_dec.o \
hantro_g1_vp8_dec.o \
- rk3399_vpu_hw_jpeg_enc.o \
- rk3399_vpu_hw_mpeg2_dec.o \
- rk3399_vpu_hw_vp8_dec.o \
+ rockchip_vpu2_hw_jpeg_enc.o \
+ rockchip_vpu2_hw_mpeg2_dec.o \
+ rockchip_vpu2_hw_vp8_dec.o \
hantro_jpeg.o \
hantro_h264.o \
+ hantro_hevc.o \
hantro_mpeg2.o \
hantro_vp8.o
hantro-vpu-$(CONFIG_VIDEO_HANTRO_IMX8M) += \
imx8m_vpu_hw.o
+hantro-vpu-$(CONFIG_VIDEO_HANTRO_SAMA5D4) += \
+ sama5d4_vdec_hw.o
+
hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \
- rk3288_vpu_hw.o \
- rk3399_vpu_hw.o
+ rockchip_vpu_hw.o
diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h
index 6c1b888abe75..a70c386de6f1 100644
--- a/drivers/staging/media/hantro/hantro.h
+++ b/drivers/staging/media/hantro/hantro.h
@@ -34,6 +34,7 @@ struct hantro_codec_ops;
#define HANTRO_MPEG2_DECODER BIT(16)
#define HANTRO_VP8_DECODER BIT(17)
#define HANTRO_H264_DECODER BIT(18)
+#define HANTRO_HEVC_DECODER BIT(19)
#define HANTRO_DECODERS 0xffff0000
/**
@@ -99,6 +100,7 @@ struct hantro_variant {
* @HANTRO_MODE_H264_DEC: H264 decoder.
* @HANTRO_MODE_MPEG2_DEC: MPEG-2 decoder.
* @HANTRO_MODE_VP8_DEC: VP8 decoder.
+ * @HANTRO_MODE_HEVC_DEC: HEVC decoder.
*/
enum hantro_codec_mode {
HANTRO_MODE_NONE = -1,
@@ -106,6 +108,7 @@ enum hantro_codec_mode {
HANTRO_MODE_H264_DEC,
HANTRO_MODE_MPEG2_DEC,
HANTRO_MODE_VP8_DEC,
+ HANTRO_MODE_HEVC_DEC,
};
/*
@@ -218,6 +221,7 @@ struct hantro_dev {
* @jpeg_enc: JPEG-encoding context.
* @mpeg2_dec: MPEG-2-decoding context.
* @vp8_dec: VP8-decoding context.
+ * @hevc_dec: HEVC-decoding context.
*/
struct hantro_ctx {
struct hantro_dev *dev;
@@ -244,6 +248,7 @@ struct hantro_ctx {
struct hantro_jpeg_enc_hw_ctx jpeg_enc;
struct hantro_mpeg2_dec_hw_ctx mpeg2_dec;
struct hantro_vp8_dec_hw_ctx vp8_dec;
+ struct hantro_hevc_dec_hw_ctx hevc_dec;
};
};
@@ -410,12 +415,8 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
return v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
}
-static inline bool
-hantro_needs_postproc(const struct hantro_ctx *ctx,
- const struct hantro_fmt *fmt)
-{
- return !ctx->is_encoder && fmt->fourcc != V4L2_PIX_FMT_NV12;
-}
+bool hantro_needs_postproc(const struct hantro_ctx *ctx,
+ const struct hantro_fmt *fmt);
static inline dma_addr_t
hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..31d8449ca1d2 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -56,16 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
return hantro_get_dec_buf_addr(ctx, buf);
}
-static void hantro_job_finish(struct hantro_dev *vpu,
- struct hantro_ctx *ctx,
- enum vb2_buffer_state result)
+static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ enum vb2_buffer_state result)
{
struct vb2_v4l2_buffer *src, *dst;
- pm_runtime_mark_last_busy(vpu->dev);
- pm_runtime_put_autosuspend(vpu->dev);
- clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
-
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -81,6 +77,18 @@ static void hantro_job_finish(struct hantro_dev *vpu,
result);
}
+static void hantro_job_finish(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ enum vb2_buffer_state result)
+{
+ pm_runtime_mark_last_busy(vpu->dev);
+ pm_runtime_put_autosuspend(vpu->dev);
+
+ clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
+
+ hantro_job_finish_no_pm(vpu, ctx, result);
+}
+
void hantro_irq_done(struct hantro_dev *vpu,
enum vb2_buffer_state result)
{
@@ -152,20 +160,23 @@ static void device_run(void *priv)
src = hantro_get_src_buf(ctx);
dst = hantro_get_dst_buf(ctx);
+ ret = pm_runtime_resume_and_get(ctx->dev->dev);
+ if (ret < 0)
+ goto err_cancel_job;
+
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
- ret = pm_runtime_get_sync(ctx->dev->dev);
- if (ret < 0)
- goto err_cancel_job;
v4l2_m2m_buf_copy_metadata(src, dst, true);
- ctx->codec_ops->run(ctx);
+ if (ctx->codec_ops->run(ctx))
+ goto err_cancel_job;
+
return;
err_cancel_job:
- hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
+ hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
}
static struct v4l2_m2m_ops vpu_m2m_ops = {
@@ -243,6 +254,18 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
if (sps->bit_depth_luma_minus8 != 0)
/* Only 8-bit is supported */
return -EINVAL;
+ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_SPS) {
+ const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
+
+ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
+ /* Luma and chroma bit depth mismatch */
+ return -EINVAL;
+ if (sps->bit_depth_luma_minus8 != 0)
+ /* Only 8-bit is supported */
+ return -EINVAL;
+ if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED)
+ /* No scaling support */
+ return -EINVAL;
}
return 0;
}
@@ -267,6 +290,26 @@ static int hantro_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
+static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct hantro_ctx *ctx;
+
+ ctx = container_of(ctrl->handler,
+ struct hantro_ctx, ctrl_handler);
+
+ vpu_debug(1, "s_ctrl: id = %d, val = %d\n", ctrl->id, ctrl->val);
+
+ switch (ctrl->id) {
+ case V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP:
+ ctx->hevc_dec.ctrls.hevc_hdr_skip_length = ctrl->val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct v4l2_ctrl_ops hantro_ctrl_ops = {
.try_ctrl = hantro_try_ctrl,
};
@@ -275,6 +318,10 @@ static const struct v4l2_ctrl_ops hantro_jpeg_ctrl_ops = {
.s_ctrl = hantro_jpeg_s_ctrl,
};
+static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = {
+ .s_ctrl = hantro_hevc_s_ctrl,
+};
+
static const struct hantro_ctrl controls[] = {
{
.codec = HANTRO_JPEG_ENCODER,
@@ -289,12 +336,17 @@ static const struct hantro_ctrl controls[] = {
}, {
.codec = HANTRO_MPEG2_DECODER,
.cfg = {
- .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
+ },
+ }, {
+ .codec = HANTRO_MPEG2_DECODER,
+ .cfg = {
+ .id = V4L2_CID_STATELESS_MPEG2_PICTURE,
},
}, {
.codec = HANTRO_MPEG2_DECODER,
.cfg = {
- .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
},
}, {
.codec = HANTRO_VP8_DECODER,
@@ -349,6 +401,64 @@ static const struct hantro_ctrl controls[] = {
.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
}
}, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE,
+ .min = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
+ .max = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
+ .def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE,
+ .min = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
+ .max = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
+ .def = V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ .def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
+ .ops = &hantro_ctrl_ops,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS,
+ },
+ }, {
+ .codec = HANTRO_HEVC_DECODER,
+ .cfg = {
+ .id = V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP,
+ .name = "Hantro HEVC slice header skip bytes",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .def = 0,
+ .max = 0x100,
+ .step = 1,
+ .ops = &hantro_hevc_ctrl_ops,
+ },
},
};
@@ -472,12 +582,18 @@ static const struct v4l2_file_operations hantro_fops = {
static const struct of_device_id of_hantro_match[] = {
#ifdef CONFIG_VIDEO_HANTRO_ROCKCHIP
- { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
- { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, },
+ { .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, },
+ { .compatible = "rockchip,rk3066-vpu", .data = &rk3066_vpu_variant, },
{ .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, },
+ { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, },
+ { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
#endif
#ifdef CONFIG_VIDEO_HANTRO_IMX8M
{ .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, },
+ { .compatible = "nxp,imx8mq-vpu-g2", .data = &imx8mq_vpu_g2_variant },
+#endif
+#ifdef CONFIG_VIDEO_HANTRO_SAMA5D4
+ { .compatible = "microchip,sama5d4-vdec", .data = &sama5d4_vdec_variant, },
#endif
{ /* sentinel */ }
};
@@ -752,12 +868,23 @@ static int hantro_probe(struct platform_device *pdev)
if (!vpu->clocks)
return -ENOMEM;
- for (i = 0; i < vpu->variant->num_clocks; i++)
- vpu->clocks[i].id = vpu->variant->clk_names[i];
- ret = devm_clk_bulk_get(&pdev->dev, vpu->variant->num_clocks,
- vpu->clocks);
- if (ret)
- return ret;
+ if (vpu->variant->num_clocks > 1) {
+ for (i = 0; i < vpu->variant->num_clocks; i++)
+ vpu->clocks[i].id = vpu->variant->clk_names[i];
+
+ ret = devm_clk_bulk_get(&pdev->dev, vpu->variant->num_clocks,
+ vpu->clocks);
+ if (ret)
+ return ret;
+ } else {
+ /*
+ * If the driver has a single clk, chances are there will be no
+ * actual name in the DT bindings.
+ */
+ vpu->clocks[0].clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(vpu->clocks[0].clk))
+ return PTR_ERR(vpu->clocks[0].clk);
+ }
num_bases = vpu->variant->num_regs ?: 1;
vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
@@ -785,13 +912,23 @@ static int hantro_probe(struct platform_device *pdev)
vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
for (i = 0; i < vpu->variant->num_irqs; i++) {
- const char *irq_name = vpu->variant->irqs[i].name;
+ const char *irq_name;
int irq;
if (!vpu->variant->irqs[i].handler)
continue;
- irq = platform_get_irq_byname(vpu->pdev, irq_name);
+ if (vpu->variant->num_clocks > 1) {
+ irq_name = vpu->variant->irqs[i].name;
+ irq = platform_get_irq_byname(vpu->pdev, irq_name);
+ } else {
+ /*
+ * If the driver has a single IRQ, chances are there
+ * will be no actual name in the DT bindings.
+ */
+ irq_name = "default";
+ irq = platform_get_irq(vpu->pdev, 0);
+ }
if (irq <= 0)
return -ENXIO;
diff --git a/drivers/staging/media/hantro/hantro_g1.c b/drivers/staging/media/hantro/hantro_g1.c
new file mode 100644
index 000000000000..0ab1cee62218
--- /dev/null
+++ b/drivers/staging/media/hantro/hantro_g1.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VPU codec driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Jeffy Chen <jeffy.chen@rock-chips.com>
+ * Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
+ * Copyright (C) 2021 Collabora Ltd, Emil Velikov <emil.velikov@collabora.com>
+ */
+
+#include "hantro.h"
+#include "hantro_g1_regs.h"
+
+irqreturn_t hantro_g1_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vdpu_read(vpu, G1_REG_INTERRUPT);
+ state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vdpu_write(vpu, 0, G1_REG_INTERRUPT);
+ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
+void hantro_g1_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
+ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
+ vdpu_write(vpu, 1, G1_REG_SOFT_RESET);
+}
diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
index 845bef73d218..5c792b7bcb79 100644
--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
@@ -273,13 +273,15 @@ static void set_buffers(struct hantro_ctx *ctx)
vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, G1_REG_ADDR_QTABLE);
}
-void hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
+int hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
+ int ret;
/* Prepare the H264 decoder context. */
- if (hantro_h264_dec_prepare_run(ctx))
- return;
+ ret = hantro_h264_dec_prepare_run(ctx);
+ if (ret)
+ return ret;
/* Configure hardware registers. */
set_params(ctx);
@@ -301,4 +303,6 @@ void hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
G1_REG_CONFIG_DEC_CLK_GATE_E,
G1_REG_CONFIG);
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c
index 6386a3989bfe..9aea331e1a3c 100644
--- a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c
@@ -10,6 +10,7 @@
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
+#include "hantro_g1_regs.h"
#define G1_SWREG(nr) ((nr) * 4)
@@ -20,7 +21,6 @@
#define G1_REG_REFER2_BASE G1_SWREG(16)
#define G1_REG_REFER3_BASE G1_SWREG(17)
#define G1_REG_QTABLE_BASE G1_SWREG(40)
-#define G1_REG_DEC_E(v) ((v) ? BIT(0) : 0)
#define G1_REG_DEC_AXI_RD_ID(v) (((v) << 24) & GENMASK(31, 24))
#define G1_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(23) : 0)
@@ -77,43 +77,33 @@
#define G1_REG_APF_THRESHOLD(v) (((v) << 0) & GENMASK(13, 0))
-#define PICT_TOP_FIELD 1
-#define PICT_BOTTOM_FIELD 2
-#define PICT_FRAME 3
-
static void
-hantro_g1_mpeg2_dec_set_quantization(struct hantro_dev *vpu,
+hantro_g1_mpeg2_dec_set_quantisation(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
- struct v4l2_ctrl_mpeg2_quantization *quantization;
-
- quantization = hantro_get_ctrl(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
- hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu,
- quantization);
- vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma,
- G1_REG_QTABLE_BASE);
+ struct v4l2_ctrl_mpeg2_quantisation *q;
+
+ q = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_MPEG2_QUANTISATION);
+ hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu, q);
+ vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma, G1_REG_QTABLE_BASE);
}
static void
hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
struct vb2_buffer *src_buf,
struct vb2_buffer *dst_buf,
- const struct v4l2_mpeg2_sequence *sequence,
- const struct v4l2_mpeg2_picture *picture,
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params)
+ const struct v4l2_ctrl_mpeg2_sequence *seq,
+ const struct v4l2_ctrl_mpeg2_picture *pic)
{
dma_addr_t forward_addr = 0, backward_addr = 0;
dma_addr_t current_addr, addr;
- switch (picture->picture_coding_type) {
- case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
- backward_addr = hantro_get_ref(ctx,
- slice_params->backward_ref_ts);
+ switch (pic->picture_coding_type) {
+ case V4L2_MPEG2_PIC_CODING_TYPE_B:
+ backward_addr = hantro_get_ref(ctx, pic->backward_ref_ts);
fallthrough;
- case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
- forward_addr = hantro_get_ref(ctx,
- slice_params->forward_ref_ts);
+ case V4L2_MPEG2_PIC_CODING_TYPE_P:
+ forward_addr = hantro_get_ref(ctx, pic->forward_ref_ts);
}
/* Source bitstream buffer */
@@ -124,7 +114,7 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
addr = hantro_get_dec_buf_addr(ctx, dst_buf);
current_addr = addr;
- if (picture->picture_structure == PICT_BOTTOM_FIELD)
+ if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD)
addr += ALIGN(ctx->dst_fmt.width, 16);
vdpu_write_relaxed(vpu, addr, G1_REG_DEC_OUT_BASE);
@@ -134,18 +124,18 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
backward_addr = current_addr;
/* Set forward ref frame (top/bottom field) */
- if (picture->picture_structure == PICT_FRAME ||
- picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B ||
- (picture->picture_structure == PICT_TOP_FIELD &&
- picture->top_field_first) ||
- (picture->picture_structure == PICT_BOTTOM_FIELD &&
- !picture->top_field_first)) {
+ if (pic->picture_structure == V4L2_MPEG2_PIC_FRAME ||
+ pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B ||
+ (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD &&
+ pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST) ||
+ (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD &&
+ !(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST))) {
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER1_BASE);
- } else if (picture->picture_structure == PICT_TOP_FIELD) {
+ } else if (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) {
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, current_addr, G1_REG_REFER1_BASE);
- } else if (picture->picture_structure == PICT_BOTTOM_FIELD) {
+ } else if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD) {
vdpu_write_relaxed(vpu, current_addr, G1_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, G1_REG_REFER1_BASE);
}
@@ -155,13 +145,12 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
vdpu_write_relaxed(vpu, backward_addr, G1_REG_REFER3_BASE);
}
-void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
+int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
- const struct v4l2_mpeg2_sequence *sequence;
- const struct v4l2_mpeg2_picture *picture;
+ const struct v4l2_ctrl_mpeg2_sequence *seq;
+ const struct v4l2_ctrl_mpeg2_picture *pic;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
@@ -170,10 +159,10 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
/* Apply request controls if any */
hantro_start_prepare_run(ctx);
- slice_params = hantro_get_ctrl(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
- sequence = &slice_params->sequence;
- picture = &slice_params->picture;
+ seq = hantro_get_ctrl(ctx,
+ V4L2_CID_STATELESS_MPEG2_SEQUENCE);
+ pic = hantro_get_ctrl(ctx,
+ V4L2_CID_STATELESS_MPEG2_PICTURE);
reg = G1_REG_DEC_AXI_RD_ID(0) |
G1_REG_DEC_TIMEOUT_E(1) |
@@ -193,11 +182,11 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
reg = G1_REG_DEC_MODE(5) |
G1_REG_RLC_MODE_E(0) |
- G1_REG_PIC_INTERLACE_E(!sequence->progressive_sequence) |
- G1_REG_PIC_FIELDMODE_E(picture->picture_structure != PICT_FRAME) |
- G1_REG_PIC_B_E(picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B) |
- G1_REG_PIC_INTER_E(picture->picture_coding_type != V4L2_MPEG2_PICTURE_CODING_TYPE_I) |
- G1_REG_PIC_TOPFIELD_E(picture->picture_structure == PICT_TOP_FIELD) |
+ G1_REG_PIC_INTERLACE_E(!(seq->flags & V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE)) |
+ G1_REG_PIC_FIELDMODE_E(pic->picture_structure != V4L2_MPEG2_PIC_FRAME) |
+ G1_REG_PIC_B_E(pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B) |
+ G1_REG_PIC_INTER_E(pic->picture_coding_type != V4L2_MPEG2_PIC_CODING_TYPE_I) |
+ G1_REG_PIC_TOPFIELD_E(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) |
G1_REG_FWD_INTERLACE_E(0) |
G1_REG_FILTERING_DIS(1) |
G1_REG_WRITE_MVS_E(0) |
@@ -206,27 +195,27 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
reg = G1_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) |
G1_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) |
- G1_REG_ALT_SCAN_E(picture->alternate_scan) |
- G1_REG_TOPFIELDFIRST_E(picture->top_field_first);
+ G1_REG_ALT_SCAN_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
+ G1_REG_TOPFIELDFIRST_E(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
vdpu_write_relaxed(vpu, reg, G1_SWREG(4));
- reg = G1_REG_STRM_START_BIT(slice_params->data_bit_offset) |
- G1_REG_QSCALE_TYPE(picture->q_scale_type) |
- G1_REG_CON_MV_E(picture->concealment_motion_vectors) |
- G1_REG_INTRA_DC_PREC(picture->intra_dc_precision) |
- G1_REG_INTRA_VLC_TAB(picture->intra_vlc_format) |
- G1_REG_FRAME_PRED_DCT(picture->frame_pred_frame_dct);
+ reg = G1_REG_STRM_START_BIT(0) |
+ G1_REG_QSCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE) |
+ G1_REG_CON_MV_E(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV) |
+ G1_REG_INTRA_DC_PREC(pic->intra_dc_precision) |
+ G1_REG_INTRA_VLC_TAB(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC) |
+ G1_REG_FRAME_PRED_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
vdpu_write_relaxed(vpu, reg, G1_SWREG(5));
reg = G1_REG_INIT_QP(1) |
- G1_REG_STREAM_LEN(slice_params->bit_size >> 3);
+ G1_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, G1_SWREG(6));
- reg = G1_REG_ALT_SCAN_FLAG_E(picture->alternate_scan) |
- G1_REG_FCODE_FWD_HOR(picture->f_code[0][0]) |
- G1_REG_FCODE_FWD_VER(picture->f_code[0][1]) |
- G1_REG_FCODE_BWD_HOR(picture->f_code[1][0]) |
- G1_REG_FCODE_BWD_VER(picture->f_code[1][1]) |
+ reg = G1_REG_ALT_SCAN_FLAG_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
+ G1_REG_FCODE_FWD_HOR(pic->f_code[0][0]) |
+ G1_REG_FCODE_FWD_VER(pic->f_code[0][1]) |
+ G1_REG_FCODE_BWD_HOR(pic->f_code[1][0]) |
+ G1_REG_FCODE_BWD_VER(pic->f_code[1][1]) |
G1_REG_MV_ACCURACY_FWD(1) |
G1_REG_MV_ACCURACY_BWD(1);
vdpu_write_relaxed(vpu, reg, G1_SWREG(18));
@@ -238,14 +227,14 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx)
reg = G1_REG_APF_THRESHOLD(8);
vdpu_write_relaxed(vpu, reg, G1_SWREG(55));
- hantro_g1_mpeg2_dec_set_quantization(vpu, ctx);
-
+ hantro_g1_mpeg2_dec_set_quantisation(vpu, ctx);
hantro_g1_mpeg2_dec_set_buffers(vpu, ctx, &src_buf->vb2_buf,
&dst_buf->vb2_buf,
- sequence, picture, slice_params);
+ seq, pic);
hantro_end_prepare_run(ctx);
- reg = G1_REG_DEC_E(1);
- vdpu_write(vpu, reg, G1_SWREG(1));
+ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
index 57002ba70176..96622a7f8279 100644
--- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
@@ -425,7 +425,7 @@ static void cfg_buffers(struct hantro_ctx *ctx,
vdpu_write_relaxed(vpu, dst_dma, G1_REG_ADDR_DST);
}
-void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
+int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
@@ -438,7 +438,7 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
hdr = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_VP8_FRAME);
if (WARN_ON(!hdr))
- return;
+ return -EINVAL;
/* Reset segment_map buffer in keyframe */
if (V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu)
@@ -498,4 +498,6 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
hantro_end_prepare_run(ctx);
vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT);
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
new file mode 100644
index 000000000000..340efb57fd18
--- /dev/null
+++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
@@ -0,0 +1,586 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VPU HEVC codec driver
+ *
+ * Copyright (C) 2020 Safran Passenger Innovations LLC
+ */
+
+#include "hantro_hw.h"
+#include "hantro_g2_regs.h"
+
+#define HEVC_DEC_MODE 0xC
+
+#define BUS_WIDTH_32 0
+#define BUS_WIDTH_64 1
+#define BUS_WIDTH_128 2
+#define BUS_WIDTH_256 3
+
+static inline void hantro_write_addr(struct hantro_dev *vpu,
+ unsigned long offset,
+ dma_addr_t addr)
+{
+ vdpu_write(vpu, addr & 0xffffffff, offset);
+}
+
+static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+ u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
+ unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
+ unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
+ unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
+ unsigned int max_log2_ctb_size, ctb_size;
+ bool tiles_enabled, uniform_spacing;
+ u32 no_chroma = 0;
+
+ tiles_enabled = !!(pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED);
+ uniform_spacing = !!(pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING);
+
+ hantro_reg_write(vpu, &g2_tile_e, tiles_enabled);
+
+ max_log2_ctb_size = sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ pic_width_in_ctbs = (sps->pic_width_in_luma_samples +
+ (1 << max_log2_ctb_size) - 1) >> max_log2_ctb_size;
+ pic_height_in_ctbs = (sps->pic_height_in_luma_samples + (1 << max_log2_ctb_size) - 1)
+ >> max_log2_ctb_size;
+ ctb_size = 1 << max_log2_ctb_size;
+
+ vpu_debug(1, "Preparing tile sizes buffer for %dx%d CTBs (CTB size %d)\n",
+ pic_width_in_ctbs, pic_height_in_ctbs, ctb_size);
+
+ if (tiles_enabled) {
+ unsigned int i, j, h;
+
+ vpu_debug(1, "Tiles enabled! %dx%d\n", num_tile_cols, num_tile_rows);
+
+ hantro_reg_write(vpu, &g2_num_tile_rows, num_tile_rows);
+ hantro_reg_write(vpu, &g2_num_tile_cols, num_tile_cols);
+
+ /* write width + height for each tile in pic */
+ if (!uniform_spacing) {
+ u32 tmp_w = 0, tmp_h = 0;
+
+ for (i = 0; i < num_tile_rows; i++) {
+ if (i == num_tile_rows - 1)
+ h = pic_height_in_ctbs - tmp_h;
+ else
+ h = pps->row_height_minus1[i] + 1;
+ tmp_h += h;
+ if (i == 0 && h == 1 && ctb_size == 16)
+ no_chroma = 1;
+ for (j = 0, tmp_w = 0; j < num_tile_cols - 1; j++) {
+ tmp_w += pps->column_width_minus1[j] + 1;
+ *p++ = pps->column_width_minus1[j + 1];
+ *p++ = h;
+ if (i == 0 && h == 1 && ctb_size == 16)
+ no_chroma = 1;
+ }
+ /* last column */
+ *p++ = pic_width_in_ctbs - tmp_w;
+ *p++ = h;
+ }
+ } else { /* uniform spacing */
+ u32 tmp, prev_h, prev_w;
+
+ for (i = 0, prev_h = 0; i < num_tile_rows; i++) {
+ tmp = (i + 1) * pic_height_in_ctbs / num_tile_rows;
+ h = tmp - prev_h;
+ prev_h = tmp;
+ if (i == 0 && h == 1 && ctb_size == 16)
+ no_chroma = 1;
+ for (j = 0, prev_w = 0; j < num_tile_cols; j++) {
+ tmp = (j + 1) * pic_width_in_ctbs / num_tile_cols;
+ *p++ = tmp - prev_w;
+ *p++ = h;
+ if (j == 0 &&
+ (pps->column_width_minus1[0] + 1) == 1 &&
+ ctb_size == 16)
+ no_chroma = 1;
+ prev_w = tmp;
+ }
+ }
+ }
+ } else {
+ hantro_reg_write(vpu, &g2_num_tile_rows, 1);
+ hantro_reg_write(vpu, &g2_num_tile_cols, 1);
+
+ /* There's one tile, with dimensions equal to pic size. */
+ p[0] = pic_width_in_ctbs;
+ p[1] = pic_height_in_ctbs;
+ }
+
+ if (no_chroma)
+ vpu_debug(1, "%s: no chroma!\n", __func__);
+}
+
+static void set_params(struct hantro_ctx *ctx)
+{
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+ const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
+ const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
+ struct hantro_dev *vpu = ctx->dev;
+ u32 min_log2_cb_size, max_log2_ctb_size, min_cb_size, max_ctb_size;
+ u32 pic_width_in_min_cbs, pic_height_in_min_cbs;
+ u32 pic_width_aligned, pic_height_aligned;
+ u32 partial_ctb_x, partial_ctb_y;
+
+ hantro_reg_write(vpu, &g2_bit_depth_y_minus8, sps->bit_depth_luma_minus8);
+ hantro_reg_write(vpu, &g2_bit_depth_c_minus8, sps->bit_depth_chroma_minus8);
+
+ hantro_reg_write(vpu, &g2_output_8_bits, 0);
+
+ hantro_reg_write(vpu, &g2_hdr_skip_length, ctrls->hevc_hdr_skip_length);
+
+ min_log2_cb_size = sps->log2_min_luma_coding_block_size_minus3 + 3;
+ max_log2_ctb_size = min_log2_cb_size + sps->log2_diff_max_min_luma_coding_block_size;
+
+ hantro_reg_write(vpu, &g2_min_cb_size, min_log2_cb_size);
+ hantro_reg_write(vpu, &g2_max_cb_size, max_log2_ctb_size);
+
+ min_cb_size = 1 << min_log2_cb_size;
+ max_ctb_size = 1 << max_log2_ctb_size;
+
+ pic_width_in_min_cbs = sps->pic_width_in_luma_samples / min_cb_size;
+ pic_height_in_min_cbs = sps->pic_height_in_luma_samples / min_cb_size;
+ pic_width_aligned = ALIGN(sps->pic_width_in_luma_samples, max_ctb_size);
+ pic_height_aligned = ALIGN(sps->pic_height_in_luma_samples, max_ctb_size);
+
+ partial_ctb_x = !!(sps->pic_width_in_luma_samples != pic_width_aligned);
+ partial_ctb_y = !!(sps->pic_height_in_luma_samples != pic_height_aligned);
+
+ hantro_reg_write(vpu, &g2_partial_ctb_x, partial_ctb_x);
+ hantro_reg_write(vpu, &g2_partial_ctb_y, partial_ctb_y);
+
+ hantro_reg_write(vpu, &g2_pic_width_in_cbs, pic_width_in_min_cbs);
+ hantro_reg_write(vpu, &g2_pic_height_in_cbs, pic_height_in_min_cbs);
+
+ hantro_reg_write(vpu, &g2_pic_width_4x4,
+ (pic_width_in_min_cbs * min_cb_size) / 4);
+ hantro_reg_write(vpu, &g2_pic_height_4x4,
+ (pic_height_in_min_cbs * min_cb_size) / 4);
+
+ hantro_reg_write(vpu, &hevc_max_inter_hierdepth,
+ sps->max_transform_hierarchy_depth_inter);
+ hantro_reg_write(vpu, &hevc_max_intra_hierdepth,
+ sps->max_transform_hierarchy_depth_intra);
+ hantro_reg_write(vpu, &hevc_min_trb_size,
+ sps->log2_min_luma_transform_block_size_minus2 + 2);
+ hantro_reg_write(vpu, &hevc_max_trb_size,
+ sps->log2_min_luma_transform_block_size_minus2 + 2 +
+ sps->log2_diff_max_min_luma_transform_block_size);
+
+ hantro_reg_write(vpu, &g2_tempor_mvp_e,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED) &&
+ !(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC));
+ hantro_reg_write(vpu, &g2_strong_smooth_e,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED));
+ hantro_reg_write(vpu, &g2_asym_pred_e,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_AMP_ENABLED));
+ hantro_reg_write(vpu, &g2_sao_e,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET));
+ hantro_reg_write(vpu, &g2_sign_data_hide,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED));
+
+ if (pps->flags & V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED) {
+ hantro_reg_write(vpu, &g2_cu_qpd_e, 1);
+ hantro_reg_write(vpu, &g2_max_cu_qpd_depth, pps->diff_cu_qp_delta_depth);
+ } else {
+ hantro_reg_write(vpu, &g2_cu_qpd_e, 0);
+ hantro_reg_write(vpu, &g2_max_cu_qpd_depth, 0);
+ }
+
+ if (pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT) {
+ hantro_reg_write(vpu, &g2_cb_qp_offset, pps->pps_cb_qp_offset);
+ hantro_reg_write(vpu, &g2_cr_qp_offset, pps->pps_cr_qp_offset);
+ } else {
+ hantro_reg_write(vpu, &g2_cb_qp_offset, 0);
+ hantro_reg_write(vpu, &g2_cr_qp_offset, 0);
+ }
+
+ hantro_reg_write(vpu, &g2_filt_offset_beta, pps->pps_beta_offset_div2);
+ hantro_reg_write(vpu, &g2_filt_offset_tc, pps->pps_tc_offset_div2);
+ hantro_reg_write(vpu, &g2_slice_hdr_ext_e,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT));
+ hantro_reg_write(vpu, &g2_slice_hdr_ext_bits, pps->num_extra_slice_header_bits);
+ hantro_reg_write(vpu, &g2_slice_chqp_present,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT));
+ hantro_reg_write(vpu, &g2_weight_bipr_idc,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED));
+ hantro_reg_write(vpu, &g2_transq_bypass,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED));
+ hantro_reg_write(vpu, &g2_list_mod_e,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT));
+ hantro_reg_write(vpu, &g2_entropy_sync_e,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED));
+ hantro_reg_write(vpu, &g2_cabac_init_present,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
+ hantro_reg_write(vpu, &g2_idr_pic_e,
+ !!(decode_params->flags & V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC));
+ hantro_reg_write(vpu, &hevc_parallel_merge,
+ pps->log2_parallel_merge_level_minus2 + 2);
+ hantro_reg_write(vpu, &g2_pcm_filt_d,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED));
+ hantro_reg_write(vpu, &g2_pcm_e,
+ !!(sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED));
+ if (sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED) {
+ hantro_reg_write(vpu, &g2_max_pcm_size,
+ sps->log2_diff_max_min_pcm_luma_coding_block_size +
+ sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
+ hantro_reg_write(vpu, &g2_min_pcm_size,
+ sps->log2_min_pcm_luma_coding_block_size_minus3 + 3);
+ hantro_reg_write(vpu, &g2_bit_depth_pcm_y,
+ sps->pcm_sample_bit_depth_luma_minus1 + 1);
+ hantro_reg_write(vpu, &g2_bit_depth_pcm_c,
+ sps->pcm_sample_bit_depth_chroma_minus1 + 1);
+ } else {
+ hantro_reg_write(vpu, &g2_max_pcm_size, 0);
+ hantro_reg_write(vpu, &g2_min_pcm_size, 0);
+ hantro_reg_write(vpu, &g2_bit_depth_pcm_y, 0);
+ hantro_reg_write(vpu, &g2_bit_depth_pcm_c, 0);
+ }
+
+ hantro_reg_write(vpu, &g2_start_code_e, 1);
+ hantro_reg_write(vpu, &g2_init_qp, pps->init_qp_minus26 + 26);
+ hantro_reg_write(vpu, &g2_weight_pred_e,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED));
+ hantro_reg_write(vpu, &g2_cabac_init_present,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT));
+ hantro_reg_write(vpu, &g2_const_intra_e,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED));
+ hantro_reg_write(vpu, &g2_transform_skip,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED));
+ hantro_reg_write(vpu, &g2_out_filtering_dis,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER));
+ hantro_reg_write(vpu, &g2_filt_ctrl_pres,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT));
+ hantro_reg_write(vpu, &g2_dependent_slice,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED));
+ hantro_reg_write(vpu, &g2_filter_override,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED));
+ hantro_reg_write(vpu, &g2_refidx0_active,
+ pps->num_ref_idx_l0_default_active_minus1 + 1);
+ hantro_reg_write(vpu, &g2_refidx1_active,
+ pps->num_ref_idx_l1_default_active_minus1 + 1);
+ hantro_reg_write(vpu, &g2_apf_threshold, 8);
+}
+
+static int find_ref_pic_index(const struct v4l2_hevc_dpb_entry *dpb, int pic_order_cnt)
+{
+ int i;
+
+ for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
+ if (dpb[i].pic_order_cnt[0] == pic_order_cnt)
+ return i;
+ }
+
+ return 0x0;
+}
+
+static void set_ref_pic_list(struct hantro_ctx *ctx)
+{
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ struct hantro_dev *vpu = ctx->dev;
+ const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
+ const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
+ u32 list0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
+ u32 list1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
+ static const struct hantro_reg ref_pic_regs0[] = {
+ hevc_rlist_f0,
+ hevc_rlist_f1,
+ hevc_rlist_f2,
+ hevc_rlist_f3,
+ hevc_rlist_f4,
+ hevc_rlist_f5,
+ hevc_rlist_f6,
+ hevc_rlist_f7,
+ hevc_rlist_f8,
+ hevc_rlist_f9,
+ hevc_rlist_f10,
+ hevc_rlist_f11,
+ hevc_rlist_f12,
+ hevc_rlist_f13,
+ hevc_rlist_f14,
+ hevc_rlist_f15,
+ };
+ static const struct hantro_reg ref_pic_regs1[] = {
+ hevc_rlist_b0,
+ hevc_rlist_b1,
+ hevc_rlist_b2,
+ hevc_rlist_b3,
+ hevc_rlist_b4,
+ hevc_rlist_b5,
+ hevc_rlist_b6,
+ hevc_rlist_b7,
+ hevc_rlist_b8,
+ hevc_rlist_b9,
+ hevc_rlist_b10,
+ hevc_rlist_b11,
+ hevc_rlist_b12,
+ hevc_rlist_b13,
+ hevc_rlist_b14,
+ hevc_rlist_b15,
+ };
+ unsigned int i, j;
+
+ /* List 0 contains: short term before, short term after and long term */
+ j = 0;
+ for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list0); i++)
+ list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]);
+ for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list0); i++)
+ list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]);
+ for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list0); i++)
+ list0[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]);
+
+ /* Fill the list, copying over and over */
+ i = 0;
+ while (j < ARRAY_SIZE(list0))
+ list0[j++] = list0[i++];
+
+ j = 0;
+ for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list1); i++)
+ list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]);
+ for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list1); i++)
+ list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]);
+ for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list1); i++)
+ list1[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]);
+
+ i = 0;
+ while (j < ARRAY_SIZE(list1))
+ list1[j++] = list1[i++];
+
+ for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
+ hantro_reg_write(vpu, &ref_pic_regs0[i], list0[i]);
+ hantro_reg_write(vpu, &ref_pic_regs1[i], list1[i]);
+ }
+}
+
+static int set_ref(struct hantro_ctx *ctx)
+{
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+ const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
+ const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
+ const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
+ dma_addr_t luma_addr, chroma_addr, mv_addr = 0;
+ struct hantro_dev *vpu = ctx->dev;
+ size_t cr_offset = hantro_hevc_chroma_offset(sps);
+ size_t mv_offset = hantro_hevc_motion_vectors_offset(sps);
+ u32 max_ref_frames;
+ u16 dpb_longterm_e;
+ static const struct hantro_reg cur_poc[] = {
+ hevc_cur_poc_00,
+ hevc_cur_poc_01,
+ hevc_cur_poc_02,
+ hevc_cur_poc_03,
+ hevc_cur_poc_04,
+ hevc_cur_poc_05,
+ hevc_cur_poc_06,
+ hevc_cur_poc_07,
+ hevc_cur_poc_08,
+ hevc_cur_poc_09,
+ hevc_cur_poc_10,
+ hevc_cur_poc_11,
+ hevc_cur_poc_12,
+ hevc_cur_poc_13,
+ hevc_cur_poc_14,
+ hevc_cur_poc_15,
+ };
+ unsigned int i;
+
+ max_ref_frames = decode_params->num_poc_lt_curr +
+ decode_params->num_poc_st_curr_before +
+ decode_params->num_poc_st_curr_after;
+ /*
+ * Set max_ref_frames to non-zero to avoid HW hang when decoding
+ * badly marked I-frames.
+ */
+ max_ref_frames = max_ref_frames ? max_ref_frames : 1;
+ hantro_reg_write(vpu, &g2_num_ref_frames, max_ref_frames);
+ hantro_reg_write(vpu, &g2_filter_over_slices,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED));
+ hantro_reg_write(vpu, &g2_filter_over_tiles,
+ !!(pps->flags & V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED));
+
+ /*
+ * Write POC count diff from current pic. For frame decoding only compute
+ * pic_order_cnt[0] and ignore pic_order_cnt[1] used in field-coding.
+ */
+ for (i = 0; i < decode_params->num_active_dpb_entries && i < ARRAY_SIZE(cur_poc); i++) {
+ char poc_diff = decode_params->pic_order_cnt_val - dpb[i].pic_order_cnt[0];
+
+ hantro_reg_write(vpu, &cur_poc[i], poc_diff);
+ }
+
+ if (i < ARRAY_SIZE(cur_poc)) {
+ /*
+ * After the references, fill one entry pointing to itself,
+ * i.e. difference is zero.
+ */
+ hantro_reg_write(vpu, &cur_poc[i], 0);
+ i++;
+ }
+
+ /* Fill the rest with the current picture */
+ for (; i < ARRAY_SIZE(cur_poc); i++)
+ hantro_reg_write(vpu, &cur_poc[i], decode_params->pic_order_cnt_val);
+
+ set_ref_pic_list(ctx);
+
+ /* We will only keep the references picture that are still used */
+ ctx->hevc_dec.ref_bufs_used = 0;
+
+ /* Set up addresses of DPB buffers */
+ dpb_longterm_e = 0;
+ for (i = 0; i < decode_params->num_active_dpb_entries &&
+ i < (V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1); i++) {
+ luma_addr = hantro_hevc_get_ref_buf(ctx, dpb[i].pic_order_cnt[0]);
+ if (!luma_addr)
+ return -ENOMEM;
+
+ chroma_addr = luma_addr + cr_offset;
+ mv_addr = luma_addr + mv_offset;
+
+ if (dpb[i].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
+ dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i);
+
+ hantro_write_addr(vpu, G2_REG_ADDR_REF(i), luma_addr);
+ hantro_write_addr(vpu, G2_REG_CHR_REF(i), chroma_addr);
+ hantro_write_addr(vpu, G2_REG_DMV_REF(i), mv_addr);
+ }
+
+ luma_addr = hantro_hevc_get_ref_buf(ctx, decode_params->pic_order_cnt_val);
+ if (!luma_addr)
+ return -ENOMEM;
+
+ chroma_addr = luma_addr + cr_offset;
+ mv_addr = luma_addr + mv_offset;
+
+ hantro_write_addr(vpu, G2_REG_ADDR_REF(i), luma_addr);
+ hantro_write_addr(vpu, G2_REG_CHR_REF(i), chroma_addr);
+ hantro_write_addr(vpu, G2_REG_DMV_REF(i++), mv_addr);
+
+ hantro_write_addr(vpu, G2_ADDR_DST, luma_addr);
+ hantro_write_addr(vpu, G2_ADDR_DST_CHR, chroma_addr);
+ hantro_write_addr(vpu, G2_ADDR_DST_MV, mv_addr);
+
+ hantro_hevc_ref_remove_unused(ctx);
+
+ for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
+ hantro_write_addr(vpu, G2_REG_ADDR_REF(i), 0);
+ hantro_write_addr(vpu, G2_REG_CHR_REF(i), 0);
+ hantro_write_addr(vpu, G2_REG_DMV_REF(i), 0);
+ }
+
+ hantro_reg_write(vpu, &g2_refer_lterm_e, dpb_longterm_e);
+
+ return 0;
+}
+
+static void set_buffers(struct hantro_ctx *ctx)
+{
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct hantro_dev *vpu = ctx->dev;
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+ size_t cr_offset = hantro_hevc_chroma_offset(sps);
+ dma_addr_t src_dma, dst_dma;
+ u32 src_len, src_buf_len;
+
+ src_buf = hantro_get_src_buf(ctx);
+ dst_buf = hantro_get_dst_buf(ctx);
+
+ /* Source (stream) buffer. */
+ src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ src_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
+ src_buf_len = vb2_plane_size(&src_buf->vb2_buf, 0);
+
+ hantro_write_addr(vpu, G2_ADDR_STR, src_dma);
+ hantro_reg_write(vpu, &g2_stream_len, src_len);
+ hantro_reg_write(vpu, &g2_strm_buffer_len, src_buf_len);
+ hantro_reg_write(vpu, &g2_strm_start_offset, 0);
+ hantro_reg_write(vpu, &g2_write_mvs_e, 1);
+
+ /* Destination (decoded frame) buffer. */
+ dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
+
+ hantro_write_addr(vpu, G2_RASTER_SCAN, dst_dma);
+ hantro_write_addr(vpu, G2_RASTER_SCAN_CHR, dst_dma + cr_offset);
+ hantro_write_addr(vpu, G2_ADDR_TILE_SIZE, ctx->hevc_dec.tile_sizes.dma);
+ hantro_write_addr(vpu, G2_TILE_FILTER, ctx->hevc_dec.tile_filter.dma);
+ hantro_write_addr(vpu, G2_TILE_SAO, ctx->hevc_dec.tile_sao.dma);
+ hantro_write_addr(vpu, G2_TILE_BSD, ctx->hevc_dec.tile_bsd.dma);
+}
+
+static void hantro_g2_check_idle(struct hantro_dev *vpu)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ u32 status;
+
+ /* Make sure the VPU is idle */
+ status = vdpu_read(vpu, G2_REG_INTERRUPT);
+ if (status & G2_REG_INTERRUPT_DEC_E) {
+ dev_warn(vpu->dev, "device still running, aborting");
+ status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS;
+ vdpu_write(vpu, status, G2_REG_INTERRUPT);
+ }
+ }
+}
+
+int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ int ret;
+
+ hantro_g2_check_idle(vpu);
+
+ /* Prepare HEVC decoder context. */
+ ret = hantro_hevc_dec_prepare_run(ctx);
+ if (ret)
+ return ret;
+
+ /* Configure hardware registers. */
+ set_params(ctx);
+
+ /* set reference pictures */
+ ret = set_ref(ctx);
+ if (ret)
+ return ret;
+
+ set_buffers(ctx);
+ prepare_tile_info_buffer(ctx);
+
+ hantro_end_prepare_run(ctx);
+
+ hantro_reg_write(vpu, &g2_mode, HEVC_DEC_MODE);
+ hantro_reg_write(vpu, &g2_clk_gate_e, 1);
+
+ /* Don't disable output */
+ hantro_reg_write(vpu, &g2_out_dis, 0);
+
+ /* Don't compress buffers */
+ hantro_reg_write(vpu, &g2_ref_compress_bypass, 1);
+
+ /* use NV12 as output format */
+ hantro_reg_write(vpu, &g2_out_rs_e, 1);
+
+ /* Bus width and max burst */
+ hantro_reg_write(vpu, &g2_buswidth, BUS_WIDTH_128);
+ hantro_reg_write(vpu, &g2_max_burst, 16);
+
+ /* Swap */
+ hantro_reg_write(vpu, &g2_strm_swap, 0xf);
+ hantro_reg_write(vpu, &g2_dirmv_swap, 0xf);
+ hantro_reg_write(vpu, &g2_compress_swap, 0xf);
+
+ /* Start decoding! */
+ vdpu_write(vpu, G2_REG_INTERRUPT_DEC_E, G2_REG_INTERRUPT);
+
+ return 0;
+}
diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h
new file mode 100644
index 000000000000..bb22fa921914
--- /dev/null
+++ b/drivers/staging/media/hantro/hantro_g2_regs.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, Collabora
+ *
+ * Author: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+ */
+
+#ifndef HANTRO_G2_REGS_H_
+#define HANTRO_G2_REGS_H_
+
+#include "hantro.h"
+
+#define G2_SWREG(nr) ((nr) * 4)
+
+#define G2_DEC_REG(b, s, m) \
+ ((const struct hantro_reg) { \
+ .base = G2_SWREG(b), \
+ .shift = s, \
+ .mask = m, \
+ })
+
+#define G2_REG_VERSION G2_SWREG(0)
+
+#define G2_REG_INTERRUPT G2_SWREG(1)
+#define G2_REG_INTERRUPT_DEC_RDY_INT BIT(12)
+#define G2_REG_INTERRUPT_DEC_ABORT_E BIT(5)
+#define G2_REG_INTERRUPT_DEC_IRQ_DIS BIT(4)
+#define G2_REG_INTERRUPT_DEC_E BIT(0)
+
+#define g2_strm_swap G2_DEC_REG(2, 28, 0xf)
+#define g2_dirmv_swap G2_DEC_REG(2, 20, 0xf)
+
+#define g2_mode G2_DEC_REG(3, 27, 0x1f)
+#define g2_compress_swap G2_DEC_REG(3, 20, 0xf)
+#define g2_ref_compress_bypass G2_DEC_REG(3, 17, 0x1)
+#define g2_out_rs_e G2_DEC_REG(3, 16, 0x1)
+#define g2_out_dis G2_DEC_REG(3, 15, 0x1)
+#define g2_out_filtering_dis G2_DEC_REG(3, 14, 0x1)
+#define g2_write_mvs_e G2_DEC_REG(3, 12, 0x1)
+
+#define g2_pic_width_in_cbs G2_DEC_REG(4, 19, 0x1fff)
+#define g2_pic_height_in_cbs G2_DEC_REG(4, 6, 0x1fff)
+#define g2_num_ref_frames G2_DEC_REG(4, 0, 0x1f)
+
+#define g2_scaling_list_e G2_DEC_REG(5, 24, 0x1)
+#define g2_cb_qp_offset G2_DEC_REG(5, 19, 0x1f)
+#define g2_cr_qp_offset G2_DEC_REG(5, 14, 0x1f)
+#define g2_sign_data_hide G2_DEC_REG(5, 12, 0x1)
+#define g2_tempor_mvp_e G2_DEC_REG(5, 11, 0x1)
+#define g2_max_cu_qpd_depth G2_DEC_REG(5, 5, 0x3f)
+#define g2_cu_qpd_e G2_DEC_REG(5, 4, 0x1)
+
+#define g2_stream_len G2_DEC_REG(6, 0, 0xffffffff)
+
+#define g2_cabac_init_present G2_DEC_REG(7, 31, 0x1)
+#define g2_weight_pred_e G2_DEC_REG(7, 28, 0x1)
+#define g2_weight_bipr_idc G2_DEC_REG(7, 26, 0x3)
+#define g2_filter_over_slices G2_DEC_REG(7, 25, 0x1)
+#define g2_filter_over_tiles G2_DEC_REG(7, 24, 0x1)
+#define g2_asym_pred_e G2_DEC_REG(7, 23, 0x1)
+#define g2_sao_e G2_DEC_REG(7, 22, 0x1)
+#define g2_pcm_filt_d G2_DEC_REG(7, 21, 0x1)
+#define g2_slice_chqp_present G2_DEC_REG(7, 20, 0x1)
+#define g2_dependent_slice G2_DEC_REG(7, 19, 0x1)
+#define g2_filter_override G2_DEC_REG(7, 18, 0x1)
+#define g2_strong_smooth_e G2_DEC_REG(7, 17, 0x1)
+#define g2_filt_offset_beta G2_DEC_REG(7, 12, 0x1f)
+#define g2_filt_offset_tc G2_DEC_REG(7, 7, 0x1f)
+#define g2_slice_hdr_ext_e G2_DEC_REG(7, 6, 0x1)
+#define g2_slice_hdr_ext_bits G2_DEC_REG(7, 3, 0x7)
+
+#define g2_const_intra_e G2_DEC_REG(8, 31, 0x1)
+#define g2_filt_ctrl_pres G2_DEC_REG(8, 30, 0x1)
+#define g2_idr_pic_e G2_DEC_REG(8, 16, 0x1)
+#define g2_bit_depth_pcm_y G2_DEC_REG(8, 12, 0xf)
+#define g2_bit_depth_pcm_c G2_DEC_REG(8, 8, 0xf)
+#define g2_bit_depth_y_minus8 G2_DEC_REG(8, 6, 0x3)
+#define g2_bit_depth_c_minus8 G2_DEC_REG(8, 4, 0x3)
+#define g2_output_8_bits G2_DEC_REG(8, 3, 0x1)
+
+#define g2_refidx1_active G2_DEC_REG(9, 19, 0x1f)
+#define g2_refidx0_active G2_DEC_REG(9, 14, 0x1f)
+#define g2_hdr_skip_length G2_DEC_REG(9, 0, 0x3fff)
+
+#define g2_start_code_e G2_DEC_REG(10, 31, 0x1)
+#define g2_init_qp G2_DEC_REG(10, 24, 0x3f)
+#define g2_num_tile_cols G2_DEC_REG(10, 19, 0x1f)
+#define g2_num_tile_rows G2_DEC_REG(10, 14, 0x1f)
+#define g2_tile_e G2_DEC_REG(10, 1, 0x1)
+#define g2_entropy_sync_e G2_DEC_REG(10, 0, 0x1)
+
+#define g2_refer_lterm_e G2_DEC_REG(12, 16, 0xffff)
+#define g2_min_cb_size G2_DEC_REG(12, 13, 0x7)
+#define g2_max_cb_size G2_DEC_REG(12, 10, 0x7)
+#define g2_min_pcm_size G2_DEC_REG(12, 7, 0x7)
+#define g2_max_pcm_size G2_DEC_REG(12, 4, 0x7)
+#define g2_pcm_e G2_DEC_REG(12, 3, 0x1)
+#define g2_transform_skip G2_DEC_REG(12, 2, 0x1)
+#define g2_transq_bypass G2_DEC_REG(12, 1, 0x1)
+#define g2_list_mod_e G2_DEC_REG(12, 0, 0x1)
+
+#define hevc_min_trb_size G2_DEC_REG(13, 13, 0x7)
+#define hevc_max_trb_size G2_DEC_REG(13, 10, 0x7)
+#define hevc_max_intra_hierdepth G2_DEC_REG(13, 7, 0x7)
+#define hevc_max_inter_hierdepth G2_DEC_REG(13, 4, 0x7)
+#define hevc_parallel_merge G2_DEC_REG(13, 0, 0xf)
+
+#define hevc_rlist_f0 G2_DEC_REG(14, 0, 0x1f)
+#define hevc_rlist_f1 G2_DEC_REG(14, 10, 0x1f)
+#define hevc_rlist_f2 G2_DEC_REG(14, 20, 0x1f)
+#define hevc_rlist_b0 G2_DEC_REG(14, 5, 0x1f)
+#define hevc_rlist_b1 G2_DEC_REG(14, 15, 0x1f)
+#define hevc_rlist_b2 G2_DEC_REG(14, 25, 0x1f)
+
+#define hevc_rlist_f3 G2_DEC_REG(15, 0, 0x1f)
+#define hevc_rlist_f4 G2_DEC_REG(15, 10, 0x1f)
+#define hevc_rlist_f5 G2_DEC_REG(15, 20, 0x1f)
+#define hevc_rlist_b3 G2_DEC_REG(15, 5, 0x1f)
+#define hevc_rlist_b4 G2_DEC_REG(15, 15, 0x1f)
+#define hevc_rlist_b5 G2_DEC_REG(15, 25, 0x1f)
+
+#define hevc_rlist_f6 G2_DEC_REG(16, 0, 0x1f)
+#define hevc_rlist_f7 G2_DEC_REG(16, 10, 0x1f)
+#define hevc_rlist_f8 G2_DEC_REG(16, 20, 0x1f)
+#define hevc_rlist_b6 G2_DEC_REG(16, 5, 0x1f)
+#define hevc_rlist_b7 G2_DEC_REG(16, 15, 0x1f)
+#define hevc_rlist_b8 G2_DEC_REG(16, 25, 0x1f)
+
+#define hevc_rlist_f9 G2_DEC_REG(17, 0, 0x1f)
+#define hevc_rlist_f10 G2_DEC_REG(17, 10, 0x1f)
+#define hevc_rlist_f11 G2_DEC_REG(17, 20, 0x1f)
+#define hevc_rlist_b9 G2_DEC_REG(17, 5, 0x1f)
+#define hevc_rlist_b10 G2_DEC_REG(17, 15, 0x1f)
+#define hevc_rlist_b11 G2_DEC_REG(17, 25, 0x1f)
+
+#define hevc_rlist_f12 G2_DEC_REG(18, 0, 0x1f)
+#define hevc_rlist_f13 G2_DEC_REG(18, 10, 0x1f)
+#define hevc_rlist_f14 G2_DEC_REG(18, 20, 0x1f)
+#define hevc_rlist_b12 G2_DEC_REG(18, 5, 0x1f)
+#define hevc_rlist_b13 G2_DEC_REG(18, 15, 0x1f)
+#define hevc_rlist_b14 G2_DEC_REG(18, 25, 0x1f)
+
+#define hevc_rlist_f15 G2_DEC_REG(19, 0, 0x1f)
+#define hevc_rlist_b15 G2_DEC_REG(19, 5, 0x1f)
+
+#define g2_partial_ctb_x G2_DEC_REG(20, 31, 0x1)
+#define g2_partial_ctb_y G2_DEC_REG(20, 30, 0x1)
+#define g2_pic_width_4x4 G2_DEC_REG(20, 16, 0xfff)
+#define g2_pic_height_4x4 G2_DEC_REG(20, 0, 0xfff)
+#define hevc_cur_poc_00 G2_DEC_REG(46, 24, 0xff)
+#define hevc_cur_poc_01 G2_DEC_REG(46, 16, 0xff)
+#define hevc_cur_poc_02 G2_DEC_REG(46, 8, 0xff)
+#define hevc_cur_poc_03 G2_DEC_REG(46, 0, 0xff)
+
+#define hevc_cur_poc_04 G2_DEC_REG(47, 24, 0xff)
+#define hevc_cur_poc_05 G2_DEC_REG(47, 16, 0xff)
+#define hevc_cur_poc_06 G2_DEC_REG(47, 8, 0xff)
+#define hevc_cur_poc_07 G2_DEC_REG(47, 0, 0xff)
+
+#define hevc_cur_poc_08 G2_DEC_REG(48, 24, 0xff)
+#define hevc_cur_poc_09 G2_DEC_REG(48, 16, 0xff)
+#define hevc_cur_poc_10 G2_DEC_REG(48, 8, 0xff)
+#define hevc_cur_poc_11 G2_DEC_REG(48, 0, 0xff)
+
+#define hevc_cur_poc_12 G2_DEC_REG(49, 24, 0xff)
+#define hevc_cur_poc_13 G2_DEC_REG(49, 16, 0xff)
+#define hevc_cur_poc_14 G2_DEC_REG(49, 8, 0xff)
+#define hevc_cur_poc_15 G2_DEC_REG(49, 0, 0xff)
+
+#define g2_apf_threshold G2_DEC_REG(55, 0, 0xffff)
+
+#define g2_clk_gate_e G2_DEC_REG(58, 16, 0x1)
+#define g2_buswidth G2_DEC_REG(58, 8, 0x7)
+#define g2_max_burst G2_DEC_REG(58, 0, 0xff)
+
+#define G2_REG_CONFIG G2_SWREG(58)
+#define G2_REG_CONFIG_DEC_CLK_GATE_E BIT(16)
+#define G2_REG_CONFIG_DEC_CLK_GATE_IDLE_E BIT(17)
+
+#define G2_ADDR_DST (G2_SWREG(65))
+#define G2_REG_ADDR_REF(i) (G2_SWREG(67) + ((i) * 0x8))
+#define G2_ADDR_DST_CHR (G2_SWREG(99))
+#define G2_REG_CHR_REF(i) (G2_SWREG(101) + ((i) * 0x8))
+#define G2_ADDR_DST_MV (G2_SWREG(133))
+#define G2_REG_DMV_REF(i) (G2_SWREG(135) + ((i) * 0x8))
+#define G2_ADDR_TILE_SIZE (G2_SWREG(167))
+#define G2_ADDR_STR (G2_SWREG(169))
+#define HEVC_SCALING_LIST (G2_SWREG(171))
+#define G2_RASTER_SCAN (G2_SWREG(175))
+#define G2_RASTER_SCAN_CHR (G2_SWREG(177))
+#define G2_TILE_FILTER (G2_SWREG(179))
+#define G2_TILE_SAO (G2_SWREG(181))
+#define G2_TILE_BSD (G2_SWREG(183))
+
+#define g2_strm_buffer_len G2_DEC_REG(258, 0, 0xffffffff)
+#define g2_strm_start_offset G2_DEC_REG(259, 0, 0xffffffff)
+
+#endif
diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
index b88dc4ed06db..56cf261a8e95 100644
--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
+++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
@@ -88,7 +88,7 @@ hantro_h1_jpeg_enc_set_qtable(struct hantro_dev *vpu,
}
}
-void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
+int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
@@ -136,6 +136,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
hantro_end_prepare_run(ctx);
vepu_write(vpu, reg, H1_REG_ENC_CTRL);
+
+ return 0;
}
void hantro_jpeg_enc_done(struct hantro_ctx *ctx)
diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c
new file mode 100644
index 000000000000..5347f5a41c2a
--- /dev/null
+++ b/drivers/staging/media/hantro/hantro_hevc.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VPU HEVC codec driver
+ *
+ * Copyright (C) 2020 Safran Passenger Innovations LLC
+ */
+
+#include <linux/types.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "hantro.h"
+#include "hantro_hw.h"
+
+#define VERT_FILTER_RAM_SIZE 8 /* bytes per pixel row */
+/*
+ * BSD control data of current picture at tile border
+ * 128 bits per 4x4 tile = 128/(8*4) bytes per row
+ */
+#define BSD_CTRL_RAM_SIZE 4 /* bytes per pixel row */
+/* tile border coefficients of filter */
+#define VERT_SAO_RAM_SIZE 48 /* bytes per pixel */
+
+#define MAX_TILE_COLS 20
+#define MAX_TILE_ROWS 22
+
+#define UNUSED_REF -1
+
+#define G2_ALIGN 16
+
+size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps)
+{
+ int bytes_per_pixel = sps->bit_depth_luma_minus8 == 0 ? 1 : 2;
+
+ return sps->pic_width_in_luma_samples *
+ sps->pic_height_in_luma_samples * bytes_per_pixel;
+}
+
+size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps)
+{
+ size_t cr_offset = hantro_hevc_chroma_offset(sps);
+
+ return ALIGN((cr_offset * 3) / 2, G2_ALIGN);
+}
+
+static size_t hantro_hevc_mv_size(const struct v4l2_ctrl_hevc_sps *sps)
+{
+ u32 min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3;
+ u32 ctb_log2_size_y = min_cb_log2_size_y + sps->log2_diff_max_min_luma_coding_block_size;
+ u32 pic_width_in_ctbs_y = (sps->pic_width_in_luma_samples + (1 << ctb_log2_size_y) - 1)
+ >> ctb_log2_size_y;
+ u32 pic_height_in_ctbs_y = (sps->pic_height_in_luma_samples + (1 << ctb_log2_size_y) - 1)
+ >> ctb_log2_size_y;
+ size_t mv_size;
+
+ mv_size = pic_width_in_ctbs_y * pic_height_in_ctbs_y *
+ (1 << (2 * (ctb_log2_size_y - 4))) * 16;
+
+ vpu_debug(4, "%dx%d (CTBs) %zu MV bytes\n",
+ pic_width_in_ctbs_y, pic_height_in_ctbs_y, mv_size);
+
+ return mv_size;
+}
+
+static size_t hantro_hevc_ref_size(struct hantro_ctx *ctx)
+{
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+
+ return hantro_hevc_motion_vectors_offset(sps) + hantro_hevc_mv_size(sps);
+}
+
+static void hantro_hevc_ref_free(struct hantro_ctx *ctx)
+{
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ struct hantro_dev *vpu = ctx->dev;
+ int i;
+
+ for (i = 0; i < NUM_REF_PICTURES; i++) {
+ if (hevc_dec->ref_bufs[i].cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->ref_bufs[i].size,
+ hevc_dec->ref_bufs[i].cpu,
+ hevc_dec->ref_bufs[i].dma);
+ }
+}
+
+static void hantro_hevc_ref_init(struct hantro_ctx *ctx)
+{
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ int i;
+
+ for (i = 0; i < NUM_REF_PICTURES; i++)
+ hevc_dec->ref_bufs_poc[i] = UNUSED_REF;
+}
+
+dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx,
+ int poc)
+{
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ int i;
+
+ /* Find the reference buffer in already know ones */
+ for (i = 0; i < NUM_REF_PICTURES; i++) {
+ if (hevc_dec->ref_bufs_poc[i] == poc) {
+ hevc_dec->ref_bufs_used |= 1 << i;
+ return hevc_dec->ref_bufs[i].dma;
+ }
+ }
+
+ /* Allocate a new reference buffer */
+ for (i = 0; i < NUM_REF_PICTURES; i++) {
+ if (hevc_dec->ref_bufs_poc[i] == UNUSED_REF) {
+ if (!hevc_dec->ref_bufs[i].cpu) {
+ struct hantro_dev *vpu = ctx->dev;
+
+ /*
+ * Allocate the space needed for the raw data +
+ * motion vector data. Optimizations could be to
+ * allocate raw data in non coherent memory and only
+ * clear the motion vector data.
+ */
+ hevc_dec->ref_bufs[i].cpu =
+ dma_alloc_coherent(vpu->dev,
+ hantro_hevc_ref_size(ctx),
+ &hevc_dec->ref_bufs[i].dma,
+ GFP_KERNEL);
+ if (!hevc_dec->ref_bufs[i].cpu)
+ return 0;
+
+ hevc_dec->ref_bufs[i].size = hantro_hevc_ref_size(ctx);
+ }
+ hevc_dec->ref_bufs_used |= 1 << i;
+ memset(hevc_dec->ref_bufs[i].cpu, 0, hantro_hevc_ref_size(ctx));
+ hevc_dec->ref_bufs_poc[i] = poc;
+
+ return hevc_dec->ref_bufs[i].dma;
+ }
+ }
+
+ return 0;
+}
+
+void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx)
+{
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ int i;
+
+ /* Just tag buffer as unused, do not free them */
+ for (i = 0; i < NUM_REF_PICTURES; i++) {
+ if (hevc_dec->ref_bufs_poc[i] == UNUSED_REF)
+ continue;
+
+ if (hevc_dec->ref_bufs_used & (1 << i))
+ continue;
+
+ hevc_dec->ref_bufs_poc[i] = UNUSED_REF;
+ }
+}
+
+static int tile_buffer_reallocate(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+ const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
+ const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
+ unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
+ unsigned int height64 = (sps->pic_height_in_luma_samples + 63) & ~63;
+ unsigned int size;
+
+ if (num_tile_cols <= 1 ||
+ num_tile_cols <= hevc_dec->num_tile_cols_allocated)
+ return 0;
+
+ /* Need to reallocate due to tiles passed via PPS */
+ if (hevc_dec->tile_filter.cpu) {
+ dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
+ hevc_dec->tile_filter.cpu,
+ hevc_dec->tile_filter.dma);
+ hevc_dec->tile_filter.cpu = NULL;
+ }
+
+ if (hevc_dec->tile_sao.cpu) {
+ dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
+ hevc_dec->tile_sao.cpu,
+ hevc_dec->tile_sao.dma);
+ hevc_dec->tile_sao.cpu = NULL;
+ }
+
+ if (hevc_dec->tile_bsd.cpu) {
+ dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
+ hevc_dec->tile_bsd.cpu,
+ hevc_dec->tile_bsd.dma);
+ hevc_dec->tile_bsd.cpu = NULL;
+ }
+
+ size = VERT_FILTER_RAM_SIZE * height64 * (num_tile_cols - 1);
+ hevc_dec->tile_filter.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_filter.dma,
+ GFP_KERNEL);
+ if (!hevc_dec->tile_filter.cpu)
+ goto err_free_tile_buffers;
+ hevc_dec->tile_filter.size = size;
+
+ size = VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1);
+ hevc_dec->tile_sao.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_sao.dma,
+ GFP_KERNEL);
+ if (!hevc_dec->tile_sao.cpu)
+ goto err_free_tile_buffers;
+ hevc_dec->tile_sao.size = size;
+
+ size = BSD_CTRL_RAM_SIZE * height64 * (num_tile_cols - 1);
+ hevc_dec->tile_bsd.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_bsd.dma,
+ GFP_KERNEL);
+ if (!hevc_dec->tile_bsd.cpu)
+ goto err_free_tile_buffers;
+ hevc_dec->tile_bsd.size = size;
+
+ hevc_dec->num_tile_cols_allocated = num_tile_cols;
+
+ return 0;
+
+err_free_tile_buffers:
+ if (hevc_dec->tile_filter.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
+ hevc_dec->tile_filter.cpu,
+ hevc_dec->tile_filter.dma);
+ hevc_dec->tile_filter.cpu = NULL;
+
+ if (hevc_dec->tile_sao.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
+ hevc_dec->tile_sao.cpu,
+ hevc_dec->tile_sao.dma);
+ hevc_dec->tile_sao.cpu = NULL;
+
+ if (hevc_dec->tile_bsd.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
+ hevc_dec->tile_bsd.cpu,
+ hevc_dec->tile_bsd.dma);
+ hevc_dec->tile_bsd.cpu = NULL;
+
+ return -ENOMEM;
+}
+
+int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx)
+{
+ struct hantro_hevc_dec_hw_ctx *hevc_ctx = &ctx->hevc_dec;
+ struct hantro_hevc_dec_ctrls *ctrls = &hevc_ctx->ctrls;
+ int ret;
+
+ hantro_start_prepare_run(ctx);
+
+ ctrls->decode_params =
+ hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS);
+ if (WARN_ON(!ctrls->decode_params))
+ return -EINVAL;
+
+ ctrls->sps =
+ hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_HEVC_SPS);
+ if (WARN_ON(!ctrls->sps))
+ return -EINVAL;
+
+ ctrls->pps =
+ hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_HEVC_PPS);
+ if (WARN_ON(!ctrls->pps))
+ return -EINVAL;
+
+ ret = tile_buffer_reallocate(ctx);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void hantro_hevc_dec_exit(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+
+ if (hevc_dec->tile_sizes.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_sizes.size,
+ hevc_dec->tile_sizes.cpu,
+ hevc_dec->tile_sizes.dma);
+ hevc_dec->tile_sizes.cpu = NULL;
+
+ if (hevc_dec->tile_filter.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
+ hevc_dec->tile_filter.cpu,
+ hevc_dec->tile_filter.dma);
+ hevc_dec->tile_filter.cpu = NULL;
+
+ if (hevc_dec->tile_sao.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
+ hevc_dec->tile_sao.cpu,
+ hevc_dec->tile_sao.dma);
+ hevc_dec->tile_sao.cpu = NULL;
+
+ if (hevc_dec->tile_bsd.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
+ hevc_dec->tile_bsd.cpu,
+ hevc_dec->tile_bsd.dma);
+ hevc_dec->tile_bsd.cpu = NULL;
+
+ hantro_hevc_ref_free(ctx);
+}
+
+int hantro_hevc_dec_init(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
+ unsigned int size;
+
+ memset(hevc_dec, 0, sizeof(*hevc_dec));
+
+ /*
+ * Maximum number of tiles times width and height (2 bytes each),
+ * rounding up to next 16 bytes boundary + one extra 16 byte
+ * chunk (HW guys wanted to have this).
+ */
+ size = round_up(MAX_TILE_COLS * MAX_TILE_ROWS * 4 * sizeof(u16) + 16, 16);
+ hevc_dec->tile_sizes.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_sizes.dma,
+ GFP_KERNEL);
+ if (!hevc_dec->tile_sizes.cpu)
+ return -ENOMEM;
+
+ hevc_dec->tile_sizes.size = size;
+
+ hantro_hevc_ref_init(ctx);
+
+ return 0;
+}
diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h
index 83b3e42b63a3..5dcf65805396 100644
--- a/drivers/staging/media/hantro/hantro_hw.h
+++ b/drivers/staging/media/hantro/hantro_hw.h
@@ -20,6 +20,8 @@
#define MB_WIDTH(w) DIV_ROUND_UP(w, MB_DIM)
#define MB_HEIGHT(h) DIV_ROUND_UP(h, MB_DIM)
+#define NUM_REF_PICTURES (V4L2_HEVC_DPB_ENTRIES_NUM_MAX + 1)
+
struct hantro_dev;
struct hantro_ctx;
struct hantro_buf;
@@ -96,6 +98,46 @@ struct hantro_h264_dec_hw_ctx {
};
/**
+ * struct hantro_hevc_dec_ctrls
+ * @decode_params: Decode params
+ * @sps: SPS info
+ * @pps: PPS info
+ * @hevc_hdr_skip_length: the number of data (in bits) to skip in the
+ * slice segment header syntax after 'slice type'
+ * token
+ */
+struct hantro_hevc_dec_ctrls {
+ const struct v4l2_ctrl_hevc_decode_params *decode_params;
+ const struct v4l2_ctrl_hevc_sps *sps;
+ const struct v4l2_ctrl_hevc_pps *pps;
+ u32 hevc_hdr_skip_length;
+};
+
+/**
+ * struct hantro_hevc_dec_hw_ctx
+ * @tile_sizes: Tile sizes buffer
+ * @tile_filter: Tile vertical filter buffer
+ * @tile_sao: Tile SAO buffer
+ * @tile_bsd: Tile BSD control buffer
+ * @ref_bufs: Internal reference buffers
+ * @ref_bufs_poc: Internal reference buffers picture order count
+ * @ref_bufs_used: Bitfield of used reference buffers
+ * @ctrls: V4L2 controls attached to a run
+ * @num_tile_cols_allocated: number of allocated tiles
+ */
+struct hantro_hevc_dec_hw_ctx {
+ struct hantro_aux_buf tile_sizes;
+ struct hantro_aux_buf tile_filter;
+ struct hantro_aux_buf tile_sao;
+ struct hantro_aux_buf tile_bsd;
+ struct hantro_aux_buf ref_bufs[NUM_REF_PICTURES];
+ int ref_bufs_poc[NUM_REF_PICTURES];
+ u32 ref_bufs_used;
+ struct hantro_hevc_dec_ctrls ctrls;
+ unsigned int num_tile_cols_allocated;
+};
+
+/**
* struct hantro_mpeg2_dec_hw_ctx
*
* @qtable: Quantization table
@@ -133,14 +175,15 @@ struct hantro_postproc_ctx {
* Optional and called from process context.
* @run: Start single {en,de)coding job. Called from atomic context
* to indicate that a pair of buffers is ready and the hardware
- * should be programmed and started.
+ * should be programmed and started. Returns zero if OK, a
+ * negative value in error cases.
* @done: Read back processing results and additional data from hardware.
* @reset: Reset the hardware in case of a timeout.
*/
struct hantro_codec_ops {
int (*init)(struct hantro_ctx *ctx);
void (*exit)(struct hantro_ctx *ctx);
- void (*run)(struct hantro_ctx *ctx);
+ int (*run)(struct hantro_ctx *ctx);
void (*done)(struct hantro_ctx *ctx);
void (*reset)(struct hantro_ctx *ctx);
};
@@ -148,22 +191,26 @@ struct hantro_codec_ops {
/**
* enum hantro_enc_fmt - source format ID for hardware registers.
*
- * @RK3288_VPU_ENC_FMT_YUV420P: Y/CbCr 4:2:0 planar format
- * @RK3288_VPU_ENC_FMT_YUV420SP: Y/CbCr 4:2:0 semi-planar format
- * @RK3288_VPU_ENC_FMT_YUYV422: YUV 4:2:2 packed format (YUYV)
- * @RK3288_VPU_ENC_FMT_UYVY422: YUV 4:2:2 packed format (UYVY)
+ * @ROCKCHIP_VPU_ENC_FMT_YUV420P: Y/CbCr 4:2:0 planar format
+ * @ROCKCHIP_VPU_ENC_FMT_YUV420SP: Y/CbCr 4:2:0 semi-planar format
+ * @ROCKCHIP_VPU_ENC_FMT_YUYV422: YUV 4:2:2 packed format (YUYV)
+ * @ROCKCHIP_VPU_ENC_FMT_UYVY422: YUV 4:2:2 packed format (UYVY)
*/
enum hantro_enc_fmt {
- RK3288_VPU_ENC_FMT_YUV420P = 0,
- RK3288_VPU_ENC_FMT_YUV420SP = 1,
- RK3288_VPU_ENC_FMT_YUYV422 = 2,
- RK3288_VPU_ENC_FMT_UYVY422 = 3,
+ ROCKCHIP_VPU_ENC_FMT_YUV420P = 0,
+ ROCKCHIP_VPU_ENC_FMT_YUV420SP = 1,
+ ROCKCHIP_VPU_ENC_FMT_YUYV422 = 2,
+ ROCKCHIP_VPU_ENC_FMT_UYVY422 = 3,
};
-extern const struct hantro_variant rk3399_vpu_variant;
-extern const struct hantro_variant rk3328_vpu_variant;
-extern const struct hantro_variant rk3288_vpu_variant;
+extern const struct hantro_variant imx8mq_vpu_g2_variant;
extern const struct hantro_variant imx8mq_vpu_variant;
+extern const struct hantro_variant rk3036_vpu_variant;
+extern const struct hantro_variant rk3066_vpu_variant;
+extern const struct hantro_variant rk3288_vpu_variant;
+extern const struct hantro_variant rk3328_vpu_variant;
+extern const struct hantro_variant rk3399_vpu_variant;
+extern const struct hantro_variant sama5d4_vdec_variant;
extern const struct hantro_postproc_regs hantro_g1_postproc_regs;
@@ -176,8 +223,11 @@ void hantro_irq_done(struct hantro_dev *vpu,
void hantro_start_prepare_run(struct hantro_ctx *ctx);
void hantro_end_prepare_run(struct hantro_ctx *ctx);
-void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx);
-void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx);
+irqreturn_t hantro_g1_irq(int irq, void *dev_id);
+void hantro_g1_reset(struct hantro_ctx *ctx);
+
+int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx);
+int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx);
int hantro_jpeg_enc_init(struct hantro_ctx *ctx);
void hantro_jpeg_enc_exit(struct hantro_ctx *ctx);
void hantro_jpeg_enc_done(struct hantro_ctx *ctx);
@@ -185,10 +235,19 @@ void hantro_jpeg_enc_done(struct hantro_ctx *ctx);
dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
unsigned int dpb_idx);
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx);
-void hantro_g1_h264_dec_run(struct hantro_ctx *ctx);
+int hantro_g1_h264_dec_run(struct hantro_ctx *ctx);
int hantro_h264_dec_init(struct hantro_ctx *ctx);
void hantro_h264_dec_exit(struct hantro_ctx *ctx);
+int hantro_hevc_dec_init(struct hantro_ctx *ctx);
+void hantro_hevc_dec_exit(struct hantro_ctx *ctx);
+int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx);
+int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx);
+dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, int poc);
+void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx);
+size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps);
+size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps);
+
static inline size_t
hantro_h264_mv_size(unsigned int width, unsigned int height)
{
@@ -216,15 +275,15 @@ hantro_h264_mv_size(unsigned int width, unsigned int height)
return 64 * MB_WIDTH(width) * MB_WIDTH(height) + 32;
}
-void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx);
-void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx);
+int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx);
+int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx);
void hantro_mpeg2_dec_copy_qtable(u8 *qtable,
- const struct v4l2_ctrl_mpeg2_quantization *ctrl);
+ const struct v4l2_ctrl_mpeg2_quantisation *ctrl);
int hantro_mpeg2_dec_init(struct hantro_ctx *ctx);
void hantro_mpeg2_dec_exit(struct hantro_ctx *ctx);
-void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx);
-void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx);
+int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx);
+int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx);
int hantro_vp8_dec_init(struct hantro_ctx *ctx);
void hantro_vp8_dec_exit(struct hantro_ctx *ctx);
void hantro_vp8_prob_update(struct hantro_ctx *ctx,
diff --git a/drivers/staging/media/hantro/hantro_mpeg2.c b/drivers/staging/media/hantro/hantro_mpeg2.c
index 1d334e6fcd06..04e545eb0a83 100644
--- a/drivers/staging/media/hantro/hantro_mpeg2.c
+++ b/drivers/staging/media/hantro/hantro_mpeg2.c
@@ -19,7 +19,7 @@ static const u8 zigzag[64] = {
};
void hantro_mpeg2_dec_copy_qtable(u8 *qtable,
- const struct v4l2_ctrl_mpeg2_quantization *ctrl)
+ const struct v4l2_ctrl_mpeg2_quantisation *ctrl)
{
int i, n;
diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c
index 6d2a8f2a8f0b..ed8916c950a4 100644
--- a/drivers/staging/media/hantro/hantro_postproc.c
+++ b/drivers/staging/media/hantro/hantro_postproc.c
@@ -50,6 +50,20 @@ const struct hantro_postproc_regs hantro_g1_postproc_regs = {
.display_width = {G1_REG_PP_DISPLAY_WIDTH, 0, 0xfff},
};
+bool hantro_needs_postproc(const struct hantro_ctx *ctx,
+ const struct hantro_fmt *fmt)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ if (ctx->is_encoder)
+ return false;
+
+ if (!vpu->variant->postproc_fmts)
+ return false;
+
+ return fmt->fourcc != V4L2_PIX_FMT_NV12;
+}
+
void hantro_postproc_enable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c
index 1bc118e375a1..bcb0bdff4a9a 100644
--- a/drivers/staging/media/hantro/hantro_v4l2.c
+++ b/drivers/staging/media/hantro/hantro_v4l2.c
@@ -55,7 +55,9 @@ static const struct hantro_fmt *
hantro_get_postproc_formats(const struct hantro_ctx *ctx,
unsigned int *num_fmts)
{
- if (ctx->is_encoder) {
+ struct hantro_dev *vpu = ctx->dev;
+
+ if (ctx->is_encoder || !vpu->variant->postproc_fmts) {
*num_fmts = 0;
return NULL;
}
@@ -390,6 +392,7 @@ hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc)
case V4L2_PIX_FMT_MPEG2_SLICE:
case V4L2_PIX_FMT_VP8_FRAME:
case V4L2_PIX_FMT_H264_SLICE:
+ case V4L2_PIX_FMT_HEVC_SLICE:
ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = true;
break;
default:
@@ -639,7 +642,14 @@ static int hantro_buf_prepare(struct vb2_buffer *vb)
ret = hantro_buf_plane_check(vb, pix_fmt);
if (ret)
return ret;
- vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
+ /*
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
+ * it to buffer length).
+ */
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
+ vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
+
return 0;
}
diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c
index c222de075ef4..ea919bfb9891 100644
--- a/drivers/staging/media/hantro/imx8m_vpu_hw.c
+++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c
@@ -11,6 +11,7 @@
#include "hantro.h"
#include "hantro_jpeg.h"
#include "hantro_g1_regs.h"
+#include "hantro_g2_regs.h"
#define CTRL_SOFT_RESET 0x00
#define RESET_G1 BIT(1)
@@ -109,10 +110,10 @@ static const struct hantro_fmt imx8m_vpu_dec_fmts[] = {
.frmsize = {
.min_width = 48,
.max_width = 3840,
- .step_width = 16,
+ .step_width = MB_DIM,
.min_height = 48,
.max_height = 2160,
- .step_height = 16,
+ .step_height = MB_DIM,
},
},
{
@@ -130,6 +131,26 @@ static const struct hantro_fmt imx8m_vpu_dec_fmts[] = {
},
};
+static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_HEVC_SLICE,
+ .codec_mode = HANTRO_MODE_HEVC_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 3840,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 2160,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
@@ -148,9 +169,26 @@ static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t imx8m_vpu_g2_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vdpu_read(vpu, G2_REG_INTERRUPT);
+ state = (status & G2_REG_INTERRUPT_DEC_RDY_INT) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vdpu_write(vpu, 0, G2_REG_INTERRUPT);
+ vdpu_write(vpu, G2_REG_CONFIG_DEC_CLK_GATE_E, G2_REG_CONFIG);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
static int imx8mq_vpu_hw_init(struct hantro_dev *vpu)
{
- vpu->dec_base = vpu->reg_bases[0];
vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1];
return 0;
@@ -163,6 +201,13 @@ static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)
imx8m_soft_reset(vpu, RESET_G1);
}
+static void imx8m_vpu_g2_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ imx8m_soft_reset(vpu, RESET_G2);
+}
+
/*
* Supported codec ops.
*/
@@ -188,13 +233,25 @@ static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = {
},
};
+static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = {
+ [HANTRO_MODE_HEVC_DEC] = {
+ .run = hantro_g2_hevc_dec_run,
+ .reset = imx8m_vpu_g2_reset,
+ .init = hantro_hevc_dec_init,
+ .exit = hantro_hevc_dec_exit,
+ },
+};
+
/*
* VPU variants.
*/
static const struct hantro_irq imx8mq_irqs[] = {
{ "g1", imx8m_vpu_g1_irq },
- { "g2", NULL /* TODO: imx8m_vpu_g2_irq */ },
+};
+
+static const struct hantro_irq imx8mq_g2_irqs[] = {
+ { "g2", imx8m_vpu_g2_irq },
};
static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };
@@ -218,3 +275,17 @@ const struct hantro_variant imx8mq_vpu_variant = {
.reg_names = imx8mq_reg_names,
.num_regs = ARRAY_SIZE(imx8mq_reg_names)
};
+
+const struct hantro_variant imx8mq_vpu_g2_variant = {
+ .dec_offset = 0x0,
+ .dec_fmts = imx8m_vpu_g2_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts),
+ .codec = HANTRO_HEVC_DECODER,
+ .codec_ops = imx8mq_vpu_g2_codec_ops,
+ .init = imx8mq_vpu_hw_init,
+ .runtime_resume = imx8mq_runtime_resume,
+ .irqs = imx8mq_g2_irqs,
+ .num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
+ .clk_names = imx8mq_clk_names,
+ .num_clocks = ARRAY_SIZE(imx8mq_clk_names),
+};
diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c
deleted file mode 100644
index 7b299ee3e93d..000000000000
--- a/drivers/staging/media/hantro/rk3288_vpu_hw.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Hantro VPU codec driver
- *
- * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
- * Jeffy Chen <jeffy.chen@rock-chips.com>
- */
-
-#include <linux/clk.h>
-
-#include "hantro.h"
-#include "hantro_jpeg.h"
-#include "hantro_g1_regs.h"
-#include "hantro_h1_regs.h"
-
-#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
-
-/*
- * Supported formats.
- */
-
-static const struct hantro_fmt rk3288_vpu_enc_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_YUV420M,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUV420P,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUV420SP,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUYV422,
- },
- {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_UYVY422,
- },
- {
- .fourcc = V4L2_PIX_FMT_JPEG,
- .codec_mode = HANTRO_MODE_JPEG_ENC,
- .max_depth = 2,
- .header_size = JPEG_HEADER_SIZE,
- .frmsize = {
- .min_width = 96,
- .max_width = 8192,
- .step_width = MB_DIM,
- .min_height = 32,
- .max_height = 8192,
- .step_height = MB_DIM,
- },
- },
-};
-
-static const struct hantro_fmt rk3288_vpu_postproc_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .codec_mode = HANTRO_MODE_NONE,
- },
-};
-
-static const struct hantro_fmt rk3288_vpu_dec_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_NV12,
- .codec_mode = HANTRO_MODE_NONE,
- },
- {
- .fourcc = V4L2_PIX_FMT_H264_SLICE,
- .codec_mode = HANTRO_MODE_H264_DEC,
- .max_depth = 2,
- .frmsize = {
- .min_width = 48,
- .max_width = 4096,
- .step_width = MB_DIM,
- .min_height = 48,
- .max_height = 2304,
- .step_height = MB_DIM,
- },
- },
- {
- .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
- .codec_mode = HANTRO_MODE_MPEG2_DEC,
- .max_depth = 2,
- .frmsize = {
- .min_width = 48,
- .max_width = 1920,
- .step_width = MB_DIM,
- .min_height = 48,
- .max_height = 1088,
- .step_height = MB_DIM,
- },
- },
- {
- .fourcc = V4L2_PIX_FMT_VP8_FRAME,
- .codec_mode = HANTRO_MODE_VP8_DEC,
- .max_depth = 2,
- .frmsize = {
- .min_width = 48,
- .max_width = 3840,
- .step_width = MB_DIM,
- .min_height = 48,
- .max_height = 2160,
- .step_height = MB_DIM,
- },
- },
-};
-
-static irqreturn_t rk3288_vepu_irq(int irq, void *dev_id)
-{
- struct hantro_dev *vpu = dev_id;
- enum vb2_buffer_state state;
- u32 status;
-
- status = vepu_read(vpu, H1_REG_INTERRUPT);
- state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
- VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
-
- vepu_write(vpu, 0, H1_REG_INTERRUPT);
- vepu_write(vpu, 0, H1_REG_AXI_CTRL);
-
- hantro_irq_done(vpu, state);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id)
-{
- struct hantro_dev *vpu = dev_id;
- enum vb2_buffer_state state;
- u32 status;
-
- status = vdpu_read(vpu, G1_REG_INTERRUPT);
- state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ?
- VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
-
- vdpu_write(vpu, 0, G1_REG_INTERRUPT);
- vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
-
- hantro_irq_done(vpu, state);
-
- return IRQ_HANDLED;
-}
-
-static int rk3288_vpu_hw_init(struct hantro_dev *vpu)
-{
- /* Bump ACLK to max. possible freq. to improve performance. */
- clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ);
- return 0;
-}
-
-static void rk3288_vpu_enc_reset(struct hantro_ctx *ctx)
-{
- struct hantro_dev *vpu = ctx->dev;
-
- vepu_write(vpu, H1_REG_INTERRUPT_DIS_BIT, H1_REG_INTERRUPT);
- vepu_write(vpu, 0, H1_REG_ENC_CTRL);
- vepu_write(vpu, 0, H1_REG_AXI_CTRL);
-}
-
-static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx)
-{
- struct hantro_dev *vpu = ctx->dev;
-
- vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
- vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
- vdpu_write(vpu, 1, G1_REG_SOFT_RESET);
-}
-
-/*
- * Supported codec ops.
- */
-
-static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = {
- [HANTRO_MODE_JPEG_ENC] = {
- .run = hantro_h1_jpeg_enc_run,
- .reset = rk3288_vpu_enc_reset,
- .init = hantro_jpeg_enc_init,
- .done = hantro_jpeg_enc_done,
- .exit = hantro_jpeg_enc_exit,
- },
- [HANTRO_MODE_H264_DEC] = {
- .run = hantro_g1_h264_dec_run,
- .reset = rk3288_vpu_dec_reset,
- .init = hantro_h264_dec_init,
- .exit = hantro_h264_dec_exit,
- },
- [HANTRO_MODE_MPEG2_DEC] = {
- .run = hantro_g1_mpeg2_dec_run,
- .reset = rk3288_vpu_dec_reset,
- .init = hantro_mpeg2_dec_init,
- .exit = hantro_mpeg2_dec_exit,
- },
- [HANTRO_MODE_VP8_DEC] = {
- .run = hantro_g1_vp8_dec_run,
- .reset = rk3288_vpu_dec_reset,
- .init = hantro_vp8_dec_init,
- .exit = hantro_vp8_dec_exit,
- },
-};
-
-/*
- * VPU variant.
- */
-
-static const struct hantro_irq rk3288_irqs[] = {
- { "vepu", rk3288_vepu_irq },
- { "vdpu", rk3288_vdpu_irq },
-};
-
-static const char * const rk3288_clk_names[] = {
- "aclk", "hclk"
-};
-
-const struct hantro_variant rk3288_vpu_variant = {
- .enc_offset = 0x0,
- .enc_fmts = rk3288_vpu_enc_fmts,
- .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts),
- .dec_offset = 0x400,
- .dec_fmts = rk3288_vpu_dec_fmts,
- .num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts),
- .postproc_fmts = rk3288_vpu_postproc_fmts,
- .num_postproc_fmts = ARRAY_SIZE(rk3288_vpu_postproc_fmts),
- .postproc_regs = &hantro_g1_postproc_regs,
- .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
- HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
- .codec_ops = rk3288_vpu_codec_ops,
- .irqs = rk3288_irqs,
- .num_irqs = ARRAY_SIZE(rk3288_irqs),
- .init = rk3288_vpu_hw_init,
- .clk_names = rk3288_clk_names,
- .num_clocks = ARRAY_SIZE(rk3288_clk_names)
-};
diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c
deleted file mode 100644
index 7a7962cf771e..000000000000
--- a/drivers/staging/media/hantro/rk3399_vpu_hw.c
+++ /dev/null
@@ -1,222 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Hantro VPU codec driver
- *
- * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
- * Jeffy Chen <jeffy.chen@rock-chips.com>
- */
-
-#include <linux/clk.h>
-
-#include "hantro.h"
-#include "hantro_jpeg.h"
-#include "rk3399_vpu_regs.h"
-
-#define RK3399_ACLK_MAX_FREQ (400 * 1000 * 1000)
-
-/*
- * Supported formats.
- */
-
-static const struct hantro_fmt rk3399_vpu_enc_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_YUV420M,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUV420P,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUV420SP,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_YUYV422,
- },
- {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .codec_mode = HANTRO_MODE_NONE,
- .enc_fmt = RK3288_VPU_ENC_FMT_UYVY422,
- },
- {
- .fourcc = V4L2_PIX_FMT_JPEG,
- .codec_mode = HANTRO_MODE_JPEG_ENC,
- .max_depth = 2,
- .header_size = JPEG_HEADER_SIZE,
- .frmsize = {
- .min_width = 96,
- .max_width = 8192,
- .step_width = MB_DIM,
- .min_height = 32,
- .max_height = 8192,
- .step_height = MB_DIM,
- },
- },
-};
-
-static const struct hantro_fmt rk3399_vpu_dec_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_NV12,
- .codec_mode = HANTRO_MODE_NONE,
- },
- {
- .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
- .codec_mode = HANTRO_MODE_MPEG2_DEC,
- .max_depth = 2,
- .frmsize = {
- .min_width = 48,
- .max_width = 1920,
- .step_width = MB_DIM,
- .min_height = 48,
- .max_height = 1088,
- .step_height = MB_DIM,
- },
- },
- {
- .fourcc = V4L2_PIX_FMT_VP8_FRAME,
- .codec_mode = HANTRO_MODE_VP8_DEC,
- .max_depth = 2,
- .frmsize = {
- .min_width = 48,
- .max_width = 3840,
- .step_width = MB_DIM,
- .min_height = 48,
- .max_height = 2160,
- .step_height = MB_DIM,
- },
- },
-};
-
-static irqreturn_t rk3399_vepu_irq(int irq, void *dev_id)
-{
- struct hantro_dev *vpu = dev_id;
- enum vb2_buffer_state state;
- u32 status;
-
- status = vepu_read(vpu, VEPU_REG_INTERRUPT);
- state = (status & VEPU_REG_INTERRUPT_FRAME_READY) ?
- VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
-
- vepu_write(vpu, 0, VEPU_REG_INTERRUPT);
- vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
-
- hantro_irq_done(vpu, state);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t rk3399_vdpu_irq(int irq, void *dev_id)
-{
- struct hantro_dev *vpu = dev_id;
- enum vb2_buffer_state state;
- u32 status;
-
- status = vdpu_read(vpu, VDPU_REG_INTERRUPT);
- state = (status & VDPU_REG_INTERRUPT_DEC_IRQ) ?
- VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
-
- vdpu_write(vpu, 0, VDPU_REG_INTERRUPT);
- vdpu_write(vpu, 0, VDPU_REG_AXI_CTRL);
-
- hantro_irq_done(vpu, state);
-
- return IRQ_HANDLED;
-}
-
-static int rk3399_vpu_hw_init(struct hantro_dev *vpu)
-{
- /* Bump ACLK to max. possible freq. to improve performance. */
- clk_set_rate(vpu->clocks[0].clk, RK3399_ACLK_MAX_FREQ);
- return 0;
-}
-
-static void rk3399_vpu_enc_reset(struct hantro_ctx *ctx)
-{
- struct hantro_dev *vpu = ctx->dev;
-
- vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
- vepu_write(vpu, 0, VEPU_REG_ENCODE_START);
- vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
-}
-
-static void rk3399_vpu_dec_reset(struct hantro_ctx *ctx)
-{
- struct hantro_dev *vpu = ctx->dev;
-
- vdpu_write(vpu, VDPU_REG_INTERRUPT_DEC_IRQ_DIS, VDPU_REG_INTERRUPT);
- vdpu_write(vpu, 0, VDPU_REG_EN_FLAGS);
- vdpu_write(vpu, 1, VDPU_REG_SOFT_RESET);
-}
-
-/*
- * Supported codec ops.
- */
-
-static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = {
- [HANTRO_MODE_JPEG_ENC] = {
- .run = rk3399_vpu_jpeg_enc_run,
- .reset = rk3399_vpu_enc_reset,
- .init = hantro_jpeg_enc_init,
- .exit = hantro_jpeg_enc_exit,
- },
- [HANTRO_MODE_MPEG2_DEC] = {
- .run = rk3399_vpu_mpeg2_dec_run,
- .reset = rk3399_vpu_dec_reset,
- .init = hantro_mpeg2_dec_init,
- .exit = hantro_mpeg2_dec_exit,
- },
- [HANTRO_MODE_VP8_DEC] = {
- .run = rk3399_vpu_vp8_dec_run,
- .reset = rk3399_vpu_dec_reset,
- .init = hantro_vp8_dec_init,
- .exit = hantro_vp8_dec_exit,
- },
-};
-
-/*
- * VPU variant.
- */
-
-static const struct hantro_irq rk3399_irqs[] = {
- { "vepu", rk3399_vepu_irq },
- { "vdpu", rk3399_vdpu_irq },
-};
-
-static const char * const rk3399_clk_names[] = {
- "aclk", "hclk"
-};
-
-const struct hantro_variant rk3399_vpu_variant = {
- .enc_offset = 0x0,
- .enc_fmts = rk3399_vpu_enc_fmts,
- .num_enc_fmts = ARRAY_SIZE(rk3399_vpu_enc_fmts),
- .dec_offset = 0x400,
- .dec_fmts = rk3399_vpu_dec_fmts,
- .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
- .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
- HANTRO_VP8_DECODER,
- .codec_ops = rk3399_vpu_codec_ops,
- .irqs = rk3399_irqs,
- .num_irqs = ARRAY_SIZE(rk3399_irqs),
- .init = rk3399_vpu_hw_init,
- .clk_names = rk3399_clk_names,
- .num_clocks = ARRAY_SIZE(rk3399_clk_names)
-};
-
-static const struct hantro_irq rk3328_irqs[] = {
- { "vdpu", rk3399_vdpu_irq },
-};
-
-const struct hantro_variant rk3328_vpu_variant = {
- .dec_offset = 0x400,
- .dec_fmts = rk3399_vpu_dec_fmts,
- .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
- .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER,
- .codec_ops = rk3399_vpu_codec_ops,
- .irqs = rk3328_irqs,
- .num_irqs = ARRAY_SIZE(rk3328_irqs),
- .init = rk3399_vpu_hw_init,
- .clk_names = rk3399_clk_names,
- .num_clocks = ARRAY_SIZE(rk3399_clk_names),
-};
diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
index 3498e6124acd..991213ce1610 100644
--- a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
@@ -28,12 +28,12 @@
#include "hantro.h"
#include "hantro_v4l2.h"
#include "hantro_hw.h"
-#include "rk3399_vpu_regs.h"
+#include "rockchip_vpu2_regs.h"
#define VEPU_JPEG_QUANT_TABLE_COUNT 16
-static void rk3399_vpu_set_src_img_ctrl(struct hantro_dev *vpu,
- struct hantro_ctx *ctx)
+static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
u32 reg;
@@ -59,9 +59,9 @@ static void rk3399_vpu_set_src_img_ctrl(struct hantro_dev *vpu,
vepu_write_relaxed(vpu, reg, VEPU_REG_ENC_CTRL1);
}
-static void rk3399_vpu_jpeg_enc_set_buffers(struct hantro_dev *vpu,
- struct hantro_ctx *ctx,
- struct vb2_buffer *src_buf)
+static void rockchip_vpu2_jpeg_enc_set_buffers(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ struct vb2_buffer *src_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
@@ -92,9 +92,9 @@ static void rk3399_vpu_jpeg_enc_set_buffers(struct hantro_dev *vpu,
}
static void
-rk3399_vpu_jpeg_enc_set_qtable(struct hantro_dev *vpu,
- unsigned char *luma_qtable,
- unsigned char *chroma_qtable)
+rockchip_vpu2_jpeg_enc_set_qtable(struct hantro_dev *vpu,
+ unsigned char *luma_qtable,
+ unsigned char *chroma_qtable)
{
u32 reg, i;
__be32 *luma_qtable_p;
@@ -118,7 +118,7 @@ rk3399_vpu_jpeg_enc_set_qtable(struct hantro_dev *vpu,
}
}
-void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx)
+int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
@@ -141,11 +141,11 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx)
vepu_write_relaxed(vpu, VEPU_REG_ENCODE_FORMAT_JPEG,
VEPU_REG_ENCODE_START);
- rk3399_vpu_set_src_img_ctrl(vpu, ctx);
- rk3399_vpu_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
- rk3399_vpu_jpeg_enc_set_qtable(vpu,
- hantro_jpeg_get_qtable(0),
- hantro_jpeg_get_qtable(1));
+ rockchip_vpu2_set_src_img_ctrl(vpu, ctx);
+ rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
+ rockchip_vpu2_jpeg_enc_set_qtable(vpu,
+ hantro_jpeg_get_qtable(0),
+ hantro_jpeg_get_qtable(1));
reg = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16
@@ -168,4 +168,6 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx)
/* Kick the watchdog and start encoding */
hantro_end_prepare_run(ctx);
vepu_write(vpu, reg, VEPU_REG_ENCODE_START);
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_mpeg2_dec.c
index f610fa5b4335..b66737fab46b 100644
--- a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_mpeg2_dec.c
@@ -79,43 +79,34 @@
#define VDPU_REG_MV_ACCURACY_FWD(v) ((v) ? BIT(2) : 0)
#define VDPU_REG_MV_ACCURACY_BWD(v) ((v) ? BIT(1) : 0)
-#define PICT_TOP_FIELD 1
-#define PICT_BOTTOM_FIELD 2
-#define PICT_FRAME 3
-
static void
-rk3399_vpu_mpeg2_dec_set_quantization(struct hantro_dev *vpu,
- struct hantro_ctx *ctx)
+rockchip_vpu2_mpeg2_dec_set_quantisation(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx)
{
- struct v4l2_ctrl_mpeg2_quantization *quantization;
+ struct v4l2_ctrl_mpeg2_quantisation *q;
- quantization = hantro_get_ctrl(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
- hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu, quantization);
- vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma,
- VDPU_REG_QTABLE_BASE);
+ q = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_MPEG2_QUANTISATION);
+ hantro_mpeg2_dec_copy_qtable(ctx->mpeg2_dec.qtable.cpu, q);
+ vdpu_write_relaxed(vpu, ctx->mpeg2_dec.qtable.dma, VDPU_REG_QTABLE_BASE);
}
static void
-rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
- struct hantro_ctx *ctx,
- struct vb2_buffer *src_buf,
- struct vb2_buffer *dst_buf,
- const struct v4l2_mpeg2_sequence *sequence,
- const struct v4l2_mpeg2_picture *picture,
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params)
+rockchip_vpu2_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ struct vb2_buffer *src_buf,
+ struct vb2_buffer *dst_buf,
+ const struct v4l2_ctrl_mpeg2_sequence *seq,
+ const struct v4l2_ctrl_mpeg2_picture *pic)
{
dma_addr_t forward_addr = 0, backward_addr = 0;
dma_addr_t current_addr, addr;
- switch (picture->picture_coding_type) {
- case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
- backward_addr = hantro_get_ref(ctx,
- slice_params->backward_ref_ts);
+ switch (pic->picture_coding_type) {
+ case V4L2_MPEG2_PIC_CODING_TYPE_B:
+ backward_addr = hantro_get_ref(ctx, pic->backward_ref_ts);
fallthrough;
- case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
- forward_addr = hantro_get_ref(ctx,
- slice_params->forward_ref_ts);
+ case V4L2_MPEG2_PIC_CODING_TYPE_P:
+ forward_addr = hantro_get_ref(ctx, pic->forward_ref_ts);
}
/* Source bitstream buffer */
@@ -126,7 +117,7 @@ rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
current_addr = addr;
- if (picture->picture_structure == PICT_BOTTOM_FIELD)
+ if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD)
addr += ALIGN(ctx->dst_fmt.width, 16);
vdpu_write_relaxed(vpu, addr, VDPU_REG_DEC_OUT_BASE);
@@ -136,18 +127,18 @@ rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
backward_addr = current_addr;
/* Set forward ref frame (top/bottom field) */
- if (picture->picture_structure == PICT_FRAME ||
- picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B ||
- (picture->picture_structure == PICT_TOP_FIELD &&
- picture->top_field_first) ||
- (picture->picture_structure == PICT_BOTTOM_FIELD &&
- !picture->top_field_first)) {
+ if (pic->picture_structure == V4L2_MPEG2_PIC_FRAME ||
+ pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B ||
+ (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD &&
+ pic->flags & V4L2_MPEG2_PIC_TOP_FIELD) ||
+ (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD &&
+ !(pic->flags & V4L2_MPEG2_PIC_TOP_FIELD))) {
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER1_BASE);
- } else if (picture->picture_structure == PICT_TOP_FIELD) {
+ } else if (pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) {
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, current_addr, VDPU_REG_REFER1_BASE);
- } else if (picture->picture_structure == PICT_BOTTOM_FIELD) {
+ } else if (pic->picture_structure == V4L2_MPEG2_PIC_BOTTOM_FIELD) {
vdpu_write_relaxed(vpu, current_addr, VDPU_REG_REFER0_BASE);
vdpu_write_relaxed(vpu, forward_addr, VDPU_REG_REFER1_BASE);
}
@@ -157,13 +148,12 @@ rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu,
vdpu_write_relaxed(vpu, backward_addr, VDPU_REG_REFER3_BASE);
}
-void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx)
+int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
- const struct v4l2_mpeg2_sequence *sequence;
- const struct v4l2_mpeg2_picture *picture;
+ const struct v4l2_ctrl_mpeg2_sequence *seq;
+ const struct v4l2_ctrl_mpeg2_picture *pic;
u32 reg;
src_buf = hantro_get_src_buf(ctx);
@@ -171,10 +161,10 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx)
hantro_start_prepare_run(ctx);
- slice_params = hantro_get_ctrl(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
- sequence = &slice_params->sequence;
- picture = &slice_params->picture;
+ seq = hantro_get_ctrl(ctx,
+ V4L2_CID_STATELESS_MPEG2_SEQUENCE);
+ pic = hantro_get_ctrl(ctx,
+ V4L2_CID_STATELESS_MPEG2_PICTURE);
reg = VDPU_REG_DEC_ADV_PRE_DIS(0) |
VDPU_REG_DEC_SCMD_DIS(0) |
@@ -183,7 +173,7 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx)
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50));
reg = VDPU_REG_INIT_QP(1) |
- VDPU_REG_STREAM_LEN(slice_params->bit_size >> 3);
+ VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51));
reg = VDPU_REG_APF_THRESHOLD(8) |
@@ -209,11 +199,11 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx)
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56));
reg = VDPU_REG_RLC_MODE_E(0) |
- VDPU_REG_PIC_INTERLACE_E(!sequence->progressive_sequence) |
- VDPU_REG_PIC_FIELDMODE_E(picture->picture_structure != PICT_FRAME) |
- VDPU_REG_PIC_B_E(picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B) |
- VDPU_REG_PIC_INTER_E(picture->picture_coding_type != V4L2_MPEG2_PICTURE_CODING_TYPE_I) |
- VDPU_REG_PIC_TOPFIELD_E(picture->picture_structure == PICT_TOP_FIELD) |
+ VDPU_REG_PIC_INTERLACE_E(!(seq->flags & V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE)) |
+ VDPU_REG_PIC_FIELDMODE_E(pic->picture_structure != V4L2_MPEG2_PIC_FRAME) |
+ VDPU_REG_PIC_B_E(pic->picture_coding_type == V4L2_MPEG2_PIC_CODING_TYPE_B) |
+ VDPU_REG_PIC_INTER_E(pic->picture_coding_type != V4L2_MPEG2_PIC_CODING_TYPE_I) |
+ VDPU_REG_PIC_TOPFIELD_E(pic->picture_structure == V4L2_MPEG2_PIC_TOP_FIELD) |
VDPU_REG_FWD_INTERLACE_E(0) |
VDPU_REG_WRITE_MVS_E(0) |
VDPU_REG_DEC_TIMEOUT_E(1) |
@@ -222,36 +212,37 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx)
reg = VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->dst_fmt.width)) |
VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->dst_fmt.height)) |
- VDPU_REG_ALT_SCAN_E(picture->alternate_scan) |
- VDPU_REG_TOPFIELDFIRST_E(picture->top_field_first);
+ VDPU_REG_ALT_SCAN_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
+ VDPU_REG_TOPFIELDFIRST_E(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(120));
- reg = VDPU_REG_STRM_START_BIT(slice_params->data_bit_offset) |
- VDPU_REG_QSCALE_TYPE(picture->q_scale_type) |
- VDPU_REG_CON_MV_E(picture->concealment_motion_vectors) |
- VDPU_REG_INTRA_DC_PREC(picture->intra_dc_precision) |
- VDPU_REG_INTRA_VLC_TAB(picture->intra_vlc_format) |
- VDPU_REG_FRAME_PRED_DCT(picture->frame_pred_frame_dct);
+ reg = VDPU_REG_STRM_START_BIT(0) |
+ VDPU_REG_QSCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE) |
+ VDPU_REG_CON_MV_E(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV) |
+ VDPU_REG_INTRA_DC_PREC(pic->intra_dc_precision) |
+ VDPU_REG_INTRA_VLC_TAB(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC) |
+ VDPU_REG_FRAME_PRED_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(122));
- reg = VDPU_REG_ALT_SCAN_FLAG_E(picture->alternate_scan) |
- VDPU_REG_FCODE_FWD_HOR(picture->f_code[0][0]) |
- VDPU_REG_FCODE_FWD_VER(picture->f_code[0][1]) |
- VDPU_REG_FCODE_BWD_HOR(picture->f_code[1][0]) |
- VDPU_REG_FCODE_BWD_VER(picture->f_code[1][1]) |
+ reg = VDPU_REG_ALT_SCAN_FLAG_E(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN) |
+ VDPU_REG_FCODE_FWD_HOR(pic->f_code[0][0]) |
+ VDPU_REG_FCODE_FWD_VER(pic->f_code[0][1]) |
+ VDPU_REG_FCODE_BWD_HOR(pic->f_code[1][0]) |
+ VDPU_REG_FCODE_BWD_VER(pic->f_code[1][1]) |
VDPU_REG_MV_ACCURACY_FWD(1) |
VDPU_REG_MV_ACCURACY_BWD(1);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(136));
- rk3399_vpu_mpeg2_dec_set_quantization(vpu, ctx);
+ rockchip_vpu2_mpeg2_dec_set_quantisation(vpu, ctx);
- rk3399_vpu_mpeg2_dec_set_buffers(vpu, ctx, &src_buf->vb2_buf,
- &dst_buf->vb2_buf,
- sequence, picture, slice_params);
+ rockchip_vpu2_mpeg2_dec_set_buffers(vpu, ctx, &src_buf->vb2_buf,
+ &dst_buf->vb2_buf, seq, pic);
/* Kick the watchdog and start decoding */
hantro_end_prepare_run(ctx);
reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1);
vdpu_write(vpu, reg, VDPU_SWREG(57));
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c
index 8661a3cc1e6b..951b55f58a61 100644
--- a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c
@@ -503,7 +503,7 @@ static void cfg_buffers(struct hantro_ctx *ctx,
vdpu_write_relaxed(vpu, dst_dma, VDPU_REG_ADDR_DST);
}
-void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx)
+int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
@@ -516,7 +516,7 @@ void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx)
hdr = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_VP8_FRAME);
if (WARN_ON(!hdr))
- return;
+ return -EINVAL;
/* Reset segment_map buffer in keyframe */
if (V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu)
@@ -589,4 +589,6 @@ void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx)
hantro_end_prepare_run(ctx);
hantro_reg_write(vpu, &vp8_dec_start_dec, 1);
+
+ return 0;
}
diff --git a/drivers/staging/media/hantro/rk3399_vpu_regs.h b/drivers/staging/media/hantro/rockchip_vpu2_regs.h
index 88d096920f30..49e40889545b 100644
--- a/drivers/staging/media/hantro/rk3399_vpu_regs.h
+++ b/drivers/staging/media/hantro/rockchip_vpu2_regs.h
@@ -6,8 +6,8 @@
* Alpha Lin <alpha.lin@rock-chips.com>
*/
-#ifndef RK3399_VPU_REGS_H_
-#define RK3399_VPU_REGS_H_
+#ifndef ROCKCHIP_VPU2_REGS_H_
+#define ROCKCHIP_VPU2_REGS_H_
/* Encoder registers. */
#define VEPU_REG_VP8_QUT_1ST(i) (0x000 + ((i) * 0x24))
@@ -597,4 +597,4 @@
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_3(x) (((x) & 0x3ff) << 12)
#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_0(x) (((x) & 0x3ff) << 2)
-#endif /* RK3399_VPU_REGS_H_ */
+#endif /* ROCKCHIP_VPU2_REGS_H_ */
diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c
new file mode 100644
index 000000000000..3ccc16413f42
--- /dev/null
+++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c
@@ -0,0 +1,526 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VPU codec driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ * Jeffy Chen <jeffy.chen@rock-chips.com>
+ */
+
+#include <linux/clk.h>
+
+#include "hantro.h"
+#include "hantro_jpeg.h"
+#include "hantro_g1_regs.h"
+#include "hantro_h1_regs.h"
+#include "rockchip_vpu2_regs.h"
+
+#define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000)
+#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
+
+/*
+ * Supported formats.
+ */
+
+static const struct hantro_fmt rockchip_vpu_enc_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_YUV420M,
+ .codec_mode = HANTRO_MODE_NONE,
+ .enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420P,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .codec_mode = HANTRO_MODE_NONE,
+ .enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUV420SP,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .codec_mode = HANTRO_MODE_NONE,
+ .enc_fmt = ROCKCHIP_VPU_ENC_FMT_YUYV422,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .codec_mode = HANTRO_MODE_NONE,
+ .enc_fmt = ROCKCHIP_VPU_ENC_FMT_UYVY422,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .codec_mode = HANTRO_MODE_JPEG_ENC,
+ .max_depth = 2,
+ .header_size = JPEG_HEADER_SIZE,
+ .frmsize = {
+ .min_width = 96,
+ .max_width = 8192,
+ .step_width = MB_DIM,
+ .min_height = 32,
+ .max_height = 8192,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
+static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+};
+
+static const struct hantro_fmt rk3066_vpu_dec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_H264_SLICE,
+ .codec_mode = HANTRO_MODE_H264_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
+ .codec_mode = HANTRO_MODE_MPEG2_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VP8_FRAME,
+ .codec_mode = HANTRO_MODE_VP8_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
+static const struct hantro_fmt rk3288_vpu_dec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_H264_SLICE,
+ .codec_mode = HANTRO_MODE_H264_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 4096,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 2304,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
+ .codec_mode = HANTRO_MODE_MPEG2_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VP8_FRAME,
+ .codec_mode = HANTRO_MODE_VP8_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 3840,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 2160,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
+static const struct hantro_fmt rk3399_vpu_dec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
+ .codec_mode = HANTRO_MODE_MPEG2_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VP8_FRAME,
+ .codec_mode = HANTRO_MODE_VP8_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 3840,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 2160,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
+static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vepu_read(vpu, H1_REG_INTERRUPT);
+ state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vepu_write(vpu, 0, H1_REG_INTERRUPT);
+ vepu_write(vpu, 0, H1_REG_AXI_CTRL);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rockchip_vpu2_vdpu_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vdpu_read(vpu, VDPU_REG_INTERRUPT);
+ state = (status & VDPU_REG_INTERRUPT_DEC_IRQ) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vdpu_write(vpu, 0, VDPU_REG_INTERRUPT);
+ vdpu_write(vpu, 0, VDPU_REG_AXI_CTRL);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rockchip_vpu2_vepu_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vepu_read(vpu, VEPU_REG_INTERRUPT);
+ state = (status & VEPU_REG_INTERRUPT_FRAME_READY) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vepu_write(vpu, 0, VEPU_REG_INTERRUPT);
+ vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
+static int rk3036_vpu_hw_init(struct hantro_dev *vpu)
+{
+ /* Bump ACLK to max. possible freq. to improve performance. */
+ clk_set_rate(vpu->clocks[0].clk, RK3066_ACLK_MAX_FREQ);
+ return 0;
+}
+
+static int rk3066_vpu_hw_init(struct hantro_dev *vpu)
+{
+ /* Bump ACLKs to max. possible freq. to improve performance. */
+ clk_set_rate(vpu->clocks[0].clk, RK3066_ACLK_MAX_FREQ);
+ clk_set_rate(vpu->clocks[2].clk, RK3066_ACLK_MAX_FREQ);
+ return 0;
+}
+
+static int rockchip_vpu_hw_init(struct hantro_dev *vpu)
+{
+ /* Bump ACLK to max. possible freq. to improve performance. */
+ clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ);
+ return 0;
+}
+
+static void rk3066_vpu_dec_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
+ vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
+}
+
+static void rockchip_vpu1_enc_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ vepu_write(vpu, H1_REG_INTERRUPT_DIS_BIT, H1_REG_INTERRUPT);
+ vepu_write(vpu, 0, H1_REG_ENC_CTRL);
+ vepu_write(vpu, 0, H1_REG_AXI_CTRL);
+}
+
+static void rockchip_vpu2_dec_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ vdpu_write(vpu, VDPU_REG_INTERRUPT_DEC_IRQ_DIS, VDPU_REG_INTERRUPT);
+ vdpu_write(vpu, 0, VDPU_REG_EN_FLAGS);
+ vdpu_write(vpu, 1, VDPU_REG_SOFT_RESET);
+}
+
+static void rockchip_vpu2_enc_reset(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
+ vepu_write(vpu, 0, VEPU_REG_ENCODE_START);
+ vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+}
+
+/*
+ * Supported codec ops.
+ */
+static const struct hantro_codec_ops rk3036_vpu_codec_ops[] = {
+ [HANTRO_MODE_H264_DEC] = {
+ .run = hantro_g1_h264_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = hantro_g1_mpeg2_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = hantro_g1_vp8_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+};
+
+static const struct hantro_codec_ops rk3066_vpu_codec_ops[] = {
+ [HANTRO_MODE_JPEG_ENC] = {
+ .run = hantro_h1_jpeg_enc_run,
+ .reset = rockchip_vpu1_enc_reset,
+ .init = hantro_jpeg_enc_init,
+ .done = hantro_jpeg_enc_done,
+ .exit = hantro_jpeg_enc_exit,
+ },
+ [HANTRO_MODE_H264_DEC] = {
+ .run = hantro_g1_h264_dec_run,
+ .reset = rk3066_vpu_dec_reset,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = hantro_g1_mpeg2_dec_run,
+ .reset = rk3066_vpu_dec_reset,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = hantro_g1_vp8_dec_run,
+ .reset = rk3066_vpu_dec_reset,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+};
+
+static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = {
+ [HANTRO_MODE_JPEG_ENC] = {
+ .run = hantro_h1_jpeg_enc_run,
+ .reset = rockchip_vpu1_enc_reset,
+ .init = hantro_jpeg_enc_init,
+ .done = hantro_jpeg_enc_done,
+ .exit = hantro_jpeg_enc_exit,
+ },
+ [HANTRO_MODE_H264_DEC] = {
+ .run = hantro_g1_h264_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = hantro_g1_mpeg2_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = hantro_g1_vp8_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+};
+
+static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = {
+ [HANTRO_MODE_JPEG_ENC] = {
+ .run = rockchip_vpu2_jpeg_enc_run,
+ .reset = rockchip_vpu2_enc_reset,
+ .init = hantro_jpeg_enc_init,
+ .exit = hantro_jpeg_enc_exit,
+ },
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = rockchip_vpu2_mpeg2_dec_run,
+ .reset = rockchip_vpu2_dec_reset,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = rockchip_vpu2_vp8_dec_run,
+ .reset = rockchip_vpu2_dec_reset,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+};
+
+/*
+ * VPU variant.
+ */
+
+static const struct hantro_irq rockchip_vdpu1_irqs[] = {
+ { "vdpu", hantro_g1_irq },
+};
+
+static const struct hantro_irq rockchip_vpu1_irqs[] = {
+ { "vepu", rockchip_vpu1_vepu_irq },
+ { "vdpu", hantro_g1_irq },
+};
+
+static const struct hantro_irq rockchip_vdpu2_irqs[] = {
+ { "vdpu", rockchip_vpu2_vdpu_irq },
+};
+
+static const struct hantro_irq rockchip_vpu2_irqs[] = {
+ { "vepu", rockchip_vpu2_vepu_irq },
+ { "vdpu", rockchip_vpu2_vdpu_irq },
+};
+
+static const char * const rk3066_vpu_clk_names[] = {
+ "aclk_vdpu", "hclk_vdpu",
+ "aclk_vepu", "hclk_vepu"
+};
+
+static const char * const rockchip_vpu_clk_names[] = {
+ "aclk", "hclk"
+};
+
+const struct hantro_variant rk3036_vpu_variant = {
+ .dec_offset = 0x400,
+ .dec_fmts = rk3066_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts),
+ .postproc_fmts = rockchip_vpu1_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
+ .postproc_regs = &hantro_g1_postproc_regs,
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
+ HANTRO_H264_DECODER,
+ .codec_ops = rk3036_vpu_codec_ops,
+ .irqs = rockchip_vdpu1_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vdpu1_irqs),
+ .init = rk3036_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
+};
+
+/*
+ * Despite this variant has separate clocks for decoder and encoder,
+ * it's still required to enable all four of them for either decoding
+ * or encoding and we can't split it in separate g1/h1 variants.
+ */
+const struct hantro_variant rk3066_vpu_variant = {
+ .enc_offset = 0x0,
+ .enc_fmts = rockchip_vpu_enc_fmts,
+ .num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
+ .dec_offset = 0x400,
+ .dec_fmts = rk3066_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts),
+ .postproc_fmts = rockchip_vpu1_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
+ .postproc_regs = &hantro_g1_postproc_regs,
+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
+ .codec_ops = rk3066_vpu_codec_ops,
+ .irqs = rockchip_vpu1_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs),
+ .init = rk3066_vpu_hw_init,
+ .clk_names = rk3066_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rk3066_vpu_clk_names)
+};
+
+const struct hantro_variant rk3288_vpu_variant = {
+ .enc_offset = 0x0,
+ .enc_fmts = rockchip_vpu_enc_fmts,
+ .num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
+ .dec_offset = 0x400,
+ .dec_fmts = rk3288_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts),
+ .postproc_fmts = rockchip_vpu1_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts),
+ .postproc_regs = &hantro_g1_postproc_regs,
+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
+ .codec_ops = rk3288_vpu_codec_ops,
+ .irqs = rockchip_vpu1_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs),
+ .init = rockchip_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
+};
+
+const struct hantro_variant rk3328_vpu_variant = {
+ .dec_offset = 0x400,
+ .dec_fmts = rk3399_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER,
+ .codec_ops = rk3399_vpu_codec_ops,
+ .irqs = rockchip_vdpu2_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs),
+ .init = rockchip_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names),
+};
+
+const struct hantro_variant rk3399_vpu_variant = {
+ .enc_offset = 0x0,
+ .enc_fmts = rockchip_vpu_enc_fmts,
+ .num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
+ .dec_offset = 0x400,
+ .dec_fmts = rk3399_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
+ HANTRO_VP8_DECODER,
+ .codec_ops = rk3399_vpu_codec_ops,
+ .irqs = rockchip_vpu2_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vpu2_irqs),
+ .init = rockchip_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
+};
diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c
new file mode 100644
index 000000000000..58ae72c2b723
--- /dev/null
+++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VDEC driver
+ *
+ * Copyright (C) 2021 Collabora Ltd, Emil Velikov <emil.velikov@collabora.com>
+ */
+
+#include "hantro.h"
+
+/*
+ * Supported formats.
+ */
+
+static const struct hantro_fmt sama5d4_vdec_postproc_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+};
+
+static const struct hantro_fmt sama5d4_vdec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
+ .codec_mode = HANTRO_MODE_MPEG2_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1280,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 720,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VP8_FRAME,
+ .codec_mode = HANTRO_MODE_VP8_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1280,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 720,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_H264_SLICE,
+ .codec_mode = HANTRO_MODE_H264_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1280,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 720,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
+static int sama5d4_hw_init(struct hantro_dev *vpu)
+{
+ return 0;
+}
+
+/*
+ * Supported codec ops.
+ */
+
+static const struct hantro_codec_ops sama5d4_vdec_codec_ops[] = {
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = hantro_g1_mpeg2_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = hantro_g1_vp8_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+ [HANTRO_MODE_H264_DEC] = {
+ .run = hantro_g1_h264_dec_run,
+ .reset = hantro_g1_reset,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
+};
+
+static const struct hantro_irq sama5d4_irqs[] = {
+ { "vdec", hantro_g1_irq },
+};
+
+static const char * const sama5d4_clk_names[] = { "vdec_clk" };
+
+const struct hantro_variant sama5d4_vdec_variant = {
+ .dec_fmts = sama5d4_vdec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(sama5d4_vdec_fmts),
+ .postproc_fmts = sama5d4_vdec_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(sama5d4_vdec_postproc_fmts),
+ .postproc_regs = &hantro_g1_postproc_regs,
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
+ HANTRO_H264_DECODER,
+ .codec_ops = sama5d4_vdec_codec_ops,
+ .init = sama5d4_hw_init,
+ .irqs = sama5d4_irqs,
+ .num_irqs = ARRAY_SIZE(sama5d4_irqs),
+ .clk_names = sama5d4_clk_names,
+ .num_clocks = ARRAY_SIZE(sama5d4_clk_names),
+};
diff --git a/drivers/staging/media/imx/imx-ic-prp.c b/drivers/staging/media/imx/imx-ic-prp.c
index f21ed881295f..ac5fb332088e 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -79,13 +79,13 @@ static void prp_stop(struct prp_priv *priv)
}
static struct v4l2_mbus_framefmt *
-__prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
struct imx_ic_priv *ic_priv = priv->ic_priv;
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&ic_priv->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&ic_priv->sd, sd_state, pad);
else
return &priv->format_mbus;
}
@@ -95,7 +95,7 @@ __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_pad_config *cfg,
*/
static int prp_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -115,7 +115,8 @@ static int prp_enum_mbus_code(struct v4l2_subdev *sd,
ret = -EINVAL;
goto out;
}
- infmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD, code->which);
+ infmt = __prp_get_fmt(priv, sd_state, PRP_SINK_PAD,
+ code->which);
code->code = infmt->code;
break;
default:
@@ -127,7 +128,7 @@ out:
}
static int prp_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -139,7 +140,7 @@ static int prp_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __prp_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out;
@@ -152,7 +153,7 @@ out:
}
static int prp_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -171,7 +172,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- infmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD, sdformat->which);
+ infmt = __prp_get_fmt(priv, sd_state, PRP_SINK_PAD, sdformat->which);
switch (sdformat->pad) {
case PRP_SINK_PAD:
@@ -201,7 +202,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
imx_media_try_colorimetry(&sdformat->format, true);
- fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __prp_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
out:
mutex_unlock(&priv->lock);
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c
index d990553de87b..9b81cfbcd777 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -787,13 +787,13 @@ static void prp_stop(struct prp_priv *priv)
}
static struct v4l2_mbus_framefmt *
-__prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
struct imx_ic_priv *ic_priv = priv->ic_priv;
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&ic_priv->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&ic_priv->sd, sd_state, pad);
else
return &priv->format_mbus[pad];
}
@@ -841,7 +841,7 @@ static bool prp_bound_align_output(struct v4l2_mbus_framefmt *outfmt,
*/
static int prp_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->pad >= PRPENCVF_NUM_PADS)
@@ -852,7 +852,7 @@ static int prp_enum_mbus_code(struct v4l2_subdev *sd,
}
static int prp_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -864,7 +864,7 @@ static int prp_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __prp_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out;
@@ -877,7 +877,7 @@ out:
}
static void prp_try_fmt(struct prp_priv *priv,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
const struct imx_media_pixfmt **cc)
{
@@ -894,7 +894,8 @@ static void prp_try_fmt(struct prp_priv *priv,
sdformat->format.code = (*cc)->codes[0];
}
- infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD, sdformat->which);
+ infmt = __prp_get_fmt(priv, sd_state, PRPENCVF_SINK_PAD,
+ sdformat->which);
if (sdformat->pad == PRPENCVF_SRC_PAD) {
sdformat->format.field = infmt->field;
@@ -920,7 +921,7 @@ static void prp_try_fmt(struct prp_priv *priv,
}
static int prp_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -938,9 +939,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- prp_try_fmt(priv, cfg, sdformat, &cc);
+ prp_try_fmt(priv, sd_state, sdformat, &cc);
- fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __prp_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
/* propagate a default format to source pad */
@@ -952,9 +953,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
format.pad = PRPENCVF_SRC_PAD;
format.which = sdformat->which;
format.format = sdformat->format;
- prp_try_fmt(priv, cfg, &format, &outcc);
+ prp_try_fmt(priv, sd_state, &format, &outcc);
- outfmt = __prp_get_fmt(priv, cfg, PRPENCVF_SRC_PAD,
+ outfmt = __prp_get_fmt(priv, sd_state, PRPENCVF_SRC_PAD,
sdformat->which);
*outfmt = format.format;
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
@@ -970,7 +971,7 @@ out:
}
static int prp_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct prp_priv *priv = sd_to_priv(sd);
@@ -988,7 +989,7 @@ static int prp_enum_frame_size(struct v4l2_subdev *sd,
format.format.code = fse->code;
format.format.width = 1;
format.format.height = 1;
- prp_try_fmt(priv, cfg, &format, &cc);
+ prp_try_fmt(priv, sd_state, &format, &cc);
fse->min_width = format.format.width;
fse->min_height = format.format.height;
@@ -1000,7 +1001,7 @@ static int prp_enum_frame_size(struct v4l2_subdev *sd,
format.format.code = fse->code;
format.format.width = -1;
format.format.height = -1;
- prp_try_fmt(priv, cfg, &format, &cc);
+ prp_try_fmt(priv, sd_state, &format, &cc);
fse->max_width = format.format.width;
fse->max_height = format.format.height;
out:
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index e3bfd635a89a..bb1305c9daaf 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -750,9 +750,10 @@ static int csi_setup(struct csi_priv *priv)
static int csi_start(struct csi_priv *priv)
{
- struct v4l2_fract *output_fi;
+ struct v4l2_fract *input_fi, *output_fi;
int ret;
+ input_fi = &priv->frame_interval[CSI_SINK_PAD];
output_fi = &priv->frame_interval[priv->active_output_pad];
/* start upstream */
@@ -761,6 +762,17 @@ static int csi_start(struct csi_priv *priv)
if (ret)
return ret;
+ /* Skip first few frames from a BT.656 source */
+ if (priv->upstream_ep.bus_type == V4L2_MBUS_BT656) {
+ u32 delay_usec, bad_frames = 20;
+
+ delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC *
+ input_fi->numerator * bad_frames,
+ input_fi->denominator);
+
+ usleep_range(delay_usec, delay_usec + 1000);
+ }
+
if (priv->dest == IPU_CSI_DEST_IDMAC) {
ret = csi_idmac_start(priv);
if (ret)
@@ -1139,31 +1151,32 @@ static int csi_link_validate(struct v4l2_subdev *sd,
}
static struct v4l2_mbus_framefmt *
-__csi_get_fmt(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__csi_get_fmt(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&priv->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&priv->sd, sd_state, pad);
else
return &priv->format_mbus[pad];
}
static struct v4l2_rect *
-__csi_get_crop(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__csi_get_crop(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_crop(&priv->sd, cfg, CSI_SINK_PAD);
+ return v4l2_subdev_get_try_crop(&priv->sd, sd_state,
+ CSI_SINK_PAD);
else
return &priv->crop;
}
static struct v4l2_rect *
-__csi_get_compose(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__csi_get_compose(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_compose(&priv->sd, cfg,
+ return v4l2_subdev_get_try_compose(&priv->sd, sd_state,
CSI_SINK_PAD);
else
return &priv->compose;
@@ -1171,7 +1184,7 @@ __csi_get_compose(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
static void csi_try_crop(struct csi_priv *priv,
struct v4l2_rect *crop,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_mbus_framefmt *infmt,
struct v4l2_fwnode_endpoint *upstream_ep)
{
@@ -1210,7 +1223,7 @@ static void csi_try_crop(struct csi_priv *priv,
}
static int csi_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1221,7 +1234,7 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, code->which);
+ infmt = __csi_get_fmt(priv, sd_state, CSI_SINK_PAD, code->which);
incc = imx_media_find_mbus_format(infmt->code, PIXFMT_SEL_ANY);
switch (code->pad) {
@@ -1263,7 +1276,7 @@ out:
}
static int csi_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1282,7 +1295,7 @@ static int csi_enum_frame_size(struct v4l2_subdev *sd,
fse->min_height = MIN_H;
fse->max_height = MAX_H;
} else {
- crop = __csi_get_crop(priv, cfg, fse->which);
+ crop = __csi_get_crop(priv, sd_state, fse->which);
fse->min_width = fse->index & 1 ?
crop->width / 2 : crop->width;
@@ -1297,7 +1310,7 @@ static int csi_enum_frame_size(struct v4l2_subdev *sd,
}
static int csi_enum_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval_enum *fie)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1313,7 +1326,7 @@ static int csi_enum_frame_interval(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
input_fi = &priv->frame_interval[CSI_SINK_PAD];
- crop = __csi_get_crop(priv, cfg, fie->which);
+ crop = __csi_get_crop(priv, sd_state, fie->which);
if ((fie->width != crop->width && fie->width != crop->width / 2) ||
(fie->height != crop->height && fie->height != crop->height / 2)) {
@@ -1333,7 +1346,7 @@ out:
}
static int csi_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1345,7 +1358,7 @@ static int csi_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- fmt = __csi_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __csi_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out;
@@ -1358,11 +1371,11 @@ out:
}
static void csi_try_field(struct csi_priv *priv,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct v4l2_mbus_framefmt *infmt =
- __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
+ __csi_get_fmt(priv, sd_state, CSI_SINK_PAD, sdformat->which);
/*
* no restrictions on sink pad field type except must
@@ -1408,7 +1421,7 @@ static void csi_try_field(struct csi_priv *priv,
static void csi_try_fmt(struct csi_priv *priv,
struct v4l2_fwnode_endpoint *upstream_ep,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
struct v4l2_rect *crop,
struct v4l2_rect *compose,
@@ -1418,7 +1431,7 @@ static void csi_try_fmt(struct csi_priv *priv,
struct v4l2_mbus_framefmt *infmt;
u32 code;
- infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
+ infmt = __csi_get_fmt(priv, sd_state, CSI_SINK_PAD, sdformat->which);
switch (sdformat->pad) {
case CSI_SRC_PAD_DIRECT:
@@ -1445,7 +1458,7 @@ static void csi_try_fmt(struct csi_priv *priv,
}
}
- csi_try_field(priv, cfg, sdformat);
+ csi_try_field(priv, sd_state, sdformat);
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
@@ -1469,7 +1482,7 @@ static void csi_try_fmt(struct csi_priv *priv,
sdformat->format.code = (*cc)->codes[0];
}
- csi_try_field(priv, cfg, sdformat);
+ csi_try_field(priv, sd_state, sdformat);
/* Reset crop and compose rectangles */
crop->left = 0;
@@ -1478,7 +1491,8 @@ static void csi_try_fmt(struct csi_priv *priv,
crop->height = sdformat->format.height;
if (sdformat->format.field == V4L2_FIELD_ALTERNATE)
crop->height *= 2;
- csi_try_crop(priv, crop, cfg, &sdformat->format, upstream_ep);
+ csi_try_crop(priv, crop, sd_state, &sdformat->format,
+ upstream_ep);
compose->left = 0;
compose->top = 0;
compose->width = crop->width;
@@ -1492,7 +1506,7 @@ static void csi_try_fmt(struct csi_priv *priv,
}
static int csi_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1518,12 +1532,13 @@ static int csi_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- crop = __csi_get_crop(priv, cfg, sdformat->which);
- compose = __csi_get_compose(priv, cfg, sdformat->which);
+ crop = __csi_get_crop(priv, sd_state, sdformat->which);
+ compose = __csi_get_compose(priv, sd_state, sdformat->which);
- csi_try_fmt(priv, &upstream_ep, cfg, sdformat, crop, compose, &cc);
+ csi_try_fmt(priv, &upstream_ep, sd_state, sdformat, crop, compose,
+ &cc);
- fmt = __csi_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __csi_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
if (sdformat->pad == CSI_SINK_PAD) {
@@ -1538,10 +1553,11 @@ static int csi_set_fmt(struct v4l2_subdev *sd,
format.pad = pad;
format.which = sdformat->which;
format.format = sdformat->format;
- csi_try_fmt(priv, &upstream_ep, cfg, &format,
+ csi_try_fmt(priv, &upstream_ep, sd_state, &format,
NULL, compose, &outcc);
- outfmt = __csi_get_fmt(priv, cfg, pad, sdformat->which);
+ outfmt = __csi_get_fmt(priv, sd_state, pad,
+ sdformat->which);
*outfmt = format.format;
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
@@ -1558,7 +1574,7 @@ out:
}
static int csi_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1571,9 +1587,9 @@ static int csi_get_selection(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
- crop = __csi_get_crop(priv, cfg, sel->which);
- compose = __csi_get_compose(priv, cfg, sel->which);
+ infmt = __csi_get_fmt(priv, sd_state, CSI_SINK_PAD, sel->which);
+ crop = __csi_get_crop(priv, sd_state, sel->which);
+ compose = __csi_get_compose(priv, sd_state, sel->which);
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
@@ -1622,7 +1638,7 @@ static int csi_set_scale(u32 *compose, u32 crop, u32 flags)
}
static int csi_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1647,9 +1663,9 @@ static int csi_set_selection(struct v4l2_subdev *sd,
goto out;
}
- infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
- crop = __csi_get_crop(priv, cfg, sel->which);
- compose = __csi_get_compose(priv, cfg, sel->which);
+ infmt = __csi_get_fmt(priv, sd_state, CSI_SINK_PAD, sel->which);
+ crop = __csi_get_crop(priv, sd_state, sel->which);
+ compose = __csi_get_compose(priv, sd_state, sel->which);
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
@@ -1665,7 +1681,7 @@ static int csi_set_selection(struct v4l2_subdev *sd,
goto out;
}
- csi_try_crop(priv, &sel->r, cfg, infmt, &upstream_ep);
+ csi_try_crop(priv, &sel->r, sd_state, infmt, &upstream_ep);
*crop = sel->r;
@@ -1706,7 +1722,7 @@ static int csi_set_selection(struct v4l2_subdev *sd,
for (pad = CSI_SINK_PAD + 1; pad < CSI_NUM_PADS; pad++) {
struct v4l2_mbus_framefmt *outfmt;
- outfmt = __csi_get_fmt(priv, cfg, pad, sel->which);
+ outfmt = __csi_get_fmt(priv, sd_state, pad, sel->which);
outfmt->width = compose->width;
outfmt->height = compose->height;
}
diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c
index 5128915a5d6f..6f90acf9c725 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -429,7 +429,7 @@ EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
* of a subdev. Can be used as the .init_cfg pad operation.
*/
int imx_media_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_mbus_framefmt *mf_try;
struct v4l2_subdev_format format;
@@ -445,7 +445,7 @@ int imx_media_init_cfg(struct v4l2_subdev *sd,
if (ret)
continue;
- mf_try = v4l2_subdev_get_try_format(sd, cfg, pad);
+ mf_try = v4l2_subdev_get_try_format(sd, sd_state, pad);
*mf_try = format.format;
}
diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c
index abf290bda98d..3c2093c520ba 100644
--- a/drivers/staging/media/imx/imx-media-vdic.c
+++ b/drivers/staging/media/imx/imx-media-vdic.c
@@ -532,17 +532,17 @@ out:
}
static struct v4l2_mbus_framefmt *
-__vdic_get_fmt(struct vdic_priv *priv, struct v4l2_subdev_pad_config *cfg,
+__vdic_get_fmt(struct vdic_priv *priv, struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&priv->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&priv->sd, sd_state, pad);
else
return &priv->format_mbus[pad];
}
static int vdic_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->pad >= VDIC_NUM_PADS)
@@ -553,7 +553,7 @@ static int vdic_enum_mbus_code(struct v4l2_subdev *sd,
}
static int vdic_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct vdic_priv *priv = v4l2_get_subdevdata(sd);
@@ -565,7 +565,7 @@ static int vdic_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&priv->lock);
- fmt = __vdic_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __vdic_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out;
@@ -578,7 +578,7 @@ out:
}
static void vdic_try_fmt(struct vdic_priv *priv,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
const struct imx_media_pixfmt **cc)
{
@@ -594,7 +594,7 @@ static void vdic_try_fmt(struct vdic_priv *priv,
sdformat->format.code = (*cc)->codes[0];
}
- infmt = __vdic_get_fmt(priv, cfg, priv->active_input_pad,
+ infmt = __vdic_get_fmt(priv, sd_state, priv->active_input_pad,
sdformat->which);
switch (sdformat->pad) {
@@ -620,7 +620,7 @@ static void vdic_try_fmt(struct vdic_priv *priv,
}
static int vdic_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct vdic_priv *priv = v4l2_get_subdevdata(sd);
@@ -638,9 +638,9 @@ static int vdic_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- vdic_try_fmt(priv, cfg, sdformat, &cc);
+ vdic_try_fmt(priv, sd_state, sdformat, &cc);
- fmt = __vdic_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ fmt = __vdic_get_fmt(priv, sd_state, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
/* propagate format to source pad */
@@ -653,9 +653,9 @@ static int vdic_set_fmt(struct v4l2_subdev *sd,
format.pad = VDIC_SRC_PAD_DIRECT;
format.which = sdformat->which;
format.format = sdformat->format;
- vdic_try_fmt(priv, cfg, &format, &outcc);
+ vdic_try_fmt(priv, sd_state, &format, &outcc);
- outfmt = __vdic_get_fmt(priv, cfg, VDIC_SRC_PAD_DIRECT,
+ outfmt = __vdic_get_fmt(priv, sd_state, VDIC_SRC_PAD_DIRECT,
sdformat->which);
*outfmt = format.format;
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index 492d9a64e704..6740e7917458 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -193,7 +193,7 @@ int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
u32 width, u32 height, u32 code, u32 field,
const struct imx_media_pixfmt **cc);
int imx_media_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg);
+ struct v4l2_subdev_state *sd_state);
void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
bool ic_route);
int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index fc2378ac04b7..9de0ebd439dc 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -508,17 +508,17 @@ out:
}
static struct v4l2_mbus_framefmt *
-__csi2_get_fmt(struct csi2_dev *csi2, struct v4l2_subdev_pad_config *cfg,
+__csi2_get_fmt(struct csi2_dev *csi2, struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csi2->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&csi2->sd, sd_state, pad);
else
return &csi2->format_mbus;
}
static int csi2_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct csi2_dev *csi2 = sd_to_dev(sd);
@@ -526,7 +526,7 @@ static int csi2_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&csi2->lock);
- fmt = __csi2_get_fmt(csi2, cfg, sdformat->pad, sdformat->which);
+ fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
sdformat->format = *fmt;
@@ -536,7 +536,7 @@ static int csi2_get_fmt(struct v4l2_subdev *sd,
}
static int csi2_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct csi2_dev *csi2 = sd_to_dev(sd);
@@ -557,7 +557,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
if (sdformat->pad != CSI2_SINK_PAD)
sdformat->format = csi2->format_mbus;
- fmt = __csi2_get_fmt(csi2, cfg, sdformat->pad, sdformat->which);
+ fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
out:
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index f85a2f5f1413..894c4de31790 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -724,7 +724,7 @@ out_unlock:
}
static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
+ struct v4l2_subdev_state *sd_state)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *mf;
@@ -732,7 +732,7 @@ static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
int i;
for (i = 0; i < IMX7_CSI_PADS_NUM; i++) {
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
+ mf = v4l2_subdev_get_try_format(sd, sd_state, i);
ret = imx_media_init_mbus_fmt(mf, 800, 600, 0, V4L2_FIELD_NONE,
&csi->cc[i]);
@@ -745,18 +745,18 @@ static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
static struct v4l2_mbus_framefmt *
imx7_csi_get_format(struct imx7_csi *csi,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csi->sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&csi->sd, sd_state, pad);
return &csi->format_mbus[pad];
}
static int imx7_csi_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
@@ -765,7 +765,8 @@ static int imx7_csi_enum_mbus_code(struct v4l2_subdev *sd,
mutex_lock(&csi->lock);
- in_fmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SINK, code->which);
+ in_fmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SINK,
+ code->which);
switch (code->pad) {
case IMX7_CSI_PAD_SINK:
@@ -791,7 +792,7 @@ out_unlock:
}
static int imx7_csi_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
@@ -800,7 +801,8 @@ static int imx7_csi_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&csi->lock);
- fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which);
+ fmt = imx7_csi_get_format(csi, sd_state, sdformat->pad,
+ sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out_unlock;
@@ -815,7 +817,7 @@ out_unlock:
}
static int imx7_csi_try_fmt(struct imx7_csi *csi,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
const struct imx_media_pixfmt **cc)
{
@@ -823,7 +825,7 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
struct v4l2_mbus_framefmt *in_fmt;
u32 code;
- in_fmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SINK,
+ in_fmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SINK,
sdformat->which);
if (!in_fmt)
return -EINVAL;
@@ -868,7 +870,7 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
}
static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
@@ -889,11 +891,12 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
goto out_unlock;
}
- ret = imx7_csi_try_fmt(csi, cfg, sdformat, &cc);
+ ret = imx7_csi_try_fmt(csi, sd_state, sdformat, &cc);
if (ret < 0)
goto out_unlock;
- fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which);
+ fmt = imx7_csi_get_format(csi, sd_state, sdformat->pad,
+ sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out_unlock;
@@ -906,11 +909,11 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
format.pad = IMX7_CSI_PAD_SRC;
format.which = sdformat->which;
format.format = sdformat->format;
- if (imx7_csi_try_fmt(csi, cfg, &format, &outcc)) {
+ if (imx7_csi_try_fmt(csi, sd_state, &format, &outcc)) {
ret = -EINVAL;
goto out_unlock;
}
- outfmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SRC,
+ outfmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SRC,
sdformat->which);
*outfmt = format.format;
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
index 025fdc488bd6..ead696eb4610 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -166,15 +167,11 @@
#define MIPI_CSIS_ISP_CONFIG_CH(n) (0x40 + (n) * 0x10)
#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24)
#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) ((x) << 24)
-#define MIPI_CSIS_ISPCFG_DOUBLE_CMPNT BIT(12)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE (0 << 12)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL (1 << 12)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD (2 << 12) /* i.MX8M[MNP] only */
#define MIPI_CSIS_ISPCFG_ALIGN_32BIT BIT(11)
-#define MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT (0x1e << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW8 (0x2a << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW10 (0x2b << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW12 (0x2c << 2)
-#define MIPI_CSIS_ISPCFG_FMT_RAW14 (0x2d << 2)
-/* User defined formats, x = 1...4 */
-#define MIPI_CSIS_ISPCFG_FMT_USER(x) ((0x30 + (x) - 1) << 2)
+#define MIPI_CSIS_ISPCFG_FMT(fmt) ((fmt) << 2)
#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2)
/* ISP Image Resolution register */
@@ -195,6 +192,24 @@
/* Debug control register */
#define MIPI_CSIS_DBG_CTRL 0xc0
+#define MIPI_CSIS_DBG_INTR_MSK 0xc4
+#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25)
+#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24)
+#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE BIT(20)
+#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16)
+#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE BIT(12)
+#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS BIT(8)
+#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL BIT(4)
+#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE BIT(0)
+#define MIPI_CSIS_DBG_INTR_SRC 0xc8
+#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25)
+#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24)
+#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE BIT(20)
+#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16)
+#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE BIT(12)
+#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS BIT(8)
+#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL BIT(4)
+#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE BIT(0)
/* Non-image packet data buffers */
#define MIPI_CSIS_PKTDATA_ODD 0x2000
@@ -203,6 +218,25 @@
#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
+/* MIPI CSI-2 Data Types */
+#define MIPI_CSI2_DATA_TYPE_YUV420_8 0x18
+#define MIPI_CSI2_DATA_TYPE_YUV420_10 0x19
+#define MIPI_CSI2_DATA_TYPE_LE_YUV420_8 0x1a
+#define MIPI_CSI2_DATA_TYPE_CS_YUV420_8 0x1c
+#define MIPI_CSI2_DATA_TYPE_CS_YUV420_10 0x1d
+#define MIPI_CSI2_DATA_TYPE_YUV422_8 0x1e
+#define MIPI_CSI2_DATA_TYPE_YUV422_10 0x1f
+#define MIPI_CSI2_DATA_TYPE_RGB565 0x22
+#define MIPI_CSI2_DATA_TYPE_RGB666 0x23
+#define MIPI_CSI2_DATA_TYPE_RGB888 0x24
+#define MIPI_CSI2_DATA_TYPE_RAW6 0x28
+#define MIPI_CSI2_DATA_TYPE_RAW7 0x29
+#define MIPI_CSI2_DATA_TYPE_RAW8 0x2a
+#define MIPI_CSI2_DATA_TYPE_RAW10 0x2b
+#define MIPI_CSI2_DATA_TYPE_RAW12 0x2c
+#define MIPI_CSI2_DATA_TYPE_RAW14 0x2d
+#define MIPI_CSI2_DATA_TYPE_USER(x) (0x30 + (x))
+
enum {
ST_POWERED = 1,
ST_STREAMING = 2,
@@ -210,6 +244,7 @@ enum {
};
struct mipi_csis_event {
+ bool debug;
u32 mask;
const char * const name;
unsigned int counter;
@@ -217,22 +252,30 @@ struct mipi_csis_event {
static const struct mipi_csis_event mipi_csis_events[] = {
/* Errors */
- { MIPI_CSIS_INT_SRC_ERR_SOT_HS, "SOT Error" },
- { MIPI_CSIS_INT_SRC_ERR_LOST_FS, "Lost Frame Start Error" },
- { MIPI_CSIS_INT_SRC_ERR_LOST_FE, "Lost Frame End Error" },
- { MIPI_CSIS_INT_SRC_ERR_OVER, "FIFO Overflow Error" },
- { MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" },
- { MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" },
- { MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" },
- { MIPI_CSIS_INT_SRC_ERR_UNKNOWN, "Unknown Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS, "SOT Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS, "Lost Frame Start Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE, "Lost Frame End Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_OVER, "FIFO Overflow Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" },
+ { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN, "Unknown Error" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE, "Frame Size Error" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE, "Early Frame End" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS, "Early Frame Start" },
/* Non-image data receive events */
- { MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" },
- { MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" },
- { MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" },
- { MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" },
+ { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" },
+ { false, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" },
+ { false, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" },
+ { false, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" },
/* Frame start/end */
- { MIPI_CSIS_INT_SRC_FRAME_START, "Frame Start" },
- { MIPI_CSIS_INT_SRC_FRAME_END, "Frame End" },
+ { false, MIPI_CSIS_INT_SRC_FRAME_START, "Frame Start" },
+ { false, MIPI_CSIS_INT_SRC_FRAME_END, "Frame End" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL, "VSYNC Falling Edge" },
+ { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE, "VSYNC Rising Edge" },
};
#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
@@ -241,63 +284,63 @@ enum mipi_csis_clk {
MIPI_CSIS_CLK_PCLK,
MIPI_CSIS_CLK_WRAP,
MIPI_CSIS_CLK_PHY,
+ MIPI_CSIS_CLK_AXI,
};
static const char * const mipi_csis_clk_id[] = {
"pclk",
"wrap",
"phy",
+ "axi",
};
-struct csis_hw_reset {
- struct regmap *src;
- u8 req_src;
- u8 rst_bit;
+enum mipi_csis_version {
+ MIPI_CSIS_V3_3,
+ MIPI_CSIS_V3_6_3,
+};
+
+struct mipi_csis_info {
+ enum mipi_csis_version version;
+ unsigned int num_clocks;
};
struct csi_state {
- /* lock elements below */
- struct mutex lock;
- /* lock for event handler */
- spinlock_t slock;
struct device *dev;
+ void __iomem *regs;
+ struct clk_bulk_data *clks;
+ struct reset_control *mrst;
+ struct regulator *mipi_phy_regulator;
+ const struct mipi_csis_info *info;
+ u8 index;
+
+ struct v4l2_subdev sd;
struct media_pad pads[CSIS_PADS_NUM];
- struct v4l2_subdev mipi_sd;
struct v4l2_async_notifier notifier;
struct v4l2_subdev *src_sd;
- u8 index;
- struct platform_device *pdev;
- struct phy *phy;
- void __iomem *regs;
- int irq;
- u32 flags;
-
- struct dentry *debugfs_root;
- bool debug;
-
- int num_clks;
- struct clk_bulk_data *clks;
-
+ struct v4l2_fwnode_bus_mipi_csi2 bus;
u32 clk_frequency;
u32 hs_settle;
+ u32 clk_settle;
- struct reset_control *mrst;
-
+ struct mutex lock; /* Protect csis_fmt, format_mbus and state */
const struct csis_pix_format *csis_fmt;
struct v4l2_mbus_framefmt format_mbus;
+ u32 state;
- struct v4l2_fwnode_bus_mipi_csi2 bus;
-
+ spinlock_t slock; /* Protect events */
struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
-
- struct csis_hw_reset hw_reset;
- struct regulator *mipi_phy_regulator;
+ struct dentry *debugfs_root;
+ bool debug;
};
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
struct csis_pix_format {
u32 code;
- u32 fmt_reg;
+ u32 data_type;
u8 width;
};
@@ -305,156 +348,117 @@ static const struct csis_pix_format mipi_csis_formats[] = {
/* YUV formats. */
{
.code = MEDIA_BUS_FMT_UYVY8_1X16,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
+ .data_type = MIPI_CSI2_DATA_TYPE_YUV422_8,
.width = 16,
},
/* RAW (Bayer and greyscale) formats. */
{
.code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
.width = 8,
}, {
.code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
.width = 8,
}, {
.code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
.width = 8,
}, {
.code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
.width = 8,
}, {
.code = MEDIA_BUS_FMT_Y8_1X8,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
.width = 8,
}, {
.code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
.width = 10,
}, {
.code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
.width = 10,
}, {
.code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
.width = 10,
}, {
.code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
.width = 10,
}, {
.code = MEDIA_BUS_FMT_Y10_1X10,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
.width = 10,
}, {
.code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW12,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
.width = 12,
}, {
.code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW12,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
.width = 12,
}, {
.code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW12,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
.width = 12,
}, {
.code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW12,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
.width = 12,
}, {
.code = MEDIA_BUS_FMT_Y12_1X12,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW12,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
.width = 12,
}, {
.code = MEDIA_BUS_FMT_SBGGR14_1X14,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW14,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
.width = 14,
}, {
.code = MEDIA_BUS_FMT_SGBRG14_1X14,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW14,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
.width = 14,
}, {
.code = MEDIA_BUS_FMT_SGRBG14_1X14,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW14,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
.width = 14,
}, {
.code = MEDIA_BUS_FMT_SRGGB14_1X14,
- .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW14,
+ .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
.width = 14,
}
};
-static inline void mipi_csis_write(struct csi_state *state, u32 reg, u32 val)
-{
- writel(val, state->regs + reg);
-}
-
-static inline u32 mipi_csis_read(struct csi_state *state, u32 reg)
-{
- return readl(state->regs + reg);
-}
-
-static int mipi_csis_dump_regs(struct csi_state *state)
+static const struct csis_pix_format *find_csis_format(u32 code)
{
- struct device *dev = &state->pdev->dev;
unsigned int i;
- u32 cfg;
- static const struct {
- u32 offset;
- const char * const name;
- } registers[] = {
- { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" },
- { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" },
- { MIPI_CSIS_INT_MSK, "INT_MSK" },
- { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" },
- { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" },
- { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" },
- { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" },
- { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" },
- { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" },
- { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" },
- { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" },
- { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" },
- };
- dev_info(dev, "--- REGISTERS ---\n");
-
- for (i = 0; i < ARRAY_SIZE(registers); i++) {
- cfg = mipi_csis_read(state, registers[i].offset);
- dev_info(dev, "%14s: 0x%08x\n", registers[i].name, cfg);
- }
-
- return 0;
+ for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
+ if (code == mipi_csis_formats[i].code)
+ return &mipi_csis_formats[i];
+ return NULL;
}
-static struct csi_state *
-mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
-{
- return container_of(n, struct csi_state, notifier);
-}
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
-static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
+static inline u32 mipi_csis_read(struct csi_state *state, u32 reg)
{
- return container_of(sdev, struct csi_state, mipi_sd);
+ return readl(state->regs + reg);
}
-static const struct csis_pix_format *find_csis_format(u32 code)
+static inline void mipi_csis_write(struct csi_state *state, u32 reg, u32 val)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
- if (code == mipi_csis_formats[i].code)
- return &mipi_csis_formats[i];
- return NULL;
+ writel(val, state->regs + reg);
}
static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
{
mipi_csis_write(state, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0);
+ mipi_csis_write(state, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0);
}
static void mipi_csis_sw_reset(struct csi_state *state)
@@ -466,25 +470,6 @@ static void mipi_csis_sw_reset(struct csi_state *state)
usleep_range(10, 20);
}
-static int mipi_csis_phy_init(struct csi_state *state)
-{
- state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy");
- if (IS_ERR(state->mipi_phy_regulator))
- return PTR_ERR(state->mipi_phy_regulator);
-
- return regulator_set_voltage(state->mipi_phy_regulator, 1000000,
- 1000000);
-}
-
-static void mipi_csis_phy_reset(struct csi_state *state)
-{
- reset_control_assert(state->mrst);
-
- msleep(20);
-
- reset_control_deassert(state->mrst);
-}
-
static void mipi_csis_system_enable(struct csi_state *state, int on)
{
u32 val, mask;
@@ -514,7 +499,7 @@ static void __mipi_csis_set_format(struct csi_state *state)
/* Color format */
val = mipi_csis_read(state, MIPI_CSIS_ISP_CONFIG_CH(0));
val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK);
- val |= state->csis_fmt->fmt_reg;
+ val |= MIPI_CSIS_ISPCFG_FMT(state->csis_fmt->data_type);
mipi_csis_write(state, MIPI_CSIS_ISP_CONFIG_CH(0), val);
/* Pixel resolution */
@@ -546,11 +531,15 @@ static int mipi_csis_calculate_params(struct csi_state *state)
/*
* The HSSETTLE counter value is document in a table, but can also
- * easily be calculated.
+ * easily be calculated. Hardcode the CLKSETTLE value to 0 for now
+ * (which is documented as corresponding to CSI-2 v0.87 to v1.00) until
+ * we figure out how to compute it correctly.
*/
state->hs_settle = (lane_rate - 5000000) / 45000000;
- dev_dbg(state->dev, "lane rate %u, Ths_settle %u\n",
- lane_rate, state->hs_settle);
+ state->clk_settle = 0;
+
+ dev_dbg(state->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n",
+ lane_rate, state->clk_settle, state->hs_settle);
return 0;
}
@@ -563,13 +552,15 @@ static void mipi_csis_set_params(struct csi_state *state)
val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
- val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
+ if (state->info->version == MIPI_CSIS_V3_3)
+ val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
__mipi_csis_set_format(state);
mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL,
- MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(state->hs_settle));
+ MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(state->hs_settle) |
+ MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(state->clk_settle));
val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET)
| (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET)
@@ -601,31 +592,30 @@ static void mipi_csis_set_params(struct csi_state *state)
static int mipi_csis_clk_enable(struct csi_state *state)
{
- return clk_bulk_prepare_enable(state->num_clks, state->clks);
+ return clk_bulk_prepare_enable(state->info->num_clocks, state->clks);
}
static void mipi_csis_clk_disable(struct csi_state *state)
{
- clk_bulk_disable_unprepare(state->num_clks, state->clks);
+ clk_bulk_disable_unprepare(state->info->num_clocks, state->clks);
}
static int mipi_csis_clk_get(struct csi_state *state)
{
- struct device *dev = &state->pdev->dev;
unsigned int i;
int ret;
- state->num_clks = ARRAY_SIZE(mipi_csis_clk_id);
- state->clks = devm_kcalloc(dev, state->num_clks, sizeof(*state->clks),
- GFP_KERNEL);
+ state->clks = devm_kcalloc(state->dev, state->info->num_clocks,
+ sizeof(*state->clks), GFP_KERNEL);
if (!state->clks)
return -ENOMEM;
- for (i = 0; i < state->num_clks; i++)
+ for (i = 0; i < state->info->num_clocks; i++)
state->clks[i].id = mipi_csis_clk_id[i];
- ret = devm_clk_bulk_get(dev, state->num_clks, state->clks);
+ ret = devm_clk_bulk_get(state->dev, state->info->num_clocks,
+ state->clks);
if (ret < 0)
return ret;
@@ -633,8 +623,8 @@ static int mipi_csis_clk_get(struct csi_state *state)
ret = clk_set_rate(state->clks[MIPI_CSIS_CLK_WRAP].clk,
state->clk_frequency);
if (ret < 0)
- dev_err(dev, "set rate=%d failed: %d\n", state->clk_frequency,
- ret);
+ dev_err(state->dev, "set rate=%d failed: %d\n",
+ state->clk_frequency, ret);
return ret;
}
@@ -653,6 +643,89 @@ static void mipi_csis_stop_stream(struct csi_state *state)
mipi_csis_system_enable(state, false);
}
+static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
+{
+ struct csi_state *state = dev_id;
+ unsigned long flags;
+ unsigned int i;
+ u32 status;
+ u32 dbg_status;
+
+ status = mipi_csis_read(state, MIPI_CSIS_INT_SRC);
+ dbg_status = mipi_csis_read(state, MIPI_CSIS_DBG_INTR_SRC);
+
+ spin_lock_irqsave(&state->slock, flags);
+
+ /* Update the event/error counters */
+ if ((status & MIPI_CSIS_INT_SRC_ERRORS) || state->debug) {
+ for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
+ struct mipi_csis_event *event = &state->events[i];
+
+ if ((!event->debug && (status & event->mask)) ||
+ (event->debug && (dbg_status & event->mask)))
+ event->counter++;
+ }
+ }
+ spin_unlock_irqrestore(&state->slock, flags);
+
+ mipi_csis_write(state, MIPI_CSIS_INT_SRC, status);
+ mipi_csis_write(state, MIPI_CSIS_DBG_INTR_SRC, dbg_status);
+
+ return IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * PHY regulator and reset
+ */
+
+static int mipi_csis_phy_enable(struct csi_state *state)
+{
+ if (state->info->version != MIPI_CSIS_V3_3)
+ return 0;
+
+ return regulator_enable(state->mipi_phy_regulator);
+}
+
+static int mipi_csis_phy_disable(struct csi_state *state)
+{
+ if (state->info->version != MIPI_CSIS_V3_3)
+ return 0;
+
+ return regulator_disable(state->mipi_phy_regulator);
+}
+
+static void mipi_csis_phy_reset(struct csi_state *state)
+{
+ if (state->info->version != MIPI_CSIS_V3_3)
+ return;
+
+ reset_control_assert(state->mrst);
+ msleep(20);
+ reset_control_deassert(state->mrst);
+}
+
+static int mipi_csis_phy_init(struct csi_state *state)
+{
+ if (state->info->version != MIPI_CSIS_V3_3)
+ return 0;
+
+ /* Get MIPI PHY reset and regulator. */
+ state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
+ if (IS_ERR(state->mrst))
+ return PTR_ERR(state->mrst);
+
+ state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy");
+ if (IS_ERR(state->mipi_phy_regulator))
+ return PTR_ERR(state->mipi_phy_regulator);
+
+ return regulator_set_voltage(state->mipi_phy_regulator, 1000000,
+ 1000000);
+}
+
+/* -----------------------------------------------------------------------------
+ * Debug
+ */
+
static void mipi_csis_clear_counters(struct csi_state *state)
{
unsigned long flags;
@@ -666,26 +739,90 @@ static void mipi_csis_clear_counters(struct csi_state *state)
static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
{
- int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4;
- struct device *dev = &state->pdev->dev;
+ unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS
+ : MIPI_CSIS_NUM_EVENTS - 8;
unsigned long flags;
+ unsigned int i;
spin_lock_irqsave(&state->slock, flags);
- for (i--; i >= 0; i--) {
+ for (i = 0; i < num_events; ++i) {
if (state->events[i].counter > 0 || state->debug)
- dev_info(dev, "%s events: %d\n", state->events[i].name,
+ dev_info(state->dev, "%s events: %d\n",
+ state->events[i].name,
state->events[i].counter);
}
spin_unlock_irqrestore(&state->slock, flags);
}
-/*
+static int mipi_csis_dump_regs(struct csi_state *state)
+{
+ static const struct {
+ u32 offset;
+ const char * const name;
+ } registers[] = {
+ { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" },
+ { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" },
+ { MIPI_CSIS_INT_MSK, "INT_MSK" },
+ { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" },
+ { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" },
+ { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" },
+ { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" },
+ { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" },
+ { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" },
+ { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" },
+ { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" },
+ { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" },
+ };
+
+ unsigned int i;
+ u32 cfg;
+
+ dev_info(state->dev, "--- REGISTERS ---\n");
+
+ for (i = 0; i < ARRAY_SIZE(registers); i++) {
+ cfg = mipi_csis_read(state, registers[i].offset);
+ dev_info(state->dev, "%14s: 0x%08x\n", registers[i].name, cfg);
+ }
+
+ return 0;
+}
+
+static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
+{
+ struct csi_state *state = m->private;
+
+ return mipi_csis_dump_regs(state);
+}
+DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
+
+static void mipi_csis_debugfs_init(struct csi_state *state)
+{
+ state->debugfs_root = debugfs_create_dir(dev_name(state->dev), NULL);
+
+ debugfs_create_bool("debug_enable", 0600, state->debugfs_root,
+ &state->debug);
+ debugfs_create_file("dump_regs", 0600, state->debugfs_root, state,
+ &mipi_csis_dump_regs_fops);
+}
+
+static void mipi_csis_debugfs_exit(struct csi_state *state)
+{
+ debugfs_remove_recursive(state->debugfs_root);
+}
+
+/* -----------------------------------------------------------------------------
* V4L2 subdev operations
*/
-static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
+
+static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ return container_of(sdev, struct csi_state, sd);
+}
+
+static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
int ret;
if (enable) {
@@ -695,11 +832,10 @@ static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
mipi_csis_clear_counters(state);
- ret = pm_runtime_get_sync(&state->pdev->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(&state->pdev->dev);
+ ret = pm_runtime_resume_and_get(state->dev);
+ if (ret < 0)
return ret;
- }
+
ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
goto done;
@@ -708,7 +844,7 @@ static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
mutex_lock(&state->lock);
if (enable) {
- if (state->flags & ST_SUSPENDED) {
+ if (state->state & ST_SUSPENDED) {
ret = -EBUSY;
goto unlock;
}
@@ -720,14 +856,14 @@ static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
mipi_csis_log_counters(state, true);
- state->flags |= ST_STREAMING;
+ state->state |= ST_STREAMING;
} else {
v4l2_subdev_call(state->src_sd, video, s_stream, 0);
ret = v4l2_subdev_call(state->src_sd, core, s_power, 0);
if (ret == -ENOIOCTLCMD)
ret = 0;
mipi_csis_stop_stream(state);
- state->flags &= ~ST_STREAMING;
+ state->state &= ~ST_STREAMING;
if (state->debug)
mipi_csis_log_counters(state, true);
}
@@ -737,62 +873,33 @@ unlock:
done:
if (!enable || ret < 0)
- pm_runtime_put(&state->pdev->dev);
+ pm_runtime_put(state->dev);
return ret;
}
-static int mipi_csis_link_setup(struct media_entity *entity,
- const struct media_pad *local_pad,
- const struct media_pad *remote_pad, u32 flags)
-{
- struct v4l2_subdev *mipi_sd = media_entity_to_v4l2_subdev(entity);
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
- struct v4l2_subdev *remote_sd;
-
- dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name,
- local_pad->entity->name);
-
- /* We only care about the link to the source. */
- if (!(local_pad->flags & MEDIA_PAD_FL_SINK))
- return 0;
-
- remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
- if (flags & MEDIA_LNK_FL_ENABLED) {
- if (state->src_sd)
- return -EBUSY;
-
- state->src_sd = remote_sd;
- } else {
- state->src_sd = NULL;
- }
-
- return 0;
-}
-
static struct v4l2_mbus_framefmt *
mipi_csis_get_format(struct csi_state *state,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
enum v4l2_subdev_format_whence which,
unsigned int pad)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&state->mipi_sd, cfg, pad);
+ return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
return &state->format_mbus;
}
-static int mipi_csis_init_cfg(struct v4l2_subdev *mipi_sd,
- struct v4l2_subdev_pad_config *cfg)
+static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
struct v4l2_mbus_framefmt *fmt_sink;
struct v4l2_mbus_framefmt *fmt_source;
enum v4l2_subdev_format_whence which;
- which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- fmt_sink = mipi_csis_get_format(state, cfg, which, CSIS_PAD_SINK);
+ which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ fmt_sink = mipi_csis_get_format(state, sd_state, which, CSIS_PAD_SINK);
fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
@@ -811,35 +918,38 @@ static int mipi_csis_init_cfg(struct v4l2_subdev *mipi_sd,
* configuration, cfg is NULL, which indicates there's no source pad
* configuration to set.
*/
- if (!cfg)
+ if (!sd_state)
return 0;
- fmt_source = mipi_csis_get_format(state, cfg, which, CSIS_PAD_SOURCE);
+ fmt_source = mipi_csis_get_format(state, sd_state, which,
+ CSIS_PAD_SOURCE);
*fmt_source = *fmt_sink;
return 0;
}
-static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
- struct v4l2_subdev_pad_config *cfg,
+static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
struct v4l2_mbus_framefmt *fmt;
+ fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
+ sdformat->pad);
+
mutex_lock(&state->lock);
- fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
sdformat->format = *fmt;
mutex_unlock(&state->lock);
return 0;
}
-static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
- struct v4l2_subdev_pad_config *cfg,
+static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
/*
* The CSIS can't transcode in any way, the source format is identical
@@ -851,7 +961,8 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
if (code->index > 0)
return -EINVAL;
- fmt = mipi_csis_get_format(state, cfg, code->which, code->pad);
+ fmt = mipi_csis_get_format(state, sd_state, code->which,
+ code->pad);
code->code = fmt->code;
return 0;
}
@@ -867,11 +978,11 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
return 0;
}
-static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
- struct v4l2_subdev_pad_config *cfg,
+static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
struct csis_pix_format const *csis_fmt;
struct v4l2_mbus_framefmt *fmt;
unsigned int align;
@@ -881,29 +992,22 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
* modified.
*/
if (sdformat->pad == CSIS_PAD_SOURCE)
- return mipi_csis_get_fmt(mipi_sd, cfg, sdformat);
+ return mipi_csis_get_fmt(sd, sd_state, sdformat);
if (sdformat->pad != CSIS_PAD_SINK)
return -EINVAL;
- fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
-
- mutex_lock(&state->lock);
-
- /* Validate the media bus code and clamp the size. */
- csis_fmt = find_csis_format(sdformat->format.code);
- if (!csis_fmt)
- csis_fmt = &mipi_csis_formats[0];
-
- fmt->code = csis_fmt->code;
- fmt->width = sdformat->format.width;
- fmt->height = sdformat->format.height;
-
/*
+ * Validate the media bus code and clamp and align the size.
+ *
* The total number of bits per line must be a multiple of 8. We thus
* need to align the width for formats that are not multiples of 8
* bits.
*/
+ csis_fmt = find_csis_format(sdformat->format.code);
+ if (!csis_fmt)
+ csis_fmt = &mipi_csis_formats[0];
+
switch (csis_fmt->width % 8) {
case 0:
align = 0;
@@ -923,13 +1027,24 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
break;
}
- v4l_bound_align_image(&fmt->width, 1, CSIS_MAX_PIX_WIDTH, align,
- &fmt->height, 1, CSIS_MAX_PIX_HEIGHT, 0, 0);
+ v4l_bound_align_image(&sdformat->format.width, 1,
+ CSIS_MAX_PIX_WIDTH, align,
+ &sdformat->format.height, 1,
+ CSIS_MAX_PIX_HEIGHT, 0, 0);
+
+ fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
+ sdformat->pad);
+
+ mutex_lock(&state->lock);
+
+ fmt->code = csis_fmt->code;
+ fmt->width = sdformat->format.width;
+ fmt->height = sdformat->format.height;
sdformat->format = *fmt;
/* Propagate the format from sink to source. */
- fmt = mipi_csis_get_format(state, cfg, sdformat->which,
+ fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
CSIS_PAD_SOURCE);
*fmt = sdformat->format;
@@ -942,55 +1057,23 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
return 0;
}
-static int mipi_csis_log_status(struct v4l2_subdev *mipi_sd)
+static int mipi_csis_log_status(struct v4l2_subdev *sd)
{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
mutex_lock(&state->lock);
mipi_csis_log_counters(state, true);
- if (state->debug && (state->flags & ST_POWERED))
+ if (state->debug && (state->state & ST_POWERED))
mipi_csis_dump_regs(state);
mutex_unlock(&state->lock);
return 0;
}
-static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
-{
- struct csi_state *state = dev_id;
- unsigned long flags;
- unsigned int i;
- u32 status;
-
- status = mipi_csis_read(state, MIPI_CSIS_INT_SRC);
-
- spin_lock_irqsave(&state->slock, flags);
-
- /* Update the event/error counters */
- if ((status & MIPI_CSIS_INT_SRC_ERRORS) || state->debug) {
- for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
- if (!(status & state->events[i].mask))
- continue;
- state->events[i].counter++;
- }
- }
- spin_unlock_irqrestore(&state->slock, flags);
-
- mipi_csis_write(state, MIPI_CSIS_INT_SRC, status);
-
- return IRQ_HANDLED;
-}
-
static const struct v4l2_subdev_core_ops mipi_csis_core_ops = {
.log_status = mipi_csis_log_status,
};
-static const struct media_entity_operations mipi_csis_entity_ops = {
- .link_setup = mipi_csis_link_setup,
- .link_validate = v4l2_subdev_link_validate,
- .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
-};
-
static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
.s_stream = mipi_csis_s_stream,
};
@@ -1008,31 +1091,61 @@ static const struct v4l2_subdev_ops mipi_csis_subdev_ops = {
.pad = &mipi_csis_pad_ops,
};
-static int mipi_csis_parse_dt(struct platform_device *pdev,
- struct csi_state *state)
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+static int mipi_csis_link_setup(struct media_entity *entity,
+ const struct media_pad *local_pad,
+ const struct media_pad *remote_pad, u32 flags)
{
- struct device_node *node = pdev->dev.of_node;
+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
+ struct v4l2_subdev *remote_sd;
- if (of_property_read_u32(node, "clock-frequency",
- &state->clk_frequency))
- state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+ dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name,
+ local_pad->entity->name);
- /* Get MIPI PHY resets */
- state->mrst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (IS_ERR(state->mrst))
- return PTR_ERR(state->mrst);
+ /* We only care about the link to the source. */
+ if (!(local_pad->flags & MEDIA_PAD_FL_SINK))
+ return 0;
+
+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+ if (flags & MEDIA_LNK_FL_ENABLED) {
+ if (state->src_sd)
+ return -EBUSY;
+
+ state->src_sd = remote_sd;
+ } else {
+ state->src_sd = NULL;
+ }
return 0;
}
-static int mipi_csis_pm_resume(struct device *dev, bool runtime);
+static const struct media_entity_operations mipi_csis_entity_ops = {
+ .link_setup = mipi_csis_link_setup,
+ .link_validate = v4l2_subdev_link_validate,
+ .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+};
+
+/* -----------------------------------------------------------------------------
+ * Async subdev notifier
+ */
+
+static struct csi_state *
+mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct csi_state, notifier);
+}
static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd)
{
struct csi_state *state = mipi_notifier_to_csis_state(notifier);
- struct media_pad *sink = &state->mipi_sd.entity.pads[CSIS_PAD_SINK];
+ struct media_pad *sink = &state->sd.entity.pads[CSIS_PAD_SINK];
return v4l2_create_fwnode_links_to_pad(sd, sink, 0);
}
@@ -1041,38 +1154,6 @@ static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
.bound = mipi_csis_notify_bound,
};
-static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
- struct platform_device *pdev,
- const struct v4l2_subdev_ops *ops)
-{
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
-
- v4l2_subdev_init(mipi_sd, ops);
- mipi_sd->owner = THIS_MODULE;
- snprintf(mipi_sd->name, sizeof(mipi_sd->name), "%s.%d",
- CSIS_SUBDEV_NAME, state->index);
-
- mipi_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- mipi_sd->ctrl_handler = NULL;
-
- mipi_sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
- mipi_sd->entity.ops = &mipi_csis_entity_ops;
-
- mipi_sd->dev = &pdev->dev;
-
- state->csis_fmt = &mipi_csis_formats[0];
- mipi_csis_init_cfg(mipi_sd, NULL);
-
- v4l2_set_subdevdata(mipi_sd, &pdev->dev);
-
- state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
- | MEDIA_PAD_FL_MUST_CONNECT;
- state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
- | MEDIA_PAD_FL_MUST_CONNECT;
- return media_entity_pads_init(&mipi_sd->entity, CSIS_PADS_NUM,
- state->pads);
-}
-
static int mipi_csis_async_register(struct csi_state *state)
{
struct v4l2_fwnode_endpoint vep = {
@@ -1080,6 +1161,7 @@ static int mipi_csis_async_register(struct csi_state *state)
};
struct v4l2_async_subdev *asd;
struct fwnode_handle *ep;
+ unsigned int i;
int ret;
v4l2_async_notifier_init(&state->notifier);
@@ -1093,6 +1175,15 @@ static int mipi_csis_async_register(struct csi_state *state)
if (ret)
goto err_parse;
+ for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
+ if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
+ dev_err(state->dev,
+ "data lanes reordering is not supported");
+ ret = -EINVAL;
+ goto err_parse;
+ }
+ }
+
state->bus = vep.bus.mipi_csi2;
dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
@@ -1109,12 +1200,11 @@ static int mipi_csis_async_register(struct csi_state *state)
state->notifier.ops = &mipi_csis_notify_ops;
- ret = v4l2_async_subdev_notifier_register(&state->mipi_sd,
- &state->notifier);
+ ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier);
if (ret)
return ret;
- return v4l2_async_register_subdev(&state->mipi_sd);
+ return v4l2_async_register_subdev(&state->sd);
err_parse:
fwnode_handle_put(ep);
@@ -1122,98 +1212,209 @@ err_parse:
return ret;
}
-static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
+/* -----------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
{
- struct csi_state *state = m->private;
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
+ int ret = 0;
- return mipi_csis_dump_regs(state);
+ mutex_lock(&state->lock);
+ if (state->state & ST_POWERED) {
+ mipi_csis_stop_stream(state);
+ ret = mipi_csis_phy_disable(state);
+ if (ret)
+ goto unlock;
+ mipi_csis_clk_disable(state);
+ state->state &= ~ST_POWERED;
+ if (!runtime)
+ state->state |= ST_SUSPENDED;
+ }
+
+unlock:
+ mutex_unlock(&state->lock);
+
+ return ret ? -EAGAIN : 0;
}
-DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
-static void mipi_csis_debugfs_init(struct csi_state *state)
+static int mipi_csis_pm_resume(struct device *dev, bool runtime)
{
- state->debugfs_root = debugfs_create_dir(dev_name(state->dev), NULL);
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
+ int ret = 0;
- debugfs_create_bool("debug_enable", 0600, state->debugfs_root,
- &state->debug);
- debugfs_create_file("dump_regs", 0600, state->debugfs_root, state,
- &mipi_csis_dump_regs_fops);
+ mutex_lock(&state->lock);
+ if (!runtime && !(state->state & ST_SUSPENDED))
+ goto unlock;
+
+ if (!(state->state & ST_POWERED)) {
+ ret = mipi_csis_phy_enable(state);
+ if (ret)
+ goto unlock;
+
+ state->state |= ST_POWERED;
+ mipi_csis_clk_enable(state);
+ }
+ if (state->state & ST_STREAMING)
+ mipi_csis_start_stream(state);
+
+ state->state &= ~ST_SUSPENDED;
+
+unlock:
+ mutex_unlock(&state->lock);
+
+ return ret ? -EAGAIN : 0;
}
-static void mipi_csis_debugfs_exit(struct csi_state *state)
+static int __maybe_unused mipi_csis_suspend(struct device *dev)
{
- debugfs_remove_recursive(state->debugfs_root);
+ return mipi_csis_pm_suspend(dev, false);
+}
+
+static int __maybe_unused mipi_csis_resume(struct device *dev)
+{
+ return mipi_csis_pm_resume(dev, false);
+}
+
+static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
+{
+ return mipi_csis_pm_suspend(dev, true);
+}
+
+static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
+{
+ return mipi_csis_pm_resume(dev, true);
+}
+
+static const struct dev_pm_ops mipi_csis_pm_ops = {
+ SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove & platform driver
+ */
+
+static int mipi_csis_subdev_init(struct csi_state *state)
+{
+ struct v4l2_subdev *sd = &state->sd;
+
+ v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
+ sd->owner = THIS_MODULE;
+ snprintf(sd->name, sizeof(sd->name), "%s.%d",
+ CSIS_SUBDEV_NAME, state->index);
+
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->ctrl_handler = NULL;
+
+ sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ sd->entity.ops = &mipi_csis_entity_ops;
+
+ sd->dev = state->dev;
+
+ state->csis_fmt = &mipi_csis_formats[0];
+ mipi_csis_init_cfg(sd, NULL);
+
+ state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+ | MEDIA_PAD_FL_MUST_CONNECT;
+ state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
+ | MEDIA_PAD_FL_MUST_CONNECT;
+ return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
+ state->pads);
+}
+
+static int mipi_csis_parse_dt(struct csi_state *state)
+{
+ struct device_node *node = state->dev->of_node;
+
+ if (of_property_read_u32(node, "clock-frequency",
+ &state->clk_frequency))
+ state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+
+ return 0;
}
static int mipi_csis_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct csi_state *state;
+ int irq;
int ret;
state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
+ mutex_init(&state->lock);
spin_lock_init(&state->slock);
- state->pdev = pdev;
state->dev = dev;
+ state->info = of_device_get_match_data(dev);
+
+ memcpy(state->events, mipi_csis_events, sizeof(state->events));
- ret = mipi_csis_parse_dt(pdev, state);
+ /* Parse DT properties. */
+ ret = mipi_csis_parse_dt(state);
if (ret < 0) {
dev_err(dev, "Failed to parse device tree: %d\n", ret);
return ret;
}
- ret = mipi_csis_phy_init(state);
- if (ret < 0)
- return ret;
-
- mipi_csis_phy_reset(state);
-
+ /* Acquire resources. */
state->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(state->regs))
return PTR_ERR(state->regs);
- state->irq = platform_get_irq(pdev, 0);
- if (state->irq < 0)
- return state->irq;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = mipi_csis_phy_init(state);
+ if (ret < 0)
+ return ret;
ret = mipi_csis_clk_get(state);
if (ret < 0)
return ret;
+ /* Reset PHY and enable the clocks. */
+ mipi_csis_phy_reset(state);
+
ret = mipi_csis_clk_enable(state);
if (ret < 0) {
dev_err(state->dev, "failed to enable clocks: %d\n", ret);
return ret;
}
- ret = devm_request_irq(dev, state->irq, mipi_csis_irq_handler,
- 0, dev_name(dev), state);
+ /* Now that the hardware is initialized, request the interrupt. */
+ ret = devm_request_irq(dev, irq, mipi_csis_irq_handler, 0,
+ dev_name(dev), state);
if (ret) {
dev_err(dev, "Interrupt request failed\n");
goto disable_clock;
}
- platform_set_drvdata(pdev, &state->mipi_sd);
-
- mutex_init(&state->lock);
- ret = mipi_csis_subdev_init(&state->mipi_sd, pdev,
- &mipi_csis_subdev_ops);
+ /* Initialize and register the subdev. */
+ ret = mipi_csis_subdev_init(state);
if (ret < 0)
goto disable_clock;
+ platform_set_drvdata(pdev, &state->sd);
+
ret = mipi_csis_async_register(state);
if (ret < 0) {
- dev_err(&pdev->dev, "async register failed: %d\n", ret);
+ dev_err(dev, "async register failed: %d\n", ret);
goto cleanup;
}
- memcpy(state->events, mipi_csis_events, sizeof(state->events));
-
+ /* Initialize debugfs. */
mipi_csis_debugfs_init(state);
+
+ /* Enable runtime PM. */
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev)) {
ret = mipi_csis_pm_resume(dev, true);
@@ -1221,7 +1422,7 @@ static int mipi_csis_probe(struct platform_device *pdev)
goto unregister_all;
}
- dev_info(&pdev->dev, "lanes: %d, freq: %u\n",
+ dev_info(dev, "lanes: %d, freq: %u\n",
state->bus.num_data_lanes, state->clk_frequency);
return 0;
@@ -1229,10 +1430,10 @@ static int mipi_csis_probe(struct platform_device *pdev)
unregister_all:
mipi_csis_debugfs_exit(state);
cleanup:
- media_entity_cleanup(&state->mipi_sd.entity);
+ media_entity_cleanup(&state->sd.entity);
v4l2_async_notifier_unregister(&state->notifier);
v4l2_async_notifier_cleanup(&state->notifier);
- v4l2_async_unregister_subdev(&state->mipi_sd);
+ v4l2_async_unregister_subdev(&state->sd);
disable_clock:
mipi_csis_clk_disable(state);
mutex_destroy(&state->lock);
@@ -1240,107 +1441,40 @@ disable_clock:
return ret;
}
-static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
-{
- struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev);
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
- int ret = 0;
-
- mutex_lock(&state->lock);
- if (state->flags & ST_POWERED) {
- mipi_csis_stop_stream(state);
- ret = regulator_disable(state->mipi_phy_regulator);
- if (ret)
- goto unlock;
- mipi_csis_clk_disable(state);
- state->flags &= ~ST_POWERED;
- if (!runtime)
- state->flags |= ST_SUSPENDED;
- }
-
-unlock:
- mutex_unlock(&state->lock);
-
- return ret ? -EAGAIN : 0;
-}
-
-static int mipi_csis_pm_resume(struct device *dev, bool runtime)
-{
- struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev);
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
- int ret = 0;
-
- mutex_lock(&state->lock);
- if (!runtime && !(state->flags & ST_SUSPENDED))
- goto unlock;
-
- if (!(state->flags & ST_POWERED)) {
- ret = regulator_enable(state->mipi_phy_regulator);
- if (ret)
- goto unlock;
-
- state->flags |= ST_POWERED;
- mipi_csis_clk_enable(state);
- }
- if (state->flags & ST_STREAMING)
- mipi_csis_start_stream(state);
-
- state->flags &= ~ST_SUSPENDED;
-
-unlock:
- mutex_unlock(&state->lock);
-
- return ret ? -EAGAIN : 0;
-}
-
-static int __maybe_unused mipi_csis_suspend(struct device *dev)
-{
- return mipi_csis_pm_suspend(dev, false);
-}
-
-static int __maybe_unused mipi_csis_resume(struct device *dev)
-{
- return mipi_csis_pm_resume(dev, false);
-}
-
-static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
-{
- return mipi_csis_pm_suspend(dev, true);
-}
-
-static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
-{
- return mipi_csis_pm_resume(dev, true);
-}
-
static int mipi_csis_remove(struct platform_device *pdev)
{
- struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev);
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
mipi_csis_debugfs_exit(state);
v4l2_async_notifier_unregister(&state->notifier);
v4l2_async_notifier_cleanup(&state->notifier);
- v4l2_async_unregister_subdev(&state->mipi_sd);
+ v4l2_async_unregister_subdev(&state->sd);
pm_runtime_disable(&pdev->dev);
mipi_csis_pm_suspend(&pdev->dev, true);
mipi_csis_clk_disable(state);
- media_entity_cleanup(&state->mipi_sd.entity);
+ media_entity_cleanup(&state->sd.entity);
mutex_destroy(&state->lock);
pm_runtime_set_suspended(&pdev->dev);
return 0;
}
-static const struct dev_pm_ops mipi_csis_pm_ops = {
- SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
- NULL)
- SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
-};
-
static const struct of_device_id mipi_csis_of_match[] = {
- { .compatible = "fsl,imx7-mipi-csi2", },
+ {
+ .compatible = "fsl,imx7-mipi-csi2",
+ .data = &(const struct mipi_csis_info){
+ .version = MIPI_CSIS_V3_3,
+ .num_clocks = 3,
+ },
+ }, {
+ .compatible = "fsl,imx8mm-mipi-csi2",
+ .data = &(const struct mipi_csis_info){
+ .version = MIPI_CSIS_V3_6_3,
+ .num_clocks = 4,
+ },
+ },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
@@ -1357,6 +1491,6 @@ static struct platform_driver mipi_csis_driver = {
module_platform_driver(mipi_csis_driver);
-MODULE_DESCRIPTION("i.MX7 MIPI CSI-2 Receiver driver");
+MODULE_DESCRIPTION("i.MX7 & i.MX8 MIPI CSI-2 receiver driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:imx7-mipi-csi2");
diff --git a/drivers/staging/media/ipu3/include/intel-ipu3.h b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h
index 9b644fb23dde..fa3d6ee5adf2 100644
--- a/drivers/staging/media/ipu3/include/intel-ipu3.h
+++ b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h
@@ -9,8 +9,10 @@
/* from /drivers/staging/media/ipu3/include/videodev2.h */
/* Vendor specific - used for IPU3 camera sub-system */
-#define V4L2_META_FMT_IPU3_PARAMS v4l2_fourcc('i', 'p', '3', 'p') /* IPU3 processing parameters */
-#define V4L2_META_FMT_IPU3_STAT_3A v4l2_fourcc('i', 'p', '3', 's') /* IPU3 3A statistics */
+/* IPU3 processing parameters */
+#define V4L2_META_FMT_IPU3_PARAMS v4l2_fourcc('i', 'p', '3', 'p')
+/* IPU3 3A statistics */
+#define V4L2_META_FMT_IPU3_STAT_3A v4l2_fourcc('i', 'p', '3', 's')
/* from include/uapi/linux/v4l2-controls.h */
#define V4L2_CID_INTEL_IPU3_BASE (V4L2_CID_USER_BASE + 0x10c0)
@@ -74,7 +76,6 @@ struct ipu3_uapi_grid_config {
(IPU3_UAPI_AWB_MAX_SETS * \
(IPU3_UAPI_AWB_SET_SIZE + IPU3_UAPI_AWB_SPARE_FOR_BUBBLES))
-
/**
* struct ipu3_uapi_awb_raw_buffer - AWB raw buffer
*
@@ -244,8 +245,8 @@ struct ipu3_uapi_ae_ccm {
*/
struct ipu3_uapi_ae_config {
struct ipu3_uapi_ae_grid_config grid_cfg __attribute__((aligned(32)));
- struct ipu3_uapi_ae_weight_elem weights[
- IPU3_UAPI_AE_WEIGHTS] __attribute__((aligned(32)));
+ struct ipu3_uapi_ae_weight_elem weights[IPU3_UAPI_AE_WEIGHTS]
+ __attribute__((aligned(32)));
struct ipu3_uapi_ae_ccm ae_ccm __attribute__((aligned(32)));
} __packed;
@@ -630,7 +631,7 @@ struct ipu3_uapi_bnr_static_config_wb_gains_thr_config {
* @cg: Gain coefficient for threshold calculation, [0, 31], default 8.
* @ci: Intensity coefficient for threshold calculation. range [0, 0x1f]
* default 6.
- * format: u3.2 (3 most significant bits represent whole number,
+ * format: u3.2 (3 most significant bits represent whole number,
* 2 least significant bits represent the fractional part
* with each count representing 0.25)
* e.g. 6 in binary format is 00110, that translates to 1.5
diff --git a/drivers/staging/media/ipu3/ipu3-abi.h b/drivers/staging/media/ipu3/ipu3-abi.h
index e1185602c7fd..c76935b436d7 100644
--- a/drivers/staging/media/ipu3/ipu3-abi.h
+++ b/drivers/staging/media/ipu3/ipu3-abi.h
@@ -4,7 +4,7 @@
#ifndef __IPU3_ABI_H
#define __IPU3_ABI_H
-#include "include/intel-ipu3.h"
+#include "include/uapi/intel-ipu3.h"
/******************* IMGU Hardware information *******************/
diff --git a/drivers/staging/media/ipu3/ipu3-css-pool.h b/drivers/staging/media/ipu3/ipu3-css-pool.h
index 35519a08c08c..3f9e32e0e9a7 100644
--- a/drivers/staging/media/ipu3/ipu3-css-pool.h
+++ b/drivers/staging/media/ipu3/ipu3-css-pool.h
@@ -15,6 +15,7 @@ struct imgu_device;
* @size: size of the buffer in bytes.
* @vaddr: kernel virtual address.
* @daddr: iova dma address to access IPU3.
+ * @pages: pages mapped to this buffer
*/
struct imgu_css_map {
size_t size;
diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c
index 6d9c49b39531..38a240764509 100644
--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
+++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
@@ -36,7 +36,7 @@ static int imgu_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
/* Initialize try_fmt */
for (i = 0; i < IMGU_NODE_NUM; i++) {
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->pad, i);
+ v4l2_subdev_get_try_format(sd, fh->state, i);
try_fmt->width = try_crop.width;
try_fmt->height = try_crop.height;
@@ -44,8 +44,8 @@ static int imgu_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->field = V4L2_FIELD_NONE;
}
- *v4l2_subdev_get_try_crop(sd, fh->pad, IMGU_NODE_IN) = try_crop;
- *v4l2_subdev_get_try_compose(sd, fh->pad, IMGU_NODE_IN) = try_crop;
+ *v4l2_subdev_get_try_crop(sd, fh->state, IMGU_NODE_IN) = try_crop;
+ *v4l2_subdev_get_try_compose(sd, fh->state, IMGU_NODE_IN) = try_crop;
return 0;
}
@@ -120,7 +120,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable)
}
static int imgu_subdev_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct imgu_device *imgu = v4l2_get_subdevdata(sd);
@@ -136,7 +136,7 @@ static int imgu_subdev_get_fmt(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
fmt->format = imgu_pipe->nodes[pad].pad_fmt;
} else {
- mf = v4l2_subdev_get_try_format(sd, cfg, pad);
+ mf = v4l2_subdev_get_try_format(sd, sd_state, pad);
fmt->format = *mf;
}
@@ -144,7 +144,7 @@ static int imgu_subdev_get_fmt(struct v4l2_subdev *sd,
}
static int imgu_subdev_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct imgu_media_pipe *imgu_pipe;
@@ -161,7 +161,7 @@ static int imgu_subdev_set_fmt(struct v4l2_subdev *sd,
imgu_pipe = &imgu->imgu_pipe[pipe];
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- mf = v4l2_subdev_get_try_format(sd, cfg, pad);
+ mf = v4l2_subdev_get_try_format(sd, sd_state, pad);
else
mf = &imgu_pipe->nodes[pad].pad_fmt;
@@ -189,7 +189,7 @@ static int imgu_subdev_set_fmt(struct v4l2_subdev *sd,
}
static int imgu_subdev_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct v4l2_rect *try_sel, *r;
@@ -202,11 +202,11 @@ static int imgu_subdev_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
- try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
+ try_sel = v4l2_subdev_get_try_crop(sd, sd_state, sel->pad);
r = &imgu_sd->rect.eff;
break;
case V4L2_SEL_TGT_COMPOSE:
- try_sel = v4l2_subdev_get_try_compose(sd, cfg, sel->pad);
+ try_sel = v4l2_subdev_get_try_compose(sd, sd_state, sel->pad);
r = &imgu_sd->rect.bds;
break;
default:
@@ -222,7 +222,7 @@ static int imgu_subdev_get_selection(struct v4l2_subdev *sd,
}
static int imgu_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct imgu_device *imgu = v4l2_get_subdevdata(sd);
@@ -241,11 +241,11 @@ static int imgu_subdev_set_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
- try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
+ try_sel = v4l2_subdev_get_try_crop(sd, sd_state, sel->pad);
rect = &imgu_sd->rect.eff;
break;
case V4L2_SEL_TGT_COMPOSE:
- try_sel = v4l2_subdev_get_try_compose(sd, cfg, sel->pad);
+ try_sel = v4l2_subdev_get_try_compose(sd, sd_state, sel->pad);
rect = &imgu_sd->rect.bds;
break;
default:
diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c
index ee1bba6bdcac..8e1e9e46e604 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -392,10 +392,9 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
}
/* Set Power */
- r = pm_runtime_get_sync(dev);
+ r = pm_runtime_resume_and_get(dev);
if (r < 0) {
dev_err(dev, "failed to set imgu power\n");
- pm_runtime_put(dev);
return r;
}
diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c
index 7f07a9175815..b9125c295d1d 100644
--- a/drivers/staging/media/meson/vdec/vdec_helpers.c
+++ b/drivers/staging/media/meson/vdec/vdec_helpers.c
@@ -183,7 +183,7 @@ int amvdec_set_canvases(struct amvdec_session *sess,
u32 pixfmt = sess->pixfmt_cap;
u32 width = ALIGN(sess->width, 32);
u32 height = ALIGN(sess->height, 32);
- u32 reg_cur = reg_base[0];
+ u32 reg_cur;
u32 reg_num_cur = 0;
u32 reg_base_cur = 0;
int i = 0;
diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h
index b88f9529683c..3f587e000729 100644
--- a/drivers/staging/media/omap4iss/iss.h
+++ b/drivers/staging/media/omap4iss/iss.h
@@ -119,9 +119,6 @@ struct iss_device {
unsigned int isp_subclk_resources;
};
-#define v4l2_dev_to_iss_device(dev) \
- container_of(dev, struct iss_device, v4l2_dev)
-
int omap4iss_get_external_info(struct iss_pipeline *pipe,
struct media_link *link);
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index a6dc2d2b1228..124ab2f44fbf 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -825,19 +825,20 @@ static const struct iss_video_operations csi2_issvideo_ops = {
static struct v4l2_mbus_framefmt *
__csi2_get_format(struct iss_csi2_device *csi2,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csi2->subdev, cfg, pad);
+ return v4l2_subdev_get_try_format(&csi2->subdev, sd_state,
+ pad);
return &csi2->formats[pad];
}
static void
csi2_try_format(struct iss_csi2_device *csi2,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
@@ -868,7 +869,8 @@ csi2_try_format(struct iss_csi2_device *csi2,
* compression.
*/
pixelcode = fmt->code;
- format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, which);
+ format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK,
+ which);
memcpy(fmt, format, sizeof(*fmt));
/*
@@ -894,7 +896,7 @@ csi2_try_format(struct iss_csi2_device *csi2,
* return -EINVAL or zero on success
*/
static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -907,7 +909,7 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
code->code = csi2_input_fmts[code->index];
} else {
- format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK,
+ format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK,
code->which);
switch (code->index) {
case 0:
@@ -931,7 +933,7 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
}
static int csi2_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -943,7 +945,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = 1;
format.height = 1;
- csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
+ csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which);
fse->min_width = format.width;
fse->min_height = format.height;
@@ -953,7 +955,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = -1;
format.height = -1;
- csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
+ csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which);
fse->max_width = format.width;
fse->max_height = format.height;
@@ -968,13 +970,13 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
* return -EINVAL or zero on success
*/
static int csi2_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
+ format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
@@ -990,25 +992,26 @@ static int csi2_get_format(struct v4l2_subdev *sd,
* return -EINVAL or zero on success
*/
static int csi2_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
+ format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
- csi2_try_format(csi2, cfg, fmt->pad, &fmt->format, fmt->which);
+ csi2_try_format(csi2, sd_state, fmt->pad, &fmt->format, fmt->which);
*format = fmt->format;
/* Propagate the format from sink to source */
if (fmt->pad == CSI2_PAD_SINK) {
- format = __csi2_get_format(csi2, cfg, CSI2_PAD_SOURCE,
+ format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SOURCE,
fmt->which);
*format = fmt->format;
- csi2_try_format(csi2, cfg, CSI2_PAD_SOURCE, format, fmt->which);
+ csi2_try_format(csi2, sd_state, CSI2_PAD_SOURCE, format,
+ fmt->which);
}
return 0;
@@ -1050,7 +1053,7 @@ static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
- csi2_set_format(sd, fh ? fh->pad : NULL, &format);
+ csi2_set_format(sd, fh ? fh->state : NULL, &format);
return 0;
}
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c
index 26be078b69f3..23f707cb336f 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.c
+++ b/drivers/staging/media/omap4iss/iss_ipipe.c
@@ -21,7 +21,7 @@
static struct v4l2_mbus_framefmt *
__ipipe_get_format(struct iss_ipipe_device *ipipe,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which);
@@ -175,12 +175,13 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
static struct v4l2_mbus_framefmt *
__ipipe_get_format(struct iss_ipipe_device *ipipe,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad);
+ return v4l2_subdev_get_try_format(&ipipe->subdev, sd_state,
+ pad);
return &ipipe->formats[pad];
}
@@ -194,7 +195,7 @@ __ipipe_get_format(struct iss_ipipe_device *ipipe,
*/
static void
ipipe_try_format(struct iss_ipipe_device *ipipe,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
@@ -222,7 +223,8 @@ ipipe_try_format(struct iss_ipipe_device *ipipe,
break;
case IPIPE_PAD_SOURCE_VP:
- format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SINK, which);
+ format = __ipipe_get_format(ipipe, sd_state, IPIPE_PAD_SINK,
+ which);
memcpy(fmt, format, sizeof(*fmt));
fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
@@ -243,7 +245,7 @@ ipipe_try_format(struct iss_ipipe_device *ipipe,
* return -EINVAL or zero on success
*/
static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
switch (code->pad) {
@@ -270,7 +272,7 @@ static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
@@ -282,7 +284,7 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = 1;
format.height = 1;
- ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
+ ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which);
fse->min_width = format.width;
fse->min_height = format.height;
@@ -292,7 +294,7 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = -1;
format.height = -1;
- ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
+ ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which);
fse->max_width = format.width;
fse->max_height = format.height;
@@ -309,13 +311,13 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
* to the format type.
*/
static int ipipe_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
+ format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
@@ -333,25 +335,26 @@ static int ipipe_get_format(struct v4l2_subdev *sd,
* to the format type.
*/
static int ipipe_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
+ format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
- ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which);
+ ipipe_try_format(ipipe, sd_state, fmt->pad, &fmt->format, fmt->which);
*format = fmt->format;
/* Propagate the format from sink to source */
if (fmt->pad == IPIPE_PAD_SINK) {
- format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP,
+ format = __ipipe_get_format(ipipe, sd_state,
+ IPIPE_PAD_SOURCE_VP,
fmt->which);
*format = fmt->format;
- ipipe_try_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP, format,
+ ipipe_try_format(ipipe, sd_state, IPIPE_PAD_SOURCE_VP, format,
fmt->which);
}
@@ -392,7 +395,7 @@ static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
- ipipe_set_format(sd, fh ? fh->pad : NULL, &format);
+ ipipe_set_format(sd, fh ? fh->state : NULL, &format);
return 0;
}
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index c2978d02e797..5e7f25cd53ac 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -357,11 +357,12 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
static struct v4l2_mbus_framefmt *
__ipipeif_get_format(struct iss_ipipeif_device *ipipeif,
- struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+ struct v4l2_subdev_state *sd_state, unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad);
+ return v4l2_subdev_get_try_format(&ipipeif->subdev, sd_state,
+ pad);
return &ipipeif->formats[pad];
}
@@ -374,7 +375,7 @@ __ipipeif_get_format(struct iss_ipipeif_device *ipipeif,
*/
static void
ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
- struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+ struct v4l2_subdev_state *sd_state, unsigned int pad,
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
{
@@ -403,7 +404,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
break;
case IPIPEIF_PAD_SOURCE_ISIF_SF:
- format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
+ format = __ipipeif_get_format(ipipeif, sd_state,
+ IPIPEIF_PAD_SINK,
which);
memcpy(fmt, format, sizeof(*fmt));
@@ -418,7 +420,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
break;
case IPIPEIF_PAD_SOURCE_VP:
- format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
+ format = __ipipeif_get_format(ipipeif, sd_state,
+ IPIPEIF_PAD_SINK,
which);
memcpy(fmt, format, sizeof(*fmt));
@@ -442,7 +445,7 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
* return -EINVAL or zero on success
*/
static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -462,7 +465,8 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index != 0)
return -EINVAL;
- format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
+ format = __ipipeif_get_format(ipipeif, sd_state,
+ IPIPEIF_PAD_SINK,
code->which);
code->code = format->code;
@@ -476,7 +480,7 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -488,7 +492,7 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = 1;
format.height = 1;
- ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
+ ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which);
fse->min_width = format.width;
fse->min_height = format.height;
@@ -498,7 +502,7 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = -1;
format.height = -1;
- ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
+ ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which);
fse->max_width = format.width;
fse->max_height = format.height;
@@ -515,13 +519,13 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
* to the format type.
*/
static int ipipeif_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
+ format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
@@ -539,33 +543,36 @@ static int ipipeif_get_format(struct v4l2_subdev *sd,
* to the format type.
*/
static int ipipeif_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
+ format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
- ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which);
+ ipipeif_try_format(ipipeif, sd_state, fmt->pad, &fmt->format,
+ fmt->which);
*format = fmt->format;
/* Propagate the format from sink to source */
if (fmt->pad == IPIPEIF_PAD_SINK) {
- format = __ipipeif_get_format(ipipeif, cfg,
+ format = __ipipeif_get_format(ipipeif, sd_state,
IPIPEIF_PAD_SOURCE_ISIF_SF,
fmt->which);
*format = fmt->format;
- ipipeif_try_format(ipipeif, cfg, IPIPEIF_PAD_SOURCE_ISIF_SF,
+ ipipeif_try_format(ipipeif, sd_state,
+ IPIPEIF_PAD_SOURCE_ISIF_SF,
format, fmt->which);
- format = __ipipeif_get_format(ipipeif, cfg,
+ format = __ipipeif_get_format(ipipeif, sd_state,
IPIPEIF_PAD_SOURCE_VP,
fmt->which);
*format = fmt->format;
- ipipeif_try_format(ipipeif, cfg, IPIPEIF_PAD_SOURCE_VP, format,
+ ipipeif_try_format(ipipeif, sd_state, IPIPEIF_PAD_SOURCE_VP,
+ format,
fmt->which);
}
@@ -608,7 +615,7 @@ static int ipipeif_init_formats(struct v4l2_subdev *sd,
format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
- ipipeif_set_format(sd, fh ? fh->pad : NULL, &format);
+ ipipeif_set_format(sd, fh ? fh->state : NULL, &format);
return 0;
}
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index 3b6875cbca9b..a5f8f9f1ab16 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -416,11 +416,12 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
static struct v4l2_mbus_framefmt *
__resizer_get_format(struct iss_resizer_device *resizer,
- struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+ struct v4l2_subdev_state *sd_state, unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&resizer->subdev, cfg, pad);
+ return v4l2_subdev_get_try_format(&resizer->subdev, sd_state,
+ pad);
return &resizer->formats[pad];
}
@@ -433,7 +434,7 @@ __resizer_get_format(struct iss_resizer_device *resizer,
*/
static void
resizer_try_format(struct iss_resizer_device *resizer,
- struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+ struct v4l2_subdev_state *sd_state, unsigned int pad,
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
{
@@ -461,7 +462,8 @@ resizer_try_format(struct iss_resizer_device *resizer,
case RESIZER_PAD_SOURCE_MEM:
pixelcode = fmt->code;
- format = __resizer_get_format(resizer, cfg, RESIZER_PAD_SINK,
+ format = __resizer_get_format(resizer, sd_state,
+ RESIZER_PAD_SINK,
which);
memcpy(fmt, format, sizeof(*fmt));
@@ -492,7 +494,7 @@ resizer_try_format(struct iss_resizer_device *resizer,
* return -EINVAL or zero on success
*/
static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
@@ -507,7 +509,8 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
break;
case RESIZER_PAD_SOURCE_MEM:
- format = __resizer_get_format(resizer, cfg, RESIZER_PAD_SINK,
+ format = __resizer_get_format(resizer, sd_state,
+ RESIZER_PAD_SINK,
code->which);
if (code->index == 0) {
@@ -537,7 +540,7 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
}
static int resizer_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
@@ -549,7 +552,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = 1;
format.height = 1;
- resizer_try_format(resizer, cfg, fse->pad, &format, fse->which);
+ resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which);
fse->min_width = format.width;
fse->min_height = format.height;
@@ -559,7 +562,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
format.code = fse->code;
format.width = -1;
format.height = -1;
- resizer_try_format(resizer, cfg, fse->pad, &format, fse->which);
+ resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which);
fse->max_width = format.width;
fse->max_height = format.height;
@@ -576,13 +579,13 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
* to the format type.
*/
static int resizer_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
+ format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
@@ -600,26 +603,28 @@ static int resizer_get_format(struct v4l2_subdev *sd,
* to the format type.
*/
static int resizer_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
- format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
+ format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which);
if (!format)
return -EINVAL;
- resizer_try_format(resizer, cfg, fmt->pad, &fmt->format, fmt->which);
+ resizer_try_format(resizer, sd_state, fmt->pad, &fmt->format,
+ fmt->which);
*format = fmt->format;
/* Propagate the format from sink to source */
if (fmt->pad == RESIZER_PAD_SINK) {
- format = __resizer_get_format(resizer, cfg,
+ format = __resizer_get_format(resizer, sd_state,
RESIZER_PAD_SOURCE_MEM,
fmt->which);
*format = fmt->format;
- resizer_try_format(resizer, cfg, RESIZER_PAD_SOURCE_MEM, format,
+ resizer_try_format(resizer, sd_state, RESIZER_PAD_SOURCE_MEM,
+ format,
fmt->which);
}
@@ -662,7 +667,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
format.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
format.format.width = 4096;
format.format.height = 4096;
- resizer_set_format(sd, fh ? fh->pad : NULL, &format);
+ resizer_set_format(sd, fh ? fh->state : NULL, &format);
return 0;
}
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index 930f638f51eb..d0da083deed5 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -399,7 +399,7 @@ static void iss_video_buf_queue(struct vb2_buffer *vb)
if (start)
omap4iss_pipeline_set_stream(pipe,
- ISS_PIPELINE_STREAM_SINGLESHOT);
+ ISS_PIPELINE_STREAM_SINGLESHOT);
}
}
@@ -960,7 +960,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
unsigned long flags;
ret = omap4iss_pipeline_set_stream(pipe,
- ISS_PIPELINE_STREAM_CONTINUOUS);
+ ISS_PIPELINE_STREAM_CONTINUOUS);
if (ret < 0)
goto err_omap4iss_set_stream;
spin_lock_irqsave(&video->qlock, flags);
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index d821661d30f3..7131156c1f2c 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -481,7 +481,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, i) < sizeimage)
return -EINVAL;
}
- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+
+ /*
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
+ * it to buffer length).
+ */
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
+ vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+
return 0;
}
@@ -658,7 +666,7 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
- ret = pm_runtime_get_sync(rkvdec->dev);
+ ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
return;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index 92812d1a39d4..c0d005dafc6c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -31,13 +31,19 @@
static const struct cedrus_control cedrus_controls[] = {
{
.cfg = {
- .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
},
.codec = CEDRUS_CODEC_MPEG2,
},
{
.cfg = {
- .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .id = V4L2_CID_STATELESS_MPEG2_PICTURE,
+ },
+ .codec = CEDRUS_CODEC_MPEG2,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
},
.codec = CEDRUS_CODEC_MPEG2,
},
@@ -151,6 +157,12 @@ static const struct cedrus_control cedrus_controls[] = {
},
.codec = CEDRUS_CODEC_VP8,
},
+ {
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS,
+ },
+ .codec = CEDRUS_CODEC_H265,
+ },
};
#define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 15f147dad4cb..88afba17b78b 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -68,14 +68,16 @@ struct cedrus_h264_run {
};
struct cedrus_mpeg2_run {
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
- const struct v4l2_ctrl_mpeg2_quantization *quantization;
+ const struct v4l2_ctrl_mpeg2_sequence *sequence;
+ const struct v4l2_ctrl_mpeg2_picture *picture;
+ const struct v4l2_ctrl_mpeg2_quantisation *quantisation;
};
struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params *slice_params;
+ const struct v4l2_ctrl_hevc_decode_params *decode_params;
};
struct cedrus_vp8_run {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index d696b3ec70c0..40e8c4123f76 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -40,10 +40,12 @@ void cedrus_device_run(void *priv)
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_MPEG2_SLICE:
- run.mpeg2.slice_params = cedrus_find_control_data(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
- run.mpeg2.quantization = cedrus_find_control_data(ctx,
- V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
+ run.mpeg2.sequence = cedrus_find_control_data(ctx,
+ V4L2_CID_STATELESS_MPEG2_SEQUENCE);
+ run.mpeg2.picture = cedrus_find_control_data(ctx,
+ V4L2_CID_STATELESS_MPEG2_PICTURE);
+ run.mpeg2.quantisation = cedrus_find_control_data(ctx,
+ V4L2_CID_STATELESS_MPEG2_QUANTISATION);
break;
case V4L2_PIX_FMT_H264_SLICE:
@@ -68,6 +70,8 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
run.h265.slice_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
+ run.h265.decode_params = cedrus_find_control_data(ctx,
+ V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS);
break;
case V4L2_PIX_FMT_VP8_FRAME:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index ce497d0197df..6821e3d05d34 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -245,6 +245,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params *slice_params;
+ const struct v4l2_ctrl_hevc_decode_params *decode_params;
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
dma_addr_t src_buf_addr;
dma_addr_t src_buf_end_addr;
@@ -256,6 +257,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
sps = run->h265.sps;
pps = run->h265.pps;
slice_params = run->h265.slice_params;
+ decode_params = run->h265.decode_params;
pred_weight_table = &slice_params->pred_weight_table;
/* MV column buffer size and allocation. */
@@ -477,8 +479,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
slice_params->flags);
reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
- V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
- pps->flags);
+ V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
+ slice_params->flags);
/* FIXME: For multi-slice support. */
reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
@@ -487,7 +489,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) |
VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) |
- VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(slice_params->num_rps_poc_st_curr_after == 0) |
+ VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(decode_params->num_poc_st_curr_after == 0) |
VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) |
VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) |
VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta);
@@ -527,8 +529,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
/* Write decoded picture buffer in pic list. */
- cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
- slice_params->num_active_dpb_entries);
+ cedrus_h265_frame_info_write_dpb(ctx, decode_params->dpb,
+ decode_params->num_active_dpb_entries);
/* Output frame. */
@@ -545,7 +547,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
/* Reference picture list 0 (for P/B frames). */
if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
- cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
+ cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
slice_params->ref_idx_l0,
slice_params->num_ref_idx_l0_active_minus1 + 1,
VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
@@ -564,7 +566,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
/* Reference picture list 1 (for B frames). */
if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
- cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
+ cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
slice_params->ref_idx_l1,
slice_params->num_ref_idx_l1_active_minus1 + 1,
VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
index 8bcd6b8f9e2d..5dad2f296c6d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
@@ -13,30 +13,6 @@
#include "cedrus_hw.h"
#include "cedrus_regs.h"
-/* Default MPEG-2 quantization coefficients, from the specification. */
-
-static const u8 intra_quantization_matrix_default[64] = {
- 8, 16, 16, 19, 16, 19, 22, 22,
- 22, 22, 22, 22, 26, 24, 26, 27,
- 27, 27, 26, 26, 26, 26, 27, 27,
- 27, 29, 29, 29, 34, 34, 34, 29,
- 29, 29, 27, 27, 29, 29, 32, 32,
- 34, 34, 37, 38, 37, 35, 35, 34,
- 35, 38, 38, 40, 40, 40, 48, 48,
- 46, 46, 56, 56, 58, 69, 69, 83
-};
-
-static const u8 non_intra_quantization_matrix_default[64] = {
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16
-};
-
static enum cedrus_irq_status cedrus_mpeg2_irq_status(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
@@ -74,10 +50,9 @@ static void cedrus_mpeg2_irq_disable(struct cedrus_ctx *ctx)
static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
{
- const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
- const struct v4l2_mpeg2_sequence *sequence;
- const struct v4l2_mpeg2_picture *picture;
- const struct v4l2_ctrl_mpeg2_quantization *quantization;
+ const struct v4l2_ctrl_mpeg2_sequence *seq;
+ const struct v4l2_ctrl_mpeg2_picture *pic;
+ const struct v4l2_ctrl_mpeg2_quantisation *quantisation;
dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr;
dma_addr_t fwd_luma_addr, fwd_chroma_addr;
dma_addr_t bwd_luma_addr, bwd_chroma_addr;
@@ -89,22 +64,16 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
unsigned int i;
u32 reg;
- slice_params = run->mpeg2.slice_params;
- sequence = &slice_params->sequence;
- picture = &slice_params->picture;
+ seq = run->mpeg2.sequence;
+ pic = run->mpeg2.picture;
- quantization = run->mpeg2.quantization;
+ quantisation = run->mpeg2.quantisation;
/* Activate MPEG engine. */
cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2);
- /* Set intra quantization matrix. */
-
- if (quantization && quantization->load_intra_quantiser_matrix)
- matrix = quantization->intra_quantiser_matrix;
- else
- matrix = intra_quantization_matrix_default;
-
+ /* Set intra quantisation matrix. */
+ matrix = quantisation->intra_quantiser_matrix;
for (i = 0; i < 64; i++) {
reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
reg |= VE_DEC_MPEG_IQMINPUT_FLAG_INTRA;
@@ -112,13 +81,8 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg);
}
- /* Set non-intra quantization matrix. */
-
- if (quantization && quantization->load_non_intra_quantiser_matrix)
- matrix = quantization->non_intra_quantiser_matrix;
- else
- matrix = non_intra_quantization_matrix_default;
-
+ /* Set non-intra quantisation matrix. */
+ matrix = quantisation->non_intra_quantiser_matrix;
for (i = 0; i < 64; i++) {
reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
reg |= VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA;
@@ -128,19 +92,19 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
/* Set MPEG picture header. */
- reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(picture->picture_coding_type);
- reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, picture->f_code[0][0]);
- reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, picture->f_code[0][1]);
- reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, picture->f_code[1][0]);
- reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, picture->f_code[1][1]);
- reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(picture->intra_dc_precision);
- reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(picture->picture_structure);
- reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(picture->top_field_first);
- reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(picture->frame_pred_frame_dct);
- reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(picture->concealment_motion_vectors);
- reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(picture->q_scale_type);
- reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(picture->intra_vlc_format);
- reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(picture->alternate_scan);
+ reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(pic->picture_coding_type);
+ reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, pic->f_code[0][0]);
+ reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, pic->f_code[0][1]);
+ reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, pic->f_code[1][0]);
+ reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, pic->f_code[1][1]);
+ reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(pic->intra_dc_precision);
+ reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(pic->picture_structure);
+ reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
+ reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
+ reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV);
+ reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE);
+ reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC);
+ reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN);
reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(0);
reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(0);
@@ -148,8 +112,8 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
/* Set frame dimensions. */
- reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(sequence->horizontal_size);
- reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(sequence->vertical_size);
+ reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(seq->horizontal_size);
+ reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(seq->vertical_size);
cedrus_write(dev, VE_DEC_MPEG_PICCODEDSIZE, reg);
@@ -162,14 +126,14 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- forward_idx = vb2_find_timestamp(vq, slice_params->forward_ref_ts, 0);
+ forward_idx = vb2_find_timestamp(vq, pic->forward_ref_ts, 0);
fwd_luma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 0);
fwd_chroma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 1);
cedrus_write(dev, VE_DEC_MPEG_FWD_REF_LUMA_ADDR, fwd_luma_addr);
cedrus_write(dev, VE_DEC_MPEG_FWD_REF_CHROMA_ADDR, fwd_chroma_addr);
- backward_idx = vb2_find_timestamp(vq, slice_params->backward_ref_ts, 0);
+ backward_idx = vb2_find_timestamp(vq, pic->backward_ref_ts, 0);
bwd_luma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 0);
bwd_chroma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 1);
@@ -186,10 +150,9 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
/* Source offset and length in bits. */
- cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET,
- slice_params->data_bit_offset);
+ cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET, 0);
- reg = slice_params->bit_size - slice_params->data_bit_offset;
+ reg = vb2_get_plane_payload(&run->src->vb2_buf, 0) * 8;
cedrus_write(dev, VE_DEC_MPEG_VLD_LEN, reg);
/* Source beginning and end addresses. */
@@ -203,7 +166,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
cedrus_write(dev, VE_DEC_MPEG_VLD_ADDR, reg);
- reg = src_buf_addr + DIV_ROUND_UP(slice_params->bit_size, 8);
+ reg = src_buf_addr + vb2_get_plane_payload(&run->src->vb2_buf, 0);
cedrus_write(dev, VE_DEC_MPEG_VLD_END_ADDR, reg);
/* Macroblock address: start at the beginning. */
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b62eb8e84057..32c13ecb22d8 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -457,7 +457,13 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
return -EINVAL;
- vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
+ /*
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
+ * it to buffer length).
+ */
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
+ vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
return 0;
}
@@ -490,11 +496,9 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
}
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(dev->dev);
+ ret = pm_runtime_resume_and_get(dev->dev);
+ if (ret < 0)
goto err_cleanup;
- }
if (dev->dec_ops[ctx->current_codec]->start) {
ret = dev->dec_ops[ctx->current_codec]->start(ctx);
diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..ed4c1250b303 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
if (ret)
goto release_dpb_frames;
- ret = pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- goto put_runtime_pm;
+ goto unlock;
/*
* We rely on the VDE registers reset value, otherwise VDE
@@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
put_runtime_pm:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
+unlock:
mutex_unlock(&vde->lock);
release_dpb_frames:
@@ -1069,11 +1071,20 @@ static int tegra_vde_probe(struct platform_device *pdev)
* power-cycle it in order to put hardware into a predictable lower
* power state.
*/
- pm_runtime_get_sync(dev);
+ err = pm_runtime_resume_and_get(dev);
+ if (err)
+ goto err_pm_runtime;
+
pm_runtime_put(dev);
return 0;
+err_pm_runtime:
+ misc_deregister(&vde->miscdev);
+
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+
err_deinit_iommu:
tegra_vde_iommu_deinit(vde);
@@ -1089,7 +1100,12 @@ static int tegra_vde_remove(struct platform_device *pdev)
struct tegra_vde *vde = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
+ /*
+ * As it increments RPM usage_count even on errors, we don't need to
+ * check the returned code here.
+ */
pm_runtime_get_sync(dev);
+
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 033a6935c26d..b26e44adb2be 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -64,7 +64,7 @@ static const struct v4l2_frmsize_discrete tegra_csi_tpg_sizes[] = {
* V4L2 Subdevice Pad Operations
*/
static int csi_enum_bus_code(struct v4l2_subdev *subdev,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
@@ -79,7 +79,7 @@ static int csi_enum_bus_code(struct v4l2_subdev *subdev,
}
static int csi_get_format(struct v4l2_subdev *subdev,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
@@ -127,7 +127,7 @@ static void csi_chan_update_blank_intervals(struct tegra_csi_channel *csi_chan,
}
static int csi_enum_framesizes(struct v4l2_subdev *subdev,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
unsigned int i;
@@ -154,7 +154,7 @@ static int csi_enum_framesizes(struct v4l2_subdev *subdev,
}
static int csi_enum_frameintervals(struct v4l2_subdev *subdev,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval_enum *fie)
{
struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
@@ -181,7 +181,7 @@ static int csi_enum_frameintervals(struct v4l2_subdev *subdev,
}
static int csi_set_format(struct v4l2_subdev *subdev,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
@@ -298,10 +298,9 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev)
struct tegra_csi *csi = csi_chan->csi;
int ret, err;
- ret = pm_runtime_get_sync(csi->dev);
+ ret = pm_runtime_resume_and_get(csi->dev);
if (ret < 0) {
dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
- pm_runtime_put_noidle(csi->dev);
return ret;
}
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index df5ca3596470..89709cd06d4d 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -297,10 +297,9 @@ static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
int ret;
- ret = pm_runtime_get_sync(chan->vi->dev);
+ ret = pm_runtime_resume_and_get(chan->vi->dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
- pm_runtime_put_noidle(chan->vi->dev);
return ret;
}
@@ -494,7 +493,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
const struct tegra_video_format *fmtinfo;
struct v4l2_subdev *subdev;
struct v4l2_subdev_format fmt;
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
struct v4l2_subdev_frame_size_enum fse = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
@@ -508,8 +507,8 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
if (!subdev)
return -ENODEV;
- pad_cfg = v4l2_subdev_alloc_pad_config(subdev);
- if (!pad_cfg)
+ sd_state = v4l2_subdev_alloc_state(subdev);
+ if (!sd_state)
return -ENOMEM;
/*
* Retrieve the format information and if requested format isn't
@@ -533,33 +532,33 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
* If not available, try to get crop boundary from subdev.
*/
fse.code = fmtinfo->code;
- ret = v4l2_subdev_call(subdev, pad, enum_frame_size, pad_cfg, &fse);
+ ret = v4l2_subdev_call(subdev, pad, enum_frame_size, sd_state, &fse);
if (ret) {
if (!v4l2_subdev_has_op(subdev, pad, get_selection)) {
- pad_cfg->try_crop.width = 0;
- pad_cfg->try_crop.height = 0;
+ sd_state->pads->try_crop.width = 0;
+ sd_state->pads->try_crop.height = 0;
} else {
ret = v4l2_subdev_call(subdev, pad, get_selection,
NULL, &sdsel);
if (ret)
return -EINVAL;
- pad_cfg->try_crop.width = sdsel.r.width;
- pad_cfg->try_crop.height = sdsel.r.height;
+ sd_state->pads->try_crop.width = sdsel.r.width;
+ sd_state->pads->try_crop.height = sdsel.r.height;
}
} else {
- pad_cfg->try_crop.width = fse.max_width;
- pad_cfg->try_crop.height = fse.max_height;
+ sd_state->pads->try_crop.width = fse.max_width;
+ sd_state->pads->try_crop.height = fse.max_height;
}
- ret = v4l2_subdev_call(subdev, pad, set_fmt, pad_cfg, &fmt);
+ ret = v4l2_subdev_call(subdev, pad, set_fmt, sd_state, &fmt);
if (ret < 0)
return ret;
v4l2_fill_pix_format(pix, &fmt.format);
tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
return 0;
}
@@ -1812,8 +1811,8 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan,
continue;
}
- tvge = v4l2_async_notifier_add_fwnode_subdev(&chan->notifier,
- remote, struct tegra_vi_graph_entity);
+ tvge = v4l2_async_notifier_add_fwnode_subdev(&chan->notifier, remote,
+ struct tegra_vi_graph_entity);
if (IS_ERR(tvge)) {
ret = PTR_ERR(tvge);
dev_err(vi->dev,
diff --git a/drivers/staging/media/zoran/zoran.h b/drivers/staging/media/zoran/zoran.h
index e7fe8da7732c..b1ad2a2b914c 100644
--- a/drivers/staging/media/zoran/zoran.h
+++ b/drivers/staging/media/zoran/zoran.h
@@ -158,7 +158,6 @@ struct zoran_jpg_settings {
struct v4l2_jpegcompression jpg_comp; /* JPEG-specific capture settings */
};
-
struct zoran;
/* zoran_fh contains per-open() settings */
diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c
index dfc60e2e9dd7..f259585b0689 100644
--- a/drivers/staging/media/zoran/zoran_card.c
+++ b/drivers/staging/media/zoran/zoran_card.c
@@ -37,9 +37,10 @@ module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "Card type");
/*
- * The video mem address of the video card. The driver has a little database for some videocards
- * to determine it from there. If your video card is not in there you have either to give it to
- * the driver as a parameter or set in in a VIDIOCSFBUF ioctl
+ * The video mem address of the video card. The driver has a little database
+ * for some videocards to determine it from there. If your video card is not
+ * in there you have either to give it to the driver as a parameter or set
+ * in a VIDIOCSFBUF ioctl
*/
static unsigned long vidmem; /* default = 0 - Video memory base address */
diff --git a/drivers/staging/media/zoran/zoran_device.c b/drivers/staging/media/zoran/zoran_device.c
index cf788d9cd1df..5b12a730a229 100644
--- a/drivers/staging/media/zoran/zoran_device.c
+++ b/drivers/staging/media/zoran/zoran_device.c
@@ -148,71 +148,6 @@ int post_office_read(struct zoran *zr, unsigned int guest, unsigned int reg)
}
/*
- * detect guests
- */
-
-static void dump_guests(struct zoran *zr)
-{
- if (zr36067_debug > 2) {
- int i, guest[8];
-
- /* do not print random data */
- guest[0] = 0;
-
- for (i = 1; i < 8; i++) /* Don't read jpeg codec here */
- guest[i] = post_office_read(zr, i, 0);
-
- pci_info(zr->pci_dev, "Guests: %*ph\n", 8, guest);
- }
-}
-
-void detect_guest_activity(struct zoran *zr)
-{
- int timeout, i, j, res, guest[8], guest0[8], change[8][3];
- ktime_t t0, t1;
-
- /* do not print random data */
- guest[0] = 0;
- guest0[0] = 0;
-
- dump_guests(zr);
- pci_info(zr->pci_dev, "Detecting guests activity, please wait...\n");
- for (i = 1; i < 8; i++) /* Don't read jpeg codec here */
- guest0[i] = guest[i] = post_office_read(zr, i, 0);
-
- timeout = 0;
- j = 0;
- t0 = ktime_get();
- while (timeout < 10000) {
- udelay(10);
- timeout++;
- for (i = 1; (i < 8) && (j < 8); i++) {
- res = post_office_read(zr, i, 0);
- if (res != guest[i]) {
- t1 = ktime_get();
- change[j][0] = ktime_to_us(ktime_sub(t1, t0));
- t0 = t1;
- change[j][1] = i;
- change[j][2] = res;
- j++;
- guest[i] = res;
- }
- }
- if (j >= 8)
- break;
- }
-
- pci_info(zr->pci_dev, "Guests: %*ph\n", 8, guest0);
-
- if (j == 0) {
- pci_info(zr->pci_dev, "No activity detected.\n");
- return;
- }
- for (i = 0; i < j; i++)
- pci_info(zr->pci_dev, "%6d: %d => 0x%02x\n", change[i][0], change[i][1], change[i][2]);
-}
-
-/*
* JPEG Codec access
*/
diff --git a/drivers/staging/media/zoran/zoran_device.h b/drivers/staging/media/zoran/zoran_device.h
index 24be19a61b6d..6c5d70238228 100644
--- a/drivers/staging/media/zoran/zoran_device.h
+++ b/drivers/staging/media/zoran/zoran_device.h
@@ -20,8 +20,6 @@ extern int post_office_wait(struct zoran *zr);
extern int post_office_write(struct zoran *zr, unsigned int guest, unsigned int reg, unsigned int value);
extern int post_office_read(struct zoran *zr, unsigned int guest, unsigned int reg);
-extern void detect_guest_activity(struct zoran *zr);
-
extern void jpeg_codec_sleep(struct zoran *zr, int sleep);
extern int jpeg_codec_reset(struct zoran *zr);
diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
index e8902f824d6c..46382e43f1bf 100644
--- a/drivers/staging/media/zoran/zoran_driver.c
+++ b/drivers/staging/media/zoran/zoran_driver.c
@@ -678,12 +678,14 @@ static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selectio
sel->r.height = zr->jpg_settings.img_height;
break;
case V4L2_SEL_TGT_CROP_DEFAULT:
- sel->r.top = sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.left = 0;
sel->r.width = BUZ_MIN_WIDTH;
sel->r.height = BUZ_MIN_HEIGHT;
break;
case V4L2_SEL_TGT_CROP_BOUNDS:
- sel->r.top = sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.left = 0;
sel->r.width = BUZ_MAX_WIDTH;
sel->r.height = BUZ_MAX_HEIGHT;
break;
diff --git a/drivers/staging/media/zoran/zr36016.c b/drivers/staging/media/zoran/zr36016.c
index 2d7dc7abde79..9b350a885879 100644
--- a/drivers/staging/media/zoran/zr36016.c
+++ b/drivers/staging/media/zoran/zr36016.c
@@ -361,7 +361,8 @@ static int zr36016_setup(struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
if (!ptr)
return -ENOMEM;
diff --git a/drivers/staging/media/zoran/zr36050.c b/drivers/staging/media/zoran/zr36050.c
index 2826f4e5d37b..c62af27f2683 100644
--- a/drivers/staging/media/zoran/zr36050.c
+++ b/drivers/staging/media/zoran/zr36050.c
@@ -16,7 +16,7 @@
#include <linux/wait.h>
/* I/O commands, error codes */
-#include <asm/io.h>
+#include <linux/io.h>
/* headerfile of this module */
#include "zr36050.h"
@@ -754,7 +754,8 @@ static int zr36050_setup(struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
if (!ptr)
return -ENOMEM;
diff --git a/drivers/staging/media/zoran/zr36057.h b/drivers/staging/media/zoran/zr36057.h
index 71b651add35a..a2a75fd9f535 100644
--- a/drivers/staging/media/zoran/zr36057.h
+++ b/drivers/staging/media/zoran/zr36057.h
@@ -30,13 +30,13 @@
#define ZR36057_VFESPFR_HOR_DCM 14
#define ZR36057_VFESPFR_VER_DCM 8
#define ZR36057_VFESPFR_DISP_MODE 6
-#define ZR36057_VFESPFR_YUV422 (0<<3)
-#define ZR36057_VFESPFR_RGB888 (1<<3)
-#define ZR36057_VFESPFR_RGB565 (2<<3)
-#define ZR36057_VFESPFR_RGB555 (3<<3)
-#define ZR36057_VFESPFR_ERR_DIF (1<<2)
-#define ZR36057_VFESPFR_PACK24 (1<<1)
-#define ZR36057_VFESPFR_LITTLE_ENDIAN (1<<0)
+#define ZR36057_VFESPFR_YUV422 (0 << 3)
+#define ZR36057_VFESPFR_RGB888 (1 << 3)
+#define ZR36057_VFESPFR_RGB565 (2 << 3)
+#define ZR36057_VFESPFR_RGB555 (3 << 3)
+#define ZR36057_VFESPFR_ERR_DIF (1 << 2)
+#define ZR36057_VFESPFR_PACK24 (1 << 1)
+#define ZR36057_VFESPFR_LITTLE_ENDIAN (1 << 0)
#define ZR36057_VDTR 0x00c /* Video Display "Top" Register */
diff --git a/drivers/staging/media/zoran/zr36060.c b/drivers/staging/media/zoran/zr36060.c
index 4f9eb9ff2c42..1c3af11b5f24 100644
--- a/drivers/staging/media/zoran/zr36060.c
+++ b/drivers/staging/media/zoran/zr36060.c
@@ -790,7 +790,8 @@ static int zr36060_setup(struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
if (!ptr)
return -ENOMEM;