forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/media/platform/pxa_camera.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * V4L2 Driver for PXA camera host
34 *
45 * Copyright (C) 2006, Sascha Hauer, Pengutronix
56 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
67 * Copyright (C) 2016, Robert Jarzmik <robert.jarzmik@free.fr>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
128 */
139
1410 #include <linux/init.h>
....@@ -68,7 +64,7 @@
6864 #define CIBR1 0x0030
6965 #define CIBR2 0x0038
7066
71
-#define CICR0_DMAEN (1 << 31) /* DMA request enable */
67
+#define CICR0_DMAEN (1UL << 31) /* DMA request enable */
7268 #define CICR0_PAR_EN (1 << 30) /* Parity enable */
7369 #define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */
7470 #define CICR0_ENB (1 << 28) /* Camera interface enable */
....@@ -85,7 +81,7 @@
8581 #define CICR0_EOFM (1 << 1) /* End-of-frame mask */
8682 #define CICR0_FOM (1 << 0) /* FIFO-overrun mask */
8783
88
-#define CICR1_TBIT (1 << 31) /* Transparency bit */
84
+#define CICR1_TBIT (1UL << 31) /* Transparency bit */
8985 #define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */
9086 #define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */
9187 #define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */
....@@ -609,42 +605,6 @@
609605 return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
610606 }
611607
612
-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
613
- unsigned int flags)
614
-{
615
- unsigned long common_flags;
616
- bool hsync = true, vsync = true, pclk, data, mode;
617
- bool mipi_lanes, mipi_clock;
618
-
619
- common_flags = cfg->flags & flags;
620
-
621
- switch (cfg->type) {
622
- case V4L2_MBUS_PARALLEL:
623
- hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
624
- V4L2_MBUS_HSYNC_ACTIVE_LOW);
625
- vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
626
- V4L2_MBUS_VSYNC_ACTIVE_LOW);
627
- /* fall through */
628
- case V4L2_MBUS_BT656:
629
- pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
630
- V4L2_MBUS_PCLK_SAMPLE_FALLING);
631
- data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
632
- V4L2_MBUS_DATA_ACTIVE_LOW);
633
- mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
634
- return (!hsync || !vsync || !pclk || !data || !mode) ?
635
- 0 : common_flags;
636
- case V4L2_MBUS_CSI2:
637
- mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
638
- mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
639
- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
640
- return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
641
- default:
642
- WARN_ON(1);
643
- return -EINVAL;
644
- }
645
- return 0;
646
-}
647
-
648608 /**
649609 * struct pxa_camera_format_xlate - match between host and sensor formats
650610 * @code: code of a sensor provided format
....@@ -697,7 +657,6 @@
697657 struct v4l2_pix_format current_pix;
698658
699659 struct v4l2_async_subdev asd;
700
- struct v4l2_async_subdev *asds[1];
701660
702661 /*
703662 * PXA27x is only supposed to handle one camera on its Quick Capture
....@@ -1021,7 +980,7 @@
1021980 * - a videobuffer is queued on the pcdev->capture list
1022981 *
1023982 * Please check the "DMA hot chaining timeslice issue" in
1024
- * Documentation/media/v4l-drivers/pxa_camera.rst
983
+ * Documentation/driver-api/media/drivers/pxa_camera.rst
1025984 *
1026985 * Context: should only be called within the dma irq handler
1027986 */
....@@ -1191,9 +1150,9 @@
11911150 clk_disable_unprepare(pcdev->clk);
11921151 }
11931152
1194
-static void pxa_camera_eof(unsigned long arg)
1153
+static void pxa_camera_eof(struct tasklet_struct *t)
11951154 {
1196
- struct pxa_camera_dev *pcdev = (struct pxa_camera_dev *)arg;
1155
+ struct pxa_camera_dev *pcdev = from_tasklet(pcdev, t, task_eof);
11971156 unsigned long cifr;
11981157 struct pxa_buffer *buf;
11991158
....@@ -1234,31 +1193,6 @@
12341193 }
12351194
12361195 return IRQ_HANDLED;
1237
-}
1238
-
1239
-static int test_platform_param(struct pxa_camera_dev *pcdev,
1240
- unsigned char buswidth, unsigned long *flags)
1241
-{
1242
- /*
1243
- * Platform specified synchronization and pixel clock polarities are
1244
- * only a recommendation and are only used during probing. The PXA270
1245
- * quick capture interface supports both.
1246
- */
1247
- *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
1248
- V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
1249
- V4L2_MBUS_HSYNC_ACTIVE_HIGH |
1250
- V4L2_MBUS_HSYNC_ACTIVE_LOW |
1251
- V4L2_MBUS_VSYNC_ACTIVE_HIGH |
1252
- V4L2_MBUS_VSYNC_ACTIVE_LOW |
1253
- V4L2_MBUS_DATA_ACTIVE_HIGH |
1254
- V4L2_MBUS_PCLK_SAMPLE_RISING |
1255
- V4L2_MBUS_PCLK_SAMPLE_FALLING;
1256
-
1257
- /* If requested data width is supported by the platform, use it */
1258
- if ((1 << (buswidth - 1)) & pcdev->width_flags)
1259
- return 0;
1260
-
1261
- return -EINVAL;
12621196 }
12631197
12641198 static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev,
....@@ -1393,7 +1327,7 @@
13931327 break;
13941328 default:
13951329 return -EINVAL;
1396
- };
1330
+ }
13971331 buf->nb_planes = nb_channels;
13981332
13991333 ret = sg_split(sgt->sgl, sgt->nents, 0, nb_channels,
....@@ -1443,7 +1377,7 @@
14431377
14441378 /*
14451379 * Please check the DMA prepared buffer structure in :
1446
- * Documentation/media/v4l-drivers/pxa_camera.rst
1380
+ * Documentation/driver-api/media/drivers/pxa_camera.rst
14471381 * Please check also in pxa_camera_check_link_miss() to understand why DMA chain
14481382 * modification while DMA chain is running will work anyway.
14491383 */
....@@ -1606,99 +1540,78 @@
16061540 */
16071541 static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev)
16081542 {
1543
+ unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample;
16091544 struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
16101545 u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc;
1611
- unsigned long bus_flags, common_flags;
1546
+ int mbus_config;
16121547 int ret;
16131548
1614
- ret = test_platform_param(pcdev,
1615
- pcdev->current_fmt->host_fmt->bits_per_sample,
1616
- &bus_flags);
1617
- if (ret < 0)
1618
- return ret;
1619
-
1620
- ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
1621
- if (!ret) {
1622
- common_flags = pxa_mbus_config_compatible(&cfg,
1623
- bus_flags);
1624
- if (!common_flags) {
1625
- dev_warn(pcdev_to_dev(pcdev),
1626
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
1627
- cfg.flags, bus_flags);
1628
- return -EINVAL;
1629
- }
1630
- } else if (ret != -ENOIOCTLCMD) {
1631
- return ret;
1632
- } else {
1633
- common_flags = bus_flags;
1549
+ if (!((1 << (bus_width - 1)) & pcdev->width_flags)) {
1550
+ dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u",
1551
+ bus_width);
1552
+ return -EINVAL;
16341553 }
16351554
16361555 pcdev->channels = 1;
16371556
1638
- /* Make choises, based on platform preferences */
1639
- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1640
- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
1641
- if (pcdev->platform_flags & PXA_CAMERA_HSP)
1642
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1643
- else
1644
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
1645
- }
1557
+ /* Make choices, based on platform preferences */
1558
+ mbus_config = 0;
1559
+ if (pcdev->platform_flags & PXA_CAMERA_MASTER)
1560
+ mbus_config |= V4L2_MBUS_MASTER;
1561
+ else
1562
+ mbus_config |= V4L2_MBUS_SLAVE;
16461563
1647
- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1648
- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
1649
- if (pcdev->platform_flags & PXA_CAMERA_VSP)
1650
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1651
- else
1652
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
1653
- }
1564
+ if (pcdev->platform_flags & PXA_CAMERA_HSP)
1565
+ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH;
1566
+ else
1567
+ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW;
16541568
1655
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
1656
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
1657
- if (pcdev->platform_flags & PXA_CAMERA_PCP)
1658
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
1659
- else
1660
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
1661
- }
1569
+ if (pcdev->platform_flags & PXA_CAMERA_VSP)
1570
+ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH;
1571
+ else
1572
+ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW;
16621573
1663
- cfg.flags = common_flags;
1664
- ret = sensor_call(pcdev, video, s_mbus_config, &cfg);
1574
+ if (pcdev->platform_flags & PXA_CAMERA_PCP)
1575
+ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING;
1576
+ else
1577
+ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
1578
+ mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH;
1579
+
1580
+ cfg.flags = mbus_config;
1581
+ ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg);
16651582 if (ret < 0 && ret != -ENOIOCTLCMD) {
1666
- dev_dbg(pcdev_to_dev(pcdev),
1667
- "camera s_mbus_config(0x%lx) returned %d\n",
1668
- common_flags, ret);
1583
+ dev_err(pcdev_to_dev(pcdev),
1584
+ "Failed to call set_mbus_config: %d\n", ret);
16691585 return ret;
16701586 }
16711587
1672
- pxa_camera_setup_cicr(pcdev, common_flags, pixfmt);
1673
-
1674
- return 0;
1675
-}
1676
-
1677
-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev,
1678
- unsigned char buswidth)
1679
-{
1680
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
1681
- unsigned long bus_flags, common_flags;
1682
- int ret = test_platform_param(pcdev, buswidth, &bus_flags);
1683
-
1684
- if (ret < 0)
1685
- return ret;
1686
-
1687
- ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
1688
- if (!ret) {
1689
- common_flags = pxa_mbus_config_compatible(&cfg,
1690
- bus_flags);
1691
- if (!common_flags) {
1692
- dev_warn(pcdev_to_dev(pcdev),
1693
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
1694
- cfg.flags, bus_flags);
1588
+ /*
1589
+ * If the requested media bus configuration has not been fully applied
1590
+ * make sure it is supported by the platform.
1591
+ *
1592
+ * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering
1593
+ * roles should match.
1594
+ */
1595
+ if (cfg.flags != mbus_config) {
1596
+ unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER |
1597
+ V4L2_MBUS_SLAVE);
1598
+ if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER |
1599
+ V4L2_MBUS_SLAVE))) {
1600
+ dev_err(pcdev_to_dev(pcdev),
1601
+ "Unsupported mbus configuration: bus mastering\n");
16951602 return -EINVAL;
16961603 }
1697
- } else if (ret == -ENOIOCTLCMD) {
1698
- ret = 0;
1604
+
1605
+ if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) {
1606
+ dev_err(pcdev_to_dev(pcdev),
1607
+ "Unsupported mbus configuration: DATA_ACTIVE_LOW\n");
1608
+ return -EINVAL;
1609
+ }
16991610 }
17001611
1701
- return ret;
1612
+ pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt);
1613
+
1614
+ return 0;
17021615 }
17031616
17041617 static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = {
....@@ -1745,11 +1658,6 @@
17451658 "Invalid format code #%u: %d\n", idx, code.code);
17461659 return 0;
17471660 }
1748
-
1749
- /* This also checks support for the requested bits-per-sample */
1750
- ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample);
1751
- if (ret < 0)
1752
- return 0;
17531661
17541662 switch (code.code) {
17551663 case MEDIA_BUS_FMT_UYVY8_2X8:
....@@ -1997,12 +1905,9 @@
19971905 static int pxac_vidioc_querycap(struct file *file, void *priv,
19981906 struct v4l2_capability *cap)
19991907 {
2000
- strlcpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info));
2001
- strlcpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver));
2002
- strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
2003
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2004
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
2005
-
1908
+ strscpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info));
1909
+ strscpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver));
1910
+ strscpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
20061911 return 0;
20071912 }
20081913
....@@ -2013,7 +1918,7 @@
20131918 return -EINVAL;
20141919
20151920 i->type = V4L2_INPUT_TYPE_CAMERA;
2016
- strlcpy(i->name, "Camera", sizeof(i->name));
1921
+ strscpy(i->name, "Camera", sizeof(i->name));
20171922
20181923 return 0;
20191924 }
....@@ -2202,7 +2107,7 @@
22022107 if (err)
22032108 goto out_sensor_poweroff;
22042109
2205
- err = video_register_device(&pcdev->vdev, VFL_TYPE_GRABBER, -1);
2110
+ err = video_register_device(&pcdev->vdev, VFL_TYPE_VIDEO, -1);
22062111 if (err) {
22072112 v4l2_err(v4l2_dev, "register video device failed: %d\n", err);
22082113 pcdev->sensor = NULL;
....@@ -2302,7 +2207,7 @@
23022207 {
23032208 u32 mclk_rate;
23042209 struct device_node *remote, *np = dev->of_node;
2305
- struct v4l2_fwnode_endpoint ep;
2210
+ struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
23062211 int err = of_property_read_u32(np, "clock-frequency",
23072212 &mclk_rate);
23082213 if (!err) {
....@@ -2354,13 +2259,11 @@
23542259 pcdev->platform_flags |= PXA_CAMERA_PCLK_EN;
23552260
23562261 asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
2357
- remote = of_graph_get_remote_port(np);
2358
- if (remote) {
2262
+ remote = of_graph_get_remote_port_parent(np);
2263
+ if (remote)
23592264 asd->match.fwnode = of_fwnode_handle(remote);
2360
- of_node_put(remote);
2361
- } else {
2265
+ else
23622266 dev_notice(dev, "no remote for %pOF\n", np);
2363
- }
23642267
23652268 out:
23662269 of_node_put(np);
....@@ -2400,15 +2303,17 @@
24002303 pcdev->res = res;
24012304
24022305 pcdev->pdata = pdev->dev.platform_data;
2403
- if (pdev->dev.of_node && !pcdev->pdata) {
2404
- err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd);
2405
- } else {
2306
+ if (pcdev->pdata) {
24062307 pcdev->platform_flags = pcdev->pdata->flags;
24072308 pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
24082309 pcdev->asd.match_type = V4L2_ASYNC_MATCH_I2C;
24092310 pcdev->asd.match.i2c.adapter_id =
24102311 pcdev->pdata->sensor_i2c_adapter_id;
24112312 pcdev->asd.match.i2c.address = pcdev->pdata->sensor_i2c_address;
2313
+ } else if (pdev->dev.of_node) {
2314
+ err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd);
2315
+ } else {
2316
+ return -ENODEV;
24122317 }
24132318 if (err < 0)
24142319 return err;
....@@ -2451,23 +2356,23 @@
24512356 pcdev->base = base;
24522357
24532358 /* request dma */
2454
- pcdev->dma_chans[0] = dma_request_slave_channel(&pdev->dev, "CI_Y");
2455
- if (!pcdev->dma_chans[0]) {
2359
+ pcdev->dma_chans[0] = dma_request_chan(&pdev->dev, "CI_Y");
2360
+ if (IS_ERR(pcdev->dma_chans[0])) {
24562361 dev_err(&pdev->dev, "Can't request DMA for Y\n");
2457
- return -ENODEV;
2362
+ return PTR_ERR(pcdev->dma_chans[0]);
24582363 }
24592364
2460
- pcdev->dma_chans[1] = dma_request_slave_channel(&pdev->dev, "CI_U");
2461
- if (!pcdev->dma_chans[1]) {
2462
- dev_err(&pdev->dev, "Can't request DMA for Y\n");
2463
- err = -ENODEV;
2365
+ pcdev->dma_chans[1] = dma_request_chan(&pdev->dev, "CI_U");
2366
+ if (IS_ERR(pcdev->dma_chans[1])) {
2367
+ dev_err(&pdev->dev, "Can't request DMA for U\n");
2368
+ err = PTR_ERR(pcdev->dma_chans[1]);
24642369 goto exit_free_dma_y;
24652370 }
24662371
2467
- pcdev->dma_chans[2] = dma_request_slave_channel(&pdev->dev, "CI_V");
2468
- if (!pcdev->dma_chans[2]) {
2372
+ pcdev->dma_chans[2] = dma_request_chan(&pdev->dev, "CI_V");
2373
+ if (IS_ERR(pcdev->dma_chans[2])) {
24692374 dev_err(&pdev->dev, "Can't request DMA for V\n");
2470
- err = -ENODEV;
2375
+ err = PTR_ERR(pcdev->dma_chans[2]);
24712376 goto exit_free_dma_u;
24722377 }
24732378
....@@ -2489,7 +2394,7 @@
24892394 goto exit_free_dma;
24902395 }
24912396
2492
- tasklet_init(&pcdev->task_eof, pxa_camera_eof, (unsigned long)pcdev);
2397
+ tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
24932398
24942399 pxa_camera_activate(pcdev);
24952400
....@@ -2498,9 +2403,14 @@
24982403 if (err)
24992404 goto exit_deactivate;
25002405
2501
- pcdev->asds[0] = &pcdev->asd;
2502
- pcdev->notifier.subdevs = pcdev->asds;
2503
- pcdev->notifier.num_subdevs = 1;
2406
+ v4l2_async_notifier_init(&pcdev->notifier);
2407
+
2408
+ err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd);
2409
+ if (err) {
2410
+ fwnode_handle_put(pcdev->asd.match.fwnode);
2411
+ goto exit_free_v4l2dev;
2412
+ }
2413
+
25042414 pcdev->notifier.ops = &pxa_camera_sensor_ops;
25052415
25062416 if (!of_have_populated_dt())
....@@ -2508,19 +2418,16 @@
25082418
25092419 err = pxa_camera_init_videobuf2(pcdev);
25102420 if (err)
2511
- goto exit_free_v4l2dev;
2421
+ goto exit_notifier_cleanup;
25122422
2513
- if (pcdev->mclk) {
2514
- v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
2515
- pcdev->asd.match.i2c.adapter_id,
2516
- pcdev->asd.match.i2c.address);
2423
+ v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
2424
+ pcdev->asd.match.i2c.adapter_id,
2425
+ pcdev->asd.match.i2c.address);
25172426
2518
- pcdev->mclk_clk = v4l2_clk_register(&pxa_camera_mclk_ops,
2519
- clk_name, NULL);
2520
- if (IS_ERR(pcdev->mclk_clk)) {
2521
- err = PTR_ERR(pcdev->mclk_clk);
2522
- goto exit_free_v4l2dev;
2523
- }
2427
+ pcdev->mclk_clk = v4l2_clk_register(&pxa_camera_mclk_ops, clk_name, NULL);
2428
+ if (IS_ERR(pcdev->mclk_clk)) {
2429
+ err = PTR_ERR(pcdev->mclk_clk);
2430
+ goto exit_notifier_cleanup;
25242431 }
25252432
25262433 err = v4l2_async_notifier_register(&pcdev->v4l2_dev, &pcdev->notifier);
....@@ -2530,10 +2437,13 @@
25302437 return 0;
25312438 exit_free_clk:
25322439 v4l2_clk_unregister(pcdev->mclk_clk);
2440
+exit_notifier_cleanup:
2441
+ v4l2_async_notifier_cleanup(&pcdev->notifier);
25332442 exit_free_v4l2dev:
25342443 v4l2_device_unregister(&pcdev->v4l2_dev);
25352444 exit_deactivate:
25362445 pxa_camera_deactivate(pcdev);
2446
+ tasklet_kill(&pcdev->task_eof);
25372447 exit_free_dma:
25382448 dma_release_channel(pcdev->dma_chans[2]);
25392449 exit_free_dma_u:
....@@ -2548,11 +2458,13 @@
25482458 struct pxa_camera_dev *pcdev = dev_get_drvdata(&pdev->dev);
25492459
25502460 pxa_camera_deactivate(pcdev);
2461
+ tasklet_kill(&pcdev->task_eof);
25512462 dma_release_channel(pcdev->dma_chans[0]);
25522463 dma_release_channel(pcdev->dma_chans[1]);
25532464 dma_release_channel(pcdev->dma_chans[2]);
25542465
25552466 v4l2_async_notifier_unregister(&pcdev->notifier);
2467
+ v4l2_async_notifier_cleanup(&pcdev->notifier);
25562468
25572469 if (pcdev->mclk_clk) {
25582470 v4l2_clk_unregister(pcdev->mclk_clk);
....@@ -2589,7 +2501,7 @@
25892501
25902502 module_platform_driver(pxa_camera_driver);
25912503
2592
-MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
2504
+MODULE_DESCRIPTION("PXA27x Camera Driver");
25932505 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
25942506 MODULE_LICENSE("GPL");
25952507 MODULE_VERSION(PXA_CAM_VERSION);