diff options
Diffstat (limited to 'drivers/media/video/mt9v022.c')
-rw-r--r-- | drivers/media/video/mt9v022.c | 167 |
1 files changed, 68 insertions, 99 deletions
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 959cc299f1ae..3cb9f0f1e256 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -14,13 +14,13 @@ #include <linux/delay.h> #include <linux/log2.h> -#include <media/v4l2-common.h> +#include <media/v4l2-subdev.h> #include <media/v4l2-chip-ident.h> #include <media/soc_camera.h> /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define ctruct i2c_board_info objects and link to them + * from struct soc_camera_link */ static char *sensor_type; module_param(sensor_type, charp, S_IRUGO); @@ -85,10 +85,16 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { }; struct mt9v022 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; +static struct mt9v022 *to_mt9v022(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9v022, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -126,26 +132,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - - /* - * The camera could have been already on, we hard-reset it additionally, - * if available. Soft reset is done in video_probe(). - */ - if (icl->reset) - icl->reset(&client->dev); - /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ @@ -169,37 +158,19 @@ static int mt9v022_init(struct soc_camera_device *icd) return ret; } -static int mt9v022_release(struct soc_camera_device *icd) +static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); - if (icl->power) - icl->power(&client->dev, 0); - - return 0; -} - -static int mt9v022_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to master "normal" mode */ - mt9v022->chip_control &= ~0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) - return -EIO; - return 0; -} + if (enable) + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + else + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; -static int mt9v022_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to snapshot mode */ - mt9v022->chip_control |= 0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; } @@ -208,7 +179,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; @@ -320,11 +291,11 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -357,9 +328,10 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, return mt9v022_set_crop(icd, &rect); } -static int mt9v022_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, @@ -369,11 +341,11 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9v022_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9v022_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -388,10 +360,10 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9v022_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -408,10 +380,10 @@ static int mt9v022_get_register(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -480,35 +452,18 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9v022_ops = { - .owner = THIS_MODULE, .init = mt9v022_init, - .release = mt9v022_release, - .start_capture = mt9v022_start_capture, - .stop_capture = mt9v022_stop_capture, .set_crop = mt9v022_set_crop, - .set_fmt = mt9v022_set_fmt, - .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), - .get_control = mt9v022_get_control, - .set_control = mt9v022_set_control, - .get_chip_id = mt9v022_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9v022_get_register, - .set_register = mt9v022_set_register, -#endif }; -static int mt9v022_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int data; switch (ctrl->id) { @@ -540,15 +495,14 @@ static int mt9v022_get_control(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { int data; - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); - if (!qctrl) return -EINVAL; @@ -644,7 +598,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, static int mt9v022_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; @@ -654,11 +608,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); @@ -723,8 +672,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, "monochrome" : "colour"); ei2c: - soc_camera_video_stop(icd); - return ret; } @@ -739,6 +686,27 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { + .g_ctrl = mt9v022_g_ctrl, + .s_ctrl = mt9v022_s_ctrl, + .g_chip_ident = mt9v022_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v022_g_register, + .s_register = mt9v022_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { + .s_stream = mt9v022_s_stream, + .s_fmt = mt9v022_s_fmt, + .try_fmt = mt9v022_try_fmt, +}; + +static struct v4l2_subdev_ops mt9v022_subdev_ops = { + .core = &mt9v022_subdev_core_ops, + .video = &mt9v022_subdev_video_ops, +}; + static int mt9v022_probe(struct i2c_client *client, const struct i2c_device_id *did) { @@ -769,8 +737,9 @@ static int mt9v022_probe(struct i2c_client *client, if (!mt9v022) return -ENOMEM; + v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops); + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - i2c_set_clientdata(client, mt9v022); icd->ops = &mt9v022_ops; icd->x_min = 1; @@ -795,7 +764,7 @@ static int mt9v022_probe(struct i2c_client *client, static int mt9v022_remove(struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; |