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