Commit 24c608a5 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 c9ff171c
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 @@ passthrough:
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.
......@@ -348,10 +348,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",
......@@ -359,19 +358,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 */
......@@ -397,8 +390,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,
......@@ -615,7 +606,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);
}
......@@ -628,7 +619,7 @@ add_single_format:
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);
}
......@@ -650,18 +641,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;
......@@ -682,7 +672,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;
}
......@@ -695,8 +685,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;
......@@ -772,7 +765,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,
......@@ -795,7 +788,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;
......@@ -873,7 +866,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
}
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;
......@@ -899,7 +892,7 @@ exit:
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,
......@@ -920,7 +913,7 @@ static struct platform_driver sh_mobile_ceu_driver = {
.name = "sh_mobile_ceu",
},
.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->power) {
ret = icl->power(&client->dev, 1);
if (ret < 0)
return ret;
}
if (icl->reset)
ret = icl->reset(&client->dev);
return ret;
}
static int tw9910_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 tw9910_start_capture(struct soc_camera_device *icd)
{
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct tw9910_priv *priv = i2c_get_clientdata(client);
if (!enable)
return 0;
if (!priv->scale) {
dev_err(&icd->dev, "norm select error\n");
dev_err(&client->dev, "norm select error\n");
return -EPERM;
}
dev_dbg(&icd->dev, "%s %dx%d\n",
dev_dbg(&client->dev, "%s %dx%d\n",
priv->scale->name,
priv->scale->width,
priv->scale->height);
......@@ -555,11 +534,6 @@ static int tw9910_start_capture(struct soc_camera_device *icd)
return 0;
}
static int tw9910_stop_capture(struct soc_camera_device *icd)
{
return 0;
}
static int tw9910_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
......@@ -569,7 +543,7 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd,
static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
{
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct tw9910_priv *priv = i2c_get_clientdata(client);
struct tw9910_priv *priv = to_tw9910(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 |
......@@ -578,21 +552,11 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
return soc_camera_apply_sensor_flags(icl, flags);
}
static int tw9910_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
id->ident = V4L2_IDENT_TW9910;
id->revision = 0;
return 0;
}
static int tw9910_set_std(struct soc_camera_device *icd,
v4l2_std_id *a)
static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
{
int ret = -EINVAL;
if (*a & (V4L2_STD_NTSC | V4L2_STD_PAL))
if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL))
ret = 0;
return ret;
......@@ -608,11 +572,20 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
return 0;
}
static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *id)
{
id->ident = V4L2_IDENT_TW9910;
id->revision = 0;
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int tw9910_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
static int tw9910_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;
if (reg->reg > 0xff)
......@@ -630,10 +603,10 @@ static int tw9910_get_register(struct soc_camera_device *icd,
return 0;
}
static int tw9910_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
static int tw9910_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)
......@@ -647,7 +620,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct tw9910_priv *priv = i2c_get_clientdata(client);
struct tw9910_priv *priv = to_tw9910(client);
int ret = -EINVAL;
u8 val;
......@@ -736,9 +709,10 @@ tw9910_set_fmt_error:
return ret;
}
static int tw9910_set_fmt(struct soc_camera_device *icd,
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_rect rect = {
.left = icd->x_current,
......@@ -761,16 +735,17 @@ static int tw9910_set_fmt(struct soc_camera_device *icd,
return tw9910_set_crop(icd, &rect);
}
static int tw9910_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
struct i2c_client *client = sd->priv;
struct soc_camera_device *icd = client->dev.platform_data;
struct v4l2_pix_format *pix = &f->fmt.pix;
const struct tw9910_scale_ctrl *scale;
if (V4L2_FIELD_ANY == pix->field) {
pix->field = V4L2_FIELD_INTERLACED;
} else if (V4L2_FIELD_INTERLACED != pix->field) {
dev_err(&icd->dev, "Field type invalid.\n");
dev_err(&client->dev, "Field type invalid.\n");
return -EINVAL;
}
......@@ -790,9 +765,8 @@ static int tw9910_try_fmt(struct soc_camera_device *icd,
static int tw9910_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{
struct tw9910_priv *priv = i2c_get_clientdata(client);
struct tw9910_priv *priv = to_tw9910(client);
s32 val;
int ret;
/*
* We must have a parent by now. And it cannot be a wrong one.
......@@ -814,18 +788,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
icd->formats = tw9910_color_fmt;
icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/*
* check and show Product ID
*/
val = i2c_smbus_read_byte_data(client, ID);
soc_camera_video_stop(icd);
if (0x0B != GET_ID(val) ||
0x00 != GET_ReV(val)) {
dev_err(&icd->dev,
......@@ -839,29 +806,36 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
icd->vdev->current_norm = V4L2_STD_NTSC;
return ret;
return 0;
}
static struct soc_camera_ops tw9910_ops = {
.owner = THIS_MODULE,
.init = tw9910_init,
.release = tw9910_release,
.start_capture = tw9910_start_capture,
.stop_capture = tw9910_stop_capture,
.set_crop = tw9910_set_crop,
.set_fmt = tw9910_set_fmt,
.try_fmt = tw9910_try_fmt,
.set_bus_param = tw9910_set_bus_param,
.query_bus_param = tw9910_query_bus_param,
.get_chip_id = tw9910_get_chip_id,
.set_std = tw9910_set_std,
.enum_input = tw9910_enum_input,
};
static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
.g_chip_ident = tw9910_g_chip_ident,
.s_std = tw9910_s_std,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.get_register = tw9910_get_register,
.set_register = tw9910_set_register,
.g_register = tw9910_g_register,
.s_register = tw9910_s_register,
#endif
};
static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
.s_stream = tw9910_s_stream,
.s_fmt = tw9910_s_fmt,
.try_fmt = tw9910_try_fmt,
};
static struct v4l2_subdev_ops tw9910_subdev_ops = {
.core = &tw9910_subdev_core_ops,
.video = &tw9910_subdev_video_ops,
};
/*
* i2c_driver function
*/
......@@ -902,7 +876,8 @@ static int tw9910_probe(struct i2c_client *client,
return -ENOMEM;
priv->info = info;
i2c_set_clientdata(client, priv);
v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
icd->ops = &tw9910_ops;
icd->iface = info->link.bus_id;
......@@ -942,7 +917,7 @@ static int tw9910_probe(struct i2c_client *client,
static int tw9910_remove(struct i2c_client *client)
{
struct tw9910_priv *priv = i2c_get_clientdata(client);
struct tw9910_priv *priv = to_tw9910(client);
struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
......
......@@ -16,10 +16,12 @@
#include <linux/pm.h>
#include <linux/videodev2.h>
#include <media/videobuf-core.h>
#include <media/v4l2-device.h>
struct soc_camera_device {
struct list_head list;
struct device dev;
struct device *pdev; /* Platform device */
unsigned short width; /* Current window */
unsigned short height; /* sizes */
unsigned short x_min; /* Camera capabilities */
......@@ -45,7 +47,6 @@ struct soc_camera_device {
struct soc_camera_format_xlate *user_formats;
int num_user_formats;
enum v4l2_field field; /* Preserve field over close() */
struct module *owner;
void *host_priv; /* Per-device host private data */
/* soc_camera.c private count. Only accessed with .video_lock held */
int use_count;
......@@ -58,8 +59,8 @@ struct soc_camera_file {
};
struct soc_camera_host {
struct v4l2_device v4l2_dev;
struct list_head list;
struct device *dev;
unsigned char nr; /* Host number */
void *priv;
const char *drv_name;
......@@ -127,7 +128,9 @@ static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
{
return dev_get_drvdata(dev);
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev);
}
static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd)
......@@ -143,9 +146,6 @@ static inline struct device *to_soc_camera_control(struct soc_camera_device *icd
int soc_camera_host_register(struct soc_camera_host *ici);
void soc_camera_host_unregister(struct soc_camera_host *ici);
int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev);
void soc_camera_video_stop(struct soc_camera_device *icd);
const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
......@@ -176,28 +176,17 @@ struct soc_camera_format_xlate {
};
struct soc_camera_ops {
struct module *owner;
int (*suspend)(struct soc_camera_device *, pm_message_t state);
int (*resume)(struct soc_camera_device *);
int (*init)(struct soc_camera_device *);
int (*release)(struct soc_camera_device *);
int (*start_capture)(struct soc_camera_device *);
int (*stop_capture)(struct soc_camera_device *);
int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
unsigned long (*query_bus_param)(struct soc_camera_device *);
int (*set_bus_param)(struct soc_camera_device *, unsigned long);
int (*get_chip_id)(struct soc_camera_device *,
struct v4l2_dbg_chip_ident *);
int (*set_std)(struct soc_camera_device *, v4l2_std_id *);
int (*enum_input)(struct soc_camera_device *, struct v4l2_input *);
#ifdef CONFIG_VIDEO_ADV_DEBUG
int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *);
int (*set_register)(struct soc_camera_device *, struct v4l2_dbg_register *);
#endif
int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
const struct v4l2_queryctrl *controls;
int num_controls;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment