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