2 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
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.
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.
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
20 * Based on STMP378X PxP driver
21 * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
24 #include <linux/dma-mapping.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.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>
42 #include "regs-pxp_v2.h"
44 #define PXP_DOWNSCALE_THRESHOLD 0x4000
46 static LIST_HEAD(head);
47 static int timeout_in_ms = 600;
48 static unsigned int block_size;
49 struct mutex hard_lock;
52 struct dma_device dma;
56 struct platform_device *pdev;
59 int irq; /* PXP IRQ to the CPU */
62 struct mutex clk_mutex;
64 #define CLK_STAT_OFF 0
70 struct pxp_dma pxp_dma;
71 struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
72 struct work_struct work;
74 /* describes most recent processing configuration */
75 struct pxp_config_data pxp_conf_state;
77 /* to turn clock off when pxp is inactive */
78 struct timer_list clk_timer;
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)
86 #define PXP_DEF_BUFS 2
89 static uint32_t pxp_s0_formats[] = {
98 * PXP common functions
100 static void dump_pxp_reg(struct pxps *pxp)
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));
214 static bool is_yuv(u32 pix_fmt)
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)) {
240 static void pxp_set_ctrl(struct pxps *pxp)
242 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
243 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
246 int need_swap = 0; /* to support YUYV and YVYU formats */
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;
253 case PXP_PIX_FMT_RGB565:
254 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
256 case PXP_PIX_FMT_RGB555:
257 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
259 case PXP_PIX_FMT_YUV420P:
260 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
262 case PXP_PIX_FMT_YVU420P:
263 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
265 case PXP_PIX_FMT_GREY:
266 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
268 case PXP_PIX_FMT_GY04:
269 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
271 case PXP_PIX_FMT_YUV422P:
272 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
274 case PXP_PIX_FMT_UYVY:
275 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
277 case PXP_PIX_FMT_YUYV:
278 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
281 case PXP_PIX_FMT_VYUY:
282 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
284 case PXP_PIX_FMT_YVYU:
285 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
288 case PXP_PIX_FMT_NV12:
289 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
291 case PXP_PIX_FMT_NV21:
292 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
294 case PXP_PIX_FMT_NV16:
295 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
297 case PXP_PIX_FMT_NV61:
298 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
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);
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;
312 case PXP_PIX_FMT_BGRA32:
313 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
315 case PXP_PIX_FMT_RGB24:
316 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
318 case PXP_PIX_FMT_RGB565:
319 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
321 case PXP_PIX_FMT_RGB555:
322 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
324 case PXP_PIX_FMT_GREY:
325 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
327 case PXP_PIX_FMT_GY04:
328 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
330 case PXP_PIX_FMT_UYVY:
331 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
333 case PXP_PIX_FMT_VYUY:
334 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
336 case PXP_PIX_FMT_NV12:
337 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
339 case PXP_PIX_FMT_NV21:
340 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
342 case PXP_PIX_FMT_NV16:
343 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
345 case PXP_PIX_FMT_NV61:
346 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
352 ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
353 __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
356 if (proc_data->scaling)
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;
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
372 ctrl |= block_size << 23;
374 __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
377 static int pxp_start(struct pxps *pxp)
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);
386 static void pxp_set_outbuf(struct pxps *pxp)
388 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
389 struct pxp_layer_param *out_params = &pxp_conf->out_param;
391 __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
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);
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);
422 __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
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);
434 static void pxp_set_s0colorkey(struct pxps *pxp)
436 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
437 struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
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);
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);
452 static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
454 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
455 struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
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);
464 /* disable color key */
465 __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
466 __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
470 static void pxp_set_oln(int layer_no, struct pxps *pxp)
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;
478 __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
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);
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);
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);
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);
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);
512 __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
516 static void pxp_set_olparam(int layer_no, struct pxps *pxp)
518 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
519 struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
522 olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
523 if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) {
525 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
526 } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
528 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
529 if (!olparams_data->combine_enable) {
531 BF_PXP_AS_CTRL_ALPHA_CTRL
532 (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
533 olparam |= 0x3 << 16;
535 } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
537 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
539 if (olparams_data->global_alpha_enable) {
540 if (olparams_data->global_override) {
542 BF_PXP_AS_CTRL_ALPHA_CTRL
543 (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
546 BF_PXP_AS_CTRL_ALPHA_CTRL
547 (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
549 if (olparams_data->alpha_invert)
550 olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
552 if (olparams_data->color_key_enable)
553 olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
555 __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
558 static void pxp_set_s0param(struct pxps *pxp)
560 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
561 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
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);
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);
581 /* crop behavior is re-designed in h/w. */
582 static void pxp_set_s0crop(struct pxps *pxp)
585 * place-holder, it's implemented in other functions in this driver.
586 * Refer to "Clipping source images" section in RM for detail.
590 static int pxp_set_scaling(struct pxps *pxp)
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;
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);
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;
610 if (decx >= 2 && decx < 4) {
613 } else if (decx >= 4 && decx < 8) {
616 } else if (decx >= 8) {
620 xscale = proc_data->srect.width * 0x1000 /
621 (proc_data->drect.width * decx);
623 xscale = proc_data->srect.width * 0x1000 /
624 proc_data->drect.width;
626 if (decy >= 2 && decy < 4) {
629 } else if (decy >= 4 && decy < 8) {
632 } else if (decy >= 8) {
636 yscale = proc_data->srect.height * 0x1000 /
637 (proc_data->drect.height * decy);
639 yscale = proc_data->srect.height * 0x1000 /
640 proc_data->drect.height;
642 __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
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);
658 static void pxp_set_bg(struct pxps *pxp)
660 __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
661 pxp->base + HW_PXP_PS_BACKGROUND);
664 static void pxp_set_lut(struct pxps *pxp)
666 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
667 int lut_op = pxp_conf->proc_data.lut_transform;
670 bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
671 u8 *cmap = pxp_conf->proc_data.lut_map;
677 * If LUT already configured as needed, return...
678 * Unless CMAP is needed and it has been updated.
680 if ((pxp->lut_state == lut_op) &&
681 !(use_cmap && pxp_conf->proc_data.lut_map_updated))
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 */
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);
698 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
699 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
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;
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);
712 } else if ((lut_op & PXP_LUT_INVERT) != 0) {
713 /* Fill out LUT table with 8-bit inverted values */
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);
722 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
723 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
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;
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);
736 } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
737 /* Fill out LUT table with 8-bit monochromized values */
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);
746 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
747 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
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;
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);
760 } else if (use_cmap) {
761 /* Fill out LUT table using colormap values */
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);
770 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
771 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
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);
783 pxp->lut_state = lut_op;
786 static void pxp_set_csc(struct pxps *pxp)
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;
793 bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
794 bool output_is_YUV = is_yuv(out_params->pixel_fmt);
796 if (input_is_YUV && output_is_YUV) {
798 * Input = YUV, Output = YUV
799 * No CSC unless we need to do combining
801 if (ol_params->combine_enable) {
802 /* Must convert to RGB for combining with RGB overlay */
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);
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);
818 /* Input & Output both YUV, so bypass both CSCs */
821 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
824 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
826 } else if (input_is_YUV && !output_is_YUV) {
828 * Input = YUV, Output = RGB
829 * Use CSC1 to convert to RGB
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);
838 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
839 } else if (!input_is_YUV && output_is_YUV) {
841 * Input = RGB, Output = YUV
842 * Use CSC2 to convert to YUV
846 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
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);
858 * Input = RGB, Output = RGB
859 * Input & Output both RGB, so bypass both CSCs
863 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
866 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
869 /* YCrCb colorspace */
870 /* Not sure when we use this...no YCrCb formats are defined for PxP */
872 __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
873 __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
874 __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
879 static void pxp_set_s0buf(struct pxps *pxp)
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;
885 dma_addr_t Y1, U1, V1;
887 u32 pitch = s0_params->stride ? s0_params->stride :
890 Y = s0_params->paddr;
892 if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
894 else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
896 offset = (proc_data->srect.top * s0_params->width +
897 proc_data->srect.left) * bpp;
898 /* clipping or cropping */
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 */
907 if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
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);
914 V = U + ((s0_params->width * s0_params->height) >> s);
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)) {
923 if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
924 (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
927 offset = (proc_data->srect.top * s0_params->width +
928 proc_data->srect.left) / s;
929 U = Y + (s0_params->width * s0_params->height);
932 __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
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);
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);
962 __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
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.
971 static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
973 struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
977 /* Configure PxP regs */
979 pxp_set_s0param(pxp);
981 pxp_set_scaling(pxp);
982 ol_nr = pxp_conf_data->layer_nr - 2;
984 i = pxp_conf_data->layer_nr - 2 - ol_nr;
986 pxp_set_olparam(i, pxp);
987 /* only the color key in higher overlay will take effect. */
988 pxp_set_olcolorkey(i, pxp);
991 pxp_set_s0colorkey(pxp);
1002 static void pxp_clk_enable(struct pxps *pxp)
1004 mutex_lock(&pxp->clk_mutex);
1006 if (pxp->clk_stat == CLK_STAT_ON) {
1007 mutex_unlock(&pxp->clk_mutex);
1011 clk_prepare_enable(pxp->clk);
1012 pxp->clk_stat = CLK_STAT_ON;
1014 mutex_unlock(&pxp->clk_mutex);
1017 static void pxp_clk_disable(struct pxps *pxp)
1019 unsigned long flags;
1021 mutex_lock(&pxp->clk_mutex);
1023 if (pxp->clk_stat == CLK_STAT_OFF) {
1024 mutex_unlock(&pxp->clk_mutex);
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;
1034 spin_unlock_irqrestore(&pxp->lock, flags);
1036 mutex_unlock(&pxp->clk_mutex);
1039 static inline void clkoff_callback(struct work_struct *w)
1041 struct pxps *pxp = container_of(w, struct pxps, work);
1043 pxp_clk_disable(pxp);
1046 static void pxp_clkoff_timer(unsigned long arg)
1048 struct pxps *pxp = (struct pxps *)arg;
1050 if ((pxp->pxp_ongoing == 0) && list_empty(&head))
1051 schedule_work(&pxp->work);
1053 mod_timer(&pxp->clk_timer,
1054 jiffies + msecs_to_jiffies(timeout_in_ms));
1057 static struct pxp_tx_desc *pxpdma_first_active(struct pxp_channel *pxp_chan)
1059 return list_entry(pxp_chan->active_list.next, struct pxp_tx_desc, list);
1062 static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
1064 return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
1067 /* called with pxp_chan->lock held */
1068 static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
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;
1076 /* so far we presume only one transaction on active_list */
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));
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));
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);
1108 static void pxpdma_dostart_work(struct pxps *pxp)
1110 struct pxp_channel *pxp_chan = NULL;
1111 unsigned long flags, flags1;
1113 spin_lock_irqsave(&pxp->lock, flags);
1114 if (list_empty(&head)) {
1115 pxp->pxp_ongoing = 0;
1116 spin_unlock_irqrestore(&pxp->lock, flags);
1120 pxp_chan = list_entry(head.next, struct pxp_channel, list);
1122 spin_lock_irqsave(&pxp_chan->lock, flags1);
1123 if (!list_empty(&pxp_chan->active_list)) {
1124 struct pxp_tx_desc *desc;
1126 desc = pxpdma_first_active(pxp_chan);
1127 __pxpdma_dostart(pxp_chan);
1129 spin_unlock_irqrestore(&pxp_chan->lock, flags1);
1132 pxp_config(pxp, pxp_chan);
1136 spin_unlock_irqrestore(&pxp->lock, flags);
1139 static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct list_head *list)
1141 struct pxp_tx_desc *desc = NULL;
1143 desc = pxpdma_first_queued(pxp_chan);
1144 list_move_tail(&desc->list, list);
1145 } while (!list_empty(&pxp_chan->queue));
1148 static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
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;
1155 dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
1157 mutex_lock(&pxp_chan->chan_mutex);
1159 cookie = pxp_chan->dma_chan.cookie;
1164 /* from dmaengine.h: "last cookie value returned to client" */
1165 pxp_chan->dma_chan.cookie = cookie;
1166 tx->cookie = cookie;
1168 /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
1169 spin_lock_irqsave(&pxp_chan->lock, flags);
1171 /* Here we add the tx descriptor to our PxP task queue. */
1172 list_add_tail(&desc->list, &pxp_chan->queue);
1174 spin_unlock_irqrestore(&pxp_chan->lock, flags);
1176 dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
1178 mutex_unlock(&pxp_chan->chan_mutex);
1182 /* Called with pxp_chan->chan_mutex held */
1183 static int pxp_desc_alloc(struct pxp_channel *pxp_chan, int n)
1185 struct pxp_tx_desc *desc = vmalloc(n * sizeof(struct pxp_tx_desc));
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);
1197 struct dma_async_tx_descriptor *txd = &desc->txd;
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;
1204 list_add(&desc->list, &pxp_chan->free_list);
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.
1218 static int pxp_init_channel(struct pxp_dma *pxp_dma,
1219 struct pxp_channel *pxp_chan)
1221 unsigned long flags;
1222 struct pxps *pxp = to_pxp(pxp_dma);
1223 int ret = 0, n_desc = 0;
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.
1232 spin_lock_irqsave(&pxp->lock, flags);
1234 /* max desc nr: S0+OL+OUT = 1+8+1 */
1237 spin_unlock_irqrestore(&pxp->lock, flags);
1239 if (n_desc && !pxp_chan->desc)
1240 ret = pxp_desc_alloc(pxp_chan, n_desc);
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.
1251 static int pxp_uninit_channel(struct pxp_dma *pxp_dma,
1252 struct pxp_channel *pxp_chan)
1257 vfree(pxp_chan->desc);
1259 pxp_chan->desc = NULL;
1264 static irqreturn_t pxp_irq(int irq, void *dev_id)
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;
1277 __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
1279 __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
1281 spin_lock_irqsave(&pxp->lock, flags);
1283 if (list_empty(&head)) {
1284 pxp->pxp_ongoing = 0;
1285 spin_unlock_irqrestore(&pxp->lock, flags);
1289 pxp_chan = list_entry(head.next, struct pxp_channel, list);
1290 list_del_init(&pxp_chan->list);
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);
1300 /* Get descriptor and call callback */
1301 desc = pxpdma_first_active(pxp_chan);
1303 pxp_chan->completed = desc->txd.cookie;
1305 callback = desc->txd.callback;
1306 callback_param = desc->txd.callback_param;
1308 /* Send histogram status back to caller */
1309 desc->hist_status = hist_status;
1311 if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
1312 callback(callback_param);
1314 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1316 list_splice_init(&desc->tx_list, &pxp_chan->free_list);
1317 list_move(&desc->list, &pxp_chan->free_list);
1319 mutex_unlock(&hard_lock);
1320 pxp->pxp_ongoing = 0;
1321 mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
1323 spin_unlock_irqrestore(&pxp->lock, flags);
1328 /* called with pxp_chan->lock held */
1329 static struct pxp_tx_desc *pxpdma_desc_get(struct pxp_channel *pxp_chan)
1331 struct pxp_tx_desc *desc, *_desc;
1332 struct pxp_tx_desc *ret = NULL;
1334 list_for_each_entry_safe(desc, _desc, &pxp_chan->free_list, list) {
1335 list_del_init(&desc->list);
1343 /* called with pxp_chan->lock held */
1344 static void pxpdma_desc_put(struct pxp_channel *pxp_chan,
1345 struct pxp_tx_desc *desc)
1348 struct device *dev = &pxp_chan->dma_chan.dev->device;
1349 struct pxp_tx_desc *child;
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);
1359 /* Allocate and initialise a transfer descriptor. */
1360 static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
1363 unsigned int sg_len,
1365 dma_transfer_direction
1367 unsigned long tx_flags,
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;
1380 if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
1381 dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
1386 if (unlikely(sg_len < 2))
1389 spin_lock_irqsave(&pxp_chan->lock, flags);
1390 for_each_sg(sgl, sg, sg_len, i) {
1391 desc = pxpdma_desc_get(pxp_chan);
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);
1399 phys_addr = sg_dma_address(sg);
1404 desc->layer_param.s0_param.paddr = phys_addr;
1406 list_add_tail(&desc->list, &first->tx_list);
1411 desc->layer_param.out_param.paddr = phys_addr;
1413 desc->layer_param.ol_param.paddr = phys_addr;
1418 spin_unlock_irqrestore(&pxp_chan->lock, flags);
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);
1429 static void pxp_issue_pending(struct dma_chan *chan)
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;
1436 spin_lock_irqsave(&pxp->lock, flags0);
1437 spin_lock_irqsave(&pxp_chan->lock, flags);
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);
1444 spin_unlock_irqrestore(&pxp_chan->lock, flags);
1445 spin_unlock_irqrestore(&pxp->lock, flags0);
1448 spin_unlock_irqrestore(&pxp_chan->lock, flags);
1449 spin_unlock_irqrestore(&pxp->lock, flags0);
1451 pxp_clk_enable(pxp);
1452 mutex_lock(&hard_lock);
1454 spin_lock_irqsave(&pxp->lock, flags);
1455 pxp->pxp_ongoing = 1;
1456 spin_unlock_irqrestore(&pxp->lock, flags);
1457 pxpdma_dostart_work(pxp);
1460 static void __pxp_terminate_all(struct dma_chan *chan)
1462 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1463 unsigned long flags;
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);
1470 spin_unlock_irqrestore(&pxp_chan->lock, flags);
1472 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1475 static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1478 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1480 /* Only supports DMA_TERMINATE_ALL */
1481 if (cmd != DMA_TERMINATE_ALL)
1484 mutex_lock(&pxp_chan->chan_mutex);
1485 __pxp_terminate_all(chan);
1486 mutex_unlock(&pxp_chan->chan_mutex);
1491 static int pxp_alloc_chan_resources(struct dma_chan *chan)
1493 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1494 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
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);
1502 pxp_chan->completed = -ENXIO;
1504 pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
1505 ret = pxp_init_channel(pxp_dma, pxp_chan);
1509 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1511 dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
1512 chan->chan_id, pxp_chan->eof_irq);
1520 static void pxp_free_chan_resources(struct dma_chan *chan)
1522 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1523 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1525 mutex_lock(&pxp_chan->chan_mutex);
1527 __pxp_terminate_all(chan);
1529 pxp_chan->status = PXP_CHANNEL_FREE;
1531 pxp_uninit_channel(pxp_dma, pxp_chan);
1533 mutex_unlock(&pxp_chan->chan_mutex);
1536 static enum dma_status pxp_tx_status(struct dma_chan *chan,
1537 dma_cookie_t cookie,
1538 struct dma_tx_state *txstate)
1540 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1542 if (cookie != chan->cookie)
1546 txstate->last = pxp_chan->completed;
1547 txstate->used = chan->cookie;
1548 txstate->residue = 0;
1553 static int pxp_hw_init(struct pxps *pxp)
1555 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
1556 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
1559 /* Pull PxP out of reset */
1560 __raw_writel(0, pxp->base + HW_PXP_CTRL);
1562 /* Config defaults */
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;
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;
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;
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;
1598 proc_data->overlay_state = 0;
1600 /* Write default h/w config */
1602 pxp_set_s0param(pxp);
1603 pxp_set_s0crop(pxp);
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.
1608 __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC);
1609 pxp_set_olparam(0, pxp);
1610 pxp_set_olcolorkey(0, pxp);
1612 pxp_set_s0colorkey(pxp);
1617 /* One-time histogram configuration */
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);
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);
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);
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);
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);
1664 static int pxp_dma_init(struct pxps *pxp)
1666 struct pxp_dma *pxp_dma = &pxp->pxp_dma;
1667 struct dma_device *dma = &pxp_dma->dma;
1670 dma_cap_set(DMA_SLAVE, dma->cap_mask);
1671 dma_cap_set(DMA_PRIVATE, dma->cap_mask);
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;
1680 /* Compulsory for DMA_SLAVE fields */
1681 dma->device_prep_slave_sg = pxp_prep_slave_sg;
1682 dma->device_control = pxp_control;
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;
1690 spin_lock_init(&pxp_chan->lock);
1691 mutex_init(&pxp_chan->chan_mutex);
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),
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);
1706 return dma_async_device_register(&pxp_dma->dma);
1709 static ssize_t clk_off_timeout_show(struct device *dev,
1710 struct device_attribute *attr, char *buf)
1712 return sprintf(buf, "%d\n", timeout_in_ms);
1715 static ssize_t clk_off_timeout_store(struct device *dev,
1716 struct device_attribute *attr,
1717 const char *buf, size_t count)
1720 if (sscanf(buf, "%d", &val) > 0) {
1721 timeout_in_ms = val;
1727 static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
1728 clk_off_timeout_store);
1730 static ssize_t block_size_show(struct device *dev,
1731 struct device_attribute *attr,
1734 return sprintf(buf, "%d\n", block_size);
1737 static ssize_t block_size_store(struct device *dev,
1738 struct device_attribute *attr,
1739 const char *buf, size_t count)
1743 block_size = simple_strtoul(buf, last, 0);
1749 static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
1750 block_size_show, block_size_store);
1752 static const struct of_device_id imx_pxpdma_dt_ids[] = {
1753 { .compatible = "fsl,imx6dl-pxp-dma", },
1756 MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
1758 static int pxp_probe(struct platform_device *pdev)
1761 struct resource *res;
1765 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1766 irq = platform_get_irq(pdev, 0);
1767 if (!res || irq < 0) {
1772 pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
1774 dev_err(&pdev->dev, "failed to allocate control object\n");
1779 pxp->dev = &pdev->dev;
1781 platform_set_drvdata(pdev, pxp);
1784 pxp->pxp_ongoing = 0;
1787 spin_lock_init(&pxp->lock);
1788 mutex_init(&pxp->clk_mutex);
1789 mutex_init(&hard_lock);
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");
1800 pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
1801 clk_prepare_enable(pxp->clk);
1803 err = pxp_hw_init(pxp);
1804 clk_disable_unprepare(pxp->clk);
1806 dev_err(&pdev->dev, "failed to initialize hardware\n");
1810 err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
1811 "pxp-dmaengine", pxp);
1814 /* Initialize DMA engine */
1815 err = pxp_dma_init(pxp);
1819 if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
1821 "Unable to create file from clk_off_timeout\n");
1825 device_create_file(&pdev->dev, &dev_attr_block_size);
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;
1833 register_pxp_device();
1837 dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
1841 static int pxp_remove(struct platform_device *pdev)
1843 struct pxps *pxp = platform_get_drvdata(pdev);
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));
1857 static int pxp_suspend(struct platform_device *pdev, pm_message_t state)
1859 struct pxps *pxp = platform_get_drvdata(pdev);
1861 pxp_clk_enable(pxp);
1862 while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
1865 __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
1866 pxp_clk_disable(pxp);
1871 static int pxp_resume(struct platform_device *pdev)
1873 struct pxps *pxp = platform_get_drvdata(pdev);
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);
1883 #define pxp_suspend NULL
1884 #define pxp_resume NULL
1887 static struct platform_driver pxp_driver = {
1890 .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
1893 .remove = pxp_remove,
1894 .suspend = pxp_suspend,
1895 .resume = pxp_resume,
1898 module_platform_driver(pxp_driver);
1901 MODULE_DESCRIPTION("i.MX PxP driver");
1902 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1903 MODULE_LICENSE("GPL");