ENGR00125275 v4l2 output:disable icbypass for input right crop case
[efikamx:linux-kernel.git] / drivers / media / video / mxc / output / mxc_v4l2_output.c
1 /*
2  * Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /*
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:
9  *
10  * http://www.opensource.org/licenses/gpl-license.html
11  * http://www.gnu.org/copyleft/gpl.html
12  */
13
14 /*!
15  * @file drivers/media/video/mxc/output/mxc_v4l2_output.c
16  *
17  * @brief MXC V4L2 Video Output Driver
18  *
19  * Video4Linux2 Output Device using MXC IPU Post-processing functionality.
20  *
21  * @ingroup MXC_V4L2_OUTPUT
22  */
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/io.h>
26 #include <linux/semaphore.h>
27 #include <linux/console.h>
28 #include <linux/fs.h>
29 #include <linux/delay.h>
30 #include <linux/platform_device.h>
31 #include <linux/dma-mapping.h>
32 #include <linux/mxcfb.h>
33 #include <media/v4l2-ioctl.h>
34 #include <asm/cacheflush.h>
35 #include <mach/hardware.h>
36
37 #include "mxc_v4l2_output.h"
38
39 vout_data *g_vout;
40 #define INTERLACED_CONTENT(vout) (((cpu_is_mx51_rev(CHIP_REV_2_0) >= 1) || \
41                                    cpu_is_mx53()) &&                    \
42                                   (((vout)->field_fmt == V4L2_FIELD_INTERLACED_TB) || \
43                                    ((vout)->field_fmt == V4L2_FIELD_INTERLACED_BT)))
44 #define LOAD_3FIELDS(vout) ((INTERLACED_CONTENT(vout)) && \
45                             ((vout)->motion_sel != HIGH_MOTION))
46
47 struct v4l2_output mxc_outputs[1] = {
48         {
49          .index = MXC_V4L2_OUT_2_SDC,
50          .name = "DISP3 Video Out",
51          .type = V4L2_OUTPUT_TYPE_ANALOG,       /* not really correct,
52                                                    but no other choice */
53          .audioset = 0,
54          .modulator = 0,
55          .std = V4L2_STD_UNKNOWN}
56 };
57
58 static int video_nr = 16;
59 static spinlock_t g_lock = SPIN_LOCK_UNLOCKED;
60 static int last_index_n;
61 static unsigned int ipu_ic_out_max_width_size;
62 static unsigned int ipu_ic_out_max_height_size;
63 /* debug counters */
64 uint32_t g_irq_cnt;
65 uint32_t g_buf_output_cnt;
66 uint32_t g_buf_q_cnt;
67 uint32_t g_buf_dq_cnt;
68
69 #define QUEUE_SIZE (MAX_FRAME_NUM + 1)
70 static __inline int queue_size(v4l_queue * q)
71 {
72         if (q->tail >= q->head)
73                 return (q->tail - q->head);
74         else
75                 return ((q->tail + QUEUE_SIZE) - q->head);
76 }
77
78 static __inline int queue_buf(v4l_queue * q, int idx)
79 {
80         if (((q->tail + 1) % QUEUE_SIZE) == q->head)
81                 return -1;      /* queue full */
82         q->list[q->tail] = idx;
83         q->tail = (q->tail + 1) % QUEUE_SIZE;
84         return 0;
85 }
86
87 static __inline int dequeue_buf(v4l_queue * q)
88 {
89         int ret;
90         if (q->tail == q->head)
91                 return -1;      /* queue empty */
92         ret = q->list[q->head];
93         q->head = (q->head + 1) % QUEUE_SIZE;
94         return ret;
95 }
96
97 static __inline int peek_next_buf(v4l_queue * q)
98 {
99         if (q->tail == q->head)
100                 return -1;      /* queue empty */
101         return q->list[q->head];
102 }
103
104 static __inline unsigned long get_jiffies(struct timeval *t)
105 {
106         struct timeval cur;
107
108         if (t->tv_usec >= 1000000) {
109                 t->tv_sec += t->tv_usec / 1000000;
110                 t->tv_usec = t->tv_usec % 1000000;
111         }
112
113         do_gettimeofday(&cur);
114         if ((t->tv_sec < cur.tv_sec)
115             || ((t->tv_sec == cur.tv_sec) && (t->tv_usec < cur.tv_usec)))
116                 return jiffies;
117
118         if (t->tv_usec < cur.tv_usec) {
119                 cur.tv_sec = t->tv_sec - cur.tv_sec - 1;
120                 cur.tv_usec = t->tv_usec + 1000000 - cur.tv_usec;
121         } else {
122                 cur.tv_sec = t->tv_sec - cur.tv_sec;
123                 cur.tv_usec = t->tv_usec - cur.tv_usec;
124         }
125
126         return jiffies + timeval_to_jiffies(&cur);
127 }
128
129 /*!
130  * Private function to free buffers
131  *
132  * @param bufs_paddr    Array of physical address of buffers to be freed
133  *
134  * @param bufs_vaddr    Array of virtual address of buffers to be freed
135  *
136  * @param num_buf       Number of buffers to be freed
137  *
138  * @param size          Size for each buffer to be free
139  *
140  * @return status  0 success.
141  */
142 static int mxc_free_buffers(dma_addr_t bufs_paddr[], void *bufs_vaddr[],
143                             int num_buf, int size)
144 {
145         int i;
146
147         for (i = 0; i < num_buf; i++) {
148                 if (bufs_vaddr[i] != 0) {
149                         dma_free_coherent(0, size, bufs_vaddr[i],
150                                           bufs_paddr[i]);
151                         pr_debug("freed @ paddr=0x%08X\n", (u32) bufs_paddr[i]);
152                         bufs_paddr[i] = 0;
153                         bufs_vaddr[i] = NULL;
154                 }
155         }
156         return 0;
157 }
158
159 /*!
160  * Private function to allocate buffers
161  *
162  * @param bufs_paddr    Output array of physical address of buffers allocated
163  *
164  * @param bufs_vaddr    Output array of virtual address of buffers allocated
165  *
166  * @param num_buf       Input number of buffers to allocate
167  *
168  * @param size          Input size for each buffer to allocate
169  *
170  * @return status       -0 Successfully allocated a buffer, -ENOBUFS failed.
171  */
172 static int mxc_allocate_buffers(dma_addr_t bufs_paddr[], void *bufs_vaddr[],
173                                 int num_buf, int size)
174 {
175         int i;
176
177         for (i = 0; i < num_buf; i++) {
178                 bufs_vaddr[i] = dma_alloc_coherent(0, size,
179                                                    &bufs_paddr[i],
180                                                    GFP_DMA | GFP_KERNEL);
181
182                 if (bufs_vaddr[i] == 0) {
183                         mxc_free_buffers(bufs_paddr, bufs_vaddr, i, size);
184                         printk(KERN_ERR "dma_alloc_coherent failed.\n");
185                         return -ENOBUFS;
186                 }
187                 pr_debug("allocated @ paddr=0x%08X, size=%d.\n",
188                          (u32) bufs_paddr[i], size);
189         }
190
191         return 0;
192 }
193
194 /*
195  * Returns bits per pixel for given pixel format
196  *
197  * @param pixelformat  V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
198  *
199  * @return bits per pixel of pixelformat
200  */
201 static u32 fmt_to_bpp(u32 pixelformat)
202 {
203         u32 bpp;
204
205         bpp = 8 * bytes_per_pixel(pixelformat);
206         return bpp;
207 }
208
209 static bool format_is_yuv(u32 pixelformat)
210 {
211         switch (pixelformat) {
212         case V4L2_PIX_FMT_YUV420:
213         case V4L2_PIX_FMT_UYVY:
214         case V4L2_PIX_FMT_YUYV:
215         case V4L2_PIX_FMT_YUV422P:
216         case V4L2_PIX_FMT_YVU420:
217         case V4L2_PIX_FMT_NV12:
218                 return true;
219                 break;
220         }
221         return false;
222 }
223
224 static u32 bpp_to_fmt(struct fb_info *fbi)
225 {
226         if (fbi->var.nonstd)
227                 return fbi->var.nonstd;
228
229         if (fbi->var.bits_per_pixel == 24)
230                 return V4L2_PIX_FMT_BGR24;
231         else if (fbi->var.bits_per_pixel == 32)
232                 return V4L2_PIX_FMT_BGR32;
233         else if (fbi->var.bits_per_pixel == 16)
234                 return V4L2_PIX_FMT_RGB565;
235
236         return 0;
237 }
238
239 /*
240  * we are using double buffer for video playback, ipu need make
241  * sure current buffer should not be the same buffer of next display
242  * one.
243  */
244 static int select_display_buffer(vout_data *vout, int next_buf)
245 {
246         int ret = 0;
247
248         if (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
249                         != next_buf)
250                 ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
251                                 next_buf);
252         else
253                 dev_dbg(&vout->video_dev->dev,
254                         "display buffer not ready for select\n");
255         return ret;
256 }
257
258 static void setup_next_buf_timer(vout_data *vout, int index)
259 {
260         unsigned long timeout;
261
262         /* Setup timer for next buffer */
263         /* if timestamp is 0, then default to 30fps */
264         if ((vout->v4l2_bufs[index].timestamp.tv_sec == 0)
265                         && (vout->v4l2_bufs[index].timestamp.tv_usec == 0)
266                         && vout->start_jiffies)
267                 timeout =
268                         vout->start_jiffies + vout->frame_count * HZ / 30;
269         else
270                 timeout =
271                         get_jiffies(&vout->v4l2_bufs[index].timestamp);
272
273         if (jiffies >= timeout) {
274                 dev_dbg(&vout->video_dev->dev,
275                                 "warning: timer timeout already expired.\n");
276         }
277         if (mod_timer(&vout->output_timer, timeout))
278                 dev_dbg(&vout->video_dev->dev,
279                                 "warning: timer was already set\n");
280
281         dev_dbg(&vout->video_dev->dev,
282                         "timer handler next schedule: %lu\n", timeout);
283 }
284
285 static int finish_previous_frame(vout_data *vout)
286 {
287         struct fb_info *fbi =
288                 registered_fb[vout->output_fb_num[vout->cur_disp_output]];
289         mm_segment_t old_fs;
290         int ret = 0;
291
292         /* make sure buf[next_done_ipu_buf] showed */
293         while (ipu_check_buffer_busy(vout->display_ch,
294                         IPU_INPUT_BUFFER, vout->next_done_ipu_buf)) {
295                 /* wait for display frame finish */
296                 if (fbi->fbops->fb_ioctl) {
297                         old_fs = get_fs();
298                         set_fs(KERNEL_DS);
299                         ret = fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
300                                         (unsigned int)NULL);
301                         set_fs(old_fs);
302
303                         if (ret < 0) {
304                                 /* ic_bypass need clear display buffer ready for next update*/
305                                 ipu_clear_buffer_ready(vout->display_ch, IPU_INPUT_BUFFER,
306                                                 vout->next_done_ipu_buf);
307                         }
308                 }
309         }
310
311         return ret;
312 }
313
314 static int show_current_frame(vout_data *vout)
315 {
316         struct fb_info *fbi =
317                 registered_fb[vout->output_fb_num[vout->cur_disp_output]];
318         mm_segment_t old_fs;
319         int ret = 0;
320
321         /* make sure buf[next_rdy_ipu_buf] begin to show */
322         if (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
323                 != vout->next_rdy_ipu_buf) {
324                 /* wait for display frame finish */
325                 if (fbi->fbops->fb_ioctl) {
326                         old_fs = get_fs();
327                         set_fs(KERNEL_DS);
328                         ret = fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
329                                         (unsigned int)NULL);
330                         set_fs(old_fs);
331                 }
332         }
333
334         return ret;
335 }
336
337 static void timer_work_func(struct work_struct *work)
338 {
339         vout_data *vout =
340                 container_of(work, vout_data, timer_work);
341         int index, ret;
342         int last_buf;
343         unsigned long lock_flags = 0;
344
345         finish_previous_frame(vout);
346
347         spin_lock_irqsave(&g_lock, lock_flags);
348
349         if (g_buf_output_cnt == 0) {
350                 ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER, 1);
351         } else {
352                 index = dequeue_buf(&vout->ready_q);
353                 if (index == -1) {      /* no buffers ready, should never occur */
354                         dev_err(&vout->video_dev->dev,
355                                         "mxc_v4l2out: timer - no queued buffers ready\n");
356                         goto exit;
357                 }
358                 g_buf_dq_cnt++;
359                 vout->frame_count++;
360
361                 vout->ipu_buf[vout->next_rdy_ipu_buf] = index;
362                 ret = ipu_update_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER,
363                                 vout->next_rdy_ipu_buf,
364                                 vout->v4l2_bufs[index].m.offset);
365                 ret += select_display_buffer(vout, vout->next_rdy_ipu_buf);
366                 if (ret < 0) {
367                         dev_err(&vout->video_dev->dev,
368                                         "unable to update buffer %d address rc=%d\n",
369                                         vout->next_rdy_ipu_buf, ret);
370                         goto exit;
371                 }
372                 spin_unlock_irqrestore(&g_lock, lock_flags);
373                 show_current_frame(vout);
374                 spin_lock_irqsave(&g_lock, lock_flags);
375                 vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
376         }
377
378         last_buf = vout->ipu_buf[vout->next_done_ipu_buf];
379         if (last_buf != -1) {
380                 g_buf_output_cnt++;
381                 vout->v4l2_bufs[last_buf].flags = V4L2_BUF_FLAG_DONE;
382                 queue_buf(&vout->done_q, last_buf);
383                 wake_up_interruptible(&vout->v4l_bufq);
384                 vout->ipu_buf[vout->next_done_ipu_buf] = -1;
385                 vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
386         }
387
388         if (g_buf_output_cnt > 0) {
389                 /* Setup timer for next buffer */
390                 index = peek_next_buf(&vout->ready_q);
391                 if (index != -1)
392                         setup_next_buf_timer(vout, index);
393                 else
394                         vout->state = STATE_STREAM_PAUSED;
395
396                 if (vout->state == STATE_STREAM_STOPPING) {
397                         if ((vout->ipu_buf[0] == -1) && (vout->ipu_buf[1] == -1)) {
398                                 vout->state = STATE_STREAM_OFF;
399                         }
400                 }
401         }
402 exit:
403         spin_unlock_irqrestore(&g_lock, lock_flags);
404 }
405
406 static void mxc_v4l2out_timer_handler(unsigned long arg)
407 {
408         int index, ret;
409         unsigned long lock_flags = 0;
410         vout_data *vout = (vout_data *) arg;
411
412         spin_lock_irqsave(&g_lock, lock_flags);
413
414         if ((vout->state == STATE_STREAM_STOPPING)
415             || (vout->state == STATE_STREAM_OFF))
416                 goto exit0;
417
418         /*
419          * If timer occurs before IPU h/w is ready, then set the state to
420          * paused and the timer will be set again when next buffer is queued
421          * or PP comletes
422          */
423         if (vout->ipu_buf[vout->next_rdy_ipu_buf] != -1) {
424                 dev_dbg(&vout->video_dev->dev, "IPU buffer busy\n");
425                 vout->state = STATE_STREAM_PAUSED;
426                 goto exit0;
427         }
428
429         /* Handle ic bypass mode in work queue */
430         if (vout->ic_bypass) {
431                 if (queue_work(vout->v4l_wq, &vout->timer_work) == 0) {
432                         dev_err(&vout->video_dev->dev, "work was in queue already!\n ");
433                         vout->state = STATE_STREAM_PAUSED;
434                 }
435                 goto exit0;
436         }
437
438         /* Dequeue buffer and pass to IPU */
439         index = dequeue_buf(&vout->ready_q);
440         if (index == -1) {      /* no buffers ready, should never occur */
441                 dev_err(&vout->video_dev->dev,
442                         "mxc_v4l2out: timer - no queued buffers ready\n");
443                 goto exit0;
444         }
445         g_buf_dq_cnt++;
446         vout->frame_count++;
447
448         /* update next buffer */
449         if (LOAD_3FIELDS(vout)) {
450                 int index_n = index;
451                 int index_p = last_index_n;
452                 vout->ipu_buf_p[vout->next_rdy_ipu_buf] = last_index_n;
453                 vout->ipu_buf[vout->next_rdy_ipu_buf] = index;
454                 vout->ipu_buf_n[vout->next_rdy_ipu_buf] = index;
455                 ret = ipu_update_channel_buffer(vout->post_proc_ch,
456                                 IPU_INPUT_BUFFER,
457                                 vout->next_rdy_ipu_buf,
458                                 vout->v4l2_bufs[index].m.offset);
459                 ret += ipu_update_channel_buffer(MEM_VDI_PRP_VF_MEM_P,
460                                 IPU_INPUT_BUFFER,
461                                 vout->next_rdy_ipu_buf,
462                                 vout->v4l2_bufs[index_p].m.offset + vout->bytesperline);
463                 ret += ipu_update_channel_buffer(MEM_VDI_PRP_VF_MEM_N,
464                                 IPU_INPUT_BUFFER,
465                                 vout->next_rdy_ipu_buf,
466                                 vout->v4l2_bufs[index_n].m.offset) + vout->bytesperline;
467                 last_index_n = index;
468         } else {
469                 vout->ipu_buf[vout->next_rdy_ipu_buf] = index;
470                 if (vout->pp_split) {
471                         vout->ipu_buf[!vout->next_rdy_ipu_buf] = index;
472                         /* always left stripe */
473                         ret = ipu_update_channel_buffer(vout->post_proc_ch,
474                                         IPU_INPUT_BUFFER,
475                                         0,/* vout->next_rdy_ipu_buf,*/
476                                         (vout->v4l2_bufs[index].m.offset) +
477                                         vout->pp_left_stripe.input_column +
478                                         vout->pp_up_stripe.input_column * vout->bytesperline);
479
480                         /* the U/V offset has to be updated inside of IDMAC */
481                         /* according to stripe offset */
482                         ret += ipu_update_channel_offset(vout->post_proc_ch,
483                                         IPU_INPUT_BUFFER,
484                                         vout->v2f.fmt.pix.pixelformat,
485                                         vout->v2f.fmt.pix.width,
486                                         vout->v2f.fmt.pix.height,
487                                         vout->bytesperline,
488                                         vout->offset.u_offset,
489                                         vout->offset.v_offset,
490                                         vout->pp_up_stripe.input_column,
491                                         vout->pp_left_stripe.input_column);
492                 } else
493                         ret = ipu_update_channel_buffer(vout->post_proc_ch,
494                                         IPU_INPUT_BUFFER,
495                                         vout->next_rdy_ipu_buf,
496                                         vout->v4l2_bufs[index].m.offset);
497         }
498
499         if (ret < 0) {
500                 dev_err(&vout->video_dev->dev,
501                         "unable to update buffer %d address rc=%d\n",
502                         vout->next_rdy_ipu_buf, ret);
503                 goto exit0;
504         }
505
506         /* set next buffer ready */
507         if (LOAD_3FIELDS(vout))
508                 ret = ipu_select_multi_vdi_buffer(vout->next_rdy_ipu_buf);
509         else
510                 ret = ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER,
511                                 vout->next_rdy_ipu_buf);
512         if (ret < 0) {
513                 dev_err(&vout->video_dev->dev,
514                                 "unable to set IPU buffer ready\n");
515                 goto exit0;
516         }
517
518         /* Non IC split action */
519         if (!vout->pp_split)
520                 vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
521
522         /* Setup timer for next buffer */
523         index = peek_next_buf(&vout->ready_q);
524         if (index != -1)
525                 setup_next_buf_timer(vout, index);
526         else
527                 vout->state = STATE_STREAM_PAUSED;
528
529         if (vout->state == STATE_STREAM_STOPPING) {
530                 if ((vout->ipu_buf[0] == -1) && (vout->ipu_buf[1] == -1)) {
531                         vout->state = STATE_STREAM_OFF;
532                 }
533         }
534
535         spin_unlock_irqrestore(&g_lock, lock_flags);
536
537         return;
538
539 exit0:
540         spin_unlock_irqrestore(&g_lock, lock_flags);
541 }
542
543 static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
544 {
545         int last_buf;
546         int index;
547         unsigned long lock_flags = 0;
548         vout_data *vout = dev_id;
549         int pp_out_buf_left_right = 0;
550         int disp_buf_num = 0;
551         int disp_buf_num_next = 1;
552         int local_buffer = 0;
553         int pp_out_buf_offset = 0;
554         int pp_out_buf_up_down = 0;
555         int release_buffer = 0;
556         u32 eba_offset = 0;
557         u32 vertical_offset = 0;
558         u16 x_pos;
559         u16 y_pos;
560         int ret = -1;
561
562         spin_lock_irqsave(&g_lock, lock_flags);
563
564         g_irq_cnt++;
565
566         /* Process previous buffer */
567         if (LOAD_3FIELDS(vout))
568                 last_buf = vout->ipu_buf_p[vout->next_done_ipu_buf];
569         else
570                 last_buf = vout->ipu_buf[vout->next_done_ipu_buf];
571
572         if (last_buf != -1) {
573                 /* If IC split mode on, update output buffer number */
574                 if (vout->pp_split) {
575                         pp_out_buf_up_down = vout->pp_split_buf_num & 1;/* left/right stripe */
576                         pp_out_buf_left_right = (vout->pp_split_buf_num >> 1) & 1; /* up/down */
577                         local_buffer = (vout->pp_split == 1) ? pp_out_buf_up_down :
578                                         pp_out_buf_left_right;
579                         disp_buf_num = vout->pp_split_buf_num >> 2;
580                         disp_buf_num_next =
581                                         ((vout->pp_split_buf_num + (vout->pp_split << 0x1)) & 7) >> 2;
582                         if ((!pp_out_buf_left_right) ||
583                                 ((!pp_out_buf_up_down) && (vout->pp_split == 1))) {
584                                 if (vout->pp_split == 1) {
585                                                 eba_offset = ((pp_out_buf_left_right + pp_out_buf_up_down) & 1) ?
586                                                                         vout->pp_right_stripe.input_column :
587                                                                         vout->pp_left_stripe.input_column;
588                                                 vertical_offset = pp_out_buf_up_down ?
589                                                                         vout->pp_up_stripe.input_column :
590                                                                         vout->pp_down_stripe.input_column;
591
592                                 } else {
593                                                 eba_offset = pp_out_buf_left_right ?
594                                                                         vout->pp_left_stripe.input_column :
595                                                                         vout->pp_right_stripe.input_column;
596                                                 vertical_offset = pp_out_buf_left_right ?
597                                                                         vout->pp_up_stripe.input_column :
598                                                                         vout->pp_down_stripe.input_column;
599                                 }
600
601                                 ret = ipu_update_channel_buffer(vout->post_proc_ch,
602                                                 IPU_INPUT_BUFFER,
603                                                 (1 - local_buffer),
604                                                 (vout->v4l2_bufs[vout->ipu_buf[disp_buf_num]].m.offset)
605                                                 + eba_offset + vertical_offset * vout->bytesperline);
606                                 ret += ipu_update_channel_offset(vout->post_proc_ch,
607                                                                 IPU_INPUT_BUFFER,
608                                                                 vout->v2f.fmt.pix.pixelformat,
609                                                                 vout->v2f.fmt.pix.width,
610                                                                 vout->v2f.fmt.pix.height,
611                                                                 vout->bytesperline,
612                                                                 vout->offset.u_offset,
613                                                                 vout->offset.v_offset,
614                                                                 vertical_offset,
615                                                                 eba_offset);
616
617                                 /* select right stripe */
618                                 ret += ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER,
619                                                         (1 - local_buffer));
620                                 if (ret < 0)
621                                         dev_err(&vout->video_dev->dev,
622                                         "unable to set IPU buffer ready\n");
623                                         vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
624
625                         } else {/* last stripe is done, run display refresh */
626                                 select_display_buffer(vout, disp_buf_num);
627                                 vout->ipu_buf[vout->next_done_ipu_buf] = -1;
628                                 vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
629                                 vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
630                         }
631
632                         /* offset for next buffer's EBA */
633                         eba_offset = 0;
634                         if (vout->pp_split == 1) {
635                                 pp_out_buf_offset = ((vout->pp_split_buf_num >> 1) & 1) ?
636                                                                 vout->pp_left_stripe.output_column :
637                                                                 vout->pp_right_stripe.output_column;
638
639                                 eba_offset = ((vout->pp_split_buf_num & 1) ?
640                                                                 vout->pp_down_stripe.output_column :
641                                                                 vout->pp_up_stripe.output_column);
642
643                         } else {
644                                 pp_out_buf_offset = ((vout->pp_split_buf_num >> 1) & 1) ?
645                                                                         vout->pp_right_stripe.output_column :
646                                                                         vout->pp_left_stripe.output_column;
647                                 eba_offset = ((vout->pp_split_buf_num >> 1) & 1) ?
648                                                                         vout->pp_down_stripe.output_column :
649                                                                         vout->pp_up_stripe.output_column;
650                         }
651
652                         if (vout->cur_disp_output == 5) {
653                                 x_pos = (vout->crop_current.left / 8) * 8;
654                                 y_pos = vout->crop_current.top;
655                                 eba_offset += (vout->xres * y_pos + x_pos) * vout->bpp / 8;
656                         }
657
658
659                         /* next buffer update */
660                         eba_offset = vout->display_bufs[disp_buf_num_next] +
661                                                 pp_out_buf_offset + eba_offset;
662
663                         ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER,
664                                                 local_buffer, eba_offset);
665
666                         /* next buffer ready */
667                         ret = ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, local_buffer);
668
669                         /* next stripe_buffer index 0..7 */
670                         vout->pp_split_buf_num = (vout->pp_split_buf_num + vout->pp_split) & 0x7;
671
672
673                 } else {
674                         /* show to display */
675                         select_display_buffer(vout, vout->next_done_ipu_buf);
676                         ret += ipu_select_buffer(vout->display_input_ch, IPU_OUTPUT_BUFFER,
677                                         vout->next_done_ipu_buf);
678                 }
679
680                 /* release buffer. For split mode: if second stripe is done */
681                 release_buffer = vout->pp_split ? (!(vout->pp_split_buf_num & 0x3)) : 1;
682                 if (release_buffer) {
683                         g_buf_output_cnt++;
684                         vout->v4l2_bufs[last_buf].flags = V4L2_BUF_FLAG_DONE;
685                         queue_buf(&vout->done_q, last_buf);
686                         wake_up_interruptible(&vout->v4l_bufq);
687                         vout->ipu_buf[vout->next_done_ipu_buf] = -1;
688                         if (LOAD_3FIELDS(vout)) {
689                                 vout->ipu_buf_p[vout->next_done_ipu_buf] = -1;
690                                 vout->ipu_buf_n[vout->next_done_ipu_buf] = -1;
691                         }
692                         vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
693                 }
694         } /* end of last_buf != -1 */
695
696         if (vout->state == STATE_STREAM_STOPPING) {
697                 if ((vout->ipu_buf[0] == -1) && (vout->ipu_buf[1] == -1)) {
698                         vout->state = STATE_STREAM_OFF;
699                 }
700         } else if ((vout->state == STATE_STREAM_PAUSED)
701                    && ((index = peek_next_buf(&vout->ready_q)) != -1)) {
702                 /* Setup timer for next buffer, when stream has been paused */
703                 pr_debug("next index %d\n", index);
704                 setup_next_buf_timer(vout, index);
705                 vout->state = STATE_STREAM_ON;
706         }
707
708         spin_unlock_irqrestore(&g_lock, lock_flags);
709
710         return IRQ_HANDLED;
711 }
712
713 /*!
714  *  Initialize VDI channels
715  *
716  * @param vout      structure vout_data *
717  *
718  * @return status  0 Success
719  */
720 static int init_VDI_channel(vout_data *vout, ipu_channel_params_t params)
721 {
722         struct device *dev = &vout->video_dev->dev;
723
724         if (ipu_init_channel(MEM_VDI_PRP_VF_MEM, &params) != 0) {
725                 dev_dbg(dev, "Error initializing VDI current channel\n");
726                 return -EINVAL;
727         }
728         if (LOAD_3FIELDS(vout)) {
729                 if (ipu_init_channel(MEM_VDI_PRP_VF_MEM_P, &params) != 0) {
730                         dev_err(dev, "Error initializing VDI previous channel\n");
731                         return -EINVAL;
732                 }
733                 if (ipu_init_channel(MEM_VDI_PRP_VF_MEM_N, &params) != 0) {
734                         dev_err(dev, "Error initializing VDI next channel\n");
735                         return -EINVAL;
736                 }
737         }
738         return 0;
739 }
740
741 /*!
742  * Initialize VDI channel buffers
743  *
744  * @param vout      structure vout_data *
745  *
746  * @return status  0 Success
747  */
748 static int init_VDI_in_channel_buffer(vout_data *vout, uint32_t in_pixel_fmt,
749                                    uint16_t in_width, uint16_t in_height,
750                                    uint32_t stride,
751                                    uint32_t u_offset, uint32_t v_offset)
752 {
753         struct device *dev = &vout->video_dev->dev;
754
755         if (ipu_init_channel_buffer(MEM_VDI_PRP_VF_MEM, IPU_INPUT_BUFFER,
756                                     in_pixel_fmt, in_width, in_height, stride,
757                                     IPU_ROTATE_NONE,
758                                     vout->v4l2_bufs[vout->ipu_buf[0]].m.offset,
759                                     vout->v4l2_bufs[vout->ipu_buf[0]].m.offset,
760                                     u_offset, v_offset) != 0) {
761                 dev_err(dev, "Error initializing VDI current input buffer\n");
762                 return -EINVAL;
763         }
764         if (LOAD_3FIELDS(vout)) {
765                 if (ipu_init_channel_buffer(MEM_VDI_PRP_VF_MEM_P,
766                                             IPU_INPUT_BUFFER,
767                                             in_pixel_fmt, in_width, in_height,
768                                             stride, IPU_ROTATE_NONE,
769                                             vout->v4l2_bufs[vout->ipu_buf_p[0]].m.offset+vout->bytesperline,
770                                             vout->v4l2_bufs[vout->ipu_buf_p[0]].m.offset+vout->bytesperline,
771                                             u_offset, v_offset) != 0) {
772                         dev_err(dev, "Error initializing VDI previous input buffer\n");
773                         return -EINVAL;
774                 }
775                 if (ipu_init_channel_buffer(MEM_VDI_PRP_VF_MEM_N,
776                                             IPU_INPUT_BUFFER,
777                                             in_pixel_fmt, in_width, in_height,
778                                             stride, IPU_ROTATE_NONE,
779                                             vout->v4l2_bufs[vout->ipu_buf_n[0]].m.offset+vout->bytesperline,
780                                             vout->v4l2_bufs[vout->ipu_buf_n[0]].m.offset+vout->bytesperline,
781                                             u_offset, v_offset) != 0) {
782                         dev_err(dev, "Error initializing VDI next input buffer\n");
783                         return -EINVAL;
784                 }
785         }
786         return 0;
787 }
788
789 /*!
790  * Initialize VDI path
791  *
792  * @param vout      structure vout_data *
793  *
794  * @return status  0 Success
795  */
796 static int init_VDI(ipu_channel_params_t params, vout_data *vout,
797                         struct device *dev, struct fb_info *fbi,
798                         u16 out_width, u16 out_height)
799 {
800         params.mem_prp_vf_mem.in_width = vout->v2f.fmt.pix.width;
801         params.mem_prp_vf_mem.in_height = vout->v2f.fmt.pix.height;
802         params.mem_prp_vf_mem.motion_sel = vout->motion_sel;
803         params.mem_prp_vf_mem.field_fmt = vout->field_fmt;
804         params.mem_prp_vf_mem.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat;
805         params.mem_prp_vf_mem.out_width = out_width;
806         params.mem_prp_vf_mem.out_height = out_height;
807         params.mem_prp_vf_mem.out_pixel_fmt = bpp_to_fmt(fbi);
808
809         if (init_VDI_channel(vout, params) != 0) {
810                 dev_err(dev, "Error init_VDI_channel channel\n");
811                 return -EINVAL;
812         }
813
814         if (init_VDI_in_channel_buffer(vout,
815                                        params.mem_prp_vf_mem.in_pixel_fmt,
816                                        params.mem_prp_vf_mem.in_width,
817                                        params.mem_prp_vf_mem.in_height,
818                                        bytes_per_pixel(params.mem_prp_vf_mem.
819                                                        in_pixel_fmt),
820                                        vout->offset.u_offset,
821                                        vout->offset.v_offset) != 0) {
822                 return -EINVAL;
823         }
824
825         if (!ipu_can_rotate_in_place(vout->rotate)) {
826                 if (vout->rot_pp_bufs[0]) {
827                         mxc_free_buffers(vout->rot_pp_bufs,
828                                          vout->rot_pp_bufs_vaddr, 2,
829                                          vout->display_buf_size);
830                 }
831                 if (mxc_allocate_buffers
832                     (vout->rot_pp_bufs, vout->rot_pp_bufs_vaddr, 2,
833                      vout->display_buf_size) < 0) {
834                         return -ENOBUFS;
835                 }
836
837                 if (ipu_init_channel_buffer(vout->post_proc_ch,
838                                             IPU_OUTPUT_BUFFER,
839                                             params.mem_prp_vf_mem.
840                                             out_pixel_fmt, out_width,
841                                             out_height, out_width,
842                                             IPU_ROTATE_NONE,
843                                             vout->rot_pp_bufs[0],
844                                             vout->rot_pp_bufs[1], 0, 0) != 0) {
845                         dev_err(dev, "Error initializing PRP output buffer\n");
846                         return -EINVAL;
847                 }
848
849                 if (ipu_init_channel(MEM_ROT_VF_MEM, NULL) != 0) {
850                         dev_err(dev, "Error initializing PP ROT channel\n");
851                         return -EINVAL;
852                 }
853                 if (ipu_init_channel_buffer(MEM_ROT_VF_MEM,
854                                             IPU_INPUT_BUFFER,
855                                             params.mem_prp_vf_mem.
856                                             out_pixel_fmt, out_width,
857                                             out_height, out_width,
858                                             vout->rotate,
859                                             vout->rot_pp_bufs[0],
860                                             vout->rot_pp_bufs[1], 0, 0) != 0) {
861                         dev_err(dev,
862                                 "Error initializing PP ROT input buffer\n");
863                         return -EINVAL;
864                 }
865
866                 /* swap width and height */
867                 if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
868                         out_width = vout->crop_current.width;
869                         out_height = vout->crop_current.height;
870                 }
871
872                 if (ipu_init_channel_buffer(MEM_ROT_VF_MEM,
873                                             IPU_OUTPUT_BUFFER,
874                                             params.mem_prp_vf_mem.
875                                             out_pixel_fmt, out_width,
876                                             out_height, out_width,
877                                             IPU_ROTATE_NONE,
878                                             vout->display_bufs[0],
879                                             vout->display_bufs[1], 0, 0) != 0) {
880                         dev_err(dev,
881                                 "Error initializing PP-VDI output buffer\n");
882                         return -EINVAL;
883                 }
884
885                 if (ipu_link_channels(vout->post_proc_ch, MEM_ROT_VF_MEM) < 0)
886                         return -EINVAL;
887
888                 vout->display_input_ch = MEM_ROT_VF_MEM;
889                 ipu_enable_channel(MEM_ROT_VF_MEM);
890                 ipu_select_buffer(MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, 0);
891                 ipu_select_buffer(MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, 1);
892         } else {
893                 if (ipu_init_channel_buffer(vout->post_proc_ch,
894                                             IPU_OUTPUT_BUFFER,
895                                             params.mem_prp_vf_mem.
896                                             out_pixel_fmt, out_width,
897                                             out_height, out_width,
898                                             vout->rotate,
899                                             vout->display_bufs[0],
900                                             vout->display_bufs[1], 0, 0) != 0) {
901                         dev_err(dev,
902                                 "Error initializing PP-VDI output buffer\n");
903                         return -EINVAL;
904                 }
905         }
906         return 0;
907 }
908
909 /*!
910  * Initialize PP path
911  *
912  * @param params    structure ipu_channel_params_t
913  *
914  * @param vout      structure vout_data *
915  *
916  * @return status  0 Success
917  */
918 static int init_PP(ipu_channel_params_t *params, vout_data *vout,
919                    struct device *dev, struct fb_info *fbi,
920                    u16 out_width, u16 out_height)
921 {
922         u16 in_width, out_stride; /* stride of output channel */
923         u32 eba_offset;
924         u16 x_pos;
925         u16 y_pos;
926         eba_offset = 0;
927         x_pos = 0;
928         y_pos = 0;
929
930         params->mem_pp_mem.out_pixel_fmt = bpp_to_fmt(fbi);
931
932         if (vout->cur_disp_output == 5) {
933                 x_pos = (vout->crop_current.left / 8) * 8;
934                 y_pos = vout->crop_current.top;
935                 eba_offset = (vout->xres*y_pos + x_pos) *
936                                 bytes_per_pixel(params->mem_pp_mem.out_pixel_fmt);
937         }
938
939         vout->bpp = fmt_to_bpp(params->mem_pp_mem.out_pixel_fmt);
940         out_stride = vout->xres *
941                                 bytes_per_pixel(params->mem_pp_mem.out_pixel_fmt);
942         in_width = params->mem_pp_mem.in_width = vout->v2f.fmt.pix.width;
943         params->mem_pp_mem.in_height = vout->v2f.fmt.pix.height;
944         params->mem_pp_mem.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat;
945         params->mem_pp_mem.out_width = out_width;
946         params->mem_pp_mem.out_height = out_height;
947         params->mem_pp_mem.outh_resize_ratio = 0; /* 0 means unused */
948         params->mem_pp_mem.outv_resize_ratio = 0; /* 0 means unused */
949         /* split IC by two stripes, the by pass is impossible*/
950         if (vout->pp_split) {
951                 vout->pp_left_stripe.input_column = 0;
952                 vout->pp_left_stripe.output_column = 0;
953                 vout->pp_right_stripe.input_column = 0;
954                 vout->pp_right_stripe.output_column = 0;
955                 vout->pp_up_stripe.input_column = 0;
956                 vout->pp_up_stripe.output_column = 0;
957                 vout->pp_down_stripe.input_column = 0;
958                 vout->pp_down_stripe.output_column = 0;
959                 if (vout->pp_split != 3) {
960                         ipu_calc_stripes_sizes(
961                                 params->mem_pp_mem.in_width, /* input frame width;>1 */
962                                 params->mem_pp_mem.out_width, /* output frame width; >1 */
963                                 ipu_ic_out_max_width_size,
964                                 (((unsigned long long)1) << 32), /* 32bit for fractional*/
965                                 1,      /* equal stripes */
966                                 params->mem_pp_mem.in_pixel_fmt,
967                                 params->mem_pp_mem.out_pixel_fmt,
968                                 &(vout->pp_left_stripe),
969                                 &(vout->pp_right_stripe));
970
971                         vout->pp_left_stripe.input_column = vout->pp_left_stripe.input_column *
972                                                                 fmt_to_bpp(vout->v2f.fmt.pix.pixelformat) / 8;
973                         vout->pp_left_stripe.output_column = vout->pp_left_stripe.output_column *
974                                                                 fmt_to_bpp(params->mem_pp_mem.out_pixel_fmt) / 8;
975                         vout->pp_right_stripe.input_column = vout->pp_right_stripe.input_column *
976                                                                 fmt_to_bpp(vout->v2f.fmt.pix.pixelformat) / 8;
977                         vout->pp_right_stripe.output_column = vout->pp_right_stripe.output_column *
978                                                                 fmt_to_bpp(params->mem_pp_mem.out_pixel_fmt) / 8;
979
980
981                 /* updare parameters */
982                 params->mem_pp_mem.in_width = vout->pp_left_stripe.input_width;
983                 params->mem_pp_mem.out_width = vout->pp_left_stripe.output_width;
984                 out_width = vout->pp_left_stripe.output_width;
985                 /* for using in ic_init*/
986                 params->mem_pp_mem.outh_resize_ratio = vout->pp_left_stripe.irr;
987                 }
988                 if (vout->pp_split != 2) {
989                         ipu_calc_stripes_sizes(
990                                 params->mem_pp_mem.in_height, /* input frame width;>1 */
991                                 params->mem_pp_mem.out_height, /* output frame width; >1 */
992                                 ipu_ic_out_max_height_size,
993                                 (((unsigned long long)1) << 32),/* 32bit for fractional */
994                                 1,      /* equal stripes */
995                                 params->mem_pp_mem.in_pixel_fmt,
996                                 params->mem_pp_mem.out_pixel_fmt,
997                                 &(vout->pp_up_stripe),
998                                 &(vout->pp_down_stripe));
999                         vout->pp_down_stripe.output_column = vout->pp_down_stripe.output_column * out_stride;
1000                         vout->pp_up_stripe.output_column = vout->pp_up_stripe.output_column * out_stride;
1001                         params->mem_pp_mem.outv_resize_ratio = vout->pp_up_stripe.irr;
1002                         params->mem_pp_mem.in_height = vout->pp_up_stripe.input_width;/*height*/
1003                         out_height = vout->pp_up_stripe.output_width;/*height*/
1004                         if (vout->pp_split == 3)
1005                                 vout->pp_split = 2;/*2 vertical stripe as two horizontal stripes */
1006                 }
1007                 vout->pp_split_buf_num = 0;
1008         }
1009
1010         if (ipu_init_channel(vout->post_proc_ch, params) != 0) {
1011                 dev_err(dev, "Error initializing PP channel\n");
1012                 return -EINVAL;
1013         }
1014
1015         if (ipu_init_channel_buffer(vout->post_proc_ch,
1016                                     IPU_INPUT_BUFFER,
1017                                     params->mem_pp_mem.in_pixel_fmt,
1018                                     params->mem_pp_mem.in_width,
1019                                     params->mem_pp_mem.in_height,
1020                                     vout->v2f.fmt.pix.bytesperline /
1021                                     bytes_per_pixel(params->mem_pp_mem.
1022                                             in_pixel_fmt),
1023                                     IPU_ROTATE_NONE,
1024                                     vout->v4l2_bufs[vout->ipu_buf[0]].m.offset,
1025                                     vout->v4l2_bufs[vout->ipu_buf[1]].m.offset,
1026                                     vout->offset.u_offset,
1027                                     vout->offset.v_offset) != 0) {
1028                 dev_err(dev, "Error initializing PP input buffer\n");
1029                 return -EINVAL;
1030         }
1031
1032         if (!ipu_can_rotate_in_place(vout->rotate)) {
1033                 if (vout->rot_pp_bufs[0]) {
1034                         mxc_free_buffers(vout->rot_pp_bufs,
1035                                          vout->rot_pp_bufs_vaddr, 2,
1036                                          vout->display_buf_size);
1037                 }
1038                 if (mxc_allocate_buffers
1039                     (vout->rot_pp_bufs, vout->rot_pp_bufs_vaddr, 2,
1040                      vout->display_buf_size) < 0) {
1041                         return -ENOBUFS;
1042                 }
1043
1044                 if (ipu_init_channel_buffer(vout->post_proc_ch,
1045                                             IPU_OUTPUT_BUFFER,
1046                                             params->mem_pp_mem.
1047                                             out_pixel_fmt, out_width,
1048                                             out_height, out_stride,
1049                                             IPU_ROTATE_NONE,
1050                                             vout->rot_pp_bufs[0] + eba_offset,
1051                                             vout->rot_pp_bufs[1] + eba_offset, 0, 0) != 0) {
1052                         dev_err(dev, "Error initializing PP output buffer\n");
1053                         return -EINVAL;
1054                 }
1055
1056                 if (ipu_init_channel(MEM_ROT_PP_MEM, NULL) != 0) {
1057                         dev_err(dev, "Error initializing PP ROT channel\n");
1058                         return -EINVAL;
1059                 }
1060                 if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,
1061                                             IPU_INPUT_BUFFER,
1062                                             params->mem_pp_mem.
1063                                             out_pixel_fmt, out_width,
1064                                             out_height, out_stride,
1065                                             vout->rotate,
1066                                             vout->rot_pp_bufs[0],
1067                                             vout->rot_pp_bufs[1], 0, 0) != 0) {
1068                         dev_err(dev,
1069                                 "Error initializing PP ROT input buffer\n");
1070                         return -EINVAL;
1071                 }
1072
1073                 /* swap width and height */
1074                 if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
1075                         out_width = vout->crop_current.width;
1076                         out_height = vout->crop_current.height;
1077                 }
1078
1079                 if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,
1080                                             IPU_OUTPUT_BUFFER,
1081                                             params->mem_pp_mem.
1082                                             out_pixel_fmt, out_width,
1083                                             out_height, out_stride,
1084                                             IPU_ROTATE_NONE,
1085                                             vout->display_bufs[0] + eba_offset,
1086                                             vout->display_bufs[1] + eba_offset, 0, 0) != 0) {
1087                         dev_err(dev, "Error initializing PP output buffer\n");
1088                         return -EINVAL;
1089                 }
1090
1091                 if (ipu_link_channels(vout->post_proc_ch, MEM_ROT_PP_MEM) < 0)
1092                         return -EINVAL;
1093
1094                 vout->display_input_ch = MEM_ROT_PP_MEM;
1095                 ipu_enable_channel(MEM_ROT_PP_MEM);
1096                 ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0);
1097                 ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 1);
1098         } else {
1099                 if (ipu_init_channel_buffer(vout->post_proc_ch,
1100                                             IPU_OUTPUT_BUFFER,
1101                                             params->mem_pp_mem.
1102                                             out_pixel_fmt, out_width,
1103                                             out_height, out_stride,
1104                                             vout->rotate,
1105                                             vout->display_bufs[0] + eba_offset,
1106                                             vout->display_bufs[1] + eba_offset, 0, 0) != 0) {
1107                         dev_err(dev, "Error initializing PP output buffer\n");
1108                         return -EINVAL;
1109                 }
1110         }
1111
1112         /* fix EBAs for IDMAC channels */
1113         if (vout->pp_split) {
1114                 ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER,
1115                                                                         0,
1116                                                                         vout->v4l2_bufs[vout->ipu_buf[0]].m.offset +
1117                                                                         vout->pp_left_stripe.input_column +
1118                                                                         vout->pp_up_stripe.input_column * vout->bytesperline);
1119
1120
1121                 ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER,
1122                                                                         1,
1123                                                                         vout->v4l2_bufs[vout->ipu_buf[0]].m.offset +
1124                                                                         vout->pp_right_stripe.input_column +
1125                                                                         vout->pp_up_stripe.input_column * vout->bytesperline);
1126
1127                 ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER,
1128                                                                         0,
1129                                                                         vout->display_bufs[0] + eba_offset +
1130                                                                         vout->pp_left_stripe.output_column +
1131                                                                         vout->pp_up_stripe.output_column);
1132
1133                 ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER,
1134                                                                         1,
1135                                                                         vout->display_bufs[0] + eba_offset +
1136                                                                         vout->pp_right_stripe.output_column +
1137                                                                         vout->pp_up_stripe.output_column);
1138         }
1139
1140         return 0;
1141 }
1142
1143 /*!
1144  * Start the output stream
1145  *
1146  * @param vout      structure vout_data *
1147  *
1148  * @return status  0 Success
1149  */
1150 static int mxc_v4l2out_streamon(vout_data * vout)
1151 {
1152         struct device *dev = &vout->video_dev->dev;
1153         ipu_channel_params_t params;
1154         struct mxcfb_pos fb_pos;
1155         struct fb_var_screeninfo fbvar;
1156         struct fb_info *fbi =
1157             registered_fb[vout->output_fb_num[vout->cur_disp_output]];
1158         u16 out_width;
1159         u16 out_height;
1160         mm_segment_t old_fs;
1161         unsigned int ipu_ch = CHAN_NONE;
1162         int rc = 0;
1163
1164         dev_dbg(dev, "mxc_v4l2out_streamon: field format=%d\n",
1165                 vout->field_fmt);
1166
1167         if (!vout)
1168                 return -EINVAL;
1169
1170         if (vout->state != STATE_STREAM_OFF)
1171                 return -EBUSY;
1172
1173         if (queue_size(&vout->ready_q) < 2) {
1174                 dev_err(dev, "2 buffers not been queued yet!\n");
1175                 return -EINVAL;
1176         }
1177
1178         if ((vout->field_fmt == V4L2_FIELD_BOTTOM) || (vout->field_fmt == V4L2_FIELD_TOP)) {
1179                 dev_err(dev, "4 queued buffers need, not supported yet!\n");
1180                 return -EINVAL;
1181         }
1182
1183         /*
1184          * params init, check whether operation exceed the IC limitation:
1185          * whether split mode used ( ipu version >= ipuv3 only)
1186          */
1187         g_irq_cnt = g_buf_output_cnt = g_buf_q_cnt = g_buf_dq_cnt = 0;
1188         out_width = vout->crop_current.width;
1189         out_height = vout->crop_current.height;
1190         vout->next_done_ipu_buf = 0;
1191         vout->next_rdy_ipu_buf = 1;
1192         vout->pp_split = 0;
1193         ipu_ic_out_max_height_size = 1024;
1194 #ifdef CONFIG_MXC_IPU_V1
1195         if (cpu_is_mx35())
1196                 ipu_ic_out_max_width_size = 800;
1197         else
1198                 ipu_ic_out_max_width_size = 720;
1199 #else
1200         ipu_ic_out_max_width_size = 1024;
1201 #endif
1202         if ((out_width > ipu_ic_out_max_width_size) ||
1203                 (out_height > ipu_ic_out_max_height_size))
1204                 vout->pp_split = 4;
1205         if (!INTERLACED_CONTENT(vout)) {
1206                 vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0;
1207                 vout->ipu_buf[0] = dequeue_buf(&vout->ready_q);
1208                 /* split IC by two stripes, the by pass is impossible*/
1209                 if ((out_width != vout->v2f.fmt.pix.width ||
1210                         out_height != vout->v2f.fmt.pix.height) &&
1211                         vout->pp_split) {
1212                         vout->ipu_buf[1] = vout->ipu_buf[0];
1213                         vout->frame_count = 1;
1214                         if ((out_width > ipu_ic_out_max_width_size) &&
1215                                 (out_height > ipu_ic_out_max_height_size))
1216                                 vout->pp_split = 1; /*4 stripes*/
1217                         else if (!(out_height > ipu_ic_out_max_height_size))
1218                                 vout->pp_split = 2; /*two horizontal stripes */
1219                         else
1220                                 vout->pp_split = 3; /*2 vertical stripes*/
1221                 } else {
1222                         vout->ipu_buf[1] = dequeue_buf(&vout->ready_q);
1223                         vout->frame_count = 2;
1224                 }
1225         } else if (!LOAD_3FIELDS(vout)) {
1226                 vout->ipu_buf[0] = dequeue_buf(&vout->ready_q);
1227                 vout->ipu_buf[1] = -1;
1228                 vout->frame_count = 1;
1229         } else {
1230                 vout->ipu_buf_p[0] = dequeue_buf(&vout->ready_q);
1231                 vout->ipu_buf[0] = dequeue_buf(&vout->ready_q);
1232                 vout->ipu_buf_n[0] = vout->ipu_buf[0];
1233                 vout->ipu_buf_p[1] = -1;
1234                 vout->ipu_buf[1] = -1;
1235                 vout->ipu_buf_n[1] = -1;
1236                 last_index_n = vout->ipu_buf_n[0];
1237                 vout->frame_count = 2;
1238         }
1239
1240         /*
1241          * Bypass IC if resizing and rotation are not needed
1242          * Meanwhile, apply IC bypass to SDC only
1243          */
1244         fbvar = fbi->var;
1245         vout->xres = fbvar.xres;
1246         vout->yres = fbvar.yres;
1247
1248         if (vout->cur_disp_output == 3 || vout->cur_disp_output == 5) {
1249                 fbvar.bits_per_pixel = 16;
1250                 if (format_is_yuv(vout->v2f.fmt.pix.pixelformat))
1251                         fbvar.nonstd = IPU_PIX_FMT_UYVY;
1252                 else
1253                         fbvar.nonstd = 0;
1254                 if (vout->cur_disp_output == 3) {
1255                         fbvar.xres = out_width;
1256                         fbvar.yres = out_height;
1257                         vout->xres = fbvar.xres;
1258                         vout->yres = fbvar.yres;
1259                 }
1260
1261                 fbvar.xres_virtual = fbvar.xres;
1262                 fbvar.yres_virtual = fbvar.yres * 2;
1263         }
1264
1265         if (out_width == vout->v2f.fmt.pix.width &&
1266             out_height == vout->v2f.fmt.pix.height &&
1267             vout->xres == out_width &&
1268             vout->yres == out_height &&
1269             ipu_can_rotate_in_place(vout->rotate) &&
1270             (vout->bytesperline ==
1271              bytes_per_pixel(vout->v2f.fmt.pix.pixelformat) * out_width) &&
1272             !INTERLACED_CONTENT(vout)) {
1273                 vout->ic_bypass = 1;
1274         } else {
1275                 vout->ic_bypass = 0;
1276         }
1277
1278 #ifdef CONFIG_MXC_IPU_V1
1279         /* IPUv1 needs IC to do CSC */
1280         if (format_is_yuv(vout->v2f.fmt.pix.pixelformat) !=
1281             format_is_yuv(bpp_to_fmt(fbi)))
1282                 vout->ic_bypass = 0;
1283 #endif
1284
1285         if (fbi->fbops->fb_ioctl) {
1286                 old_fs = get_fs();
1287                 set_fs(KERNEL_DS);
1288                 fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
1289                                 (unsigned long)&ipu_ch);
1290                 set_fs(old_fs);
1291         }
1292
1293         if (ipu_ch == CHAN_NONE) {
1294                 dev_err(dev, "Can not get display ipu channel\n");
1295                 return -EINVAL;
1296         }
1297
1298         vout->display_ch = ipu_ch;
1299
1300         if (vout->ic_bypass) {
1301                 pr_debug("Bypassing IC\n");
1302                 vout->pp_split = 0;
1303                 switch (vout->v2f.fmt.pix.pixelformat) {
1304                         case V4L2_PIX_FMT_YUV420:
1305                         case V4L2_PIX_FMT_YVU420:
1306                         case V4L2_PIX_FMT_NV12:
1307                                 fbvar.bits_per_pixel = 12;
1308                                 break;
1309                         case V4L2_PIX_FMT_YUV422P:
1310                                 fbvar.bits_per_pixel = 16;
1311                                 break;
1312                         default:
1313                                 fbvar.bits_per_pixel = 8*
1314                                         bytes_per_pixel(vout->v2f.fmt.pix.pixelformat);
1315                 }
1316                 fbvar.nonstd = vout->v2f.fmt.pix.pixelformat;
1317         }
1318
1319         /* Init display channel through fb API */
1320         fbvar.activate |= FB_ACTIVATE_FORCE;
1321         fb_set_var(fbi, &fbvar);
1322
1323         if (fbi->fbops->fb_ioctl && vout->display_ch == MEM_FG_SYNC) {
1324                 fb_pos.x = vout->crop_current.left;
1325                 fb_pos.y = vout->crop_current.top;
1326                 old_fs = get_fs();
1327                 set_fs(KERNEL_DS);
1328                 fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS,
1329                                 (unsigned long)&fb_pos);
1330                 set_fs(old_fs);
1331         }
1332
1333         vout->display_bufs[1] = fbi->fix.smem_start;
1334         vout->display_bufs[0] = fbi->fix.smem_start +
1335                 (fbi->fix.line_length * vout->yres);
1336         vout->display_buf_size = vout->xres *
1337                 vout->yres * fbi->var.bits_per_pixel / 8;
1338
1339         /* fill black color for init fb, we assume fb has double buffer*/
1340         if (format_is_yuv(vout->v2f.fmt.pix.pixelformat)) {
1341                 int i;
1342
1343                 if ((vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) ||
1344                         (vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) ||
1345                         (!vout->ic_bypass)) {
1346                         short * tmp = (short *) fbi->screen_base;
1347                         short color;
1348                         if (vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
1349                                 color = 0x8000;
1350                         else
1351                                 color = 0x80;
1352                         for (i = 0; i < (fbi->fix.line_length * fbi->var.yres_virtual)/2;
1353                                         i++, tmp++)
1354                                 *tmp = color;
1355                 } else if ((vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) ||
1356                                 (vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) ||
1357                                 (vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)) {
1358                         char * base = (char *)fbi->screen_base;
1359                         int j, screen_size = fbi->var.xres * fbi->var.yres;
1360
1361                         for (j = 0; j < 2; j++) {
1362                                 memset(base, 0, screen_size);
1363                                 base += screen_size;
1364                                 for (i = 0; i < screen_size/2; i++, base++)
1365                                         *base = 0x80;
1366                         }
1367                 } else if (vout->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
1368                         char * base = (char *)fbi->screen_base;
1369                         int j, screen_size = fbi->var.xres * fbi->var.yres;
1370
1371                         for (j = 0; j < 2; j++) {
1372                                 memset(base, 0, screen_size);
1373                                 base += screen_size;
1374                                 for (i = 0; i < screen_size; i++, base++)
1375                                         *base = 0x80;
1376                         }
1377                 }
1378         } else
1379                 memset(fbi->screen_base, 0x0,
1380                                 fbi->fix.line_length * fbi->var.yres_virtual);
1381
1382         if (INTERLACED_CONTENT(vout))
1383                 vout->post_proc_ch = MEM_VDI_PRP_VF_MEM;
1384         else if (!vout->ic_bypass)
1385                 vout->post_proc_ch = MEM_PP_MEM;
1386
1387         /* Init IC channel */
1388         if (!vout->ic_bypass) {
1389                 if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
1390                         out_width = vout->crop_current.height;
1391                         out_height = vout->crop_current.width;
1392                 }
1393                 vout->display_input_ch = vout->post_proc_ch;
1394                 memset(&params, 0, sizeof(params));
1395                 if (INTERLACED_CONTENT(vout)) {
1396                         if (vout->pp_split) {
1397                                 dev_err(&vout->video_dev->dev, "VDI split has not supported yet.\n");
1398                                 return -1;
1399                         } else
1400                                 rc = init_VDI(params, vout, dev, fbi, out_width, out_height);
1401                 } else {
1402                         rc = init_PP(&params, vout, dev, fbi, out_width, out_height);
1403                 }
1404                 if (rc < 0)
1405                         return rc;
1406         }
1407
1408         if (!vout->ic_bypass) {
1409                 switch (vout->display_input_ch) {
1410                 case MEM_PP_MEM:
1411                         vout->work_irq = IPU_IRQ_PP_OUT_EOF;
1412                         break;
1413                 case MEM_VDI_PRP_VF_MEM:
1414                         vout->work_irq = IPU_IRQ_PRP_VF_OUT_EOF;
1415                         break;
1416                 case MEM_ROT_VF_MEM:
1417                         vout->work_irq = IPU_IRQ_PRP_VF_ROT_OUT_EOF;
1418                         break;
1419                 case MEM_ROT_PP_MEM:
1420                         vout->work_irq = IPU_IRQ_PP_ROT_OUT_EOF;
1421                         break;
1422                 default:
1423                         dev_err(&vout->video_dev->dev,
1424                                 "not support channel, should not be here\n");
1425                 }
1426         } else
1427                 vout->work_irq = -1;
1428
1429         if (!vout->ic_bypass && (vout->work_irq > 0)) {
1430                 ipu_clear_irq(vout->work_irq);
1431                 ipu_request_irq(vout->work_irq,
1432                                 mxc_v4l2out_work_irq_handler,
1433                                 0, vout->video_dev->name, vout);
1434         }
1435
1436         vout->state = STATE_STREAM_PAUSED;
1437
1438         /* Enable display and IC channels */
1439         if (fbi) {
1440                 acquire_console_sem();
1441                 fb_blank(fbi, FB_BLANK_UNBLANK);
1442                 release_console_sem();
1443         } else {
1444                 ipu_enable_channel(vout->display_ch);
1445         }
1446         if (!vout->ic_bypass) {
1447 #ifndef CONFIG_MXC_IPU_V1
1448                 ipu_enable_channel(vout->post_proc_ch);
1449 #endif
1450                 if (LOAD_3FIELDS(vout)) {
1451                         ipu_enable_channel(MEM_VDI_PRP_VF_MEM_P);
1452                         ipu_enable_channel(MEM_VDI_PRP_VF_MEM_N);
1453                         ipu_select_multi_vdi_buffer(0);
1454                 } else if (INTERLACED_CONTENT(vout)) {
1455                         ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);
1456                 } else {
1457                         ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);
1458                         if (!vout->pp_split)
1459                                 ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1);
1460                 }
1461                 ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0);
1462                 ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1);
1463 #ifdef CONFIG_MXC_IPU_V1
1464                 ipu_enable_channel(vout->post_proc_ch);
1465 #endif
1466         } else {
1467                 ipu_update_channel_buffer(vout->display_ch,
1468                                 IPU_INPUT_BUFFER,
1469                                 0, vout->v4l2_bufs[vout->ipu_buf[0]].m.offset);
1470                 ipu_update_channel_buffer(vout->display_ch,
1471                                 IPU_INPUT_BUFFER,
1472                                 1, vout->v4l2_bufs[vout->ipu_buf[1]].m.offset);
1473                 if (vout->offset.u_offset || vout->offset.v_offset)
1474                         /* only update u/v offset */
1475                         ipu_update_channel_offset(vout->display_ch,
1476                                         IPU_INPUT_BUFFER,
1477                                         vout->v2f.fmt.pix.pixelformat,
1478                                         vout->v2f.fmt.pix.width,
1479                                         vout->v2f.fmt.pix.height,
1480                                         vout->bytesperline,
1481                                         vout->offset.u_offset,
1482                                         vout->offset.v_offset,
1483                                         0,
1484                                         0);
1485                 ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER, 0);
1486                 queue_work(vout->v4l_wq, &vout->timer_work);
1487         }
1488
1489         vout->start_jiffies = jiffies;
1490
1491         msleep(1);
1492
1493         dev_dbg(dev,
1494                 "streamon: start time = %lu jiffies\n", vout->start_jiffies);
1495
1496         return 0;
1497 }
1498
1499 /*!
1500  * Shut down the voutera
1501  *
1502  * @param vout      structure vout_data *
1503  *
1504  * @return status  0 Success
1505  */
1506 static int mxc_v4l2out_streamoff(vout_data * vout)
1507 {
1508         struct fb_info *fbi =
1509             registered_fb[vout->output_fb_num[vout->cur_disp_output]];
1510         int i, retval = 0;
1511         unsigned long lockflag = 0;
1512
1513         if (!vout)
1514                 return -EINVAL;
1515
1516         if (vout->state == STATE_STREAM_OFF) {
1517                 return 0;
1518         }
1519
1520         if (!vout->ic_bypass)
1521                 ipu_free_irq(vout->work_irq, vout);
1522
1523         if (vout->ic_bypass)
1524                 cancel_work_sync(&vout->timer_work);
1525
1526         spin_lock_irqsave(&g_lock, lockflag);
1527
1528         del_timer(&vout->output_timer);
1529
1530         if (vout->state == STATE_STREAM_ON) {
1531                 vout->state = STATE_STREAM_STOPPING;
1532         }
1533
1534         spin_unlock_irqrestore(&g_lock, lockflag);
1535
1536         if (vout->display_ch == MEM_FG_SYNC) {
1537                 struct mxcfb_pos fb_pos;
1538                 mm_segment_t old_fs;
1539
1540                 fb_pos.x = 0;
1541                 fb_pos.y = 0;
1542                 if (fbi->fbops->fb_ioctl) {
1543                         old_fs = get_fs();
1544                         set_fs(KERNEL_DS);
1545                         fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS,
1546                                         (unsigned long)&fb_pos);
1547                         set_fs(old_fs);
1548                 }
1549         }
1550
1551         if (vout->ic_bypass) {
1552                 fbi->var.activate |= FB_ACTIVATE_FORCE;
1553                 fb_set_var(fbi, &fbi->var);
1554
1555                 if (vout->display_ch == MEM_FG_SYNC) {
1556                         acquire_console_sem();
1557                         fb_blank(fbi, FB_BLANK_POWERDOWN);
1558                         release_console_sem();
1559                 }
1560
1561                 vout->display_bufs[0] = 0;
1562                 vout->display_bufs[1] = 0;
1563         } else if (vout->post_proc_ch == MEM_PP_MEM ||
1564             vout->post_proc_ch == MEM_PRP_VF_MEM) {
1565                 /* SDC with Rotation */
1566                 if (!ipu_can_rotate_in_place(vout->rotate)) {
1567                         ipu_unlink_channels(MEM_PP_MEM, MEM_ROT_PP_MEM);
1568                         ipu_disable_channel(MEM_ROT_PP_MEM, true);
1569
1570                         if (vout->rot_pp_bufs[0]) {
1571                                 mxc_free_buffers(vout->rot_pp_bufs,
1572                                                  vout->rot_pp_bufs_vaddr, 2,
1573                                                  vout->display_buf_size);
1574                         }
1575                 }
1576                 ipu_disable_channel(MEM_PP_MEM, true);
1577
1578                 fbi->var.activate |= FB_ACTIVATE_FORCE;
1579                 fb_set_var(fbi, &fbi->var);
1580
1581                 if (vout->display_ch == MEM_FG_SYNC) {
1582                         acquire_console_sem();
1583                         fb_blank(fbi, FB_BLANK_POWERDOWN);
1584                         release_console_sem();
1585                 }
1586
1587                 vout->display_bufs[0] = 0;
1588                 vout->display_bufs[1] = 0;
1589
1590                 ipu_uninit_channel(MEM_PP_MEM);
1591                 if (!ipu_can_rotate_in_place(vout->rotate))
1592                         ipu_uninit_channel(MEM_ROT_PP_MEM);
1593         } else if (INTERLACED_CONTENT(vout) &&
1594                 (vout->post_proc_ch == MEM_VDI_PRP_VF_MEM)) {
1595                 if (!ipu_can_rotate_in_place(vout->rotate)) {
1596                         ipu_unlink_channels(MEM_VDI_PRP_VF_MEM,
1597                                             MEM_ROT_VF_MEM);
1598                         ipu_disable_channel(MEM_ROT_VF_MEM, true);
1599
1600                         if (vout->rot_pp_bufs[0]) {
1601                                 mxc_free_buffers(vout->rot_pp_bufs,
1602                                                  vout->rot_pp_bufs_vaddr, 2,
1603                                                  vout->display_buf_size);
1604                         }
1605                 }
1606
1607                 ipu_disable_channel(MEM_VDI_PRP_VF_MEM, true);
1608                 if (LOAD_3FIELDS(vout)) {
1609                         ipu_disable_channel(MEM_VDI_PRP_VF_MEM_P, true);
1610                         ipu_disable_channel(MEM_VDI_PRP_VF_MEM_N, true);
1611                 }
1612
1613                 fbi->var.activate |= FB_ACTIVATE_FORCE;
1614                 fb_set_var(fbi, &fbi->var);
1615
1616                 if (vout->display_ch == MEM_FG_SYNC) {
1617                         acquire_console_sem();
1618                         fb_blank(fbi, FB_BLANK_POWERDOWN);
1619                         release_console_sem();
1620                 }
1621
1622                 vout->display_bufs[0] = 0;
1623                 vout->display_bufs[1] = 0;
1624
1625                 ipu_uninit_channel(MEM_VDI_PRP_VF_MEM);
1626                 if (LOAD_3FIELDS(vout)) {
1627                         ipu_uninit_channel(MEM_VDI_PRP_VF_MEM_P);
1628                         ipu_uninit_channel(MEM_VDI_PRP_VF_MEM_N);
1629                 }
1630                 if (!ipu_can_rotate_in_place(vout->rotate))
1631                         ipu_uninit_channel(MEM_ROT_VF_MEM);
1632         }
1633
1634         vout->ready_q.head = vout->ready_q.tail = 0;
1635         vout->done_q.head = vout->done_q.tail = 0;
1636         for (i = 0; i < vout->buffer_cnt; i++) {
1637                 vout->v4l2_bufs[i].flags = 0;
1638                 vout->v4l2_bufs[i].timestamp.tv_sec = 0;
1639                 vout->v4l2_bufs[i].timestamp.tv_usec = 0;
1640         }
1641
1642         vout->post_proc_ch = CHAN_NONE;
1643         vout->state = STATE_STREAM_OFF;
1644
1645         return retval;
1646 }
1647
1648 /*
1649  * Valid whether the palette is supported
1650  *
1651  * @param palette  V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
1652  *
1653  * @return 1 if supported, 0 if failed
1654  */
1655 static inline int valid_mode(u32 palette)
1656 {
1657         return ((palette == V4L2_PIX_FMT_RGB565) ||
1658                 (palette == V4L2_PIX_FMT_BGR24) ||
1659                 (palette == V4L2_PIX_FMT_RGB24) ||
1660                 (palette == V4L2_PIX_FMT_BGR32) ||
1661                 (palette == V4L2_PIX_FMT_RGB32) ||
1662                 (palette == V4L2_PIX_FMT_NV12) ||
1663                 (palette == V4L2_PIX_FMT_UYVY) ||
1664                 (palette == V4L2_PIX_FMT_YUYV) ||
1665                 (palette == V4L2_PIX_FMT_YUV422P) ||
1666                 (palette == V4L2_PIX_FMT_YUV420));
1667 }
1668
1669 /*
1670  * V4L2 - Handles VIDIOC_G_FMT Ioctl
1671  *
1672  * @param vout         structure vout_data *
1673  *
1674  * @param v4l2_format structure v4l2_format *
1675  *
1676  * @return  status    0 success, EINVAL failed
1677  */
1678 static int mxc_v4l2out_g_fmt(vout_data * vout, struct v4l2_format *f)
1679 {
1680         if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1681                 return -EINVAL;
1682         }
1683         *f = vout->v2f;
1684         return 0;
1685 }
1686
1687 /*
1688  * V4L2 - Handles VIDIOC_S_FMT Ioctl
1689  *
1690  * @param vout         structure vout_data *
1691  *
1692  * @param v4l2_format structure v4l2_format *
1693  *
1694  * @return  status    0 success, EINVAL failed
1695  */
1696 static int mxc_v4l2out_s_fmt(vout_data * vout, struct v4l2_format *f)
1697 {
1698         int retval = 0;
1699         u32 size = 0;
1700         u32 bytesperline;
1701
1702         if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1703                 retval = -EINVAL;
1704                 goto err0;
1705         }
1706         if (!valid_mode(f->fmt.pix.pixelformat)) {
1707                 dev_err(&vout->video_dev->dev, "pixel format not supported\n");
1708                 retval = -EINVAL;
1709                 goto err0;
1710         }
1711
1712         bytesperline = (f->fmt.pix.width * fmt_to_bpp(f->fmt.pix.pixelformat)) /
1713             8;
1714         if (f->fmt.pix.bytesperline < bytesperline) {
1715                 f->fmt.pix.bytesperline = bytesperline;
1716         } else {
1717                 bytesperline = f->fmt.pix.bytesperline;
1718         }
1719         vout->bytesperline = bytesperline;
1720
1721         /* Based on http://v4l2spec.bytesex.org/spec/x6386.htm#V4L2-FIELD */
1722         vout->field_fmt = f->fmt.pix.field;
1723         switch (vout->field_fmt) {
1724                 /* Images are in progressive format, not interlaced */
1725         case V4L2_FIELD_NONE:
1726                 break;
1727                 /* The two fields of a frame are passed in separate buffers,
1728                    in temporal order, i. e. the older one first. */
1729         case V4L2_FIELD_ALTERNATE:
1730                 dev_err(&vout->video_dev->dev,
1731                         "V4L2_FIELD_ALTERNATE field format not supported yet!\n");
1732                 break;
1733         case V4L2_FIELD_INTERLACED_TB:
1734                 if (cpu_is_mx51() || cpu_is_mx53())
1735                         break;
1736                 dev_err(&vout->video_dev->dev,
1737                         "De-interlacing not supported in this device!\n");
1738                 vout->field_fmt = V4L2_FIELD_NONE;
1739         case V4L2_FIELD_INTERLACED_BT:
1740                 dev_err(&vout->video_dev->dev,
1741                         "V4L2_FIELD_INTERLACED_BT field format not supported yet!\n");
1742         default:
1743                 vout->field_fmt = V4L2_FIELD_NONE;
1744                 break;
1745         }
1746
1747         switch (f->fmt.pix.pixelformat) {
1748         case V4L2_PIX_FMT_YUV422P:
1749                 /* byteperline for YUV planar formats is for
1750                    Y plane only */
1751                 size = bytesperline * f->fmt.pix.height * 2;
1752                 break;
1753         case V4L2_PIX_FMT_YUV420:
1754         case V4L2_PIX_FMT_NV12:
1755                 size = (bytesperline * f->fmt.pix.height * 3) / 2;
1756                 break;
1757         default:
1758                 size = bytesperline * f->fmt.pix.height;
1759                 break;
1760         }
1761
1762         /* Return the actual size of the image to the app */
1763         if (f->fmt.pix.sizeimage < size) {
1764                 f->fmt.pix.sizeimage = size;
1765         } else {
1766                 size = f->fmt.pix.sizeimage;
1767         }
1768
1769         vout->v2f.fmt.pix = f->fmt.pix;
1770         if (vout->v2f.fmt.pix.priv != 0) {
1771                 if (copy_from_user(&vout->offset,
1772                                    (void *)vout->v2f.fmt.pix.priv,
1773                                    sizeof(vout->offset))) {
1774                         retval = -EFAULT;
1775                         goto err0;
1776                 }
1777         } else {
1778                 vout->offset.u_offset = 0;
1779                 vout->offset.v_offset = 0;
1780         }
1781
1782         retval = 0;
1783       err0:
1784         return retval;
1785 }
1786
1787 /*
1788  * V4L2 - Handles VIDIOC_G_CTRL Ioctl
1789  *
1790  * @param vout         structure vout_data *
1791  *
1792  * @param c           structure v4l2_control *
1793  *
1794  * @return  status    0 success, EINVAL failed
1795  */
1796 static int mxc_get_v42lout_control(vout_data * vout, struct v4l2_control *c)
1797 {
1798         switch (c->id) {
1799         case V4L2_CID_HFLIP:
1800                 return (vout->rotate & IPU_ROTATE_HORIZ_FLIP) ? 1 : 0;
1801         case V4L2_CID_VFLIP:
1802                 return (vout->rotate & IPU_ROTATE_VERT_FLIP) ? 1 : 0;
1803         case (V4L2_CID_PRIVATE_BASE + 1):
1804                 return vout->rotate;
1805         default:
1806                 return -EINVAL;
1807         }
1808 }
1809
1810 /*
1811  * V4L2 - Handles VIDIOC_S_CTRL Ioctl
1812  *
1813  * @param vout         structure vout_data *
1814  *
1815  * @param c           structure v4l2_control *
1816  *
1817  * @return  status    0 success, EINVAL failed
1818  */
1819 static int mxc_set_v42lout_control(vout_data * vout, struct v4l2_control *c)
1820 {
1821         switch (c->id) {
1822         case V4L2_CID_HFLIP:
1823                 vout->rotate |= c->value ? IPU_ROTATE_HORIZ_FLIP :
1824                     IPU_ROTATE_NONE;
1825                 break;
1826         case V4L2_CID_VFLIP:
1827                 vout->rotate |= c->value ? IPU_ROTATE_VERT_FLIP :
1828                     IPU_ROTATE_NONE;
1829                 break;
1830         case V4L2_CID_MXC_ROT:
1831                 vout->rotate = c->value;
1832                 break;
1833         case V4L2_CID_MXC_MOTION:
1834                 vout->motion_sel = c->value;
1835                 break;
1836         default:
1837                 return -EINVAL;
1838         }
1839         return 0;
1840 }
1841
1842 /*!
1843  * V4L2 interface - open function
1844  *
1845  * @param file         structure file *
1846  *
1847  * @return  status    0 success, ENODEV invalid device instance,
1848  *                    ENODEV timeout, ERESTARTSYS interrupted by user
1849  */
1850 static int mxc_v4l2out_open(struct file *file)
1851 {
1852         struct video_device *dev = video_devdata(file);
1853         vout_data *vout = video_get_drvdata(dev);
1854         int err;
1855
1856         if (!vout) {
1857                 return -ENODEV;
1858         }
1859
1860         down(&vout->busy_lock);
1861
1862         err = -EINTR;
1863         if (signal_pending(current))
1864                 goto oops;
1865
1866
1867         if (vout->open_count++ == 0) {
1868                 init_waitqueue_head(&vout->v4l_bufq);
1869
1870                 init_timer(&vout->output_timer);
1871                 vout->output_timer.function = mxc_v4l2out_timer_handler;
1872                 vout->output_timer.data = (unsigned long)vout;
1873
1874                 vout->state = STATE_STREAM_OFF;
1875                 vout->rotate = IPU_ROTATE_NONE;
1876
1877                 vout->v4l_wq = create_singlethread_workqueue("v4l2q");
1878                 if (!vout->v4l_wq) {
1879                         dev_dbg(&dev->dev,
1880                                         "Could not create work queue\n");
1881                         err = -ENOMEM;
1882                         goto oops;
1883                 }
1884
1885                 INIT_WORK(&vout->timer_work, timer_work_func);
1886         }
1887
1888         file->private_data = dev;
1889
1890         up(&vout->busy_lock);
1891
1892         return 0;
1893
1894       oops:
1895         up(&vout->busy_lock);
1896         return err;
1897 }
1898
1899 /*!
1900  * V4L2 interface - close function
1901  *
1902  * @param file     struct file *
1903  *
1904  * @return         0 success
1905  */
1906 static int mxc_v4l2out_close(struct file *file)
1907 {
1908         struct video_device *dev = video_devdata(file);
1909         vout_data *vout = video_get_drvdata(dev);
1910
1911         if (--vout->open_count == 0) {
1912                 if (vout->state != STATE_STREAM_OFF)
1913                         mxc_v4l2out_streamoff(vout);
1914
1915                 file->private_data = NULL;
1916
1917                 mxc_free_buffers(vout->queue_buf_paddr, vout->queue_buf_vaddr,
1918                                  vout->buffer_cnt, vout->queue_buf_size);
1919                 vout->buffer_cnt = 0;
1920                 mxc_free_buffers(vout->rot_pp_bufs, vout->rot_pp_bufs_vaddr, 2,
1921                                  vout->display_buf_size);
1922
1923                 /* capture off */
1924                 wake_up_interruptible(&vout->v4l_bufq);
1925
1926                 flush_workqueue(vout->v4l_wq);
1927                 destroy_workqueue(vout->v4l_wq);
1928         }
1929
1930         return 0;
1931 }
1932
1933 /*!
1934  * V4L2 interface - ioctl function
1935  *
1936  * @param file       struct file *
1937  *
1938  * @param ioctlnr    unsigned int
1939  *
1940  * @param arg        void *
1941  *
1942  * @return           0 success, ENODEV for invalid device instance,
1943  *                   -1 for other errors.
1944  */
1945 static long
1946 mxc_v4l2out_do_ioctl(struct file *file,
1947                      unsigned int ioctlnr, void *arg)
1948 {
1949         struct video_device *vdev = file->private_data;
1950         vout_data *vout = video_get_drvdata(vdev);
1951         int retval = 0;
1952         int i = 0;
1953
1954         if (!vout)
1955                 return -EBADF;
1956
1957         /* make this _really_ smp-safe */
1958         if (down_interruptible(&vout->busy_lock))
1959                 return -EBUSY;
1960
1961         switch (ioctlnr) {
1962         case VIDIOC_QUERYCAP:
1963                 {
1964                         struct v4l2_capability *cap = arg;
1965                         strcpy(cap->driver, "mxc_v4l2_output");
1966                         cap->version = 0;
1967                         cap->capabilities =
1968                             V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
1969                         cap->card[0] = '\0';
1970                         cap->bus_info[0] = '\0';
1971                         retval = 0;
1972                         break;
1973                 }
1974         case VIDIOC_G_FMT:
1975                 {
1976                         struct v4l2_format *gf = arg;
1977                         retval = mxc_v4l2out_g_fmt(vout, gf);
1978                         break;
1979                 }
1980         case VIDIOC_S_FMT:
1981                 {
1982                         struct v4l2_format *sf = arg;
1983                         if (vout->state != STATE_STREAM_OFF) {
1984                                 retval = -EBUSY;
1985                                 break;
1986                         }
1987                         retval = mxc_v4l2out_s_fmt(vout, sf);
1988                         break;
1989                 }
1990         case VIDIOC_REQBUFS:
1991                 {
1992                         struct v4l2_requestbuffers *req = arg;
1993                         if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
1994                             (req->memory != V4L2_MEMORY_MMAP)) {
1995                                 dev_dbg(&vdev->dev,
1996                                         "VIDIOC_REQBUFS: incorrect buffer type\n");
1997                                 retval = -EINVAL;
1998                                 break;
1999                         }
2000
2001                         if (req->count == 0)
2002                                 mxc_v4l2out_streamoff(vout);
2003
2004                         if (vout->state == STATE_STREAM_OFF) {
2005                                 if (vout->queue_buf_paddr[0] != 0) {
2006                                         mxc_free_buffers(vout->queue_buf_paddr,
2007                                                          vout->queue_buf_vaddr,
2008                                                          vout->buffer_cnt,
2009                                                          vout->queue_buf_size);
2010                                         dev_dbg(&vdev->dev,
2011                                                 "VIDIOC_REQBUFS: freed buffers\n");
2012                                 }
2013                                 vout->buffer_cnt = 0;
2014                         } else {
2015                                 dev_dbg(&vdev->dev,
2016                                         "VIDIOC_REQBUFS: Buffer is in use\n");
2017                                 retval = -EBUSY;
2018                                 break;
2019                         }
2020
2021                         if (req->count == 0)
2022                                 break;
2023
2024                         if (req->count < MIN_FRAME_NUM) {
2025                                 req->count = MIN_FRAME_NUM;
2026                         } else if (req->count > MAX_FRAME_NUM) {
2027                                 req->count = MAX_FRAME_NUM;
2028                         }
2029                         vout->buffer_cnt = req->count;
2030                         vout->queue_buf_size =
2031                             PAGE_ALIGN(vout->v2f.fmt.pix.sizeimage);
2032
2033                         retval = mxc_allocate_buffers(vout->queue_buf_paddr,
2034                                                       vout->queue_buf_vaddr,
2035                                                       vout->buffer_cnt,
2036                                                       vout->queue_buf_size);
2037                         if (retval < 0)
2038                                 break;
2039
2040                         /* Init buffer queues */
2041                         vout->done_q.head = 0;
2042                         vout->done_q.tail = 0;
2043                         vout->ready_q.head = 0;
2044                         vout->ready_q.tail = 0;
2045
2046                         for (i = 0; i < vout->buffer_cnt; i++) {
2047                                 memset(&(vout->v4l2_bufs[i]), 0,
2048                                        sizeof(vout->v4l2_bufs[i]));
2049                                 vout->v4l2_bufs[i].flags = 0;
2050                                 vout->v4l2_bufs[i].memory = V4L2_MEMORY_MMAP;
2051                                 vout->v4l2_bufs[i].index = i;
2052                                 vout->v4l2_bufs[i].type =
2053                                     V4L2_BUF_TYPE_VIDEO_OUTPUT;
2054                                 vout->v4l2_bufs[i].length =
2055                                     PAGE_ALIGN(vout->v2f.fmt.pix.sizeimage);
2056                                 vout->v4l2_bufs[i].m.offset =
2057                                     (unsigned long)vout->queue_buf_paddr[i];
2058                                 vout->v4l2_bufs[i].timestamp.tv_sec = 0;
2059                                 vout->v4l2_bufs[i].timestamp.tv_usec = 0;
2060                         }
2061                         break;
2062                 }
2063         case VIDIOC_QUERYBUF:
2064                 {
2065                         struct v4l2_buffer *buf = arg;
2066                         u32 type = buf->type;
2067                         int index = buf->index;
2068
2069                         if ((type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
2070                             (index >= vout->buffer_cnt)) {
2071                                 dev_dbg(&vdev->dev,
2072                                         "VIDIOC_QUERYBUFS: incorrect buffer type\n");
2073                                 retval = -EINVAL;
2074                                 break;
2075                         }
2076                         down(&vout->param_lock);
2077                         memcpy(buf, &(vout->v4l2_bufs[index]), sizeof(*buf));
2078                         up(&vout->param_lock);
2079                         break;
2080                 }
2081         case VIDIOC_QBUF:
2082                 {
2083                         struct v4l2_buffer *buf = arg;
2084                         int index = buf->index;
2085                         unsigned long lock_flags;
2086                         int param[5][3];
2087
2088                         if ((buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
2089                             (index >= vout->buffer_cnt)) {
2090                                 retval = -EINVAL;
2091                                 break;
2092                         }
2093
2094                         dev_dbg(&vdev->dev, "VIDIOC_QBUF: %d field = %d\n", buf->index, buf->field);
2095
2096                         /* mmapped buffers are L1 WB cached,
2097                          * so we need to clean them */
2098                         if (buf->memory & V4L2_MEMORY_MMAP) {
2099                                 flush_cache_all();
2100                         }
2101
2102                         spin_lock_irqsave(&g_lock, lock_flags);
2103
2104                         memcpy(&(vout->v4l2_bufs[index]), buf, sizeof(*buf));
2105                         vout->v4l2_bufs[index].flags |= V4L2_BUF_FLAG_QUEUED;
2106
2107                         g_buf_q_cnt++;
2108                         if (vout->v4l2_bufs[index].reserved)
2109                                 if (!copy_from_user(&param[0][0],
2110                                                     (void *)vout->
2111                                                     v4l2_bufs[index]
2112                                                     .reserved, sizeof(param)))
2113                                         ipu_set_csc_coefficients(vout->
2114                                                                  display_ch,
2115                                                                  param);
2116                         queue_buf(&vout->ready_q, index);
2117                         if (vout->state == STATE_STREAM_PAUSED) {
2118                                 index = peek_next_buf(&vout->ready_q);
2119                                 setup_next_buf_timer(vout, index);
2120                                 vout->state = STATE_STREAM_ON;
2121                         }
2122
2123                         spin_unlock_irqrestore(&g_lock, lock_flags);
2124                         break;
2125                 }
2126         case VIDIOC_DQBUF:
2127                 {
2128                         struct v4l2_buffer *buf = arg;
2129                         int idx;
2130
2131                         if ((queue_size(&vout->done_q) == 0) &&
2132                             (file->f_flags & O_NONBLOCK)) {
2133                                 retval = -EAGAIN;
2134                                 break;
2135                         }
2136
2137                         if (!wait_event_interruptible_timeout(vout->v4l_bufq,
2138                                                               queue_size(&vout->
2139                                                                          done_q)
2140                                                               != 0, 10 * HZ)) {
2141                                 dev_dbg(&vdev->dev, "VIDIOC_DQBUF: timeout\n");
2142                                 retval = -ETIME;
2143                                 break;
2144                         } else if (signal_pending(current)) {
2145                                 dev_dbg(&vdev->dev,
2146                                         "VIDIOC_DQBUF: interrupt received\n");
2147                                 retval = -ERESTARTSYS;
2148                                 break;
2149                         }
2150                         idx = dequeue_buf(&vout->done_q);
2151                         if (idx == -1) {        /* No frame free */
2152                                 dev_dbg(&vdev->dev,
2153                                         "VIDIOC_DQBUF: no free buffers, returning\n");
2154                                 retval = -EAGAIN;
2155                                 break;
2156                         }
2157                         if ((vout->v4l2_bufs[idx].flags & V4L2_BUF_FLAG_DONE) ==
2158                             0)
2159                                 dev_dbg(&vdev->dev,
2160                                         "VIDIOC_DQBUF: buffer in done q, but not "
2161                                         "flagged as done\n");
2162
2163                         vout->v4l2_bufs[idx].flags = 0;
2164                         memcpy(buf, &(vout->v4l2_bufs[idx]), sizeof(*buf));
2165                         dev_dbg(&vdev->dev, "VIDIOC_DQBUF: %d\n", buf->index);
2166                         break;
2167                 }
2168         case VIDIOC_STREAMON:
2169                 {
2170                         retval = mxc_v4l2out_streamon(vout);
2171                         break;
2172                 }
2173         case VIDIOC_STREAMOFF:
2174                 {
2175                         retval = mxc_v4l2out_streamoff(vout);
2176                         break;
2177                 }
2178         case VIDIOC_G_CTRL:
2179                 {
2180                         retval = mxc_get_v42lout_control(vout, arg);
2181                         break;
2182                 }
2183         case VIDIOC_S_CTRL:
2184                 {
2185                         retval = mxc_set_v42lout_control(vout, arg);
2186                         break;
2187                 }
2188         case VIDIOC_CROPCAP:
2189                 {
2190                         struct v4l2_cropcap *cap = arg;
2191
2192                         if (cap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2193                                 retval = -EINVAL;
2194                                 break;
2195                         }
2196
2197                         cap->bounds = vout->crop_bounds[vout->cur_disp_output];
2198                         cap->defrect = vout->crop_bounds[vout->cur_disp_output];
2199                         retval = 0;
2200                         break;
2201                 }
2202         case VIDIOC_G_CROP:
2203                 {
2204                         struct v4l2_crop *crop = arg;
2205
2206                         if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2207                                 retval = -EINVAL;
2208                                 break;
2209                         }
2210                         crop->c = vout->crop_current;
2211                         break;
2212                 }
2213         case VIDIOC_S_CROP:
2214                 {
2215                         struct v4l2_crop *crop = arg;
2216                         struct v4l2_rect *b =
2217                             &(vout->crop_bounds[vout->cur_disp_output]);
2218
2219                         if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2220                                 retval = -EINVAL;
2221                                 break;
2222                         }
2223                         if (crop->c.height < 0) {
2224                                 retval = -EINVAL;
2225                                 break;
2226                         }
2227                         if (crop->c.width < 0) {
2228                                 retval = -EINVAL;
2229                                 break;
2230                         }
2231
2232                         /* only full screen supported for SDC BG and SDC DC */
2233                         if (vout->cur_disp_output == 4) {
2234                                 crop->c = vout->crop_current;
2235                                 break;
2236                         }
2237
2238                         if (crop->c.top < b->top)
2239                                 crop->c.top = b->top;
2240                         if (crop->c.top >= b->top + b->height)
2241                                 crop->c.top = b->top + b->height - 1;
2242                         if (crop->c.height > b->top - crop->c.top + b->height)
2243                                 crop->c.height =
2244                                     b->top - crop->c.top + b->height;
2245
2246                         if (crop->c.left < b->left)
2247                                 crop->c.left = b->left;
2248                         if (crop->c.left >= b->left + b->width)
2249                                 crop->c.left = b->left + b->width - 1;
2250                         if (crop->c.width > b->left - crop->c.left + b->width)
2251                                 crop->c.width =
2252                                     b->left - crop->c.left + b->width;
2253
2254                         /* stride line limitation */
2255                         crop->c.height -= crop->c.height % 8;
2256                         crop->c.width -= crop->c.width % 8;
2257
2258                         vout->crop_current = crop->c;
2259                         break;
2260                 }
2261         case VIDIOC_ENUMOUTPUT:
2262                 {
2263                         struct v4l2_output *output = arg;
2264
2265                         if ((output->index >= 5) ||
2266                             (vout->output_enabled[output->index] == false)) {
2267                                 retval = -EINVAL;
2268                                 break;
2269                         }
2270
2271                         if (output->index >= 3)
2272                                 *output = mxc_outputs[MXC_V4L2_OUT_2_SDC];
2273                         break;
2274                 }
2275         case VIDIOC_G_OUTPUT:
2276                 {
2277                         int *p_output_num = arg;
2278
2279                         *p_output_num = vout->cur_disp_output;
2280                         break;
2281                 }
2282         case VIDIOC_S_OUTPUT:
2283                 {
2284                         int *p_output_num = arg;
2285                         int fbnum;
2286                         struct v4l2_rect *b;
2287
2288                         if ((*p_output_num >= MXC_V4L2_OUT_NUM_OUTPUTS) ||
2289                             (vout->output_enabled[*p_output_num] == false)) {
2290                                 retval = -EINVAL;
2291                                 break;
2292                         }
2293
2294                         if (vout->state != STATE_STREAM_OFF) {
2295                                 retval = -EBUSY;
2296                                 break;
2297                         }
2298
2299                         vout->cur_disp_output = *p_output_num;
2300
2301                         /* Update bounds in case they have changed */
2302                         b = &vout->crop_bounds[vout->cur_disp_output];
2303
2304                         fbnum = vout->output_fb_num[vout->cur_disp_output];
2305
2306                         /*
2307                          * For FG overlay, it uses BG window parameter as
2308                          * limitation reference; and BG must be enabled to
2309                          * support FG.
2310                          */
2311                         if (vout->cur_disp_output == 3) {
2312                                 unsigned int i, ipu_ch = CHAN_NONE;
2313                                 struct fb_info *fbi;
2314                                 mm_segment_t old_fs;
2315
2316                                 for (i = 0; i < num_registered_fb; i++) {
2317                                         fbi = registered_fb[i];
2318                                         if (fbi->fbops->fb_ioctl) {
2319                                                 old_fs = get_fs();
2320                                                 set_fs(KERNEL_DS);
2321                                                 fbi->fbops->fb_ioctl(fbi,
2322                                                         MXCFB_GET_FB_IPU_CHAN,
2323                                                         (unsigned long)&ipu_ch);
2324                                                 set_fs(old_fs);
2325                                         }
2326                                         if (ipu_ch == CHAN_NONE) {
2327                                                 dev_err(&vdev->dev,
2328                                                 "Can't get disp ipu channel\n");
2329                                                 retval = -EINVAL;
2330                                                 break;
2331                                         }
2332
2333                                         if (ipu_ch == MEM_BG_SYNC) {
2334                                                 fbnum = i;
2335                                                 break;
2336                                         }
2337                                 }
2338                         }
2339
2340                         b->width = registered_fb[fbnum]->var.xres;
2341                         b->height = registered_fb[fbnum]->var.yres;
2342
2343                         vout->crop_current = *b;
2344                         break;
2345                 }
2346         case VIDIOC_ENUM_FMT:
2347         case VIDIOC_TRY_FMT:
2348         case VIDIOC_QUERYCTRL:
2349         case VIDIOC_G_PARM:
2350         case VIDIOC_ENUMSTD:
2351         case VIDIOC_G_STD:
2352         case VIDIOC_S_STD:
2353         case VIDIOC_G_TUNER:
2354         case VIDIOC_S_TUNER:
2355         case VIDIOC_G_FREQUENCY:
2356         case VIDIOC_S_FREQUENCY:
2357         default:
2358                 retval = -EINVAL;
2359                 break;
2360         }
2361
2362         up(&vout->busy_lock);
2363         return retval;
2364 }
2365
2366 /*
2367  * V4L2 interface - ioctl function
2368  *
2369  * @return  None
2370  */
2371 static long
2372 mxc_v4l2out_ioctl(struct file *file,
2373                   unsigned int cmd, unsigned long arg)
2374 {
2375         return video_usercopy(file, cmd, arg, mxc_v4l2out_do_ioctl);
2376 }
2377
2378 /*!
2379  * V4L2 interface - mmap function
2380  *
2381  * @param file          structure file *
2382  *
2383  * @param vma           structure vm_area_struct *
2384  *
2385  * @return status       0 Success, EINTR busy lock error,
2386  *                      ENOBUFS remap_page error
2387  */
2388 static int mxc_v4l2out_mmap(struct file *file, struct vm_area_struct *vma)
2389 {
2390         struct video_device *vdev = video_devdata(file);
2391         unsigned long size = vma->vm_end - vma->vm_start;
2392         int res = 0;
2393         int i;
2394         vout_data *vout = video_get_drvdata(vdev);
2395
2396         dev_dbg(&vdev->dev, "pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
2397                 vma->vm_pgoff, vma->vm_start, vma->vm_end);
2398
2399         /* make this _really_ smp-safe */
2400         if (down_interruptible(&vout->busy_lock))
2401                 return -EINTR;
2402
2403         for (i = 0; i < vout->buffer_cnt; i++) {
2404                 if ((vout->v4l2_bufs[i].m.offset ==
2405                      (vma->vm_pgoff << PAGE_SHIFT)) &&
2406                     (vout->v4l2_bufs[i].length >= size)) {
2407                         vout->v4l2_bufs[i].flags |= V4L2_BUF_FLAG_MAPPED;
2408                         break;
2409                 }
2410         }
2411         if (i == vout->buffer_cnt) {
2412                 res = -ENOBUFS;
2413                 goto mxc_mmap_exit;
2414         }
2415
2416         /* make buffers inner write-back, outer write-thru cacheable */
2417         /* vma->vm_page_prot = pgprot_outer_wrthru(vma->vm_page_prot);*/
2418
2419         if (remap_pfn_range(vma, vma->vm_start,
2420                             vma->vm_pgoff, size, vma->vm_page_prot)) {
2421                 dev_dbg(&vdev->dev, "mmap remap_pfn_range failed\n");
2422                 res = -ENOBUFS;
2423                 goto mxc_mmap_exit;
2424         }
2425
2426         vma->vm_flags &= ~VM_IO;        /* using shared anonymous pages */
2427
2428       mxc_mmap_exit:
2429         up(&vout->busy_lock);
2430         return res;
2431 }
2432
2433 /*!
2434  * V4L2 interface - poll function
2435  *
2436  * @param file       structure file *
2437  *
2438  * @param wait       structure poll_table_struct *
2439  *
2440  * @return  status   POLLIN | POLLRDNORM
2441  */
2442 static unsigned int mxc_v4l2out_poll(struct file *file, struct poll_table_struct * wait)
2443 {
2444         struct video_device *dev = video_devdata(file);
2445         vout_data *vout = video_get_drvdata(dev);
2446
2447         wait_queue_head_t *queue = NULL;
2448         int res = POLLIN | POLLRDNORM;
2449
2450         if (down_interruptible(&vout->busy_lock))
2451                 return -EINTR;
2452
2453         queue = &vout->v4l_bufq;
2454         poll_wait(file, queue, wait);
2455
2456         up(&vout->busy_lock);
2457         return res;
2458 }
2459
2460 static struct
2461 v4l2_file_operations mxc_v4l2out_fops = {
2462         .owner = THIS_MODULE,
2463         .open = mxc_v4l2out_open,
2464         .release = mxc_v4l2out_close,
2465         .ioctl = mxc_v4l2out_ioctl,
2466         .mmap = mxc_v4l2out_mmap,
2467         .poll = mxc_v4l2out_poll,
2468 };
2469
2470 static struct video_device mxc_v4l2out_template = {
2471         .name = "MXC Video Output",
2472         .vfl_type = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING,
2473         .fops = &mxc_v4l2out_fops,
2474         .release = video_device_release,
2475 };
2476
2477 /*!
2478  * Probe routine for the framebuffer driver. It is called during the
2479  * driver binding process.      The following functions are performed in
2480  * this routine: Framebuffer initialization, Memory allocation and
2481  * mapping, Framebuffer registration, IPU initialization.
2482  *
2483  * @return      Appropriate error code to the kernel common code
2484  */
2485 static int mxc_v4l2out_probe(struct platform_device *pdev)
2486 {
2487         int i;
2488         vout_data *vout;
2489
2490         /*
2491          * Allocate sufficient memory for the fb structure
2492          */
2493         g_vout = vout = kmalloc(sizeof(vout_data), GFP_KERNEL);
2494
2495         if (!vout)
2496                 return 0;
2497
2498         memset(vout, 0, sizeof(vout_data));
2499
2500         vout->video_dev = video_device_alloc();
2501         if (vout->video_dev == NULL)
2502                 return -1;
2503         vout->video_dev->minor = -1;
2504
2505         *(vout->video_dev) = mxc_v4l2out_template;
2506
2507         /* register v4l device */
2508         if (video_register_device(vout->video_dev,
2509                                   VFL_TYPE_GRABBER, video_nr) == -1) {
2510                 dev_dbg(&pdev->dev, "video_register_device failed\n");
2511                 return 0;
2512         }
2513         dev_info(&pdev->dev, "Registered device video%d\n",
2514                  vout->video_dev->minor & 0x1f);
2515         /*vout->video_dev->dev = &pdev->dev;*/
2516
2517         video_set_drvdata(vout->video_dev, vout);
2518
2519         init_MUTEX(&vout->param_lock);
2520         init_MUTEX(&vout->busy_lock);
2521
2522         /* setup outputs and cropping */
2523         vout->cur_disp_output = -1;
2524         for (i = 0; i < num_registered_fb; i++) {
2525                 char *idstr = registered_fb[i]->fix.id;
2526                 if (strncmp(idstr, "DISP", 4) == 0) {
2527                         int disp_num = idstr[4] - '0';
2528                         if (disp_num == 3) {
2529                                 if (strcmp(idstr, "DISP3 BG - DI1") == 0)
2530                                         disp_num = 5;
2531                                 else if (strncmp(idstr, "DISP3 BG", 8) == 0)
2532                                         disp_num = 4;
2533                         }
2534                         vout->crop_bounds[disp_num].left = 0;
2535                         vout->crop_bounds[disp_num].top = 0;
2536                         vout->crop_bounds[disp_num].width =
2537                             registered_fb[i]->var.xres;
2538                         vout->crop_bounds[disp_num].height =
2539                             registered_fb[i]->var.yres;
2540                         vout->output_enabled[disp_num] = true;
2541                         vout->output_fb_num[disp_num] = i;
2542                         if (vout->cur_disp_output == -1) {
2543                                 vout->cur_disp_output = disp_num;
2544                         }
2545                 }
2546
2547         }
2548         vout->crop_current = vout->crop_bounds[vout->cur_disp_output];
2549
2550         platform_set_drvdata(pdev, vout);
2551
2552         return 0;
2553 }
2554
2555 static int mxc_v4l2out_remove(struct platform_device *pdev)
2556 {
2557         vout_data *vout = platform_get_drvdata(pdev);
2558
2559         if (vout->video_dev) {
2560                 if (-1 != vout->video_dev->minor)
2561                         video_unregister_device(vout->video_dev);
2562                 else
2563                         video_device_release(vout->video_dev);
2564                 vout->video_dev = NULL;
2565         }
2566
2567         platform_set_drvdata(pdev, NULL);
2568
2569         kfree(vout);
2570
2571         return 0;
2572 }
2573
2574 /*!
2575  * This structure contains pointers to the power management callback functions.
2576  */
2577 static struct platform_driver mxc_v4l2out_driver = {
2578         .driver = {
2579                    .name = "MXC Video Output",
2580                    },
2581         .probe = mxc_v4l2out_probe,
2582         .remove = mxc_v4l2out_remove,
2583 };
2584
2585 static struct platform_device mxc_v4l2out_device = {
2586         .name = "MXC Video Output",
2587         .id = 0,
2588 };
2589
2590 /*!
2591  * mxc v4l2 init function
2592  *
2593  */
2594 static int mxc_v4l2out_init(void)
2595 {
2596         u8 err = 0;
2597
2598         err = platform_driver_register(&mxc_v4l2out_driver);
2599         if (err == 0) {
2600                 platform_device_register(&mxc_v4l2out_device);
2601         }
2602         return err;
2603 }
2604
2605 /*!
2606  * mxc v4l2 cleanup function
2607  *
2608  */
2609 static void mxc_v4l2out_clean(void)
2610 {
2611         video_unregister_device(g_vout->video_dev);
2612
2613         platform_driver_unregister(&mxc_v4l2out_driver);
2614         platform_device_unregister(&mxc_v4l2out_device);
2615         kfree(g_vout);
2616         g_vout = NULL;
2617 }
2618
2619 module_init(mxc_v4l2out_init);
2620 module_exit(mxc_v4l2out_clean);
2621
2622 module_param(video_nr, int, 0444);
2623 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
2624 MODULE_DESCRIPTION("V4L2-driver for MXC video output");
2625 MODULE_LICENSE("GPL");
2626 MODULE_SUPPORTED_DEVICE("video");