]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/dma/pxp/pxp_dma_v2.c
ENGR00290613 PXP: add asynchronous multi instances support for PXP
[karo-tx-linux.git] / drivers / dma / pxp / pxp_dma_v2.c
1 /*
2  * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  */
19 /*
20  * Based on STMP378X PxP driver
21  * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
22  */
23
24 #include <linux/dma-mapping.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/io.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/mutex.h>
31 #include <linux/platform_device.h>
32 #include <linux/slab.h>
33 #include <linux/vmalloc.h>
34 #include <linux/dmaengine.h>
35 #include <linux/pxp_dma.h>
36 #include <linux/timer.h>
37 #include <linux/clk.h>
38 #include <linux/workqueue.h>
39 #include <linux/sched.h>
40 #include <linux/of.h>
41 #include <linux/kthread.h>
42
43 #include "regs-pxp_v2.h"
44
45 #define PXP_DOWNSCALE_THRESHOLD         0x4000
46
47 static LIST_HEAD(head);
48 static int timeout_in_ms = 600;
49 static unsigned int block_size;
50
51 struct pxp_dma {
52         struct dma_device dma;
53 };
54
55 struct pxps {
56         struct platform_device *pdev;
57         struct clk *clk;
58         void __iomem *base;
59         int irq;                /* PXP IRQ to the CPU */
60
61         spinlock_t lock;
62         struct mutex clk_mutex;
63         int clk_stat;
64 #define CLK_STAT_OFF            0
65 #define CLK_STAT_ON             1
66         int pxp_ongoing;
67         int lut_state;
68
69         struct device *dev;
70         struct pxp_dma pxp_dma;
71         struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
72         struct work_struct work;
73
74         /* describes most recent processing configuration */
75         struct pxp_config_data pxp_conf_state;
76
77         /* to turn clock off when pxp is inactive */
78         struct timer_list clk_timer;
79
80         /* for pxp config dispatch asynchronously*/
81         struct task_struct *dispatch;
82         wait_queue_head_t thread_waitq;
83         struct completion complete;
84 };
85
86 #define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
87 #define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
88 #define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
89 #define to_pxp(id) container_of(id, struct pxps, pxp_dma)
90
91 #define PXP_DEF_BUFS    2
92 #define PXP_MIN_PIX     8
93
94 static uint32_t pxp_s0_formats[] = {
95         PXP_PIX_FMT_RGB32,
96         PXP_PIX_FMT_RGB565,
97         PXP_PIX_FMT_RGB555,
98         PXP_PIX_FMT_YUV420P,
99         PXP_PIX_FMT_YUV422P,
100 };
101
102 /*
103  * PXP common functions
104  */
105 static void dump_pxp_reg(struct pxps *pxp)
106 {
107         dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
108                 __raw_readl(pxp->base + HW_PXP_CTRL));
109         dev_dbg(pxp->dev, "PXP_STAT 0x%x",
110                 __raw_readl(pxp->base + HW_PXP_STAT));
111         dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
112                 __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
113         dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
114                 __raw_readl(pxp->base + HW_PXP_OUT_BUF));
115         dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
116                 __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
117         dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
118                 __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
119         dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
120                 __raw_readl(pxp->base + HW_PXP_OUT_LRC));
121         dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
122                 __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
123         dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
124                 __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
125         dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
126                 __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
127         dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
128                 __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
129         dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
130                 __raw_readl(pxp->base + HW_PXP_PS_CTRL));
131         dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
132                 __raw_readl(pxp->base + HW_PXP_PS_BUF));
133         dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
134                 __raw_readl(pxp->base + HW_PXP_PS_UBUF));
135         dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
136                 __raw_readl(pxp->base + HW_PXP_PS_VBUF));
137         dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
138                 __raw_readl(pxp->base + HW_PXP_PS_PITCH));
139         dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x",
140                 __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND));
141         dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
142                 __raw_readl(pxp->base + HW_PXP_PS_SCALE));
143         dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
144                 __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
145         dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x",
146                 __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW));
147         dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
148                 __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH));
149         dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
150                 __raw_readl(pxp->base + HW_PXP_AS_CTRL));
151         dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
152                 __raw_readl(pxp->base + HW_PXP_AS_BUF));
153         dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
154                 __raw_readl(pxp->base + HW_PXP_AS_PITCH));
155         dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
156                 __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW));
157         dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
158                 __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH));
159         dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
160                 __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
161         dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
162                 __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
163         dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
164                 __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
165         dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
166                 __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
167         dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
168                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
169         dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
170                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
171         dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
172                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
173         dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
174                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
175         dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
176                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
177         dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
178                 __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
179         dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
180                 __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
181         dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
182                 __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
183         dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
184                 __raw_readl(pxp->base + HW_PXP_LUT_DATA));
185         dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
186                 __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
187         dev_dbg(pxp->dev, "PXP_CFA 0x%x",
188                 __raw_readl(pxp->base + HW_PXP_CFA));
189         dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
190                 __raw_readl(pxp->base + HW_PXP_HIST_CTRL));
191         dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
192                 __raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
193         dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
194                 __raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
195         dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
196                 __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
197         dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
198                 __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
199         dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
200                 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
201         dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
202                 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
203         dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
204                 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
205         dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
206                 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
207         dev_dbg(pxp->dev, "PXP_POWER 0x%x",
208                 __raw_readl(pxp->base + HW_PXP_POWER));
209         dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
210                 __raw_readl(pxp->base + HW_PXP_NEXT));
211         dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
212                 __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
213         dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
214                 __raw_readl(pxp->base + HW_PXP_DEBUG));
215         dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
216                 __raw_readl(pxp->base + HW_PXP_VERSION));
217 }
218
219 static bool is_yuv(u32 pix_fmt)
220 {
221         if ((pix_fmt == PXP_PIX_FMT_YUYV) |
222             (pix_fmt == PXP_PIX_FMT_UYVY) |
223             (pix_fmt == PXP_PIX_FMT_YVYU) |
224             (pix_fmt == PXP_PIX_FMT_VYUY) |
225             (pix_fmt == PXP_PIX_FMT_Y41P) |
226             (pix_fmt == PXP_PIX_FMT_YUV444) |
227             (pix_fmt == PXP_PIX_FMT_NV12) |
228             (pix_fmt == PXP_PIX_FMT_NV16) |
229             (pix_fmt == PXP_PIX_FMT_NV61) |
230             (pix_fmt == PXP_PIX_FMT_GREY) |
231             (pix_fmt == PXP_PIX_FMT_GY04) |
232             (pix_fmt == PXP_PIX_FMT_YVU410P) |
233             (pix_fmt == PXP_PIX_FMT_YUV410P) |
234             (pix_fmt == PXP_PIX_FMT_YVU420P) |
235             (pix_fmt == PXP_PIX_FMT_YUV420P) |
236             (pix_fmt == PXP_PIX_FMT_YUV420P2) |
237             (pix_fmt == PXP_PIX_FMT_YVU422P) |
238             (pix_fmt == PXP_PIX_FMT_YUV422P)) {
239                 return true;
240         } else {
241                 return false;
242         }
243 }
244
245 static void pxp_set_ctrl(struct pxps *pxp)
246 {
247         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
248         struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
249         u32 ctrl;
250         u32 fmt_ctrl;
251         int need_swap = 0;   /* to support YUYV and YVYU formats */
252
253         /* Configure S0 input format */
254         switch (pxp_conf->s0_param.pixel_fmt) {
255         case PXP_PIX_FMT_RGB32:
256                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
257                 break;
258         case PXP_PIX_FMT_RGB565:
259                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
260                 break;
261         case PXP_PIX_FMT_RGB555:
262                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
263                 break;
264         case PXP_PIX_FMT_YUV420P:
265                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
266                 break;
267         case PXP_PIX_FMT_YVU420P:
268                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
269                 break;
270         case PXP_PIX_FMT_GREY:
271                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
272                 break;
273         case PXP_PIX_FMT_GY04:
274                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
275                 break;
276         case PXP_PIX_FMT_YUV422P:
277                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
278                 break;
279         case PXP_PIX_FMT_UYVY:
280                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
281                 break;
282         case PXP_PIX_FMT_YUYV:
283                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
284                 need_swap = 1;
285                 break;
286         case PXP_PIX_FMT_VYUY:
287                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
288                 break;
289         case PXP_PIX_FMT_YVYU:
290                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
291                 need_swap = 1;
292                 break;
293         case PXP_PIX_FMT_NV12:
294                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
295                 break;
296         case PXP_PIX_FMT_NV21:
297                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
298                 break;
299         case PXP_PIX_FMT_NV16:
300                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
301                 break;
302         case PXP_PIX_FMT_NV61:
303                 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
304                 break;
305         default:
306                 fmt_ctrl = 0;
307         }
308
309         ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap);
310         __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET);
311
312         /* Configure output format based on out_channel format */
313         switch (pxp_conf->out_param.pixel_fmt) {
314         case PXP_PIX_FMT_RGB32:
315                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
316                 break;
317         case PXP_PIX_FMT_BGRA32:
318                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
319                 break;
320         case PXP_PIX_FMT_RGB24:
321                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
322                 break;
323         case PXP_PIX_FMT_RGB565:
324                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
325                 break;
326         case PXP_PIX_FMT_RGB555:
327                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
328                 break;
329         case PXP_PIX_FMT_GREY:
330                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
331                 break;
332         case PXP_PIX_FMT_GY04:
333                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
334                 break;
335         case PXP_PIX_FMT_UYVY:
336                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
337                 break;
338         case PXP_PIX_FMT_VYUY:
339                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
340                 break;
341         case PXP_PIX_FMT_NV12:
342                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
343                 break;
344         case PXP_PIX_FMT_NV21:
345                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
346                 break;
347         case PXP_PIX_FMT_NV16:
348                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
349                 break;
350         case PXP_PIX_FMT_NV61:
351                 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
352                 break;
353         default:
354                 fmt_ctrl = 0;
355         }
356
357         ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
358         __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
359
360         ctrl = 0;
361         if (proc_data->scaling)
362                 ;
363         if (proc_data->vflip)
364                 ctrl |= BM_PXP_CTRL_VFLIP;
365         if (proc_data->hflip)
366                 ctrl |= BM_PXP_CTRL_HFLIP;
367         if (proc_data->rotate) {
368                 ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
369                 if (proc_data->rot_pos)
370                         ctrl |= BM_PXP_CTRL_ROT_POS;
371         }
372
373         /* In default, the block size is set to 8x8
374          * But block size can be set to 16x16 due to
375          * blocksize variable modification
376          */
377         ctrl |= block_size << 23;
378
379         __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
380 }
381
382 static int pxp_start(struct pxps *pxp)
383 {
384         __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET);
385         __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET);
386         dump_pxp_reg(pxp);
387
388         return 0;
389 }
390
391 static void pxp_set_outbuf(struct pxps *pxp)
392 {
393         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
394         struct pxp_layer_param *out_params = &pxp_conf->out_param;
395
396         __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
397
398         __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) |
399                      BF_PXP_OUT_LRC_Y(out_params->height - 1),
400                      pxp->base + HW_PXP_OUT_LRC);
401
402         if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
403                 __raw_writel(out_params->stride * 3,
404                                 pxp->base + HW_PXP_OUT_PITCH);
405         } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
406                  out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
407                 __raw_writel(out_params->stride << 2,
408                                 pxp->base + HW_PXP_OUT_PITCH);
409         } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) {
410                 __raw_writel(out_params->stride << 1,
411                                 pxp->base + HW_PXP_OUT_PITCH);
412         } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
413                 (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) {
414                 __raw_writel(out_params->stride << 1,
415                                 pxp->base + HW_PXP_OUT_PITCH);
416         } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY ||
417                    out_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
418                    out_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
419                    out_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
420                    out_params->pixel_fmt == PXP_PIX_FMT_NV61) {
421                 __raw_writel(out_params->stride,
422                                 pxp->base + HW_PXP_OUT_PITCH);
423         } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) {
424                 __raw_writel(out_params->stride >> 1,
425                                 pxp->base + HW_PXP_OUT_PITCH);
426         } else {
427                 __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
428         }
429
430         /* set global alpha if necessary */
431         if (out_params->global_alpha_enable) {
432                 __raw_writel(out_params->global_alpha << 24,
433                                 pxp->base + HW_PXP_OUT_CTRL_SET);
434                 __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT,
435                                 pxp->base + HW_PXP_OUT_CTRL_SET);
436         }
437 }
438
439 static void pxp_set_s0colorkey(struct pxps *pxp)
440 {
441         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
442         struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
443
444         /* Low and high are set equal. V4L does not allow a chromakey range */
445         if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
446                 /* disable color key */
447                 __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW);
448                 __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH);
449         } else {
450                 __raw_writel(s0_params->color_key,
451                              pxp->base + HW_PXP_PS_CLRKEYLOW);
452                 __raw_writel(s0_params->color_key,
453                              pxp->base + HW_PXP_PS_CLRKEYHIGH);
454         }
455 }
456
457 static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
458 {
459         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
460         struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
461
462         /* Low and high are set equal. V4L does not allow a chromakey range */
463         if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
464                 __raw_writel(ol_params->color_key,
465                              pxp->base + HW_PXP_AS_CLRKEYLOW);
466                 __raw_writel(ol_params->color_key,
467                              pxp->base + HW_PXP_AS_CLRKEYHIGH);
468         } else {
469                 /* disable color key */
470                 __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
471                 __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
472         }
473 }
474
475 static void pxp_set_oln(int layer_no, struct pxps *pxp)
476 {
477         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
478         struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
479         dma_addr_t phys_addr = olparams_data->paddr;
480         u32 pitch = olparams_data->stride ? olparams_data->stride :
481                                             olparams_data->width;
482
483         __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
484
485         /* Fixme */
486         if (olparams_data->width == 0 && olparams_data->height == 0) {
487                 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
488                 __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
489         } else {
490                 __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
491                 if (pxp_conf->proc_data.rotate == 90 ||
492                     pxp_conf->proc_data.rotate == 270) {
493                         if (pxp_conf->proc_data.rot_pos == 1) {
494                                 __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) |
495                                         BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1),
496                                         pxp->base + HW_PXP_OUT_AS_LRC);
497                         } else {
498                                 __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
499                                         BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
500                                         pxp->base + HW_PXP_OUT_AS_LRC);
501                         }
502                 } else {
503                         __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
504                                 BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
505                                 pxp->base + HW_PXP_OUT_AS_LRC);
506                 }
507         }
508
509         if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) |
510                  (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) {
511                 __raw_writel(pitch << 2,
512                                 pxp->base + HW_PXP_AS_PITCH);
513         } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
514                 __raw_writel(pitch << 1,
515                                 pxp->base + HW_PXP_AS_PITCH);
516         } else {
517                 __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
518         }
519 }
520
521 static void pxp_set_olparam(int layer_no, struct pxps *pxp)
522 {
523         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
524         struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
525         u32 olparam;
526
527         olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
528         if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) {
529                 olparam |=
530                     BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
531         } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
532                 olparam |=
533                     BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
534                 if (!olparams_data->combine_enable) {
535                         olparam |=
536                                 BF_PXP_AS_CTRL_ALPHA_CTRL
537                                 (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
538                         olparam |= 0x3 << 16;
539                 }
540         } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
541                 olparam |=
542                     BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
543         }
544         if (olparams_data->global_alpha_enable) {
545                 if (olparams_data->global_override) {
546                         olparam |=
547                                 BF_PXP_AS_CTRL_ALPHA_CTRL
548                                 (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
549                 } else {
550                         olparam |=
551                                 BF_PXP_AS_CTRL_ALPHA_CTRL
552                                 (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
553                 }
554                 if (olparams_data->alpha_invert)
555                         olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
556         }
557         if (olparams_data->color_key_enable)
558                 olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
559
560         __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
561 }
562
563 static void pxp_set_s0param(struct pxps *pxp)
564 {
565         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
566         struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
567         u32 s0param;
568
569         /* contains the coordinate for the PS in the OUTPUT buffer. */
570         if ((pxp_conf->s0_param).width == 0 &&
571                 (pxp_conf->s0_param).height == 0) {
572                 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
573                 __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
574         } else {
575                 s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
576                 s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
577                 __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC);
578                 s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
579                                 proc_data->drect.width - 1);
580                 s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
581                                 proc_data->drect.height - 1);
582                 __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC);
583         }
584 }
585
586 /* crop behavior is re-designed in h/w. */
587 static void pxp_set_s0crop(struct pxps *pxp)
588 {
589         /*
590          * place-holder, it's implemented in other functions in this driver.
591          * Refer to "Clipping source images" section in RM for detail.
592          */
593 }
594
595 static int pxp_set_scaling(struct pxps *pxp)
596 {
597         int ret = 0;
598         u32 xscale, yscale, s0scale;
599         u32 decx, decy, xdec = 0, ydec = 0;
600         struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
601
602         if (((proc_data->srect.width == proc_data->drect.width) &&
603             (proc_data->srect.height == proc_data->drect.height)) ||
604             ((proc_data->srect.width == 0) && (proc_data->srect.height == 0))) {
605                 proc_data->scaling = 0;
606                 __raw_writel(0x10001000, pxp->base + HW_PXP_PS_SCALE);
607                 __raw_writel(0, pxp->base + HW_PXP_PS_CTRL);
608                 goto out;
609         }
610
611         proc_data->scaling = 1;
612         decx = proc_data->srect.width / proc_data->drect.width;
613         decy = proc_data->srect.height / proc_data->drect.height;
614         if (decx > 0) {
615                 if (decx >= 2 && decx < 4) {
616                         decx = 2;
617                         xdec = 1;
618                 } else if (decx >= 4 && decx < 8) {
619                         decx = 4;
620                         xdec = 2;
621                 } else if (decx >= 8) {
622                         decx = 8;
623                         xdec = 3;
624                 }
625                 xscale = proc_data->srect.width * 0x1000 /
626                          (proc_data->drect.width * decx);
627         } else
628                 xscale = proc_data->srect.width * 0x1000 /
629                          proc_data->drect.width;
630         if (decy > 0) {
631                 if (decy >= 2 && decy < 4) {
632                         decy = 2;
633                         ydec = 1;
634                 } else if (decy >= 4 && decy < 8) {
635                         decy = 4;
636                         ydec = 2;
637                 } else if (decy >= 8) {
638                         decy = 8;
639                         ydec = 3;
640                 }
641                 yscale = proc_data->srect.height * 0x1000 /
642                          (proc_data->drect.height * decy);
643         } else
644                 yscale = proc_data->srect.height * 0x1000 /
645                          proc_data->drect.height;
646
647         __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
648
649         if (xscale > PXP_DOWNSCALE_THRESHOLD)
650                 xscale = PXP_DOWNSCALE_THRESHOLD;
651         if (yscale > PXP_DOWNSCALE_THRESHOLD)
652                 yscale = PXP_DOWNSCALE_THRESHOLD;
653         s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
654                 BF_PXP_PS_SCALE_XSCALE(xscale);
655         __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE);
656
657 out:
658         pxp_set_ctrl(pxp);
659
660         return ret;
661 }
662
663 static void pxp_set_bg(struct pxps *pxp)
664 {
665         __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
666                      pxp->base + HW_PXP_PS_BACKGROUND);
667 }
668
669 static void pxp_set_lut(struct pxps *pxp)
670 {
671         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
672         int lut_op = pxp_conf->proc_data.lut_transform;
673         u32 reg_val;
674         int i;
675         bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
676         u8 *cmap = pxp_conf->proc_data.lut_map;
677         u32 entry_src;
678         u32 pix_val;
679         u8 entry[4];
680
681         /*
682          * If LUT already configured as needed, return...
683          * Unless CMAP is needed and it has been updated.
684          */
685         if ((pxp->lut_state == lut_op) &&
686                 !(use_cmap && pxp_conf->proc_data.lut_map_updated))
687                 return;
688
689         if (lut_op == PXP_LUT_NONE) {
690                 __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
691                              pxp->base + HW_PXP_LUT_CTRL);
692         } else if (((lut_op & PXP_LUT_INVERT) != 0)
693                 && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
694                 /* Fill out LUT table with inverted monochromized values */
695
696                 /* clear bypass bit, set lookup mode & out mode */
697                 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
698                                 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
699                                 BF_PXP_LUT_CTRL_OUT_MODE
700                                 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
701                                 pxp->base + HW_PXP_LUT_CTRL);
702
703                 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
704                 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
705
706                 /* LUT address pointer auto-increments after each data write */
707                 for (pix_val = 0; pix_val < 256; pix_val += 4) {
708                         for (i = 0; i < 4; i++) {
709                                 entry_src = use_cmap ?
710                                         cmap[pix_val + i] : pix_val + i;
711                                 entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
712                         }
713                         reg_val = (entry[3] << 24) | (entry[2] << 16) |
714                                 (entry[1] << 8) | entry[0];
715                         __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
716                 }
717         } else if ((lut_op & PXP_LUT_INVERT) != 0) {
718                 /* Fill out LUT table with 8-bit inverted values */
719
720                 /* clear bypass bit, set lookup mode & out mode */
721                 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
722                                 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
723                                 BF_PXP_LUT_CTRL_OUT_MODE
724                                 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
725                                 pxp->base + HW_PXP_LUT_CTRL);
726
727                 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
728                 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
729
730                 /* LUT address pointer auto-increments after each data write */
731                 for (pix_val = 0; pix_val < 256; pix_val += 4) {
732                         for (i = 0; i < 4; i++) {
733                                 entry_src = use_cmap ?
734                                         cmap[pix_val + i] : pix_val + i;
735                                 entry[i] = ~entry_src & 0xFF;
736                         }
737                         reg_val = (entry[3] << 24) | (entry[2] << 16) |
738                                 (entry[1] << 8) | entry[0];
739                         __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
740                 }
741         } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
742                 /* Fill out LUT table with 8-bit monochromized values */
743
744                 /* clear bypass bit, set lookup mode & out mode */
745                 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
746                                 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
747                                 BF_PXP_LUT_CTRL_OUT_MODE
748                                 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
749                                 pxp->base + HW_PXP_LUT_CTRL);
750
751                 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
752                 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
753
754                 /* LUT address pointer auto-increments after each data write */
755                 for (pix_val = 0; pix_val < 256; pix_val += 4) {
756                         for (i = 0; i < 4; i++) {
757                                 entry_src = use_cmap ?
758                                         cmap[pix_val + i] : pix_val + i;
759                                 entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
760                         }
761                         reg_val = (entry[3] << 24) | (entry[2] << 16) |
762                                 (entry[1] << 8) | entry[0];
763                         __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
764                 }
765         } else if (use_cmap) {
766                 /* Fill out LUT table using colormap values */
767
768                 /* clear bypass bit, set lookup mode & out mode */
769                 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
770                                 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
771                                 BF_PXP_LUT_CTRL_OUT_MODE
772                                 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
773                                 pxp->base + HW_PXP_LUT_CTRL);
774
775                 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
776                 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
777
778                 /* LUT address pointer auto-increments after each data write */
779                 for (pix_val = 0; pix_val < 256; pix_val += 4) {
780                         for (i = 0; i < 4; i++)
781                                 entry[i] = cmap[pix_val + i];
782                         reg_val = (entry[3] << 24) | (entry[2] << 16) |
783                                 (entry[1] << 8) | entry[0];
784                         __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
785                 }
786         }
787
788         pxp->lut_state = lut_op;
789 }
790
791 static void pxp_set_csc(struct pxps *pxp)
792 {
793         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
794         struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
795         struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
796         struct pxp_layer_param *out_params = &pxp_conf->out_param;
797
798         bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
799         bool output_is_YUV = is_yuv(out_params->pixel_fmt);
800
801         if (input_is_YUV && output_is_YUV) {
802                 /*
803                  * Input = YUV, Output = YUV
804                  * No CSC unless we need to do combining
805                  */
806                 if (ol_params->combine_enable) {
807                         /* Must convert to RGB for combining with RGB overlay */
808
809                         /* CSC1 - YUV->RGB */
810                         __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0);
811                         __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1);
812                         __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2);
813
814                         /* CSC2 - RGB->YUV */
815                         __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
816                         __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
817                         __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
818                         __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
819                         __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
820                         __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
821                         __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
822                 } else {
823                         /* Input & Output both YUV, so bypass both CSCs */
824
825                         /* CSC1 - Bypass */
826                         __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
827
828                         /* CSC2 - Bypass */
829                         __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
830                 }
831         } else if (input_is_YUV && !output_is_YUV) {
832                 /*
833                  * Input = YUV, Output = RGB
834                  * Use CSC1 to convert to RGB
835                  */
836
837                 /* CSC1 - YUV->RGB */
838                 __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
839                 __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
840                 __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
841
842                 /* CSC2 - Bypass */
843                 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
844         } else if (!input_is_YUV && output_is_YUV) {
845                 /*
846                  * Input = RGB, Output = YUV
847                  * Use CSC2 to convert to YUV
848                  */
849
850                 /* CSC1 - Bypass */
851                 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
852
853                 /* CSC2 - RGB->YUV */
854                 __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
855                 __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
856                 __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
857                 __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
858                 __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
859                 __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
860                 __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
861         } else {
862                 /*
863                  * Input = RGB, Output = RGB
864                  * Input & Output both RGB, so bypass both CSCs
865                  */
866
867                 /* CSC1 - Bypass */
868                 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
869
870                 /* CSC2 - Bypass */
871                 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
872         }
873
874         /* YCrCb colorspace */
875         /* Not sure when we use this...no YCrCb formats are defined for PxP */
876         /*
877            __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
878            __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
879            __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
880          */
881
882 }
883
884 static void pxp_set_s0buf(struct pxps *pxp)
885 {
886         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
887         struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
888         struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
889         dma_addr_t Y, U, V;
890         dma_addr_t Y1, U1, V1;
891         u32 offset, bpp = 1;
892         u32 pitch = s0_params->stride ? s0_params->stride :
893                                         s0_params->width;
894
895         Y = s0_params->paddr;
896
897         if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
898                 bpp = 2;
899         else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
900                 bpp = 4;
901         offset = (proc_data->srect.top * s0_params->width +
902                  proc_data->srect.left) * bpp;
903         /* clipping or cropping */
904         Y1 = Y + offset;
905         __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF);
906         if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) ||
907             (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) ||
908             (s0_params->pixel_fmt == PXP_PIX_FMT_GREY)    ||
909             (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) {
910                 /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */
911                 int s = 2;
912                 if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
913                         s = 1;
914
915                 offset = proc_data->srect.top * s0_params->width / 4 +
916                          proc_data->srect.left / 2;
917                 U = Y + (s0_params->width * s0_params->height);
918                 U1 = U + offset;
919                 V = U + ((s0_params->width * s0_params->height) >> s);
920                 V1 = V + offset;
921                 __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
922                 __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF);
923         } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
924                  (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
925                  (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
926                  (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
927                 int s = 2;
928                 if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
929                     (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
930                         s = 1;
931
932                 offset = (proc_data->srect.top * s0_params->width +
933                           proc_data->srect.left) / s;
934                 U = Y + (s0_params->width * s0_params->height);
935                 U1 = U + offset;
936
937                 __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
938         }
939
940         /* TODO: only support RGB565, Y8, Y4, YUV420 */
941         if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY ||
942             s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P ||
943             s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P ||
944             s0_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
945             s0_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
946             s0_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
947             s0_params->pixel_fmt == PXP_PIX_FMT_NV61 ||
948             s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) {
949                 __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH);
950         }
951         else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04)
952                 __raw_writel(pitch >> 1,
953                                 pxp->base + HW_PXP_PS_PITCH);
954         else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
955                 __raw_writel(pitch << 2,
956                                 pxp->base + HW_PXP_PS_PITCH);
957         else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
958                  s0_params->pixel_fmt == PXP_PIX_FMT_YUYV ||
959                  s0_params->pixel_fmt == PXP_PIX_FMT_VYUY ||
960                  s0_params->pixel_fmt == PXP_PIX_FMT_YVYU)
961                 __raw_writel(pitch << 1,
962                                 pxp->base + HW_PXP_PS_PITCH);
963         else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
964                 __raw_writel(pitch << 1,
965                                 pxp->base + HW_PXP_PS_PITCH);
966         else
967                 __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
968 }
969
970 /**
971  * pxp_config() - configure PxP for a processing task
972  * @pxps:       PXP context.
973  * @pxp_chan:   PXP channel.
974  * @return:     0 on success or negative error code on failure.
975  */
976 static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
977 {
978         struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
979         int ol_nr;
980         int i;
981
982         /* Configure PxP regs */
983         pxp_set_ctrl(pxp);
984         pxp_set_s0param(pxp);
985         pxp_set_s0crop(pxp);
986         pxp_set_scaling(pxp);
987         ol_nr = pxp_conf_data->layer_nr - 2;
988         while (ol_nr > 0) {
989                 i = pxp_conf_data->layer_nr - 2 - ol_nr;
990                 pxp_set_oln(i, pxp);
991                 pxp_set_olparam(i, pxp);
992                 /* only the color key in higher overlay will take effect. */
993                 pxp_set_olcolorkey(i, pxp);
994                 ol_nr--;
995         }
996         pxp_set_s0colorkey(pxp);
997         pxp_set_csc(pxp);
998         pxp_set_bg(pxp);
999         pxp_set_lut(pxp);
1000
1001         pxp_set_s0buf(pxp);
1002         pxp_set_outbuf(pxp);
1003
1004         return 0;
1005 }
1006
1007 static void pxp_clk_enable(struct pxps *pxp)
1008 {
1009         mutex_lock(&pxp->clk_mutex);
1010
1011         if (pxp->clk_stat == CLK_STAT_ON) {
1012                 mutex_unlock(&pxp->clk_mutex);
1013                 return;
1014         }
1015
1016         clk_prepare_enable(pxp->clk);
1017         pxp->clk_stat = CLK_STAT_ON;
1018
1019         mutex_unlock(&pxp->clk_mutex);
1020 }
1021
1022 static void pxp_clk_disable(struct pxps *pxp)
1023 {
1024         unsigned long flags;
1025
1026         mutex_lock(&pxp->clk_mutex);
1027
1028         if (pxp->clk_stat == CLK_STAT_OFF) {
1029                 mutex_unlock(&pxp->clk_mutex);
1030                 return;
1031         }
1032
1033         spin_lock_irqsave(&pxp->lock, flags);
1034         if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
1035                 spin_unlock_irqrestore(&pxp->lock, flags);
1036                 clk_disable_unprepare(pxp->clk);
1037                 pxp->clk_stat = CLK_STAT_OFF;
1038         } else
1039                 spin_unlock_irqrestore(&pxp->lock, flags);
1040
1041         mutex_unlock(&pxp->clk_mutex);
1042 }
1043
1044 static inline void clkoff_callback(struct work_struct *w)
1045 {
1046         struct pxps *pxp = container_of(w, struct pxps, work);
1047
1048         pxp_clk_disable(pxp);
1049 }
1050
1051 static void pxp_clkoff_timer(unsigned long arg)
1052 {
1053         struct pxps *pxp = (struct pxps *)arg;
1054
1055         if ((pxp->pxp_ongoing == 0) && list_empty(&head))
1056                 schedule_work(&pxp->work);
1057         else
1058                 mod_timer(&pxp->clk_timer,
1059                           jiffies + msecs_to_jiffies(timeout_in_ms));
1060 }
1061
1062 static struct pxp_tx_desc *pxpdma_first_active(struct pxp_channel *pxp_chan)
1063 {
1064         return list_entry(pxp_chan->active_list.next, struct pxp_tx_desc, list);
1065 }
1066
1067 static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
1068 {
1069         return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
1070 }
1071
1072 /* called with pxp_chan->lock held */
1073 static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
1074 {
1075         struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
1076         struct pxps *pxp = to_pxp(pxp_dma);
1077         struct pxp_tx_desc *desc;
1078         struct pxp_tx_desc *child;
1079         int i = 0;
1080
1081         /* so far we presume only one transaction on active_list */
1082         /* S0 */
1083         desc = pxpdma_first_active(pxp_chan);
1084         memcpy(&pxp->pxp_conf_state.s0_param,
1085                &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
1086         memcpy(&pxp->pxp_conf_state.proc_data,
1087                &desc->proc_data, sizeof(struct pxp_proc_data));
1088
1089         /* Save PxP configuration */
1090         list_for_each_entry(child, &desc->tx_list, list) {
1091                 if (i == 0) {   /* Output */
1092                         memcpy(&pxp->pxp_conf_state.out_param,
1093                                &child->layer_param.out_param,
1094                                sizeof(struct pxp_layer_param));
1095                 } else {        /* Overlay */
1096                         memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
1097                                &child->layer_param.ol_param,
1098                                sizeof(struct pxp_layer_param));
1099                 }
1100
1101                 i++;
1102         }
1103         pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
1104                  pxp->pxp_conf_state.s0_param.width,
1105                  pxp->pxp_conf_state.s0_param.height,
1106                  pxp->pxp_conf_state.s0_param.paddr);
1107         pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
1108                  pxp->pxp_conf_state.out_param.width,
1109                  pxp->pxp_conf_state.out_param.height,
1110                  pxp->pxp_conf_state.out_param.paddr);
1111 }
1112
1113 static void pxpdma_dostart_work(struct pxps *pxp)
1114 {
1115         struct pxp_channel *pxp_chan = NULL;
1116         unsigned long flags, flags1;
1117
1118         spin_lock_irqsave(&pxp->lock, flags);
1119         if (list_empty(&head)) {
1120                 pxp->pxp_ongoing = 0;
1121                 spin_unlock_irqrestore(&pxp->lock, flags);
1122                 return;
1123         }
1124
1125         pxp_chan = list_entry(head.next, struct pxp_channel, list);
1126
1127         spin_lock_irqsave(&pxp_chan->lock, flags1);
1128         if (!list_empty(&pxp_chan->active_list)) {
1129                 struct pxp_tx_desc *desc;
1130                 /* REVISIT */
1131                 desc = pxpdma_first_active(pxp_chan);
1132                 __pxpdma_dostart(pxp_chan);
1133         }
1134         spin_unlock_irqrestore(&pxp_chan->lock, flags1);
1135
1136         /* Configure PxP */
1137         pxp_config(pxp, pxp_chan);
1138
1139         pxp_start(pxp);
1140
1141         spin_unlock_irqrestore(&pxp->lock, flags);
1142 }
1143
1144 static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct list_head *list)
1145 {
1146         struct pxp_tx_desc *desc = NULL;
1147         do {
1148                 desc = pxpdma_first_queued(pxp_chan);
1149                 list_move_tail(&desc->list, list);
1150         } while (!list_empty(&pxp_chan->queue));
1151 }
1152
1153 static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
1154 {
1155         struct pxp_tx_desc *desc = to_tx_desc(tx);
1156         struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
1157         dma_cookie_t cookie;
1158         unsigned long flags;
1159
1160         dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
1161
1162         mutex_lock(&pxp_chan->chan_mutex);
1163
1164         cookie = pxp_chan->dma_chan.cookie;
1165
1166         if (++cookie < 0)
1167                 cookie = 1;
1168
1169         /* from dmaengine.h: "last cookie value returned to client" */
1170         pxp_chan->dma_chan.cookie = cookie;
1171         tx->cookie = cookie;
1172
1173         /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
1174         spin_lock_irqsave(&pxp_chan->lock, flags);
1175
1176         /* Here we add the tx descriptor to our PxP task queue. */
1177         list_add_tail(&desc->list, &pxp_chan->queue);
1178
1179         spin_unlock_irqrestore(&pxp_chan->lock, flags);
1180
1181         dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
1182
1183         mutex_unlock(&pxp_chan->chan_mutex);
1184         return cookie;
1185 }
1186
1187 /* Called with pxp_chan->chan_mutex held */
1188 static int pxp_desc_alloc(struct pxp_channel *pxp_chan, int n)
1189 {
1190         struct pxp_tx_desc *desc = vmalloc(n * sizeof(struct pxp_tx_desc));
1191
1192         if (!desc)
1193                 return -ENOMEM;
1194
1195         pxp_chan->n_tx_desc = n;
1196         pxp_chan->desc = desc;
1197         INIT_LIST_HEAD(&pxp_chan->active_list);
1198         INIT_LIST_HEAD(&pxp_chan->queue);
1199         INIT_LIST_HEAD(&pxp_chan->free_list);
1200
1201         while (n--) {
1202                 struct dma_async_tx_descriptor *txd = &desc->txd;
1203
1204                 memset(txd, 0, sizeof(*txd));
1205                 INIT_LIST_HEAD(&desc->tx_list);
1206                 dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
1207                 txd->tx_submit = pxp_tx_submit;
1208
1209                 list_add(&desc->list, &pxp_chan->free_list);
1210
1211                 desc++;
1212         }
1213
1214         return 0;
1215 }
1216
1217 /**
1218  * pxp_init_channel() - initialize a PXP channel.
1219  * @pxp_dma:   PXP DMA context.
1220  * @pchan:  pointer to the channel object.
1221  * @return      0 on success or negative error code on failure.
1222  */
1223 static int pxp_init_channel(struct pxp_dma *pxp_dma,
1224                             struct pxp_channel *pxp_chan)
1225 {
1226         unsigned long flags;
1227         struct pxps *pxp = to_pxp(pxp_dma);
1228         int ret = 0, n_desc = 0;
1229
1230         /*
1231          * We are using _virtual_ channel here.
1232          * Each channel contains all parameters of corresponding layers
1233          * for one transaction; each layer is represented as one descriptor
1234          * (i.e., pxp_tx_desc) here.
1235          */
1236
1237         spin_lock_irqsave(&pxp->lock, flags);
1238
1239         /* max desc nr: S0+OL+OUT = 1+8+1 */
1240         n_desc = 16;
1241
1242         spin_unlock_irqrestore(&pxp->lock, flags);
1243
1244         if (n_desc && !pxp_chan->desc)
1245                 ret = pxp_desc_alloc(pxp_chan, n_desc);
1246
1247         return ret;
1248 }
1249
1250 /**
1251  * pxp_uninit_channel() - uninitialize a PXP channel.
1252  * @pxp_dma:   PXP DMA context.
1253  * @pchan:  pointer to the channel object.
1254  * @return      0 on success or negative error code on failure.
1255  */
1256 static int pxp_uninit_channel(struct pxp_dma *pxp_dma,
1257                               struct pxp_channel *pxp_chan)
1258 {
1259         int ret = 0;
1260
1261         if (pxp_chan->desc)
1262                 vfree(pxp_chan->desc);
1263
1264         pxp_chan->desc = NULL;
1265
1266         return ret;
1267 }
1268
1269 static irqreturn_t pxp_irq(int irq, void *dev_id)
1270 {
1271         struct pxps *pxp = dev_id;
1272         struct pxp_channel *pxp_chan;
1273         struct pxp_tx_desc *desc;
1274         dma_async_tx_callback callback;
1275         void *callback_param;
1276         unsigned long flags;
1277         u32 hist_status;
1278
1279         dump_pxp_reg(pxp);
1280
1281         hist_status =
1282             __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
1283
1284         __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
1285
1286         spin_lock_irqsave(&pxp->lock, flags);
1287
1288         if (list_empty(&head)) {
1289                 pxp->pxp_ongoing = 0;
1290                 spin_unlock_irqrestore(&pxp->lock, flags);
1291                 return IRQ_NONE;
1292         }
1293
1294         pxp_chan = list_entry(head.next, struct pxp_channel, list);
1295
1296         if (list_empty(&pxp_chan->active_list)) {
1297                 pr_debug("PXP_IRQ pxp_chan->active_list empty. chan_id %d\n",
1298                          pxp_chan->dma_chan.chan_id);
1299                 pxp->pxp_ongoing = 0;
1300                 spin_unlock_irqrestore(&pxp->lock, flags);
1301                 return IRQ_NONE;
1302         }
1303
1304         /* Get descriptor and call callback */
1305         desc = pxpdma_first_active(pxp_chan);
1306
1307         pxp_chan->completed = desc->txd.cookie;
1308
1309         callback = desc->txd.callback;
1310         callback_param = desc->txd.callback_param;
1311
1312         /* Send histogram status back to caller */
1313         desc->hist_status = hist_status;
1314
1315         if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
1316                 callback(callback_param);
1317
1318         pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1319
1320         list_splice_init(&desc->tx_list, &pxp_chan->free_list);
1321         list_move(&desc->list, &pxp_chan->free_list);
1322
1323         if (list_empty(&pxp_chan->active_list))
1324                 list_del_init(&pxp_chan->list);
1325
1326         complete(&pxp->complete);
1327         pxp->pxp_ongoing = 0;
1328         mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
1329
1330         spin_unlock_irqrestore(&pxp->lock, flags);
1331
1332         return IRQ_HANDLED;
1333 }
1334
1335 /* called with pxp_chan->lock held */
1336 static struct pxp_tx_desc *pxpdma_desc_get(struct pxp_channel *pxp_chan)
1337 {
1338         struct pxp_tx_desc *desc, *_desc;
1339         struct pxp_tx_desc *ret = NULL;
1340
1341         list_for_each_entry_safe(desc, _desc, &pxp_chan->free_list, list) {
1342                 list_del_init(&desc->list);
1343                 ret = desc;
1344                 break;
1345         }
1346
1347         return ret;
1348 }
1349
1350 /* called with pxp_chan->lock held */
1351 static void pxpdma_desc_put(struct pxp_channel *pxp_chan,
1352                             struct pxp_tx_desc *desc)
1353 {
1354         if (desc) {
1355                 struct device *dev = &pxp_chan->dma_chan.dev->device;
1356                 struct pxp_tx_desc *child;
1357
1358                 list_for_each_entry(child, &desc->tx_list, list)
1359                     dev_info(dev, "moving child desc %p to freelist\n", child);
1360                 list_splice_init(&desc->tx_list, &pxp_chan->free_list);
1361                 dev_info(dev, "moving desc %p to freelist\n", desc);
1362                 list_add(&desc->list, &pxp_chan->free_list);
1363         }
1364 }
1365
1366 /* Allocate and initialise a transfer descriptor. */
1367 static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
1368                                                          struct scatterlist
1369                                                          *sgl,
1370                                                          unsigned int sg_len,
1371                                                          enum
1372                                                          dma_transfer_direction
1373                                                          direction,
1374                                                          unsigned long tx_flags,
1375                                                          void *context)
1376 {
1377         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1378         struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1379         struct pxps *pxp = to_pxp(pxp_dma);
1380         struct pxp_tx_desc *desc = NULL;
1381         struct pxp_tx_desc *first = NULL, *prev = NULL;
1382         struct scatterlist *sg;
1383         unsigned long flags;
1384         dma_addr_t phys_addr;
1385         int i;
1386
1387         if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
1388                 dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
1389                         direction);
1390                 return NULL;
1391         }
1392
1393         if (unlikely(sg_len < 2))
1394                 return NULL;
1395
1396         spin_lock_irqsave(&pxp_chan->lock, flags);
1397         for_each_sg(sgl, sg, sg_len, i) {
1398                 desc = pxpdma_desc_get(pxp_chan);
1399                 if (!desc) {
1400                         pxpdma_desc_put(pxp_chan, first);
1401                         dev_err(chan->device->dev, "Can't get DMA desc.\n");
1402                         spin_unlock_irqrestore(&pxp_chan->lock, flags);
1403                         return NULL;
1404                 }
1405
1406                 phys_addr = sg_dma_address(sg);
1407
1408                 if (!first) {
1409                         first = desc;
1410
1411                         desc->layer_param.s0_param.paddr = phys_addr;
1412                 } else {
1413                         list_add_tail(&desc->list, &first->tx_list);
1414                         prev->next = desc;
1415                         desc->next = NULL;
1416
1417                         if (i == 1)
1418                                 desc->layer_param.out_param.paddr = phys_addr;
1419                         else
1420                                 desc->layer_param.ol_param.paddr = phys_addr;
1421                 }
1422
1423                 prev = desc;
1424         }
1425         spin_unlock_irqrestore(&pxp_chan->lock, flags);
1426
1427         pxp->pxp_conf_state.layer_nr = sg_len;
1428         first->txd.flags = tx_flags;
1429         first->len = sg_len;
1430         pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
1431                  __func__, __LINE__, first, first->len, first->txd.flags);
1432
1433         return &first->txd;
1434 }
1435
1436 static void pxp_issue_pending(struct dma_chan *chan)
1437 {
1438         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1439         struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1440         struct pxps *pxp = to_pxp(pxp_dma);
1441         unsigned long flags0, flags;
1442         struct list_head *iter;
1443
1444         spin_lock_irqsave(&pxp->lock, flags0);
1445         spin_lock_irqsave(&pxp_chan->lock, flags);
1446
1447         if (!list_empty(&pxp_chan->queue)) {
1448                 pxpdma_dequeue(pxp_chan, &pxp_chan->active_list);
1449                 pxp_chan->status = PXP_CHANNEL_READY;
1450                 iter = head.next;
1451                 /* Avoid adding a pxp channel to head list which
1452                  * has been already listed in it. And this may
1453                  * cause the head list to be broken down.
1454                  */
1455                 if (list_empty(&head)) {
1456                         list_add_tail(&pxp_chan->list, &head);
1457                 } else {
1458                         while (iter != &head) {
1459                                 if (&pxp_chan->list == iter)
1460                                         break;
1461                                 iter = iter->next;
1462                         }
1463                         if (iter == &head)
1464                                 list_add_tail(&pxp_chan->list, &head);
1465                 }
1466         } else {
1467                 spin_unlock_irqrestore(&pxp_chan->lock, flags);
1468                 spin_unlock_irqrestore(&pxp->lock, flags0);
1469                 return;
1470         }
1471         spin_unlock_irqrestore(&pxp_chan->lock, flags);
1472         spin_unlock_irqrestore(&pxp->lock, flags0);
1473
1474         pxp_clk_enable(pxp);
1475         wake_up_interruptible(&pxp->thread_waitq);
1476 }
1477
1478 static void __pxp_terminate_all(struct dma_chan *chan)
1479 {
1480         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1481         unsigned long flags;
1482
1483         /* pchan->queue is modified in ISR, have to spinlock */
1484         spin_lock_irqsave(&pxp_chan->lock, flags);
1485         list_splice_init(&pxp_chan->queue, &pxp_chan->free_list);
1486         list_splice_init(&pxp_chan->active_list, &pxp_chan->free_list);
1487
1488         spin_unlock_irqrestore(&pxp_chan->lock, flags);
1489
1490         pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1491 }
1492
1493 static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1494                         unsigned long arg)
1495 {
1496         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1497
1498         /* Only supports DMA_TERMINATE_ALL */
1499         if (cmd != DMA_TERMINATE_ALL)
1500                 return -ENXIO;
1501
1502         mutex_lock(&pxp_chan->chan_mutex);
1503         __pxp_terminate_all(chan);
1504         mutex_unlock(&pxp_chan->chan_mutex);
1505
1506         return 0;
1507 }
1508
1509 static int pxp_alloc_chan_resources(struct dma_chan *chan)
1510 {
1511         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1512         struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1513         int ret;
1514
1515         /* dmaengine.c now guarantees to only offer free channels */
1516         BUG_ON(chan->client_count > 1);
1517         WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
1518
1519         chan->cookie = 1;
1520         pxp_chan->completed = -ENXIO;
1521
1522         pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
1523         ret = pxp_init_channel(pxp_dma, pxp_chan);
1524         if (ret < 0)
1525                 goto err_chan;
1526
1527         pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1528
1529         dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
1530                 chan->chan_id, pxp_chan->eof_irq);
1531
1532         return ret;
1533
1534 err_chan:
1535         return ret;
1536 }
1537
1538 static void pxp_free_chan_resources(struct dma_chan *chan)
1539 {
1540         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1541         struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1542
1543         mutex_lock(&pxp_chan->chan_mutex);
1544
1545         __pxp_terminate_all(chan);
1546
1547         pxp_chan->status = PXP_CHANNEL_FREE;
1548
1549         pxp_uninit_channel(pxp_dma, pxp_chan);
1550
1551         mutex_unlock(&pxp_chan->chan_mutex);
1552 }
1553
1554 static enum dma_status pxp_tx_status(struct dma_chan *chan,
1555                                      dma_cookie_t cookie,
1556                                      struct dma_tx_state *txstate)
1557 {
1558         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1559
1560         if (cookie != chan->cookie)
1561                 return DMA_ERROR;
1562
1563         if (txstate) {
1564                 txstate->last = pxp_chan->completed;
1565                 txstate->used = chan->cookie;
1566                 txstate->residue = 0;
1567         }
1568         return DMA_SUCCESS;
1569 }
1570
1571 static int pxp_hw_init(struct pxps *pxp)
1572 {
1573         struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
1574         struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
1575         u32 reg_val;
1576
1577         /* Pull PxP out of reset */
1578         __raw_writel(0, pxp->base + HW_PXP_CTRL);
1579
1580         /* Config defaults */
1581
1582         /* Initialize non-channel-specific PxP parameters */
1583         proc_data->drect.left = proc_data->srect.left = 0;
1584         proc_data->drect.top = proc_data->srect.top = 0;
1585         proc_data->drect.width = proc_data->srect.width = 0;
1586         proc_data->drect.height = proc_data->srect.height = 0;
1587         proc_data->scaling = 0;
1588         proc_data->hflip = 0;
1589         proc_data->vflip = 0;
1590         proc_data->rotate = 0;
1591         proc_data->bgcolor = 0;
1592
1593         /* Initialize S0 channel parameters */
1594         pxp_conf->s0_param.pixel_fmt = pxp_s0_formats[0];
1595         pxp_conf->s0_param.width = 0;
1596         pxp_conf->s0_param.height = 0;
1597         pxp_conf->s0_param.color_key = -1;
1598         pxp_conf->s0_param.color_key_enable = false;
1599
1600         /* Initialize OL channel parameters */
1601         pxp_conf->ol_param[0].combine_enable = false;
1602         pxp_conf->ol_param[0].width = 0;
1603         pxp_conf->ol_param[0].height = 0;
1604         pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565;
1605         pxp_conf->ol_param[0].color_key_enable = false;
1606         pxp_conf->ol_param[0].color_key = -1;
1607         pxp_conf->ol_param[0].global_alpha_enable = false;
1608         pxp_conf->ol_param[0].global_alpha = 0;
1609         pxp_conf->ol_param[0].local_alpha_enable = false;
1610
1611         /* Initialize Output channel parameters */
1612         pxp_conf->out_param.width = 0;
1613         pxp_conf->out_param.height = 0;
1614         pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
1615
1616         proc_data->overlay_state = 0;
1617
1618         /* Write default h/w config */
1619         pxp_set_ctrl(pxp);
1620         pxp_set_s0param(pxp);
1621         pxp_set_s0crop(pxp);
1622         /*
1623          * simply program the ULC to a higher value than the LRC
1624          * to avoid any AS pixels to show up in the output buffer.
1625          */
1626         __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC);
1627         pxp_set_olparam(0, pxp);
1628         pxp_set_olcolorkey(0, pxp);
1629
1630         pxp_set_s0colorkey(pxp);
1631         pxp_set_csc(pxp);
1632         pxp_set_bg(pxp);
1633         pxp_set_lut(pxp);
1634
1635         /* One-time histogram configuration */
1636         reg_val =
1637             BF_PXP_HIST_CTRL_PANEL_MODE(BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16);
1638         __raw_writel(reg_val, pxp->base + HW_PXP_HIST_CTRL);
1639
1640         reg_val = BF_PXP_HIST2_PARAM_VALUE0(0x00) |
1641             BF_PXP_HIST2_PARAM_VALUE1(0x00F);
1642         __raw_writel(reg_val, pxp->base + HW_PXP_HIST2_PARAM);
1643
1644         reg_val = BF_PXP_HIST4_PARAM_VALUE0(0x00) |
1645             BF_PXP_HIST4_PARAM_VALUE1(0x05) |
1646             BF_PXP_HIST4_PARAM_VALUE2(0x0A) | BF_PXP_HIST4_PARAM_VALUE3(0x0F);
1647         __raw_writel(reg_val, pxp->base + HW_PXP_HIST4_PARAM);
1648
1649         reg_val = BF_PXP_HIST8_PARAM0_VALUE0(0x00) |
1650             BF_PXP_HIST8_PARAM0_VALUE1(0x02) |
1651             BF_PXP_HIST8_PARAM0_VALUE2(0x04) | BF_PXP_HIST8_PARAM0_VALUE3(0x06);
1652         __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM0);
1653         reg_val = BF_PXP_HIST8_PARAM1_VALUE4(0x09) |
1654             BF_PXP_HIST8_PARAM1_VALUE5(0x0B) |
1655             BF_PXP_HIST8_PARAM1_VALUE6(0x0D) | BF_PXP_HIST8_PARAM1_VALUE7(0x0F);
1656         __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM1);
1657
1658         reg_val = BF_PXP_HIST16_PARAM0_VALUE0(0x00) |
1659             BF_PXP_HIST16_PARAM0_VALUE1(0x01) |
1660             BF_PXP_HIST16_PARAM0_VALUE2(0x02) |
1661             BF_PXP_HIST16_PARAM0_VALUE3(0x03);
1662         __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM0);
1663         reg_val = BF_PXP_HIST16_PARAM1_VALUE4(0x04) |
1664             BF_PXP_HIST16_PARAM1_VALUE5(0x05) |
1665             BF_PXP_HIST16_PARAM1_VALUE6(0x06) |
1666             BF_PXP_HIST16_PARAM1_VALUE7(0x07);
1667         __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM1);
1668         reg_val = BF_PXP_HIST16_PARAM2_VALUE8(0x08) |
1669             BF_PXP_HIST16_PARAM2_VALUE9(0x09) |
1670             BF_PXP_HIST16_PARAM2_VALUE10(0x0A) |
1671             BF_PXP_HIST16_PARAM2_VALUE11(0x0B);
1672         __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM2);
1673         reg_val = BF_PXP_HIST16_PARAM3_VALUE12(0x0C) |
1674             BF_PXP_HIST16_PARAM3_VALUE13(0x0D) |
1675             BF_PXP_HIST16_PARAM3_VALUE14(0x0E) |
1676             BF_PXP_HIST16_PARAM3_VALUE15(0x0F);
1677         __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM3);
1678
1679         return 0;
1680 }
1681
1682 static int pxp_dma_init(struct pxps *pxp)
1683 {
1684         struct pxp_dma *pxp_dma = &pxp->pxp_dma;
1685         struct dma_device *dma = &pxp_dma->dma;
1686         int i;
1687
1688         dma_cap_set(DMA_SLAVE, dma->cap_mask);
1689         dma_cap_set(DMA_PRIVATE, dma->cap_mask);
1690
1691         /* Compulsory common fields */
1692         dma->dev = pxp->dev;
1693         dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
1694         dma->device_free_chan_resources = pxp_free_chan_resources;
1695         dma->device_tx_status = pxp_tx_status;
1696         dma->device_issue_pending = pxp_issue_pending;
1697
1698         /* Compulsory for DMA_SLAVE fields */
1699         dma->device_prep_slave_sg = pxp_prep_slave_sg;
1700         dma->device_control = pxp_control;
1701
1702         /* Initialize PxP Channels */
1703         INIT_LIST_HEAD(&dma->channels);
1704         for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
1705                 struct pxp_channel *pxp_chan = pxp->channel + i;
1706                 struct dma_chan *dma_chan = &pxp_chan->dma_chan;
1707
1708                 spin_lock_init(&pxp_chan->lock);
1709                 mutex_init(&pxp_chan->chan_mutex);
1710
1711                 /* Only one EOF IRQ for PxP, shared by all channels */
1712                 pxp_chan->eof_irq = pxp->irq;
1713                 pxp_chan->status = PXP_CHANNEL_FREE;
1714                 pxp_chan->completed = -ENXIO;
1715                 snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
1716                          "PXP EOF %d", i);
1717
1718                 dma_chan->device = &pxp_dma->dma;
1719                 dma_chan->cookie = 1;
1720                 dma_chan->chan_id = i;
1721                 list_add_tail(&dma_chan->device_node, &dma->channels);
1722         }
1723
1724         return dma_async_device_register(&pxp_dma->dma);
1725 }
1726
1727 static ssize_t clk_off_timeout_show(struct device *dev,
1728                                     struct device_attribute *attr, char *buf)
1729 {
1730         return sprintf(buf, "%d\n", timeout_in_ms);
1731 }
1732
1733 static ssize_t clk_off_timeout_store(struct device *dev,
1734                                      struct device_attribute *attr,
1735                                      const char *buf, size_t count)
1736 {
1737         int val;
1738         if (sscanf(buf, "%d", &val) > 0) {
1739                 timeout_in_ms = val;
1740                 return count;
1741         }
1742         return -EINVAL;
1743 }
1744
1745 static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
1746                    clk_off_timeout_store);
1747
1748 static ssize_t block_size_show(struct device *dev,
1749                                struct device_attribute *attr,
1750                                char *buf)
1751 {
1752         return sprintf(buf, "%d\n", block_size);
1753 }
1754
1755 static ssize_t block_size_store(struct device *dev,
1756                                 struct device_attribute *attr,
1757                                 const char *buf, size_t count)
1758 {
1759         char **last = NULL;
1760
1761         block_size = simple_strtoul(buf, last, 0);
1762         if (block_size > 1)
1763                 block_size = 1;
1764
1765         return count;
1766 }
1767 static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
1768                    block_size_show, block_size_store);
1769
1770 static const struct of_device_id imx_pxpdma_dt_ids[] = {
1771         { .compatible = "fsl,imx6dl-pxp-dma", },
1772         { /* sentinel */ }
1773 };
1774 MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
1775
1776 static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
1777 {
1778         int found;
1779         unsigned long flags;
1780
1781         spin_lock_irqsave(&pxp->lock, flags);
1782         found = !list_empty(&head);
1783         spin_unlock_irqrestore(&pxp->lock, flags);
1784
1785         return found;
1786 }
1787
1788 static int pxp_dispatch_thread(void *argv)
1789 {
1790         struct pxps *pxp = (struct pxps *)argv;
1791         struct pxp_channel *pending = NULL;
1792         unsigned long flags;
1793
1794         while (!kthread_should_stop()) {
1795                 int ret;
1796                 ret = wait_event_interruptible(pxp->thread_waitq,
1797                                         has_pending_task(pxp, pending));
1798                 if (signal_pending(current))
1799                         continue;
1800
1801                 spin_lock_irqsave(&pxp->lock, flags);
1802                 pxp->pxp_ongoing = 1;
1803                 spin_unlock_irqrestore(&pxp->lock, flags);
1804                 init_completion(&pxp->complete);
1805                 pxpdma_dostart_work(pxp);
1806                 ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
1807                 if (ret == 0) {
1808                         printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
1809                         break;
1810                 }
1811         }
1812
1813         return 0;
1814 }
1815
1816 static int pxp_probe(struct platform_device *pdev)
1817 {
1818         struct pxps *pxp;
1819         struct resource *res;
1820         int irq;
1821         int err = 0;
1822
1823         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1824         irq = platform_get_irq(pdev, 0);
1825         if (!res || irq < 0) {
1826                 err = -ENODEV;
1827                 goto exit;
1828         }
1829
1830         pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
1831         if (!pxp) {
1832                 dev_err(&pdev->dev, "failed to allocate control object\n");
1833                 err = -ENOMEM;
1834                 goto exit;
1835         }
1836
1837         pxp->dev = &pdev->dev;
1838
1839         platform_set_drvdata(pdev, pxp);
1840         pxp->irq = irq;
1841
1842         pxp->pxp_ongoing = 0;
1843         pxp->lut_state = 0;
1844
1845         spin_lock_init(&pxp->lock);
1846         mutex_init(&pxp->clk_mutex);
1847
1848         pxp->base = devm_request_and_ioremap(&pdev->dev, res);
1849         if (pxp->base == NULL) {
1850                 dev_err(&pdev->dev, "Couldn't ioremap regs\n");
1851                 err = -ENODEV;
1852                 goto exit;
1853         }
1854
1855         pxp->pdev = pdev;
1856
1857         pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
1858         clk_prepare_enable(pxp->clk);
1859
1860         err = pxp_hw_init(pxp);
1861         clk_disable_unprepare(pxp->clk);
1862         if (err) {
1863                 dev_err(&pdev->dev, "failed to initialize hardware\n");
1864                 goto exit;
1865         }
1866
1867         err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
1868                                 "pxp-dmaengine", pxp);
1869         if (err)
1870                 goto exit;
1871         /* Initialize DMA engine */
1872         err = pxp_dma_init(pxp);
1873         if (err < 0)
1874                 goto exit;
1875
1876         if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
1877                 dev_err(&pdev->dev,
1878                         "Unable to create file from clk_off_timeout\n");
1879                 goto exit;
1880         }
1881
1882         device_create_file(&pdev->dev, &dev_attr_block_size);
1883         dump_pxp_reg(pxp);
1884
1885         INIT_WORK(&pxp->work, clkoff_callback);
1886         init_timer(&pxp->clk_timer);
1887         pxp->clk_timer.function = pxp_clkoff_timer;
1888         pxp->clk_timer.data = (unsigned long)pxp;
1889
1890         /* allocate a kernel thread to dispatch pxp conf */
1891         pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
1892         if (IS_ERR(pxp->dispatch)) {
1893                 err = PTR_ERR(pxp->dispatch);
1894                 goto exit;
1895         }
1896         init_waitqueue_head(&pxp->thread_waitq);
1897
1898         register_pxp_device();
1899
1900 exit:
1901         if (err)
1902                 dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
1903         return err;
1904 }
1905
1906 static int pxp_remove(struct platform_device *pdev)
1907 {
1908         struct pxps *pxp = platform_get_drvdata(pdev);
1909
1910         unregister_pxp_device();
1911         kthread_stop(pxp->dispatch);
1912         cancel_work_sync(&pxp->work);
1913         del_timer_sync(&pxp->clk_timer);
1914         clk_disable_unprepare(pxp->clk);
1915         device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
1916         device_remove_file(&pdev->dev, &dev_attr_block_size);
1917         dma_async_device_unregister(&(pxp->pxp_dma.dma));
1918
1919         return 0;
1920 }
1921
1922 #ifdef CONFIG_PM
1923 static int pxp_suspend(struct platform_device *pdev, pm_message_t state)
1924 {
1925         struct pxps *pxp = platform_get_drvdata(pdev);
1926
1927         pxp_clk_enable(pxp);
1928         while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
1929                 ;
1930
1931         __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
1932         pxp_clk_disable(pxp);
1933
1934         return 0;
1935 }
1936
1937 static int pxp_resume(struct platform_device *pdev)
1938 {
1939         struct pxps *pxp = platform_get_drvdata(pdev);
1940
1941         pxp_clk_enable(pxp);
1942         /* Pull PxP out of reset */
1943         __raw_writel(0, pxp->base + HW_PXP_CTRL);
1944         pxp_clk_disable(pxp);
1945
1946         return 0;
1947 }
1948 #else
1949 #define pxp_suspend     NULL
1950 #define pxp_resume      NULL
1951 #endif
1952
1953 static struct platform_driver pxp_driver = {
1954         .driver = {
1955                         .name = "imx-pxp",
1956                         .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
1957                    },
1958         .probe = pxp_probe,
1959         .remove = pxp_remove,
1960         .suspend = pxp_suspend,
1961         .resume = pxp_resume,
1962 };
1963
1964 module_platform_driver(pxp_driver);
1965
1966
1967 MODULE_DESCRIPTION("i.MX PxP driver");
1968 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1969 MODULE_LICENSE("GPL");