2 * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
15 * @file ipu_prp_vf_sdc_bg.c
17 * @brief IPU Use case for PRP-VF back-ground
21 #include <linux/dma-mapping.h>
23 #include <linux/ipu.h>
24 #include <linux/module.h>
25 #include <mach/mipi_csi2.h>
26 #include "mxc_v4l2_capture.h"
27 #include "ipu_prp_sw.h"
29 static int buffer_num;
30 static int buffer_ready;
31 static struct ipu_soc *disp_ipu;
33 static void get_disp_ipu(cam_data *cam)
36 disp_ipu = ipu_get_soc(1); /* using DISP4 */
38 disp_ipu = ipu_get_soc(0);
42 * Function definitions
46 * SDC V-Sync callback function.
48 * @param irq int irq line
49 * @param dev_id void * device id
51 * @return status IRQ_HANDLED for handled
53 static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id)
55 cam_data *cam = dev_id;
56 if (buffer_ready > 0) {
57 ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
58 IPU_OUTPUT_BUFFER, 0);
66 * VF EOF callback function.
68 * @param irq int irq line
69 * @param dev_id void * device id
71 * @return status IRQ_HANDLED for handled
73 static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id)
75 cam_data *cam = dev_id;
76 pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
78 ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
79 IPU_INPUT_BUFFER, buffer_num);
80 buffer_num = (buffer_num == 0) ? 1 : 0;
81 ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
82 IPU_OUTPUT_BUFFER, buffer_num);
88 * prpvf_start - start the vf task
90 * @param private cam_data * mxc v4l2 main structure
93 static int prpvf_start(void *private)
95 cam_data *cam = (cam_data *) private;
96 ipu_channel_params_t vf;
101 #ifdef CONFIG_MXC_MIPI_CSI2
102 void *mipi_csi2_info;
108 printk(KERN_ERR "private is NULL\n");
112 if (cam->overlay_active == true) {
113 pr_debug("already start.\n");
119 format = cam->v4l2_fb.fmt.pixelformat;
120 if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
123 } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
126 } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
131 "unsupported fix format from the framebuffer.\n");
135 offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
136 size * cam->win.w.left;
138 if (cam->v4l2_fb.base == 0)
139 printk(KERN_ERR "invalid frame buffer address.\n");
141 offset += (u32) cam->v4l2_fb.base;
143 memset(&vf, 0, sizeof(ipu_channel_params_t));
144 ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
145 &vf.csi_prp_vf_mem.in_height, cam->csi);
146 vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
147 vf.csi_prp_vf_mem.out_width = cam->win.w.width;
148 vf.csi_prp_vf_mem.out_height = cam->win.w.height;
149 vf.csi_prp_vf_mem.csi = cam->csi;
150 if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
151 vf.csi_prp_vf_mem.out_width = cam->win.w.height;
152 vf.csi_prp_vf_mem.out_height = cam->win.w.width;
154 vf.csi_prp_vf_mem.out_pixel_fmt = format;
155 size = cam->win.w.width * cam->win.w.height * size;
157 #ifdef CONFIG_MXC_MIPI_CSI2
158 mipi_csi2_info = mipi_csi2_get_info();
160 if (mipi_csi2_info) {
161 if (mipi_csi2_get_status(mipi_csi2_info)) {
162 ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
163 csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
165 if (cam->ipu == ipu_get_soc(ipu_id)
166 && cam->csi == csi_id) {
167 vf.csi_prp_vf_mem.mipi_en = true;
168 vf.csi_prp_vf_mem.mipi_vc =
169 mipi_csi2_get_virtual_channel(mipi_csi2_info);
170 vf.csi_prp_vf_mem.mipi_id =
171 mipi_csi2_get_datatype(mipi_csi2_info);
173 mipi_csi2_pixelclk_enable(mipi_csi2_info);
175 vf.csi_prp_vf_mem.mipi_en = false;
176 vf.csi_prp_vf_mem.mipi_vc = 0;
177 vf.csi_prp_vf_mem.mipi_id = 0;
180 vf.csi_prp_vf_mem.mipi_en = false;
181 vf.csi_prp_vf_mem.mipi_vc = 0;
182 vf.csi_prp_vf_mem.mipi_id = 0;
185 printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
191 err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
195 if (cam->vf_bufs_vaddr[0]) {
196 dma_free_coherent(0, cam->vf_bufs_size[0],
197 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
199 if (cam->vf_bufs_vaddr[1]) {
200 dma_free_coherent(0, cam->vf_bufs_size[1],
201 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
203 cam->vf_bufs_size[0] = PAGE_ALIGN(size);
204 cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
205 cam->vf_bufs_size[0],
209 if (cam->vf_bufs_vaddr[0] == NULL) {
210 printk(KERN_ERR "Error to allocate vf buffer\n");
214 cam->vf_bufs_size[1] = PAGE_ALIGN(size);
215 cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
216 cam->vf_bufs_size[1],
220 if (cam->vf_bufs_vaddr[1] == NULL) {
221 printk(KERN_ERR "Error to allocate vf buffer\n");
226 err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
228 format, vf.csi_prp_vf_mem.out_width,
229 vf.csi_prp_vf_mem.out_height,
230 vf.csi_prp_vf_mem.out_width,
236 printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
239 err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
241 printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
245 err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
247 format, vf.csi_prp_vf_mem.out_width,
248 vf.csi_prp_vf_mem.out_height,
249 vf.csi_prp_vf_mem.out_width,
255 printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
259 if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
260 err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
263 vf.csi_prp_vf_mem.out_height,
264 vf.csi_prp_vf_mem.out_width,
265 cam->overlay_fb->var.xres * bpp,
270 printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
274 err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
277 vf.csi_prp_vf_mem.out_width,
278 vf.csi_prp_vf_mem.out_height,
279 cam->overlay_fb->var.xres * bpp,
283 printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
288 ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
289 err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
290 prpvf_vf_eof_callback,
291 0, "Mxc Camera", cam);
294 "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n");
298 ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END);
299 err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END,
300 prpvf_sdc_vsync_callback,
301 0, "Mxc Camera", cam);
303 printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n");
307 ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
308 ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
312 ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
314 cam->overlay_active = true;
318 ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
320 ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
322 ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
324 if (cam->vf_bufs_vaddr[0]) {
325 dma_free_coherent(0, cam->vf_bufs_size[0],
326 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
327 cam->vf_bufs_vaddr[0] = NULL;
330 if (cam->vf_bufs_vaddr[1]) {
331 dma_free_coherent(0, cam->vf_bufs_size[1],
332 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
333 cam->vf_bufs_vaddr[1] = NULL;
336 if (cam->rot_vf_bufs_vaddr[0]) {
337 dma_free_coherent(0, cam->rot_vf_buf_size[0],
338 cam->rot_vf_bufs_vaddr[0],
339 cam->rot_vf_bufs[0]);
340 cam->rot_vf_bufs_vaddr[0] = NULL;
341 cam->rot_vf_bufs[0] = 0;
343 if (cam->rot_vf_bufs_vaddr[1]) {
344 dma_free_coherent(0, cam->rot_vf_buf_size[1],
345 cam->rot_vf_bufs_vaddr[1],
346 cam->rot_vf_bufs[1]);
347 cam->rot_vf_bufs_vaddr[1] = NULL;
348 cam->rot_vf_bufs[1] = 0;
354 * prpvf_stop - stop the vf task
356 * @param private cam_data * mxc v4l2 main structure
359 static int prpvf_stop(void *private)
361 cam_data *cam = (cam_data *) private;
362 #ifdef CONFIG_MXC_MIPI_CSI2
363 void *mipi_csi2_info;
368 if (cam->overlay_active == false)
371 ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam);
373 ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
374 ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
375 ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
376 ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
378 #ifdef CONFIG_MXC_MIPI_CSI2
379 mipi_csi2_info = mipi_csi2_get_info();
381 if (mipi_csi2_info) {
382 if (mipi_csi2_get_status(mipi_csi2_info)) {
383 ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
384 csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
386 if (cam->ipu == ipu_get_soc(ipu_id)
387 && cam->csi == csi_id)
388 mipi_csi2_pixelclk_disable(mipi_csi2_info);
391 printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
397 if (cam->vf_bufs_vaddr[0]) {
398 dma_free_coherent(0, cam->vf_bufs_size[0],
399 cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
400 cam->vf_bufs_vaddr[0] = NULL;
403 if (cam->vf_bufs_vaddr[1]) {
404 dma_free_coherent(0, cam->vf_bufs_size[1],
405 cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
406 cam->vf_bufs_vaddr[1] = NULL;
409 if (cam->rot_vf_bufs_vaddr[0]) {
410 dma_free_coherent(0, cam->rot_vf_buf_size[0],
411 cam->rot_vf_bufs_vaddr[0],
412 cam->rot_vf_bufs[0]);
413 cam->rot_vf_bufs_vaddr[0] = NULL;
414 cam->rot_vf_bufs[0] = 0;
416 if (cam->rot_vf_bufs_vaddr[1]) {
417 dma_free_coherent(0, cam->rot_vf_buf_size[1],
418 cam->rot_vf_bufs_vaddr[1],
419 cam->rot_vf_bufs[1]);
420 cam->rot_vf_bufs_vaddr[1] = NULL;
421 cam->rot_vf_bufs[1] = 0;
426 cam->overlay_active = false;
432 * @param private struct cam_data * mxc capture instance
436 static int prp_vf_enable_csi(void *private)
438 cam_data *cam = (cam_data *) private;
440 return ipu_enable_csi(cam->ipu, cam->csi);
445 * @param private struct cam_data * mxc capture instance
449 static int prp_vf_disable_csi(void *private)
451 cam_data *cam = (cam_data *) private;
453 /* free csi eof irq firstly.
454 * when disable csi, wait for idmac eof.
455 * it requests eof irq again */
456 ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
458 return ipu_disable_csi(cam->ipu, cam->csi);
462 * function to select PRP-VF as the working path
464 * @param private cam_data * mxc v4l2 main structure
468 int prp_vf_sdc_select_bg(void *private)
470 cam_data *cam = (cam_data *) private;
473 cam->vf_start_sdc = prpvf_start;
474 cam->vf_stop_sdc = prpvf_stop;
475 cam->vf_enable_csi = prp_vf_enable_csi;
476 cam->vf_disable_csi = prp_vf_disable_csi;
477 cam->overlay_active = false;
482 EXPORT_SYMBOL(prp_vf_sdc_select_bg);
485 * function to de-select PRP-VF as the working path
487 * @param private cam_data * mxc v4l2 main structure
491 int prp_vf_sdc_deselect_bg(void *private)
493 cam_data *cam = (cam_data *) private;
496 cam->vf_start_sdc = NULL;
497 cam->vf_stop_sdc = NULL;
498 cam->vf_enable_csi = NULL;
499 cam->vf_disable_csi = NULL;
503 EXPORT_SYMBOL(prp_vf_sdc_deselect_bg);
506 * Init viewfinder task.
508 * @return Error code indicating success or failure
510 __init int prp_vf_sdc_init_bg(void)
516 * Deinit viewfinder task.
518 * @return Error code indicating success or failure
520 void __exit prp_vf_sdc_exit_bg(void)
524 module_init(prp_vf_sdc_init_bg);
525 module_exit(prp_vf_sdc_exit_bg);
527 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
528 MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
529 MODULE_LICENSE("GPL");