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