[media] m5mols: Move the control handler initialization to probe()
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Sat, 3 Dec 2011 17:53:30 +0000 (14:53 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 30 Dec 2011 16:38:39 +0000 (14:38 -0200)
This is prerequisite for enabling the sub-device node.

The control handler is now initialized in driver's probe callback
in order to allow the user space access controls before the device
power is enabled with s_power. This is needed due to s_power being
currently called only by the host driver.

It also adds the subdev internal operations, only open() for now
for the TRY format initialization.

Acked-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/m5mols/m5mols_core.c

index 9966d2e..ea594cf 100644 (file)
@@ -685,16 +685,25 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct v4l2_subdev *sd = to_sd(ctrl);
        struct m5mols_info *info = to_m5mols(sd);
-       int isp_state = info->mode;
-       int ret = 0;
+       int ispstate = info->mode;
+       int ret;
 
-       ret = m5mols_mode(info, REG_PARAMETER);
-       if (!ret)
-               ret = m5mols_set_ctrl(ctrl);
-       if (!ret)
-               ret = m5mols_mode(info, isp_state);
+       /*
+        * If needed, defer restoring the controls until
+        * the device is fully initialized.
+        */
+       if (!info->isp_ready) {
+               info->ctrl_sync = 0;
+               return 0;
+       }
 
-       return ret;
+       ret = m5mols_mode(info, REG_PARAMETER);
+       if (ret < 0)
+               return ret;
+       ret = m5mols_set_ctrl(ctrl);
+       if (ret < 0)
+               return ret;
+       return m5mols_mode(info, ispstate);
 }
 
 static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
@@ -855,8 +864,6 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
                ret = m5mols_sensor_power(info, true);
                if (!ret)
                        ret = m5mols_fw_start(sd);
-               if (!ret)
-                       ret = m5mols_init_controls(info);
                if (ret)
                        return ret;
 
@@ -881,10 +888,7 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
        }
 
        ret = m5mols_sensor_power(info, false);
-       if (!ret) {
-               v4l2_ctrl_handler_free(&info->handle);
-               info->ctrl_sync = 0;
-       }
+       info->ctrl_sync = 0;
 
        return ret;
 }
@@ -910,6 +914,21 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = {
        .log_status     = m5mols_log_status,
 };
 
+/*
+ * V4L2 subdev internal operations
+ */
+static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+       *format = m5mols_default_ffmt[0];
+       return 0;
+}
+
+static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
+       .open           = m5mols_open,
+};
+
 static const struct v4l2_subdev_ops m5mols_ops = {
        .core           = &m5mols_core_ops,
        .pad            = &m5mols_pad_ops,
@@ -973,6 +992,7 @@ static int __devinit m5mols_probe(struct i2c_client *client,
        strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
        v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
 
+       sd->internal_ops = &m5mols_subdev_internal_ops;
        info->pad.flags = MEDIA_PAD_FL_SOURCE;
        ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
        if (ret < 0)
@@ -988,7 +1008,17 @@ static int __devinit m5mols_probe(struct i2c_client *client,
        }
        info->res_type = M5MOLS_RESTYPE_MONITOR;
 
-       return 0;
+       ret = m5mols_sensor_power(info, true);
+       if (ret)
+               goto out_me;
+
+       ret = m5mols_fw_start(sd);
+       if (!ret)
+               ret = m5mols_init_controls(info);
+
+       m5mols_sensor_power(info, false);
+       if (!ret)
+               return 0;
 out_me:
        media_entity_cleanup(&sd->entity);
 out_reg:
@@ -1006,6 +1036,7 @@ static int __devexit m5mols_remove(struct i2c_client *client)
        struct m5mols_info *info = to_m5mols(sd);
 
        v4l2_device_unregister_subdev(sd);
+       v4l2_ctrl_handler_free(sd->ctrl_handler);
        free_irq(client->irq, sd);
 
        regulator_bulk_free(ARRAY_SIZE(supplies), supplies);