summaryrefslogtreecommitdiff
path: root/drivers/media/platform/intel/pxa_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/intel/pxa_camera.c')
-rw-r--r--drivers/media/platform/intel/pxa_camera.c103
1 files changed, 52 insertions, 51 deletions
diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index 9ed3c2e063de..bef1e7137f23 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -43,6 +43,7 @@
#include <linux/videodev2.h>
#include <linux/platform_data/media/camera-pxa.h>
+#include <linux/workqueue.h>
#define PXA_CAM_VERSION "0.0.6"
#define PXA_CAM_DRV_NAME "pxa27x-camera"
@@ -683,7 +684,7 @@ struct pxa_camera_dev {
unsigned int buf_sequence;
struct pxa_buffer *active;
- struct tasklet_struct task_eof;
+ struct work_struct eof_bh_work;
u32 save_cicr[5];
};
@@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
clk_disable_unprepare(pcdev->clk);
}
-static void pxa_camera_eof(struct tasklet_struct *t)
+static void pxa_camera_eof_bh_work(struct work_struct *t)
{
- struct pxa_camera_dev *pcdev = from_tasklet(pcdev, t, task_eof);
+ struct pxa_camera_dev *pcdev = from_work(pcdev, t, eof_bh_work);
unsigned long cifr;
struct pxa_buffer *buf;
@@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
if (status & CISR_EOF) {
cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;
__raw_writel(cicr0, pcdev->base + CICR0);
- tasklet_schedule(&pcdev->task_eof);
+ queue_work(system_bh_wq, &pcdev->eof_bh_work);
}
return IRQ_HANDLED;
@@ -1503,8 +1504,6 @@ static const struct vb2_ops pxac_vb2_ops = {
.buf_cleanup = pxac_vb2_cleanup,
.start_streaming = pxac_vb2_start_streaming,
.stop_streaming = pxac_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int pxa_camera_init_videobuf2(struct pxa_camera_dev *pcdev)
@@ -2044,7 +2043,7 @@ static const struct video_device pxa_camera_videodev_template = {
static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
- struct v4l2_async_subdev *asd)
+ struct v4l2_async_connection *asd)
{
int err;
struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
@@ -2123,7 +2122,7 @@ out:
static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
- struct v4l2_async_subdev *asd)
+ struct v4l2_async_connection *asd)
{
struct pxa_camera_dev *pcdev = v4l2_dev_to_pcdev(notifier->v4l2_dev);
@@ -2197,7 +2196,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
struct pxa_camera_dev *pcdev)
{
u32 mclk_rate;
- struct v4l2_async_subdev *asd;
+ struct v4l2_async_connection *asd;
struct device_node *np = dev->of_node;
struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int err = of_property_read_u32(np, "clock-frequency",
@@ -2207,7 +2206,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
pcdev->mclk = mclk_rate;
}
- np = of_graph_get_next_endpoint(np, NULL);
+ np = of_graph_get_endpoint_by_regs(np, 0, -1);
if (!np) {
dev_err(dev, "could not find endpoint\n");
return -EINVAL;
@@ -2252,7 +2251,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
asd = v4l2_async_nf_add_fwnode_remote(&pcdev->notifier,
of_fwnode_handle(np),
- struct v4l2_async_subdev);
+ struct v4l2_async_connection);
if (IS_ERR(asd))
err = PTR_ERR(asd);
out:
@@ -2274,9 +2273,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
int irq;
int err = 0, i;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
- if (!res || irq < 0)
+ if (irq < 0)
return -ENODEV;
pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
@@ -2289,27 +2287,41 @@ static int pxa_camera_probe(struct platform_device *pdev)
if (IS_ERR(pcdev->clk))
return PTR_ERR(pcdev->clk);
- v4l2_async_nf_init(&pcdev->notifier);
+ /*
+ * Request the regions.
+ */
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ pcdev->irq = irq;
+ pcdev->base = base;
+
+ err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
+ if (err)
+ return err;
+
+ v4l2_async_nf_init(&pcdev->notifier, &pcdev->v4l2_dev);
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
if (pcdev->pdata) {
- struct v4l2_async_subdev *asd;
+ struct v4l2_async_connection *asd;
pcdev->platform_flags = pcdev->pdata->flags;
pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
asd = v4l2_async_nf_add_i2c(&pcdev->notifier,
pcdev->pdata->sensor_i2c_adapter_id,
pcdev->pdata->sensor_i2c_address,
- struct v4l2_async_subdev);
+ struct v4l2_async_connection);
if (IS_ERR(asd))
err = PTR_ERR(asd);
} else if (pdev->dev.of_node) {
err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
} else {
- return -ENODEV;
+ err = -ENODEV;
}
if (err < 0)
- return err;
+ goto exit_v4l2_device_unregister;
if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
@@ -2338,21 +2350,12 @@ static int pxa_camera_probe(struct platform_device *pdev)
spin_lock_init(&pcdev->lock);
mutex_init(&pcdev->mlock);
- /*
- * Request the regions.
- */
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- pcdev->irq = irq;
- pcdev->base = base;
-
/* request dma */
pcdev->dma_chans[0] = dma_request_chan(&pdev->dev, "CI_Y");
if (IS_ERR(pcdev->dma_chans[0])) {
dev_err(&pdev->dev, "Can't request DMA for Y\n");
- return PTR_ERR(pcdev->dma_chans[0]);
+ err = PTR_ERR(pcdev->dma_chans[0]);
+ goto exit_notifier_cleanup;
}
pcdev->dma_chans[1] = dma_request_chan(&pdev->dev, "CI_U");
@@ -2379,45 +2382,43 @@ static int pxa_camera_probe(struct platform_device *pdev)
}
}
- /* request irq */
- err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
- PXA_CAM_DRV_NAME, pcdev);
- if (err) {
- dev_err(&pdev->dev, "Camera interrupt register failed\n");
- goto exit_free_dma;
- }
-
- tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
+ INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work);
pxa_camera_activate(pcdev);
platform_set_drvdata(pdev, pcdev);
- err = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
- if (err)
- goto exit_deactivate;
err = pxa_camera_init_videobuf2(pcdev);
if (err)
- goto exit_notifier_cleanup;
+ goto exit_deactivate;
+
+ /* request irq */
+ err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
+ PXA_CAM_DRV_NAME, pcdev);
+ if (err) {
+ dev_err(&pdev->dev, "Camera interrupt register failed\n");
+ goto exit_deactivate;
+ }
pcdev->notifier.ops = &pxa_camera_sensor_ops;
- err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
+ err = v4l2_async_nf_register(&pcdev->notifier);
if (err)
- goto exit_notifier_cleanup;
+ goto exit_deactivate;
return 0;
-exit_notifier_cleanup:
- v4l2_async_nf_cleanup(&pcdev->notifier);
- v4l2_device_unregister(&pcdev->v4l2_dev);
exit_deactivate:
pxa_camera_deactivate(pcdev);
- tasklet_kill(&pcdev->task_eof);
+ cancel_work_sync(&pcdev->eof_bh_work);
exit_free_dma:
dma_release_channel(pcdev->dma_chans[2]);
exit_free_dma_u:
dma_release_channel(pcdev->dma_chans[1]);
exit_free_dma_y:
dma_release_channel(pcdev->dma_chans[0]);
+exit_notifier_cleanup:
+ v4l2_async_nf_cleanup(&pcdev->notifier);
+exit_v4l2_device_unregister:
+ v4l2_device_unregister(&pcdev->v4l2_dev);
return err;
}
@@ -2426,7 +2427,7 @@ static void pxa_camera_remove(struct platform_device *pdev)
struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
pxa_camera_deactivate(pcdev);
- tasklet_kill(&pcdev->task_eof);
+ cancel_work_sync(&pcdev->eof_bh_work);
dma_release_channel(pcdev->dma_chans[0]);
dma_release_channel(pcdev->dma_chans[1]);
dma_release_channel(pcdev->dma_chans[2]);
@@ -2454,10 +2455,10 @@ static struct platform_driver pxa_camera_driver = {
.driver = {
.name = PXA_CAM_DRV_NAME,
.pm = &pxa_camera_pm,
- .of_match_table = of_match_ptr(pxa_camera_of_match),
+ .of_match_table = pxa_camera_of_match,
},
.probe = pxa_camera_probe,
- .remove_new = pxa_camera_remove,
+ .remove = pxa_camera_remove,
};
module_platform_driver(pxa_camera_driver);