summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/mx3_camera.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-17 22:39:23 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-17 22:39:23 -0300
commitfb2e83ece3c03b94ad9e9ca75d658729b684a789 (patch)
tree6c1d6b7124e5dd844b02007e66471e7e9238f707 /linux/drivers/media/video/mx3_camera.c
parent5e90c221e48890f2f2433f153d9584bc4bdd327a (diff)
parent1596f74981cbcf720947b4fd600028d24edfa783 (diff)
downloadmediapointer-dvb-s2-fb2e83ece3c03b94ad9e9ca75d658729b684a789.tar.gz
mediapointer-dvb-s2-fb2e83ece3c03b94ad9e9ca75d658729b684a789.tar.bz2
merge: http://linuxtv.org/hg/~hgoede/libv4l
From: Mauro Carvalho Chehab <mchehab@redhat.com> Priority: normal Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media/video/mx3_camera.c')
-rw-r--r--linux/drivers/media/video/mx3_camera.c207
1 files changed, 120 insertions, 87 deletions
diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c
index f525dc48f..e605c076e 100644
--- a/linux/drivers/media/video/mx3_camera.c
+++ b/linux/drivers/media/video/mx3_camera.c
@@ -87,7 +87,6 @@ struct mx3_camera_buffer {
* @soc_host: embedded soc_host object
*/
struct mx3_camera_dev {
- struct device *dev;
/*
* i.MX3x is only supposed to handle one camera on its Camera Sensor
* Interface. If anyone ever builds hardware to enable more than one
@@ -431,7 +430,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev,
+ videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev,
&mx3_cam->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
@@ -544,16 +543,14 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
}
static bool channel_change_requested(struct soc_camera_device *icd,
- const struct soc_camera_format_xlate *xlate,
- __u32 pixfmt, struct v4l2_rect *rect)
+ struct v4l2_rect *rect)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
- /* So far only one configuration is supported */
- return pixfmt || (ichan && rect->width * rect->height >
- icd->width * icd->height);
+ /* Do buffers have to be re-allocated or channel re-configured? */
+ return ichan && rect->width * rect->height > icd->width * icd->height;
}
static int test_platform_param(struct mx3_camera_dev *mx3_cam,
@@ -601,7 +598,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
*flags |= SOCAM_DATAWIDTH_4;
break;
default:
- dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth);
+ dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n",
+ buswidth);
return -EINVAL;
}
@@ -616,7 +614,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
unsigned long bus_flags, camera_flags;
int ret = test_platform_param(mx3_cam, depth, &bus_flags);
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret);
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret);
if (ret < 0)
return ret;
@@ -639,7 +637,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
if (!rq)
return false;
- pdata = rq->mx3_cam->dev->platform_data;
+ pdata = rq->mx3_cam->soc_host.dev->platform_data;
return rq->id == chan->chan_id &&
pdata->dma_dev == chan->device->dev;
@@ -699,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -711,7 +709,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -724,7 +722,7 @@ passthrough:
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -733,61 +731,10 @@ passthrough:
return formats;
}
-static int mx3_camera_set_fmt(struct soc_camera_device *icd,
- __u32 pixfmt, struct v4l2_rect *rect)
+static void configure_geometry(struct mx3_camera_dev *mx3_cam,
+ struct v4l2_rect *rect)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- const struct soc_camera_format_xlate *xlate;
u32 ctrl, width_field, height_field;
- int ret;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
- if (pixfmt && !xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
- return -EINVAL;
- }
-
- /*
- * We now know pixel formats and can decide upon DMA-channel(s)
- * So far only direct camera-to-memory is supported
- */
- if (channel_change_requested(icd, xlate, pixfmt, rect)) {
- dma_cap_mask_t mask;
- struct dma_chan *chan;
- struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
- /* We have to use IDMAC_IC_7 for Bayer / generic data */
- struct dma_chan_request rq = {.mx3_cam = mx3_cam,
- .id = IDMAC_IC_7};
-
- if (*ichan) {
- struct videobuf_buffer *vb, *_vb;
- dma_release_channel(&(*ichan)->dma_chan);
- *ichan = NULL;
- mx3_cam->active = NULL;
- list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_ERROR;
- wake_up(&vb->done);
- }
- }
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_PRIVATE, mask);
- chan = dma_request_channel(mask, chan_filter, &rq);
- if (!chan)
- return -EBUSY;
-
- *ichan = to_idmac_chan(chan);
- (*ichan)->client = mx3_cam;
- }
-
- /*
- * Might have to perform a complete interface initialisation like in
- * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
- * mxc_v4l2_s_fmt()
- */
/* Setup frame size - this cannot be changed on-the-fly... */
width_field = rect->width - 1;
@@ -808,9 +755,98 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
* No need to free resources here if we fail, we'll see if we need to
* do this next time we are called
*/
+}
+
+static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
+ /* We have to use IDMAC_IC_7 for Bayer / generic data */
+ struct dma_chan_request rq = {.mx3_cam = mx3_cam,
+ .id = IDMAC_IC_7};
+
+ if (*ichan) {
+ struct videobuf_buffer *vb, *_vb;
+ dma_release_channel(&(*ichan)->dma_chan);
+ *ichan = NULL;
+ mx3_cam->active = NULL;
+ list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
+ list_del_init(&vb->queue);
+ vb->state = VIDEOBUF_ERROR;
+ wake_up(&vb->done);
+ }
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+ chan = dma_request_channel(mask, chan_filter, &rq);
+ if (!chan)
+ return -EBUSY;
+
+ *ichan = to_idmac_chan(chan);
+ (*ichan)->client = mx3_cam;
- ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect);
- if (pixfmt && !ret) {
+ return 0;
+}
+
+static int mx3_camera_set_crop(struct soc_camera_device *icd,
+ struct v4l2_rect *rect)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx3_camera_dev *mx3_cam = ici->priv;
+
+ /*
+ * We now know pixel formats and can decide upon DMA-channel(s)
+ * So far only direct camera-to-memory is supported
+ */
+ if (channel_change_requested(icd, rect)) {
+ int ret = acquire_dma_channel(mx3_cam);
+ if (ret < 0)
+ return ret;
+ }
+
+ configure_geometry(mx3_cam, rect);
+
+ return icd->ops->set_crop(icd, rect);
+}
+
+static int mx3_camera_set_fmt(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx3_camera_dev *mx3_cam = ici->priv;
+ const struct soc_camera_format_xlate *xlate;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_rect rect = {
+ .left = icd->x_current,
+ .top = icd->y_current,
+ .width = pix->width,
+ .height = pix->height,
+ };
+ int ret;
+
+ xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+ if (!xlate) {
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
+ return -EINVAL;
+ }
+
+ ret = acquire_dma_channel(mx3_cam);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Might have to perform a complete interface initialisation like in
+ * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
+ * mxc_v4l2_s_fmt()
+ */
+
+ configure_geometry(mx3_cam, &rect);
+
+ ret = icd->ops->set_fmt(icd, f);
+ if (!ret) {
icd->buswidth = xlate->buswidth;
icd->current_fmt = xlate->host_fmt;
}
@@ -830,7 +866,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (pixfmt && !xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -897,11 +933,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n",
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n",
icd->buswidth, ret);
if (ret < 0)
@@ -911,7 +947,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
if (!common_flags) {
- dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n",
+ dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
camera_flags, bus_flags);
return -EINVAL;
}
@@ -1018,7 +1054,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
- dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
+ dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
return 0;
}
@@ -1027,10 +1063,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
.owner = THIS_MODULE,
.add = mx3_camera_add_device,
.remove = mx3_camera_remove_device,
-#ifdef CONFIG_PM
- .suspend = mx3_camera_suspend,
- .resume = mx3_camera_resume,
-#endif
+ .set_crop = mx3_camera_set_crop,
.set_fmt = mx3_camera_set_fmt,
.try_fmt = mx3_camera_try_fmt,
.get_formats = mx3_camera_get_formats,
@@ -1041,7 +1074,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
.set_bus_param = mx3_camera_set_bus_param,
};
-static int mx3_camera_probe(struct platform_device *pdev)
+static int __devinit mx3_camera_probe(struct platform_device *pdev)
{
struct mx3_camera_dev *mx3_cam;
struct resource *res;
@@ -1063,14 +1096,12 @@ static int mx3_camera_probe(struct platform_device *pdev)
}
memset(mx3_cam, 0, sizeof(*mx3_cam));
- mx3_cam->clk = clk_get(&pdev->dev, "csi_clk");
+ mx3_cam->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(mx3_cam->clk)) {
err = PTR_ERR(mx3_cam->clk);
goto eclkget;
}
- dev_set_drvdata(&pdev->dev, mx3_cam);
-
mx3_cam->pdata = pdev->dev.platform_data;
mx3_cam->platform_flags = mx3_cam->pdata->flags;
if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
@@ -1102,14 +1133,14 @@ static int mx3_camera_probe(struct platform_device *pdev)
}
mx3_cam->base = base;
- mx3_cam->dev = &pdev->dev;
soc_host = &mx3_cam->soc_host;
soc_host->drv_name = MX3_CAM_DRV_NAME;
soc_host->ops = &mx3_soc_camera_host_ops;
soc_host->priv = mx3_cam;
- soc_host->dev.parent = &pdev->dev;
+ soc_host->dev = &pdev->dev;
soc_host->nr = pdev->id;
+
err = soc_camera_host_register(soc_host);
if (err)
goto ecamhostreg;
@@ -1132,11 +1163,13 @@ egetres:
static int __devexit mx3_camera_remove(struct platform_device *pdev)
{
- struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx3_camera_dev *mx3_cam = container_of(soc_host,
+ struct mx3_camera_dev, soc_host);
clk_put(mx3_cam->clk);
- soc_camera_host_unregister(&mx3_cam->soc_host);
+ soc_camera_host_unregister(soc_host);
iounmap(mx3_cam->base);
@@ -1161,11 +1194,11 @@ static struct platform_driver mx3_camera_driver = {
.name = MX3_CAM_DRV_NAME,
},
.probe = mx3_camera_probe,
- .remove = __exit_p(mx3_camera_remove),
+ .remove = __devexit_p(mx3_camera_remove),
};
-static int __devinit mx3_camera_init(void)
+static int __init mx3_camera_init(void)
{
return platform_driver_register(&mx3_camera_driver);
}