V4L/DVB (12529): soc-camera: switch to s_crop v4l2-subdev video operation
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 <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
961801bbb3
commit
08590b9613
@@ -194,11 +194,12 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
|
|||||||
return soc_camera_apply_sensor_flags(icl, flags);
|
return soc_camera_apply_sensor_flags(icl, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m001_set_crop(struct soc_camera_device *icd,
|
static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
struct v4l2_rect *rect = &a->c;
|
||||||
|
struct i2c_client *client = sd->priv;
|
||||||
struct mt9m001 *mt9m001 = to_mt9m001(client);
|
struct mt9m001 *mt9m001 = to_mt9m001(client);
|
||||||
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
int ret;
|
int ret;
|
||||||
const u16 hblank = 9, vblank = 25;
|
const u16 hblank = 9, vblank = 25;
|
||||||
|
|
||||||
@@ -239,15 +240,17 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = sd->priv;
|
struct i2c_client *client = sd->priv;
|
||||||
struct soc_camera_device *icd = client->dev.platform_data;
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
struct v4l2_rect rect = {
|
struct v4l2_crop a = {
|
||||||
.left = icd->rect_current.left,
|
.c = {
|
||||||
.top = icd->rect_current.top,
|
.left = icd->rect_current.left,
|
||||||
.width = f->fmt.pix.width,
|
.top = icd->rect_current.top,
|
||||||
.height = f->fmt.pix.height,
|
.width = f->fmt.pix.width,
|
||||||
|
.height = f->fmt.pix.height,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* No support for scaling so far, just crop. TODO: use skipping */
|
/* No support for scaling so far, just crop. TODO: use skipping */
|
||||||
return mt9m001_set_crop(icd, &rect);
|
return mt9m001_s_crop(sd, &a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||||
@@ -361,7 +364,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
|
|||||||
static struct soc_camera_ops mt9m001_ops = {
|
static struct soc_camera_ops mt9m001_ops = {
|
||||||
.init = mt9m001_init,
|
.init = mt9m001_init,
|
||||||
.release = mt9m001_release,
|
.release = mt9m001_release,
|
||||||
.set_crop = mt9m001_set_crop,
|
|
||||||
.set_bus_param = mt9m001_set_bus_param,
|
.set_bus_param = mt9m001_set_bus_param,
|
||||||
.query_bus_param = mt9m001_query_bus_param,
|
.query_bus_param = mt9m001_query_bus_param,
|
||||||
.controls = mt9m001_controls,
|
.controls = mt9m001_controls,
|
||||||
@@ -575,6 +577,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
|
|||||||
.s_stream = mt9m001_s_stream,
|
.s_stream = mt9m001_s_stream,
|
||||||
.s_fmt = mt9m001_s_fmt,
|
.s_fmt = mt9m001_s_fmt,
|
||||||
.try_fmt = mt9m001_try_fmt,
|
.try_fmt = mt9m001_try_fmt,
|
||||||
|
.s_crop = mt9m001_s_crop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9m001_subdev_ops = {
|
static struct v4l2_subdev_ops mt9m001_subdev_ops = {
|
||||||
|
@@ -395,11 +395,12 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m111_set_crop(struct soc_camera_device *icd,
|
static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
struct v4l2_rect *rect = &a->c;
|
||||||
|
struct i2c_client *client = sd->priv;
|
||||||
struct mt9m111 *mt9m111 = to_mt9m111(client);
|
struct mt9m111 *mt9m111 = to_mt9m111(client);
|
||||||
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
|
dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
|
||||||
@@ -601,7 +602,6 @@ static struct soc_camera_ops mt9m111_ops = {
|
|||||||
.init = mt9m111_init,
|
.init = mt9m111_init,
|
||||||
.resume = mt9m111_resume,
|
.resume = mt9m111_resume,
|
||||||
.release = mt9m111_release,
|
.release = mt9m111_release,
|
||||||
.set_crop = mt9m111_set_crop,
|
|
||||||
.query_bus_param = mt9m111_query_bus_param,
|
.query_bus_param = mt9m111_query_bus_param,
|
||||||
.set_bus_param = mt9m111_set_bus_param,
|
.set_bus_param = mt9m111_set_bus_param,
|
||||||
.controls = mt9m111_controls,
|
.controls = mt9m111_controls,
|
||||||
@@ -908,6 +908,7 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
|
|||||||
static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
|
static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
|
||||||
.s_fmt = mt9m111_s_fmt,
|
.s_fmt = mt9m111_s_fmt,
|
||||||
.try_fmt = mt9m111_try_fmt,
|
.try_fmt = mt9m111_try_fmt,
|
||||||
|
.s_crop = mt9m111_s_crop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9m111_subdev_ops = {
|
static struct v4l2_subdev_ops mt9m111_subdev_ops = {
|
||||||
|
@@ -321,11 +321,12 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
|
|||||||
return ret < 0 ? ret : 0;
|
return ret < 0 ? ret : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9t031_set_crop(struct soc_camera_device *icd,
|
static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
struct v4l2_rect *rect = &a->c;
|
||||||
|
struct i2c_client *client = sd->priv;
|
||||||
struct mt9t031 *mt9t031 = to_mt9t031(client);
|
struct mt9t031 *mt9t031 = to_mt9t031(client);
|
||||||
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
|
|
||||||
/* Make sure we don't exceed sensor limits */
|
/* Make sure we don't exceed sensor limits */
|
||||||
if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width)
|
if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width)
|
||||||
@@ -495,7 +496,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
|
|||||||
static struct soc_camera_ops mt9t031_ops = {
|
static struct soc_camera_ops mt9t031_ops = {
|
||||||
.init = mt9t031_init,
|
.init = mt9t031_init,
|
||||||
.release = mt9t031_release,
|
.release = mt9t031_release,
|
||||||
.set_crop = mt9t031_set_crop,
|
|
||||||
.set_bus_param = mt9t031_set_bus_param,
|
.set_bus_param = mt9t031_set_bus_param,
|
||||||
.query_bus_param = mt9t031_query_bus_param,
|
.query_bus_param = mt9t031_query_bus_param,
|
||||||
.controls = mt9t031_controls,
|
.controls = mt9t031_controls,
|
||||||
@@ -689,6 +689,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
|
|||||||
.s_stream = mt9t031_s_stream,
|
.s_stream = mt9t031_s_stream,
|
||||||
.s_fmt = mt9t031_s_fmt,
|
.s_fmt = mt9t031_s_fmt,
|
||||||
.try_fmt = mt9t031_try_fmt,
|
.try_fmt = mt9t031_try_fmt,
|
||||||
|
.s_crop = mt9t031_s_crop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9t031_subdev_ops = {
|
static struct v4l2_subdev_ops mt9t031_subdev_ops = {
|
||||||
|
@@ -248,10 +248,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
|
|||||||
width_flag;
|
width_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9v022_set_crop(struct soc_camera_device *icd,
|
static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
struct v4l2_rect *rect = &a->c;
|
||||||
|
struct i2c_client *client = sd->priv;
|
||||||
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Like in example app. Contradicts the datasheet though */
|
/* Like in example app. Contradicts the datasheet though */
|
||||||
@@ -297,11 +298,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
|||||||
struct mt9v022 *mt9v022 = to_mt9v022(client);
|
struct mt9v022 *mt9v022 = to_mt9v022(client);
|
||||||
struct soc_camera_device *icd = client->dev.platform_data;
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
struct v4l2_pix_format *pix = &f->fmt.pix;
|
struct v4l2_pix_format *pix = &f->fmt.pix;
|
||||||
struct v4l2_rect rect = {
|
struct v4l2_crop a = {
|
||||||
.left = icd->rect_current.left,
|
.c = {
|
||||||
.top = icd->rect_current.top,
|
.left = icd->rect_current.left,
|
||||||
.width = pix->width,
|
.top = icd->rect_current.top,
|
||||||
.height = pix->height,
|
.width = pix->width,
|
||||||
|
.height = pix->height,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The caller provides a supported format, as verified per call to
|
/* The caller provides a supported format, as verified per call to
|
||||||
@@ -325,7 +328,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* No support for scaling on this camera, just crop. */
|
/* No support for scaling on this camera, just crop. */
|
||||||
return mt9v022_set_crop(icd, &rect);
|
return mt9v022_s_crop(sd, &a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||||
@@ -454,7 +457,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
|
|||||||
|
|
||||||
static struct soc_camera_ops mt9v022_ops = {
|
static struct soc_camera_ops mt9v022_ops = {
|
||||||
.init = mt9v022_init,
|
.init = mt9v022_init,
|
||||||
.set_crop = mt9v022_set_crop,
|
|
||||||
.set_bus_param = mt9v022_set_bus_param,
|
.set_bus_param = mt9v022_set_bus_param,
|
||||||
.query_bus_param = mt9v022_query_bus_param,
|
.query_bus_param = mt9v022_query_bus_param,
|
||||||
.controls = mt9v022_controls,
|
.controls = mt9v022_controls,
|
||||||
@@ -700,6 +702,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
|
|||||||
.s_stream = mt9v022_s_stream,
|
.s_stream = mt9v022_s_stream,
|
||||||
.s_fmt = mt9v022_s_fmt,
|
.s_fmt = mt9v022_s_fmt,
|
||||||
.try_fmt = mt9v022_try_fmt,
|
.try_fmt = mt9v022_try_fmt,
|
||||||
|
.s_crop = mt9v022_s_crop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9v022_subdev_ops = {
|
static struct v4l2_subdev_ops mt9v022_subdev_ops = {
|
||||||
|
@@ -463,9 +463,13 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int mx1_camera_set_crop(struct soc_camera_device *icd,
|
static int mx1_camera_set_crop(struct soc_camera_device *icd,
|
||||||
struct v4l2_rect *rect)
|
struct v4l2_crop *a)
|
||||||
{
|
{
|
||||||
return icd->ops->set_crop(icd, rect);
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||||
|
struct device *control = to_soc_camera_control(icd);
|
||||||
|
struct v4l2_subdev *sd = dev_get_drvdata(control);
|
||||||
|
|
||||||
|
return v4l2_subdev_call(sd, video, s_crop, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
|
static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
|
||||||
|
@@ -781,10 +781,13 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int mx3_camera_set_crop(struct soc_camera_device *icd,
|
static int mx3_camera_set_crop(struct soc_camera_device *icd,
|
||||||
struct v4l2_rect *rect)
|
struct v4l2_crop *a)
|
||||||
{
|
{
|
||||||
|
struct v4l2_rect *rect = &a->c;
|
||||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||||
struct mx3_camera_dev *mx3_cam = ici->priv;
|
struct mx3_camera_dev *mx3_cam = ici->priv;
|
||||||
|
struct device *control = to_soc_camera_control(icd);
|
||||||
|
struct v4l2_subdev *sd = dev_get_drvdata(control);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We now know pixel formats and can decide upon DMA-channel(s)
|
* We now know pixel formats and can decide upon DMA-channel(s)
|
||||||
@@ -798,7 +801,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
|
|||||||
|
|
||||||
configure_geometry(mx3_cam, rect);
|
configure_geometry(mx3_cam, rect);
|
||||||
|
|
||||||
return icd->ops->set_crop(icd, rect);
|
return v4l2_subdev_call(sd, video, s_crop, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mx3_camera_set_fmt(struct soc_camera_device *icd,
|
static int mx3_camera_set_fmt(struct soc_camera_device *icd,
|
||||||
|
@@ -955,24 +955,6 @@ ov772x_set_fmt_error:
|
|||||||
return ret;
|
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)
|
static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = sd->priv;
|
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 = {
|
static struct soc_camera_ops ov772x_ops = {
|
||||||
.set_crop = ov772x_set_crop,
|
|
||||||
.set_bus_param = ov772x_set_bus_param,
|
.set_bus_param = ov772x_set_bus_param,
|
||||||
.query_bus_param = ov772x_query_bus_param,
|
.query_bus_param = ov772x_query_bus_param,
|
||||||
.controls = ov772x_controls,
|
.controls = ov772x_controls,
|
||||||
|
@@ -1281,10 +1281,13 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int pxa_camera_set_crop(struct soc_camera_device *icd,
|
static int pxa_camera_set_crop(struct soc_camera_device *icd,
|
||||||
struct v4l2_rect *rect)
|
struct v4l2_crop *a)
|
||||||
{
|
{
|
||||||
|
struct v4l2_rect *rect = &a->c;
|
||||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||||
struct pxa_camera_dev *pcdev = ici->priv;
|
struct pxa_camera_dev *pcdev = ici->priv;
|
||||||
|
struct device *control = to_soc_camera_control(icd);
|
||||||
|
struct v4l2_subdev *sd = dev_get_drvdata(control);
|
||||||
struct soc_camera_sense sense = {
|
struct soc_camera_sense sense = {
|
||||||
.master_clock = pcdev->mclk,
|
.master_clock = pcdev->mclk,
|
||||||
.pixel_clock_max = pcdev->ciclk / 4,
|
.pixel_clock_max = pcdev->ciclk / 4,
|
||||||
@@ -1295,7 +1298,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
|
|||||||
if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
|
if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
|
||||||
icd->sense = &sense;
|
icd->sense = &sense;
|
||||||
|
|
||||||
ret = icd->ops->set_crop(icd, rect);
|
ret = v4l2_subdev_call(sd, video, s_crop, a);
|
||||||
|
|
||||||
icd->sense = NULL;
|
icd->sense = NULL;
|
||||||
|
|
||||||
|
@@ -846,12 +846,16 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
|
|||||||
* 3. if (2) failed, try to request the maximum image
|
* 3. if (2) failed, try to request the maximum image
|
||||||
*/
|
*/
|
||||||
static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
|
static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
|
||||||
struct v4l2_rect *rect)
|
struct v4l2_crop *a)
|
||||||
{
|
{
|
||||||
|
struct v4l2_rect *rect = &a->c;
|
||||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||||
struct sh_mobile_ceu_dev *pcdev = ici->priv;
|
struct sh_mobile_ceu_dev *pcdev = ici->priv;
|
||||||
struct v4l2_rect cam_rect, target, cam_max;
|
struct v4l2_crop cam_crop;
|
||||||
|
struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max;
|
||||||
struct sh_mobile_ceu_cam *cam = icd->host_priv;
|
struct sh_mobile_ceu_cam *cam = icd->host_priv;
|
||||||
|
struct device *control = to_soc_camera_control(icd);
|
||||||
|
struct v4l2_subdev *sd = dev_get_drvdata(control);
|
||||||
unsigned int hscale = pcdev->cflcr & 0xffff;
|
unsigned int hscale = pcdev->cflcr & 0xffff;
|
||||||
unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff;
|
unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff;
|
||||||
unsigned short width, height;
|
unsigned short width, height;
|
||||||
@@ -859,80 +863,80 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Scale back up into client units */
|
/* Scale back up into client units */
|
||||||
cam_rect.left = size_src(rect->left, hscale);
|
cam_rect->left = size_src(rect->left, hscale);
|
||||||
cam_rect.width = size_src(rect->width, hscale);
|
cam_rect->width = size_src(rect->width, hscale);
|
||||||
cam_rect.top = size_src(rect->top, vscale);
|
cam_rect->top = size_src(rect->top, vscale);
|
||||||
cam_rect.height = size_src(rect->height, vscale);
|
cam_rect->height = size_src(rect->height, vscale);
|
||||||
|
|
||||||
target = cam_rect;
|
target = *cam_rect;
|
||||||
|
|
||||||
capsr = capture_save_reset(pcdev);
|
capsr = capture_save_reset(pcdev);
|
||||||
dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
|
dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
|
||||||
|
|
||||||
/* First attempt - see if the client can deliver a perfect result */
|
/* First attempt - see if the client can deliver a perfect result */
|
||||||
ret = icd->ops->set_crop(icd, &cam_rect);
|
ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
|
||||||
if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) {
|
if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) {
|
||||||
dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n",
|
dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n",
|
||||||
cam_rect.width, cam_rect.height,
|
cam_rect->width, cam_rect->height,
|
||||||
cam_rect.left, cam_rect.top);
|
cam_rect->left, cam_rect->top);
|
||||||
goto ceu_set_rect;
|
goto ceu_set_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to fix cropping, that camera hasn't managed to do */
|
/* Try to fix cropping, that camera hasn't managed to do */
|
||||||
dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u"
|
dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u"
|
||||||
" to %ux%u@%u:%u\n",
|
" to %ux%u@%u:%u\n",
|
||||||
ret, cam_rect.width, cam_rect.height,
|
ret, cam_rect->width, cam_rect->height,
|
||||||
cam_rect.left, cam_rect.top,
|
cam_rect->left, cam_rect->top,
|
||||||
target.width, target.height, target.left, target.top);
|
target.width, target.height, target.left, target.top);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Popular special case - some cameras can only handle fixed sizes like
|
* Popular special case - some cameras can only handle fixed sizes like
|
||||||
* QVGA, VGA,... Take care to avoid infinite loop.
|
* QVGA, VGA,... Take care to avoid infinite loop.
|
||||||
*/
|
*/
|
||||||
width = max(cam_rect.width, 1);
|
width = max(cam_rect->width, 1);
|
||||||
height = max(cam_rect.height, 1);
|
height = max(cam_rect->height, 1);
|
||||||
cam_max.width = size_src(icd->rect_max.width, hscale);
|
cam_max.width = size_src(icd->rect_max.width, hscale);
|
||||||
cam_max.left = size_src(icd->rect_max.left, hscale);
|
cam_max.left = size_src(icd->rect_max.left, hscale);
|
||||||
cam_max.height = size_src(icd->rect_max.height, vscale);
|
cam_max.height = size_src(icd->rect_max.height, vscale);
|
||||||
cam_max.top = size_src(icd->rect_max.top, vscale);
|
cam_max.top = size_src(icd->rect_max.top, vscale);
|
||||||
while (!ret && (is_smaller(&cam_rect, &target) ||
|
while (!ret && (is_smaller(cam_rect, &target) ||
|
||||||
is_inside(&cam_rect, &target)) &&
|
is_inside(cam_rect, &target)) &&
|
||||||
cam_max.width >= width && cam_max.height >= height) {
|
cam_max.width >= width && cam_max.height >= height) {
|
||||||
|
|
||||||
width *= 2;
|
width *= 2;
|
||||||
height *= 2;
|
height *= 2;
|
||||||
cam_rect.width = width;
|
cam_rect->width = width;
|
||||||
cam_rect.height = height;
|
cam_rect->height = height;
|
||||||
|
|
||||||
/* We do not know what the camera is capable of, play safe */
|
/* We do not know what the camera is capable of, play safe */
|
||||||
if (cam_rect.left > target.left)
|
if (cam_rect->left > target.left)
|
||||||
cam_rect.left = cam_max.left;
|
cam_rect->left = cam_max.left;
|
||||||
|
|
||||||
if (cam_rect.left + cam_rect.width < target.left + target.width)
|
if (cam_rect->left + cam_rect->width < target.left + target.width)
|
||||||
cam_rect.width = target.left + target.width -
|
cam_rect->width = target.left + target.width -
|
||||||
cam_rect.left;
|
cam_rect->left;
|
||||||
|
|
||||||
if (cam_rect.top > target.top)
|
if (cam_rect->top > target.top)
|
||||||
cam_rect.top = cam_max.top;
|
cam_rect->top = cam_max.top;
|
||||||
|
|
||||||
if (cam_rect.top + cam_rect.height < target.top + target.height)
|
if (cam_rect->top + cam_rect->height < target.top + target.height)
|
||||||
cam_rect.height = target.top + target.height -
|
cam_rect->height = target.top + target.height -
|
||||||
cam_rect.top;
|
cam_rect->top;
|
||||||
|
|
||||||
if (cam_rect.width + cam_rect.left >
|
if (cam_rect->width + cam_rect->left >
|
||||||
cam_max.width + cam_max.left)
|
cam_max.width + cam_max.left)
|
||||||
cam_rect.left = max(cam_max.width + cam_max.left -
|
cam_rect->left = max(cam_max.width + cam_max.left -
|
||||||
cam_rect.width, cam_max.left);
|
cam_rect->width, cam_max.left);
|
||||||
|
|
||||||
if (cam_rect.height + cam_rect.top >
|
if (cam_rect->height + cam_rect->top >
|
||||||
cam_max.height + cam_max.top)
|
cam_max.height + cam_max.top)
|
||||||
cam_rect.top = max(cam_max.height + cam_max.top -
|
cam_rect->top = max(cam_max.height + cam_max.top -
|
||||||
cam_rect.height, cam_max.top);
|
cam_rect->height, cam_max.top);
|
||||||
|
|
||||||
ret = icd->ops->set_crop(icd, &cam_rect);
|
ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
|
||||||
dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n",
|
dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n",
|
||||||
ret, cam_rect.width, cam_rect.height,
|
ret, cam_rect->width, cam_rect->height,
|
||||||
cam_rect.left, cam_rect.top);
|
cam_rect->left, cam_rect->top);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -941,30 +945,30 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
|
|||||||
*/
|
*/
|
||||||
if ((ret < 0 && (is_smaller(&icd->rect_current, rect) ||
|
if ((ret < 0 && (is_smaller(&icd->rect_current, rect) ||
|
||||||
is_inside(&icd->rect_current, rect))) ||
|
is_inside(&icd->rect_current, rect))) ||
|
||||||
is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) {
|
is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) {
|
||||||
/*
|
/*
|
||||||
* The camera failed to configure a suitable cropping,
|
* The camera failed to configure a suitable cropping,
|
||||||
* we cannot use the current rectangle, set to max
|
* we cannot use the current rectangle, set to max
|
||||||
*/
|
*/
|
||||||
cam_rect = cam_max;
|
*cam_rect = cam_max;
|
||||||
ret = icd->ops->set_crop(icd, &cam_rect);
|
ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
|
||||||
dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n",
|
dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n",
|
||||||
ret, cam_rect.width, cam_rect.height,
|
ret, cam_rect->width, cam_rect->height,
|
||||||
cam_rect.left, cam_rect.top);
|
cam_rect->left, cam_rect->top);
|
||||||
if (ret < 0)
|
if (ret < 0 && ret != -ENOIOCTLCMD)
|
||||||
/* All failed, hopefully resume current capture */
|
/* All failed, hopefully resume current capture */
|
||||||
goto resume_capture;
|
goto resume_capture;
|
||||||
|
|
||||||
/* Finally, adjust the target rectangle */
|
/* Finally, adjust the target rectangle */
|
||||||
if (target.width > cam_rect.width)
|
if (target.width > cam_rect->width)
|
||||||
target.width = cam_rect.width;
|
target.width = cam_rect->width;
|
||||||
if (target.height > cam_rect.height)
|
if (target.height > cam_rect->height)
|
||||||
target.height = cam_rect.height;
|
target.height = cam_rect->height;
|
||||||
if (target.left + target.width > cam_rect.left + cam_rect.width)
|
if (target.left + target.width > cam_rect->left + cam_rect->width)
|
||||||
target.left = cam_rect.left + cam_rect.width -
|
target.left = cam_rect->left + cam_rect->width -
|
||||||
target.width;
|
target.width;
|
||||||
if (target.top + target.height > cam_rect.top + cam_rect.height)
|
if (target.top + target.height > cam_rect->top + cam_rect->height)
|
||||||
target.top = cam_rect.top + cam_rect.height -
|
target.top = cam_rect->top + cam_rect->height -
|
||||||
target.height;
|
target.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,14 +982,14 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
|
|||||||
*/
|
*/
|
||||||
dev_dbg(&icd->dev,
|
dev_dbg(&icd->dev,
|
||||||
"SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n",
|
"SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n",
|
||||||
cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top,
|
cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top,
|
||||||
target.width, target.height, target.left, target.top,
|
target.width, target.height, target.left, target.top,
|
||||||
rect->width, rect->height, rect->left, rect->top);
|
rect->width, rect->height, rect->left, rect->top);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
ceu_set_rect:
|
ceu_set_rect:
|
||||||
cam->camera_rect = cam_rect;
|
cam->camera_rect = *cam_rect;
|
||||||
|
|
||||||
rect->width = size_dst(target.width, hscale);
|
rect->width = size_dst(target.width, hscale);
|
||||||
rect->left = size_dst(target.left, hscale);
|
rect->left = size_dst(target.left, hscale);
|
||||||
|
@@ -797,7 +797,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
|
|||||||
rect.top = icd->rect_max.height + icd->rect_max.top -
|
rect.top = icd->rect_max.height + icd->rect_max.top -
|
||||||
rect.height;
|
rect.height;
|
||||||
|
|
||||||
ret = ici->ops->set_crop(icd, &rect);
|
ret = ici->ops->set_crop(icd, a);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
icd->rect_current = rect;
|
icd->rect_current = rect;
|
||||||
|
|
||||||
@@ -970,7 +970,7 @@ static int soc_camera_probe(struct device *dev)
|
|||||||
|
|
||||||
/* FIXME: this is racy, have to use driver-binding notification */
|
/* FIXME: this is racy, have to use driver-binding notification */
|
||||||
control = to_soc_camera_control(icd);
|
control = to_soc_camera_control(icd);
|
||||||
if (!control || !control->driver ||
|
if (!control || !control->driver || !dev_get_drvdata(control) ||
|
||||||
!try_module_get(control->driver->owner)) {
|
!try_module_get(control->driver->owner)) {
|
||||||
icl->del_device(icl);
|
icl->del_device(icl);
|
||||||
goto enodrv;
|
goto enodrv;
|
||||||
|
@@ -25,10 +25,15 @@ struct soc_camera_platform_priv {
|
|||||||
struct soc_camera_data_format format;
|
struct soc_camera_data_format format;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct soc_camera_platform_info *
|
static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev)
|
||||||
soc_camera_platform_get_info(struct soc_camera_device *icd)
|
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev));
|
struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
|
||||||
|
return container_of(subdev, struct soc_camera_platform_priv, subdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd));
|
||||||
return pdev->dev.platform_data;
|
return pdev->dev.platform_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,16 +52,10 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
|
|||||||
static unsigned long
|
static unsigned long
|
||||||
soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
|
soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
|
||||||
{
|
{
|
||||||
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
|
struct soc_camera_platform_info *p = get_info(icd);
|
||||||
return p->bus_param;
|
return p->bus_param;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int soc_camera_platform_set_crop(struct soc_camera_device *icd,
|
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
|
static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
|
||||||
struct v4l2_format *f)
|
struct v4l2_format *f)
|
||||||
{
|
{
|
||||||
@@ -71,7 +70,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
|
|||||||
static void soc_camera_platform_video_probe(struct soc_camera_device *icd,
|
static void soc_camera_platform_video_probe(struct soc_camera_device *icd,
|
||||||
struct platform_device *pdev)
|
struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
|
struct soc_camera_platform_priv *priv = get_priv(pdev);
|
||||||
struct soc_camera_platform_info *p = pdev->dev.platform_data;
|
struct soc_camera_platform_info *p = pdev->dev.platform_data;
|
||||||
|
|
||||||
priv->format.name = p->format_name;
|
priv->format.name = p->format_name;
|
||||||
@@ -96,7 +95,6 @@ static struct v4l2_subdev_ops platform_subdev_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct soc_camera_ops soc_camera_platform_ops = {
|
static struct soc_camera_ops soc_camera_platform_ops = {
|
||||||
.set_crop = soc_camera_platform_set_crop,
|
|
||||||
.set_bus_param = soc_camera_platform_set_bus_param,
|
.set_bus_param = soc_camera_platform_set_bus_param,
|
||||||
.query_bus_param = soc_camera_platform_query_bus_param,
|
.query_bus_param = soc_camera_platform_query_bus_param,
|
||||||
};
|
};
|
||||||
@@ -124,7 +122,9 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
icd = to_soc_camera_dev(p->dev);
|
icd = to_soc_camera_dev(p->dev);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, priv);
|
/* soc-camera convention: control's drvdata points to the subdev */
|
||||||
|
platform_set_drvdata(pdev, &priv->subdev);
|
||||||
|
/* Set the control device reference */
|
||||||
dev_set_drvdata(&icd->dev, &pdev->dev);
|
dev_set_drvdata(&icd->dev, &pdev->dev);
|
||||||
|
|
||||||
icd->width_min = 0;
|
icd->width_min = 0;
|
||||||
@@ -158,7 +158,7 @@ evdrs:
|
|||||||
|
|
||||||
static int soc_camera_platform_remove(struct platform_device *pdev)
|
static int soc_camera_platform_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
|
struct soc_camera_platform_priv *priv = get_priv(pdev);
|
||||||
struct soc_camera_platform_info *p = pdev->dev.platform_data;
|
struct soc_camera_platform_info *p = pdev->dev.platform_data;
|
||||||
struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
|
struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
|
||||||
|
|
||||||
|
@@ -616,11 +616,12 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int tw9910_set_crop(struct soc_camera_device *icd,
|
static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
struct v4l2_rect *rect)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
struct v4l2_rect *rect = &a->c;
|
||||||
|
struct i2c_client *client = sd->priv;
|
||||||
struct tw9910_priv *priv = to_tw9910(client);
|
struct tw9910_priv *priv = to_tw9910(client);
|
||||||
|
struct soc_camera_device *icd = client->dev.platform_data;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
u8 val;
|
u8 val;
|
||||||
|
|
||||||
@@ -716,15 +717,15 @@ tw9910_set_fmt_error:
|
|||||||
|
|
||||||
static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
static int tw9910_s_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;
|
struct v4l2_pix_format *pix = &f->fmt.pix;
|
||||||
/* See tw9910_set_crop() - no proper cropping support */
|
/* See tw9910_s_crop() - no proper cropping support */
|
||||||
struct v4l2_rect rect = {
|
struct v4l2_crop a = {
|
||||||
.left = 0,
|
.c = {
|
||||||
.top = 0,
|
.left = 0,
|
||||||
.width = pix->width,
|
.top = 0,
|
||||||
.height = pix->height,
|
.width = pix->width,
|
||||||
|
.height = pix->height,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
@@ -738,10 +739,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
|||||||
if (i == ARRAY_SIZE(tw9910_color_fmt))
|
if (i == ARRAY_SIZE(tw9910_color_fmt))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = tw9910_set_crop(icd, &rect);
|
ret = tw9910_s_crop(sd, &a);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
pix->width = rect.width;
|
pix->width = a.c.width;
|
||||||
pix->height = rect.height;
|
pix->height = a.c.height;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -821,7 +822,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct soc_camera_ops tw9910_ops = {
|
static struct soc_camera_ops tw9910_ops = {
|
||||||
.set_crop = tw9910_set_crop,
|
|
||||||
.set_bus_param = tw9910_set_bus_param,
|
.set_bus_param = tw9910_set_bus_param,
|
||||||
.query_bus_param = tw9910_query_bus_param,
|
.query_bus_param = tw9910_query_bus_param,
|
||||||
.enum_input = tw9910_enum_input,
|
.enum_input = tw9910_enum_input,
|
||||||
@@ -840,6 +840,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
|
|||||||
.s_stream = tw9910_s_stream,
|
.s_stream = tw9910_s_stream,
|
||||||
.s_fmt = tw9910_s_fmt,
|
.s_fmt = tw9910_s_fmt,
|
||||||
.try_fmt = tw9910_try_fmt,
|
.try_fmt = tw9910_try_fmt,
|
||||||
|
.s_crop = tw9910_s_crop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops tw9910_subdev_ops = {
|
static struct v4l2_subdev_ops tw9910_subdev_ops = {
|
||||||
|
@@ -76,7 +76,7 @@ struct soc_camera_host_ops {
|
|||||||
int (*get_formats)(struct soc_camera_device *, int,
|
int (*get_formats)(struct soc_camera_device *, int,
|
||||||
struct soc_camera_format_xlate *);
|
struct soc_camera_format_xlate *);
|
||||||
void (*put_formats)(struct soc_camera_device *);
|
void (*put_formats)(struct soc_camera_device *);
|
||||||
int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
|
int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *);
|
||||||
int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
|
int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
|
||||||
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
|
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
|
||||||
void (*init_videobuf)(struct videobuf_queue *,
|
void (*init_videobuf)(struct videobuf_queue *,
|
||||||
@@ -185,7 +185,6 @@ struct soc_camera_ops {
|
|||||||
int (*resume)(struct soc_camera_device *);
|
int (*resume)(struct soc_camera_device *);
|
||||||
int (*init)(struct soc_camera_device *);
|
int (*init)(struct soc_camera_device *);
|
||||||
int (*release)(struct soc_camera_device *);
|
int (*release)(struct soc_camera_device *);
|
||||||
int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
|
|
||||||
unsigned long (*query_bus_param)(struct soc_camera_device *);
|
unsigned long (*query_bus_param)(struct soc_camera_device *);
|
||||||
int (*set_bus_param)(struct soc_camera_device *, unsigned long);
|
int (*set_bus_param)(struct soc_camera_device *, unsigned long);
|
||||||
int (*get_chip_id)(struct soc_camera_device *,
|
int (*get_chip_id)(struct soc_camera_device *,
|
||||||
|
Reference in New Issue
Block a user