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