2 * Copyright 2009-2014 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
17 * @brief CSI Use case for video capture
22 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/ipu.h>
26 #include <linux/mipi_csi2.h>
27 #include "mxc_v4l2_capture.h"
28 #include "ipu_prp_sw.h"
31 #define CAMERA_TRACE(x) (printk)x
33 #define CAMERA_TRACE(x)
37 * Function definitions
41 * csi ENC callback function.
43 * @param irq int irq line
44 * @param dev_id void * device id
46 * @return status IRQ_HANDLED for handled
48 static irqreturn_t csi_enc_callback(int irq, void *dev_id)
50 cam_data *cam = (cam_data *) dev_id;
52 if (cam->enc_callback == NULL)
55 cam->enc_callback(irq, dev_id);
60 * CSI ENC enable channel setup function
62 * @param cam struct cam_data * mxc capture instance
66 static int csi_enc_setup(cam_data *cam)
68 ipu_channel_params_t params;
70 int err = 0, sensor_protocol = 0;
71 dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
72 #ifdef CONFIG_MXC_MIPI_CSI2
78 CAMERA_TRACE("In csi_enc_setup\n");
80 printk(KERN_ERR "cam private is NULL\n");
84 memset(¶ms, 0, sizeof(ipu_channel_params_t));
85 params.csi_mem.csi = cam->csi;
87 sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
88 switch (sensor_protocol) {
89 case IPU_CSI_CLK_MODE_GATED_CLK:
90 case IPU_CSI_CLK_MODE_NONGATED_CLK:
91 case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
92 case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
93 case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
94 params.csi_mem.interlaced = false;
96 case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
97 case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
98 case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
99 params.csi_mem.interlaced = true;
102 printk(KERN_ERR "sensor protocol unsupported\n");
106 if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
107 pixel_fmt = IPU_PIX_FMT_YUV420P;
108 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420)
109 pixel_fmt = IPU_PIX_FMT_YVU420P;
110 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
111 pixel_fmt = IPU_PIX_FMT_YUV422P;
112 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
113 pixel_fmt = IPU_PIX_FMT_UYVY;
114 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
115 pixel_fmt = IPU_PIX_FMT_YUYV;
116 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
117 pixel_fmt = IPU_PIX_FMT_NV12;
118 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
119 pixel_fmt = IPU_PIX_FMT_BGR24;
120 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
121 pixel_fmt = IPU_PIX_FMT_RGB24;
122 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
123 pixel_fmt = IPU_PIX_FMT_RGB565;
124 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
125 pixel_fmt = IPU_PIX_FMT_BGR32;
126 else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
127 pixel_fmt = IPU_PIX_FMT_RGB32;
129 printk(KERN_ERR "format not supported\n");
133 #ifdef CONFIG_MXC_MIPI_CSI2
134 mipi_csi2_info = mipi_csi2_get_info();
136 if (mipi_csi2_info) {
137 if (mipi_csi2_get_status(mipi_csi2_info)) {
138 ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
139 csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
141 if (cam->ipu == ipu_get_soc(ipu_id)
142 && cam->csi == csi_id) {
143 params.csi_mem.mipi_en = true;
144 params.csi_mem.mipi_vc =
145 mipi_csi2_get_virtual_channel(mipi_csi2_info);
146 params.csi_mem.mipi_id =
147 mipi_csi2_get_datatype(mipi_csi2_info);
149 mipi_csi2_pixelclk_enable(mipi_csi2_info);
151 params.csi_mem.mipi_en = false;
152 params.csi_mem.mipi_vc = 0;
153 params.csi_mem.mipi_id = 0;
156 params.csi_mem.mipi_en = false;
157 params.csi_mem.mipi_vc = 0;
158 params.csi_mem.mipi_id = 0;
163 err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms);
165 printk(KERN_ERR "ipu_init_channel %d\n", err);
169 err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
170 pixel_fmt, cam->v2f.fmt.pix.width,
171 cam->v2f.fmt.pix.height,
172 cam->v2f.fmt.pix.bytesperline,
175 cam->offset.u_offset,
176 cam->offset.v_offset);
178 printk(KERN_ERR "CSI_MEM output buffer\n");
181 err = ipu_enable_channel(cam->ipu, CSI_MEM);
183 printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
191 * function to update physical buffer address for encorder IDMA channel
193 * @param eba physical buffer address for encorder IDMA channel
194 * @param buffer_num int buffer 0 or buffer 1
198 static int csi_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba,
203 pr_debug("eba %x\n", eba);
204 err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
207 ipu_clear_buffer_ready(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
210 err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
213 pr_err("ERROR: v4l2 capture: fail to update "
214 "buf%d\n", *buffer_num);
219 ipu_select_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num);
221 *buffer_num = (*buffer_num == 0) ? 1 : 0;
227 * Enable encoder task
228 * @param private struct cam_data * mxc capture instance
232 static int csi_enc_enabling_tasks(void *private)
234 cam_data *cam = (cam_data *) private;
236 CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
238 cam->dummy_frame.vaddress = dma_alloc_coherent(0,
239 PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
240 &cam->dummy_frame.paddress,
241 GFP_DMA | GFP_KERNEL);
242 if (cam->dummy_frame.vaddress == 0) {
243 pr_err("ERROR: v4l2 capture: Allocate dummy frame "
247 cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
248 cam->dummy_frame.buffer.length =
249 PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
250 cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
252 ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
253 err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
254 csi_enc_callback, 0, "Mxc Camera", cam);
256 printk(KERN_ERR "Error registering rot irq\n");
260 err = csi_enc_setup(cam);
262 printk(KERN_ERR "csi_enc_setup %d\n", err);
270 * Disable encoder task
271 * @param private struct cam_data * mxc capture instance
275 static int csi_enc_disabling_tasks(void *private)
277 cam_data *cam = (cam_data *) private;
279 #ifdef CONFIG_MXC_MIPI_CSI2
280 void *mipi_csi2_info;
285 err = ipu_disable_channel(cam->ipu, CSI_MEM, true);
287 ipu_uninit_channel(cam->ipu, CSI_MEM);
289 if (cam->dummy_frame.vaddress != 0) {
290 dma_free_coherent(0, cam->dummy_frame.buffer.length,
291 cam->dummy_frame.vaddress,
292 cam->dummy_frame.paddress);
293 cam->dummy_frame.vaddress = 0;
296 #ifdef CONFIG_MXC_MIPI_CSI2
297 mipi_csi2_info = mipi_csi2_get_info();
299 if (mipi_csi2_info) {
300 if (mipi_csi2_get_status(mipi_csi2_info)) {
301 ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
302 csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
304 if (cam->ipu == ipu_get_soc(ipu_id)
305 && cam->csi == csi_id)
306 mipi_csi2_pixelclk_disable(mipi_csi2_info);
316 * @param private struct cam_data * mxc capture instance
320 static int csi_enc_enable_csi(void *private)
322 cam_data *cam = (cam_data *) private;
324 return ipu_enable_csi(cam->ipu, cam->csi);
329 * @param private struct cam_data * mxc capture instance
333 static int csi_enc_disable_csi(void *private)
335 cam_data *cam = (cam_data *) private;
337 /* free csi eof irq firstly.
338 * when disable csi, wait for idmac eof.
339 * it requests eof irq again */
340 ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
342 return ipu_disable_csi(cam->ipu, cam->csi);
346 * function to select CSI ENC as the working path
348 * @param private struct cam_data * mxc capture instance
352 int csi_enc_select(void *private)
354 cam_data *cam = (cam_data *) private;
358 cam->enc_update_eba = csi_enc_eba_update;
359 cam->enc_enable = csi_enc_enabling_tasks;
360 cam->enc_disable = csi_enc_disabling_tasks;
361 cam->enc_enable_csi = csi_enc_enable_csi;
362 cam->enc_disable_csi = csi_enc_disable_csi;
369 EXPORT_SYMBOL(csi_enc_select);
372 * function to de-select CSI ENC as the working path
374 * @param private struct cam_data * mxc capture instance
378 int csi_enc_deselect(void *private)
380 cam_data *cam = (cam_data *) private;
384 cam->enc_update_eba = NULL;
385 cam->enc_enable = NULL;
386 cam->enc_disable = NULL;
387 cam->enc_enable_csi = NULL;
388 cam->enc_disable_csi = NULL;
393 EXPORT_SYMBOL(csi_enc_deselect);
396 * Init the Encorder channels
398 * @return Error code indicating success or failure
400 __init int csi_enc_init(void)
406 * Deinit the Encorder channels
409 void __exit csi_enc_exit(void)
413 module_init(csi_enc_init);
414 module_exit(csi_enc_exit);
416 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
417 MODULE_DESCRIPTION("CSI ENC Driver");
418 MODULE_LICENSE("GPL");