2 * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
13 #ifndef __INCLUDE_IPU_PARAM_MEM_H__
14 #define __INCLUDE_IPU_PARAM_MEM_H__
16 #include <linux/bitrev.h>
17 #include <linux/types.h>
21 extern u32 *ipu_cpmem_base;
23 struct ipu_ch_param_word {
29 struct ipu_ch_param_word word[2];
32 #define ipu_ch_param_addr(ipu, ch) (((struct ipu_ch_param *)ipu->cpmem_base) + (ch))
34 #define _param_word(base, w) \
35 (((struct ipu_ch_param *)(base))->word[(w)].data)
37 #define ipu_ch_param_set_field(base, w, bit, size, v) { \
39 int off = (bit) % 32; \
40 _param_word(base, w)[i] |= (v) << off; \
41 if (((bit)+(size)-1)/32 > i) { \
42 _param_word(base, w)[i + 1] |= (v) >> (off ? (32 - off) : 0); \
46 #define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
48 int off = (bit) % 32; \
49 unsigned reg_offset; \
51 reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
53 temp = readl((u32 *)base + reg_offset); \
55 writel(temp, (u32 *)base + reg_offset); \
56 if (((bit)+(size)-1)/32 > i) { \
58 temp = readl((u32 *)base + reg_offset); \
59 temp |= (v) >> (off ? (32 - off) : 0); \
60 writel(temp, (u32 *)base + reg_offset); \
64 #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
66 int off = (bit) % 32; \
67 u32 mask = (1UL << size) - 1; \
68 u32 temp = _param_word(base, w)[i]; \
69 temp &= ~(mask << off); \
70 _param_word(base, w)[i] = temp | (v) << off; \
71 if (((bit)+(size)-1)/32 > i) { \
72 temp = _param_word(base, w)[i + 1]; \
73 temp &= ~(mask >> (32 - off)); \
74 _param_word(base, w)[i + 1] = \
75 temp | ((v) >> (off ? (32 - off) : 0)); \
79 #define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
81 int off = (bit) % 32; \
82 u32 mask = (1UL << size) - 1; \
83 unsigned reg_offset; \
85 reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
87 temp = readl((u32 *)base + reg_offset); \
88 temp &= ~(mask << off); \
90 writel(temp, (u32 *)base + reg_offset); \
91 if (((bit)+(size)-1)/32 > i) { \
93 temp = readl((u32 *)base + reg_offset); \
94 temp &= ~(mask >> (32 - off)); \
95 temp |= ((v) >> (off ? (32 - off) : 0)); \
96 writel(temp, (u32 *)base + reg_offset); \
100 #define ipu_ch_param_read_field(base, w, bit, size) ({ \
102 int i = (bit) / 32; \
103 int off = (bit) % 32; \
104 u32 mask = (1UL << size) - 1; \
105 u32 temp1 = _param_word(base, w)[i]; \
106 temp1 = mask & (temp1 >> off); \
107 if (((bit)+(size)-1)/32 > i) { \
108 temp2 = _param_word(base, w)[i + 1]; \
109 temp2 &= mask >> (off ? (32 - off) : 0); \
110 temp1 |= temp2 << (off ? (32 - off) : 0); \
115 #define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
117 int i = (bit) / 32; \
118 int off = (bit) % 32; \
119 u32 mask = (1UL << size) - 1; \
120 unsigned reg_offset; \
121 reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
123 temp1 = readl((u32 *)base + reg_offset); \
124 temp1 = mask & (temp1 >> off); \
125 if (((bit)+(size)-1)/32 > i) { \
127 temp2 = readl((u32 *)base + reg_offset); \
128 temp2 &= mask >> (off ? (32 - off) : 0); \
129 temp1 |= temp2 << (off ? (32 - off) : 0); \
134 static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
159 static inline void _ipu_ch_params_set_packing(struct ipu_ch_param *p,
160 int red_width, int red_offset,
161 int green_width, int green_offset,
162 int blue_width, int blue_offset,
163 int alpha_width, int alpha_offset)
165 /* Setup red width and offset */
166 ipu_ch_param_set_field(p, 1, 116, 3, red_width - 1);
167 ipu_ch_param_set_field(p, 1, 128, 5, red_offset);
168 /* Setup green width and offset */
169 ipu_ch_param_set_field(p, 1, 119, 3, green_width - 1);
170 ipu_ch_param_set_field(p, 1, 133, 5, green_offset);
171 /* Setup blue width and offset */
172 ipu_ch_param_set_field(p, 1, 122, 3, blue_width - 1);
173 ipu_ch_param_set_field(p, 1, 138, 5, blue_offset);
174 /* Setup alpha width and offset */
175 ipu_ch_param_set_field(p, 1, 125, 3, alpha_width - 1);
176 ipu_ch_param_set_field(p, 1, 143, 5, alpha_offset);
179 static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
181 struct ipu_ch_param *p = ipu_ch_param_addr(ipu, ch);
182 dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", ch,
183 p->word[0].data[0], p->word[0].data[1], p->word[0].data[2],
184 p->word[0].data[3], p->word[0].data[4]);
185 dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", ch,
186 p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
187 p->word[1].data[3], p->word[1].data[4]);
188 dev_dbg(ipu->dev, "PFS 0x%x, ",
189 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
190 dev_dbg(ipu->dev, "BPP 0x%x, ",
191 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
192 dev_dbg(ipu->dev, "NPB 0x%x\n",
193 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
195 dev_dbg(ipu->dev, "FW %d, ",
196 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
197 dev_dbg(ipu->dev, "FH %d, ",
198 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
199 dev_dbg(ipu->dev, "EBA0 0x%x\n",
200 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 0, 29) << 3);
201 dev_dbg(ipu->dev, "EBA1 0x%x\n",
202 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 29, 29) << 3);
203 dev_dbg(ipu->dev, "Stride %d\n",
204 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
205 dev_dbg(ipu->dev, "scan_order %d\n",
206 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1));
207 dev_dbg(ipu->dev, "uv_stride %d\n",
208 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 14));
209 dev_dbg(ipu->dev, "u_offset 0x%x\n",
210 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22) << 3);
211 dev_dbg(ipu->dev, "v_offset 0x%x\n",
212 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22) << 3);
214 dev_dbg(ipu->dev, "Width0 %d+1, ",
215 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
216 dev_dbg(ipu->dev, "Width1 %d+1, ",
217 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
218 dev_dbg(ipu->dev, "Width2 %d+1, ",
219 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
220 dev_dbg(ipu->dev, "Width3 %d+1, ",
221 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
222 dev_dbg(ipu->dev, "Offset0 %d, ",
223 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
224 dev_dbg(ipu->dev, "Offset1 %d, ",
225 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
226 dev_dbg(ipu->dev, "Offset2 %d, ",
227 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
228 dev_dbg(ipu->dev, "Offset3 %d\n",
229 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
232 static inline void fill_cpmem(struct ipu_soc *ipu, int ch, struct ipu_ch_param *params)
235 void *addr = ipu_ch_param_addr(ipu, ch);
237 /* 2 words, 5 valid data */
238 for (w = 0; w < 2; w++) {
239 for (i = 0; i < 5; i++) {
240 writel(params->word[w].data[i], addr);
247 static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
248 uint32_t pixel_fmt, uint32_t width,
249 uint32_t height, uint32_t stride,
250 uint32_t u, uint32_t v,
251 uint32_t uv_stride, dma_addr_t addr0,
252 dma_addr_t addr1, dma_addr_t addr2)
254 uint32_t u_offset = 0;
255 uint32_t v_offset = 0;
257 struct ipu_ch_param params;
259 memset(¶ms, 0, sizeof(params));
261 ipu_ch_param_set_field(¶ms, 0, 125, 13, width - 1);
263 if (((ch == 8) || (ch == 9) || (ch == 10)) && !ipu->vdoa_en) {
264 ipu_ch_param_set_field(¶ms, 0, 138, 12, (height / 2) - 1);
265 ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1);
267 /* note: for vdoa+vdi- ch8/9/10, always use band mode */
268 ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1);
269 ipu_ch_param_set_field(¶ms, 1, 102, 14, stride - 1);
272 /* EBA is 8-byte aligned */
273 ipu_ch_param_set_field(¶ms, 1, 0, 29, addr0 >> 3);
274 ipu_ch_param_set_field(¶ms, 1, 29, 29, addr1 >> 3);
277 "IDMAC%d's EBA0 is not 8-byte aligned\n", ch);
280 "IDMAC%d's EBA1 is not 8-byte aligned\n", ch);
283 case IPU_PIX_FMT_GENERIC:
284 /*Represents 8-bit Generic data */
285 ipu_ch_param_set_field(¶ms, 0, 107, 3, 5); /* bits/pixel */
286 ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
287 ipu_ch_param_set_field(¶ms, 1, 78, 7, 63); /* burst size */
290 case IPU_PIX_FMT_GENERIC_16:
291 /* Represents 16-bit generic data */
292 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
293 ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
294 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
297 case IPU_PIX_FMT_GENERIC_32:
298 /*Represents 32-bit Generic data */
300 case IPU_PIX_FMT_RGB565:
301 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
302 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
303 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
305 _ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16);
307 case IPU_PIX_FMT_BGR24:
308 ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
309 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
310 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
312 _ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
314 case IPU_PIX_FMT_RGB24:
315 case IPU_PIX_FMT_YUV444:
316 ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
317 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
318 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
320 _ipu_ch_params_set_packing(¶ms, 8, 16, 8, 8, 8, 0, 8, 24);
322 case IPU_PIX_FMT_VYU444:
323 ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
324 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
325 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
327 _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 0, 8, 16, 8, 24);
329 case IPU_PIX_FMT_BGRA32:
330 case IPU_PIX_FMT_BGR32:
331 ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
332 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
333 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
335 _ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0);
337 case IPU_PIX_FMT_RGBA32:
338 case IPU_PIX_FMT_RGB32:
339 ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
340 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
341 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
343 _ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0);
345 case IPU_PIX_FMT_ABGR32:
346 ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
347 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
348 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
350 _ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
352 case IPU_PIX_FMT_UYVY:
353 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
354 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */
355 if ((ch == 8) || (ch == 9) || (ch == 10)) {
356 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
358 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
361 case IPU_PIX_FMT_YUYV:
362 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
363 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */
364 if ((ch == 8) || (ch == 9) || (ch == 10)) {
366 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31);
368 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
371 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
374 case IPU_PIX_FMT_YUV420P2:
375 case IPU_PIX_FMT_YUV420P:
376 ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
378 if (uv_stride < stride / 2)
379 uv_stride = stride / 2;
381 u_offset = stride * height;
382 v_offset = u_offset + (uv_stride * height / 2);
383 if ((ch == 8) || (ch == 9) || (ch == 10)) {
384 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
385 uv_stride = uv_stride*2;
387 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
390 case IPU_PIX_FMT_YVU420P:
391 ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
393 if (uv_stride < stride / 2)
394 uv_stride = stride / 2;
396 v_offset = stride * height;
397 u_offset = v_offset + (uv_stride * height / 2);
398 if ((ch == 8) || (ch == 9) || (ch == 10)) {
399 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
400 uv_stride = uv_stride*2;
402 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
405 case IPU_PIX_FMT_YVU422P:
406 /* BPP & pixel format */
407 ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
408 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
410 if (uv_stride < stride / 2)
411 uv_stride = stride / 2;
413 v_offset = (v == 0) ? stride * height : v;
414 u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
416 case IPU_PIX_FMT_YUV422P:
417 /* BPP & pixel format */
418 ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
419 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
421 if (uv_stride < stride / 2)
422 uv_stride = stride / 2;
424 u_offset = (u == 0) ? stride * height : u;
425 v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
427 case IPU_PIX_FMT_YUV444P:
428 /* BPP & pixel format */
429 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0); /* pix format */
430 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
432 u_offset = (u == 0) ? stride * height : u;
433 v_offset = (v == 0) ? u_offset * 2 : v;
435 case IPU_PIX_FMT_NV12:
436 /* BPP & pixel format */
437 ipu_ch_param_set_field(¶ms, 1, 85, 4, 4); /* pix format */
439 u_offset = (u == 0) ? stride * height : u;
440 if ((ch == 8) || (ch == 9) || (ch == 10)) {
442 /* one field buffer, memory width 64bits */
443 ipu_ch_param_set_field(¶ms, 1, 78, 7, 63);
445 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
446 /* top/bottom field in one buffer*/
447 uv_stride = uv_stride*2;
450 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
454 dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
457 /*set burst size to 16*/
461 ipu_ch_param_set_field(¶ms, 1, 128, 14, uv_stride - 1);
463 /* Get the uv offset from user when need cropping */
469 /* UBO and VBO are 22-bit and 8-byte aligned */
470 if (u_offset/8 > 0x3fffff)
472 "IDMAC%d's U offset exceeds IPU limitation\n", ch);
473 if (v_offset/8 > 0x3fffff)
475 "IDMAC%d's V offset exceeds IPU limitation\n", ch);
478 "IDMAC%d's U offset is not 8-byte aligned\n", ch);
481 "IDMAC%d's V offset is not 8-byte aligned\n", ch);
483 ipu_ch_param_set_field(¶ms, 0, 46, 22, u_offset / 8);
484 ipu_ch_param_set_field(¶ms, 0, 68, 22, v_offset / 8);
486 dev_dbg(ipu->dev, "initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ipu, ch));
487 fill_cpmem(ipu, ch, ¶ms);
489 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
493 ipu_ch_param_set_field(¶ms, 1, 0, 29, addr2 >> 3);
494 ipu_ch_param_set_field(¶ms, 1, 29, 29, 0);
497 "IDMAC%d's sub-CPMEM entry%d EBA0 is not "
498 "8-byte aligned\n", ch, sub_ch);
500 dev_dbg(ipu->dev, "initializing idma ch %d @ %p sub cpmem\n", ch,
501 ipu_ch_param_addr(ipu, sub_ch));
502 fill_cpmem(ipu, sub_ch, ¶ms);
506 static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
508 uint16_t burst_pixels)
512 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
515 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
518 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
522 static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
524 return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
527 static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
529 return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
532 static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
533 int bufNum, dma_addr_t phyaddr)
536 ch = __ipu_ch_get_third_buf_cpmem_num(ch);
542 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
546 static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
547 ipu_rotate_mode_t rot)
549 u32 temp_rot = bitrev8(rot) >> 5;
552 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
554 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
557 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
560 static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
564 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
566 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
569 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
572 static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
579 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
581 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
584 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
589 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
591 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
595 static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, uint32_t ch)
599 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
601 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
604 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
607 static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
613 case 14: /* PRP graphic */
616 case 15: /* PP graphic */
619 case 23: /* DP BG SYNC graphic */
622 case 27: /* DP FG SYNC graphic */
626 dev_err(ipu->dev, "unsupported correlative channel of local "
631 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
633 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
636 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
639 static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
644 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
646 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
648 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
649 stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
650 /* ILO is 20-bit and 8-byte aligned */
651 if (stride/8 > 0xfffff)
653 "IDMAC%d's ILO exceeds IPU limitation\n", ch);
656 "IDMAC%d's ILO is not 8-byte aligned\n", ch);
657 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
659 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
662 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
664 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
668 static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
674 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
676 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
679 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
682 /* IDMAC U/V offset changing support */
683 /* U and V input is not affected, */
684 /* the update is done by new calculation according to */
685 /* vertical_offset and horizontal_offset */
686 static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
695 uint32_t vertical_offset,
696 uint32_t horizontal_offset)
698 uint32_t u_offset = 0;
699 uint32_t v_offset = 0;
700 uint32_t old_offset = 0;
706 case IPU_PIX_FMT_GENERIC:
707 case IPU_PIX_FMT_GENERIC_16:
708 case IPU_PIX_FMT_GENERIC_32:
709 case IPU_PIX_FMT_RGB565:
710 case IPU_PIX_FMT_BGR24:
711 case IPU_PIX_FMT_RGB24:
712 case IPU_PIX_FMT_YUV444:
713 case IPU_PIX_FMT_BGRA32:
714 case IPU_PIX_FMT_BGR32:
715 case IPU_PIX_FMT_RGBA32:
716 case IPU_PIX_FMT_RGB32:
717 case IPU_PIX_FMT_ABGR32:
718 case IPU_PIX_FMT_UYVY:
719 case IPU_PIX_FMT_YUYV:
722 case IPU_PIX_FMT_YUV420P2:
723 case IPU_PIX_FMT_YUV420P:
724 if (uv_stride < stride / 2)
725 uv_stride = stride / 2;
727 u_offset = stride * (height - vertical_offset - 1) +
728 (stride - horizontal_offset) +
729 (uv_stride * vertical_offset / 2) +
730 horizontal_offset / 2;
731 v_offset = u_offset + (uv_stride * height / 2);
732 u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
733 (horizontal_offset / 2) -
734 (stride * vertical_offset) - (horizontal_offset)) :
736 v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
737 (horizontal_offset / 2) -
738 (stride * vertical_offset) - (horizontal_offset)) :
742 case IPU_PIX_FMT_YVU420P:
743 if (uv_stride < stride / 2)
744 uv_stride = stride / 2;
746 v_offset = stride * (height - vertical_offset - 1) +
747 (stride - horizontal_offset) +
748 (uv_stride * vertical_offset / 2) +
749 horizontal_offset / 2;
750 u_offset = v_offset + (uv_stride * height / 2);
751 u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
752 (horizontal_offset / 2) -
753 (stride * vertical_offset) - (horizontal_offset)) :
755 v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
756 (horizontal_offset / 2) -
757 (stride * vertical_offset) - (horizontal_offset)) :
761 case IPU_PIX_FMT_YVU422P:
762 if (uv_stride < stride / 2)
763 uv_stride = stride / 2;
765 v_offset = stride * (height - vertical_offset - 1) +
766 (stride - horizontal_offset) +
767 (uv_stride * vertical_offset) +
768 horizontal_offset / 2;
769 u_offset = v_offset + uv_stride * height;
770 u_fix = u ? (u + (uv_stride * vertical_offset) +
771 horizontal_offset / 2 -
772 (stride * vertical_offset) - (horizontal_offset)) :
774 v_fix = v ? (v + (uv_stride * vertical_offset) +
775 horizontal_offset / 2 -
776 (stride * vertical_offset) - (horizontal_offset)) :
779 case IPU_PIX_FMT_YUV422P:
780 if (uv_stride < stride / 2)
781 uv_stride = stride / 2;
783 u_offset = stride * (height - vertical_offset - 1) +
784 (stride - horizontal_offset) +
785 (uv_stride * vertical_offset) +
786 horizontal_offset / 2;
787 v_offset = u_offset + uv_stride * height;
788 u_fix = u ? (u + (uv_stride * vertical_offset) +
789 horizontal_offset / 2 -
790 (stride * vertical_offset) - (horizontal_offset)) :
792 v_fix = v ? (v + (uv_stride * vertical_offset) +
793 horizontal_offset / 2 -
794 (stride * vertical_offset) - (horizontal_offset)) :
798 case IPU_PIX_FMT_YUV444P:
800 u_offset = stride * (height - vertical_offset - 1) +
801 (stride - horizontal_offset) +
802 (uv_stride * vertical_offset) +
804 v_offset = u_offset + uv_stride * height;
805 u_fix = u ? (u + (uv_stride * vertical_offset) +
807 (stride * vertical_offset) -
808 (horizontal_offset)) :
810 v_fix = v ? (v + (uv_stride * vertical_offset) +
812 (stride * vertical_offset) -
813 (horizontal_offset)) :
816 case IPU_PIX_FMT_NV12:
818 u_offset = stride * (height - vertical_offset - 1) +
819 (stride - horizontal_offset) +
820 (uv_stride * vertical_offset / 2) +
822 u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
824 (stride * vertical_offset) - (horizontal_offset)) :
829 dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
835 if (u_fix > u_offset)
838 if (v_fix > v_offset)
841 /* UBO and VBO are 22-bit and 8-byte aligned */
842 if (u_offset/8 > 0x3fffff)
844 "IDMAC%d's U offset exceeds IPU limitation\n", ch);
845 if (v_offset/8 > 0x3fffff)
847 "IDMAC%d's V offset exceeds IPU limitation\n", ch);
850 "IDMAC%d's U offset is not 8-byte aligned\n", ch);
853 "IDMAC%d's V offset is not 8-byte aligned\n", ch);
855 old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22);
856 if (old_offset != u_offset / 8)
857 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
858 old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22);
859 if (old_offset != v_offset / 8)
860 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
862 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
865 old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22);
866 if (old_offset != u_offset / 8)
867 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
868 old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22);
869 if (old_offset != v_offset / 8)
870 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
873 static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
877 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
879 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
882 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
885 static inline void _ipu_ch_param_set_bandmode(struct ipu_soc *ipu,
886 uint32_t ch, uint32_t band_height)
890 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch),
891 0, 114, 3, band_height - 1);
892 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
895 ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch),
896 0, 114, 3, band_height - 1);
898 dev_dbg(ipu->dev, "BNDM 0x%x, ",
899 ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 114, 3));