2 * Copyright (C) 2012 Texas Instruments Inc
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
22 * Driver name : VPFE Capture driver
23 * VPFE Capture driver allows applications to capture and stream video
24 * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
25 * TVP5146 or Raw Bayer RGB image data from an image sensor
26 * such as Microns' MT9T001, MT9T031 etc.
28 * These SoCs have, in common, a Video Processing Subsystem (VPSS) that
29 * consists of a Video Processing Front End (VPFE) for capturing
30 * video/raw image data and Video Processing Back End (VPBE) for displaying
31 * YUV data through an in-built analog encoder or Digital LCD port. This
32 * driver is for capture through VPFE. A typical EVM using these SoCs have
33 * following high level configuration.
35 * decoder(TVP5146/ YUV/
36 * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
45 * The data flow happens from a decoder connected to the VPFE over a
46 * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
47 * and to the input of VPFE through an optional MUX (if more inputs are
48 * to be interfaced on the EVM). The input data is first passed through
49 * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
50 * does very little or no processing on YUV data and does pre-process Raw
51 * Bayer RGB data through modules such as Defect Pixel Correction (DFC)
52 * Color Space Conversion (CSC), data gain/offset etc. After this, data
53 * can be written to SDRAM or can be connected to the image processing
54 * block such as IPIPE (on DM355/DM365 only).
59 * - Capture using TVP5146 over BT.656
60 * - Support for interfacing decoders using sub device model
61 * - Work with DM365 or DM355 or DM6446 CCDC to do Raw Bayer
62 * RGB/YUV data capture to SDRAM.
63 * - Chaining of Image Processor
67 #include <linux/interrupt.h>
68 #include <linux/module.h>
69 #include <linux/slab.h>
72 #include "vpfe_mc_capture.h"
75 static bool interface
;
77 module_param(interface
, bool, S_IRUGO
);
78 module_param(debug
, bool, 0644);
81 * VPFE capture can be used for capturing video such as from TVP5146 or TVP7002
82 * and for capture raw bayer data from camera sensors such as mt9p031. At this
83 * point there is problem in co-existence of mt9p031 and tvp5146 due to i2c
84 * address collision. So set the variable below from bootargs to do either video
85 * capture or camera capture.
86 * interface = 0 - video capture (from TVP514x or such),
87 * interface = 1 - Camera capture (from mt9p031 or such)
88 * Re-visit this when we fix the co-existence issue
90 MODULE_PARM_DESC(interface
, "interface 0-1 (default:0)");
91 MODULE_PARM_DESC(debug
, "Debug level 0-1");
93 MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
94 MODULE_LICENSE("GPL");
95 MODULE_AUTHOR("Texas Instruments");
97 /* map mbus_fmt to pixelformat */
98 void mbus_to_pix(const struct v4l2_mbus_framefmt
*mbus
,
99 struct v4l2_pix_format
*pix
)
101 switch (mbus
->code
) {
102 case MEDIA_BUS_FMT_UYVY8_2X8
:
103 pix
->pixelformat
= V4L2_PIX_FMT_UYVY
;
104 pix
->bytesperline
= pix
->width
* 2;
107 case MEDIA_BUS_FMT_YUYV8_2X8
:
108 pix
->pixelformat
= V4L2_PIX_FMT_YUYV
;
109 pix
->bytesperline
= pix
->width
* 2;
112 case MEDIA_BUS_FMT_YUYV10_1X20
:
113 pix
->pixelformat
= V4L2_PIX_FMT_UYVY
;
114 pix
->bytesperline
= pix
->width
* 2;
117 case MEDIA_BUS_FMT_SGRBG12_1X12
:
118 pix
->pixelformat
= V4L2_PIX_FMT_SBGGR16
;
119 pix
->bytesperline
= pix
->width
* 2;
122 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8
:
123 pix
->pixelformat
= V4L2_PIX_FMT_SGRBG10DPCM8
;
124 pix
->bytesperline
= pix
->width
;
127 case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8
:
128 pix
->pixelformat
= V4L2_PIX_FMT_SGRBG10ALAW8
;
129 pix
->bytesperline
= pix
->width
;
132 case MEDIA_BUS_FMT_YDYUYDYV8_1X16
:
133 pix
->pixelformat
= V4L2_PIX_FMT_NV12
;
134 pix
->bytesperline
= pix
->width
;
137 case MEDIA_BUS_FMT_Y8_1X8
:
138 pix
->pixelformat
= V4L2_PIX_FMT_GREY
;
139 pix
->bytesperline
= pix
->width
;
142 case MEDIA_BUS_FMT_UV8_1X8
:
143 pix
->pixelformat
= V4L2_PIX_FMT_UV8
;
144 pix
->bytesperline
= pix
->width
;
148 pr_err("Invalid mbus code set\n");
150 /* pitch should be 32 bytes aligned */
151 pix
->bytesperline
= ALIGN(pix
->bytesperline
, 32);
152 if (pix
->pixelformat
== V4L2_PIX_FMT_NV12
)
153 pix
->sizeimage
= pix
->bytesperline
* pix
->height
+
154 ((pix
->bytesperline
* pix
->height
) >> 1);
156 pix
->sizeimage
= pix
->bytesperline
* pix
->height
;
160 static irqreturn_t
vpfe_isr(int irq
, void *dev_id
)
162 struct vpfe_device
*vpfe_dev
= dev_id
;
164 v4l2_dbg(1, debug
, &vpfe_dev
->v4l2_dev
, "vpfe_isr\n");
165 vpfe_isif_buffer_isr(&vpfe_dev
->vpfe_isif
);
166 vpfe_resizer_buffer_isr(&vpfe_dev
->vpfe_resizer
);
170 /* vpfe_vdint1_isr() - isr handler for VINT1 interrupt */
171 static irqreturn_t
vpfe_vdint1_isr(int irq
, void *dev_id
)
173 struct vpfe_device
*vpfe_dev
= dev_id
;
175 v4l2_dbg(1, debug
, &vpfe_dev
->v4l2_dev
, "vpfe_vdint1_isr\n");
176 vpfe_isif_vidint1_isr(&vpfe_dev
->vpfe_isif
);
180 /* vpfe_imp_dma_isr() - ISR for ipipe dma completion */
181 static irqreturn_t
vpfe_imp_dma_isr(int irq
, void *dev_id
)
183 struct vpfe_device
*vpfe_dev
= dev_id
;
185 v4l2_dbg(1, debug
, &vpfe_dev
->v4l2_dev
, "vpfe_imp_dma_isr\n");
186 vpfe_ipipeif_ss_buffer_isr(&vpfe_dev
->vpfe_ipipeif
);
187 vpfe_resizer_dma_isr(&vpfe_dev
->vpfe_resizer
);
192 * vpfe_disable_clock() - Disable clocks for vpfe capture driver
193 * @vpfe_dev - ptr to vpfe capture device
195 * Disables clocks defined in vpfe configuration. The function
196 * assumes that at least one clock is to be defined which is
199 static void vpfe_disable_clock(struct vpfe_device
*vpfe_dev
)
201 struct vpfe_config
*vpfe_cfg
= vpfe_dev
->cfg
;
204 for (i
= 0; i
< vpfe_cfg
->num_clocks
; i
++) {
205 clk_disable_unprepare(vpfe_dev
->clks
[i
]);
206 clk_put(vpfe_dev
->clks
[i
]);
208 kzfree(vpfe_dev
->clks
);
209 v4l2_info(vpfe_dev
->pdev
->driver
, "vpfe capture clocks disabled\n");
213 * vpfe_enable_clock() - Enable clocks for vpfe capture driver
214 * @vpfe_dev - ptr to vpfe capture device
216 * Enables clocks defined in vpfe configuration. The function
217 * assumes that at least one clock is to be defined which is
220 static int vpfe_enable_clock(struct vpfe_device
*vpfe_dev
)
222 struct vpfe_config
*vpfe_cfg
= vpfe_dev
->cfg
;
226 if (!vpfe_cfg
->num_clocks
)
229 vpfe_dev
->clks
= kzalloc(vpfe_cfg
->num_clocks
*
230 sizeof(struct clock
*), GFP_KERNEL
);
231 if (vpfe_dev
->clks
== NULL
)
234 for (i
= 0; i
< vpfe_cfg
->num_clocks
; i
++) {
235 if (vpfe_cfg
->clocks
[i
] == NULL
) {
236 v4l2_err(vpfe_dev
->pdev
->driver
,
237 "clock %s is not defined in vpfe config\n",
238 vpfe_cfg
->clocks
[i
]);
243 clk_get(vpfe_dev
->pdev
, vpfe_cfg
->clocks
[i
]);
244 if (IS_ERR(vpfe_dev
->clks
[i
])) {
245 v4l2_err(vpfe_dev
->pdev
->driver
,
246 "Failed to get clock %s\n",
247 vpfe_cfg
->clocks
[i
]);
251 if (clk_prepare_enable(vpfe_dev
->clks
[i
])) {
252 v4l2_err(vpfe_dev
->pdev
->driver
,
253 "vpfe clock %s not enabled\n",
254 vpfe_cfg
->clocks
[i
]);
258 v4l2_info(vpfe_dev
->pdev
->driver
, "vpss clock %s enabled",
259 vpfe_cfg
->clocks
[i
]);
264 for (i
= 0; i
< vpfe_cfg
->num_clocks
; i
++)
265 if (!IS_ERR(vpfe_dev
->clks
[i
])) {
266 clk_disable_unprepare(vpfe_dev
->clks
[i
]);
267 clk_put(vpfe_dev
->clks
[i
]);
270 v4l2_err(vpfe_dev
->pdev
->driver
, "Failed to enable clocks\n");
271 kzfree(vpfe_dev
->clks
);
277 * vpfe_detach_irq() - Detach IRQs for vpfe capture driver
278 * @vpfe_dev - ptr to vpfe capture device
280 * Detach all IRQs defined in vpfe configuration.
282 static void vpfe_detach_irq(struct vpfe_device
*vpfe_dev
)
284 free_irq(vpfe_dev
->ccdc_irq0
, vpfe_dev
);
285 free_irq(vpfe_dev
->ccdc_irq1
, vpfe_dev
);
286 free_irq(vpfe_dev
->imp_dma_irq
, vpfe_dev
);
290 * vpfe_attach_irq() - Attach IRQs for vpfe capture driver
291 * @vpfe_dev - ptr to vpfe capture device
293 * Attach all IRQs defined in vpfe configuration.
295 static int vpfe_attach_irq(struct vpfe_device
*vpfe_dev
)
299 ret
= request_irq(vpfe_dev
->ccdc_irq0
, vpfe_isr
, 0,
300 "vpfe_capture0", vpfe_dev
);
302 v4l2_err(&vpfe_dev
->v4l2_dev
,
303 "Error: requesting VINT0 interrupt\n");
307 ret
= request_irq(vpfe_dev
->ccdc_irq1
, vpfe_vdint1_isr
, 0,
308 "vpfe_capture1", vpfe_dev
);
310 v4l2_err(&vpfe_dev
->v4l2_dev
,
311 "Error: requesting VINT1 interrupt\n");
312 free_irq(vpfe_dev
->ccdc_irq0
, vpfe_dev
);
316 ret
= request_irq(vpfe_dev
->imp_dma_irq
, vpfe_imp_dma_isr
,
317 0, "Imp_Sdram_Irq", vpfe_dev
);
319 v4l2_err(&vpfe_dev
->v4l2_dev
,
320 "Error: requesting IMP IRQ interrupt\n");
321 free_irq(vpfe_dev
->ccdc_irq1
, vpfe_dev
);
322 free_irq(vpfe_dev
->ccdc_irq0
, vpfe_dev
);
330 * register_i2c_devices() - register all i2c v4l2 subdevs
331 * @vpfe_dev - ptr to vpfe capture device
333 * register all i2c v4l2 subdevs
335 static int register_i2c_devices(struct vpfe_device
*vpfe_dev
)
337 struct vpfe_ext_subdev_info
*sdinfo
;
338 struct vpfe_config
*vpfe_cfg
;
339 struct i2c_adapter
*i2c_adap
;
340 unsigned int num_subdevs
;
345 vpfe_cfg
= vpfe_dev
->cfg
;
346 i2c_adap
= i2c_get_adapter(1);
347 num_subdevs
= vpfe_cfg
->num_subdevs
;
349 kzalloc(sizeof(struct v4l2_subdev
*)*num_subdevs
, GFP_KERNEL
);
350 if (vpfe_dev
->sd
== NULL
)
353 for (i
= 0, k
= 0; i
< num_subdevs
; i
++) {
354 sdinfo
= &vpfe_cfg
->sub_devs
[i
];
356 * register subdevices based on interface setting. Currently
357 * tvp5146 and mt9p031 cannot co-exists due to i2c address
358 * conflicts. So only one of them is registered. Re-visit this
359 * once we have support for i2c switch handling in i2c driver
362 if (interface
== sdinfo
->is_camera
) {
363 /* setup input path */
364 if (vpfe_cfg
->setup_input
&&
365 vpfe_cfg
->setup_input(sdinfo
->grp_id
) < 0) {
367 v4l2_info(&vpfe_dev
->v4l2_dev
,
368 "could not setup input for %s\n",
369 sdinfo
->module_name
);
372 /* Load up the subdevice */
374 v4l2_i2c_new_subdev_board(&vpfe_dev
->v4l2_dev
,
375 i2c_adap
, &sdinfo
->board_info
,
377 if (vpfe_dev
->sd
[k
]) {
378 v4l2_info(&vpfe_dev
->v4l2_dev
,
379 "v4l2 sub device %s registered\n",
380 sdinfo
->module_name
);
382 vpfe_dev
->sd
[k
]->grp_id
= sdinfo
->grp_id
;
385 sdinfo
->registered
= 1;
388 v4l2_info(&vpfe_dev
->v4l2_dev
,
389 "v4l2 sub device %s is not registered\n",
390 sdinfo
->module_name
);
393 vpfe_dev
->num_ext_subdevs
= k
;
398 kzfree(vpfe_dev
->sd
);
404 * vpfe_register_entities() - register all v4l2 subdevs and media entities
405 * @vpfe_dev - ptr to vpfe capture device
407 * register all v4l2 subdevs, media entities, and creates links
410 static int vpfe_register_entities(struct vpfe_device
*vpfe_dev
)
412 unsigned int flags
= 0;
416 /* register i2c devices first */
417 ret
= register_i2c_devices(vpfe_dev
);
421 /* register rest of the sub-devs */
422 ret
= vpfe_isif_register_entities(&vpfe_dev
->vpfe_isif
,
423 &vpfe_dev
->v4l2_dev
);
427 ret
= vpfe_ipipeif_register_entities(&vpfe_dev
->vpfe_ipipeif
,
428 &vpfe_dev
->v4l2_dev
);
430 goto out_isif_register
;
432 ret
= vpfe_ipipe_register_entities(&vpfe_dev
->vpfe_ipipe
,
433 &vpfe_dev
->v4l2_dev
);
435 goto out_ipipeif_register
;
437 ret
= vpfe_resizer_register_entities(&vpfe_dev
->vpfe_resizer
,
438 &vpfe_dev
->v4l2_dev
);
440 goto out_ipipe_register
;
442 /* create links now, starting with external(i2c) entities */
443 for (i
= 0; i
< vpfe_dev
->num_ext_subdevs
; i
++)
444 /* if entity has no pads (ex: amplifier),
445 cant establish link */
446 if (vpfe_dev
->sd
[i
]->entity
.num_pads
) {
447 ret
= media_entity_create_link(&vpfe_dev
->sd
[i
]->entity
,
448 0, &vpfe_dev
->vpfe_isif
.subdev
.entity
,
451 goto out_resizer_register
;
454 ret
= media_entity_create_link(&vpfe_dev
->vpfe_isif
.subdev
.entity
, 1,
455 &vpfe_dev
->vpfe_ipipeif
.subdev
.entity
,
458 goto out_resizer_register
;
460 ret
= media_entity_create_link(&vpfe_dev
->vpfe_ipipeif
.subdev
.entity
, 1,
461 &vpfe_dev
->vpfe_ipipe
.subdev
.entity
,
464 goto out_resizer_register
;
466 ret
= media_entity_create_link(&vpfe_dev
->vpfe_ipipe
.subdev
.entity
,
467 1, &vpfe_dev
->vpfe_resizer
.crop_resizer
.subdev
.entity
,
470 goto out_resizer_register
;
472 ret
= media_entity_create_link(&vpfe_dev
->vpfe_ipipeif
.subdev
.entity
, 1,
473 &vpfe_dev
->vpfe_resizer
.crop_resizer
.subdev
.entity
,
476 goto out_resizer_register
;
478 ret
= v4l2_device_register_subdev_nodes(&vpfe_dev
->v4l2_dev
);
480 goto out_resizer_register
;
484 out_resizer_register
:
485 vpfe_resizer_unregister_entities(&vpfe_dev
->vpfe_resizer
);
487 vpfe_ipipe_unregister_entities(&vpfe_dev
->vpfe_ipipe
);
488 out_ipipeif_register
:
489 vpfe_ipipeif_unregister_entities(&vpfe_dev
->vpfe_ipipeif
);
491 vpfe_isif_unregister_entities(&vpfe_dev
->vpfe_isif
);
497 * vpfe_unregister_entities() - unregister all v4l2 subdevs and media entities
498 * @vpfe_dev - ptr to vpfe capture device
500 * unregister all v4l2 subdevs and media entities
502 static void vpfe_unregister_entities(struct vpfe_device
*vpfe_dev
)
504 vpfe_isif_unregister_entities(&vpfe_dev
->vpfe_isif
);
505 vpfe_ipipeif_unregister_entities(&vpfe_dev
->vpfe_ipipeif
);
506 vpfe_ipipe_unregister_entities(&vpfe_dev
->vpfe_ipipe
);
507 vpfe_resizer_unregister_entities(&vpfe_dev
->vpfe_resizer
);
511 * vpfe_cleanup_modules() - cleanup all non-i2c v4l2 subdevs
512 * @vpfe_dev - ptr to vpfe capture device
513 * @pdev - pointer to platform device
515 * cleanup all v4l2 subdevs
517 static void vpfe_cleanup_modules(struct vpfe_device
*vpfe_dev
,
518 struct platform_device
*pdev
)
520 vpfe_isif_cleanup(&vpfe_dev
->vpfe_isif
, pdev
);
521 vpfe_ipipeif_cleanup(&vpfe_dev
->vpfe_ipipeif
, pdev
);
522 vpfe_ipipe_cleanup(&vpfe_dev
->vpfe_ipipe
, pdev
);
523 vpfe_resizer_cleanup(&vpfe_dev
->vpfe_resizer
, pdev
);
527 * vpfe_initialize_modules() - initialize all non-i2c v4l2 subdevs
528 * @vpfe_dev - ptr to vpfe capture device
529 * @pdev - pointer to platform device
531 * intialize all v4l2 subdevs and media entities
533 static int vpfe_initialize_modules(struct vpfe_device
*vpfe_dev
,
534 struct platform_device
*pdev
)
538 ret
= vpfe_isif_init(&vpfe_dev
->vpfe_isif
, pdev
);
542 ret
= vpfe_ipipeif_init(&vpfe_dev
->vpfe_ipipeif
, pdev
);
546 ret
= vpfe_ipipe_init(&vpfe_dev
->vpfe_ipipe
, pdev
);
548 goto out_ipipeif_init
;
550 ret
= vpfe_resizer_init(&vpfe_dev
->vpfe_resizer
, pdev
);
557 vpfe_ipipe_cleanup(&vpfe_dev
->vpfe_ipipe
, pdev
);
559 vpfe_ipipeif_cleanup(&vpfe_dev
->vpfe_ipipeif
, pdev
);
561 vpfe_isif_cleanup(&vpfe_dev
->vpfe_isif
, pdev
);
567 * vpfe_probe() : vpfe probe function
568 * @pdev: platform device pointer
570 * This function creates device entries by register itself to the V4L2 driver
571 * and initializes fields of each device objects
573 static int vpfe_probe(struct platform_device
*pdev
)
575 struct vpfe_device
*vpfe_dev
;
576 struct resource
*res1
;
579 vpfe_dev
= kzalloc(sizeof(*vpfe_dev
), GFP_KERNEL
);
583 if (pdev
->dev
.platform_data
== NULL
) {
584 v4l2_err(pdev
->dev
.driver
, "Unable to get vpfe config\n");
586 goto probe_free_dev_mem
;
589 vpfe_dev
->cfg
= pdev
->dev
.platform_data
;
590 if (vpfe_dev
->cfg
->card_name
== NULL
||
591 vpfe_dev
->cfg
->sub_devs
== NULL
) {
592 v4l2_err(pdev
->dev
.driver
, "null ptr in vpfe_cfg\n");
594 goto probe_free_dev_mem
;
597 /* Get VINT0 irq resource */
598 res1
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
600 v4l2_err(pdev
->dev
.driver
,
601 "Unable to get interrupt for VINT0\n");
603 goto probe_free_dev_mem
;
605 vpfe_dev
->ccdc_irq0
= res1
->start
;
607 /* Get VINT1 irq resource */
608 res1
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 1);
610 v4l2_err(pdev
->dev
.driver
,
611 "Unable to get interrupt for VINT1\n");
613 goto probe_free_dev_mem
;
615 vpfe_dev
->ccdc_irq1
= res1
->start
;
617 /* Get DMA irq resource */
618 res1
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 2);
620 v4l2_err(pdev
->dev
.driver
,
621 "Unable to get interrupt for DMA\n");
623 goto probe_free_dev_mem
;
625 vpfe_dev
->imp_dma_irq
= res1
->start
;
627 vpfe_dev
->pdev
= &pdev
->dev
;
629 /* enable vpss clocks */
630 ret
= vpfe_enable_clock(vpfe_dev
);
632 goto probe_free_dev_mem
;
634 ret
= vpfe_initialize_modules(vpfe_dev
, pdev
);
636 goto probe_disable_clock
;
638 vpfe_dev
->media_dev
.dev
= vpfe_dev
->pdev
;
639 strcpy((char *)&vpfe_dev
->media_dev
.model
, "davinci-media");
641 ret
= media_device_register(&vpfe_dev
->media_dev
);
643 v4l2_err(pdev
->dev
.driver
,
644 "Unable to register media device.\n");
645 goto probe_out_entities_cleanup
;
648 vpfe_dev
->v4l2_dev
.mdev
= &vpfe_dev
->media_dev
;
649 ret
= v4l2_device_register(&pdev
->dev
, &vpfe_dev
->v4l2_dev
);
651 v4l2_err(pdev
->dev
.driver
, "Unable to register v4l2 device.\n");
652 goto probe_out_media_unregister
;
655 v4l2_info(&vpfe_dev
->v4l2_dev
, "v4l2 device registered\n");
656 /* set the driver data in platform device */
657 platform_set_drvdata(pdev
, vpfe_dev
);
658 /* register subdevs/entities */
659 ret
= vpfe_register_entities(vpfe_dev
);
661 goto probe_out_v4l2_unregister
;
663 ret
= vpfe_attach_irq(vpfe_dev
);
665 goto probe_out_entities_unregister
;
669 probe_out_entities_unregister
:
670 vpfe_unregister_entities(vpfe_dev
);
671 kzfree(vpfe_dev
->sd
);
672 probe_out_v4l2_unregister
:
673 v4l2_device_unregister(&vpfe_dev
->v4l2_dev
);
674 probe_out_media_unregister
:
675 media_device_unregister(&vpfe_dev
->media_dev
);
676 probe_out_entities_cleanup
:
677 vpfe_cleanup_modules(vpfe_dev
, pdev
);
679 vpfe_disable_clock(vpfe_dev
);
687 * vpfe_remove : This function un-registers device from V4L2 driver
689 static int vpfe_remove(struct platform_device
*pdev
)
691 struct vpfe_device
*vpfe_dev
= platform_get_drvdata(pdev
);
693 v4l2_info(pdev
->dev
.driver
, "vpfe_remove\n");
695 kzfree(vpfe_dev
->sd
);
696 vpfe_detach_irq(vpfe_dev
);
697 vpfe_unregister_entities(vpfe_dev
);
698 vpfe_cleanup_modules(vpfe_dev
, pdev
);
699 v4l2_device_unregister(&vpfe_dev
->v4l2_dev
);
700 media_device_unregister(&vpfe_dev
->media_dev
);
701 vpfe_disable_clock(vpfe_dev
);
707 static struct platform_driver vpfe_driver
= {
709 .name
= CAPTURE_DRV_NAME
,
712 .remove
= vpfe_remove
,
715 module_platform_driver(vpfe_driver
);