V4L/DVB (10655): tvp514x: make the module aware of rich people
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Mon, 12 Jan 2009 09:17:43 +0000 (06:17 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:42:51 +0000 (12:42 -0300)
because they might design two of those chips on a single board.
You never know.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/tvp514x.c

index 5f4cbc2b23c18f20cccabff6ec83aa80fd58ca51..f0b2b8ed2fe46b6024749e4216b95e71963c7675 100644 (file)
@@ -86,9 +86,12 @@ struct tvp514x_std_info {
        struct v4l2_standard standard;
 };
 
+static struct tvp514x_reg tvp514x_reg_list_default[0x40];
 /**
- * struct tvp514x_decoded - TVP5146/47 decoder object
+ * struct tvp514x_decoder - TVP5146/47 decoder object
  * @v4l2_int_device: Slave handle
+ * @tvp514x_slave: Slave pointer which is used by @v4l2_int_device
+ * @tvp514x_regs: copy of hw's regs with preset values.
  * @pdata: Board specific
  * @client: I2C client data
  * @id: Entry from I2C table
@@ -103,7 +106,9 @@ struct tvp514x_std_info {
  * @route: input and output routing at chip level
  */
 struct tvp514x_decoder {
-       struct v4l2_int_device *v4l2_int_device;
+       struct v4l2_int_device v4l2_int_device;
+       struct v4l2_int_slave tvp514x_slave;
+       struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)];
        const struct tvp514x_platform_data *pdata;
        struct i2c_client *client;
 
@@ -124,7 +129,7 @@ struct tvp514x_decoder {
 };
 
 /* TVP514x default register values */
-static struct tvp514x_reg tvp514x_reg_list[] = {
+static struct tvp514x_reg tvp514x_reg_list_default[] = {
        {TOK_WRITE, REG_INPUT_SEL, 0x05},       /* Composite selected */
        {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F},
        {TOK_WRITE, REG_VIDEO_STD, 0x00},       /* Auto mode */
@@ -422,7 +427,7 @@ static int tvp514x_configure(struct tvp514x_decoder *decoder)
 
        /* common register initialization */
        err =
-           tvp514x_write_regs(decoder->client, tvp514x_reg_list);
+           tvp514x_write_regs(decoder->client, decoder->tvp514x_regs);
        if (err)
                return err;
 
@@ -580,7 +585,8 @@ static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id)
                return err;
 
        decoder->current_std = i;
-       tvp514x_reg_list[REG_VIDEO_STD].val = decoder->std_list[i].video_std;
+       decoder->tvp514x_regs[REG_VIDEO_STD].val =
+               decoder->std_list[i].video_std;
 
        v4l_dbg(1, debug, decoder->client, "Standard set to: %s",
                        decoder->std_list[i].standard.name);
@@ -625,8 +631,8 @@ static int ioctl_s_routing(struct v4l2_int_device *s,
        if (err)
                return err;
 
-       tvp514x_reg_list[REG_INPUT_SEL].val = input_sel;
-       tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val = output_sel;
+       decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
+       decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
 
        /* Clear status */
        msleep(LOCK_RETRY_DELAY);
@@ -779,16 +785,16 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
-               ctrl->value = tvp514x_reg_list[REG_BRIGHTNESS].val;
+               ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val;
                break;
        case V4L2_CID_CONTRAST:
-               ctrl->value = tvp514x_reg_list[REG_CONTRAST].val;
+               ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val;
                break;
        case V4L2_CID_SATURATION:
-               ctrl->value = tvp514x_reg_list[REG_SATURATION].val;
+               ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val;
                break;
        case V4L2_CID_HUE:
-               ctrl->value = tvp514x_reg_list[REG_HUE].val;
+               ctrl->value = decoder->tvp514x_regs[REG_HUE].val;
                if (ctrl->value == 0x7F)
                        ctrl->value = 180;
                else if (ctrl->value == 0x80)
@@ -798,7 +804,7 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
 
                break;
        case V4L2_CID_AUTOGAIN:
-               ctrl->value = tvp514x_reg_list[REG_AFE_GAIN_CTRL].val;
+               ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val;
                if ((ctrl->value & 0x3) == 3)
                        ctrl->value = 1;
                else
@@ -848,7 +854,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
                                value);
                if (err)
                        return err;
-               tvp514x_reg_list[REG_BRIGHTNESS].val = value;
+               decoder->tvp514x_regs[REG_BRIGHTNESS].val = value;
                break;
        case V4L2_CID_CONTRAST:
                if (ctrl->value < 0 || ctrl->value > 255) {
@@ -861,7 +867,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
                                value);
                if (err)
                        return err;
-               tvp514x_reg_list[REG_CONTRAST].val = value;
+               decoder->tvp514x_regs[REG_CONTRAST].val = value;
                break;
        case V4L2_CID_SATURATION:
                if (ctrl->value < 0 || ctrl->value > 255) {
@@ -874,7 +880,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
                                value);
                if (err)
                        return err;
-               tvp514x_reg_list[REG_SATURATION].val = value;
+               decoder->tvp514x_regs[REG_SATURATION].val = value;
                break;
        case V4L2_CID_HUE:
                if (value == 180)
@@ -893,7 +899,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
                                value);
                if (err)
                        return err;
