]> Pileus Git - ~andy/linux/blobdiff - drivers/media/i2c/soc_camera/mt9m111.c
[media] mt9m111: fix Oops - initialise context before dereferencing
[~andy/linux] / drivers / media / i2c / soc_camera / mt9m111.c
index 62fd94af599be4010e72ccde0bf6fa61f7794a5f..2902ba633da637e0d06a0b7bbc653fef877a1fd9 100644 (file)
@@ -24,7 +24,8 @@
 /*
  * MT9M111, MT9M112 and MT9M131:
  * i2c address is 0x48 or 0x5d (depending on SADDR pin)
- * The platform has to define i2c_board_info and call i2c_register_board_info()
+ * The platform has to define struct i2c_board_info objects and link to them
+ * from struct soc_camera_host_desc
  */
 
 /*
@@ -700,11 +701,11 @@ static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
        return reg_write(GLOBAL_GAIN, val);
 }
 
-static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
+static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
 
-       if (on)
+       if (val == V4L2_EXPOSURE_AUTO)
                return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
        return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 }
@@ -784,8 +785,6 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
-       /* Default HIGHPOWER context */
-       mt9m111->ctx = &context_b;
        ret = mt9m111_enable(mt9m111);
        if (!ret)
                ret = mt9m111_reset(mt9m111);
@@ -799,17 +798,17 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
 static int mt9m111_power_on(struct mt9m111 *mt9m111)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
        int ret;
 
-       ret = soc_camera_power_on(&client->dev, icl);
+       ret = soc_camera_power_on(&client->dev, ssdd);
        if (ret < 0)
                return ret;
 
        ret = mt9m111_resume(mt9m111);
        if (ret < 0) {
                dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
-               soc_camera_power_off(&client->dev, icl);
+               soc_camera_power_off(&client->dev, ssdd);
        }
 
        return ret;
@@ -818,10 +817,10 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)
 static void mt9m111_power_off(struct mt9m111 *mt9m111)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
 
        mt9m111_suspend(mt9m111);
-       soc_camera_power_off(&client->dev, icl);
+       soc_camera_power_off(&client->dev, ssdd);
 }
 
 static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
@@ -879,13 +878,13 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
                                struct v4l2_mbus_config *cfg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
 
        cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
                V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
                V4L2_MBUS_DATA_ACTIVE_HIGH;
        cfg->type = V4L2_MBUS_PARALLEL;
-       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+       cfg->flags = soc_camera_apply_board_flags(ssdd, cfg);
 
        return 0;
 }
@@ -956,10 +955,10 @@ static int mt9m111_probe(struct i2c_client *client,
 {
        struct mt9m111 *mt9m111;
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
        int ret;
 
-       if (!icl) {
+       if (!ssdd) {
                dev_err(&client->dev, "mt9m111: driver needs platform data\n");
                return -EINVAL;
        }
@@ -970,10 +969,13 @@ static int mt9m111_probe(struct i2c_client *client,
                return -EIO;
        }
 
-       mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL);
+       mt9m111 = devm_kzalloc(&client->dev, sizeof(struct mt9m111), GFP_KERNEL);
        if (!mt9m111)
                return -ENOMEM;
 
+       /* Default HIGHPOWER context */
+       mt9m111->ctx = &context_b;
+
        v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
        v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
        v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
@@ -988,12 +990,8 @@ static int mt9m111_probe(struct i2c_client *client,
                        &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
                        V4L2_EXPOSURE_AUTO);
        mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
-       if (mt9m111->hdl.error) {
-               int err = mt9m111->hdl.error;
-
-               kfree(mt9m111);
-               return err;
-       }
+       if (mt9m111->hdl.error)
+               return mt9m111->hdl.error;
 
        /* Second stage probe - when a capture adapter is there */
        mt9m111->rect.left      = MT9M111_MIN_DARK_COLS;
@@ -1005,10 +1003,8 @@ static int mt9m111_probe(struct i2c_client *client,
        mutex_init(&mt9m111->power_lock);
 
        ret = mt9m111_video_probe(client);
-       if (ret) {
+       if (ret)
                v4l2_ctrl_handler_free(&mt9m111->hdl);
-               kfree(mt9m111);
-       }
 
        return ret;
 }
@@ -1019,7 +1015,6 @@ static int mt9m111_remove(struct i2c_client *client)
 
        v4l2_device_unregister_subdev(&mt9m111->subdev);
        v4l2_ctrl_handler_free(&mt9m111->hdl);
-       kfree(mt9m111);
 
        return 0;
 }