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