-               tvp514x_reg_list[REG_HUE].val = value;
+               decoder->tvp514x_regs[REG_HUE].val = value;
                break;
        case V4L2_CID_AUTOGAIN:
                if (value == 1)
@@ -910,7 +916,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl)
                                value);
                if (err)
                        return err;
-               tvp514x_reg_list[REG_AFE_GAIN_CTRL].val = value;
+               decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value;
                break;
        default:
                v4l_err(decoder->client,
@@ -1275,7 +1281,7 @@ static int ioctl_init(struct v4l2_int_device *s)
        struct tvp514x_decoder *decoder = s->priv;
 
        /* Set default standard to auto */
-       tvp514x_reg_list[REG_VIDEO_STD].val =
+       decoder->tvp514x_regs[REG_VIDEO_STD].val =
            VIDEO_STD_AUTO_SWITCH_BIT;
 
        return tvp514x_configure(decoder);
@@ -1344,11 +1350,6 @@ static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = {
                (v4l2_int_ioctl_func *) ioctl_s_routing},
 };
 
-static struct v4l2_int_slave tvp514x_slave = {
-       .ioctls = tvp514x_ioctl_desc,
-       .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc),
-};
-
 static struct tvp514x_decoder tvp514x_dev = {
        .state = STATE_NOT_DETECTED,
 
@@ -1369,17 +1370,15 @@ static struct tvp514x_decoder tvp514x_dev = {
        .current_std = STD_NTSC_MJ,
        .std_list = tvp514x_std_list,
        .num_stds = ARRAY_SIZE(tvp514x_std_list),
-
-};
-
-static struct v4l2_int_device tvp514x_int_device = {
-       .module = THIS_MODULE,
-       .name = TVP514X_MODULE_NAME,
-       .priv = &tvp514x_dev,
-       .type = v4l2_int_type_slave,
-       .u = {
-             .slave = &tvp514x_slave,
-             },
+       .v4l2_int_device = {
+               .module = THIS_MODULE,
+               .name = TVP514X_MODULE_NAME,
+               .type = v4l2_int_type_slave,
+       },
+       .tvp514x_slave = {
+               .ioctls = tvp514x_ioctl_desc,
+               .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc),
+       },
 };
 
 /**
@@ -1392,26 +1391,37 @@ static struct v4l2_int_device tvp514x_int_device = {
 static int
 tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-       struct tvp514x_decoder *decoder = &tvp514x_dev;
+       struct tvp514x_decoder *decoder;
        int err;
 
        /* Check if the adapter supports the needed features */
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -EIO;
 
-       decoder->pdata = client->dev.platform_data;
-       if (!decoder->pdata) {
+       decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
+       if (!decoder)
+               return -ENOMEM;
+
+       if (!client->dev.platform_data) {
                v4l_err(client, "No platform data!!\n");
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_free;
        }
+
+       *decoder = tvp514x_dev;
+       decoder->v4l2_int_device.priv = decoder;
+       decoder->pdata = client->dev.platform_data;
+       decoder->v4l2_int_device.u.slave = &decoder->tvp514x_slave;
+       memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default,
+                       sizeof(tvp514x_reg_list_default));
        /*
         * Fetch platform specific data, and configure the
         * tvp514x_reg_list[] accordingly. Since this is one
         * time configuration, no need to preserve.
         */
-       tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |=
+       decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |=
                        (decoder->pdata->clk_polarity << 1);
-       tvp514x_reg_list[REG_SYNC_CONTROL].val |=
+       decoder->tvp514x_regs[REG_SYNC_CONTROL].val |=
                        ((decoder->pdata->hs_polarity << 2) |
                        (decoder->pdata->vs_polarity << 3));
        /*
@@ -1419,23 +1429,27 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
         */
        decoder->id = (struct i2c_device_id *)id;
        /* Attach to Master */
-       strcpy(tvp514x_int_device.u.slave->attach_to, decoder->pdata->master);
-       decoder->v4l2_int_device = &tvp514x_int_device;
+       strcpy(decoder->v4l2_int_device.u.slave->attach_to,
+                       decoder->pdata->master);
        decoder->client = client;
        i2c_set_clientdata(client, decoder);
 
        /* Register with V4L2 layer as slave device */
-       err = v4l2_int_device_register(decoder->v4l2_int_device);
+       err = v4l2_int_device_register(&decoder->v4l2_int_device);
        if (err) {
                i2c_set_clientdata(client, NULL);
                v4l_err(client,
                        "Unable to register to v4l2. Err[%d]\n", err);
+               goto out_free;
 
        } else
                v4l_info(client, "Registered to v4l2 master %s!!\n",
                                decoder->pdata->master);
-
        return 0;
+
+out_free:
+       kfree(decoder);
+       return err;
 }
 
 /**
@@ -1452,9 +1466,9 @@ static int __exit tvp514x_remove(struct i2c_client *client)
        if (!client->adapter)
                return -ENODEV; /* our client isn't attached */
 
-       v4l2_int_device_unregister(decoder->v4l2_int_device);
+       v4l2_int_device_unregister(&decoder->v4l2_int_device);
        i2c_set_clientdata(client, NULL);
-
+       kfree(decoder);
        return 0;
 }
 /*