Commit 979ea1dd authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

V4L/DVB (12510): soc-camera: (partially) convert to v4l2-(sub)dev API

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: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0bab829d
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -219,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
int ret;
if (unlikely(!pcdev->active)) {
dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n");
return -EFAULT;
}
......@@ -229,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
vbuf->size, pcdev->res->start +
CSIRXR, DMA_MODE_READ);
if (unlikely(ret))
dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n");
dev_err(pcdev->icd->dev.parent, "Failed to setup DMA sg list\n");
return ret;
}
......@@ -334,14 +334,14 @@ static void mx1_camera_dma_irq(int channel, void *data)
imx_dma_disable(channel);
if (unlikely(!pcdev->active)) {
dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n");
goto out;
}
vb = &pcdev->active->vb;
buf = container_of(vb, struct mx1_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
dev_dbg(pcdev->icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
mx1_camera_wakeup(pcdev, vb, buf);
......@@ -362,7 +362,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx1_camera_dev *pcdev = ici->priv;
videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev,
videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent,
&pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
......@@ -381,7 +381,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
* they get a nice Oops */
div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, "
dev_dbg(pcdev->icd->dev.parent, "System clock %lukHz, target freq %dkHz, "
"divisor %lu\n", lcdclk / 1000, mclk / 1000, div);
return div;
......@@ -391,7 +391,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
{
unsigned int csicr1 = CSICR1_EN;
dev_dbg(pcdev->soc_host.dev, "Activate device\n");
dev_dbg(pcdev->icd->dev.parent, "Activate device\n");
clk_enable(pcdev->clk);
......@@ -407,7 +407,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
{
dev_dbg(pcdev->soc_host.dev, "Deactivate device\n");
dev_dbg(pcdev->icd->dev.parent, "Deactivate device\n");
/* Disable all CSI interface */
__raw_writel(0x00, pcdev->base + CSICR1);
......@@ -432,10 +432,8 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
icd->devnum);
mx1_camera_activate(pcdev);
ret = icd->ops->init(icd);
if (!ret)
pcdev->icd = icd;
pcdev->icd = icd;
ebusy:
return ret;
......@@ -459,8 +457,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n",
icd->devnum);
icd->ops->release(icd);
mx1_camera_deactivate(pcdev);
pcdev->icd = NULL;
......@@ -546,11 +542,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
ret = icd->ops->set_fmt(icd, f);
ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f);
if (!ret) {
icd->buswidth = xlate->buswidth;
icd->current_fmt = xlate->host_fmt;
......@@ -562,10 +558,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
static int mx1_camera_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
/* TODO: limit to mx1 hardware capabilities */
/* limit to sensor capabilities */
return icd->ops->try_fmt(icd, f);
return v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f);
}
static int mx1_camera_reqbufs(struct soc_camera_file *icf,
......@@ -737,7 +734,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
pcdev->soc_host.drv_name = DRIVER_NAME;
pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
pcdev->soc_host.priv = pcdev;
pcdev->soc_host.dev = &pdev->dev;
pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id;
err = soc_camera_host_register(&pcdev->soc_host);
if (err)
......
......@@ -431,7 +431,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, ici->dev,
videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent,
&mx3_cam->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
......@@ -494,17 +494,11 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
int ret;
if (mx3_cam->icd) {
ret = -EBUSY;
goto ebusy;
}
if (mx3_cam->icd)
return -EBUSY;
mx3_camera_activate(mx3_cam, icd);
ret = icd->ops->init(icd);
if (ret < 0)
goto einit;
mx3_cam->icd = icd;
......@@ -512,12 +506,6 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
icd->devnum);
return 0;
einit:
clk_disable(mx3_cam->clk);
ebusy:
return ret;
}
/* Called with .video_lock held */
......@@ -534,8 +522,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
*ichan = NULL;
}
icd->ops->release(icd);
clk_disable(mx3_cam->clk);
mx3_cam->icd = NULL;
......@@ -600,7 +586,7 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
*flags |= SOCAM_DATAWIDTH_4;
break;
default:
dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n",
dev_info(mx3_cam->soc_host.v4l2_dev.dev, "Unsupported bus width %d\n",
buswidth);
return -EINVAL;
}
......@@ -616,7 +602,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(icd->dev.parent, "requested bus width %d bit: %d\n", depth, ret);
if (ret < 0)
return ret;
......@@ -639,7 +625,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
if (!rq)
return false;
pdata = rq->mx3_cam->soc_host.dev->platform_data;
pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data;
return rq->id == chan->chan_id &&
pdata->dma_dev == chan->device->dev;
......@@ -699,7 +685,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(icd->dev.parent, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
......@@ -711,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(icd->dev.parent, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
......@@ -724,7 +710,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,
dev_dbg(icd->dev.parent,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
......@@ -831,7 +817,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
......@@ -847,7 +833,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
configure_geometry(mx3_cam, &rect);
ret = icd->ops->set_fmt(icd, f);
ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f);
if (!ret) {
icd->buswidth = xlate->buswidth;
icd->current_fmt = xlate->host_fmt;
......@@ -868,7 +854,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(icd->dev.parent, "Format %x not found\n", pixfmt);
return -EINVAL;
}
......@@ -885,7 +871,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
/* camera has to see its format, but the user the original one */
pix->pixelformat = xlate->cam_fmt->fourcc;
/* limit to sensor capabilities */
ret = icd->ops->try_fmt(icd, f);
ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f);
pix->pixelformat = xlate->host_fmt->fourcc;
field = pix->field;
......@@ -935,11 +921,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(icd->dev.parent, "Format %x not found\n", pixfmt);
return -EINVAL;
}
dev_dbg(ici->dev, "requested bus width %d bit: %d\n",
dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n",
icd->buswidth, ret);
if (ret < 0)
......@@ -948,10 +934,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
camera_flags = icd->ops->query_bus_param(icd);
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
dev_dbg(icd->dev.parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
camera_flags, bus_flags, common_flags);
if (!common_flags) {
dev_dbg(ici->dev, "no common flags");
dev_dbg(icd->dev.parent, "no common flags");
return -EINVAL;
}
......@@ -1005,7 +991,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
ret = icd->ops->set_bus_param(icd, common_flags);
if (ret < 0) {
dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
dev_dbg(icd->dev.parent, "camera set_bus_param(%lx) returned %d\n",
common_flags, ret);
return ret;
}
......@@ -1060,7 +1046,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(icd->dev.parent, "Set SENS_CONF to %x\n", sens_conf | dw);
return 0;
}
......@@ -1145,7 +1131,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
soc_host->drv_name = MX3_CAM_DRV_NAME;
soc_host->ops = &mx3_soc_camera_host_ops;
soc_host->priv = mx3_cam;
soc_host->dev = &pdev->dev;
soc_host->v4l2_dev.dev = &pdev->dev;
soc_host->nr = pdev->id;
err = soc_camera_host_register(soc_host);
......
This diff is collapsed.
This diff is collapsed.
......@@ -347,10 +347,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
int ret = -EBUSY;
if (pcdev->icd)
goto err;
return -EBUSY;
dev_info(&icd->dev,
"SuperH Mobile CEU driver attached to camera %d\n",
......@@ -358,19 +357,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
clk_enable(pcdev->clk);
ret = icd->ops->init(icd);
if (ret) {
clk_disable(pcdev->clk);
goto err;
}
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
while (ceu_read(pcdev, CSTSR) & 1)
msleep(1);
pcdev->icd = icd;
err:
return ret;
return 0;
}
/* Called with .video_lock held */
......@@ -396,8 +389,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
}
spin_unlock_irqrestore(&pcdev->lock, flags);
icd->ops->release(icd);
clk_disable(pcdev->clk);
dev_info(&icd->dev,
......@@ -614,7 +605,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
dev_dbg(ici->dev, "Providing format %s using %s\n",
dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n",
sh_mobile_ceu_formats[k].name,
icd->formats[idx].name);
}
......@@ -627,7 +618,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
dev_dbg(ici->dev,
dev_dbg(ici->v4l2_dev.dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
......@@ -649,18 +640,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
struct sh_mobile_ceu_dev *pcdev = ici->priv;
__u32 pixfmt = f->fmt.pix.pixelformat;
const struct soc_camera_format_xlate *xlate;
struct v4l2_format cam_f = *f;
int ret;
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
dev_warn(ici->dev, "Format %x not found\n", pixfmt);
dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
ret = icd->ops->set_fmt(icd, &cam_f);
f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f);
f->fmt.pix.pixelformat = pixfmt;
if (!ret) {
icd->buswidth = xlate->buswidth;
icd->current_fmt = xlate->host_fmt;
......@@ -681,7 +671,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
dev_warn(ici->dev, "Format %x not found\n", pixfmt);
dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
......@@ -694,8 +684,11 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
DIV_ROUND_UP(xlate->host_fmt->depth, 8);
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
/* limit to sensor capabilities */
ret = icd->ops->try_fmt(icd, f);
ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f);
f->fmt.pix.pixelformat = pixfmt;
if (ret < 0)
return ret;
......@@ -771,7 +764,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
videobuf_queue_dma_contig_init(q,
&sh_mobile_ceu_videobuf_ops,
ici->dev, &pcdev->lock,
ici->v4l2_dev.dev, &pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
pcdev->is_interlaced ?
V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
......@@ -794,7 +787,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
.init_videobuf = sh_mobile_ceu_init_videobuf,
};
static int sh_mobile_ceu_probe(struct platform_device *pdev)
static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
{
struct sh_mobile_ceu_dev *pcdev;
struct resource *res;
......@@ -867,7 +860,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
pm_runtime_resume(&pdev->dev);
pcdev->ici.priv = pcdev;
pcdev->ici.dev = &pdev->dev;
pcdev->ici.v4l2_dev.dev = &pdev->dev;
pcdev->ici.nr = pdev->id;
pcdev->ici.drv_name = dev_name(&pdev->dev);
pcdev->ici.ops = &sh_mobile_ceu_host_ops;
......@@ -891,7 +884,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
return err;
}
static int sh_mobile_ceu_remove(struct platform_device *pdev)
static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
{
struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
......@@ -929,7 +922,7 @@ static struct platform_driver sh_mobile_ceu_driver = {
.pm = &sh_mobile_ceu_dev_pm_ops,
},
.probe = sh_mobile_ceu_probe,
.remove = sh_mobile_ceu_remove,
.remove = __exit_p(sh_mobile_ceu_remove),
};
static int __init sh_mobile_ceu_init(void)
......
This diff is collapsed.
......@@ -16,11 +16,12 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-subdev.h>
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
struct soc_camera_platform_priv {
struct v4l2_subdev subdev;
struct soc_camera_data_format format;
};
......@@ -31,36 +32,10 @@ soc_camera_platform_get_info(struct soc_camera_device *icd)
return pdev->dev.platform_data;
}
static int soc_camera_platform_init(struct soc_camera_device *icd)
static int soc_camera_platform_s_stream(struct v4l2_subdev *sd, int enable)
{
struct soc_camera_link *icl = to_soc_camera_link(icd);
if (icl->power)
icl->power(dev_get_drvdata(&icd->dev), 1);
return 0;
}
static int soc_camera_platform_release(struct soc_camera_device *icd)
{
struct soc_camera_link *icl = to_soc_camera_link(icd);
if (icl->power)
icl->power(dev_get_drvdata(&icd->dev), 0);
return 0;
}
static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
{
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
return p->set_capture(p, 1);
}
static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
{
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
return p->set_capture(p, 0);
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
return p->set_capture(p, enable);
}
static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
......@@ -82,16 +57,10 @@ static int soc_camera_platform_set_crop(struct soc_camera_device *icd,
return 0;
}
static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
struct v4l2_format *f)
{
return 0;
}
static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
struct v4l2_pix_format *pix = &f->fmt.pix;
pix->width = p->format.width;
......@@ -99,12 +68,11 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
return 0;
}
static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
struct platform_device *pdev)
static void soc_camera_platform_video_probe(struct soc_camera_device *icd,
struct platform_device *pdev)
{
struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
struct soc_camera_platform_info *p = pdev->dev.platform_data;
int ret;
priv->format.name = p->format_name;
priv->format.depth = p->format_depth;
......@@ -113,28 +81,29 @@ static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
icd->formats = &priv->format;
icd->num_formats = 1;
/* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */
ret = soc_camera_video_start(icd, &pdev->dev);
soc_camera_video_stop(icd);
return ret;
}
static struct v4l2_subdev_core_ops platform_subdev_core_ops;
static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
.s_stream = soc_camera_platform_s_stream,
.try_fmt = soc_camera_platform_try_fmt,
};
static struct v4l2_subdev_ops platform_subdev_ops = {
.core = &platform_subdev_core_ops,
.video = &platform_subdev_video_ops,
};
static struct soc_camera_ops soc_camera_platform_ops = {
.owner = THIS_MODULE,
.init = soc_camera_platform_init,
.release = soc_camera_platform_release,
.start_capture = soc_camera_platform_start_capture,
.stop_capture = soc_camera_platform_stop_capture,
.set_crop = soc_camera_platform_set_crop,
.set_fmt = soc_camera_platform_set_fmt,
.try_fmt = soc_camera_platform_try_fmt,
.set_bus_param = soc_camera_platform_set_bus_param,
.query_bus_param = soc_camera_platform_query_bus_param,
};
static int soc_camera_platform_probe(struct platform_device *pdev)
{
struct soc_camera_host *ici;
struct soc_camera_platform_priv *priv;
struct soc_camera_platform_info *p = pdev->dev.platform_data;
struct soc_camera_device *icd;
......@@ -143,35 +112,48 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
if (!p)
return -EINVAL;
if (!p->dev) {
dev_err(&pdev->dev,
"Platform has not set soc_camera_device pointer!\n");
return -EINVAL;
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
icd = to_soc_camera_dev(p->dev);
if (!icd)
goto enoicd;
icd->ops = &soc_camera_platform_ops;
platform_set_drvdata(pdev, priv);
dev_set_drvdata(&icd->dev, &pdev->dev);
icd->width_min = 0;
icd->width_max = p->format.width;
icd->height_min = 0;
icd->height_max = p->format.height;
icd->y_skip_top = 0;
icd->ops = &soc_camera_platform_ops;
ret = soc_camera_platform_video_probe(icd, pdev);
if (ret) {
icd->ops = NULL;
kfree(priv);
}
ici = to_soc_camera_host(icd->dev.parent);
soc_camera_platform_video_probe(icd, pdev);
v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
v4l2_set_subdevdata(&priv->subdev, p);
priv->subdev.grp_id = (__u32)icd;
strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE);
ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev);
if (ret)
goto evdrs;
return ret;
enoicd:
evdrs:
icd->ops = NULL;
platform_set_drvdata(pdev, NULL);
kfree(priv);
return -EINVAL;
return ret;
}
static int soc_camera_platform_remove(struct platform_device *pdev)
......@@ -180,7 +162,9 @@ static int soc_camera_platform_remove(struct platform_device *pdev)
struct soc_camera_platform_info *p = pdev->dev.platform_data;
struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
v4l2_device_unregister_subdev(&priv->subdev);
icd->ops = NULL;
platform_set_drvdata(pdev, NULL);
kfree(priv);
return 0;
}
......@@ -188,6 +172,7 @@ static int soc_camera_platform_remove(struct platform_device *pdev)
static struct platform_driver soc_camera_platform_driver = {
.driver = {
.name = "soc_camera_platform",
.owner = THIS_MODULE,
},
.probe = soc_camera_platform_probe,
.remove = soc_camera_platform_remove,
......
......@@ -24,7 +24,7 @@
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-common.h>
#include <media/v4l2-subdev.h>
#include <media/soc_camera.h>
#include <media/tw9910.h>
......@@ -223,6 +223,7 @@ struct tw9910_hsync_ctrl {
};
struct tw9910_priv {
struct v4l2_subdev subdev;
struct tw9910_video_info *info;
const struct tw9910_scale_ctrl *scale;
};
......@@ -354,6 +355,11 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
/*
* general function
*/
static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
{
return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev);
}
static int tw9910_set_scale(struct i2c_client *client,
const struct tw9910_scale_ctrl *scale)
{
......@@ -507,47 +513,20 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
/*
* soc_camera_ops function
*/
static int tw9910_init(struct soc_camera_device *icd)
static int tw9910_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 tw9910_priv *priv = to_tw9910(client);
if (icl