2 * Copyright (C) 2010-2014 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/busfreq-imx6.h>
25 #include <linux/clk.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/dmaengine.h>
28 #include <linux/freezer.h>
29 #include <linux/init.h>
30 #include <linux/interrupt.h>
32 #include <linux/kernel.h>
33 #include <linux/kthread.h>
34 #include <linux/module.h>
35 #include <linux/mutex.h>
37 #include <linux/platform_device.h>
38 #include <linux/pm_runtime.h>
39 #include <linux/pxp_dma.h>
40 #include <linux/sched.h>
41 #include <linux/slab.h>
42 #include <linux/timer.h>
43 #include <linux/vmalloc.h>
44 #include <linux/workqueue.h>
46 #include "regs-pxp_v2.h"
48 #define PXP_DOWNSCALE_THRESHOLD 0x4000
50 static LIST_HEAD(head);
51 static int timeout_in_ms = 600;
52 static unsigned int block_size;
53 static struct kmem_cache *tx_desc_cache;
56 struct dma_device dma;
60 struct platform_device *pdev;
62 struct clk *clk_disp_axi; /* may exist on some SoC for gating */
64 int irq; /* PXP IRQ to the CPU */
67 struct mutex clk_mutex;
69 #define CLK_STAT_OFF 0
75 struct pxp_dma pxp_dma;
76 struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
77 struct work_struct work;
79 /* describes most recent processing configuration */
80 struct pxp_config_data pxp_conf_state;
82 /* to turn clock off when pxp is inactive */
83 struct timer_list clk_timer;
85 /* for pxp config dispatch asynchronously*/
86 struct task_struct *dispatch;
87 wait_queue_head_t thread_waitq;
88 struct completion complete;
91 #define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
92 #define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
93 #define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
94 #define to_pxp(id) container_of(id, struct pxps, pxp_dma)
96 #define PXP_DEF_BUFS 2
100 * PXP common functions
102 static void dump_pxp_reg(struct pxps *pxp)
104 dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
105 __raw_readl(pxp->base + HW_PXP_CTRL));
106 dev_dbg(pxp->dev, "PXP_STAT 0x%x",
107 __raw_readl(pxp->base + HW_PXP_STAT));
108 dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
109 __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
110 dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
111 __raw_readl(pxp->base + HW_PXP_OUT_BUF));
112 dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
113 __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
114 dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
115 __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
116 dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
117 __raw_readl(pxp->base + HW_PXP_OUT_LRC));
118 dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
119 __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
120 dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
121 __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
122 dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
123 __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
124 dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
125 __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
126 dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
127 __raw_readl(pxp->base + HW_PXP_PS_CTRL));
128 dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
129 __raw_readl(pxp->base + HW_PXP_PS_BUF));
130 dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
131 __raw_readl(pxp->base + HW_PXP_PS_UBUF));
132 dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
133 __raw_readl(pxp->base + HW_PXP_PS_VBUF));
134 dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
135 __raw_readl(pxp->base + HW_PXP_PS_PITCH));
136 dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x",
137 __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND));
138 dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
139 __raw_readl(pxp->base + HW_PXP_PS_SCALE));
140 dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
141 __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
142 dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x",
143 __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW));
144 dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
145 __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH));
146 dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
147 __raw_readl(pxp->base + HW_PXP_AS_CTRL));
148 dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
149 __raw_readl(pxp->base + HW_PXP_AS_BUF));
150 dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
151 __raw_readl(pxp->base + HW_PXP_AS_PITCH));
152 dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
153 __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW));
154 dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
155 __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH));
156 dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
157 __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
158 dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
159 __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
160 dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
161 __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
162 dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
163 __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
164 dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
165 __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
166 dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
167 __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
168 dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
169 __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
170 dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
171 __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
172 dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
173 __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
174 dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
175 __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
176 dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
177 __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
178 dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
179 __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
180 dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
181 __raw_readl(pxp->base + HW_PXP_LUT_DATA));
182 dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
183 __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
184 dev_dbg(pxp->dev, "PXP_CFA 0x%x",
185 __raw_readl(pxp->base + HW_PXP_CFA));
186 dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
187 __raw_readl(pxp->base + HW_PXP_HIST_CTRL));
188 dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
189 __raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
190 dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
191 __raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
192 dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
193 __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
194 dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
195 __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
196 dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
197 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
198 dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
199 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
200 dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
201 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
202 dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
203 __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
204 dev_dbg(pxp->dev, "PXP_POWER 0x%x",
205 __raw_readl(pxp->base + HW_PXP_POWER));
206 dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
207 __raw_readl(pxp->base + HW_PXP_NEXT));
208 dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
209 __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
210 dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
211 __raw_readl(pxp->base + HW_PXP_DEBUG));
212 dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
213 __raw_readl(pxp->base + HW_PXP_VERSION));
216 static bool is_yuv(u32 pix_fmt)
218 if ((pix_fmt == PXP_PIX_FMT_YUYV) |
219 (pix_fmt == PXP_PIX_FMT_UYVY) |
220 (pix_fmt == PXP_PIX_FMT_YVYU) |
221 (pix_fmt == PXP_PIX_FMT_VYUY) |
222 (pix_fmt == PXP_PIX_FMT_Y41P) |
223 (pix_fmt == PXP_PIX_FMT_YUV444) |
224 (pix_fmt == PXP_PIX_FMT_NV12) |
225 (pix_fmt == PXP_PIX_FMT_NV16) |
226 (pix_fmt == PXP_PIX_FMT_NV61) |
227 (pix_fmt == PXP_PIX_FMT_GREY) |
228 (pix_fmt == PXP_PIX_FMT_GY04) |
229 (pix_fmt == PXP_PIX_FMT_YVU410P) |
230 (pix_fmt == PXP_PIX_FMT_YUV410P) |
231 (pix_fmt == PXP_PIX_FMT_YVU420P) |
232 (pix_fmt == PXP_PIX_FMT_YUV420P) |
233 (pix_fmt == PXP_PIX_FMT_YUV420P2) |
234 (pix_fmt == PXP_PIX_FMT_YVU422P) |
235 (pix_fmt == PXP_PIX_FMT_YUV422P)) {
242 static void pxp_soft_reset(struct pxps *pxp)
244 __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
245 __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
247 __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_SET);
248 while (!(__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_CLKGATE))
249 dev_dbg(pxp->dev, "%s: wait for clock gate off", __func__);
251 __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
252 __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
255 static void pxp_set_ctrl(struct pxps *pxp)
257 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
258 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
261 int need_swap = 0; /* to support YUYV and YVYU formats */
263 /* Configure S0 input format */
264 switch (pxp_conf->s0_param.pixel_fmt) {
265 case PXP_PIX_FMT_RGB32:
266 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
268 case PXP_PIX_FMT_RGB565:
269 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
271 case PXP_PIX_FMT_RGB555:
272 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
274 case PXP_PIX_FMT_YUV420P:
275 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
277 case PXP_PIX_FMT_YVU420P:
278 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
280 case PXP_PIX_FMT_GREY:
281 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
283 case PXP_PIX_FMT_GY04:
284 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
286 case PXP_PIX_FMT_YUV444:
287 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV1P444;
289 case PXP_PIX_FMT_YUV422P:
290 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
292 case PXP_PIX_FMT_UYVY:
293 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
295 case PXP_PIX_FMT_YUYV:
296 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
299 case PXP_PIX_FMT_VYUY:
300 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
302 case PXP_PIX_FMT_YVYU:
303 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
306 case PXP_PIX_FMT_NV12:
307 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
309 case PXP_PIX_FMT_NV21:
310 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
312 case PXP_PIX_FMT_NV16:
313 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
315 case PXP_PIX_FMT_NV61:
316 fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
322 ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap);
323 __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET);
325 /* Configure output format based on out_channel format */
326 switch (pxp_conf->out_param.pixel_fmt) {
327 case PXP_PIX_FMT_RGB32:
328 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
330 case PXP_PIX_FMT_BGRA32:
331 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
333 case PXP_PIX_FMT_RGB24:
334 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
336 case PXP_PIX_FMT_RGB565:
337 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
339 case PXP_PIX_FMT_RGB555:
340 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
342 case PXP_PIX_FMT_GREY:
343 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
345 case PXP_PIX_FMT_GY04:
346 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
348 case PXP_PIX_FMT_UYVY:
349 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
351 case PXP_PIX_FMT_VYUY:
352 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
354 case PXP_PIX_FMT_NV12:
355 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
357 case PXP_PIX_FMT_NV21:
358 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
360 case PXP_PIX_FMT_NV16:
361 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
363 case PXP_PIX_FMT_NV61:
364 fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
370 ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
371 __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
374 if (proc_data->scaling)
376 if (proc_data->vflip)
377 ctrl |= BM_PXP_CTRL_VFLIP;
378 if (proc_data->hflip)
379 ctrl |= BM_PXP_CTRL_HFLIP;
380 if (proc_data->rotate) {
381 ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
382 if (proc_data->rot_pos)
383 ctrl |= BM_PXP_CTRL_ROT_POS;
386 /* In default, the block size is set to 8x8
387 * But block size can be set to 16x16 due to
388 * blocksize variable modification
390 ctrl |= block_size << 23;
392 __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
395 static int pxp_start(struct pxps *pxp)
397 __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET);
398 __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET);
404 static void pxp_set_outbuf(struct pxps *pxp)
406 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
407 struct pxp_layer_param *out_params = &pxp_conf->out_param;
408 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
410 __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
412 if (proc_data->rotate == 90 || proc_data->rotate == 270) {
413 if (proc_data->rot_pos == 1)
414 __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.height - 1) |
415 BF_PXP_OUT_LRC_Y(proc_data->drect.width - 1),
416 pxp->base + HW_PXP_OUT_LRC);
418 __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
419 BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
420 pxp->base + HW_PXP_OUT_LRC);
422 __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
423 BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
424 pxp->base + HW_PXP_OUT_LRC);
426 if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
427 __raw_writel(out_params->stride * 3,
428 pxp->base + HW_PXP_OUT_PITCH);
429 } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
430 out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
431 __raw_writel(out_params->stride << 2,
432 pxp->base + HW_PXP_OUT_PITCH);
433 } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) {
434 __raw_writel(out_params->stride << 1,
435 pxp->base + HW_PXP_OUT_PITCH);
436 } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
437 (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) {
438 __raw_writel(out_params->stride << 1,
439 pxp->base + HW_PXP_OUT_PITCH);
440 } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY ||
441 out_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
442 out_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
443 out_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
444 out_params->pixel_fmt == PXP_PIX_FMT_NV61) {
445 __raw_writel(out_params->stride,
446 pxp->base + HW_PXP_OUT_PITCH);
447 } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) {
448 __raw_writel(out_params->stride >> 1,
449 pxp->base + HW_PXP_OUT_PITCH);
451 __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
454 /* set global alpha if necessary */
455 if (out_params->global_alpha_enable) {
456 __raw_writel(out_params->global_alpha << 24,
457 pxp->base + HW_PXP_OUT_CTRL_SET);
458 __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT,
459 pxp->base + HW_PXP_OUT_CTRL_SET);
463 static void pxp_set_s0colorkey(struct pxps *pxp)
465 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
466 struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
468 /* Low and high are set equal. V4L does not allow a chromakey range */
469 if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
470 /* disable color key */
471 __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW);
472 __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH);
474 __raw_writel(s0_params->color_key,
475 pxp->base + HW_PXP_PS_CLRKEYLOW);
476 __raw_writel(s0_params->color_key,
477 pxp->base + HW_PXP_PS_CLRKEYHIGH);
481 static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
483 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
484 struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
486 /* Low and high are set equal. V4L does not allow a chromakey range */
487 if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
488 __raw_writel(ol_params->color_key,
489 pxp->base + HW_PXP_AS_CLRKEYLOW);
490 __raw_writel(ol_params->color_key,
491 pxp->base + HW_PXP_AS_CLRKEYHIGH);
493 /* disable color key */
494 __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
495 __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
499 static void pxp_set_oln(int layer_no, struct pxps *pxp)
501 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
502 struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
503 dma_addr_t phys_addr = olparams_data->paddr;
504 u32 pitch = olparams_data->stride ? olparams_data->stride :
505 olparams_data->width;
507 __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
510 if (olparams_data->width == 0 && olparams_data->height == 0) {
511 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
512 __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
514 __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
515 if (pxp_conf->proc_data.rotate == 90 ||
516 pxp_conf->proc_data.rotate == 270) {
517 if (pxp_conf->proc_data.rot_pos == 1) {
518 __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) |
519 BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1),
520 pxp->base + HW_PXP_OUT_AS_LRC);
522 __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
523 BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
524 pxp->base + HW_PXP_OUT_AS_LRC);
527 __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
528 BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
529 pxp->base + HW_PXP_OUT_AS_LRC);
533 if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) |
534 (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) {
535 __raw_writel(pitch << 2,
536 pxp->base + HW_PXP_AS_PITCH);
537 } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
538 __raw_writel(pitch << 1,
539 pxp->base + HW_PXP_AS_PITCH);
541 __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
545 static void pxp_set_olparam(int layer_no, struct pxps *pxp)
547 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
548 struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
551 olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
552 if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) {
554 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
555 } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
557 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
558 if (!olparams_data->combine_enable) {
560 BF_PXP_AS_CTRL_ALPHA_CTRL
561 (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
562 olparam |= 0x3 << 16;
564 } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
566 BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
568 if (olparams_data->global_alpha_enable) {
569 if (olparams_data->global_override) {
571 BF_PXP_AS_CTRL_ALPHA_CTRL
572 (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
575 BF_PXP_AS_CTRL_ALPHA_CTRL
576 (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
578 if (olparams_data->alpha_invert)
579 olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
581 if (olparams_data->color_key_enable)
582 olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
584 __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
587 static void pxp_set_s0param(struct pxps *pxp)
589 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
590 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
591 struct pxp_layer_param *out_params = &pxp_conf->out_param;
594 if (proc_data->drect.left != 0 || proc_data->drect.top != 0) {
595 out_params->paddr += (proc_data->drect.top * out_params->stride +
596 proc_data->drect.left) * 2;
597 proc_data->drect.left = proc_data->drect.top = 0;
600 /* Since user apps always pass the rotated drect
601 * to this driver, we need to first swap the width
602 * and height which is used to calculate the scale
605 if (proc_data->rotate == 90 || proc_data->rotate == 270) {
607 temp = proc_data->drect.width;
608 proc_data->drect.width = proc_data->drect.height;
609 proc_data->drect.height = temp;
612 /* contains the coordinate for the PS in the OUTPUT buffer. */
613 if ((pxp_conf->s0_param).width == 0 &&
614 (pxp_conf->s0_param).height == 0) {
615 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
616 __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
618 s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
619 s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
620 __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC);
621 /* In PXP, the two different rotation
622 * position requires different settings
623 * on OUT_PS_LRC register
625 if (proc_data->rot_pos == 1) {
626 s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
627 proc_data->drect.height - 1);
628 s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
629 proc_data->drect.width - 1);
631 s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
632 proc_data->drect.width - 1);
633 s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
634 proc_data->drect.height - 1);
636 __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC);
640 /* crop behavior is re-designed in h/w. */
641 static void pxp_set_s0crop(struct pxps *pxp)
644 * place-holder, it's implemented in other functions in this driver.
645 * Refer to "Clipping source images" section in RM for detail.
649 static int pxp_set_scaling(struct pxps *pxp)
652 u32 xscale, yscale, s0scale;
653 u32 decx, decy, xdec = 0, ydec = 0;
654 struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
655 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
656 struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
658 proc_data->scaling = 1;
659 decx = proc_data->srect.width / proc_data->drect.width;
660 decy = proc_data->srect.height / proc_data->drect.height;
662 if (decx >= 2 && decx < 4) {
665 } else if (decx >= 4 && decx < 8) {
668 } else if (decx >= 8) {
672 xscale = proc_data->srect.width * 0x1000 /
673 (proc_data->drect.width * decx);
675 if (!is_yuv(s0_params->pixel_fmt) ||
676 (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
677 (s0_params->pixel_fmt == PXP_PIX_FMT_GY04) ||
678 (s0_params->pixel_fmt == PXP_PIX_FMT_YUV444))
679 xscale = (proc_data->srect.width - 1) * 0x1000 /
680 (proc_data->drect.width - 1);
682 xscale = (proc_data->srect.width - 2) * 0x1000 /
683 (proc_data->drect.width - 1);
686 if (decy >= 2 && decy < 4) {
689 } else if (decy >= 4 && decy < 8) {
692 } else if (decy >= 8) {
696 yscale = proc_data->srect.height * 0x1000 /
697 (proc_data->drect.height * decy);
699 yscale = (proc_data->srect.height - 1) * 0x1000 /
700 (proc_data->drect.height - 1);
702 __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
704 if (xscale > PXP_DOWNSCALE_THRESHOLD)
705 xscale = PXP_DOWNSCALE_THRESHOLD;
706 if (yscale > PXP_DOWNSCALE_THRESHOLD)
707 yscale = PXP_DOWNSCALE_THRESHOLD;
708 s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
709 BF_PXP_PS_SCALE_XSCALE(xscale);
710 __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE);
717 static void pxp_set_bg(struct pxps *pxp)
719 __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
720 pxp->base + HW_PXP_PS_BACKGROUND);
723 static void pxp_set_lut(struct pxps *pxp)
725 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
726 int lut_op = pxp_conf->proc_data.lut_transform;
729 bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
730 u8 *cmap = pxp_conf->proc_data.lut_map;
736 * If LUT already configured as needed, return...
737 * Unless CMAP is needed and it has been updated.
739 if ((pxp->lut_state == lut_op) &&
740 !(use_cmap && pxp_conf->proc_data.lut_map_updated))
743 if (lut_op == PXP_LUT_NONE) {
744 __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
745 pxp->base + HW_PXP_LUT_CTRL);
746 } else if (((lut_op & PXP_LUT_INVERT) != 0)
747 && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
748 /* Fill out LUT table with inverted monochromized values */
750 /* clear bypass bit, set lookup mode & out mode */
751 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
752 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
753 BF_PXP_LUT_CTRL_OUT_MODE
754 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
755 pxp->base + HW_PXP_LUT_CTRL);
757 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
758 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
760 /* LUT address pointer auto-increments after each data write */
761 for (pix_val = 0; pix_val < 256; pix_val += 4) {
762 for (i = 0; i < 4; i++) {
763 entry_src = use_cmap ?
764 cmap[pix_val + i] : pix_val + i;
765 entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
767 reg_val = (entry[3] << 24) | (entry[2] << 16) |
768 (entry[1] << 8) | entry[0];
769 __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
771 } else if ((lut_op & PXP_LUT_INVERT) != 0) {
772 /* Fill out LUT table with 8-bit inverted values */
774 /* clear bypass bit, set lookup mode & out mode */
775 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
776 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
777 BF_PXP_LUT_CTRL_OUT_MODE
778 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
779 pxp->base + HW_PXP_LUT_CTRL);
781 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
782 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
784 /* LUT address pointer auto-increments after each data write */
785 for (pix_val = 0; pix_val < 256; pix_val += 4) {
786 for (i = 0; i < 4; i++) {
787 entry_src = use_cmap ?
788 cmap[pix_val + i] : pix_val + i;
789 entry[i] = ~entry_src & 0xFF;
791 reg_val = (entry[3] << 24) | (entry[2] << 16) |
792 (entry[1] << 8) | entry[0];
793 __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
795 } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
796 /* Fill out LUT table with 8-bit monochromized values */
798 /* clear bypass bit, set lookup mode & out mode */
799 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
800 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
801 BF_PXP_LUT_CTRL_OUT_MODE
802 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
803 pxp->base + HW_PXP_LUT_CTRL);
805 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
806 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
808 /* LUT address pointer auto-increments after each data write */
809 for (pix_val = 0; pix_val < 256; pix_val += 4) {
810 for (i = 0; i < 4; i++) {
811 entry_src = use_cmap ?
812 cmap[pix_val + i] : pix_val + i;
813 entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
815 reg_val = (entry[3] << 24) | (entry[2] << 16) |
816 (entry[1] << 8) | entry[0];
817 __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
819 } else if (use_cmap) {
820 /* Fill out LUT table using colormap values */
822 /* clear bypass bit, set lookup mode & out mode */
823 __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
824 (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
825 BF_PXP_LUT_CTRL_OUT_MODE
826 (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
827 pxp->base + HW_PXP_LUT_CTRL);
829 /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
830 __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
832 /* LUT address pointer auto-increments after each data write */
833 for (pix_val = 0; pix_val < 256; pix_val += 4) {
834 for (i = 0; i < 4; i++)
835 entry[i] = cmap[pix_val + i];
836 reg_val = (entry[3] << 24) | (entry[2] << 16) |
837 (entry[1] << 8) | entry[0];
838 __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
842 pxp->lut_state = lut_op;
845 static void pxp_set_csc(struct pxps *pxp)
847 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
848 struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
849 struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
850 struct pxp_layer_param *out_params = &pxp_conf->out_param;
852 bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
853 bool output_is_YUV = is_yuv(out_params->pixel_fmt);
855 if (input_is_YUV && output_is_YUV) {
857 * Input = YUV, Output = YUV
858 * No CSC unless we need to do combining
860 if (ol_params->combine_enable) {
861 /* Must convert to RGB for combining with RGB overlay */
863 /* CSC1 - YUV->RGB */
864 __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0);
865 __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1);
866 __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2);
868 /* CSC2 - RGB->YUV */
869 __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
870 __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
871 __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
872 __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
873 __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
874 __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
875 __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
877 /* Input & Output both YUV, so bypass both CSCs */
880 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
883 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
885 } else if (input_is_YUV && !output_is_YUV) {
887 * Input = YUV, Output = RGB
888 * Use CSC1 to convert to RGB
891 /* CSC1 - YUV->RGB */
892 __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
893 __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
894 __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
897 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
898 } else if (!input_is_YUV && output_is_YUV) {
900 * Input = RGB, Output = YUV
901 * Use CSC2 to convert to YUV
905 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
907 /* CSC2 - RGB->YUV */
908 __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
909 __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
910 __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
911 __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
912 __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
913 __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
914 __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
917 * Input = RGB, Output = RGB
918 * Input & Output both RGB, so bypass both CSCs
922 __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
925 __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
928 /* YCrCb colorspace */
929 /* Not sure when we use this...no YCrCb formats are defined for PxP */
931 __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
932 __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
933 __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
938 static void pxp_set_s0buf(struct pxps *pxp)
940 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
941 struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
942 struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
944 dma_addr_t Y1, U1, V1;
946 u32 pitch = s0_params->stride ? s0_params->stride :
949 Y = s0_params->paddr;
951 if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
953 else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
955 offset = (proc_data->srect.top * s0_params->width +
956 proc_data->srect.left) * bpp;
957 /* clipping or cropping */
959 __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF);
960 if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) ||
961 (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) ||
962 (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
963 (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) {
964 /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */
966 if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
969 offset = proc_data->srect.top * s0_params->width / 4 +
970 proc_data->srect.left / 2;
971 U = Y + (s0_params->width * s0_params->height);
973 V = U + ((s0_params->width * s0_params->height) >> s);
975 if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) {
976 __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF);
977 __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF);
979 __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
980 __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF);
982 } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
983 (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
984 (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
985 (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
987 if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
988 (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
991 offset = (proc_data->srect.top * s0_params->width +
992 proc_data->srect.left) / s;
993 U = Y + (s0_params->width * s0_params->height);
996 __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
999 /* TODO: only support RGB565, Y8, Y4, YUV420 */
1000 if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY ||
1001 s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P ||
1002 s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P ||
1003 s0_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
1004 s0_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
1005 s0_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
1006 s0_params->pixel_fmt == PXP_PIX_FMT_NV61 ||
1007 s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) {
1008 __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH);
1010 else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04)
1011 __raw_writel(pitch >> 1,
1012 pxp->base + HW_PXP_PS_PITCH);
1013 else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32 ||
1014 s0_params->pixel_fmt == PXP_PIX_FMT_YUV444)
1015 __raw_writel(pitch << 2,
1016 pxp->base + HW_PXP_PS_PITCH);
1017 else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
1018 s0_params->pixel_fmt == PXP_PIX_FMT_YUYV ||
1019 s0_params->pixel_fmt == PXP_PIX_FMT_VYUY ||
1020 s0_params->pixel_fmt == PXP_PIX_FMT_YVYU)
1021 __raw_writel(pitch << 1,
1022 pxp->base + HW_PXP_PS_PITCH);
1023 else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
1024 __raw_writel(pitch << 1,
1025 pxp->base + HW_PXP_PS_PITCH);
1027 __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
1031 * pxp_config() - configure PxP for a processing task
1032 * @pxps: PXP context.
1033 * @pxp_chan: PXP channel.
1034 * @return: 0 on success or negative error code on failure.
1036 static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
1038 struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
1042 /* Configure PxP regs */
1044 pxp_set_s0param(pxp);
1045 pxp_set_s0crop(pxp);
1046 pxp_set_scaling(pxp);
1047 ol_nr = pxp_conf_data->layer_nr - 2;
1049 i = pxp_conf_data->layer_nr - 2 - ol_nr;
1050 pxp_set_oln(i, pxp);
1051 pxp_set_olparam(i, pxp);
1052 /* only the color key in higher overlay will take effect. */
1053 pxp_set_olcolorkey(i, pxp);
1056 pxp_set_s0colorkey(pxp);
1062 pxp_set_outbuf(pxp);
1067 static void pxp_clk_enable(struct pxps *pxp)
1069 mutex_lock(&pxp->clk_mutex);
1071 if (pxp->clk_stat == CLK_STAT_ON) {
1072 mutex_unlock(&pxp->clk_mutex);
1076 pm_runtime_get_sync(pxp->dev);
1078 if (pxp->clk_disp_axi)
1079 clk_prepare_enable(pxp->clk_disp_axi);
1080 clk_prepare_enable(pxp->clk);
1081 pxp->clk_stat = CLK_STAT_ON;
1083 mutex_unlock(&pxp->clk_mutex);
1086 static void pxp_clk_disable(struct pxps *pxp)
1088 unsigned long flags;
1090 mutex_lock(&pxp->clk_mutex);
1092 if (pxp->clk_stat == CLK_STAT_OFF) {
1093 mutex_unlock(&pxp->clk_mutex);
1097 spin_lock_irqsave(&pxp->lock, flags);
1098 if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
1099 spin_unlock_irqrestore(&pxp->lock, flags);
1100 clk_disable_unprepare(pxp->clk);
1101 if (pxp->clk_disp_axi)
1102 clk_disable_unprepare(pxp->clk_disp_axi);
1103 pxp->clk_stat = CLK_STAT_OFF;
1105 spin_unlock_irqrestore(&pxp->lock, flags);
1107 pm_runtime_put_sync_suspend(pxp->dev);
1109 mutex_unlock(&pxp->clk_mutex);
1112 static inline void clkoff_callback(struct work_struct *w)
1114 struct pxps *pxp = container_of(w, struct pxps, work);
1116 pxp_clk_disable(pxp);
1119 static void pxp_clkoff_timer(unsigned long arg)
1121 struct pxps *pxp = (struct pxps *)arg;
1123 if ((pxp->pxp_ongoing == 0) && list_empty(&head))
1124 schedule_work(&pxp->work);
1126 mod_timer(&pxp->clk_timer,
1127 jiffies + msecs_to_jiffies(timeout_in_ms));
1130 static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
1132 return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
1135 /* called with pxp_chan->lock held */
1136 static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
1138 struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
1139 struct pxps *pxp = to_pxp(pxp_dma);
1140 struct pxp_tx_desc *desc;
1141 struct pxp_tx_desc *child;
1144 memset(&pxp->pxp_conf_state, 0, sizeof(struct pxp_config_data));
1146 desc = list_first_entry(&head, struct pxp_tx_desc, list);
1147 memcpy(&pxp->pxp_conf_state.s0_param,
1148 &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
1149 memcpy(&pxp->pxp_conf_state.proc_data,
1150 &desc->proc_data, sizeof(struct pxp_proc_data));
1152 /* Save PxP configuration */
1153 list_for_each_entry(child, &desc->tx_list, list) {
1154 if (i == 0) { /* Output */
1155 memcpy(&pxp->pxp_conf_state.out_param,
1156 &child->layer_param.out_param,
1157 sizeof(struct pxp_layer_param));
1158 } else { /* Overlay */
1159 memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
1160 &child->layer_param.ol_param,
1161 sizeof(struct pxp_layer_param));
1166 pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
1167 pxp->pxp_conf_state.s0_param.width,
1168 pxp->pxp_conf_state.s0_param.height,
1169 pxp->pxp_conf_state.s0_param.paddr);
1170 pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
1171 pxp->pxp_conf_state.out_param.width,
1172 pxp->pxp_conf_state.out_param.height,
1173 pxp->pxp_conf_state.out_param.paddr);
1176 static void pxpdma_dostart_work(struct pxps *pxp)
1178 struct pxp_channel *pxp_chan = NULL;
1179 unsigned long flags;
1180 struct pxp_tx_desc *desc = NULL;
1182 spin_lock_irqsave(&pxp->lock, flags);
1184 desc = list_entry(head.next, struct pxp_tx_desc, list);
1185 pxp_chan = to_pxp_channel(desc->txd.chan);
1187 __pxpdma_dostart(pxp_chan);
1190 pxp_config(pxp, pxp_chan);
1194 spin_unlock_irqrestore(&pxp->lock, flags);
1197 static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
1199 unsigned long flags;
1200 struct pxp_tx_desc *desc = NULL;
1203 desc = pxpdma_first_queued(pxp_chan);
1204 spin_lock_irqsave(&pxp->lock, flags);
1205 list_move_tail(&desc->list, &head);
1206 spin_unlock_irqrestore(&pxp->lock, flags);
1207 } while (!list_empty(&pxp_chan->queue));
1210 static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
1212 struct pxp_tx_desc *desc = to_tx_desc(tx);
1213 struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
1214 dma_cookie_t cookie;
1216 dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
1218 /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
1219 spin_lock(&pxp_chan->lock);
1221 cookie = pxp_chan->dma_chan.cookie;
1226 /* from dmaengine.h: "last cookie value returned to client" */
1227 pxp_chan->dma_chan.cookie = cookie;
1228 tx->cookie = cookie;
1230 /* Here we add the tx descriptor to our PxP task queue. */
1231 list_add_tail(&desc->list, &pxp_chan->queue);
1233 spin_unlock(&pxp_chan->lock);
1235 dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
1241 * pxp_init_channel() - initialize a PXP channel.
1242 * @pxp_dma: PXP DMA context.
1243 * @pchan: pointer to the channel object.
1244 * @return 0 on success or negative error code on failure.
1246 static int pxp_init_channel(struct pxp_dma *pxp_dma,
1247 struct pxp_channel *pxp_chan)
1252 * We are using _virtual_ channel here.
1253 * Each channel contains all parameters of corresponding layers
1254 * for one transaction; each layer is represented as one descriptor
1255 * (i.e., pxp_tx_desc) here.
1258 INIT_LIST_HEAD(&pxp_chan->queue);
1263 static irqreturn_t pxp_irq(int irq, void *dev_id)
1265 struct pxps *pxp = dev_id;
1266 struct pxp_channel *pxp_chan;
1267 struct pxp_tx_desc *desc;
1268 struct pxp_tx_desc *child, *_child;
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 /* set the SFTRST bit to be 1 to reset
1282 * the PXP block to its default state.
1284 pxp_soft_reset(pxp);
1286 spin_lock_irqsave(&pxp->lock, flags);
1288 if (list_empty(&head)) {
1289 pxp->pxp_ongoing = 0;
1290 spin_unlock_irqrestore(&pxp->lock, flags);
1294 /* Get descriptor and call callback */
1295 desc = list_entry(head.next, struct pxp_tx_desc, list);
1296 pxp_chan = to_pxp_channel(desc->txd.chan);
1298 pxp_chan->completed = desc->txd.cookie;
1300 callback = desc->txd.callback;
1301 callback_param = desc->txd.callback_param;
1303 /* Send histogram status back to caller */
1304 desc->hist_status = hist_status;
1306 if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
1307 callback(callback_param);
1309 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1311 list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
1312 list_del_init(&child->list);
1313 kmem_cache_free(tx_desc_cache, (void *)child);
1315 list_del_init(&desc->list);
1316 kmem_cache_free(tx_desc_cache, (void *)desc);
1318 complete(&pxp->complete);
1319 pxp->pxp_ongoing = 0;
1320 mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
1322 spin_unlock_irqrestore(&pxp->lock, flags);
1327 /* allocate/free dma tx descriptor dynamically*/
1328 static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan)
1330 struct pxp_tx_desc *desc = NULL;
1331 struct dma_async_tx_descriptor *txd = NULL;
1333 desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO);
1337 INIT_LIST_HEAD(&desc->list);
1338 INIT_LIST_HEAD(&desc->tx_list);
1340 dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
1341 txd->tx_submit = pxp_tx_submit;
1346 /* Allocate and initialise a transfer descriptor. */
1347 static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
1350 unsigned int sg_len,
1352 dma_transfer_direction
1354 unsigned long tx_flags,
1357 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1358 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1359 struct pxps *pxp = to_pxp(pxp_dma);
1360 struct pxp_tx_desc *desc = NULL;
1361 struct pxp_tx_desc *first = NULL, *prev = NULL;
1362 struct scatterlist *sg;
1363 dma_addr_t phys_addr;
1366 if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
1367 dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
1372 if (unlikely(sg_len < 2))
1375 for_each_sg(sgl, sg, sg_len, i) {
1376 desc = pxpdma_desc_alloc(pxp_chan);
1378 dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n");
1382 phys_addr = sg_dma_address(sg);
1387 desc->layer_param.s0_param.paddr = phys_addr;
1389 list_add_tail(&desc->list, &first->tx_list);
1394 desc->layer_param.out_param.paddr = phys_addr;
1396 desc->layer_param.ol_param.paddr = phys_addr;
1402 pxp->pxp_conf_state.layer_nr = sg_len;
1403 first->txd.flags = tx_flags;
1404 first->len = sg_len;
1405 pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
1406 __func__, __LINE__, first, first->len, first->txd.flags);
1411 static void pxp_issue_pending(struct dma_chan *chan)
1413 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1414 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1415 struct pxps *pxp = to_pxp(pxp_dma);
1417 spin_lock(&pxp_chan->lock);
1419 if (list_empty(&pxp_chan->queue)) {
1420 spin_unlock(&pxp_chan->lock);
1424 pxpdma_dequeue(pxp_chan, pxp);
1425 pxp_chan->status = PXP_CHANNEL_READY;
1427 spin_unlock(&pxp_chan->lock);
1429 pxp_clk_enable(pxp);
1430 wake_up_interruptible(&pxp->thread_waitq);
1433 static void __pxp_terminate_all(struct dma_chan *chan)
1435 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1437 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1440 static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1443 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1445 /* Only supports DMA_TERMINATE_ALL */
1446 if (cmd != DMA_TERMINATE_ALL)
1449 spin_lock(&pxp_chan->lock);
1450 __pxp_terminate_all(chan);
1451 spin_unlock(&pxp_chan->lock);
1456 static int pxp_alloc_chan_resources(struct dma_chan *chan)
1458 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1459 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1462 /* dmaengine.c now guarantees to only offer free channels */
1463 BUG_ON(chan->client_count > 1);
1464 WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
1467 pxp_chan->completed = -ENXIO;
1469 pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
1470 ret = pxp_init_channel(pxp_dma, pxp_chan);
1474 pxp_chan->status = PXP_CHANNEL_INITIALIZED;
1476 dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
1477 chan->chan_id, pxp_chan->eof_irq);
1485 static void pxp_free_chan_resources(struct dma_chan *chan)
1487 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1489 spin_lock(&pxp_chan->lock);
1491 __pxp_terminate_all(chan);
1493 pxp_chan->status = PXP_CHANNEL_FREE;
1495 spin_unlock(&pxp_chan->lock);
1498 static enum dma_status pxp_tx_status(struct dma_chan *chan,
1499 dma_cookie_t cookie,
1500 struct dma_tx_state *txstate)
1502 struct pxp_channel *pxp_chan = to_pxp_channel(chan);
1504 if (cookie != chan->cookie)
1508 txstate->last = pxp_chan->completed;
1509 txstate->used = chan->cookie;
1510 txstate->residue = 0;
1515 static int pxp_dma_init(struct pxps *pxp)
1517 struct pxp_dma *pxp_dma = &pxp->pxp_dma;
1518 struct dma_device *dma = &pxp_dma->dma;
1521 dma_cap_set(DMA_SLAVE, dma->cap_mask);
1522 dma_cap_set(DMA_PRIVATE, dma->cap_mask);
1524 /* Compulsory common fields */
1525 dma->dev = pxp->dev;
1526 dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
1527 dma->device_free_chan_resources = pxp_free_chan_resources;
1528 dma->device_tx_status = pxp_tx_status;
1529 dma->device_issue_pending = pxp_issue_pending;
1531 /* Compulsory for DMA_SLAVE fields */
1532 dma->device_prep_slave_sg = pxp_prep_slave_sg;
1533 dma->device_control = pxp_control;
1535 /* Initialize PxP Channels */
1536 INIT_LIST_HEAD(&dma->channels);
1537 for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
1538 struct pxp_channel *pxp_chan = pxp->channel + i;
1539 struct dma_chan *dma_chan = &pxp_chan->dma_chan;
1541 spin_lock_init(&pxp_chan->lock);
1543 /* Only one EOF IRQ for PxP, shared by all channels */
1544 pxp_chan->eof_irq = pxp->irq;
1545 pxp_chan->status = PXP_CHANNEL_FREE;
1546 pxp_chan->completed = -ENXIO;
1547 snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
1550 dma_chan->device = &pxp_dma->dma;
1551 dma_chan->cookie = 1;
1552 dma_chan->chan_id = i;
1553 list_add_tail(&dma_chan->device_node, &dma->channels);
1556 return dma_async_device_register(&pxp_dma->dma);
1559 static ssize_t clk_off_timeout_show(struct device *dev,
1560 struct device_attribute *attr, char *buf)
1562 return sprintf(buf, "%d\n", timeout_in_ms);
1565 static ssize_t clk_off_timeout_store(struct device *dev,
1566 struct device_attribute *attr,
1567 const char *buf, size_t count)
1570 if (sscanf(buf, "%d", &val) > 0) {
1571 timeout_in_ms = val;
1577 static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
1578 clk_off_timeout_store);
1580 static ssize_t block_size_show(struct device *dev,
1581 struct device_attribute *attr,
1584 return sprintf(buf, "%d\n", block_size);
1587 static ssize_t block_size_store(struct device *dev,
1588 struct device_attribute *attr,
1589 const char *buf, size_t count)
1593 block_size = simple_strtoul(buf, last, 0);
1599 static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
1600 block_size_show, block_size_store);
1602 static const struct of_device_id imx_pxpdma_dt_ids[] = {
1603 { .compatible = "fsl,imx6dl-pxp-dma", },
1606 MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
1608 static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
1611 unsigned long flags;
1613 spin_lock_irqsave(&pxp->lock, flags);
1614 found = !list_empty(&head);
1615 spin_unlock_irqrestore(&pxp->lock, flags);
1620 static int pxp_dispatch_thread(void *argv)
1622 struct pxps *pxp = (struct pxps *)argv;
1623 struct pxp_channel *pending = NULL;
1624 unsigned long flags;
1628 while (!kthread_should_stop()) {
1630 ret = wait_event_freezable(pxp->thread_waitq,
1631 has_pending_task(pxp, pending) ||
1632 kthread_should_stop());
1636 if (kthread_should_stop())
1639 spin_lock_irqsave(&pxp->lock, flags);
1640 pxp->pxp_ongoing = 1;
1641 spin_unlock_irqrestore(&pxp->lock, flags);
1642 init_completion(&pxp->complete);
1643 pxpdma_dostart_work(pxp);
1644 ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
1646 printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
1654 static int pxp_probe(struct platform_device *pdev)
1657 struct resource *res;
1661 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1662 irq = platform_get_irq(pdev, 0);
1663 if (!res || irq < 0) {
1668 pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
1670 dev_err(&pdev->dev, "failed to allocate control object\n");
1675 pxp->dev = &pdev->dev;
1677 platform_set_drvdata(pdev, pxp);
1680 pxp->pxp_ongoing = 0;
1683 spin_lock_init(&pxp->lock);
1684 mutex_init(&pxp->clk_mutex);
1686 pxp->base = devm_request_and_ioremap(&pdev->dev, res);
1687 if (pxp->base == NULL) {
1688 dev_err(&pdev->dev, "Couldn't ioremap regs\n");
1695 pxp->clk_disp_axi = devm_clk_get(&pdev->dev, "disp-axi");
1696 if (IS_ERR(pxp->clk_disp_axi))
1697 pxp->clk_disp_axi = NULL;
1698 pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
1700 err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
1701 "pxp-dmaengine", pxp);
1704 /* Initialize DMA engine */
1705 err = pxp_dma_init(pxp);
1709 if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
1711 "Unable to create file from clk_off_timeout\n");
1715 device_create_file(&pdev->dev, &dev_attr_block_size);
1716 pxp_clk_enable(pxp);
1718 pxp_clk_disable(pxp);
1720 INIT_WORK(&pxp->work, clkoff_callback);
1721 init_timer(&pxp->clk_timer);
1722 pxp->clk_timer.function = pxp_clkoff_timer;
1723 pxp->clk_timer.data = (unsigned long)pxp;
1725 /* allocate a kernel thread to dispatch pxp conf */
1726 pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
1727 if (IS_ERR(pxp->dispatch)) {
1728 err = PTR_ERR(pxp->dispatch);
1731 init_waitqueue_head(&pxp->thread_waitq);
1732 tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc),
1733 0, SLAB_HWCACHE_ALIGN, NULL);
1734 if (!tx_desc_cache) {
1739 register_pxp_device();
1741 pm_runtime_enable(pxp->dev);
1745 dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
1749 static int pxp_remove(struct platform_device *pdev)
1751 struct pxps *pxp = platform_get_drvdata(pdev);
1753 unregister_pxp_device();
1754 kmem_cache_destroy(tx_desc_cache);
1755 kthread_stop(pxp->dispatch);
1756 cancel_work_sync(&pxp->work);
1757 del_timer_sync(&pxp->clk_timer);
1758 clk_disable_unprepare(pxp->clk);
1759 if (pxp->clk_disp_axi)
1760 clk_disable_unprepare(pxp->clk_disp_axi);
1761 device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
1762 device_remove_file(&pdev->dev, &dev_attr_block_size);
1763 dma_async_device_unregister(&(pxp->pxp_dma.dma));
1768 #ifdef CONFIG_PM_SLEEP
1769 static int pxp_suspend(struct device *dev)
1771 struct pxps *pxp = dev_get_drvdata(dev);
1773 pxp_clk_enable(pxp);
1774 while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
1777 __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
1778 pxp_clk_disable(pxp);
1783 static int pxp_resume(struct device *dev)
1785 struct pxps *pxp = dev_get_drvdata(dev);
1787 pxp_clk_enable(pxp);
1788 /* Pull PxP out of reset */
1789 __raw_writel(0, pxp->base + HW_PXP_CTRL);
1790 pxp_clk_disable(pxp);
1795 #define pxp_suspend NULL
1796 #define pxp_resume NULL
1799 #ifdef CONFIG_PM_RUNTIME
1800 static int pxp_runtime_suspend(struct device *dev)
1802 release_bus_freq(BUS_FREQ_HIGH);
1803 dev_dbg(dev, "pxp busfreq high release.\n");
1808 static int pxp_runtime_resume(struct device *dev)
1810 request_bus_freq(BUS_FREQ_HIGH);
1811 dev_dbg(dev, "pxp busfreq high request.\n");
1816 #define pxp_runtime_suspend NULL
1817 #define pxp_runtime_resume NULL
1820 static const struct dev_pm_ops pxp_pm_ops = {
1821 SET_RUNTIME_PM_OPS(pxp_runtime_suspend, pxp_runtime_resume, NULL)
1822 SET_SYSTEM_SLEEP_PM_OPS(pxp_suspend, pxp_resume)
1825 static struct platform_driver pxp_driver = {
1828 .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
1832 .remove = pxp_remove,
1835 module_platform_driver(pxp_driver);
1838 MODULE_DESCRIPTION("i.MX PxP driver");
1839 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1840 MODULE_LICENSE("GPL");