From ada365c021ff668eae8fa17042a39d33a4cdf4e1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: soc-camera: separate S_FMT and S_CROP operations From: Guennadi Liakhovetski As host and camera drivers become more complex, differences between S_FMT and S_CROP functionality grow, this patch separates them. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 19 +++- drivers/media/video/mt9m111.c | 56 +++++++--- drivers/media/video/mt9t031.c | 84 ++++++++++------ drivers/media/video/mt9v022.c | 62 +++++++---- drivers/media/video/mx3_camera.c | 157 +++++++++++++++++----------- drivers/media/video/ov772x.c | 31 +++++- drivers/media/video/pxa_camera.c | 67 +++++++++--- drivers/media/video/sh_mobile_ceu_camera.c | 17 ++- drivers/media/video/soc_camera.c | 20 ++-- drivers/media/video/soc_camera_platform.c | 9 ++- drivers/media/video/tw9910.c | 45 +++++--- include/media/soc_camera.h | 6 +- 12 files changed, 381 insertions(+), 192 deletions(-) --- linux/drivers/media/video/ov772x.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2f3313524..73d447247 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -781,11 +781,9 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, - struct v4l2_rect *rect) +static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, + u32 pixfmt) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; u8 val; int i; @@ -806,7 +804,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, /* * select win */ - priv->win = ov772x_select_win(rect->width, rect->height); + priv->win = ov772x_select_win(width, height); /* * reset hardware @@ -870,6 +868,28 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + if (!priv->fmt) + return -EINVAL; + + return ov772x_set_params(priv, rect->width, rect->height, + priv->fmt->fourcc); +} + +static int ov772x_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + + return ov772x_set_params(priv, pix->width, pix->height, + pix->pixelformat); +} + static int ov772x_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -959,6 +979,7 @@ static struct soc_camera_ops ov772x_ops = { .release = ov772x_release, .start_capture = ov772x_start_capture, .stop_capture = ov772x_stop_capture, + .set_crop = ov772x_set_crop, .set_fmt = ov772x_set_fmt, .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, -- cgit v1.2.3 From 823ea474f6ef741eb378f550d4c7b2aaf233b23f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: ov772x: use soft sleep mode in stop_capture From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) --- linux/drivers/media/video/ov772x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 73d447247..cde3a1019 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -646,6 +646,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) return -EPERM; } + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); @@ -654,6 +656,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) static int ov772x_stop_capture(struct soc_camera_device *icd) { + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } -- cgit v1.2.3 From 2adb7ebfe8e864f77d3f58a65523a9766f86137a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: ov772x: wrong pointer for soc_camera_link is modified From: Kuninori Morimoto priv->client->dev.platrom_data mean ov772x_camera_info in ov772x driver. So, struct soc_camera_link doesn't exist there. This patch modify this bug. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/ov772x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index cde3a1019..d3e0bd30e 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -670,7 +670,7 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - struct soc_camera_link *icl = priv->client->dev.platform_data; + struct soc_camera_link *icl = &priv->info->link; unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; -- cgit v1.2.3 From 5e8385995e4d6c1811a1b8e5e819094658cdb77c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: ov772x: add edge contrl support From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 63 +++++++++++++++++++++++++++++++++++++++-- include/media/ov772x.h | 35 +++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 63 +++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index d3e0bd30e..b17a7400d 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -169,11 +169,11 @@ #define GAM15 0x8C /* Gamma Curve 15th segment input end point */ #define SLOP 0x8D /* Gamma curve highest segment slope */ #define DNSTH 0x8E /* De-noise threshold */ -#define EDGE0 0x8F /* Edge enhancement control 0 */ -#define EDGE1 0x90 /* Edge enhancement control 1 */ +#define EDGE_STRNGT 0x8F /* Edge strength control when manual mode */ +#define EDGE_TRSHLD 0x90 /* Edge threshold control when manual mode */ #define DNSOFF 0x91 /* Auto De-noise threshold control */ -#define EDGE2 0x92 /* Edge enhancement strength low point control */ -#define EDGE3 0x93 /* Edge enhancement strength high point control */ +#define EDGE_UPPER 0x92 /* Edge strength upper limit when Auto mode */ +#define EDGE_LOWER 0x93 /* Edge strength lower limit when Auto mode */ #define MTX1 0x94 /* Matrix coefficient 1 */ #define MTX2 0x95 /* Matrix coefficient 2 */ #define MTX3 0x96 /* Matrix coefficient 3 */ @@ -358,6 +358,14 @@ #define VOSZ_VGA 0xF0 #define VOSZ_QVGA 0x78 +/* DSPAUTO (DSP Auto Function ON/OFF Control) */ +#define AWB_ACTRL 0x80 /* AWB auto threshold control */ +#define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */ +#define EDGE_ACTRL 0x20 /* Edge enhancement auto strength control */ +#define UV_ACTRL 0x10 /* UV adjust auto slope control */ +#define SCAL0_ACTRL 0x08 /* Auto scaling factor control */ +#define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */ + /* * ID */ @@ -815,6 +823,53 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, */ ov772x_reset(priv->client); + /* + * Edge Ctrl + */ + if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) { + + /* + * Manual Edge Control Mode + * + * Edge auto strength bit is set by default. + * Remove it when manual mode. + */ + + ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_TRSHLD, EDGE_THRESHOLD_MASK, + priv->info->edgectrl.threshold); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_STRNGT, EDGE_STRENGTH_MASK, + priv->info->edgectrl.strength); + if (ret < 0) + goto ov772x_set_fmt_error; + + } else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) { + /* + * Auto Edge Control Mode + * + * set upper and lower limit + */ + ret = ov772x_mask_set(priv->client, + EDGE_UPPER, EDGE_UPPER_MASK, + priv->info->edgectrl.upper); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_LOWER, EDGE_LOWER_MASK, + priv->info->edgectrl.lower); + if (ret < 0) + goto ov772x_set_fmt_error; + } + /* * set size format */ -- cgit v1.2.3 From e1afff6e5f2d6b35928ab6651ac5705659713ca0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 15:27:33 -0300 Subject: backport commit 0a861e9eb76c68b23be1aa4758269c5b412089a9 From: Mauro Carvalho Chehab kernel-sync: Author: Guennadi Liakhovetski Date: Tue May 12 15:13:32 2009 +0000 soc-camera: unify i2c camera device platform data Unify i2c camera device platform data to point to struct soc_camera_link for a smooth transition to soc-camera as a platform driver. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ov772x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index b17a7400d..4b0363940 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1071,10 +1071,12 @@ static int ov772x_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int ret; - info = client->dev.platform_data; - if (!info) + if (!client->dev.platform_data) return -EINVAL; + info = container_of(client->dev.platform_data, + struct ov772x_camera_info, link); + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, "I2C-Adapter doesn't support " -- cgit v1.2.3 From 0326f126a4d2f1e2cda2c11725a7f7d7d8273f7f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:28:22 +0200 Subject: soc-camera: convert to platform device From: Guennadi Liakhovetski Convert soc-camera core and all drivers to platform device API. We already converted platforms to register a platform device for each soc-camera client, now we remove the compatibility code and switch completely to the new scheme. This is a preparatory step for the v4l2-subdev conversion. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/ov772x.c | 157 ++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 71 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4b0363940..297a46fc9 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -399,8 +399,6 @@ struct ov772x_win_size { struct ov772x_priv { struct ov772x_camera_info *info; - struct i2c_client *client; - struct soc_camera_device icd; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_init(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) { - ret = priv->info->link.power(&priv->client->dev, 1); + if (icl->power) { + ret = icl->power(&client->dev, 1); if (ret < 0) return ret; } - if (priv->info->link.reset) - ret = priv->info->link.reset(&priv->client->dev); + if (icl->reset) + ret = icl->reset(&client->dev); return ret; } static int ov772x_release(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) - ret = priv->info->link.power(&priv->client->dev, 0); + if (icl->power) + ret = icl->power(&client->dev, 0); return ret; } static int ov772x_start_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->win || !priv->fmt) { dev_err(&icd->dev, "norm or win select error\n"); return -EPERM; } - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); dev_dbg(&icd->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } static int ov772x_stop_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - struct soc_camera_link *icl = &priv->info->link; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, static int ov772x_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = 0; u8 val; @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, priv->flag_vflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_VFLIP) val ^= VFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); break; case V4L2_CID_HFLIP: val = ctrl->value ? HFLIP_IMG : 0x00; priv->flag_hflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_HFLIP) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; } @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd, } static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); id->ident = priv->model; id->revision = 0; @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, static int ov772x_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - int ret; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + int ret; reg->size = 1; if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, static int ov772x_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); } #endif @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, - u32 pixfmt) +static int ov772x_set_params(struct soc_camera_device *icd, + u32 width, u32 height, u32 pixfmt) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = -EINVAL; u8 val; int i; @@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, break; } } + dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * reset hardware */ - ov772x_reset(priv->client); + ov772x_reset(client); /* * Edge Ctrl @@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * Remove it when manual mode. */ - ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); + ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_TRSHLD, EDGE_THRESHOLD_MASK, priv->info->edgectrl.threshold); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_STRNGT, EDGE_STRENGTH_MASK, priv->info->edgectrl.strength); if (ret < 0) @@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * * set upper and lower limit */ - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_UPPER, EDGE_UPPER_MASK, priv->info->edgectrl.upper); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_LOWER, EDGE_LOWER_MASK, priv->info->edgectrl.lower); if (ret < 0) @@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * set size format */ - ret = ov772x_write_array(priv->client, priv->win->regs); + ret = ov772x_write_array(client, priv->win->regs); if (ret < 0) goto ov772x_set_fmt_error; @@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, */ val = priv->fmt->dsp3; if (val) { - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, if (priv->flag_hflip) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * set COM7 */ val = priv->win->com7_bit | priv->fmt->com7; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), val); if (ret < 0) @@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ov772x_set_fmt_error: - ov772x_reset(priv->client); + ov772x_reset(client); priv->win = NULL; priv->fmt = NULL; @@ -930,22 +938,22 @@ ov772x_set_fmt_error: static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(priv, rect->width, rect->height, + return ov772x_set_params(icd, rect->width, rect->height, priv->fmt->fourcc); } static int ov772x_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(priv, pix->width, pix->height, + return ov772x_set_params(icd, pix->width, pix->height, pix->pixelformat); } @@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, return 0; } -static int ov772x_video_probe(struct soc_camera_device *icd) +static int ov772x_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct ov772x_priv *priv = i2c_get_clientdata(client); u8 pid, ver; const char *devname; + int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd) icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* * check and show product ID and manufacturer ID */ - pid = i2c_smbus_read_byte_data(priv->client, PID); - ver = i2c_smbus_read_byte_data(priv->client, VER); + pid = i2c_smbus_read_byte_data(client, PID); + ver = i2c_smbus_read_byte_data(client, VER); switch (VERSION(pid, ver)) { case OV7720: @@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - return -ENODEV; + ret = -ENODEV; + goto ever; } dev_info(&icd->dev, @@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) devname, pid, ver, - i2c_smbus_read_byte_data(priv->client, MIDH), - i2c_smbus_read_byte_data(priv->client, MIDL)); - - return soc_camera_video_start(icd); -} + i2c_smbus_read_byte_data(client, MIDH), + i2c_smbus_read_byte_data(client, MIDL)); -static void ov772x_video_remove(struct soc_camera_device *icd) -{ soc_camera_video_stop(icd); + +ever: + return ret; } static struct soc_camera_ops ov772x_ops = { .owner = THIS_MODULE, - .probe = ov772x_video_probe, - .remove = ov772x_video_remove, .init = ov772x_init, .release = ov772x_release, .start_capture = ov772x_start_capture, @@ -1062,20 +1074,26 @@ static struct soc_camera_ops ov772x_ops = { static int ov772x_probe(struct i2c_client *client) #else static int ov772x_probe(struct i2c_client *client, - const struct i2c_device_id *did) + const struct i2c_device_id *did) #endif { struct ov772x_priv *priv; struct ov772x_camera_info *info; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; int ret; - if (!client->dev.platform_data) + if (!icd) { + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); return -EINVAL; + } - info = container_of(client->dev.platform_data, - struct ov772x_camera_info, link); + icl = to_soc_camera_link(icd); + if (!icl) + return -EINVAL; + + info = container_of(icl, struct ov772x_camera_info, link); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, @@ -1089,19 +1107,15 @@ static int ov772x_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - priv->client = client; i2c_set_clientdata(client, priv); - icd = &priv->icd; icd->ops = &ov772x_ops; - icd->control = &client->dev; icd->width_max = MAX_WIDTH; icd->height_max = MAX_HEIGHT; - icd->iface = priv->info->link.bus_id; - - ret = soc_camera_device_register(icd); + ret = ov772x_video_probe(icd, client); if (ret) { + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); } @@ -1112,8 +1126,9 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); return 0; -- cgit v1.2.3 From a9c698e163df3064b2a003395d6115985d8a4f78 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:43:33 +0200 Subject: soc-camera: (partially) convert to v4l2-(sub)dev API From: Guennadi Liakhovetski Convert the soc-camera framework to use the v4l2-(sub)dev API. Start using v4l2-subdev operations. Only a part of the interface between the soc_camera core, soc_camera host drivers on one side and soc_camera device drivers on the other side is replaced so far. The rest of the interface will be replaced in incremental steps, and will require extensions and, possibly, modifications to the v4l2-subdev code. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/ov772x.c | 169 +++++++++++++++---------------------- 1 file changed, 68 insertions(+), 101 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 297a46fc9..4da12e8c4 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -398,6 +398,7 @@ struct ov772x_win_size { }; struct ov772x_priv { + struct v4l2_subdev subdev; struct ov772x_camera_info *info; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; @@ -575,6 +576,11 @@ static const struct v4l2_queryctrl ov772x_controls[] = { * general function */ +static struct ov772x_priv *to_ov772x(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); +} + static int ov772x_write_array(struct i2c_client *client, const struct regval_list *vals) { @@ -615,61 +621,29 @@ static int ov772x_reset(struct i2c_client *client) * soc_camera_ops function */ -static int ov772x_init(struct soc_camera_device *icd) +static int ov772x_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); - int ret = 0; + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) - return ret; + if (!enable) { + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + return 0; } - if (icl->reset) - ret = icl->reset(&client->dev); - - return ret; -} - -static int ov772x_release(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); - int ret = 0; - - if (icl->power) - ret = icl->power(&client->dev, 0); - - return ret; -} - -static int ov772x_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); - if (!priv->win || !priv->fmt) { - dev_err(&icd->dev, "norm or win select error\n"); + dev_err(&client->dev, "norm or win select error\n"); return -EPERM; } ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&icd->dev, + dev_dbg(&client->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } -static int ov772x_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); - return 0; -} - static int ov772x_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -688,11 +662,10 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int ov772x_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,11 +678,10 @@ static int ov772x_get_control(struct soc_camera_device *icd, return 0; } -static int ov772x_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); int ret = 0; u8 val; @@ -733,11 +705,11 @@ static int ov772x_set_control(struct soc_camera_device *icd, return ret; } -static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int ov772x_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 ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); id->ident = priv->model; id->revision = 0; @@ -746,10 +718,10 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int ov772x_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_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; int ret; reg->size = 1; @@ -765,10 +737,10 @@ static int ov772x_get_register(struct soc_camera_device *icd, return 0; } -static int ov772x_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_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->reg > 0xff || reg->val > 0xff) @@ -778,8 +750,7 @@ static int ov772x_set_register(struct soc_camera_device *icd, } #endif -static const struct ov772x_win_size* -ov772x_select_win(u32 width, u32 height) +static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) { __u32 diff; const struct ov772x_win_size *win; @@ -798,11 +769,10 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct soc_camera_device *icd, +static int ov772x_set_params(struct i2c_client *client, u32 width, u32 height, u32 pixfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; u8 val; int i; @@ -817,7 +787,6 @@ static int ov772x_set_params(struct soc_camera_device *icd, break; } } - dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -939,26 +908,26 @@ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(icd, rect->width, rect->height, + return ov772x_set_params(client, rect->width, rect->height, priv->fmt->fourcc); } -static int ov772x_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(icd, pix->width, pix->height, + return ov772x_set_params(client, pix->width, pix->height, pix->pixelformat); } -static int ov772x_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_try_fmt(struct v4l2_subdev *sd, + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; const struct ov772x_win_size *win; @@ -978,10 +947,9 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, static int ov772x_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); u8 pid, ver; const char *devname; - int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -1003,11 +971,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* * check and show product ID and manufacturer ID */ @@ -1026,8 +989,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - ret = -ENODEV; - goto ever; + return -ENODEV; } dev_info(&icd->dev, @@ -1038,34 +1000,38 @@ static int ov772x_video_probe(struct soc_camera_device *icd, i2c_smbus_read_byte_data(client, MIDH), i2c_smbus_read_byte_data(client, MIDL)); - soc_camera_video_stop(icd); - -ever: - return ret; + return 0; } static struct soc_camera_ops ov772x_ops = { - .owner = THIS_MODULE, - .init = ov772x_init, - .release = ov772x_release, - .start_capture = ov772x_start_capture, - .stop_capture = ov772x_stop_capture, .set_crop = ov772x_set_crop, - .set_fmt = ov772x_set_fmt, - .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, .num_controls = ARRAY_SIZE(ov772x_controls), - .get_control = ov772x_get_control, - .set_control = ov772x_set_control, - .get_chip_id = ov772x_get_chip_id, +}; + +static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { + .g_ctrl = ov772x_g_ctrl, + .s_ctrl = ov772x_s_ctrl, + .g_chip_ident = ov772x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = ov772x_get_register, - .set_register = ov772x_set_register, + .g_register = ov772x_g_register, + .s_register = ov772x_s_register, #endif }; +static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { + .s_stream = ov772x_s_stream, + .s_fmt = ov772x_s_fmt, + .try_fmt = ov772x_try_fmt, +}; + +static struct v4l2_subdev_ops ov772x_subdev_ops = { + .core = &ov772x_subdev_core_ops, + .video = &ov772x_subdev_video_ops, +}; + /* * i2c_driver function */ @@ -1085,7 +1051,7 @@ static int ov772x_probe(struct i2c_client *client, int ret; if (!icd) { - dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); + dev_err(&client->dev, "OV772X: missing soc-camera data!\n"); return -EINVAL; } @@ -1106,8 +1072,9 @@ static int ov772x_probe(struct i2c_client *client, if (!priv) return -ENOMEM; - priv->info = info; - i2c_set_clientdata(client, priv); + priv->info = info; + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; icd->width_max = MAX_WIDTH; @@ -1125,7 +1092,7 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; -- cgit v1.2.3 From 4e4ce6d0b364f6dcab06b9f80942339fbfef9e0a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:14 +0200 Subject: ov772x: implement a band-stop filter support From: Guennadi Liakhovetski The V4L2_CID_BAND_STOP_FILTER control is used to switch the "Banding Filter" on OV772x cameras on and off and to set the minimum AEC value in BDBASE register. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 50 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4da12e8c4..05e06f5b8 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -403,8 +403,9 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; - unsigned int flag_vflip:1; - unsigned int flag_hflip:1; + unsigned short flag_vflip:1; + unsigned short flag_hflip:1; + unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ }; #define ENDMARKER { 0xff, 0xff } @@ -569,6 +570,15 @@ static const struct v4l2_queryctrl ov772x_controls[] = { .step = 1, .default_value = 0, }, + { + .id = V4L2_CID_BAND_STOP_FILTER, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Band-stop filter", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, }; @@ -674,6 +684,9 @@ static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_HFLIP: ctrl->value = priv->flag_hflip; break; + case V4L2_CID_BAND_STOP_FILTER: + ctrl->value = priv->band_filter; + break; } return 0; } @@ -700,6 +713,29 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) val ^= HFLIP_IMG; ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; + case V4L2_CID_BAND_STOP_FILTER: + if ((unsigned)ctrl->value > 256) + ctrl->value = 256; + if (ctrl->value == priv->band_filter) + break; + if (!ctrl->value) { + /* Switch the filter off, it is on now */ + ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); + if (!ret) + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, 0); + } else { + /* Switch the filter on, set AEC low limit */ + val = 256 - ctrl->value; + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, BNDF_ON_OFF); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, val); + } + if (!ret) + priv->band_filter = ctrl->value; + break; } return ret; @@ -893,6 +929,18 @@ static int ov772x_set_params(struct i2c_client *client, if (ret < 0) goto ov772x_set_fmt_error; + /* + * set COM8 + */ + if (priv->band_filter) { + ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, 256 - priv->band_filter); + if (ret < 0) + goto ov772x_set_fmt_error; + } + return ret; ov772x_set_fmt_error: -- cgit v1.2.3 From 67b6fcc4c0404e94f16820566585bb0ff9891b89 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:17 +0200 Subject: soc-camera: use struct v4l2_rect in struct soc_camera_device From: Guennadi Liakhovetski Switch to using struct v4l2_rect in struct soc_camera_device for uniformity and simplicity. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/ov772x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 05e06f5b8..a853c3514 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1124,9 +1124,9 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); - icd->ops = &ov772x_ops; - icd->width_max = MAX_WIDTH; - icd->height_max = MAX_HEIGHT; + icd->ops = &ov772x_ops; + icd->rect_max.width = MAX_WIDTH; + icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { -- cgit v1.2.3 From bbbc50159e8cab3ba46fe1491657840d91490829 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: successful S_FMT and S_CROP must update user-provided rectangle From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a853c3514..a9f9c04c1 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -806,7 +806,7 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) } static int ov772x_set_params(struct i2c_client *client, - u32 width, u32 height, u32 pixfmt) + u32 *width, u32 *height, u32 pixfmt) { struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; @@ -829,7 +829,7 @@ static int ov772x_set_params(struct i2c_client *client, /* * select win */ - priv->win = ov772x_select_win(width, height); + priv->win = ov772x_select_win(*width, *height); /* * reset hardware @@ -941,6 +941,9 @@ static int ov772x_set_params(struct i2c_client *client, goto ov772x_set_fmt_error; } + *width = priv->win->width; + *height = priv->win->height; + return ret; ov772x_set_fmt_error: @@ -961,7 +964,7 @@ static int ov772x_set_crop(struct soc_camera_device *icd, if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, rect->width, rect->height, + return ov772x_set_params(client, &rect->width, &rect->height, priv->fmt->fourcc); } @@ -970,7 +973,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(client, pix->width, pix->height, + return ov772x_set_params(client, &pix->width, &pix->height, pix->pixelformat); } -- cgit v1.2.3 From 50dda2d882c41d334002fb2437c66080c5d87080 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: S_CROP must return actually configured geometry From: Guennadi Liakhovetski V4L2 drivers are allowed to configure a geometry different than what has been requested by the user with S_CROP, but then they have to adjust the input rectangle accordingly. Fix ov772x to comply with this requirement. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a9f9c04c1..700f655fd 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -960,12 +960,18 @@ static int ov772x_set_crop(struct soc_camera_device *icd, { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); + int ret; if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); + ret = ov772x_set_params(client, &rect->width, &rect->height, + priv->fmt->fourcc); + if (!ret) { + rect->left = 0; + rect->top = 0; + } + return ret; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 4eb5903e517a1d50a63f75fef61090f5f90b81ea Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: ov772x: do not use scaling for cropping From: Guennadi Liakhovetski OV772x sensors cannot crop, they only support two fixed formats: VGA and QVGA. We should not change the format when requested to crop, only S_FMT can do this. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) --- linux/drivers/media/video/ov772x.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 700f655fd..e8bb337da 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,23 +955,22 @@ ov772x_set_fmt_error: return ret; } +/* Cannot crop, just return the current geometry */ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); - int ret; - if (!priv->fmt) + if (!priv->fmt || !priv->win) return -EINVAL; - ret = ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); - if (!ret) { - rect->left = 0; - rect->top = 0; - } - return ret; + rect->left = 0; + rect->top = 0; + rect->width = priv->win->width; + rect->height = priv->win->height; + + return 0; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From a94ff67f3f3091badb6034566504ad58206989ef Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:54 +0200 Subject: soc-camera: switch to s_crop v4l2-subdev video operation From: Guennadi Liakhovetski Remove set_crop soc-camera device method and switch to s_crop from v4l2-subdev video operations. Also extend non-i2c drivers to also hold a pointer to their v4l2-subdev instance in control device driver-data, i.e., in dev_get_drvdata((struct device *)to_soc_camera_control(icd)) Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 23 +++--- drivers/media/video/mt9m111.c | 9 +- drivers/media/video/mt9t031.c | 9 +- drivers/media/video/mt9v022.c | 23 +++--- drivers/media/video/mx1_camera.c | 8 ++- drivers/media/video/mx3_camera.c | 7 +- drivers/media/video/ov772x.c | 19 ----- drivers/media/video/pxa_camera.c | 7 +- drivers/media/video/sh_mobile_ceu_camera.c | 110 ++++++++++++++------------- drivers/media/video/soc_camera.c | 4 +- drivers/media/video/soc_camera_platform.c | 28 ++++---- drivers/media/video/tw9910.c | 31 ++++---- include/media/soc_camera.h | 3 +- 13 files changed, 142 insertions(+), 139 deletions(-) --- linux/drivers/media/video/ov772x.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index e8bb337da..c5b63f420 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,24 +955,6 @@ ov772x_set_fmt_error: return ret; } -/* Cannot crop, just return the current geometry */ -static int ov772x_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = to_ov772x(client); - - if (!priv->fmt || !priv->win) - return -EINVAL; - - rect->left = 0; - rect->top = 0; - rect->width = priv->win->width; - rect->height = priv->win->height; - - return 0; -} - static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,7 +1042,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, } static struct soc_camera_ops ov772x_ops = { - .set_crop = ov772x_set_crop, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, -- cgit v1.2.3 From 3a76b0c22111746bd099bc5c9279dbedc734e3ac Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use I2C device for dev_{dbg,info,...} output in all clients From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 20 +++++++++++--------- drivers/media/video/mt9m111.c | 11 +++++------ drivers/media/video/mt9t031.c | 16 ++++++++-------- drivers/media/video/mt9v022.c | 16 ++++++++-------- drivers/media/video/ov772x.c | 6 +++--- drivers/media/video/tw9910.c | 6 +++--- 6 files changed, 38 insertions(+), 37 deletions(-) --- linux/drivers/media/video/ov772x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index c5b63f420..392327b72 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1002,7 +1002,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, */ if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && SOCAM_DATAWIDTH_8 != priv->info->buswidth) { - dev_err(&icd->dev, "bus width error\n"); + dev_err(&client->dev, "bus width error\n"); return -ENODEV; } @@ -1025,12 +1025,12 @@ static int ov772x_video_probe(struct soc_camera_device *icd, priv->model = V4L2_IDENT_OV7725; break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); return -ENODEV; } - dev_info(&icd->dev, + dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, -- cgit v1.2.3 From 30e8a71f69f2769f966054f168e9e4ced8a1d091 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:50:46 +0200 Subject: soc-camera: V4L2 API compliant scaling (S_FMT) and cropping (S_CROP) From: Guennadi Liakhovetski The initial soc-camera scaling and cropping implementation turned out to be incompliant with the V4L2 API, e.g., it expected the user to specify cropping in output window pixels, instead of input window pixels. This patch converts the soc-camera core and all drivers to comply with the standard. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/ov772x.c | 84 ++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 17 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 392327b72..2d48a7aeb 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -382,11 +382,10 @@ struct regval_list { }; struct ov772x_color_format { - char *name; - __u32 fourcc; - u8 dsp3; - u8 com3; - u8 com7; + const struct soc_camera_data_format *format; + u8 dsp3; + u8 com3; + u8 com7; }; struct ov772x_win_size { @@ -481,43 +480,43 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { */ static const struct ov772x_color_format ov772x_cfmts[] = { { - SETFOURCC(YUYV), + .format = &ov772x_fmt_lists[0], .dsp3 = 0x0, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(YVYU), + .format = &ov772x_fmt_lists[1], .dsp3 = UV_ON, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(UYVY), + .format = &ov772x_fmt_lists[2], .dsp3 = 0x0, .com3 = 0x0, .com7 = OFMT_YUV, }, { - SETFOURCC(RGB555), + .format = &ov772x_fmt_lists[3], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB555X), + .format = &ov772x_fmt_lists[4], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB565), + .format = &ov772x_fmt_lists[5], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB565 | OFMT_RGB, }, { - SETFOURCC(RGB565X), + .format = &ov772x_fmt_lists[6], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB565 | OFMT_RGB, @@ -648,8 +647,8 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&client->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + dev_dbg(&client->dev, "format %s, win %s\n", + priv->fmt->format->name, priv->win->name); return 0; } @@ -818,7 +817,7 @@ static int ov772x_set_params(struct i2c_client *client, */ priv->fmt = NULL; for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { - if (pixfmt == ov772x_cfmts[i].fourcc) { + if (pixfmt == ov772x_cfmts[i].format->fourcc) { priv->fmt = ov772x_cfmts + i; break; } @@ -955,6 +954,56 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = VGA_WIDTH; + a->c.height = VGA_HEIGHT; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = VGA_WIDTH; + a->bounds.height = VGA_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (!priv->win || !priv->fmt) { + u32 width = VGA_WIDTH, height = VGA_HEIGHT; + int ret = ov772x_set_params(client, &width, &height, + V4L2_PIX_FMT_YUYV); + if (ret < 0) + return ret; + } + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix->width = priv->win->width; + pix->height = priv->win->height; + pix->pixelformat = priv->fmt->format->fourcc; + pix->colorspace = priv->fmt->format->colorspace; + pix->field = V4L2_FIELD_NONE; + + return 0; +} + static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,8 +1109,11 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { .s_stream = ov772x_s_stream, + .g_fmt = ov772x_g_fmt, .s_fmt = ov772x_s_fmt, .try_fmt = ov772x_try_fmt, + .cropcap = ov772x_cropcap, + .g_crop = ov772x_g_crop, }; static struct v4l2_subdev_ops ov772x_subdev_ops = { @@ -1114,8 +1166,6 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; - icd->rect_max.width = MAX_WIDTH; - icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { -- cgit v1.2.3 From 92c15735f63a6159490a9b6110e81925d093a10d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: fix recently introduced overlong lines From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 3 ++- drivers/media/video/mt9m111.c | 9 +++++---- drivers/media/video/mt9v022.c | 5 ++++- drivers/media/video/mx1_camera.c | 3 ++- drivers/media/video/ov772x.c | 6 ++++-- drivers/media/video/pxa_camera.c | 3 ++- drivers/media/video/soc_camera.c | 14 +++++++++++--- drivers/media/video/soc_camera_platform.c | 3 ++- drivers/media/video/tw9910.c | 3 ++- include/media/soc_camera.h | 15 ++++++++++----- 10 files changed, 44 insertions(+), 20 deletions(-) --- linux/drivers/media/video/ov772x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media/video/ov772x.c') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2d48a7aeb..47e7c7c53 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -404,7 +404,8 @@ struct ov772x_priv { int model; unsigned short flag_vflip:1; unsigned short flag_hflip:1; - unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ + /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ + unsigned short band_filter; }; #define ENDMARKER { 0xff, 0xff } @@ -587,7 +588,8 @@ static const struct v4l2_queryctrl ov772x_controls[] = { static struct ov772x_priv *to_ov772x(const struct i2c_client *client) { - return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); + return container_of(i2c_get_clientdata(client), struct ov772x_priv, + subdev); } static int ov772x_write_array(struct i2c_client *client, -- cgit v1.2.3