]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/mxc/ipu3/ipu_device.c
e20241476424ed1479f229b19de6b364d8a5d24e
[karo-tx-linux.git] / drivers / mxc / ipu3 / ipu_device.c
1 /*
2  * Copyright 2005-2013 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 ipu_device.c
16  *
17  * @brief This file contains the IPUv3 driver device interface and fops functions.
18  *
19  * @ingroup IPU
20  */
21 #include <linux/clk.h>
22 #include <linux/cpumask.h>
23 #include <linux/delay.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/err.h>
26 #include <linux/init.h>
27 #include <linux/io.h>
28 #include <linux/ipu-v3.h>
29 #include <linux/kthread.h>
30 #include <linux/module.h>
31 #include <linux/platform_device.h>
32 #include <linux/poll.h>
33 #include <linux/sched.h>
34 #include <linux/sched/rt.h>
35 #include <linux/slab.h>
36 #include <linux/spinlock.h>
37 #include <linux/time.h>
38 #include <linux/types.h>
39 #include <linux/vmalloc.h>
40 #include <linux/wait.h>
41
42 #include <asm/cacheflush.h>
43 #include <asm/outercache.h>
44
45 #include "ipu_param_mem.h"
46 #include "ipu_regs.h"
47 #include "vdoa.h"
48
49 #define CHECK_RETCODE(cont, str, err, label, ret)                       \
50 do {                                                                    \
51         if (cont) {                                                     \
52                 dev_err(t->dev, "ERR:[0x%p]-no:0x%x "#str" ret:%d,"     \
53                                 "line:%d\n", t, t->task_no, ret, __LINE__);\
54                 if (ret != -EACCES) {                                   \
55                         t->state = err;                                 \
56                         goto label;                                     \
57                 }                                                       \
58         }                                                               \
59 } while (0)
60
61 #define CHECK_RETCODE_CONT(cont, str, err, ret)                         \
62 do {                                                                    \
63         if (cont) {                                                     \
64                 dev_err(t->dev, "ERR:[0x%p]-no:0x%x"#str" ret:%d,"      \
65                                 "line:%d\n", t, t->task_no, ret, __LINE__);\
66                 if (ret != -EACCES) {                                   \
67                         if (t->state == STATE_OK)                       \
68                                 t->state = err;                         \
69                 }                                                       \
70         }                                                               \
71 } while (0)
72
73 #undef DBG_IPU_PERF
74 #ifdef DBG_IPU_PERF
75 #define CHECK_PERF(ts)                                                  \
76 do {                                                                    \
77         getnstimeofday(ts);                                             \
78 } while (0)
79
80 #define DECLARE_PERF_VAR                                                \
81         struct timespec ts_queue;                                       \
82         struct timespec ts_dotask;                                      \
83         struct timespec ts_waitirq;                                     \
84         struct timespec ts_sche;                                        \
85         struct timespec ts_rel;                                         \
86         struct timespec ts_frame
87
88 #define PRINT_TASK_STATISTICS                                           \
89 do {                                                                    \
90         ts_queue = timespec_sub(tsk->ts_dotask, tsk->ts_queue);         \
91         ts_dotask = timespec_sub(tsk->ts_waitirq, tsk->ts_dotask);      \
92         ts_waitirq = timespec_sub(tsk->ts_inirq, tsk->ts_waitirq);      \
93         ts_sche = timespec_sub(tsk->ts_wakeup, tsk->ts_inirq);          \
94         ts_rel = timespec_sub(tsk->ts_rel, tsk->ts_wakeup);             \
95         ts_frame = timespec_sub(tsk->ts_rel, tsk->ts_queue);            \
96         dev_dbg(tsk->dev, "[0x%p] no-0x%x, ts_q:%ldus, ts_do:%ldus,"    \
97                 "ts_waitirq:%ldus,ts_sche:%ldus, ts_rel:%ldus,"         \
98                 "ts_frame: %ldus\n", tsk, tsk->task_no,                 \
99         ts_queue.tv_nsec / NSEC_PER_USEC + ts_queue.tv_sec * USEC_PER_SEC,\
100         ts_dotask.tv_nsec / NSEC_PER_USEC + ts_dotask.tv_sec * USEC_PER_SEC,\
101         ts_waitirq.tv_nsec / NSEC_PER_USEC + ts_waitirq.tv_sec * USEC_PER_SEC,\
102         ts_sche.tv_nsec / NSEC_PER_USEC + ts_sche.tv_sec * USEC_PER_SEC,\
103         ts_rel.tv_nsec / NSEC_PER_USEC + ts_rel.tv_sec * USEC_PER_SEC,\
104         ts_frame.tv_nsec / NSEC_PER_USEC + ts_frame.tv_sec * USEC_PER_SEC); \
105         if ((ts_frame.tv_nsec/NSEC_PER_USEC + ts_frame.tv_sec*USEC_PER_SEC) > \
106                 80000)  \
107                 dev_dbg(tsk->dev, "ts_frame larger than 80ms [0x%p] no-0x%x.\n"\
108                                 , tsk, tsk->task_no);   \
109 } while (0)
110 #else
111 #define CHECK_PERF(ts)
112 #define DECLARE_PERF_VAR
113 #define PRINT_TASK_STATISTICS
114 #endif
115
116 #define IPU_PP_CH_VF    (IPU_TASK_ID_VF - 1)
117 #define IPU_PP_CH_PP    (IPU_TASK_ID_PP - 1)
118 #define MAX_PP_CH       (IPU_TASK_ID_MAX - 1)
119 #define VDOA_DEF_TIMEOUT_MS     (HZ/2)
120
121 /* Strucutures and variables for exporting MXC IPU as device*/
122 typedef enum {
123         STATE_OK = 0,
124         STATE_QUEUE,
125         STATE_IN_PROGRESS,
126         STATE_ERR,
127         STATE_TIMEOUT,
128         STATE_RES_TIMEOUT,
129         STATE_NO_IPU,
130         STATE_NO_IRQ,
131         STATE_IPU_BUSY,
132         STATE_IRQ_FAIL,
133         STATE_IRQ_TIMEOUT,
134         STATE_ENABLE_CHAN_FAIL,
135         STATE_DISABLE_CHAN_FAIL,
136         STATE_SEL_BUF_FAIL,
137         STATE_INIT_CHAN_FAIL,
138         STATE_LINK_CHAN_FAIL,
139         STATE_UNLINK_CHAN_FAIL,
140         STATE_INIT_CHAN_BUF_FAIL,
141         STATE_INIT_CHAN_BAND_FAIL,
142         STATE_SYS_NO_MEM,
143         STATE_VDOA_IRQ_TIMEOUT,
144         STATE_VDOA_IRQ_FAIL,
145         STATE_VDOA_TASK_FAIL,
146 } ipu_state_t;
147
148 enum {
149         INPUT_CHAN_VDI_P = 1,
150         INPUT_CHAN,
151         INPUT_CHAN_VDI_N,
152 };
153
154 struct ipu_state_msg {
155         int state;
156         char *msg;
157 } state_msg[] = {
158         {STATE_OK, "ok"},
159         {STATE_QUEUE, "split queue"},
160         {STATE_IN_PROGRESS, "split in progress"},
161         {STATE_ERR, "error"},
162         {STATE_TIMEOUT, "split task timeout"},
163         {STATE_RES_TIMEOUT, "wait resource timeout"},
164         {STATE_NO_IPU, "no ipu found"},
165         {STATE_NO_IRQ, "no irq found for task"},
166         {STATE_IPU_BUSY, "ipu busy"},
167         {STATE_IRQ_FAIL, "request irq failed"},
168         {STATE_IRQ_TIMEOUT, "wait for irq timeout"},
169         {STATE_ENABLE_CHAN_FAIL, "ipu enable channel fail"},
170         {STATE_DISABLE_CHAN_FAIL, "ipu disable channel fail"},
171         {STATE_SEL_BUF_FAIL, "ipu select buf fail"},
172         {STATE_INIT_CHAN_FAIL, "ipu init channel fail"},
173         {STATE_LINK_CHAN_FAIL, "ipu link channel fail"},
174         {STATE_UNLINK_CHAN_FAIL, "ipu unlink channel fail"},
175         {STATE_INIT_CHAN_BUF_FAIL, "ipu init channel buffer fail"},
176         {STATE_INIT_CHAN_BAND_FAIL, "ipu init channel band mode fail"},
177         {STATE_SYS_NO_MEM, "sys no mem: -ENOMEM"},
178         {STATE_VDOA_IRQ_TIMEOUT, "wait for vdoa irq timeout"},
179         {STATE_VDOA_IRQ_FAIL, "vdoa irq fail"},
180         {STATE_VDOA_TASK_FAIL, "vdoa task fail"},
181 };
182
183 struct stripe_setting {
184         u32 iw;
185         u32 ih;
186         u32 ow;
187         u32 oh;
188         u32 outh_resize_ratio;
189         u32 outv_resize_ratio;
190         u32 i_left_pos;
191         u32 i_right_pos;
192         u32 i_top_pos;
193         u32 i_bottom_pos;
194         u32 o_left_pos;
195         u32 o_right_pos;
196         u32 o_top_pos;
197         u32 o_bottom_pos;
198         u32 rl_split_line;
199         u32 ud_split_line;
200 };
201
202 struct task_set {
203 #define NULL_MODE       0x0
204 #define IC_MODE         0x1
205 #define ROT_MODE        0x2
206 #define VDI_MODE        0x4
207 #define IPU_PREPROCESS_MODE_MASK        (IC_MODE | ROT_MODE | VDI_MODE)
208 /* VDOA_MODE means this task use vdoa, and VDOA has two modes:
209  * BAND MODE and non-BAND MODE. Non-band mode will do transfer data
210  * to memory. BAND mode needs hareware sync with IPU, it is used default
211  * if connected to VDIC.
212  */
213 #define VDOA_MODE       0x8
214 #define VDOA_BAND_MODE  0x10
215         u8      mode;
216 #define IC_VF   0x1
217 #define IC_PP   0x2
218 #define ROT_VF  0x4
219 #define ROT_PP  0x8
220 #define VDI_VF  0x10
221 #define VDOA_ONLY       0x20
222         u8      task;
223 #define NO_SPLIT        0x0
224 #define RL_SPLIT        0x1
225 #define UD_SPLIT        0x2
226 #define LEFT_STRIPE     0x1
227 #define RIGHT_STRIPE    0x2
228 #define UP_STRIPE       0x4
229 #define DOWN_STRIPE     0x8
230 #define SPLIT_MASK      0xF
231         u8      split_mode;
232         u8      band_lines;
233         ipu_channel_t ic_chan;
234         ipu_channel_t rot_chan;
235         ipu_channel_t vdi_ic_p_chan;
236         ipu_channel_t vdi_ic_n_chan;
237
238         u32 i_off;
239         u32 i_uoff;
240         u32 i_voff;
241         u32 istride;
242
243         u32 ov_off;
244         u32 ov_uoff;
245         u32 ov_voff;
246         u32 ovstride;
247
248         u32 ov_alpha_off;
249         u32 ov_alpha_stride;
250
251         u32 o_off;
252         u32 o_uoff;
253         u32 o_voff;
254         u32 ostride;
255
256         u32 r_fmt;
257         u32 r_width;
258         u32 r_height;
259         u32 r_stride;
260         dma_addr_t r_paddr;
261
262         struct stripe_setting sp_setting;
263 };
264
265 struct ipu_split_task {
266         struct ipu_task task;
267         struct ipu_task_entry *parent_task;
268         struct ipu_task_entry *child_task;
269         u32 task_no;
270 };
271
272 struct ipu_task_entry {
273         struct ipu_input input;
274         struct ipu_output output;
275
276         bool overlay_en;
277         struct ipu_overlay overlay;
278 #define DEF_TIMEOUT_MS  1000
279 #define DEF_DELAY_MS 20
280         int     timeout;
281         int     irq;
282
283         u8      task_id;
284         u8      ipu_id;
285         u8      task_in_list;
286         u8      split_done;
287         struct mutex split_lock;
288         wait_queue_head_t split_waitq;
289
290         struct list_head node;
291         struct list_head split_list;
292         struct ipu_soc *ipu;
293         struct device *dev;
294         struct task_set set;
295         wait_queue_head_t task_waitq;
296         struct completion irq_comp;
297         struct kref refcount;
298         ipu_state_t state;
299         u32 task_no;
300         atomic_t done;
301         atomic_t res_free;
302         atomic_t res_get;
303
304         struct ipu_task_entry *parent;
305         char *vditmpbuf[2];
306         u32 old_save_lines;
307         u32 old_size;
308         bool buf1filled;
309         bool buf0filled;
310
311         vdoa_handle_t vdoa_handle;
312         struct vdoa_output_mem {
313                 void *vaddr;
314                 dma_addr_t paddr;
315                 int size;
316         } vdoa_dma;
317
318 #ifdef DBG_IPU_PERF
319         struct timespec ts_queue;
320         struct timespec ts_dotask;
321         struct timespec ts_waitirq;
322         struct timespec ts_inirq;
323         struct timespec ts_wakeup;
324         struct timespec ts_rel;
325 #endif
326 };
327
328 struct ipu_channel_tabel {
329         struct mutex    lock;
330         u8              used[MXC_IPU_MAX_NUM][MAX_PP_CH];
331         u8              vdoa_used;
332 };
333
334 struct ipu_thread_data {
335         struct ipu_soc *ipu;
336         u32     id;
337         u32     is_vdoa;
338 };
339
340 struct ipu_alloc_list {
341         struct list_head list;
342         dma_addr_t phy_addr;
343         void *cpu_addr;
344         u32 size;
345         void *file_index;
346 };
347
348 static LIST_HEAD(ipu_alloc_list);
349 static DEFINE_MUTEX(ipu_alloc_lock);
350 static struct ipu_channel_tabel ipu_ch_tbl;
351 static LIST_HEAD(ipu_task_list);
352 static DEFINE_SPINLOCK(ipu_task_list_lock);
353 static DECLARE_WAIT_QUEUE_HEAD(thread_waitq);
354 static DECLARE_WAIT_QUEUE_HEAD(res_waitq);
355 static atomic_t req_cnt;
356 static atomic_t file_index = ATOMIC_INIT(1);
357 static int major;
358 static int max_ipu_no;
359 static int thread_id;
360 static atomic_t frame_no;
361 static struct class *ipu_class;
362 static struct device *ipu_dev;
363 static int debug;
364 module_param(debug, int, 0600);
365 #ifdef DBG_IPU_PERF
366 static struct timespec ts_frame_max;
367 static u32 ts_frame_avg;
368 static atomic_t frame_cnt;
369 #endif
370
371 static bool deinterlace_3_field(struct ipu_task_entry *t)
372 {
373         return ((t->set.mode & VDI_MODE) &&
374                 (t->input.deinterlace.motion != HIGH_MOTION));
375 }
376
377 static u32 tiled_filed_size(struct ipu_task_entry *t)
378 {
379         u32 field_size;
380
381         /* note: page_align is required by VPU hw ouput buffer */
382         field_size = TILED_NV12_FRAME_SIZE(t->input.width, t->input.height/2);
383         return field_size;
384 }
385
386 static bool only_ic(u8 mode)
387 {
388         mode = mode & IPU_PREPROCESS_MODE_MASK;
389         return ((mode == IC_MODE) || (mode == VDI_MODE));
390 }
391
392 static bool only_rot(u8 mode)
393 {
394         mode = mode & IPU_PREPROCESS_MODE_MASK;
395         return (mode == ROT_MODE);
396 }
397
398 static bool ic_and_rot(u8 mode)
399 {
400         mode = mode & IPU_PREPROCESS_MODE_MASK;
401         return ((mode == (IC_MODE | ROT_MODE)) ||
402                  (mode == (VDI_MODE | ROT_MODE)));
403 }
404
405 static bool need_split(struct ipu_task_entry *t)
406 {
407         return ((t->set.split_mode != NO_SPLIT) || (t->task_no & SPLIT_MASK));
408 }
409
410 unsigned int fmt_to_bpp(unsigned int pixelformat)
411 {
412         u32 bpp;
413
414         switch (pixelformat) {
415         case IPU_PIX_FMT_RGB565:
416         /*interleaved 422*/
417         case IPU_PIX_FMT_YUYV:
418         case IPU_PIX_FMT_UYVY:
419         /*non-interleaved 422*/
420         case IPU_PIX_FMT_YUV422P:
421         case IPU_PIX_FMT_YVU422P:
422                 bpp = 16;
423                 break;
424         case IPU_PIX_FMT_BGR24:
425         case IPU_PIX_FMT_RGB24:
426         case IPU_PIX_FMT_YUV444:
427         case IPU_PIX_FMT_YUV444P:
428                 bpp = 24;
429                 break;
430         case IPU_PIX_FMT_BGR32:
431         case IPU_PIX_FMT_BGRA32:
432         case IPU_PIX_FMT_RGB32:
433         case IPU_PIX_FMT_RGBA32:
434         case IPU_PIX_FMT_ABGR32:
435                 bpp = 32;
436                 break;
437         /*non-interleaved 420*/
438         case IPU_PIX_FMT_YUV420P:
439         case IPU_PIX_FMT_YVU420P:
440         case IPU_PIX_FMT_YUV420P2:
441         case IPU_PIX_FMT_NV12:
442                 bpp = 12;
443                 break;
444         default:
445                 bpp = 8;
446                 break;
447         }
448         return bpp;
449 }
450 EXPORT_SYMBOL_GPL(fmt_to_bpp);
451
452 cs_t colorspaceofpixel(int fmt)
453 {
454         switch (fmt) {
455         case IPU_PIX_FMT_RGB565:
456         case IPU_PIX_FMT_BGR24:
457         case IPU_PIX_FMT_RGB24:
458         case IPU_PIX_FMT_BGRA32:
459         case IPU_PIX_FMT_BGR32:
460         case IPU_PIX_FMT_RGBA32:
461         case IPU_PIX_FMT_RGB32:
462         case IPU_PIX_FMT_ABGR32:
463                 return RGB_CS;
464                 break;
465         case IPU_PIX_FMT_UYVY:
466         case IPU_PIX_FMT_YUYV:
467         case IPU_PIX_FMT_YUV420P2:
468         case IPU_PIX_FMT_YUV420P:
469         case IPU_PIX_FMT_YVU420P:
470         case IPU_PIX_FMT_YVU422P:
471         case IPU_PIX_FMT_YUV422P:
472         case IPU_PIX_FMT_YUV444:
473         case IPU_PIX_FMT_YUV444P:
474         case IPU_PIX_FMT_NV12:
475         case IPU_PIX_FMT_TILED_NV12:
476         case IPU_PIX_FMT_TILED_NV12F:
477                 return YUV_CS;
478                 break;
479         default:
480                 return NULL_CS;
481         }
482 }
483 EXPORT_SYMBOL_GPL(colorspaceofpixel);
484
485 int need_csc(int ifmt, int ofmt)
486 {
487         cs_t ics, ocs;
488
489         ics = colorspaceofpixel(ifmt);
490         ocs = colorspaceofpixel(ofmt);
491
492         if ((ics == NULL_CS) || (ocs == NULL_CS))
493                 return -1;
494         else if (ics != ocs)
495                 return 1;
496
497         return 0;
498 }
499 EXPORT_SYMBOL_GPL(need_csc);
500
501 static int soc_max_in_width(u32 is_vdoa)
502 {
503         return is_vdoa ? 8192 : 4096;
504 }
505
506 static int soc_max_vdi_in_width(void)
507 {
508         return IPU_MAX_VDI_IN_WIDTH;
509 }
510 static int soc_max_in_height(void)
511 {
512         return 4096;
513 }
514
515 static int soc_max_out_width(void)
516 {
517         /* mx51/mx53/mx6q is 1024*/
518         return 1024;
519 }
520
521 static int soc_max_out_height(void)
522 {
523         /* mx51/mx53/mx6q is 1024*/
524         return 1024;
525 }
526
527 static void dump_task_info(struct ipu_task_entry *t)
528 {
529         if (!debug)
530                 return;
531         dev_dbg(t->dev, "[0x%p]input:\n", (void *)t);
532         dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->input.format);
533         dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->input.width);
534         dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->input.height);
535         dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->input.crop.w);
536         dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->input.crop.h);
537         dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
538                         (void *)t, t->input.crop.pos.x);
539         dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
540                         (void *)t, t->input.crop.pos.y);
541         dev_dbg(t->dev, "[0x%p]input buffer:\n", (void *)t);
542         dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->input.paddr);
543         dev_dbg(t->dev, "[0x%p]\ti_off = 0x%x\n", (void *)t, t->set.i_off);
544         dev_dbg(t->dev, "[0x%p]\ti_uoff = 0x%x\n", (void *)t, t->set.i_uoff);
545         dev_dbg(t->dev, "[0x%p]\ti_voff = 0x%x\n", (void *)t, t->set.i_voff);
546         dev_dbg(t->dev, "[0x%p]\tistride = %d\n", (void *)t, t->set.istride);
547         if (t->input.deinterlace.enable) {
548                 dev_dbg(t->dev, "[0x%p]deinterlace enabled with:\n", (void *)t);
549                 if (t->input.deinterlace.motion != HIGH_MOTION) {
550                         dev_dbg(t->dev, "[0x%p]\tlow/medium motion\n", (void *)t);
551                         dev_dbg(t->dev, "[0x%p]\tpaddr_n = 0x%x\n",
552                                 (void *)t, t->input.paddr_n);
553                 } else
554                         dev_dbg(t->dev, "[0x%p]\thigh motion\n", (void *)t);
555         }
556
557         dev_dbg(t->dev, "[0x%p]output:\n", (void *)t);
558         dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->output.format);
559         dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->output.width);
560         dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->output.height);
561         dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->output.crop.w);
562         dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->output.crop.h);
563         dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
564                         (void *)t, t->output.crop.pos.x);
565         dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
566                         (void *)t, t->output.crop.pos.y);
567         dev_dbg(t->dev, "[0x%p]\trotate = %d\n", (void *)t, t->output.rotate);
568         dev_dbg(t->dev, "[0x%p]output buffer:\n", (void *)t);
569         dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->output.paddr);
570         dev_dbg(t->dev, "[0x%p]\to_off = 0x%x\n", (void *)t, t->set.o_off);
571         dev_dbg(t->dev, "[0x%p]\to_uoff = 0x%x\n", (void *)t, t->set.o_uoff);
572         dev_dbg(t->dev, "[0x%p]\to_voff = 0x%x\n", (void *)t, t->set.o_voff);
573         dev_dbg(t->dev, "[0x%p]\tostride = %d\n", (void *)t, t->set.ostride);
574
575         if (t->overlay_en) {
576                 dev_dbg(t->dev, "[0x%p]overlay:\n", (void *)t);
577                 dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n",
578                                 (void *)t, t->overlay.format);
579                 dev_dbg(t->dev, "[0x%p]\twidth = %d\n",
580                                 (void *)t, t->overlay.width);
581                 dev_dbg(t->dev, "[0x%p]\theight = %d\n",
582                                 (void *)t, t->overlay.height);
583                 dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n",
584                                 (void *)t, t->overlay.crop.w);
585                 dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n",
586                                 (void *)t, t->overlay.crop.h);
587                 dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
588                                 (void *)t, t->overlay.crop.pos.x);
589                 dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
590                                 (void *)t, t->overlay.crop.pos.y);
591                 dev_dbg(t->dev, "[0x%p]overlay buffer:\n", (void *)t);
592                 dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
593                                 (void *)t, t->overlay.paddr);
594                 dev_dbg(t->dev, "[0x%p]\tov_off = 0x%x\n",
595                                 (void *)t, t->set.ov_off);
596                 dev_dbg(t->dev, "[0x%p]\tov_uoff = 0x%x\n",
597                                 (void *)t, t->set.ov_uoff);
598                 dev_dbg(t->dev, "[0x%p]\tov_voff = 0x%x\n",
599                                 (void *)t, t->set.ov_voff);
600                 dev_dbg(t->dev, "[0x%p]\tovstride = %d\n",
601                                 (void *)t, t->set.ovstride);
602                 if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
603                         dev_dbg(t->dev, "[0x%p]local alpha enabled with:\n",
604                                         (void *)t);
605                         dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
606                                         (void *)t, t->overlay.alpha.loc_alp_paddr);
607                         dev_dbg(t->dev, "[0x%p]\tov_alpha_off = 0x%x\n",
608                                         (void *)t, t->set.ov_alpha_off);
609                         dev_dbg(t->dev, "[0x%p]\tov_alpha_stride = %d\n",
610                                         (void *)t, t->set.ov_alpha_stride);
611                 } else
612                         dev_dbg(t->dev, "[0x%p]globle alpha enabled with value 0x%x\n",
613                                         (void *)t, t->overlay.alpha.gvalue);
614                 if (t->overlay.colorkey.enable)
615                         dev_dbg(t->dev, "[0x%p]colorkey enabled with value 0x%x\n",
616                                         (void *)t, t->overlay.colorkey.value);
617         }
618
619         dev_dbg(t->dev, "[0x%p]want task_id = %d\n", (void *)t, t->task_id);
620         dev_dbg(t->dev, "[0x%p]want task mode is 0x%x\n",
621                                 (void *)t, t->set.mode);
622         dev_dbg(t->dev, "[0x%p]\tIC_MODE = 0x%x\n", (void *)t, IC_MODE);
623         dev_dbg(t->dev, "[0x%p]\tROT_MODE = 0x%x\n", (void *)t, ROT_MODE);
624         dev_dbg(t->dev, "[0x%p]\tVDI_MODE = 0x%x\n", (void *)t, VDI_MODE);
625         dev_dbg(t->dev, "[0x%p]\tTask_no = 0x%x\n\n\n", (void *)t, t->task_no);
626 }
627
628 static void dump_check_err(struct device *dev, int err)
629 {
630         switch (err) {
631         case IPU_CHECK_ERR_INPUT_CROP:
632                 dev_err(dev, "input crop setting error\n");
633                 break;
634         case IPU_CHECK_ERR_OUTPUT_CROP:
635                 dev_err(dev, "output crop setting error\n");
636                 break;
637         case IPU_CHECK_ERR_OVERLAY_CROP:
638                 dev_err(dev, "overlay crop setting error\n");
639                 break;
640         case IPU_CHECK_ERR_INPUT_OVER_LIMIT:
641                 dev_err(dev, "input over limitation\n");
642                 break;
643         case IPU_CHECK_ERR_OVERLAY_WITH_VDI:
644                 dev_err(dev, "do not support overlay with deinterlace\n");
645                 break;
646         case IPU_CHECK_ERR_OV_OUT_NO_FIT:
647                 dev_err(dev,
648                         "width/height of overlay and ic output should be same\n");
649                 break;
650         case IPU_CHECK_ERR_PROC_NO_NEED:
651                 dev_err(dev, "no ipu processing need\n");
652                 break;
653         case IPU_CHECK_ERR_SPLIT_INPUTW_OVER:
654                 dev_err(dev, "split mode input width overflow\n");
655                 break;
656         case IPU_CHECK_ERR_SPLIT_INPUTH_OVER:
657                 dev_err(dev, "split mode input height overflow\n");
658                 break;
659         case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER:
660                 dev_err(dev, "split mode output width overflow\n");
661                 break;
662         case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER:
663                 dev_err(dev, "split mode output height overflow\n");
664                 break;
665         case IPU_CHECK_ERR_SPLIT_WITH_ROT:
666                 dev_err(dev, "not support split mode with rotation\n");
667                 break;
668         case IPU_CHECK_ERR_W_DOWNSIZE_OVER:
669                 dev_err(dev, "horizontal downsizing ratio overflow\n");
670                 break;
671         case IPU_CHECK_ERR_H_DOWNSIZE_OVER:
672                 dev_err(dev, "vertical downsizing ratio overflow\n");
673                 break;
674         default:
675                 break;
676         }
677 }
678
679 static void dump_check_warn(struct device *dev, int warn)
680 {
681         if (warn & IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN)
682                 dev_warn(dev, "input u/v offset not 8 align\n");
683         if (warn & IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN)
684                 dev_warn(dev, "output u/v offset not 8 align\n");
685         if (warn & IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN)
686                 dev_warn(dev, "overlay u/v offset not 8 align\n");
687 }
688
689 static int set_crop(struct ipu_crop *crop, int width, int height, int fmt)
690 {
691         if ((width == 0) || (height == 0)) {
692                 pr_err("Invalid param: width=%d, height=%d\n", width, height);
693                 return -EINVAL;
694         }
695
696         if ((IPU_PIX_FMT_TILED_NV12 == fmt) ||
697                 (IPU_PIX_FMT_TILED_NV12F == fmt)) {
698                 if (crop->w || crop->h) {
699                         if (((crop->w + crop->pos.x) > width)
700                         || ((crop->h + crop->pos.y) > height)
701                         || (0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
702                         || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
703                         || (0 != (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN))
704                         || (0 != (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN))
705                         ) {
706                                 pr_err("set_crop error MB align.\n");
707                                 return -EINVAL;
708                         }
709                 } else {
710                         crop->pos.x = 0;
711                         crop->pos.y = 0;
712                         crop->w = width;
713                         crop->h = height;
714                         if ((0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
715                         || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))) {
716                                 pr_err("set_crop error w/h MB align.\n");
717                                 return -EINVAL;
718                         }
719                 }
720         } else {
721                 if (crop->w || crop->h) {
722                         if (((crop->w + crop->pos.x) > width)
723                         || ((crop->h + crop->pos.y) > height))
724                                 return -EINVAL;
725                 } else {
726                         crop->pos.x = 0;
727                         crop->pos.y = 0;
728                         crop->w = width;
729                         crop->h = height;
730                 }
731                 crop->w -= crop->w%8;
732                 crop->h -= crop->h%8;
733         }
734
735         if ((crop->w == 0) || (crop->h == 0)) {
736                 pr_err("Invalid crop param: crop.w=%d, crop.h=%d\n",
737                         crop->w, crop->h);
738                 return -EINVAL;
739         }
740
741         return 0;
742 }
743
744 static void update_offset(unsigned int fmt,
745                                 unsigned int width, unsigned int height,
746                                 unsigned int pos_x, unsigned int pos_y,
747                                 int *off, int *uoff, int *voff, int *stride)
748 {
749         /* NOTE: u v offset should based on start point of off*/
750         switch (fmt) {
751         case IPU_PIX_FMT_YUV420P2:
752         case IPU_PIX_FMT_YUV420P:
753                 *off = pos_y * width + pos_x;
754                 *uoff = (width * (height - pos_y) - pos_x)
755                         + (width/2) * (pos_y/2) + pos_x/2;
756                 /* In case height is odd, round up to even */
757                 *voff = *uoff + (width/2) * ((height+1)/2);
758                 break;
759         case IPU_PIX_FMT_YVU420P:
760                 *off = pos_y * width + pos_x;
761                 *voff = (width * (height - pos_y) - pos_x)
762                         + (width/2) * (pos_y/2) + pos_x/2;
763                 /* In case height is odd, round up to even */
764                 *uoff = *voff + (width/2) * ((height+1)/2);
765                 break;
766         case IPU_PIX_FMT_YVU422P:
767                 *off = pos_y * width + pos_x;
768                 *voff = (width * (height - pos_y) - pos_x)
769                         + (width/2) * pos_y + pos_x/2;
770                 *uoff = *voff + (width/2) * height;
771                 break;
772         case IPU_PIX_FMT_YUV422P:
773                 *off = pos_y * width + pos_x;
774                 *uoff = (width * (height - pos_y) - pos_x)
775                         + (width/2) * pos_y + pos_x/2;
776                 *voff = *uoff + (width/2) * height;
777                 break;
778         case IPU_PIX_FMT_YUV444P:
779                 *off = pos_y * width + pos_x;
780                 *uoff = width * height;
781                 *voff = width * height * 2;
782                 break;
783         case IPU_PIX_FMT_NV12:
784                 *off = pos_y * width + pos_x;
785                 *uoff = (width * (height - pos_y) - pos_x)
786                         + width * (pos_y/2) + pos_x;
787                 break;
788         case IPU_PIX_FMT_TILED_NV12:
789                 /*
790                  * tiled format, progressive:
791                  * assuming that line is aligned with MB height (aligned to 16)
792                  * offset = line * stride + (pixel / MB_width) * pixels_in_MB
793                  * = line * stride + (pixel / 16) * 256
794                  * = line * stride + pixel * 16
795                  */
796                 *off = pos_y * width + (pos_x << 4);
797                 *uoff = ALIGN(width * height, SZ_4K) + (*off >> 1) - *off;
798                 break;
799         case IPU_PIX_FMT_TILED_NV12F:
800                 /*
801                  * tiled format, interlaced:
802                  * same as above, only number of pixels in MB is 128,
803                  * instead of 256
804                  */
805                 *off = (pos_y >> 1) * width + (pos_x << 3);
806                 *uoff = ALIGN(width * height/2, SZ_4K) + (*off >> 1) - *off;
807                 break;
808         default:
809                 *off = (pos_y * width + pos_x) * fmt_to_bpp(fmt)/8;
810                 break;
811         }
812         *stride = width * bytes_per_pixel(fmt);
813 }
814
815 static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
816 {
817         struct stripe_param left_stripe;
818         struct stripe_param right_stripe;
819         struct stripe_param up_stripe;
820         struct stripe_param down_stripe;
821         u32 iw, ih, ow, oh;
822         u32 max_width;
823         int ret;
824
825         if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
826                 return IPU_CHECK_ERR_SPLIT_WITH_ROT;
827
828         iw = t->input.crop.w;
829         ih = t->input.crop.h;
830
831         ow = t->output.crop.w;
832         oh = t->output.crop.h;
833
834         memset(&left_stripe, 0, sizeof(left_stripe));
835         memset(&right_stripe, 0, sizeof(right_stripe));
836         memset(&up_stripe, 0, sizeof(up_stripe));
837         memset(&down_stripe, 0, sizeof(down_stripe));
838
839         if (t->set.split_mode & RL_SPLIT) {
840                 /*
841                  * We do want equal strips: initialize stripes in case
842                  * calc_stripes returns before actually doing the calculation
843                  */
844                 left_stripe.input_width = iw / 2;
845                 left_stripe.output_width = ow / 2;
846                 right_stripe.input_column = iw / 2;
847                 right_stripe.output_column = ow / 2;
848
849                 if (vdi_split)
850                         max_width = soc_max_vdi_in_width();
851                 else
852                         max_width = soc_max_out_width();
853                 ret = ipu_calc_stripes_sizes(iw,
854                                 ow,
855                                 max_width,
856                                 (((unsigned long long)1) << 32), /* 32bit for fractional*/
857                                 1, /* equal stripes */
858                                 t->input.format,
859                                 t->output.format,
860                                 &left_stripe,
861                                 &right_stripe);
862                 if (ret)
863                         dev_dbg(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
864                                  t->task_no, ret);
865                 t->set.sp_setting.iw = left_stripe.input_width;
866                 t->set.sp_setting.ow = left_stripe.output_width;
867                 t->set.sp_setting.outh_resize_ratio = left_stripe.irr;
868                 t->set.sp_setting.i_left_pos = left_stripe.input_column;
869                 t->set.sp_setting.o_left_pos = left_stripe.output_column;
870                 t->set.sp_setting.i_right_pos = right_stripe.input_column;
871                 t->set.sp_setting.o_right_pos = right_stripe.output_column;
872         } else {
873                 t->set.sp_setting.iw = iw;
874                 t->set.sp_setting.ow = ow;
875                 t->set.sp_setting.outh_resize_ratio = 0;
876                 t->set.sp_setting.i_left_pos = 0;
877                 t->set.sp_setting.o_left_pos = 0;
878                 t->set.sp_setting.i_right_pos = 0;
879                 t->set.sp_setting.o_right_pos = 0;
880         }
881         if ((t->set.sp_setting.iw + t->set.sp_setting.i_right_pos) > iw)
882                 return IPU_CHECK_ERR_SPLIT_INPUTW_OVER;
883         if (((t->set.sp_setting.ow + t->set.sp_setting.o_right_pos) > ow)
884                 || (t->set.sp_setting.ow > soc_max_out_width()))
885                 return IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER;
886
887         if (t->set.split_mode & UD_SPLIT) {
888                 /*
889                  * We do want equal strips: initialize stripes in case
890                  * calc_stripes returns before actually doing the calculation
891                  */
892                 up_stripe.input_width = ih / 2;
893                 up_stripe.output_width = oh / 2;
894                 down_stripe.input_column = ih / 2;
895                 down_stripe.output_column = oh / 2;
896                 ret = ipu_calc_stripes_sizes(ih,
897                                 oh,
898                                 soc_max_out_height(),
899                                 (((unsigned long long)1) << 32), /* 32bit for fractional*/
900                                 1, /* equal stripes */
901                                 t->input.format,
902                                 t->output.format,
903                                 &up_stripe,
904                                 &down_stripe);
905                 if (ret)
906                         dev_err(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
907                                  t->task_no, ret);
908                 t->set.sp_setting.ih = up_stripe.input_width;
909                 t->set.sp_setting.oh = up_stripe.output_width;
910                 t->set.sp_setting.outv_resize_ratio = up_stripe.irr;
911                 t->set.sp_setting.i_top_pos = up_stripe.input_column;
912                 t->set.sp_setting.o_top_pos = up_stripe.output_column;
913                 t->set.sp_setting.i_bottom_pos = down_stripe.input_column;
914                 t->set.sp_setting.o_bottom_pos = down_stripe.output_column;
915         } else {
916                 t->set.sp_setting.ih = ih;
917                 t->set.sp_setting.oh = oh;
918                 t->set.sp_setting.outv_resize_ratio = 0;
919                 t->set.sp_setting.i_top_pos = 0;
920                 t->set.sp_setting.o_top_pos = 0;
921                 t->set.sp_setting.i_bottom_pos = 0;
922                 t->set.sp_setting.o_bottom_pos = 0;
923         }
924         if ((t->set.sp_setting.ih + t->set.sp_setting.i_bottom_pos) > ih)
925                 return IPU_CHECK_ERR_SPLIT_INPUTH_OVER;
926         if (((t->set.sp_setting.oh + t->set.sp_setting.o_bottom_pos) > oh)
927                 || (t->set.sp_setting.oh > soc_max_out_height()))
928                 return IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER;
929
930         return IPU_CHECK_OK;
931 }
932
933 static int check_task(struct ipu_task_entry *t)
934 {
935         int tmp;
936         int ret = IPU_CHECK_OK;
937         int timeout;
938         bool vdi_split = false;
939
940         if ((IPU_PIX_FMT_TILED_NV12 == t->overlay.format) ||
941                 (IPU_PIX_FMT_TILED_NV12F == t->overlay.format) ||
942                 (IPU_PIX_FMT_TILED_NV12 == t->output.format) ||
943                 (IPU_PIX_FMT_TILED_NV12F == t->output.format) ||
944                 ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
945                         !t->input.deinterlace.enable)) {
946                 ret = IPU_CHECK_ERR_NOT_SUPPORT;
947                 goto done;
948         }
949
950         /* check input */
951         ret = set_crop(&t->input.crop, t->input.width, t->input.height,
952                 t->input.format);
953         if (ret < 0) {
954                 ret = IPU_CHECK_ERR_INPUT_CROP;
955                 goto done;
956         } else
957                 update_offset(t->input.format, t->input.width, t->input.height,
958                                 t->input.crop.pos.x, t->input.crop.pos.y,
959                                 &t->set.i_off, &t->set.i_uoff,
960                                 &t->set.i_voff, &t->set.istride);
961
962         /* check output */
963         ret = set_crop(&t->output.crop, t->output.width, t->output.height,
964                 t->output.format);
965         if (ret < 0) {
966                 ret = IPU_CHECK_ERR_OUTPUT_CROP;
967                 goto done;
968         } else
969                 update_offset(t->output.format,
970                                 t->output.width, t->output.height,
971                                 t->output.crop.pos.x, t->output.crop.pos.y,
972                                 &t->set.o_off, &t->set.o_uoff,
973                                 &t->set.o_voff, &t->set.ostride);
974
975         if (t->output.crop.w * 8 <= t->input.crop.w) {
976                 ret = IPU_CHECK_ERR_W_DOWNSIZE_OVER;
977                 goto done;
978         }
979
980         if (t->output.crop.h * 8 <= t->input.crop.h) {
981                 ret = IPU_CHECK_ERR_H_DOWNSIZE_OVER;
982                 goto done;
983         }
984
985         if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
986                 (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
987                 if ((t->input.crop.w > soc_max_in_width(1)) ||
988                         (t->input.crop.h > soc_max_in_height())) {
989                         ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
990                         goto done;
991                 }
992                 /* output fmt: NV12 and YUYV, now don't support resize */
993                 if (((IPU_PIX_FMT_NV12 != t->output.format) &&
994                                 (IPU_PIX_FMT_YUYV != t->output.format)) ||
995                         (t->input.crop.w != t->output.crop.w) ||
996                         (t->input.crop.h != t->output.crop.h)) {
997                         ret = IPU_CHECK_ERR_NOT_SUPPORT;
998                         goto done;
999                 }
1000         }
1001
1002         /* check overlay if there is */
1003         if (t->overlay_en) {
1004                 if (t->input.deinterlace.enable) {
1005                         ret = IPU_CHECK_ERR_OVERLAY_WITH_VDI;
1006                         goto done;
1007                 }
1008
1009                 ret = set_crop(&t->overlay.crop, t->overlay.width,
1010                         t->overlay.height, t->overlay.format);
1011                 if (ret < 0) {
1012                         ret = IPU_CHECK_ERR_OVERLAY_CROP;
1013                         goto done;
1014                 } else {
1015                         int ow = t->output.crop.w;
1016                         int oh = t->output.crop.h;
1017
1018                         if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
1019                                 ow = t->output.crop.h;
1020                                 oh = t->output.crop.w;
1021                         }
1022                         if ((t->overlay.crop.w != ow) || (t->overlay.crop.h != oh)) {
1023                                 ret = IPU_CHECK_ERR_OV_OUT_NO_FIT;
1024                                 goto done;
1025                         }
1026
1027                         update_offset(t->overlay.format,
1028                                         t->overlay.width, t->overlay.height,
1029                                         t->overlay.crop.pos.x, t->overlay.crop.pos.y,
1030                                         &t->set.ov_off, &t->set.ov_uoff,
1031                                         &t->set.ov_voff, &t->set.ovstride);
1032                         if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
1033                                 t->set.ov_alpha_stride = t->overlay.width;
1034                                 t->set.ov_alpha_off = t->overlay.crop.pos.y *
1035                                         t->overlay.width + t->overlay.crop.pos.x;
1036                         }
1037                 }
1038         }
1039
1040         /* input overflow? */
1041         if (!((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
1042                 (IPU_PIX_FMT_TILED_NV12F == t->input.format))) {
1043                 if ((t->input.crop.w > soc_max_in_width(0)) ||
1044                         (t->input.crop.h > soc_max_in_height())) {
1045                                 ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
1046                                 goto done;
1047                 }
1048         }
1049
1050         /* check task mode */
1051         t->set.mode = NULL_MODE;
1052         t->set.split_mode = NO_SPLIT;
1053
1054         if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
1055                 /*output swap*/
1056                 tmp = t->output.crop.w;
1057                 t->output.crop.w = t->output.crop.h;
1058                 t->output.crop.h = tmp;
1059         }
1060
1061         if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
1062                 t->set.mode |= ROT_MODE;
1063
1064         /*need resize or CSC?*/
1065         if ((t->input.crop.w != t->output.crop.w) ||
1066                         (t->input.crop.h != t->output.crop.h) ||
1067                         need_csc(t->input.format, t->output.format))
1068                 t->set.mode |= IC_MODE;
1069
1070         /*need flip?*/
1071         if ((t->set.mode == NULL_MODE) && (t->output.rotate > IPU_ROTATE_NONE))
1072                 t->set.mode |= IC_MODE;
1073
1074         /*need IDMAC do format(same color space)?*/
1075         if ((t->set.mode == NULL_MODE) && (t->input.format != t->output.format))
1076                 t->set.mode |= IC_MODE;
1077
1078         /*overlay support*/
1079         if (t->overlay_en)
1080                 t->set.mode |= IC_MODE;
1081
1082         /*deinterlace*/
1083         if (t->input.deinterlace.enable) {
1084                 t->set.mode &= ~IC_MODE;
1085                 t->set.mode |= VDI_MODE;
1086         }
1087         if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
1088                 (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
1089                 if (t->set.mode & ROT_MODE) {
1090                         ret = IPU_CHECK_ERR_NOT_SUPPORT;
1091                         goto done;
1092                 }
1093                 t->set.mode |= VDOA_MODE;
1094                 if (IPU_PIX_FMT_TILED_NV12F == t->input.format)
1095                         t->set.mode |= VDOA_BAND_MODE;
1096                 t->set.mode &= ~IC_MODE;
1097         }
1098
1099         if ((t->set.mode & (IC_MODE | VDI_MODE)) &&
1100                 (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
1101                 if (t->output.crop.w > soc_max_out_width())
1102                         t->set.split_mode |= RL_SPLIT;
1103                 if (t->output.crop.h > soc_max_out_height())
1104                         t->set.split_mode |= UD_SPLIT;
1105                 if (!t->set.split_mode && (t->set.mode & VDI_MODE) &&
1106                                 (t->input.crop.w > soc_max_vdi_in_width())) {
1107                         t->set.split_mode |= RL_SPLIT;
1108                         vdi_split = true;
1109                 }
1110                 if (t->set.split_mode) {
1111                         if ((t->set.split_mode == RL_SPLIT) ||
1112                                  (t->set.split_mode == UD_SPLIT))
1113                                 timeout = DEF_TIMEOUT_MS * 2 + DEF_DELAY_MS;
1114                         else
1115                                 timeout = DEF_TIMEOUT_MS * 4 + DEF_DELAY_MS;
1116                         if (t->timeout < timeout)
1117                                 t->timeout = timeout;
1118
1119                         ret = update_split_setting(t, vdi_split);
1120                         if (ret > IPU_CHECK_ERR_MIN)
1121                                 goto done;
1122                 }
1123         }
1124
1125         if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
1126                 /*output swap*/
1127                 tmp = t->output.crop.w;
1128                 t->output.crop.w = t->output.crop.h;
1129                 t->output.crop.h = tmp;
1130         }
1131
1132         if (t->set.mode == NULL_MODE) {
1133                 ret = IPU_CHECK_ERR_PROC_NO_NEED;
1134                 goto done;
1135         }
1136
1137         if ((t->set.i_uoff % 8) || (t->set.i_voff % 8))
1138                 ret |= IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN;
1139         if ((t->set.o_uoff % 8) || (t->set.o_voff % 8))
1140                 ret |= IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN;
1141         if (t->overlay_en && ((t->set.ov_uoff % 8) || (t->set.ov_voff % 8)))
1142                 ret |= IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN;
1143
1144 done:
1145         /* dump msg */
1146         if (debug) {
1147                 if (ret > IPU_CHECK_ERR_MIN)
1148                         dump_check_err(t->dev, ret);
1149                 else if (ret != IPU_CHECK_OK)
1150                         dump_check_warn(t->dev, ret);
1151         }
1152
1153         return ret;
1154 }
1155
1156 static int prepare_task(struct ipu_task_entry *t)
1157 {
1158         int ret = 0;
1159
1160         ret = check_task(t);
1161         if (ret > IPU_CHECK_ERR_MIN)
1162                 return -EINVAL;
1163
1164         if (t->set.mode & VDI_MODE) {
1165                 t->task_id = IPU_TASK_ID_VF;
1166                 t->set.task = VDI_VF;
1167                 if (t->set.mode & ROT_MODE)
1168                         t->set.task |= ROT_VF;
1169         }
1170
1171         if (VDOA_MODE == t->set.mode) {
1172                 if (t->set.task != 0) {
1173                         dev_err(t->dev, "ERR: vdoa only task:0x%x, [0x%p].\n",
1174                                         t->set.task, t);
1175                         return -EINVAL;
1176                 }
1177                 t->set.task |= VDOA_ONLY;
1178         }
1179
1180         if (VDOA_BAND_MODE & t->set.mode) {
1181                 /* to save band size: 1<<3 = 8 lines */
1182                 t->set.band_lines = 3;
1183         }
1184
1185         dump_task_info(t);
1186
1187         return ret;
1188 }
1189
1190 static uint32_t ic_vf_pp_is_busy(struct ipu_soc *ipu, bool is_vf)
1191 {
1192         uint32_t        status;
1193         uint32_t        status_vf;
1194         uint32_t        status_rot;
1195
1196         if (is_vf) {
1197                 status = ipu_channel_status(ipu, MEM_VDI_PRP_VF_MEM);
1198                 status_vf = ipu_channel_status(ipu, MEM_PRP_VF_MEM);
1199                 status_rot = ipu_channel_status(ipu, MEM_ROT_VF_MEM);
1200                 return status || status_vf || status_rot;
1201         } else {
1202                 status = ipu_channel_status(ipu, MEM_PP_MEM);
1203                 status_rot = ipu_channel_status(ipu, MEM_ROT_PP_MEM);
1204                 return status || status_rot;
1205         }
1206 }
1207
1208 static int _get_vdoa_ipu_res(struct ipu_task_entry *t)
1209 {
1210         int             i;
1211         struct ipu_soc  *ipu;
1212         u8              *used;
1213         uint32_t        found_ipu = 0;
1214         uint32_t        found_vdoa = 0;
1215         struct ipu_channel_tabel        *tbl = &ipu_ch_tbl;
1216
1217         mutex_lock(&tbl->lock);
1218         if (t->set.mode & VDOA_MODE) {
1219                 if (NULL != t->vdoa_handle)
1220                         found_vdoa = 1;
1221                 else {
1222                         found_vdoa = tbl->vdoa_used ? 0 : 1;
1223                         if (found_vdoa) {
1224                                 tbl->vdoa_used = 1;
1225                                 vdoa_get_handle(&t->vdoa_handle);
1226                         } else
1227                                 /* first get vdoa->ipu resource sequence */
1228                                 goto out;
1229                         if (t->set.task & VDOA_ONLY)
1230                                 goto out;
1231                 }
1232         }
1233
1234         for (i = 0; i < max_ipu_no; i++) {
1235                 ipu = ipu_get_soc(i);
1236                 if (IS_ERR(ipu))
1237                         dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
1238                                  t->task_no, found_vdoa, i);
1239
1240                 used = &tbl->used[i][IPU_PP_CH_VF];
1241                 if (t->set.mode & VDI_MODE) {
1242                         if (0 == *used) {
1243                                 *used = 1;
1244                                 found_ipu = 1;
1245                                 break;
1246                         }
1247                 } else if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
1248                         if (0 == *used) {
1249                                 t->task_id = IPU_TASK_ID_VF;
1250                                 if (t->set.mode & IC_MODE)
1251                                         t->set.task |= IC_VF;
1252                                 if (t->set.mode & ROT_MODE)
1253                                         t->set.task |= ROT_VF;
1254                                 *used = 1;
1255                                 found_ipu = 1;
1256                                 break;
1257                         }
1258                 } else
1259                         dev_err(t->dev, "no:0x%x,found_vdoa:%d, mode:0x%x\n",
1260                                  t->task_no, found_vdoa, t->set.mode);
1261         }
1262         if (found_ipu)
1263                 goto next;
1264
1265         for (i = 0; i < max_ipu_no; i++) {
1266                 ipu = ipu_get_soc(i);
1267                 if (IS_ERR(ipu))
1268                         dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
1269                                  t->task_no, found_vdoa, i);
1270
1271                 if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
1272                         used = &tbl->used[i][IPU_PP_CH_PP];
1273                         if (0 == *used) {
1274                                 t->task_id = IPU_TASK_ID_PP;
1275                                 if (t->set.mode & IC_MODE)
1276                                         t->set.task |= IC_PP;
1277                                 if (t->set.mode & ROT_MODE)
1278                                         t->set.task |= ROT_PP;
1279                                 *used = 1;
1280                                 found_ipu = 1;
1281                                 break;
1282                         }
1283                 }
1284         }
1285
1286 next:
1287         if (found_ipu) {
1288                 t->ipu = ipu;
1289                 t->ipu_id = i;
1290                 t->dev = ipu->dev;
1291                 if (atomic_inc_return(&t->res_get) == 2)
1292                         dev_err(t->dev,
1293                                 "ERR no:0x%x,found_vdoa:%d,get ipu twice\n",
1294                                  t->task_no, found_vdoa);
1295         }
1296 out:
1297         dev_dbg(t->dev,
1298                 "%s:no:0x%x,found_vdoa:%d, found_ipu:%d\n",
1299                  __func__, t->task_no, found_vdoa, found_ipu);
1300         mutex_unlock(&tbl->lock);
1301         if (t->set.task & VDOA_ONLY)
1302                 return found_vdoa;
1303         else if (t->set.mode & VDOA_MODE)
1304                 return found_vdoa && found_ipu;
1305         else
1306                 return found_ipu;
1307 }
1308
1309 static void put_vdoa_ipu_res(struct ipu_task_entry *tsk, int vdoa_only)
1310 {
1311         int ret;
1312         int rel_vdoa = 0, rel_ipu = 0;
1313         struct ipu_channel_tabel        *tbl = &ipu_ch_tbl;
1314
1315         mutex_lock(&tbl->lock);
1316         if (tsk->set.mode & VDOA_MODE) {
1317                 if (!tbl->vdoa_used && tsk->vdoa_handle)
1318                         dev_err(tsk->dev,
1319                                 "ERR no:0x%x,vdoa not used,mode:0x%x\n",
1320                                  tsk->task_no, tsk->set.mode);
1321                 if (tbl->vdoa_used && tsk->vdoa_handle) {
1322                         tbl->vdoa_used = 0;
1323                         vdoa_put_handle(&tsk->vdoa_handle);
1324                         if (tsk->ipu)
1325                                 tsk->ipu->vdoa_en = 0;
1326                         rel_vdoa = 1;
1327                         if (vdoa_only || (tsk->set.task & VDOA_ONLY))
1328                                 goto out;
1329                 }
1330         }
1331
1332         tbl->used[tsk->ipu_id][tsk->task_id - 1] = 0;
1333         rel_ipu = 1;
1334         ret = atomic_inc_return(&tsk->res_free);
1335         if (ret == 2)
1336                 dev_err(tsk->dev,
1337                         "ERR no:0x%x,rel_vdoa:%d,put ipu twice\n",
1338                          tsk->task_no, rel_vdoa);
1339 out:
1340         dev_dbg(tsk->dev,
1341                 "%s:no:0x%x,rel_vdoa:%d, rel_ipu:%d\n",
1342                  __func__, tsk->task_no, rel_vdoa, rel_ipu);
1343         mutex_unlock(&tbl->lock);
1344 }
1345
1346 static int get_vdoa_ipu_res(struct ipu_task_entry *t)
1347 {
1348         int             ret;
1349         uint32_t        found = 0;
1350
1351         found = _get_vdoa_ipu_res(t);
1352         if (!found) {
1353                 t->ipu_id = -1;
1354                 t->ipu = NULL;
1355                 /* blocking to get resource */
1356                 ret = atomic_inc_return(&req_cnt);
1357                 dev_dbg(t->dev,
1358                         "wait_res:no:0x%x,req_cnt:%d\n", t->task_no, ret);
1359                 ret = wait_event_timeout(res_waitq, _get_vdoa_ipu_res(t),
1360                                  msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
1361                 if (ret == 0) {
1362                         dev_err(t->dev, "ERR[0x%p,no-0x%x] wait_res timeout:%dms!\n",
1363                                          t, t->task_no, t->timeout - DEF_DELAY_MS);
1364                         ret = -ETIMEDOUT;
1365                         t->state = STATE_RES_TIMEOUT;
1366                         goto out;
1367                 } else {
1368                         if (!(t->set.task & VDOA_ONLY) && (!t->ipu))
1369                                 dev_err(t->dev,
1370                                         "ERR[no-0x%x] can not get ipu!\n",
1371                                         t->task_no);
1372                         ret = atomic_read(&req_cnt);
1373                         if (ret > 0)
1374                                 ret = atomic_dec_return(&req_cnt);
1375                         else
1376                                 dev_err(t->dev,
1377                                         "ERR[no-0x%x] req_cnt:%d mismatch!\n",
1378                                         t->task_no, ret);
1379                         dev_dbg(t->dev, "no-0x%x,[0x%p],req_cnt:%d, got_res!\n",
1380                                                 t->task_no, t, ret);
1381                         found = 1;
1382                 }
1383         }
1384
1385 out:
1386         return found;
1387 }
1388
1389 static struct ipu_task_entry *create_task_entry(struct ipu_task *task)
1390 {
1391         struct ipu_task_entry *tsk;
1392
1393         tsk = kzalloc(sizeof(struct ipu_task_entry), GFP_KERNEL);
1394         if (!tsk)
1395                 return ERR_PTR(-ENOMEM);
1396         kref_init(&tsk->refcount);
1397         tsk->state = -EINVAL;
1398         tsk->ipu_id = -1;
1399         tsk->dev = ipu_dev;
1400         tsk->input = task->input;
1401         tsk->output = task->output;
1402         tsk->overlay_en = task->overlay_en;
1403         if (tsk->overlay_en)
1404                 tsk->overlay = task->overlay;
1405         if (task->timeout > DEF_TIMEOUT_MS)
1406                 tsk->timeout = task->timeout;
1407         else
1408                 tsk->timeout = DEF_TIMEOUT_MS;
1409
1410         return tsk;
1411 }
1412
1413 static void task_mem_free(struct kref *ref)
1414 {
1415         struct ipu_task_entry *tsk =
1416                         container_of(ref, struct ipu_task_entry, refcount);
1417
1418         memset(tsk, 0, sizeof(*tsk));
1419         kfree(tsk);
1420 }
1421
1422 int create_split_child_task(struct ipu_split_task *sp_task)
1423 {
1424         int ret = 0;
1425         struct ipu_task_entry *tsk;
1426
1427         tsk = create_task_entry(&sp_task->task);
1428         if (IS_ERR(tsk))
1429                 return PTR_ERR(tsk);
1430
1431         sp_task->child_task = tsk;
1432         tsk->task_no = sp_task->task_no;
1433
1434         ret = prepare_task(tsk);
1435         if (ret < 0)
1436                 goto err;
1437
1438         tsk->parent = sp_task->parent_task;
1439         tsk->set.sp_setting = sp_task->parent_task->set.sp_setting;
1440
1441         list_add(&tsk->node, &tsk->parent->split_list);
1442         dev_dbg(tsk->dev, "[0x%p] sp_tsk Q list,no-0x%x\n", tsk, tsk->task_no);
1443         tsk->state = STATE_QUEUE;
1444         CHECK_PERF(&tsk->ts_queue);
1445 err:
1446         return ret;
1447 }
1448
1449 static inline int sp_task_check_done(struct ipu_split_task *sp_task,
1450                         struct ipu_task_entry *parent, int num, int *idx)
1451 {
1452         int i;
1453         int ret = 0;
1454         struct ipu_task_entry *tsk;
1455         struct mutex *lock = &parent->split_lock;
1456
1457         *idx = -EINVAL;
1458         mutex_lock(lock);
1459         for (i = 0; i < num; i++) {
1460                 tsk = sp_task[i].child_task;
1461                 if (tsk && tsk->split_done) {
1462                         *idx = i;
1463                         ret = 1;
1464                         goto out;
1465                 }
1466         }
1467
1468 out:
1469         mutex_unlock(lock);
1470         return ret;
1471 }
1472
1473 static int create_split_task(
1474                 int stripe,
1475                 struct ipu_split_task *sp_task)
1476 {
1477         struct ipu_task *task = &(sp_task->task);
1478         struct ipu_task_entry *t = sp_task->parent_task;
1479         int ret;
1480
1481         sp_task->task_no |= stripe;
1482
1483         task->input = t->input;
1484         task->output = t->output;
1485         task->overlay_en = t->overlay_en;
1486         if (task->overlay_en)
1487                 task->overlay = t->overlay;
1488         task->task_id = t->task_id;
1489         if ((t->set.split_mode == RL_SPLIT) ||
1490                  (t->set.split_mode == UD_SPLIT))
1491                 task->timeout = t->timeout / 2;
1492         else
1493                 task->timeout = t->timeout / 4;
1494
1495         task->input.crop.w = t->set.sp_setting.iw;
1496         task->input.crop.h = t->set.sp_setting.ih;
1497         if (task->overlay_en) {
1498                 task->overlay.crop.w = t->set.sp_setting.ow;
1499                 task->overlay.crop.h = t->set.sp_setting.oh;
1500         }
1501         if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
1502                 task->output.crop.w = t->set.sp_setting.oh;
1503                 task->output.crop.h = t->set.sp_setting.ow;
1504                 t->set.sp_setting.rl_split_line = t->set.sp_setting.o_bottom_pos;
1505                 t->set.sp_setting.ud_split_line = t->set.sp_setting.o_right_pos;
1506
1507         } else {
1508                 task->output.crop.w = t->set.sp_setting.ow;
1509                 task->output.crop.h = t->set.sp_setting.oh;
1510                 t->set.sp_setting.rl_split_line = t->set.sp_setting.o_right_pos;
1511                 t->set.sp_setting.ud_split_line = t->set.sp_setting.o_bottom_pos;
1512         }
1513
1514         if (stripe & LEFT_STRIPE)
1515                 task->input.crop.pos.x += t->set.sp_setting.i_left_pos;
1516         else if (stripe & RIGHT_STRIPE)
1517                 task->input.crop.pos.x += t->set.sp_setting.i_right_pos;
1518         if (stripe & UP_STRIPE)
1519                 task->input.crop.pos.y += t->set.sp_setting.i_top_pos;
1520         else if (stripe & DOWN_STRIPE)
1521                 task->input.crop.pos.y += t->set.sp_setting.i_bottom_pos;
1522
1523         if (task->overlay_en) {
1524                 if (stripe & LEFT_STRIPE)
1525                         task->overlay.crop.pos.x += t->set.sp_setting.o_left_pos;
1526                 else if (stripe & RIGHT_STRIPE)
1527                         task->overlay.crop.pos.x += t->set.sp_setting.o_right_pos;
1528                 if (stripe & UP_STRIPE)
1529                         task->overlay.crop.pos.y += t->set.sp_setting.o_top_pos;
1530                 else if (stripe & DOWN_STRIPE)
1531                         task->overlay.crop.pos.y += t->set.sp_setting.o_bottom_pos;
1532         }
1533
1534         switch (t->output.rotate) {
1535         case IPU_ROTATE_NONE:
1536                 if (stripe & LEFT_STRIPE)
1537                         task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
1538                 else if (stripe & RIGHT_STRIPE)
1539                         task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
1540                 if (stripe & UP_STRIPE)
1541                         task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
1542                 else if (stripe & DOWN_STRIPE)
1543                         task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
1544                 break;
1545         case IPU_ROTATE_VERT_FLIP:
1546                 if (stripe & LEFT_STRIPE)
1547                         task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
1548                 else if (stripe & RIGHT_STRIPE)
1549                         task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
1550                 if (stripe & UP_STRIPE)
1551                         task->output.crop.pos.y =
1552                                         t->output.crop.pos.y + t->output.crop.h
1553                                         - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
1554                 else if (stripe & DOWN_STRIPE)
1555                         task->output.crop.pos.y =
1556                                         t->output.crop.pos.y + t->output.crop.h
1557                                         - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
1558                 break;
1559         case IPU_ROTATE_HORIZ_FLIP:
1560                 if (stripe & LEFT_STRIPE)
1561                         task->output.crop.pos.x =
1562                                         t->output.crop.pos.x + t->output.crop.w
1563                                         - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
1564                 else if (stripe & RIGHT_STRIPE)
1565                         task->output.crop.pos.x =
1566                                         t->output.crop.pos.x + t->output.crop.w
1567                                         - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
1568                 if (stripe & UP_STRIPE)
1569                         task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
1570                 else if (stripe & DOWN_STRIPE)
1571                         task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
1572                 break;
1573         case IPU_ROTATE_180:
1574                 if (stripe & LEFT_STRIPE)
1575                         task->output.crop.pos.x =
1576                                         t->output.crop.pos.x + t->output.crop.w
1577                                         - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
1578                 else if (stripe & RIGHT_STRIPE)
1579                         task->output.crop.pos.x =
1580                                         t->output.crop.pos.x + t->output.crop.w
1581                                         - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
1582                 if (stripe & UP_STRIPE)
1583                         task->output.crop.pos.y =
1584                                         t->output.crop.pos.y + t->output.crop.h
1585                                         - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
1586                 else if (stripe & DOWN_STRIPE)
1587                         task->output.crop.pos.y =
1588                                         t->output.crop.pos.y + t->output.crop.h
1589                                         - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
1590                 break;
1591         case IPU_ROTATE_90_RIGHT:
1592                 if (stripe & UP_STRIPE)
1593                         task->output.crop.pos.x =
1594                                         t->output.crop.pos.x + t->output.crop.w
1595                                         - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
1596                 else if (stripe & DOWN_STRIPE)
1597                         task->output.crop.pos.x =
1598                                         t->output.crop.pos.x + t->output.crop.w
1599                                         - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
1600                 if (stripe & LEFT_STRIPE)
1601                         task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
1602                 else if (stripe & RIGHT_STRIPE)
1603                         task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
1604                 break;
1605         case IPU_ROTATE_90_RIGHT_HFLIP:
1606                 if (stripe & UP_STRIPE)
1607                         task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
1608                 else if (stripe & DOWN_STRIPE)
1609                         task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
1610                 if (stripe & LEFT_STRIPE)
1611                         task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
1612                 else if (stripe & RIGHT_STRIPE)
1613                         task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
1614                 break;
1615         case IPU_ROTATE_90_RIGHT_VFLIP:
1616                 if (stripe & UP_STRIPE)
1617                         task->output.crop.pos.x =
1618                                         t->output.crop.pos.x + t->output.crop.w
1619                                         - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
1620                 else if (stripe & DOWN_STRIPE)
1621                         task->output.crop.pos.x =
1622                                         t->output.crop.pos.x + t->output.crop.w
1623                                         - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
1624                 if (stripe & LEFT_STRIPE)
1625                         task->output.crop.pos.y =
1626                                         t->output.crop.pos.y + t->output.crop.h
1627                                         - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
1628                 else if (stripe & RIGHT_STRIPE)
1629                         task->output.crop.pos.y =
1630                                         t->output.crop.pos.y + t->output.crop.h
1631                                         - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
1632                 break;
1633         case IPU_ROTATE_90_LEFT:
1634                 if (stripe & UP_STRIPE)
1635                         task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
1636                 else if (stripe & DOWN_STRIPE)
1637                         task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
1638                 if (stripe & LEFT_STRIPE)
1639                         task->output.crop.pos.y =
1640                                         t->output.crop.pos.y + t->output.crop.h
1641                                         - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
1642                 else if (stripe & RIGHT_STRIPE)
1643                         task->output.crop.pos.y =
1644                                         t->output.crop.pos.y + t->output.crop.h
1645                                         - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
1646                 break;
1647         default:
1648                 dev_err(t->dev, "ERR:should not be here\n");
1649                 break;
1650         }
1651
1652         ret = create_split_child_task(sp_task);
1653         if (ret < 0)
1654                 dev_err(t->dev, "ERR:create_split_child_task() ret:%d\n", ret);
1655         return ret;
1656 }
1657
1658 static int queue_split_task(struct ipu_task_entry *t,
1659                                 struct ipu_split_task *sp_task, uint32_t size)
1660 {
1661         int err[4];
1662         int ret = 0;
1663         int i, j;
1664         struct ipu_task_entry *tsk = NULL;
1665         struct mutex *lock = &t->split_lock;
1666
1667         dev_dbg(t->dev, "Split task 0x%p, no-0x%x, size:%d\n",
1668                          t, t->task_no, size);
1669         mutex_init(lock);
1670         init_waitqueue_head(&t->split_waitq);
1671         INIT_LIST_HEAD(&t->split_list);
1672         for (j = 0; j < size; j++) {
1673                 memset(&sp_task[j], 0, sizeof(*sp_task));
1674                 sp_task[j].parent_task = t;
1675                 sp_task[j].task_no = t->task_no;
1676         }
1677
1678         if (t->set.split_mode == RL_SPLIT) {
1679                 i = 0;
1680                 err[i] = create_split_task(RIGHT_STRIPE, &sp_task[i]);
1681                 if (err[i] < 0)
1682                         goto err_start;
1683                 i = 1;
1684                 err[i] = create_split_task(LEFT_STRIPE, &sp_task[i]);
1685         } else if (t->set.split_mode == UD_SPLIT) {
1686                 i = 0;
1687                 err[i] = create_split_task(DOWN_STRIPE, &sp_task[i]);
1688                 if (err[i] < 0)
1689                         goto err_start;
1690                 i = 1;
1691                 err[i] = create_split_task(UP_STRIPE, &sp_task[i]);
1692         } else {
1693                 i = 0;
1694                 err[i] = create_split_task(RIGHT_STRIPE | DOWN_STRIPE, &sp_task[i]);
1695                 if (err[i] < 0)
1696                         goto err_start;
1697                 i = 1;
1698                 err[i] = create_split_task(LEFT_STRIPE | DOWN_STRIPE, &sp_task[i]);
1699                 if (err[i] < 0)
1700                         goto err_start;
1701                 i = 2;
1702                 err[i] = create_split_task(RIGHT_STRIPE | UP_STRIPE, &sp_task[i]);
1703                 if (err[i] < 0)
1704                         goto err_start;
1705                 i = 3;
1706                 err[i] = create_split_task(LEFT_STRIPE | UP_STRIPE, &sp_task[i]);
1707         }
1708
1709 err_start:
1710         for (j = 0; j < (i + 1); j++) {
1711                 if (err[j] < 0) {
1712                         if (sp_task[j].child_task)
1713                                 dev_err(t->dev,
1714                                  "sp_task[%d],no-0x%x fail state:%d, queue err:%d.\n",
1715                                 j, sp_task[j].child_task->task_no,
1716                                 sp_task[j].child_task->state, err[j]);
1717                         goto err_exit;
1718                 }
1719                 dev_dbg(t->dev, "[0x%p] sp_task[%d], no-0x%x state:%s, queue ret:%d.\n",
1720                         sp_task[j].child_task, j, sp_task[j].child_task->task_no,
1721                         state_msg[sp_task[j].child_task->state].msg, err[j]);
1722         }
1723
1724         return ret;
1725
1726 err_exit:
1727         for (j = 0; j < (i + 1); j++) {
1728                 if (err[j] < 0 && !ret)
1729                         ret = err[j];
1730                 tsk = sp_task[j].child_task;
1731                 if (!tsk)
1732                         continue;
1733                 kfree(tsk);
1734                 memset(tsk, 0, sizeof(*tsk));
1735         }
1736         t->state = STATE_ERR;
1737         return ret;
1738
1739 }
1740
1741 static int init_tiled_buf(struct ipu_soc *ipu, struct ipu_task_entry *t,
1742                                 ipu_channel_t channel, uint32_t ch_type)
1743 {
1744         int ret = 0;
1745         int i;
1746         uint32_t ipu_fmt;
1747         dma_addr_t inbuf_base = 0;
1748         u32 field_size;
1749         struct vdoa_params param;
1750         struct vdoa_ipu_buf buf;
1751         struct ipu_soc *ipu_idx;
1752         u32 ipu_stride, obuf_size;
1753         u32 height, width;
1754         ipu_buffer_t type;
1755
1756         if ((IPU_PIX_FMT_YUYV != t->output.format) &&
1757                 (IPU_PIX_FMT_NV12 != t->output.format)) {
1758                 dev_err(t->dev, "ERR:[0x%d] output format\n", t->task_no);
1759                 return -EINVAL;
1760         }
1761
1762         memset(&param, 0, sizeof(param));
1763         /* init channel tiled bufs */
1764         if (deinterlace_3_field(t) &&
1765                 (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
1766                 field_size = tiled_filed_size(t);
1767                 if (INPUT_CHAN_VDI_P == ch_type) {
1768                         inbuf_base = t->input.paddr + field_size;
1769                         param.vfield_buf.prev_veba = inbuf_base + t->set.i_off;
1770                 } else if (INPUT_CHAN == ch_type) {
1771                         inbuf_base = t->input.paddr_n;
1772                         param.vfield_buf.cur_veba = inbuf_base + t->set.i_off;
1773                 } else if (INPUT_CHAN_VDI_N == ch_type) {
1774                         inbuf_base = t->input.paddr_n + field_size;
1775                         param.vfield_buf.next_veba = inbuf_base + t->set.i_off;
1776                 } else
1777                         return -EINVAL;
1778                 height = t->input.crop.h >> 1; /* field format for vdoa */
1779                 width = t->input.crop.w;
1780                 param.vfield_buf.vubo = t->set.i_uoff;
1781                 param.interlaced = 1;
1782                 param.scan_order = 1;
1783                 type = IPU_INPUT_BUFFER;
1784         } else if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) &&
1785                         (INPUT_CHAN == ch_type)) {
1786                 height = t->input.crop.h;
1787                 width = t->input.crop.w;
1788                 param.vframe_buf.veba = t->input.paddr + t->set.i_off;
1789                 param.vframe_buf.vubo = t->set.i_uoff;
1790                 type = IPU_INPUT_BUFFER;
1791         } else
1792                 return -EINVAL;
1793
1794         param.band_mode = (t->set.mode & VDOA_BAND_MODE) ? 1 : 0;
1795         if (param.band_mode && (t->set.band_lines != 3) &&
1796                  (t->set.band_lines != 4) && (t->set.band_lines != 5))
1797                 return -EINVAL;
1798         else if (param.band_mode)
1799                 param.band_lines = (1 << t->set.band_lines);
1800         for (i = 0; i < max_ipu_no; i++) {
1801                 ipu_idx = ipu_get_soc(i);
1802                 if (!IS_ERR(ipu_idx) && ipu_idx == ipu)
1803                         break;
1804         }
1805         if (t->set.task & VDOA_ONLY)
1806                 /* dummy, didn't need ipu res */
1807                 i = 0;
1808         if (max_ipu_no == i) {
1809                 dev_err(t->dev, "ERR:[0x%p] get ipu num\n", t);
1810                 return -EINVAL;
1811         }
1812
1813         param.ipu_num = i;
1814         param.vpu_stride = t->input.width;
1815         param.height = height;
1816         param.width = width;
1817         if (IPU_PIX_FMT_NV12 == t->output.format)
1818                 param.pfs = VDOA_PFS_NV12;
1819         else
1820                 param.pfs = VDOA_PFS_YUYV;
1821         ipu_fmt = (param.pfs == VDOA_PFS_YUYV) ? IPU_PIX_FMT_YUYV :
1822                                 IPU_PIX_FMT_NV12;
1823         ipu_stride = param.width * bytes_per_pixel(ipu_fmt);
1824         obuf_size = PAGE_ALIGN(param.width * param.height *
1825                                 fmt_to_bpp(ipu_fmt)/8);
1826         dev_dbg(t->dev, "band_mode:%d, band_lines:%d\n",
1827                         param.band_mode, param.band_lines);
1828         if (!param.band_mode) {
1829                 /* note: if only for tiled -> raster convert and
1830                    no other post-processing, we don't need alloc buf
1831                    and use output buffer directly.
1832                 */
1833                 if (t->set.task & VDOA_ONLY)
1834                         param.ieba0 = t->output.paddr;
1835                 else {
1836                         dev_err(t->dev, "ERR:[0x%d] vdoa task\n", t->task_no);
1837                         return -EINVAL;
1838                 }
1839         } else {
1840                 if (IPU_PIX_FMT_TILED_NV12F != t->input.format) {
1841                         dev_err(t->dev, "ERR [0x%d] vdoa task\n", t->task_no);
1842                         return -EINVAL;
1843                 }
1844         }
1845         ret = vdoa_setup(t->vdoa_handle, &param);
1846         if (ret)
1847                 goto done;
1848         vdoa_get_output_buf(t->vdoa_handle, &buf);
1849         if (t->set.task & VDOA_ONLY)
1850                 goto done;
1851
1852         ret = ipu_init_channel_buffer(ipu,
1853                         channel,
1854                         type,
1855                         ipu_fmt,
1856                         width,
1857                         height,
1858                         ipu_stride,
1859                         IPU_ROTATE_NONE,
1860                         buf.ieba0,
1861                         buf.ieba1,
1862                         0,
1863                         buf.iubo,
1864                         0);
1865         if (ret < 0) {
1866                 t->state = STATE_INIT_CHAN_BUF_FAIL;
1867                 goto done;
1868         }
1869
1870         if (param.band_mode) {
1871                 ret = ipu_set_channel_bandmode(ipu, channel,
1872                                 type, t->set.band_lines);
1873                 if (ret < 0) {
1874                         t->state = STATE_INIT_CHAN_BAND_FAIL;
1875                         goto done;
1876                 }
1877         }
1878 done:
1879         return ret;
1880 }
1881
1882 static int init_tiled_ch_bufs(struct ipu_soc *ipu, struct ipu_task_entry *t)
1883 {
1884         int ret = 0;
1885
1886         if (IPU_PIX_FMT_TILED_NV12 == t->input.format) {
1887                 ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
1888                 CHECK_RETCODE(ret < 0, "init tiled_ch", t->state, done, ret);
1889         } else if (IPU_PIX_FMT_TILED_NV12F == t->input.format) {
1890                 ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
1891                 CHECK_RETCODE(ret < 0, "init tiled_ch-c", t->state, done, ret);
1892                 ret = init_tiled_buf(ipu, t, t->set.vdi_ic_p_chan,
1893                                         INPUT_CHAN_VDI_P);
1894                 CHECK_RETCODE(ret < 0, "init tiled_ch-p", t->state, done, ret);
1895                 ret = init_tiled_buf(ipu, t, t->set.vdi_ic_n_chan,
1896                                         INPUT_CHAN_VDI_N);
1897                 CHECK_RETCODE(ret < 0, "init tiled_ch-n", t->state, done, ret);
1898         } else {
1899                 ret = -EINVAL;
1900                 dev_err(t->dev, "ERR[no-0x%x] invalid fmt:0x%x!\n",
1901                         t->task_no, t->input.format);
1902         }
1903
1904 done:
1905         return ret;
1906 }
1907
1908 static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
1909 {
1910         int ret = 0;
1911         ipu_channel_params_t params;
1912         dma_addr_t inbuf = 0, ovbuf = 0, ov_alp_buf = 0;
1913         dma_addr_t inbuf_p = 0, inbuf_n = 0;
1914         dma_addr_t outbuf = 0;
1915         int out_uoff = 0, out_voff = 0, out_rot;
1916         int out_w = 0, out_h = 0, out_stride;
1917         int out_fmt;
1918         u32 vdi_frame_idx = 0;
1919
1920         memset(&params, 0, sizeof(params));
1921
1922         /* is it need link a rot channel */
1923         if (ic_and_rot(t->set.mode)) {
1924                 outbuf = t->set.r_paddr;
1925                 out_w = t->set.r_width;
1926                 out_h = t->set.r_height;
1927                 out_stride = t->set.r_stride;
1928                 out_fmt = t->set.r_fmt;
1929                 out_uoff = 0;
1930                 out_voff = 0;
1931                 out_rot = IPU_ROTATE_NONE;
1932         } else {
1933                 outbuf = t->output.paddr + t->set.o_off;
1934                 out_w = t->output.crop.w;
1935                 out_h = t->output.crop.h;
1936                 out_stride = t->set.ostride;
1937                 out_fmt = t->output.format;
1938                 out_uoff = t->set.o_uoff;
1939                 out_voff = t->set.o_voff;
1940                 out_rot = t->output.rotate;
1941         }
1942
1943         /* settings */
1944         params.mem_prp_vf_mem.in_width = t->input.crop.w;
1945         params.mem_prp_vf_mem.out_width = out_w;
1946         params.mem_prp_vf_mem.in_height = t->input.crop.h;
1947         params.mem_prp_vf_mem.out_height = out_h;
1948         params.mem_prp_vf_mem.in_pixel_fmt = t->input.format;
1949         params.mem_prp_vf_mem.out_pixel_fmt = out_fmt;
1950         params.mem_prp_vf_mem.motion_sel = t->input.deinterlace.motion;
1951
1952         params.mem_prp_vf_mem.outh_resize_ratio =
1953                         t->set.sp_setting.outh_resize_ratio;
1954         params.mem_prp_vf_mem.outv_resize_ratio =
1955                         t->set.sp_setting.outv_resize_ratio;
1956
1957         if (t->overlay_en) {
1958                 params.mem_prp_vf_mem.in_g_pixel_fmt = t->overlay.format;
1959                 params.mem_prp_vf_mem.graphics_combine_en = 1;
1960                 if (t->overlay.alpha.mode == IPU_ALPHA_MODE_GLOBAL)
1961                         params.mem_prp_vf_mem.global_alpha_en = 1;
1962                 else if (t->overlay.alpha.loc_alp_paddr)
1963                         params.mem_prp_vf_mem.alpha_chan_en = 1;
1964                 /* otherwise, alpha bending per pixel is used. */
1965                 params.mem_prp_vf_mem.alpha = t->overlay.alpha.gvalue;
1966                 if (t->overlay.colorkey.enable) {
1967                         params.mem_prp_vf_mem.key_color_en = 1;
1968                         params.mem_prp_vf_mem.key_color = t->overlay.colorkey.value;
1969                 }
1970         }
1971
1972         if (t->input.deinterlace.enable) {
1973                 if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_FIELD_MASK)
1974                         params.mem_prp_vf_mem.field_fmt =
1975                                 IPU_DEINTERLACE_FIELD_BOTTOM;
1976                 else
1977                         params.mem_prp_vf_mem.field_fmt =
1978                                 IPU_DEINTERLACE_FIELD_TOP;
1979
1980                 if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN)
1981                         vdi_frame_idx = t->input.deinterlace.field_fmt &
1982                                                 IPU_DEINTERLACE_RATE_FRAME1;
1983         }
1984
1985         if (t->set.mode & VDOA_MODE)
1986                 ipu->vdoa_en = 1;
1987
1988         /* init channels */
1989         if (!(t->set.task & VDOA_ONLY)) {
1990                 ret = ipu_init_channel(ipu, t->set.ic_chan, &params);
1991                 if (ret < 0) {
1992                         t->state = STATE_INIT_CHAN_FAIL;
1993                         goto done;
1994                 }
1995         }
1996
1997         if (deinterlace_3_field(t)) {
1998                 ret = ipu_init_channel(ipu, t->set.vdi_ic_p_chan, &params);
1999                 if (ret < 0) {
2000                         t->state = STATE_INIT_CHAN_FAIL;
2001                         goto done;
2002                 }
2003                 ret = ipu_init_channel(ipu, t->set.vdi_ic_n_chan, &params);
2004                 if (ret < 0) {
2005                         t->state = STATE_INIT_CHAN_FAIL;
2006                         goto done;
2007                 }
2008         }
2009
2010         /* init channel bufs */
2011         if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
2012                 (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
2013                 ret = init_tiled_ch_bufs(ipu, t);
2014                 if (ret < 0)
2015                         goto done;
2016         } else {
2017                 if ((deinterlace_3_field(t)) &&
2018                         (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
2019                         if (params.mem_prp_vf_mem.field_fmt ==
2020                                 IPU_DEINTERLACE_FIELD_TOP) {
2021                                 if (vdi_frame_idx) {
2022                                         inbuf_p = t->input.paddr + t->set.istride +
2023                                                         t->set.i_off;
2024                                         inbuf = t->input.paddr_n + t->set.i_off;
2025                                         inbuf_n = t->input.paddr_n + t->set.istride +
2026                                                         t->set.i_off;
2027                                         params.mem_prp_vf_mem.field_fmt =
2028                                                 IPU_DEINTERLACE_FIELD_BOTTOM;
2029                                 } else {
2030                                         inbuf_p = t->input.paddr + t->set.i_off;
2031                                         inbuf = t->input.paddr + t->set.istride + t->set.i_off;
2032                                         inbuf_n = t->input.paddr_n + t->set.i_off;
2033                                 }
2034                         } else {
2035                                 if (vdi_frame_idx) {
2036                                         inbuf_p = t->input.paddr + t->set.i_off;
2037                                         inbuf = t->input.paddr_n + t->set.istride + t->set.i_off;
2038                                         inbuf_n = t->input.paddr_n + t->set.i_off;
2039                                         params.mem_prp_vf_mem.field_fmt =
2040                                                 IPU_DEINTERLACE_FIELD_TOP;
2041                                 } else {
2042                                         inbuf_p = t->input.paddr + t->set.istride +
2043                                                         t->set.i_off;
2044                                         inbuf = t->input.paddr + t->set.i_off;
2045                                         inbuf_n = t->input.paddr_n + t->set.istride +
2046                                                         t->set.i_off;
2047                                 }
2048                         }
2049                 } else {
2050                         if (t->input.deinterlace.enable) {
2051                                 if (params.mem_prp_vf_mem.field_fmt ==
2052                                         IPU_DEINTERLACE_FIELD_TOP) {
2053                                         if (vdi_frame_idx) {
2054                                                 inbuf = t->input.paddr + t->set.istride + t->set.i_off;
2055                                                 params.mem_prp_vf_mem.field_fmt =
2056                                                         IPU_DEINTERLACE_FIELD_BOTTOM;
2057                                         } else
2058                                                 inbuf = t->input.paddr + t->set.i_off;
2059                                 } else {
2060                                         if (vdi_frame_idx) {
2061                                                 inbuf = t->input.paddr + t->set.i_off;
2062                                                 params.mem_prp_vf_mem.field_fmt =
2063                                                         IPU_DEINTERLACE_FIELD_TOP;
2064                                         } else
2065                                                 inbuf = t->input.paddr + t->set.istride + t->set.i_off;
2066                                 }
2067                         } else
2068                                 inbuf = t->input.paddr + t->set.i_off;
2069                 }
2070
2071                 if (t->overlay_en)
2072                         ovbuf = t->overlay.paddr + t->set.ov_off;
2073         }
2074         if (t->overlay_en && (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL))
2075                 ov_alp_buf = t->overlay.alpha.loc_alp_paddr
2076                         + t->set.ov_alpha_off;
2077
2078         if ((IPU_PIX_FMT_TILED_NV12 != t->input.format) &&
2079                 (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
2080                 ret = ipu_init_channel_buffer(ipu,
2081                                 t->set.ic_chan,
2082                                 IPU_INPUT_BUFFER,
2083                                 t->input.format,
2084                                 t->input.crop.w,
2085                                 t->input.crop.h,
2086                                 t->set.istride,
2087                                 IPU_ROTATE_NONE,
2088                                 inbuf,
2089                                 0,
2090                                 0,
2091                                 t->set.i_uoff,
2092                                 t->set.i_voff);
2093                 if (ret < 0) {
2094                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2095                         goto done;
2096                 }
2097         }
2098         if (deinterlace_3_field(t) &&
2099                 (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
2100                 ret = ipu_init_channel_buffer(ipu,
2101                                 t->set.vdi_ic_p_chan,
2102                                 IPU_INPUT_BUFFER,
2103                                 t->input.format,
2104                                 t->input.crop.w,
2105                                 t->input.crop.h,
2106                                 t->set.istride,
2107                                 IPU_ROTATE_NONE,
2108                                 inbuf_p,
2109                                 0,
2110                                 0,
2111                                 t->set.i_uoff,
2112                                 t->set.i_voff);
2113                 if (ret < 0) {
2114                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2115                         goto done;
2116                 }
2117
2118                 ret = ipu_init_channel_buffer(ipu,
2119                                 t->set.vdi_ic_n_chan,
2120                                 IPU_INPUT_BUFFER,
2121                                 t->input.format,
2122                                 t->input.crop.w,
2123                                 t->input.crop.h,
2124                                 t->set.istride,
2125                                 IPU_ROTATE_NONE,
2126                                 inbuf_n,
2127                                 0,
2128                                 0,
2129                                 t->set.i_uoff,
2130                                 t->set.i_voff);
2131                 if (ret < 0) {
2132                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2133                         goto done;
2134                 }
2135         }
2136
2137         if (t->overlay_en) {
2138                 ret = ipu_init_channel_buffer(ipu,
2139                                 t->set.ic_chan,
2140                                 IPU_GRAPH_IN_BUFFER,
2141                                 t->overlay.format,
2142                                 t->overlay.crop.w,
2143                                 t->overlay.crop.h,
2144                                 t->set.ovstride,
2145                                 IPU_ROTATE_NONE,
2146                                 ovbuf,
2147                                 0,
2148                                 0,
2149                                 t->set.ov_uoff,
2150                                 t->set.ov_voff);
2151                 if (ret < 0) {
2152                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2153                         goto done;
2154                 }
2155         }
2156
2157         if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
2158                 ret = ipu_init_channel_buffer(ipu,
2159                                 t->set.ic_chan,
2160                                 IPU_ALPHA_IN_BUFFER,
2161                                 IPU_PIX_FMT_GENERIC,
2162                                 t->overlay.crop.w,
2163                                 t->overlay.crop.h,
2164                                 t->set.ov_alpha_stride,
2165                                 IPU_ROTATE_NONE,
2166                                 ov_alp_buf,
2167                                 0,
2168                                 0,
2169                                 0, 0);
2170                 if (ret < 0) {
2171                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2172                         goto done;
2173                 }
2174         }
2175
2176         if (!(t->set.task & VDOA_ONLY)) {
2177                 ret = ipu_init_channel_buffer(ipu,
2178                                 t->set.ic_chan,
2179                                 IPU_OUTPUT_BUFFER,
2180                                 out_fmt,
2181                                 out_w,
2182                                 out_h,
2183                                 out_stride,
2184                                 out_rot,
2185                                 outbuf,
2186                                 0,
2187                                 0,
2188                                 out_uoff,
2189                                 out_voff);
2190                 if (ret < 0) {
2191                         t->state = STATE_INIT_CHAN_BUF_FAIL;
2192                         goto done;
2193                 }
2194         }
2195
2196         if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
2197                 ret = ipu_link_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
2198                 CHECK_RETCODE(ret < 0, "ipu_link_ch vdoa_ic",
2199                                 STATE_LINK_CHAN_FAIL, done, ret);
2200         }
2201
2202 done:
2203         return ret;
2204 }
2205
2206 static void uninit_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
2207 {
2208         int ret;
2209
2210         if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
2211                 ret = ipu_unlink_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
2212                 CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch vdoa_ic",
2213                                 STATE_UNLINK_CHAN_FAIL, ret);
2214         }
2215         ipu_uninit_channel(ipu, t->set.ic_chan);
2216         if (deinterlace_3_field(t)) {
2217                 ipu_uninit_channel(ipu, t->set.vdi_ic_p_chan);
2218                 ipu_uninit_channel(ipu, t->set.vdi_ic_n_chan);
2219         }
2220 }
2221
2222 static int init_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
2223 {
2224         int ret = 0;
2225         dma_addr_t inbuf = 0, outbuf = 0;
2226         int in_uoff = 0, in_voff = 0;
2227         int in_fmt, in_width, in_height, in_stride;
2228
2229         /* init channel */
2230         ret = ipu_init_channel(ipu, t->set.rot_chan, NULL);
2231         if (ret < 0) {
2232                 t->state = STATE_INIT_CHAN_FAIL;
2233                 goto done;
2234         }
2235
2236         /* init channel buf */
2237         /* is it need link to a ic channel */
2238         if (ic_and_rot(t->set.mode)) {
2239                 in_fmt = t->set.r_fmt;
2240                 in_width = t->set.r_width;
2241                 in_height = t->set.r_height;
2242                 in_stride = t->set.r_stride;
2243                 inbuf = t->set.r_paddr;
2244                 in_uoff = 0;
2245                 in_voff = 0;
2246         } else {
2247                 in_fmt = t->input.format;
2248                 in_width = t->input.crop.w;
2249                 in_height = t->input.crop.h;
2250                 in_stride = t->set.istride;
2251                 inbuf = t->input.paddr + t->set.i_off;
2252                 in_uoff = t->set.i_uoff;
2253                 in_voff = t->set.i_voff;
2254         }
2255         outbuf = t->output.paddr + t->set.o_off;
2256
2257         ret = ipu_init_channel_buffer(ipu,
2258                         t->set.rot_chan,
2259                         IPU_INPUT_BUFFER,
2260                         in_fmt,
2261                         in_width,
2262                         in_height,
2263                         in_stride,
2264                         t->output.rotate,
2265                         inbuf,
2266                         0,
2267                         0,
2268                         in_uoff,
2269                         in_voff);
2270         if (ret < 0) {
2271                 t->state = STATE_INIT_CHAN_BUF_FAIL;
2272                 goto done;
2273         }
2274
2275         ret = ipu_init_channel_buffer(ipu,
2276                         t->set.rot_chan,
2277                         IPU_OUTPUT_BUFFER,
2278                         t->output.format,
2279                         t->output.crop.w,
2280                         t->output.crop.h,
2281                         t->set.ostride,
2282                         IPU_ROTATE_NONE,
2283                         outbuf,
2284                         0,
2285                         0,
2286                         t->set.o_uoff,
2287                         t->set.o_voff);
2288         if (ret < 0) {
2289                 t->state = STATE_INIT_CHAN_BUF_FAIL;
2290                 goto done;
2291         }
2292
2293 done:
2294         return ret;
2295 }
2296
2297 static void uninit_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
2298 {
2299         ipu_uninit_channel(ipu, t->set.rot_chan);
2300 }
2301
2302 static int get_irq(struct ipu_task_entry *t)
2303 {
2304         int irq;
2305         ipu_channel_t chan;
2306
2307         if (only_ic(t->set.mode))
2308                 chan = t->set.ic_chan;
2309         else
2310                 chan = t->set.rot_chan;
2311
2312         switch (chan) {
2313         case MEM_ROT_VF_MEM:
2314                 irq = IPU_IRQ_PRP_VF_ROT_OUT_EOF;
2315                 break;
2316         case MEM_ROT_PP_MEM:
2317                 irq = IPU_IRQ_PP_ROT_OUT_EOF;
2318                 break;
2319         case MEM_VDI_PRP_VF_MEM:
2320         case MEM_PRP_VF_MEM:
2321                 irq = IPU_IRQ_PRP_VF_OUT_EOF;
2322                 break;
2323         case MEM_PP_MEM:
2324                 irq = IPU_IRQ_PP_OUT_EOF;
2325                 break;
2326         case MEM_VDI_MEM:
2327                 irq = IPU_IRQ_VDIC_OUT_EOF;
2328                 break;
2329         default:
2330                 irq = -EINVAL;
2331         }
2332
2333         return irq;
2334 }
2335
2336 static irqreturn_t task_irq_handler(int irq, void *dev_id)
2337 {
2338         struct ipu_task_entry *prev_tsk = dev_id;
2339
2340         CHECK_PERF(&prev_tsk->ts_inirq);
2341         complete(&prev_tsk->irq_comp);
2342         dev_dbg(prev_tsk->dev, "[0x%p] no-0x%x in-irq!",
2343                                  prev_tsk, prev_tsk->task_no);
2344
2345         return IRQ_HANDLED;
2346 }
2347
2348 /* Fix deinterlace up&down split mode medium line */
2349 static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
2350 {
2351         u32 vdi_size;
2352         u32 vdi_save_lines;
2353         u32 stripe_mode;
2354         u32 task_no;
2355         u32 i, offset_addr;
2356         unsigned char  *base_off;
2357         struct ipu_task_entry *parent = t->parent;
2358
2359         if (!parent) {
2360                 dev_err(t->dev, "ERR[0x%x]invalid parent\n", t->task_no);
2361                 return;
2362         }
2363         stripe_mode = t->task_no & 0xf;
2364         task_no = t->task_no >> 4;
2365
2366         base_off = (char *) __va(t->output.paddr);
2367         if (base_off == NULL) {
2368                 dev_err(t->dev, "ERR[0x%p]Falied get vitual address\n", t);
2369                 return;
2370         }
2371
2372         vdi_save_lines = (t->output.crop.h - t->set.sp_setting.ud_split_line)/2;
2373         vdi_size = vdi_save_lines * t->output.crop.w * 2;
2374
2375         if (vdi_save_lines <= 0) {
2376                 dev_err(t->dev, "[0x%p] vdi_save_line error\n", (void *)t);
2377                 return;
2378         }
2379
2380         /*check vditmpbuf buffer have alloced or buffer size is changed */
2381         if ((vdi_save_lines != parent->old_save_lines) ||
2382                 (vdi_size != parent->old_size)) {
2383                 if (parent->vditmpbuf[0] != NULL)
2384                         kfree(parent->vditmpbuf[0]);
2385                 if (parent->vditmpbuf[1] != NULL)
2386                         kfree(parent->vditmpbuf[1]);
2387
2388                 parent->vditmpbuf[0] = kmalloc(vdi_size, GFP_KERNEL);
2389                 if (parent->vditmpbuf[0] == NULL) {
2390                         dev_err(t->dev,
2391                                 "[0x%p]Falied Alloc vditmpbuf[0]\n", (void *)t);
2392                         return;
2393                 }
2394                 memset(parent->vditmpbuf[0], 0, vdi_size);
2395
2396                 parent->vditmpbuf[1] = kmalloc(vdi_size, GFP_KERNEL);
2397                 if (parent->vditmpbuf[1] == NULL) {
2398                         dev_err(t->dev,
2399                                 "[0x%p]Falied Alloc vditmpbuf[1]\n", (void *)t);
2400                         return;
2401                 }
2402                 memset(parent->vditmpbuf[1], 0, vdi_size);
2403
2404                 parent->old_save_lines = vdi_save_lines;
2405                 parent->old_size = vdi_size;
2406         }
2407
2408         /* UP stripe or UP&LEFT stripe */
2409         if ((stripe_mode == UP_STRIPE) ||
2410                         (stripe_mode == (UP_STRIPE | LEFT_STRIPE))) {
2411                 if (!parent->buf0filled) {
2412                         offset_addr = t->set.o_off +
2413                                 t->set.sp_setting.ud_split_line*t->set.ostride;
2414                         dmac_flush_range(base_off + offset_addr,
2415                                         base_off + offset_addr + vdi_size);
2416                         outer_flush_range(t->output.paddr + offset_addr,
2417                                 t->output.paddr + offset_addr + vdi_size);
2418
2419                         for (i = 0; i < vdi_save_lines; i++)
2420                                 memcpy(parent->vditmpbuf[0] + i*t->output.crop.w*2,
2421                                         base_off + offset_addr +
2422                                         i*t->set.ostride, t->output.crop.w*2);
2423                         parent->buf0filled = true;
2424                 } else {
2425                         offset_addr = t->set.o_off + (t->output.crop.h -
2426                                         vdi_save_lines) * t->set.ostride;
2427                         for (i = 0; i < vdi_save_lines; i++)
2428                                 memcpy(base_off + offset_addr + i*t->set.ostride,
2429                                                 parent->vditmpbuf[0] + i*t->output.crop.w*2,
2430                                                 t->output.crop.w*2);
2431
2432                         dmac_flush_range(base_off + offset_addr,
2433                                         base_off + offset_addr + i*t->set.ostride);
2434                         outer_flush_range(t->output.paddr + offset_addr,
2435                                         t->output.paddr + offset_addr + i*t->set.ostride);
2436                         parent->buf0filled = false;
2437                 }
2438         }
2439         /*Down stripe or Down&Left stripe*/
2440         else if ((stripe_mode == DOWN_STRIPE) ||
2441                         (stripe_mode == (DOWN_STRIPE | LEFT_STRIPE))) {
2442                 if (!parent->buf0filled) {
2443                         offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
2444                         dmac_flush_range(base_off + offset_addr,
2445                                         base_off + offset_addr + vdi_size);
2446                         outer_flush_range(t->output.paddr + offset_addr,
2447                                         t->output.paddr + offset_addr + vdi_size);
2448
2449                         for (i = 0; i < vdi_save_lines; i++)
2450                                 memcpy(parent->vditmpbuf[0] + i*t->output.crop.w*2,
2451                                                 base_off + offset_addr + i*t->set.ostride,
2452                                                 t->output.crop.w*2);
2453                         parent->buf0filled = true;
2454                 } else {
2455                         offset_addr = t->set.o_off;
2456                         for (i = 0; i < vdi_save_lines; i++)
2457                                 memcpy(base_off + offset_addr + i*t->set.ostride,
2458                                                 parent->vditmpbuf[0] + i*t->output.crop.w*2,
2459                                                 t->output.crop.w*2);
2460
2461                         dmac_flush_range(base_off + offset_addr,
2462                                         base_off + offset_addr + i*t->set.ostride);
2463                         outer_flush_range(t->output.paddr + offset_addr,
2464                                         t->output.paddr + offset_addr + i*t->set.ostride);
2465                         parent->buf0filled = false;
2466                 }
2467         }
2468         /*Up&Right stripe*/
2469         else if (stripe_mode == (UP_STRIPE | RIGHT_STRIPE)) {
2470                 if (!parent->buf1filled) {
2471                         offset_addr = t->set.o_off +
2472                                 t->set.sp_setting.ud_split_line*t->set.ostride;
2473                         dmac_flush_range(base_off + offset_addr,
2474                                         base_off + offset_addr + vdi_size);
2475                         outer_flush_range(t->output.paddr + offset_addr,
2476                                         t->output.paddr + offset_addr + vdi_size);
2477
2478                         for (i = 0; i < vdi_save_lines; i++)
2479                                 memcpy(parent->vditmpbuf[1] + i*t->output.crop.w*2,
2480                                                 base_off + offset_addr + i*t->set.ostride,
2481                                                 t->output.crop.w*2);
2482                         parent->buf1filled = true;
2483                 } else {
2484                         offset_addr = t->set.o_off +
2485                                 (t->output.crop.h - vdi_save_lines)*t->set.ostride;
2486                         for (i = 0; i < vdi_save_lines; i++)
2487                                 memcpy(base_off + offset_addr + i*t->set.ostride,
2488                                                 parent->vditmpbuf[1] + i*t->output.crop.w*2,
2489                                                 t->output.crop.w*2);
2490
2491                         dmac_flush_range(base_off + offset_addr,
2492                                         base_off + offset_addr + i*t->set.ostride);
2493                         outer_flush_range(t->output.paddr + offset_addr,
2494                                         t->output.paddr + offset_addr + i*t->set.ostride);
2495                         parent->buf1filled = false;
2496                 }
2497         }
2498         /*Down stripe or Down&Right stript*/
2499         else if (stripe_mode == (DOWN_STRIPE | RIGHT_STRIPE)) {
2500                 if (!parent->buf1filled) {
2501                         offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
2502                         dmac_flush_range(base_off + offset_addr,
2503                                         base_off + offset_addr + vdi_save_lines*t->set.ostride);
2504                         outer_flush_range(t->output.paddr + offset_addr,
2505                                         t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
2506
2507                         for (i = 0; i < vdi_save_lines; i++)
2508                                 memcpy(parent->vditmpbuf[1] + i*t->output.crop.w*2,
2509                                                 base_off + offset_addr + i*t->set.ostride,
2510                                                 t->output.crop.w*2);
2511                         parent->buf1filled = true;
2512                 } else {
2513                         offset_addr = t->set.o_off;
2514                         for (i = 0; i < vdi_save_lines; i++)
2515                                 memcpy(base_off + offset_addr + i*t->set.ostride,
2516                                                 parent->vditmpbuf[1] + i*t->output.crop.w*2,
2517                                                 t->output.crop.w*2);
2518
2519                         dmac_flush_range(base_off + offset_addr,
2520                                         base_off + offset_addr + vdi_save_lines*t->set.ostride);
2521                         outer_flush_range(t->output.paddr + offset_addr,
2522                                         t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
2523                         parent->buf1filled = false;
2524                 }
2525         }
2526 }
2527
2528 static void do_task_release(struct ipu_task_entry *t, int fail)
2529 {
2530         int ret;
2531         struct ipu_soc *ipu = t->ipu;
2532
2533         if (t->input.deinterlace.enable && !fail &&
2534                         (t->task_no & (UP_STRIPE | DOWN_STRIPE)))
2535                 vdi_split_process(ipu, t);
2536
2537         ipu_free_irq(ipu, t->irq, t);
2538
2539         if (t->vdoa_dma.vaddr)
2540                 dma_free_coherent(t->dev,
2541                         t->vdoa_dma.size,
2542                         t->vdoa_dma.vaddr,
2543                         t->vdoa_dma.paddr);
2544
2545         if (only_ic(t->set.mode)) {
2546                 ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
2547                 CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic",
2548                                 STATE_DISABLE_CHAN_FAIL, ret);
2549                 if (deinterlace_3_field(t)) {
2550                         ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
2551                                                         true);
2552                         CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_p",
2553                                         STATE_DISABLE_CHAN_FAIL, ret);
2554                         ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
2555                                                         true);
2556                         CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_n",
2557                                         STATE_DISABLE_CHAN_FAIL, ret);
2558                 }
2559         } else if (only_rot(t->set.mode)) {
2560                 ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
2561                 CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_rot",
2562                                 STATE_DISABLE_CHAN_FAIL, ret);
2563         } else if (ic_and_rot(t->set.mode)) {
2564                 ret = ipu_unlink_channels(ipu, t->set.ic_chan, t->set.rot_chan);
2565                 CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch",
2566                                 STATE_UNLINK_CHAN_FAIL, ret);
2567                 ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
2568                 CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-rot",
2569                                 STATE_DISABLE_CHAN_FAIL, ret);
2570                 ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
2571                 CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-ic",
2572                                 STATE_DISABLE_CHAN_FAIL, ret);
2573                 if (deinterlace_3_field(t)) {
2574                         ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
2575                                                         true);
2576                         CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-p",
2577                                         STATE_DISABLE_CHAN_FAIL, ret);
2578                         ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
2579                                                         true);
2580                         CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-n",
2581                                         STATE_DISABLE_CHAN_FAIL, ret);
2582                 }
2583         }
2584
2585         if (only_ic(t->set.mode))
2586                 uninit_ic(ipu, t);
2587         else if (only_rot(t->set.mode))
2588                 uninit_rot(ipu, t);
2589         else if (ic_and_rot(t->set.mode)) {
2590                 uninit_ic(ipu, t);
2591                 uninit_rot(ipu, t);
2592         }
2593
2594         t->state = STATE_OK;
2595         CHECK_PERF(&t->ts_rel);
2596         return;
2597 }
2598
2599 static void do_task_vdoa_only(struct ipu_task_entry *t)
2600 {
2601         int ret;
2602
2603         ret = init_tiled_ch_bufs(NULL, t);
2604         CHECK_RETCODE(ret < 0, "do_vdoa_only", STATE_ERR, out, ret);
2605         ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
2606         vdoa_stop(t->vdoa_handle);
2607         CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_only",
2608                         STATE_VDOA_IRQ_TIMEOUT, out, ret);
2609
2610         t->state = STATE_OK;
2611 out:
2612         return;
2613 }
2614
2615 static void do_task(struct ipu_task_entry *t)
2616 {
2617         int r_size;
2618         int irq;
2619         int ret;
2620         uint32_t busy;
2621         struct ipu_soc *ipu = t->ipu;
2622
2623         CHECK_PERF(&t->ts_dotask);
2624
2625         if (!ipu) {
2626                 t->state = STATE_NO_IPU;
2627                 return;
2628         }
2629
2630         init_completion(&t->irq_comp);
2631         dev_dbg(ipu->dev, "[0x%p]Do task no:0x%x: id %d\n", (void *)t,
2632                  t->task_no, t->task_id);
2633         dump_task_info(t);
2634
2635         if (t->set.task & IC_PP) {
2636                 t->set.ic_chan = MEM_PP_MEM;
2637                 dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PP_MEM\n", (void *)t);
2638         } else if (t->set.task & IC_VF) {
2639                 t->set.ic_chan = MEM_PRP_VF_MEM;
2640                 dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PRP_VF_MEM\n", (void *)t);
2641         } else if (t->set.task & VDI_VF) {
2642                 if (t->set.mode & VDOA_BAND_MODE) {
2643                         t->set.ic_chan = MEM_VDI_MEM;
2644                         if (deinterlace_3_field(t)) {
2645                                 t->set.vdi_ic_p_chan = MEM_VDI_MEM_P;
2646                                 t->set.vdi_ic_n_chan = MEM_VDI_MEM_N;
2647                         }
2648                         dev_dbg(ipu->dev, "[0x%p]ic ch MEM_VDI_MEM\n",
2649                                          (void *)t);
2650                 } else {
2651                         t->set.ic_chan = MEM_VDI_PRP_VF_MEM;
2652                         if (deinterlace_3_field(t)) {
2653                                 t->set.vdi_ic_p_chan = MEM_VDI_PRP_VF_MEM_P;
2654                                 t->set.vdi_ic_n_chan = MEM_VDI_PRP_VF_MEM_N;
2655                         }
2656                         dev_dbg(ipu->dev,
2657                                 "[0x%p]ic ch MEM_VDI_PRP_VF_MEM\n", t);
2658                 }
2659         }
2660
2661         if (t->set.task & ROT_PP) {
2662                 t->set.rot_chan = MEM_ROT_PP_MEM;
2663                 dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_PP_MEM\n", (void *)t);
2664         } else if (t->set.task & ROT_VF) {
2665                 t->set.rot_chan = MEM_ROT_VF_MEM;
2666                 dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_VF_MEM\n", (void *)t);
2667         }
2668
2669         if (t->task_id == IPU_TASK_ID_VF)
2670                 busy = ic_vf_pp_is_busy(ipu, true);
2671         else if (t->task_id == IPU_TASK_ID_PP)
2672                 busy = ic_vf_pp_is_busy(ipu, false);
2673         else {
2674                 dev_err(ipu->dev, "ERR[no:0x%x]ipu task_id:%d invalid!\n",
2675                                 t->task_no, t->task_id);
2676                 return;
2677         }
2678         if (busy) {
2679                 dev_err(ipu->dev, "ERR[0x%p-no:0x%x]ipu task_id:%d busy!\n",
2680                                 (void *)t, t->task_no, t->task_id);
2681                 t->state = STATE_IPU_BUSY;
2682                 return;
2683         }
2684
2685         irq = get_irq(t);
2686         if (irq < 0) {
2687                 t->state = STATE_NO_IRQ;
2688                 return;
2689         }
2690         t->irq = irq;
2691
2692         /* channel setup */
2693         if (only_ic(t->set.mode)) {
2694                 dev_dbg(t->dev, "[0x%p]only ic mode\n", (void *)t);
2695                 ret = init_ic(ipu, t);
2696                 CHECK_RETCODE(ret < 0, "init_ic only_ic",
2697                                 t->state, chan_setup, ret);
2698         } else if (only_rot(t->set.mode)) {
2699                 dev_dbg(t->dev, "[0x%p]only rot mode\n", (void *)t);
2700                 ret = init_rot(ipu, t);
2701                 CHECK_RETCODE(ret < 0, "init_rot only_rot",
2702                                 t->state, chan_setup, ret);
2703         } else if (ic_and_rot(t->set.mode)) {
2704                 int rot_idx = (t->task_id == IPU_TASK_ID_VF) ? 0 : 1;
2705
2706                 dev_dbg(t->dev, "[0x%p]ic + rot mode\n", (void *)t);
2707                 t->set.r_fmt = t->output.format;
2708                 if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
2709                         t->set.r_width = t->output.crop.h;
2710                         t->set.r_height = t->output.crop.w;
2711                 } else {
2712                         t->set.r_width = t->output.crop.w;
2713                         t->set.r_height = t->output.crop.h;
2714                 }
2715                 t->set.r_stride = t->set.r_width *
2716                         bytes_per_pixel(t->set.r_fmt);
2717                 r_size = PAGE_ALIGN(t->set.r_width * t->set.r_height
2718                         * fmt_to_bpp(t->set.r_fmt)/8);
2719
2720                 if (r_size > ipu->rot_dma[rot_idx].size) {
2721                         dev_dbg(t->dev, "[0x%p]realloc rot buffer\n", (void *)t);
2722
2723                         if (ipu->rot_dma[rot_idx].vaddr)
2724                                 dma_free_coherent(t->dev,
2725                                         ipu->rot_dma[rot_idx].size,
2726                                         ipu->rot_dma[rot_idx].vaddr,
2727                                         ipu->rot_dma[rot_idx].paddr);
2728
2729                         ipu->rot_dma[rot_idx].size = r_size;
2730                         ipu->rot_dma[rot_idx].vaddr = dma_alloc_coherent(t->dev,
2731                                                 r_size,
2732                                                 &ipu->rot_dma[rot_idx].paddr,
2733                                                 GFP_DMA | GFP_KERNEL);
2734                         CHECK_RETCODE(ipu->rot_dma[rot_idx].vaddr == NULL,
2735                                         "ic_and_rot", STATE_SYS_NO_MEM,
2736                                         chan_setup, -ENOMEM);
2737                 }
2738                 t->set.r_paddr = ipu->rot_dma[rot_idx].paddr;
2739
2740                 dev_dbg(t->dev, "[0x%p]rotation:\n", (void *)t);
2741                 dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->set.r_fmt);
2742                 dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->set.r_width);
2743                 dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->set.r_height);
2744                 dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->set.r_paddr);
2745                 dev_dbg(t->dev, "[0x%p]\trstride = %d\n", (void *)t, t->set.r_stride);
2746
2747                 ret = init_ic(ipu, t);
2748                 CHECK_RETCODE(ret < 0, "init_ic ic_and_rot",
2749                                 t->state, chan_setup, ret);
2750                 ret = init_rot(ipu, t);
2751                 CHECK_RETCODE(ret < 0, "init_rot ic_and_rot",
2752                                 t->state, chan_setup, ret);
2753                 ret = ipu_link_channels(ipu, t->set.ic_chan,
2754                                 t->set.rot_chan);
2755                 CHECK_RETCODE(ret < 0, "ipu_link_ch ic_and_rot",
2756                                 STATE_LINK_CHAN_FAIL, chan_setup, ret);
2757         } else {
2758                 dev_err(t->dev, "ERR [0x%p]do task: should not be here\n", t);
2759                 t->state = STATE_ERR;
2760                 return;
2761         }
2762
2763         ret = ipu_request_irq(ipu, irq, task_irq_handler, 0, NULL, t);
2764         CHECK_RETCODE(ret < 0, "ipu_req_irq",
2765                         STATE_IRQ_FAIL, chan_setup, ret);
2766
2767         /* enable/start channel */
2768         if (only_ic(t->set.mode)) {
2769                 ret = ipu_enable_channel(ipu, t->set.ic_chan);
2770                 CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic",
2771                                 STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2772                 if (deinterlace_3_field(t)) {
2773                         ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
2774                         CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_p",
2775                                         STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2776                         ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
2777                         CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_n",
2778                                         STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2779                 }
2780
2781                 ret = ipu_select_buffer(ipu, t->set.ic_chan, IPU_OUTPUT_BUFFER,
2782                                         0);
2783                 CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic",
2784                                 STATE_SEL_BUF_FAIL, chan_buf, ret);
2785                 if (t->overlay_en) {
2786                         ret = ipu_select_buffer(ipu, t->set.ic_chan,
2787                                                 IPU_GRAPH_IN_BUFFER, 0);
2788                         CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_g",
2789                                         STATE_SEL_BUF_FAIL, chan_buf, ret);
2790                         if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
2791                                 ret = ipu_select_buffer(ipu, t->set.ic_chan,
2792                                                         IPU_ALPHA_IN_BUFFER, 0);
2793                                 CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_a",
2794                                                 STATE_SEL_BUF_FAIL, chan_buf,
2795                                                 ret);
2796                         }
2797                 }
2798                 if (!(t->set.mode & VDOA_BAND_MODE)) {
2799                         if (deinterlace_3_field(t))
2800                                 ipu_select_multi_vdi_buffer(ipu, 0);
2801                         else {
2802                                 ret = ipu_select_buffer(ipu, t->set.ic_chan,
2803                                                         IPU_INPUT_BUFFER, 0);
2804                                 CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_i",
2805                                         STATE_SEL_BUF_FAIL, chan_buf, ret);
2806                         }
2807                 }
2808         } else if (only_rot(t->set.mode)) {
2809                 ret = ipu_enable_channel(ipu, t->set.rot_chan);
2810                 CHECK_RETCODE(ret < 0, "ipu_enable_ch only_rot",
2811                                 STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2812                 ret = ipu_select_buffer(ipu, t->set.rot_chan,
2813                                                 IPU_OUTPUT_BUFFER, 0);
2814                 CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_o",
2815                                 STATE_SEL_BUF_FAIL, chan_buf, ret);
2816                 ret = ipu_select_buffer(ipu, t->set.rot_chan,
2817                                                 IPU_INPUT_BUFFER, 0);
2818                 CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_i",
2819                                 STATE_SEL_BUF_FAIL, chan_buf, ret);
2820         } else if (ic_and_rot(t->set.mode)) {
2821                 ret = ipu_enable_channel(ipu, t->set.rot_chan);
2822                 CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-rot",
2823                                 STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2824                 ret = ipu_enable_channel(ipu, t->set.ic_chan);
2825                 CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-ic",
2826                                 STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2827                 if (deinterlace_3_field(t)) {
2828                         ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
2829                         CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-p",
2830                                         STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2831                         ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
2832                         CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-n",
2833                                         STATE_ENABLE_CHAN_FAIL, chan_en, ret);
2834                 }
2835
2836                 ret = ipu_select_buffer(ipu, t->set.rot_chan,
2837                                                 IPU_OUTPUT_BUFFER, 0);
2838                 CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-rot-o",
2839                                 STATE_SEL_BUF_FAIL, chan_buf, ret);
2840                 if (t->overlay_en) {
2841                         ret = ipu_select_buffer(ipu, t->set.ic_chan,
2842                                                         IPU_GRAPH_IN_BUFFER, 0);
2843                         CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-g",
2844                                         STATE_SEL_BUF_FAIL, chan_buf, ret);
2845                         if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
2846                                 ret = ipu_select_buffer(ipu, t->set.ic_chan,
2847                                                         IPU_ALPHA_IN_BUFFER, 0);
2848                                 CHECK_RETCODE(ret < 0, "ipu_sel_buf icrot-ic-a",
2849                                                 STATE_SEL_BUF_FAIL,
2850                                                 chan_buf, ret);
2851                         }
2852                 }
2853                 ret = ipu_select_buffer(ipu, t->set.ic_chan,
2854                                                 IPU_OUTPUT_BUFFER, 0);
2855                 CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-o",
2856                                 STATE_SEL_BUF_FAIL, chan_buf, ret);
2857                 if (deinterlace_3_field(t))
2858                         ipu_select_multi_vdi_buffer(ipu, 0);
2859                 else {
2860                         ret = ipu_select_buffer(ipu, t->set.ic_chan,
2861                                                         IPU_INPUT_BUFFER, 0);
2862                         CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-i",
2863                                         STATE_SEL_BUF_FAIL, chan_buf, ret);
2864                 }
2865         }
2866
2867         if (need_split(t))
2868                 t->state = STATE_IN_PROGRESS;
2869
2870         if (t->set.mode & VDOA_BAND_MODE) {
2871                 ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
2872                 CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_band",
2873                                 STATE_VDOA_IRQ_TIMEOUT, chan_rel, ret);
2874         }
2875
2876         CHECK_PERF(&t->ts_waitirq);
2877         ret = wait_for_completion_timeout(&t->irq_comp,
2878                                  msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
2879         CHECK_PERF(&t->ts_wakeup);
2880         CHECK_RETCODE(ret == 0, "wait_for_comp_timeout",
2881                         STATE_IRQ_TIMEOUT, chan_rel, ret);
2882         dev_dbg(t->dev, "[0x%p] no-0x%x ipu irq done!", t, t->task_no);
2883
2884 chan_rel:
2885 chan_buf:
2886 chan_en:
2887 chan_setup:
2888         if (t->set.mode & VDOA_BAND_MODE)
2889                 vdoa_stop(t->vdoa_handle);
2890         do_task_release(t, t->state >= STATE_ERR);
2891         return;
2892 }
2893
2894 static void do_task_vdoa_vdi(struct ipu_task_entry *t)
2895 {
2896         int i;
2897         int ret;
2898         u32 stripe_width;
2899
2900         /* FIXME: crop mode not support now */
2901         stripe_width = t->input.width >> 1;
2902         t->input.crop.pos.x = 0;
2903         t->input.crop.pos.y = 0;
2904         t->input.crop.w = stripe_width;
2905         t->input.crop.h = t->input.height;
2906         t->output.crop.w = stripe_width;
2907         t->output.crop.h = t->input.height;
2908
2909         for (i = 0; i < 2; i++) {
2910                 t->input.crop.pos.x = t->input.crop.pos.x + i * stripe_width;
2911                 t->output.crop.pos.x = t->output.crop.pos.x + i * stripe_width;
2912                 /* check input */
2913                 ret = set_crop(&t->input.crop, t->input.width, t->input.height,
2914                         t->input.format);
2915                 if (ret < 0) {
2916                         ret = STATE_ERR;
2917                         goto done;
2918                 } else
2919                         update_offset(t->input.format,
2920                                         t->input.width, t->input.height,
2921                                         t->input.crop.pos.x,
2922                                         t->input.crop.pos.y,
2923                                         &t->set.i_off, &t->set.i_uoff,
2924                                         &t->set.i_voff, &t->set.istride);
2925                 dev_dbg(t->dev, "i_off:0x%x, i_uoff:0x%x, istride:%d.\n",
2926                         t->set.i_off, t->set.i_uoff, t->set.istride);
2927                 /* check output */
2928                 ret = set_crop(&t->output.crop, t->input.width,
2929                                         t->output.height, t->output.format);
2930                 if (ret < 0) {
2931                         ret = STATE_ERR;
2932                         goto done;
2933                 } else
2934                         update_offset(t->output.format,
2935                                         t->output.width, t->output.height,
2936                                         t->output.crop.pos.x,
2937                                         t->output.crop.pos.y,
2938                                         &t->set.o_off, &t->set.o_uoff,
2939                                         &t->set.o_voff, &t->set.ostride);
2940
2941                 dev_dbg(t->dev, "o_off:0x%x, o_uoff:0x%x, ostride:%d.\n",
2942                                 t->set.o_off, t->set.o_uoff, t->set.ostride);
2943
2944                 do_task(t);
2945         }
2946
2947         return;
2948 done:
2949         dev_err(t->dev, "ERR %s set_crop.\n", __func__);
2950         t->state = ret;
2951         return;
2952 }
2953
2954 static void get_res_do_task(struct ipu_task_entry *t)
2955 {
2956         uint32_t        found;
2957         uint32_t        split_child;
2958         struct mutex    *lock;
2959
2960         found = get_vdoa_ipu_res(t);
2961         if (!found) {
2962                 dev_err(t->dev, "ERR:[0x%p] no-0x%x can not get res\n",
2963                         t, t->task_no);
2964                 return;
2965         } else {
2966                 if (t->set.task & VDOA_ONLY)
2967                         do_task_vdoa_only(t);
2968                 else if ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
2969                                 (t->set.mode & VDOA_BAND_MODE) &&
2970                                 (t->input.crop.w > soc_max_vdi_in_width()))
2971                         do_task_vdoa_vdi(t);
2972                 else
2973                         do_task(t);
2974                 put_vdoa_ipu_res(t, 0);
2975         }
2976         if (t->state != STATE_OK) {
2977                 dev_err(t->dev, "ERR:[0x%p] no-0x%x state: %s\n",
2978                         t, t->task_no, state_msg[t->state].msg);
2979         }
2980
2981         split_child = need_split(t) && t->parent;
2982         if (split_child) {
2983                 lock = &t->parent->split_lock;
2984                 mutex_lock(lock);
2985                 t->split_done = 1;
2986                 mutex_unlock(lock);
2987                 wake_up(&t->parent->split_waitq);
2988         }
2989
2990         return;
2991 }
2992
2993 static void wait_split_task_complete(struct ipu_task_entry *parent,
2994                                 struct ipu_split_task *sp_task, uint32_t size)
2995 {
2996         struct ipu_task_entry *tsk = NULL;
2997         int ret = 0, rc;
2998         int j, idx = -1;
2999         unsigned long flags;
3000         struct mutex *lock = &parent->split_lock;
3001         int k, busy_vf, busy_pp;
3002         struct ipu_soc *ipu;
3003         DECLARE_PERF_VAR;
3004
3005         for (j = 0; j < size; j++) {
3006                 rc = wait_event_timeout(
3007                         parent->split_waitq,
3008                         sp_task_check_done(sp_task, parent, size, &idx),
3009                         msecs_to_jiffies(parent->timeout - DEF_DELAY_MS));
3010                 if (!rc) {
3011                         dev_err(parent->dev,
3012                                 "ERR:[0x%p] no-0x%x, split_task timeout,j:%d,"
3013                                 "size:%d.\n",
3014                                  parent, parent->task_no, j, size);
3015                         ret = -ETIMEDOUT;
3016                         goto out;
3017                 } else {
3018                         if (idx < 0) {
3019                                 dev_err(parent->dev,
3020                                 "ERR:[0x%p] no-0x%x, invalid task idx:%d\n",
3021                                  parent, parent->task_no, idx);
3022                                 continue;
3023                         }
3024                         tsk = sp_task[idx].child_task;
3025                         mutex_lock(lock);
3026                         if (!tsk->split_done || !tsk->ipu)
3027                                 dev_err(tsk->dev,
3028                                 "ERR:no-0x%x,split not done:%d/null ipu:0x%p\n",
3029                                  tsk->task_no, tsk->split_done, tsk->ipu);
3030                         tsk->split_done = 0;
3031                         mutex_unlock(lock);
3032
3033                         dev_dbg(tsk->dev,
3034                                 "[0x%p] no-0x%x sp_tsk[%d] done,state:%d.\n",
3035                                  tsk, tsk->task_no, idx, tsk->state);
3036                         #ifdef DBG_IPU_PERF
3037                                 CHECK_PERF(&tsk->ts_rel);
3038                                 PRINT_TASK_STATISTICS;
3039                         #endif
3040                 }
3041         }
3042
3043 out:
3044         if (ret == -ETIMEDOUT) {
3045                 /* debug */
3046                 for (k = 0; k < max_ipu_no; k++) {
3047                         ipu = ipu_get_soc(k);
3048                         if (IS_ERR(ipu)) {
3049                                 dev_err(parent->dev, "no:0x%x, null ipu:%d\n",
3050                                  parent->task_no, k);
3051                         } else {
3052                                 busy_vf = ic_vf_pp_is_busy(ipu, true);
3053                                 busy_pp = ic_vf_pp_is_busy(ipu, false);
3054                                 dev_err(parent->dev,
3055                                         "ERR:ipu[%d] busy_vf:%d, busy_pp:%d.\n",
3056                                         k, busy_vf, busy_pp);
3057                         }
3058                 }
3059                 for (k = 0; k < size; k++) {
3060                         tsk = sp_task[k].child_task;
3061                         if (!tsk)
3062                                 continue;
3063                         dev_err(parent->dev,
3064                                 "ERR: sp_task[%d][0x%p] no-0x%x done:%d,"
3065                                  "state:%s,on_list:%d, ipu:0x%p,timeout!\n",
3066                                  k, tsk, tsk->task_no, tsk->split_done,
3067                                  state_msg[tsk->state].msg, tsk->task_in_list,
3068                                  tsk->ipu);
3069                 }
3070         }
3071
3072         for (j = 0; j < size; j++) {
3073                 tsk = sp_task[j].child_task;
3074                 if (!tsk)
3075                         continue;
3076                 spin_lock_irqsave(&ipu_task_list_lock, flags);
3077                 if (tsk->task_in_list) {
3078                         list_del(&tsk->node);
3079                         tsk->task_in_list = 0;
3080                         dev_dbg(tsk->dev,
3081                                 "[0x%p] no-0x%x,id:%d sp_tsk timeout list_del.\n",
3082                                  tsk, tsk->task_no, tsk->task_id);
3083                 }
3084                 spin_unlock_irqrestore(&ipu_task_list_lock, flags);
3085                 if (!tsk->ipu)
3086                         continue;
3087                 if (tsk->state != STATE_OK) {
3088                         dev_err(tsk->dev,
3089                                 "ERR:[0x%p] no-0x%x,id:%d, sp_tsk state: %s\n",
3090                                         tsk, tsk->task_no, tsk->task_id,
3091                                         state_msg[tsk->state].msg);
3092                 }
3093                 kref_put(&tsk->refcount, task_mem_free);
3094         }
3095
3096         kfree(parent->vditmpbuf[0]);
3097         kfree(parent->vditmpbuf[1]);
3098
3099         if (ret < 0)
3100                 parent->state = STATE_TIMEOUT;
3101         else
3102                 parent->state = STATE_OK;
3103         return;
3104 }
3105
3106 static inline int find_task(struct ipu_task_entry **t, int thread_id)
3107 {
3108         int found;
3109         unsigned long flags;
3110         struct ipu_task_entry *tsk;
3111         struct list_head *task_list = &ipu_task_list;
3112
3113         *t = NULL;
3114         spin_lock_irqsave(&ipu_task_list_lock, flags);
3115         found = !list_empty(task_list);
3116         if (found) {
3117                 tsk = list_first_entry(task_list, struct ipu_task_entry, node);
3118                 if (tsk->task_in_list) {
3119                         list_del(&tsk->node);
3120                         tsk->task_in_list = 0;
3121                         *t = tsk;
3122                         kref_get(&tsk->refcount);
3123                         dev_dbg(tsk->dev,
3124                         "thread_id:%d,[0x%p] task_no:0x%x,mode:0x%x list_del\n",
3125                         thread_id, tsk, tsk->task_no, tsk->set.mode);
3126                 } else
3127                         dev_err(tsk->dev,
3128                         "thread_id:%d,task_no:0x%x,mode:0x%x not on list_del\n",
3129                         thread_id, tsk->task_no, tsk->set.mode);
3130         }
3131         spin_unlock_irqrestore(&ipu_task_list_lock, flags);
3132
3133         return found;
3134 }
3135
3136 static int ipu_task_thread(void *argv)
3137 {
3138         struct ipu_task_entry *tsk;
3139         struct ipu_task_entry *sp_tsk0;
3140         struct ipu_split_task sp_task[4];
3141         /* priority lower than irq_thread */
3142         const struct sched_param param = {
3143                 .sched_priority = MAX_USER_RT_PRIO/2 - 1,
3144         };
3145         int ret;
3146         int curr_thread_id;
3147         uint32_t size;
3148         unsigned long flags;
3149         unsigned int cpu;
3150         struct cpumask cpu_mask;
3151         struct ipu_thread_data *data = (struct ipu_thread_data *)argv;
3152
3153         thread_id++;
3154         curr_thread_id = thread_id;
3155         sched_setscheduler(current, SCHED_FIFO, &param);
3156
3157         if (!data->is_vdoa) {
3158                 cpu = cpumask_first(cpu_online_mask);
3159                 cpumask_set_cpu(cpu, &cpu_mask);
3160                 ret = sched_setaffinity(data->ipu->thread[data->id]->pid,
3161                         &cpu_mask);
3162                 if (ret < 0) {
3163                         pr_err("%s: sched_setaffinity fail:%d.\n", __func__, ret);
3164                 }
3165                 pr_debug("%s: sched_setaffinity cpu:%d.\n", __func__, cpu);
3166         }
3167
3168         while (!kthread_should_stop()) {
3169                 int split_fail = 0;
3170                 int split_parent;
3171                 int split_child;
3172
3173                 wait_event_interruptible(thread_waitq, find_task(&tsk, curr_thread_id));
3174
3175                 if (!tsk) {
3176                         pr_err("thread:%d can not find task.\n",
3177                                 curr_thread_id);
3178                         continue;
3179                 }
3180
3181                 /* note: other threads run split child task */
3182                 split_parent = need_split(tsk) && !tsk->parent;
3183                 split_child = need_split(tsk) && tsk->parent;
3184                 if (split_parent) {
3185                         if ((tsk->set.split_mode == RL_SPLIT) ||
3186                                  (tsk->set.split_mode == UD_SPLIT))
3187                                 size = 2;
3188                         else
3189                                 size = 4;
3190                         ret = queue_split_task(tsk, sp_task, size);
3191                         if (ret < 0) {
3192                                 split_fail = 1;
3193                         } else {
3194                                 struct list_head *pos;
3195
3196                                 spin_lock_irqsave(&ipu_task_list_lock, flags);
3197
3198                                 sp_tsk0 = list_first_entry(&tsk->split_list,
3199                                                 struct ipu_task_entry, node);
3200                                 list_del(&sp_tsk0->node);
3201
3202                                 list_for_each(pos, &tsk->split_list) {
3203                                         struct ipu_task_entry *tmp;
3204
3205                                         tmp = list_entry(pos,
3206                                                 struct ipu_task_entry, node);
3207                                         tmp->task_in_list = 1;
3208                                         dev_dbg(tmp->dev,
3209                                                 "[0x%p] no-0x%x,id:%d sp_tsk "
3210                                                 "add_to_list.\n", tmp,
3211                                                 tmp->task_no, tmp->task_id);
3212                                 }
3213                                 /* add to global list */
3214                                 list_splice(&tsk->split_list, &ipu_task_list);
3215
3216                                 spin_unlock_irqrestore(&ipu_task_list_lock,
3217                                                                         flags);
3218                                 /* let the parent thread do the first sp_task */
3219                                 /* FIXME: ensure the correct sequence for split
3220                                         4size: 5/6->9/a*/
3221                                 if (!sp_tsk0)
3222                                         dev_err(tsk->dev,
3223                                         "ERR: no-0x%x,can not get split_tsk0\n",
3224                                         tsk->task_no);
3225                                 wake_up_interruptible(&thread_waitq);
3226                                 get_res_do_task(sp_tsk0);
3227                                 dev_dbg(sp_tsk0->dev,
3228                                         "thread:%d complete tsk no:0x%x.\n",
3229                                         curr_thread_id, sp_tsk0->task_no);
3230                                 ret = atomic_read(&req_cnt);
3231                                 if (ret > 0) {
3232                                         wake_up(&res_waitq);
3233                                         dev_dbg(sp_tsk0->dev,
3234                                         "sp_tsk0 sche thread:%d no:0x%x,"
3235                                         "req_cnt:%d\n", curr_thread_id,
3236                                         sp_tsk0->task_no, ret);
3237                                         /* For other threads to get_res */
3238                                         schedule();
3239                                 }
3240                         }
3241                 } else
3242                         get_res_do_task(tsk);
3243
3244                 /* wait for all 4 sp_task finished here or timeout
3245                         and then release all resources */
3246                 if (split_parent && !split_fail)
3247                         wait_split_task_complete(tsk, sp_task, size);
3248
3249                 if (!split_child) {
3250                         atomic_inc(&tsk->done);
3251                         wake_up(&tsk->task_waitq);
3252                 }
3253
3254                 dev_dbg(tsk->dev, "thread:%d complete tsk no:0x%x-[0x%p].\n",
3255                                 curr_thread_id, tsk->task_no, tsk);
3256                 ret = atomic_read(&req_cnt);
3257                 if (ret > 0) {
3258                         wake_up(&res_waitq);
3259                         dev_dbg(tsk->dev, "sche thread:%d no:0x%x,req_cnt:%d\n",
3260                                 curr_thread_id, tsk->task_no, ret);
3261                         /* note: give cpu to other threads to get_res */
3262                         schedule();
3263                 }
3264
3265                 kref_put(&tsk->refcount, task_mem_free);
3266         }
3267
3268         pr_info("ERR %s exit.\n", __func__);
3269         return 0;
3270 }
3271
3272 int ipu_check_task(struct ipu_task *task)
3273 {
3274         struct ipu_task_entry *tsk;
3275         int ret = 0;
3276
3277         tsk = create_task_entry(task);
3278         if (IS_ERR(tsk))
3279                 return PTR_ERR(tsk);
3280
3281         ret = check_task(tsk);
3282
3283         task->input = tsk->input;
3284         task->output = tsk->output;
3285         task->overlay = tsk->overlay;
3286         dump_task_info(tsk);
3287
3288         kref_put(&tsk->refcount, task_mem_free);
3289         if (ret != 0)
3290                 pr_debug("%s ret:%d.\n", __func__, ret);
3291         return ret;
3292 }
3293 EXPORT_SYMBOL_GPL(ipu_check_task);
3294
3295 int ipu_queue_task(struct ipu_task *task)
3296 {
3297         struct ipu_task_entry *tsk;
3298         unsigned long flags;
3299         int ret;
3300         u32 tmp_task_no;
3301         DECLARE_PERF_VAR;
3302
3303         tsk = create_task_entry(task);
3304         if (IS_ERR(tsk))
3305                 return PTR_ERR(tsk);
3306
3307         CHECK_PERF(&tsk->ts_queue);
3308         ret = prepare_task(tsk);
3309         if (ret < 0)
3310                 goto done;
3311
3312         if (need_split(tsk)) {
3313                 CHECK_PERF(&tsk->ts_dotask);
3314                 CHECK_PERF(&tsk->ts_waitirq);
3315                 CHECK_PERF(&tsk->ts_inirq);
3316                 CHECK_PERF(&tsk->ts_wakeup);
3317         }
3318
3319         /* task_no last four bits for split task type*/
3320         tmp_task_no = atomic_inc_return(&frame_no);
3321         tsk->task_no = tmp_task_no << 4;
3322         init_waitqueue_head(&tsk->task_waitq);
3323
3324         spin_lock_irqsave(&ipu_task_list_lock, flags);
3325         list_add_tail(&tsk->node, &ipu_task_list);
3326         tsk->task_in_list = 1;
3327         dev_dbg(tsk->dev, "[0x%p,no-0x%x] list_add_tail\n", tsk, tsk->task_no);
3328         spin_unlock_irqrestore(&ipu_task_list_lock, flags);
3329         wake_up_interruptible(&thread_waitq);
3330
3331         ret = wait_event_timeout(tsk->task_waitq, atomic_read(&tsk->done),
3332                                                 msecs_to_jiffies(tsk->timeout));
3333         if (0 == ret) {
3334                 /* note: the timeout should larger than the internal timeout!*/
3335                 ret = -ETIMEDOUT;
3336                 dev_err(tsk->dev, "ERR: [0x%p] no-0x%x, timeout:%dms!\n",
3337                                 tsk, tsk->task_no, tsk->timeout);
3338         } else {
3339                 if (STATE_OK != tsk->state) {
3340                         dev_err(tsk->dev, "ERR: [0x%p] no-0x%x,state %d: %s\n",
3341                                 tsk, tsk->task_no, tsk->state,
3342                                 state_msg[tsk->state].msg);
3343                         ret = -ECANCELED;
3344                 } else
3345                         ret = 0;
3346         }
3347
3348         spin_lock_irqsave(&ipu_task_list_lock, flags);
3349         if (tsk->task_in_list) {
3350                 list_del(&tsk->node);
3351                 tsk->task_in_list = 0;
3352                 dev_dbg(tsk->dev, "[0x%p] no:0x%x list_del\n",
3353                                 tsk, tsk->task_no);
3354         }
3355         spin_unlock_irqrestore(&ipu_task_list_lock, flags);
3356
3357 #ifdef DBG_IPU_PERF
3358         CHECK_PERF(&tsk->ts_rel);
3359         PRINT_TASK_STATISTICS;
3360         if (ts_frame_avg == 0)
3361                 ts_frame_avg = ts_frame.tv_nsec / NSEC_PER_USEC +
3362                                 ts_frame.tv_sec * USEC_PER_SEC;
3363         else
3364                 ts_frame_avg = (ts_frame_avg + ts_frame.tv_nsec / NSEC_PER_USEC
3365                                 + ts_frame.tv_sec * USEC_PER_SEC)/2;
3366         if (timespec_compare(&ts_frame, &ts_frame_max) > 0)
3367                 ts_frame_max = ts_frame;
3368
3369         atomic_inc(&frame_cnt);
3370
3371         if ((atomic_read(&frame_cnt) %  1000) == 0)
3372                 pr_debug("ipu_dev: max frame time:%ldus, avg frame time:%dus,"
3373                         "frame_cnt:%d\n", ts_frame_max.tv_nsec / NSEC_PER_USEC
3374                         + ts_frame_max.tv_sec * USEC_PER_SEC,
3375                         ts_frame_avg, atomic_read(&frame_cnt));
3376 #endif
3377 done:
3378         if (ret < 0)
3379                 dev_err(tsk->dev, "ERR: no-0x%x,ipu_queue_task err:%d\n",
3380                                 tsk->task_no, ret);
3381
3382         kref_put(&tsk->refcount, task_mem_free);
3383
3384         return ret;
3385 }
3386 EXPORT_SYMBOL_GPL(ipu_queue_task);
3387
3388 static int mxc_ipu_open(struct inode *inode, struct file *file)
3389 {
3390         file->private_data = (void *)atomic_inc_return(&file_index);
3391         return 0;
3392 }
3393
3394 static long mxc_ipu_ioctl(struct file *file,
3395                 unsigned int cmd, unsigned long arg)
3396 {
3397         int __user *argp = (void __user *)arg;
3398         int ret = 0;
3399
3400         switch (cmd) {
3401         case IPU_CHECK_TASK:
3402                 {
3403                         struct ipu_task task;
3404
3405                         if (copy_from_user
3406                                         (&task, (struct ipu_task *) arg,
3407                                          sizeof(struct ipu_task)))
3408                                 return -EFAULT;
3409                         ret = ipu_check_task(&task);
3410                         if (copy_to_user((struct ipu_task *) arg,
3411                                 &task, sizeof(struct ipu_task)))
3412                                 return -EFAULT;
3413                         break;
3414                 }
3415         case IPU_QUEUE_TASK:
3416                 {
3417                         struct ipu_task task;
3418
3419                         if (copy_from_user
3420                                         (&task, (struct ipu_task *) arg,
3421                                          sizeof(struct ipu_task)))
3422                                 return -EFAULT;
3423                         ret = ipu_queue_task(&task);
3424                         break;
3425                 }
3426         case IPU_ALLOC:
3427                 {
3428                         int size;
3429                         struct ipu_alloc_list *mem;
3430
3431                         mem = kzalloc(sizeof(*mem), GFP_KERNEL);
3432                         if (mem == NULL)
3433                                 return -ENOMEM;
3434
3435                         if (get_user(size, argp))
3436                                 return -EFAULT;
3437
3438                         mem->size = PAGE_ALIGN(size);
3439
3440                         mem->cpu_addr = dma_alloc_coherent(ipu_dev, size,
3441                                                            &mem->phy_addr,
3442                                                            GFP_DMA | GFP_KERNEL);
3443                         if (mem->cpu_addr == NULL) {
3444                                 kfree(mem);
3445                                 return -ENOMEM;
3446                         }
3447                         mem->file_index = file->private_data;
3448                         mutex_lock(&ipu_alloc_lock);
3449                         list_add(&mem->list, &ipu_alloc_list);
3450                         mutex_unlock(&ipu_alloc_lock);
3451
3452                         dev_dbg(ipu_dev, "allocated %d bytes @ 0x%08X\n",
3453                                 mem->size, mem->phy_addr);
3454
3455                         if (put_user(mem->phy_addr, argp))
3456                                 return -EFAULT;
3457
3458                         break;
3459                 }
3460         case IPU_FREE:
3461                 {
3462                         unsigned long offset;
3463                         struct ipu_alloc_list *mem;
3464
3465                         if (get_user(offset, argp))
3466                                 return -EFAULT;
3467
3468                         ret = -EINVAL;
3469                         mutex_lock(&ipu_alloc_lock);
3470                         list_for_each_entry(mem, &ipu_alloc_list, list) {
3471                                 if (mem->phy_addr == offset) {
3472                                         list_del(&mem->list);
3473                                         dma_free_coherent(ipu_dev,
3474                                                           mem->size,
3475                                                           mem->cpu_addr,
3476                                                           mem->phy_addr);
3477                                         kfree(mem);
3478                                         ret = 0;
3479                                         break;
3480                                 }
3481                         }
3482                         mutex_unlock(&ipu_alloc_lock);
3483                         if (0 == ret)
3484                                 dev_dbg(ipu_dev, "free %d bytes @ 0x%08X\n",
3485                                         mem->size, mem->phy_addr);
3486
3487                         break;
3488                 }
3489         default:
3490                 break;
3491         }
3492         return ret;
3493 }
3494
3495 static int mxc_ipu_mmap(struct file *file, struct vm_area_struct *vma)
3496 {
3497         bool found = false;
3498         u32 len;
3499         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
3500         struct ipu_alloc_list *mem;
3501
3502         mutex_lock(&ipu_alloc_lock);
3503         list_for_each_entry(mem, &ipu_alloc_list, list) {
3504                 if (offset == mem->phy_addr) {
3505                         found = true;
3506                         len = mem->size;
3507                         break;
3508                 }
3509         }
3510         mutex_unlock(&ipu_alloc_lock);
3511         if (!found)
3512                 return -EINVAL;
3513
3514         if (vma->vm_end - vma->vm_start > len)
3515                 return -EINVAL;
3516
3517         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
3518
3519         if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
3520                                 vma->vm_end - vma->vm_start,
3521                                 vma->vm_page_prot)) {
3522                 printk(KERN_ERR
3523                                 "mmap failed!\n");
3524                 return -ENOBUFS;
3525         }
3526         return 0;
3527 }
3528
3529 static int mxc_ipu_release(struct inode *inode, struct file *file)
3530 {
3531         struct ipu_alloc_list *mem;
3532         struct ipu_alloc_list *n;
3533
3534         mutex_lock(&ipu_alloc_lock);
3535         list_for_each_entry_safe(mem, n, &ipu_alloc_list, list) {
3536                 if ((mem->cpu_addr != 0) &&
3537                         (file->private_data == mem->file_index)) {
3538                         list_del(&mem->list);
3539                         dma_free_coherent(ipu_dev,
3540                                           mem->size,
3541                                           mem->cpu_addr,
3542                                           mem->phy_addr);
3543                         dev_dbg(ipu_dev, "rel-free %d bytes @ 0x%08X\n",
3544                                 mem->size, mem->phy_addr);
3545                         kfree(mem);
3546                 }
3547         }
3548         mutex_unlock(&ipu_alloc_lock);
3549         atomic_dec(&file_index);
3550
3551         return 0;
3552 }
3553
3554 static struct file_operations mxc_ipu_fops = {
3555         .owner = THIS_MODULE,
3556         .open = mxc_ipu_open,
3557         .mmap = mxc_ipu_mmap,
3558         .release = mxc_ipu_release,
3559         .unlocked_ioctl = mxc_ipu_ioctl,
3560 };
3561
3562 int register_ipu_device(struct ipu_soc *ipu, int id)
3563 {
3564         int ret = 0;
3565         static int idx;
3566         static struct ipu_thread_data thread_data[5];
3567
3568         if (!major) {
3569                 major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
3570                 if (major < 0) {
3571                         printk(KERN_ERR "Unable to register mxc_ipu as a char device\n");
3572                         ret = major;
3573                         goto register_cdev_fail;
3574                 }
3575
3576                 ipu_class = class_create(THIS_MODULE, "mxc_ipu");
3577                 if (IS_ERR(ipu_class)) {
3578                         ret = PTR_ERR(ipu_class);
3579                         goto ipu_class_fail;
3580                 }
3581
3582                 ipu_dev = device_create(ipu_class, NULL, MKDEV(major, 0),
3583                                 NULL, "mxc_ipu");
3584                 if (IS_ERR(ipu_dev)) {
3585                         ret = PTR_ERR(ipu_dev);
3586                         goto dev_create_fail;
3587                 }
3588                 ipu_dev->dma_mask = kmalloc(sizeof(*ipu_dev->dma_mask), GFP_KERNEL);
3589                 *ipu_dev->dma_mask = DMA_BIT_MASK(32);
3590                 ipu_dev->coherent_dma_mask = DMA_BIT_MASK(32);
3591
3592                 mutex_init(&ipu_ch_tbl.lock);
3593         }
3594         max_ipu_no = ++id;
3595         ipu->rot_dma[0].size = 0;
3596         ipu->rot_dma[1].size = 0;
3597
3598         thread_data[idx].ipu = ipu;
3599         thread_data[idx].id = 0;
3600         thread_data[idx].is_vdoa = 0;
3601         ipu->thread[0] = kthread_run(ipu_task_thread, &thread_data[idx++],
3602                                         "ipu%d_task", id);
3603         if (IS_ERR(ipu->thread[0])) {
3604                 ret = PTR_ERR(ipu->thread[0]);
3605                 goto kthread0_fail;
3606         }
3607
3608         thread_data[idx].ipu = ipu;
3609         thread_data[idx].id = 1;
3610         thread_data[idx].is_vdoa = 0;
3611         ipu->thread[1] = kthread_run(ipu_task_thread, &thread_data[idx++],
3612                                 "ipu%d_task", id);
3613         if (IS_ERR(ipu->thread[1])) {
3614                 ret = PTR_ERR(ipu->thread[1]);
3615                 goto kthread1_fail;
3616         }
3617
3618
3619         return ret;
3620
3621 kthread1_fail:
3622         kthread_stop(ipu->thread[0]);
3623 kthread0_fail:
3624         if (id == 0)
3625                 device_destroy(ipu_class, MKDEV(major, 0));
3626 dev_create_fail:
3627         if (id == 0) {
3628                 class_destroy(ipu_class);
3629         }
3630 ipu_class_fail:
3631         if (id == 0)
3632                 unregister_chrdev(major, "mxc_ipu");
3633 register_cdev_fail:
3634         return ret;
3635 }
3636
3637 void unregister_ipu_device(struct ipu_soc *ipu, int id)
3638 {
3639         int i;
3640
3641         kthread_stop(ipu->thread[0]);
3642         kthread_stop(ipu->thread[1]);
3643         for (i = 0; i < 2; i++) {
3644                 if (ipu->rot_dma[i].vaddr)
3645                         dma_free_coherent(ipu_dev,
3646                                 ipu->rot_dma[i].size,
3647                                 ipu->rot_dma[i].vaddr,
3648                                 ipu->rot_dma[i].paddr);
3649         }
3650
3651         if (major) {
3652                 device_destroy(ipu_class, MKDEV(major, 0));
3653                 class_destroy(ipu_class);
3654                 unregister_chrdev(major, "mxc_ipu");
3655                 major = 0;
3656         }
3657 }