From 1d3e15436f8bf078137ff3e0146d882cb2b8e4b6 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 07:37:22 -0300 Subject: [media] adv7842: Remove deprecated create_singlethread_workqueue The workqueue "work_queues" enables hotplugging. It has a single work item(&state->delayed_work_enable_hotplug) and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been sync cancelled in adv7842_remove() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7842.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 8081ef78ec05..a45e7537b936 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -118,7 +118,6 @@ struct adv7842_state { struct v4l2_fract aspect_ratio; u32 rgb_quantization_range; bool is_cea_format; - struct workqueue_struct *work_queues; struct delayed_work delayed_work_enable_hotplug; bool restart_stdi_once; bool hdmi_port_a; @@ -756,8 +755,7 @@ static int edid_write_vga_segment(struct v4l2_subdev *sd) } /* enable hotplug after 200 ms */ - queue_delayed_work(state->work_queues, - &state->delayed_work_enable_hotplug, HZ / 5); + schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 5); return 0; } @@ -855,8 +853,7 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) } /* enable hotplug after 200 ms */ - queue_delayed_work(state->work_queues, - &state->delayed_work_enable_hotplug, HZ / 5); + schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 5); return 0; } @@ -3314,13 +3311,6 @@ static int adv7842_probe(struct i2c_client *client, goto err_i2c; } - /* work queues */ - state->work_queues = create_singlethread_workqueue(client->name); - if (!state->work_queues) { - v4l2_err(sd, "Could not create work queue\n"); - err = -ENOMEM; - goto err_i2c; - } INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, adv7842_delayed_work_enable_hotplug); @@ -3342,7 +3332,6 @@ err_entity: media_entity_cleanup(&sd->entity); err_work_queues: cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); err_i2c: adv7842_unregister_clients(sd); err_hdl: @@ -3360,7 +3349,6 @@ static int adv7842_remove(struct i2c_client *client) adv7842_irq_enable(sd, false); cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); v4l2_device_unregister_subdev(sd); media_entity_cleanup(&sd->entity); adv7842_unregister_clients(sd); -- cgit v1.2.1 From 1ce395465788d2a103d155bf14317dfbf6c58e34 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 07:41:53 -0300 Subject: [media] tc358743: Remove deprecated create_singlethread_workqueue The workqueue "work_queues" enables hotplugging. It has a single work item(&state->delayed_work_enable_hotplug) and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been sync cancelled in tc358743_remove() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 6cf6d06737a5..1e3a0dd2238c 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -89,8 +89,6 @@ struct tc358743_state { struct v4l2_ctrl *audio_sampling_rate_ctrl; struct v4l2_ctrl *audio_present_ctrl; - /* work queues */ - struct workqueue_struct *work_queues; struct delayed_work delayed_work_enable_hotplug; /* edid */ @@ -425,8 +423,7 @@ static void tc358743_enable_edid(struct v4l2_subdev *sd) /* Enable hotplug after 100 ms. DDC access to EDID is also enabled when * hotplug is enabled. See register DDC_CTL */ - queue_delayed_work(state->work_queues, - &state->delayed_work_enable_hotplug, HZ / 10); + schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 10); tc358743_enable_interrupts(sd, true); tc358743_s_ctrl_detect_tx_5v(sd); @@ -1884,14 +1881,6 @@ static int tc358743_probe(struct i2c_client *client, goto err_hdl; } - /* work queues */ - state->work_queues = create_singlethread_workqueue(client->name); - if (!state->work_queues) { - v4l2_err(sd, "Could not create work queue\n"); - err = -ENOMEM; - goto err_hdl; - } - state->pad.flags = MEDIA_PAD_FL_SOURCE; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err < 0) @@ -1940,7 +1929,6 @@ static int tc358743_probe(struct i2c_client *client, err_work_queues: cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); mutex_destroy(&state->confctl_mutex); err_hdl: media_entity_cleanup(&sd->entity); @@ -1954,7 +1942,6 @@ static int tc358743_remove(struct i2c_client *client) struct tc358743_state *state = to_state(sd); cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); v4l2_async_unregister_subdev(sd); v4l2_device_unregister_subdev(sd); mutex_destroy(&state->confctl_mutex); -- cgit v1.2.1 From 0423ff9bd4193dd9fd4dd2ef1a6698fc80fa17ec Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 07:43:55 -0300 Subject: [media] adv7604: Remove deprecated create_singlethread_workqueue The workqueue "work_queues" enables hotplugging. It has a single work item(&state->delayed_work_enable_hotplug) and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been sync cancelled in adv76xx_remove() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 3f1ab4986cfc..3ffb3231be3f 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -184,7 +184,6 @@ struct adv76xx_state { u16 spa_port_a[2]; struct v4l2_fract aspect_ratio; u32 rgb_quantization_range; - struct workqueue_struct *work_queues; struct delayed_work delayed_work_enable_hotplug; bool restart_stdi_once; @@ -2154,8 +2153,7 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) } /* enable hotplug after 100 ms */ - queue_delayed_work(state->work_queues, - &state->delayed_work_enable_hotplug, HZ / 10); + schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 10); return 0; } @@ -3206,14 +3204,6 @@ static int adv76xx_probe(struct i2c_client *client, } } - /* work queues */ - state->work_queues = create_singlethread_workqueue(client->name); - if (!state->work_queues) { - v4l2_err(sd, "Could not create work queue\n"); - err = -ENOMEM; - goto err_i2c; - } - INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, adv76xx_delayed_work_enable_hotplug); @@ -3249,7 +3239,6 @@ err_entity: media_entity_cleanup(&sd->entity); err_work_queues: cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); err_i2c: adv76xx_unregister_clients(state); err_hdl: @@ -3265,7 +3254,6 @@ static int adv76xx_remove(struct i2c_client *client) struct adv76xx_state *state = to_state(sd); cancel_delayed_work(&state->delayed_work_enable_hotplug); - destroy_workqueue(state->work_queues); v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); adv76xx_unregister_clients(to_state(sd)); -- cgit v1.2.1 From f5591da992b952624cf191ed4988360f921e9e57 Mon Sep 17 00:00:00 2001 From: Dragos Bogdan Date: Wed, 22 Jun 2016 08:30:42 -0300 Subject: [media] adv7604: Add support for hardware reset The part can be reset by a low pulse on the RESET pin (i.e. a hardware reset) with a minimum width of 5 ms. It is recommended to wait 5 ms after the low pulse before an I2C write is performed to the part. For safety reasons, the delays will be between 5 and 10 ms. The RESET pin can be tied high, so the GPIO is optional. Signed-off-by: Dragos Bogdan Reviewed-by: Lars-Peter Clausen Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 3ffb3231be3f..0b362eeb55c7 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -164,6 +164,7 @@ struct adv76xx_state { struct adv76xx_platform_data pdata; struct gpio_desc *hpd_gpio[4]; + struct gpio_desc *reset_gpio; struct v4l2_subdev sd; struct media_pad pads[ADV76XX_PAD_MAX]; @@ -3018,6 +3019,19 @@ static int configure_regmaps(struct adv76xx_state *state) return 0; } +static void adv76xx_reset(struct adv76xx_state *state) +{ + if (state->reset_gpio) { + /* ADV76XX can be reset by a low reset pulse of minimum 5 ms. */ + gpiod_set_value_cansleep(state->reset_gpio, 0); + usleep_range(5000, 10000); + gpiod_set_value_cansleep(state->reset_gpio, 1); + /* It is recommended to wait 5 ms after the low pulse before */ + /* an I2C write is performed to the ADV76XX. */ + usleep_range(5000, 10000); + } +} + static int adv76xx_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -3081,6 +3095,12 @@ static int adv76xx_probe(struct i2c_client *client, if (state->hpd_gpio[i]) v4l_info(client, "Handling HPD %u GPIO\n", i); } + state->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(state->reset_gpio)) + return PTR_ERR(state->reset_gpio); + + adv76xx_reset(state); state->timings = cea640x480; state->format = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8); -- cgit v1.2.1 From 743eb09f4c96054addb53bda2615ea886343306b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Jul 2016 09:01:22 -0300 Subject: [media] media/i2c: drop the last users of the ctrl core ops Nobody is using these ops anymore, so remove these callbacks from the subdev drivers that still have them. Signed-off-by: Hans Verkuil Cc: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/cs53l32a.c | 7 ------- drivers/media/i2c/cx25840/cx25840-core.c | 7 ------- drivers/media/i2c/msp3400-driver.c | 7 ------- drivers/media/i2c/saa7115.c | 7 ------- drivers/media/i2c/tvaudio.c | 7 ------- drivers/media/i2c/wm8775.c | 7 ------- 6 files changed, 42 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index b7e87e38642a..e4b3cf49dd38 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -121,13 +121,6 @@ static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = { static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { .log_status = cs53l32a_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = { diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 07a3e7173144..142ae28803bb 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -5042,13 +5042,6 @@ static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { static const struct v4l2_subdev_core_ops cx25840_core_ops = { .log_status = cx25840_log_status, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, .reset = cx25840_reset, .load_fw = cx25840_load_fw, .s_io_pin_config = common_s_io_pin_config, diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index e016626ebf89..503b7c4f0a9b 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -642,13 +642,6 @@ static const struct v4l2_ctrl_ops msp_ctrl_ops = { static const struct v4l2_subdev_core_ops msp_core_ops = { .log_status = msp_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_video_ops msp_video_ops = { diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index bd3526bdd539..58062b41c923 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1585,13 +1585,6 @@ static const struct v4l2_ctrl_ops saa711x_ctrl_ops = { static const struct v4l2_subdev_core_ops saa711x_core_ops = { .log_status = saa711x_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, .reset = saa711x_reset, .s_gpio = saa711x_s_gpio, #ifdef CONFIG_VIDEO_ADV_DEBUG diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index fece2a4339a1..42d1e26e581c 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -1855,13 +1855,6 @@ static const struct v4l2_ctrl_ops tvaudio_ctrl_ops = { static const struct v4l2_subdev_core_ops tvaudio_core_ops = { .log_status = tvaudio_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 6e00f145b948..5581f4db02af 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -178,13 +178,6 @@ static const struct v4l2_ctrl_ops wm8775_ctrl_ops = { static const struct v4l2_subdev_core_ops wm8775_core_ops = { .log_status = wm8775_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_tuner_ops wm8775_tuner_ops = { -- cgit v1.2.1 From afd620f81bb02762b77fb76f29a0287cbce32e8c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 28 Jun 2016 11:30:35 -0300 Subject: [media] adv7511: drop adv7511_set_IT_content_AVI_InfoFrame The IT Content bit has nothing to do with CE vs IT timings. Delete this code. This will also fix a bug where this could override the 'content type' control, which is actually the correct place to set/clear the ITC bit. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 39d409f99628..df507adb130a 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -382,18 +382,6 @@ static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) } } -static void adv7511_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd) -{ - struct adv7511_state *state = get_adv7511_state(sd); - if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) { - /* CE format, not IT */ - adv7511_wr_and_or(sd, 0x57, 0x7f, 0x00); - } else { - /* IT format */ - adv7511_wr_and_or(sd, 0x57, 0x7f, 0x80); - } -} - static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) { switch (ctrl->val) { @@ -1068,9 +1056,6 @@ static int adv7511_s_dv_timings(struct v4l2_subdev *sd, /* update quantization range based on new dv_timings */ adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); - /* update AVI infoframe */ - adv7511_set_IT_content_AVI_InfoFrame(sd); - return 0; } -- cgit v1.2.1 From 0a25a0125194639507cf24319d02f5de63d182b5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 28 Jun 2016 11:32:36 -0300 Subject: [media] adv7511: fix quantization range handling Commit 1fb69bfd29e4b2e5e93922105326dd6cbd5ef6eb (adv7511: improve colorspace handling) introduced a number of bugs, specifically with regards to YCbCr output and quantization range handling: - if the output is not RGB, then disable the full-to-limited range CSC matrix since that is meant for RGB formats. YCbCr formats are always limited range, so there is nothing to convert. (OK, full range YCbCr is possible, but we don't support that right now). - the mediabus code that was passed to adv7511_set_fmt was always cleared by the memset in adv7511_fill_format. This made it effectively impossible to select YCbCr output. - adv7511_set_fmt never updated the rgb quantization range. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index df507adb130a..03797b5f3172 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -382,16 +382,20 @@ static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) } } -static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) +static void adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) { + struct adv7511_state *state = get_adv7511_state(sd); + + /* Only makes sense for RGB formats */ + if (state->fmt_code != MEDIA_BUS_FMT_RGB888_1X24) { + /* so just keep quantization */ + adv7511_csc_rgb_full2limit(sd, false); + return; + } + switch (ctrl->val) { - default: - return -EINVAL; - break; - case V4L2_DV_RGB_RANGE_AUTO: { + case V4L2_DV_RGB_RANGE_AUTO: /* automatic */ - struct adv7511_state *state = get_adv7511_state(sd); - if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) { /* CE format, RGB limited range (16-235) */ adv7511_csc_rgb_full2limit(sd, true); @@ -399,7 +403,6 @@ static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2 /* not CE format, RGB full range (0-255) */ adv7511_csc_rgb_full2limit(sd, false); } - } break; case V4L2_DV_RGB_RANGE_LIMITED: /* RGB limited range (16-235) */ @@ -410,7 +413,6 @@ static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2 adv7511_csc_rgb_full2limit(sd, false); break; } - return 0; } /* ------------------------------ CTRL OPS ------------------------------ */ @@ -427,8 +429,10 @@ static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) adv7511_wr_and_or(sd, 0xaf, 0xfd, ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00); return 0; } - if (state->rgb_quantization_range_ctrl == ctrl) - return adv7511_set_rgb_quantization_mode(sd, ctrl); + if (state->rgb_quantization_range_ctrl == ctrl) { + adv7511_set_rgb_quantization_mode(sd, ctrl); + return 0; + } if (state->content_type_ctrl == ctrl) { u8 itc, cn; @@ -1235,8 +1239,6 @@ static int adv7511_enum_mbus_code(struct v4l2_subdev *sd, static void adv7511_fill_format(struct adv7511_state *state, struct v4l2_mbus_framefmt *format) { - memset(format, 0, sizeof(*format)); - format->width = state->dv_timings.bt.width; format->height = state->dv_timings.bt.height; format->field = V4L2_FIELD_NONE; @@ -1251,6 +1253,7 @@ static int adv7511_get_fmt(struct v4l2_subdev *sd, if (format->pad != 0) return -EINVAL; + memset(&format->format, 0, sizeof(format->format)); adv7511_fill_format(state, &format->format); if (format->which == V4L2_SUBDEV_FORMAT_TRY) { @@ -1411,6 +1414,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2) | (itc << 7)); adv7511_wr_and_or(sd, 0x59, 0x0f, (yq << 6) | (cn << 4)); adv7511_wr_and_or(sd, 0x4a, 0xff, 1); + adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); return 0; } -- cgit v1.2.1 From fd74246d2ade37cd477178652448410a35bdaca0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 28 Jun 2016 11:43:01 -0300 Subject: [media] adv7604/adv7842: fix quantization range handling Fix a number of bugs that appeared when support for mediabus formats was added: - Support for V4L2_DV_RGB_RANGE_FULL/LIMITED should only be enabled for HDMI RGB formats, not for YCbCr formats. Since, as the name says, this setting is for RGB only. So read the InfoFrame to check the format. - the quantization range for the pixelport depends on whether the mediabus code is RGB or not: if it is RGB, then produce full range RGB values, otherwise produce limited range YCbCr values. This means that the op_656_range and alt_data_sat fields of the platform data are no longer used and these will be removed in a following patch. - when setting up a new format the RGB quantization range settings were never updated. Do so, since this depends on the format. - fix the log_status output which was confusing and incorrect. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 27 ++++++++++++++++----------- drivers/media/i2c/adv7842.c | 26 +++++++++++++++++--------- 2 files changed, 33 insertions(+), 20 deletions(-) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 2d7927150450..4003831de712 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1102,6 +1102,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) struct adv76xx_state *state = to_state(sd); bool rgb_output = io_read(sd, 0x02) & 0x02; bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80; + u8 y = HDMI_COLORSPACE_RGB; + + if (hdmi_signal && (io_read(sd, 0x60) & 1)) + y = infoframe_read(sd, 0x01) >> 5; v4l2_dbg(2, debug, sd, "%s: RGB quantization range: %d, RGB out: %d, HDMI: %d\n", __func__, state->rgb_quantization_range, @@ -1109,6 +1113,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) adv76xx_set_gain(sd, true, 0x0, 0x0, 0x0); adv76xx_set_offset(sd, true, 0x0, 0x0, 0x0); + io_write_clr_set(sd, 0x02, 0x04, rgb_output ? 0 : 4); switch (state->rgb_quantization_range) { case V4L2_DV_RGB_RANGE_AUTO: @@ -1158,6 +1163,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) break; } + if (y != HDMI_COLORSPACE_RGB) + break; + /* RGB limited range (16-235) */ io_write_clr_set(sd, 0x02, 0xf0, 0x00); @@ -1169,6 +1177,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) break; } + if (y != HDMI_COLORSPACE_RGB) + break; + /* RGB full range (0-255) */ io_write_clr_set(sd, 0x02, 0xf0, 0x10); @@ -1865,6 +1876,7 @@ static void adv76xx_setup_format(struct adv76xx_state *state) io_write_clr_set(sd, 0x04, 0xe0, adv76xx_op_ch_sel(state)); io_write_clr_set(sd, 0x05, 0x01, state->format->swap_cb_cr ? ADV76XX_OP_SWAP_CB_CR : 0); + set_rgb_quantization_range(sd); } static int adv76xx_get_format(struct v4l2_subdev *sd, @@ -2539,11 +2551,10 @@ static int adv76xx_log_status(struct v4l2_subdev *sd) rgb_quantization_range_txt[state->rgb_quantization_range]); v4l2_info(sd, "Input color space: %s\n", input_color_space_txt[reg_io_0x02 >> 4]); - v4l2_info(sd, "Output color space: %s %s, saturator %s, alt-gamma %s\n", + v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n", (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", - (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ? - "enabled" : "disabled", + "(16-235)" : "(0-255)", (reg_io_0x02 & 0x08) ? "enabled" : "disabled"); v4l2_info(sd, "Color space conversion: %s\n", csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]); @@ -2731,10 +2742,7 @@ static int adv76xx_core_init(struct v4l2_subdev *sd) cp_write(sd, 0xcf, 0x01); /* Power down macrovision */ /* video format */ - io_write_clr_set(sd, 0x02, 0x0f, - pdata->alt_gamma << 3 | - pdata->op_656_range << 2 | - pdata->alt_data_sat << 0); + io_write_clr_set(sd, 0x02, 0x0f, pdata->alt_gamma << 3); io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 | pdata->insert_av_codes << 2 | pdata->replicate_av_codes << 1); @@ -3084,10 +3092,8 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) state->pdata.inv_llc_pol = 1; - if (bus_cfg.bus_type == V4L2_MBUS_BT656) { + if (bus_cfg.bus_type == V4L2_MBUS_BT656) state->pdata.insert_av_codes = 1; - state->pdata.op_656_range = 1; - } /* Disable the interrupt for now as no DT-based board uses it. */ state->pdata.int1_config = ADV76XX_INT1_CONFIG_DISABLED; @@ -3110,7 +3116,6 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) state->pdata.disable_pwrdnb = 0; state->pdata.disable_cable_det_rst = 0; state->pdata.blank_data = 1; - state->pdata.alt_data_sat = 1; state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0; state->pdata.bus_order = ADV7604_BUS_ORDER_RGB; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 100bd3f96b59..8c2a52e280af 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -1184,6 +1184,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) struct adv7842_state *state = to_state(sd); bool rgb_output = io_read(sd, 0x02) & 0x02; bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80; + u8 y = HDMI_COLORSPACE_RGB; + + if (hdmi_signal && (io_read(sd, 0x60) & 1)) + y = infoframe_read(sd, 0x01) >> 5; v4l2_dbg(2, debug, sd, "%s: RGB quantization range: %d, RGB out: %d, HDMI: %d\n", __func__, state->rgb_quantization_range, @@ -1191,6 +1195,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) adv7842_set_gain(sd, true, 0x0, 0x0, 0x0); adv7842_set_offset(sd, true, 0x0, 0x0, 0x0); + io_write_clr_set(sd, 0x02, 0x04, rgb_output ? 0 : 4); switch (state->rgb_quantization_range) { case V4L2_DV_RGB_RANGE_AUTO: @@ -1240,6 +1245,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) break; } + if (y != HDMI_COLORSPACE_RGB) + break; + /* RGB limited range (16-235) */ io_write_and_or(sd, 0x02, 0x0f, 0x00); @@ -1251,6 +1259,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) break; } + if (y != HDMI_COLORSPACE_RGB) + break; + /* RGB full range (0-255) */ io_write_and_or(sd, 0x02, 0x0f, 0x10); @@ -2058,6 +2069,7 @@ static void adv7842_setup_format(struct adv7842_state *state) io_write_clr_set(sd, 0x04, 0xe0, adv7842_op_ch_sel(state)); io_write_clr_set(sd, 0x05, 0x01, state->format->swap_cb_cr ? ADV7842_OP_SWAP_CB_CR : 0); + set_rgb_quantization_range(sd); } static int adv7842_get_format(struct v4l2_subdev *sd, @@ -2777,11 +2789,11 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd) rgb_quantization_range_txt[state->rgb_quantization_range]); v4l2_info(sd, "Input color space: %s\n", input_color_space_txt[reg_io_0x02 >> 4]); - v4l2_info(sd, "Output color space: %s %s, saturator %s\n", + v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n", (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", - (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", - ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? - "enabled" : "disabled"); + (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ? + "(16-235)" : "(0-255)", + (reg_io_0x02 & 0x08) ? "enabled" : "disabled"); v4l2_info(sd, "Color space conversion: %s\n", csc_coeff_sel_rb[cp_read(sd, 0xf4) >> 4]); @@ -2985,11 +2997,7 @@ static int adv7842_core_init(struct v4l2_subdev *sd) io_write(sd, 0x15, 0x80); /* Power up pads */ /* video format */ - io_write(sd, 0x02, - 0xf0 | - pdata->alt_gamma << 3 | - pdata->op_656_range << 2 | - pdata->alt_data_sat << 0); + io_write(sd, 0x02, 0xf0 | pdata->alt_gamma << 3); io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 | pdata->insert_av_codes << 2 | pdata->replicate_av_codes << 1); -- cgit v1.2.1 From 65898fb99cd7629683d7759d0c0242b8280413fc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 5 Jul 2016 07:16:23 -0300 Subject: [media] adv7511: the h/vsync polarities were always positive Correctly set the h/vsync polarities instead of keeping to the default (positive). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/i2c') diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 03797b5f3172..6d7cad54a65d 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1057,6 +1057,11 @@ static int adv7511_s_dv_timings(struct v4l2_subdev *sd, /* save timings */ state->dv_timings = *timings; + /* set h/vsync polarities */ + adv7511_wr_and_or(sd, 0x17, 0x9f, + ((timings->bt.polarities & V4L2_DV_VSYNC_POS_POL) ? 0 : 0x40) | + ((timings->bt.polarities & V4L2_DV_HSYNC_POS_POL) ? 0 : 0x20)); + /* update quantization range based on new dv_timings */ adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); -- cgit v1.2.1