On 08/14/2013 05:10 AM, Prabhakar Lad wrote:
> Hi Hans,
> 
> Thanks for the patch. Few nits below.
> 
> On Mon, Aug 12, 2013 at 6:43 PM, Hans Verkuil <hverk...@xs4all.nl> wrote:
>> From: Hans Verkuil <hans.verk...@cisco.com>
>>
>> Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
>> ---
>>  drivers/media/i2c/Kconfig   |   12 +
>>  drivers/media/i2c/Makefile  |    1 +
>>  drivers/media/i2c/adv7842.c | 3022 
>> +++++++++++++++++++++++++++++++++++++++++++
>>  include/media/adv7842.h     |  226 ++++
>>  4 files changed, 3261 insertions(+)
>>  create mode 100644 drivers/media/i2c/adv7842.c
>>  create mode 100644 include/media/adv7842.h
>>
>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>> index b2cd8ca..847b711 100644
>> --- a/drivers/media/i2c/Kconfig
>> +++ b/drivers/media/i2c/Kconfig
>> @@ -206,6 +206,18 @@ config VIDEO_ADV7604
>>           To compile this driver as a module, choose M here: the
>>           module will be called adv7604.
>>
>> +config VIDEO_ADV7842
>> +       tristate "Analog Devices ADV7842 decoder"
>> +       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
>> +       ---help---
>> +         Support for the Analog Devices ADV7842 video decoder.
>> +
>> +         This is a Analog Devices Component/Graphics/SD Digitizer
>> +         with 2:1 Multiplexed HDMI Receiver.
>> +
>> +         To compile this driver as a module, choose M here: the
>> +         module will be called adv7842.
>> +
>>  config VIDEO_BT819
>>         tristate "BT819A VideoStream decoder"
>>         depends on VIDEO_V4L2 && I2C
>> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
>> index dc20653..b4cf972 100644
>> --- a/drivers/media/i2c/Makefile
>> +++ b/drivers/media/i2c/Makefile
>> @@ -26,6 +26,7 @@ obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
>>  obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
>>  obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
>>  obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
>> +obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o
>>  obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
>>  obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
>>  obj-$(CONFIG_VIDEO_VS6624)  += vs6624.o
>> diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
>> new file mode 100644
>> index 0000000..84c9a83
>> --- /dev/null
>> +++ b/drivers/media/i2c/adv7842.c
>> @@ -0,0 +1,3022 @@
>> +/*
>> + * adv7842 - Analog Devices ADV7842 video decoder driver
>> + *
>> + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights 
>> reserved.
>> + *
>> + * This program is free software; you may redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
>> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
>> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
>> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + *
>> + */
>> +
>> +/*
>> + * References (c = chapter, p = page):
>> + * REF_01 - Analog devices, ADV7842, Register Settings Recommendations,
>> + *             Revision 2.5, June 2010
>> + * REF_02 - Analog devices, Register map documentation, Documentation of
>> + *             the register maps, Software manual, Rev. F, June 2010
>> + */
>> +
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/i2c.h>
>> +#include <linux/delay.h>
>> +#include <linux/videodev2.h>
>> +#include <linux/workqueue.h>
>> +#include <linux/v4l2-dv-timings.h>
>> +#include <media/v4l2-device.h>
>> +#include <media/v4l2-ctrls.h>
>> +#include <media/adv7842.h>
>> +
>> +static int debug;
>> +module_param(debug, int, 0644);
>> +MODULE_PARM_DESC(debug, "debug level (0-2)");
>> +
>> +MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver");
>> +MODULE_AUTHOR("Hans Verkuil <hans.verk...@cisco.com>");
>> +MODULE_AUTHOR("Martin Bugge <marbu...@cisco.com>");
>> +MODULE_LICENSE("GPL");
>> +
>> +/* ADV7842 system clock frequency */
>> +#define ADV7842_fsc (28636360)
>> +
>> +/*
>> +**********************************************************************
>> +*
>> +*  Arrays with configuration parameters for the ADV7842
>> +*
>> +**********************************************************************
>> +*/
>> +
>> +struct adv7842_state {
>> +       struct v4l2_subdev sd;
>> +       struct media_pad pad;
>> +       struct v4l2_ctrl_handler hdl;
>> +       enum adv7842_mode mode;
>> +       struct v4l2_dv_timings timings;
>> +       enum adv7842_vid_std_select vid_std_select;
>> +       v4l2_std_id norm;
>> +       struct {
>> +               u8 edid[256];
>> +               u32 present;
>> +       } hdmi_edid;
>> +       struct {
>> +               u8 edid[256];
>> +               u32 present;
>> +       } vga_edid;
>> +       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 connector_hdmi;
>> +       bool hdmi_port_a;
>> +
>> +       /* i2c clients */
>> +       struct i2c_client *i2c_sdp_io;
>> +       struct i2c_client *i2c_sdp;
>> +       struct i2c_client *i2c_cp;
>> +       struct i2c_client *i2c_vdp;
>> +       struct i2c_client *i2c_afe;
>> +       struct i2c_client *i2c_hdmi;
>> +       struct i2c_client *i2c_repeater;
>> +       struct i2c_client *i2c_edid;
>> +       struct i2c_client *i2c_infoframe;
>> +       struct i2c_client *i2c_cec;
>> +       struct i2c_client *i2c_avlink;
>> +
>> +       /* controls */
>> +       struct v4l2_ctrl *detect_tx_5v_ctrl;
>> +       struct v4l2_ctrl *analog_sampling_phase_ctrl;
>> +       struct v4l2_ctrl *free_run_color_ctrl_manual;
>> +       struct v4l2_ctrl *free_run_color_ctrl;
>> +       struct v4l2_ctrl *rgb_quantization_range_ctrl;
>> +};
>> +
>> +/* Supported CEA and DMT timings */
>> +static const struct v4l2_dv_timings adv7842_timings[] = {
>> +       V4L2_DV_BT_CEA_720X480P59_94,
>> +       V4L2_DV_BT_CEA_720X576P50,
>> +       V4L2_DV_BT_CEA_1280X720P24,
>> +       V4L2_DV_BT_CEA_1280X720P25,
>> +       V4L2_DV_BT_CEA_1280X720P50,
>> +       V4L2_DV_BT_CEA_1280X720P60,
>> +       V4L2_DV_BT_CEA_1920X1080P24,
>> +       V4L2_DV_BT_CEA_1920X1080P25,
>> +       V4L2_DV_BT_CEA_1920X1080P30,
>> +       V4L2_DV_BT_CEA_1920X1080P50,
>> +       V4L2_DV_BT_CEA_1920X1080P60,
>> +
>> +       /* sorted by DMT ID */
>> +       V4L2_DV_BT_DMT_640X350P85,
>> +       V4L2_DV_BT_DMT_640X400P85,
>> +       V4L2_DV_BT_DMT_720X400P85,
>> +       V4L2_DV_BT_DMT_640X480P60,
>> +       V4L2_DV_BT_DMT_640X480P72,
>> +       V4L2_DV_BT_DMT_640X480P75,
>> +       V4L2_DV_BT_DMT_640X480P85,
>> +       V4L2_DV_BT_DMT_800X600P56,
>> +       V4L2_DV_BT_DMT_800X600P60,
>> +       V4L2_DV_BT_DMT_800X600P72,
>> +       V4L2_DV_BT_DMT_800X600P75,
>> +       V4L2_DV_BT_DMT_800X600P85,
>> +       V4L2_DV_BT_DMT_848X480P60,
>> +       V4L2_DV_BT_DMT_1024X768P60,
>> +       V4L2_DV_BT_DMT_1024X768P70,
>> +       V4L2_DV_BT_DMT_1024X768P75,
>> +       V4L2_DV_BT_DMT_1024X768P85,
>> +       V4L2_DV_BT_DMT_1152X864P75,
>> +       V4L2_DV_BT_DMT_1280X768P60_RB,
>> +       V4L2_DV_BT_DMT_1280X768P60,
>> +       V4L2_DV_BT_DMT_1280X768P75,
>> +       V4L2_DV_BT_DMT_1280X768P85,
>> +       V4L2_DV_BT_DMT_1280X800P60_RB,
>> +       V4L2_DV_BT_DMT_1280X800P60,
>> +       V4L2_DV_BT_DMT_1280X800P75,
>> +       V4L2_DV_BT_DMT_1280X800P85,
>> +       V4L2_DV_BT_DMT_1280X960P60,
>> +       V4L2_DV_BT_DMT_1280X960P85,
>> +       V4L2_DV_BT_DMT_1280X1024P60,
>> +       V4L2_DV_BT_DMT_1280X1024P75,
>> +       V4L2_DV_BT_DMT_1280X1024P85,
>> +       V4L2_DV_BT_DMT_1360X768P60,
>> +       V4L2_DV_BT_DMT_1400X1050P60_RB,
>> +       V4L2_DV_BT_DMT_1400X1050P60,
>> +       V4L2_DV_BT_DMT_1400X1050P75,
>> +       V4L2_DV_BT_DMT_1400X1050P85,
>> +       V4L2_DV_BT_DMT_1440X900P60_RB,
>> +       V4L2_DV_BT_DMT_1440X900P60,
>> +       V4L2_DV_BT_DMT_1600X1200P60,
>> +       V4L2_DV_BT_DMT_1680X1050P60_RB,
>> +       V4L2_DV_BT_DMT_1680X1050P60,
>> +       V4L2_DV_BT_DMT_1792X1344P60,
>> +       V4L2_DV_BT_DMT_1856X1392P60,
>> +       V4L2_DV_BT_DMT_1920X1200P60_RB,
>> +       V4L2_DV_BT_DMT_1366X768P60,
>> +       V4L2_DV_BT_DMT_1920X1080P60,
>> +       { },
>> +};
>> +
> why not use the dv_timings helpers ?

I'm planning to once the helpers are merged.

> 
>> +struct adv7842_video_standards {
>> +       struct v4l2_dv_timings timings;
>> +       u8 vid_std;
>> +       u8 v_freq;
>> +};
>> +
>> +/* sorted by number of lines */
>> +static const struct adv7842_video_standards adv7842_prim_mode_comp[] = {
>> +       /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
>> +       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
>> +       { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
>> +       { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
>> +       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
>> +       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
>> +       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
>> +       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
>> +       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
>> +       /* TODO add 1920x1080P60_RB (CVT timing) */
>> +       { },
>> +};
>> +
>> +/* sorted by number of lines */
>> +static const struct adv7842_video_standards adv7842_prim_mode_gr[] = {
>> +       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
>> +       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
>> +       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
>> +       { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
>> +       { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
>> +       { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
>> +       { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
>> +       { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
>> +       /* TODO add 1600X1200P60_RB (not a DMT timing) */
>> +       { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
>> +       { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
>> +       { },
>> +};
>> +
>> +/* sorted by number of lines */
>> +static const struct adv7842_video_standards adv7842_prim_mode_hdmi_comp[] = 
>> {
>> +       { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
>> +       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
>> +       { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
>> +       { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
>> +       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
>> +       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
>> +       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
>> +       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
>> +       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
>> +       { },
>> +};
>> +
>> +/* sorted by number of lines */
>> +static const struct adv7842_video_standards adv7842_prim_mode_hdmi_gr[] = {
>> +       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
>> +       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
>> +       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
>> +       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
>> +       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
>> +       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
>> +       { },
>> +};
>> +
>> +/* ----------------------------------------------------------------------- 
>> */
>> +
>> +static inline struct adv7842_state *to_state(struct v4l2_subdev *sd)
>> +{
>> +       return container_of(sd, struct adv7842_state, sd);
>> +}
>> +
>> +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
>> +{
>> +       return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
>> +}
>> +
>> +static inline unsigned hblanking(const struct v4l2_bt_timings *t)
>> +{
>> +       return t->hfrontporch + t->hsync + t->hbackporch;
>> +}
>> +
>> +static inline unsigned htotal(const struct v4l2_bt_timings *t)
>> +{
>> +       return t->width + t->hfrontporch + t->hsync + t->hbackporch;
>> +}
>> +
>> +static inline unsigned vblanking(const struct v4l2_bt_timings *t)
>> +{
>> +       return t->vfrontporch + t->vsync + t->vbackporch;
>> +}
>> +
>> +static inline unsigned vtotal(const struct v4l2_bt_timings *t)
>> +{
>> +       return t->height + t->vfrontporch + t->vsync + t->vbackporch;
>> +}
>> +
> 
> Replacing the above with V4L2_DV_BT_BLANKING/FRAME defines ?

Ditto, waiting for that to be merged first.

> 
> 

<snip>

>> +static int adv7842_probe(struct i2c_client *client,
>> +                        const struct i2c_device_id *id)
>> +{
>> +       struct adv7842_state *state;
>> +       struct adv7842_platform_data *pdata = client->dev.platform_data;
>> +       struct v4l2_ctrl_handler *hdl;
>> +       struct v4l2_subdev *sd;
>> +       u16 rev;
>> +       int err;
>> +
>> +       /* Check if the adapter supports the needed features */
>> +       if (!i2c_check_functionality(client->adapter, 
>> I2C_FUNC_SMBUS_BYTE_DATA))
>> +               return -EIO;
>> +
>> +       v4l_dbg(1, debug, client, "detecting adv7842 client on address 
>> 0x%x\n",
>> +               client->addr << 1);
>> +
>> +       if (!pdata) {
>> +               v4l_err(client, "No platform data!\n");
>> +               return -ENODEV;
>> +       }
>> +
>> +       state = kzalloc(sizeof(struct adv7842_state), GFP_KERNEL);
> devm*() instead ?

Good point. Will do.

> 
>> +       if (!state) {
>> +               v4l_err(client, "Could not allocate adv7842_state 
>> memory!\n");
>> +               return -ENOMEM;
>> +       }
>> +
>> +       sd = &state->sd;
>> +       v4l2_i2c_subdev_init(sd, client, &adv7842_ops);
>> +       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
>> +       state->connector_hdmi = pdata->connector_hdmi;
>> +       state->mode = pdata->mode;
>> +
>> +       state->hdmi_port_a = true;
>> +
>> +       /* i2c access to adv7842? */
>> +       rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 |
>> +               adv_smbus_read_byte_data_check(client, 0xeb, false);
>> +       if (rev != 0x2012) {
>> +               v4l2_info(sd, "got rev=0x%04x on first read attempt\n", rev);
>> +               rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 
>> 8 |
>> +                       adv_smbus_read_byte_data_check(client, 0xeb, false);
>> +       }
>> +       if (rev != 0x2012) {
>> +               v4l2_info(sd, "not an adv7842 on address 0x%x 
>> (rev=0x%04x)\n",
>> +                         client->addr << 1, rev);
>> +               err = -ENODEV;
>> +               goto err_state;
>> +       }
>> +
>> +       if (pdata->chip_reset)
>> +               main_reset(sd);
>> +
>> +       /* control handlers */
>> +       hdl = &state->hdl;
>> +       v4l2_ctrl_handler_init(hdl, 6);
>> +
>> +       /* add in ascending ID order */
>> +       v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops,
>> +                         V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
>> +       v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops,
>> +                         V4L2_CID_CONTRAST, 0, 255, 1, 128);
>> +       v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops,
>> +                         V4L2_CID_SATURATION, 0, 255, 1, 128);
>> +       v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops,
>> +                         V4L2_CID_HUE, 0, 128, 1, 0);
>> +
>> +       /* custom controls */
>> +       state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
>> +                       V4L2_CID_DV_RX_POWER_PRESENT, 0, 3, 0, 0);
>> +       state->analog_sampling_phase_ctrl = v4l2_ctrl_new_custom(hdl,
>> +                       &adv7842_ctrl_analog_sampling_phase, NULL);
>> +       state->free_run_color_ctrl_manual = v4l2_ctrl_new_custom(hdl,
>> +                       &adv7842_ctrl_free_run_color_manual, NULL);
>> +       state->free_run_color_ctrl = v4l2_ctrl_new_custom(hdl,
>> +                       &adv7842_ctrl_free_run_color, NULL);
>> +       state->rgb_quantization_range_ctrl =
>> +               v4l2_ctrl_new_std_menu(hdl, &adv7842_ctrl_ops,
>> +                       V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
>> +                       0, V4L2_DV_RGB_RANGE_AUTO);
>> +       sd->ctrl_handler = hdl;
>> +       if (hdl->error) {
>> +               err = hdl->error;
>> +               goto err_hdl;
>> +       }
>> +
>> +       if (adv7842_s_detect_tx_5v_ctrl(sd)) {
>> +               err = -ENODEV;
>> +               goto err_hdl;
>> +       }
>> +
>> +       state->i2c_avlink = adv7842_dummy_client(sd, pdata->i2c_avlink, 
>> 0xf3);
>> +       state->i2c_cec = adv7842_dummy_client(sd, pdata->i2c_cec, 0xf4);
>> +       state->i2c_infoframe = adv7842_dummy_client(sd, 
>> pdata->i2c_infoframe, 0xf5);
>> +       state->i2c_sdp_io = adv7842_dummy_client(sd, pdata->i2c_sdp_io, 
>> 0xf2);
>> +       state->i2c_sdp = adv7842_dummy_client(sd, pdata->i2c_sdp, 0xf1);
>> +       state->i2c_afe = adv7842_dummy_client(sd, pdata->i2c_afe, 0xf8);
>> +       state->i2c_repeater = adv7842_dummy_client(sd, pdata->i2c_repeater, 
>> 0xf9);
>> +       state->i2c_edid = adv7842_dummy_client(sd, pdata->i2c_edid, 0xfa);
>> +       state->i2c_hdmi = adv7842_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
>> +       state->i2c_cp = adv7842_dummy_client(sd, pdata->i2c_cp, 0xfd);
>> +       state->i2c_vdp = adv7842_dummy_client(sd, pdata->i2c_vdp, 0xfe);
>> +       if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe ||
>> +           !state->i2c_sdp_io || !state->i2c_sdp || !state->i2c_afe ||
>> +           !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
>> +           !state->i2c_cp || !state->i2c_vdp) {
>> +               err = -ENOMEM;
>> +               v4l2_err(sd, "failed to create all i2c clients\n");
>> +               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);
>> +
>> +       state->pad.flags = MEDIA_PAD_FL_SOURCE;
>> +       err = media_entity_init(&sd->entity, 1, &state->pad, 0);
>> +       if (err)
>> +               goto err_work_queues;
>> +
>> +       err = adv7842_core_init(sd, pdata);
>> +       if (err)
>> +               goto err_entity;
>> +
>> +       v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
>> +                 client->addr << 1, client->adapter->name);
>> +       return 0;
>> +
>> +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(state);
>> +err_hdl:
>> +       v4l2_ctrl_handler_free(hdl);
>> +err_state:
>> +       kfree(state);
>> +       return err;
>> +}
>> +
>> +/* ----------------------------------------------------------------------- 
>> */
>> +
>> +static int adv7842_remove(struct i2c_client *client)
>> +{
>> +       struct v4l2_subdev *sd = i2c_get_clientdata(client);
>> +       struct adv7842_state *state = to_state(sd);
>> +
>> +       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(to_state(sd));
>> +       v4l2_ctrl_handler_free(sd->ctrl_handler);
>> +       kfree(to_state(sd));
>> +       return 0;
>> +}
>> +
>> +/* ----------------------------------------------------------------------- 
>> */
>> +
>> +static struct i2c_device_id adv7842_id[] = {
>> +       { "adv7842", 0 },
>> +       { }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, adv7842_id);
>> +
>> +/* ----------------------------------------------------------------------- 
>> */
>> +
>> +static struct i2c_driver adv7842_driver = {
>> +       .driver = {
>> +               .owner = THIS_MODULE,
>> +               .name = "adv7842",
>> +       },
>> +       .probe = adv7842_probe,
>> +       .remove = adv7842_remove,
>> +       .id_table = adv7842_id,
>> +};
>> +
>> +module_i2c_driver(adv7842_driver);

Thanks!

        Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to