]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/mxc/ipu3/ipu_param_mem.h
ENGR00240987: ipu: port ipuv3 driver from 3.5.7 kernel
[karo-tx-linux.git] / drivers / mxc / ipu3 / ipu_param_mem.h
1 /*
2  * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /*
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:
9  *
10  * http://www.opensource.org/licenses/gpl-license.html
11  * http://www.gnu.org/copyleft/gpl.html
12  */
13 #ifndef __INCLUDE_IPU_PARAM_MEM_H__
14 #define __INCLUDE_IPU_PARAM_MEM_H__
15
16 #include <linux/bitrev.h>
17 #include <linux/types.h>
18
19 #include "ipu_prv.h"
20
21 extern u32 *ipu_cpmem_base;
22
23 struct ipu_ch_param_word {
24         uint32_t data[5];
25         uint32_t res[3];
26 };
27
28 struct ipu_ch_param {
29         struct ipu_ch_param_word word[2];
30 };
31
32 #define ipu_ch_param_addr(ipu, ch) (((struct ipu_ch_param *)ipu->cpmem_base) + (ch))
33
34 #define _param_word(base, w) \
35         (((struct ipu_ch_param *)(base))->word[(w)].data)
36
37 #define ipu_ch_param_set_field(base, w, bit, size, v) { \
38         int i = (bit) / 32; \
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); \
43         } \
44 }
45
46 #define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
47         int i = (bit) / 32; \
48         int off = (bit) % 32; \
49         unsigned reg_offset; \
50         u32 temp; \
51         reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
52         reg_offset += i; \
53         temp = readl((u32 *)base + reg_offset); \
54         temp |= (v) << off; \
55         writel(temp, (u32 *)base + reg_offset); \
56         if (((bit)+(size)-1)/32 > i) { \
57                 reg_offset++; \
58                 temp = readl((u32 *)base + reg_offset); \
59                 temp |= (v) >> (off ? (32 - off) : 0); \
60                 writel(temp, (u32 *)base + reg_offset); \
61         } \
62 }
63
64 #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
65         int i = (bit) / 32; \
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)); \
76         } \
77 }
78
79 #define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
80         int i = (bit) / 32; \
81         int off = (bit) % 32; \
82         u32 mask = (1UL << size) - 1; \
83         unsigned reg_offset; \
84         u32 temp; \
85         reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
86         reg_offset += i; \
87         temp = readl((u32 *)base + reg_offset); \
88         temp &= ~(mask << off); \
89         temp |= (v) << off; \
90         writel(temp, (u32 *)base + reg_offset); \
91         if (((bit)+(size)-1)/32 > i) { \
92                 reg_offset++; \
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); \
97         } \
98 }
99
100 #define ipu_ch_param_read_field(base, w, bit, size) ({ \
101         u32 temp2; \
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); \
111         } \
112         temp1; \
113 })
114
115 #define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
116         u32 temp1, temp2; \
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; \
122         reg_offset += i; \
123         temp1 = readl((u32 *)base + reg_offset); \
124         temp1 = mask & (temp1 >> off); \
125         if (((bit)+(size)-1)/32 > i) { \
126                 reg_offset++; \
127                 temp2 = readl((u32 *)base + reg_offset); \
128                 temp2 &= mask >> (off ? (32 - off) : 0); \
129                 temp1 |= temp2 << (off ? (32 - off) : 0); \
130         } \
131         temp1; \
132 })
133
134 static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
135 {
136         switch (ch) {
137         case 8:
138                 return 64;
139         case 9:
140                 return 65;
141         case 10:
142                 return 66;
143         case 13:
144                 return 67;
145         case 21:
146                 return 68;
147         case 23:
148                 return 69;
149         case 27:
150                 return 70;
151         case 28:
152                 return 71;
153         default:
154                 return -EINVAL;
155         }
156         return 0;
157 }
158
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)
164 {
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);
177 }
178
179 static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
180 {
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));
194
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);
213
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));
230 }
231
232 static inline void fill_cpmem(struct ipu_soc *ipu, int ch, struct ipu_ch_param *params)
233 {
234         int i, w;
235         void *addr = ipu_ch_param_addr(ipu, ch);
236
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);
241                         addr += 4;
242                 }
243                 addr += 12;
244         }
245 }
246
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)
253 {
254         uint32_t u_offset = 0;
255         uint32_t v_offset = 0;
256         int32_t sub_ch = 0;
257         struct ipu_ch_param params;
258
259         memset(&params, 0, sizeof(params));
260
261         ipu_ch_param_set_field(&params, 0, 125, 13, width - 1);
262
263         if (((ch == 8) || (ch == 9) || (ch == 10)) && !ipu->vdoa_en) {
264                 ipu_ch_param_set_field(&params, 0, 138, 12, (height / 2) - 1);
265                 ipu_ch_param_set_field(&params, 1, 102, 14, (stride * 2) - 1);
266         } else {
267                 /* note: for vdoa+vdi- ch8/9/10, always use band mode */
268                 ipu_ch_param_set_field(&params, 0, 138, 12, height - 1);
269                 ipu_ch_param_set_field(&params, 1, 102, 14, stride - 1);
270         }
271
272         /* EBA is 8-byte aligned */
273         ipu_ch_param_set_field(&params, 1, 0, 29, addr0 >> 3);
274         ipu_ch_param_set_field(&params, 1, 29, 29, addr1 >> 3);
275         if (addr0%8)
276                 dev_warn(ipu->dev,
277                          "IDMAC%d's EBA0 is not 8-byte aligned\n", ch);
278         if (addr1%8)
279                 dev_warn(ipu->dev,
280                          "IDMAC%d's EBA1 is not 8-byte aligned\n", ch);
281
282         switch (pixel_fmt) {
283         case IPU_PIX_FMT_GENERIC:
284                 /*Represents 8-bit Generic data */
285                 ipu_ch_param_set_field(&params, 0, 107, 3, 5);  /* bits/pixel */
286                 ipu_ch_param_set_field(&params, 1, 85, 4, 6);   /* pix format */
287                 ipu_ch_param_set_field(&params, 1, 78, 7, 63);  /* burst size */
288
289                 break;
290         case IPU_PIX_FMT_GENERIC_16:
291                 /* Represents 16-bit generic data */
292                 ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
293                 ipu_ch_param_set_field(&params, 1, 85, 4, 6);   /* pix format */
294                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
295
296                 break;
297         case IPU_PIX_FMT_GENERIC_32:
298                 /*Represents 32-bit Generic data */
299                 break;
300         case IPU_PIX_FMT_RGB565:
301                 ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
302                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
303                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
304
305                 _ipu_ch_params_set_packing(&params, 5, 0, 6, 5, 5, 11, 8, 16);
306                 break;
307         case IPU_PIX_FMT_BGR24:
308                 ipu_ch_param_set_field(&params, 0, 107, 3, 1);  /* bits/pixel */
309                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
310                 ipu_ch_param_set_field(&params, 1, 78, 7, 19);  /* burst size */
311
312                 _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
313                 break;
314         case IPU_PIX_FMT_RGB24:
315         case IPU_PIX_FMT_YUV444:
316                 ipu_ch_param_set_field(&params, 0, 107, 3, 1);  /* bits/pixel */
317                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
318                 ipu_ch_param_set_field(&params, 1, 78, 7, 19);  /* burst size */
319
320                 _ipu_ch_params_set_packing(&params, 8, 16, 8, 8, 8, 0, 8, 24);
321                 break;
322         case IPU_PIX_FMT_VYU444:
323                 ipu_ch_param_set_field(&params, 0, 107, 3, 1);  /* bits/pixel */
324                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
325                 ipu_ch_param_set_field(&params, 1, 78, 7, 19);  /* burst size */
326
327                 _ipu_ch_params_set_packing(&params, 8, 8, 8, 0, 8, 16, 8, 24);
328                 break;
329         case IPU_PIX_FMT_BGRA32:
330         case IPU_PIX_FMT_BGR32:
331                 ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
332                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
333                 ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
334
335                 _ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
336                 break;
337         case IPU_PIX_FMT_RGBA32:
338         case IPU_PIX_FMT_RGB32:
339                 ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
340                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
341                 ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
342
343                 _ipu_ch_params_set_packing(&params, 8, 24, 8, 16, 8, 8, 8, 0);
344                 break;
345         case IPU_PIX_FMT_ABGR32:
346                 ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
347                 ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
348                 ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
349
350                 _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
351                 break;
352         case IPU_PIX_FMT_UYVY:
353                 ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
354                 ipu_ch_param_set_field(&params, 1, 85, 4, 0xA); /* pix format */
355                 if ((ch == 8) || (ch == 9) || (ch == 10)) {
356                         ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
357                 } else {
358                         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
359                 }
360                 break;
361         case IPU_PIX_FMT_YUYV:
362                 ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
363                 ipu_ch_param_set_field(&params, 1, 85, 4, 0x8); /* pix format */
364                 if ((ch == 8) || (ch == 9) || (ch == 10)) {
365                         if (ipu->vdoa_en) {
366                                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);
367                         } else {
368                                 ipu_ch_param_set_field(&params, 1, 78, 7, 15);
369                         }
370                 } else {
371                         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
372                 }
373                 break;
374         case IPU_PIX_FMT_YUV420P2:
375         case IPU_PIX_FMT_YUV420P:
376                 ipu_ch_param_set_field(&params, 1, 85, 4, 2);   /* pix format */
377
378                 if (uv_stride < stride / 2)
379                         uv_stride = stride / 2;
380
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(&params, 1, 78, 7, 15);  /* burst size */
385                         uv_stride = uv_stride*2;
386                 } else {
387                         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
388                 }
389                 break;
390         case IPU_PIX_FMT_YVU420P:
391                 ipu_ch_param_set_field(&params, 1, 85, 4, 2);   /* pix format */
392
393                 if (uv_stride < stride / 2)
394                         uv_stride = stride / 2;
395
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(&params, 1, 78, 7, 15);  /* burst size */
400                         uv_stride = uv_stride*2;
401                 } else {
402                         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
403                 }
404                 break;
405         case IPU_PIX_FMT_YVU422P:
406                 /* BPP & pixel format */
407                 ipu_ch_param_set_field(&params, 1, 85, 4, 1);   /* pix format */
408                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
409
410                 if (uv_stride < stride / 2)
411                         uv_stride = stride / 2;
412
413                 v_offset = (v == 0) ? stride * height : v;
414                 u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
415                 break;
416         case IPU_PIX_FMT_YUV422P:
417                 /* BPP & pixel format */
418                 ipu_ch_param_set_field(&params, 1, 85, 4, 1);   /* pix format */
419                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
420
421                 if (uv_stride < stride / 2)
422                         uv_stride = stride / 2;
423
424                 u_offset = (u == 0) ? stride * height : u;
425                 v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
426                 break;
427         case IPU_PIX_FMT_YUV444P:
428                 /* BPP & pixel format */
429                 ipu_ch_param_set_field(&params, 1, 85, 4, 0);   /* pix format */
430                 ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
431                 uv_stride = stride;
432                 u_offset = (u == 0) ? stride * height : u;
433                 v_offset = (v == 0) ? u_offset * 2 : v;
434                 break;
435         case IPU_PIX_FMT_NV12:
436                 /* BPP & pixel format */
437                 ipu_ch_param_set_field(&params, 1, 85, 4, 4);   /* pix format */
438                 uv_stride = stride;
439                 u_offset = (u == 0) ? stride * height : u;
440                 if ((ch == 8) || (ch == 9) || (ch == 10)) {
441                         if (ipu->vdoa_en) {
442                                  /* one field buffer, memory width 64bits */
443                                 ipu_ch_param_set_field(&params, 1, 78, 7, 63);
444                         } else {
445                                 ipu_ch_param_set_field(&params, 1, 78, 7, 15);
446                                  /* top/bottom field in one buffer*/
447                                 uv_stride = uv_stride*2;
448                         }
449                 } else {
450                         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
451                 }
452                 break;
453         default:
454                 dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
455                 break;
456         }
457         /*set burst size to 16*/
458
459
460         if (uv_stride)
461                 ipu_ch_param_set_field(&params, 1, 128, 14, uv_stride - 1);
462
463         /* Get the uv offset from user when need cropping */
464         if (u || v) {
465                 u_offset = u;
466                 v_offset = v;
467         }
468
469         /* UBO and VBO are 22-bit and 8-byte aligned */
470         if (u_offset/8 > 0x3fffff)
471                 dev_warn(ipu->dev,
472                          "IDMAC%d's U offset exceeds IPU limitation\n", ch);
473         if (v_offset/8 > 0x3fffff)
474                 dev_warn(ipu->dev,
475                          "IDMAC%d's V offset exceeds IPU limitation\n", ch);
476         if (u_offset%8)
477                 dev_warn(ipu->dev,
478                          "IDMAC%d's U offset is not 8-byte aligned\n", ch);
479         if (v_offset%8)
480                 dev_warn(ipu->dev,
481                          "IDMAC%d's V offset is not 8-byte aligned\n", ch);
482
483         ipu_ch_param_set_field(&params, 0, 46, 22, u_offset / 8);
484         ipu_ch_param_set_field(&params, 0, 68, 22, v_offset / 8);
485
486         dev_dbg(ipu->dev, "initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ipu, ch));
487         fill_cpmem(ipu, ch, &params);
488         if (addr2) {
489                 sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
490                 if (sub_ch <= 0)
491                         return;
492
493                 ipu_ch_param_set_field(&params, 1, 0, 29, addr2 >> 3);
494                 ipu_ch_param_set_field(&params, 1, 29, 29, 0);
495                 if (addr2%8)
496                         dev_warn(ipu->dev,
497                                  "IDMAC%d's sub-CPMEM entry%d EBA0 is not "
498                                  "8-byte aligned\n", ch, sub_ch);
499
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, &params);
503         }
504 };
505
506 static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
507                                                 uint32_t ch,
508                                                 uint16_t burst_pixels)
509 {
510         int32_t sub_ch = 0;
511
512         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
513                                burst_pixels - 1);
514
515         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
516         if (sub_ch <= 0)
517                 return;
518         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
519                                burst_pixels - 1);
520 };
521
522 static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
523 {
524         return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
525 };
526
527 static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
528 {
529         return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
530 };
531
532 static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
533                                         int bufNum, dma_addr_t phyaddr)
534 {
535         if (bufNum == 2) {
536                 ch = __ipu_ch_get_third_buf_cpmem_num(ch);
537                 if (ch <= 0)
538                         return;
539                 bufNum = 0;
540         }
541
542         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
543                                phyaddr / 8);
544 };
545
546 static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
547                                               ipu_rotate_mode_t rot)
548 {
549         u32 temp_rot = bitrev8(rot) >> 5;
550         int32_t sub_ch = 0;
551
552         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
553
554         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
555         if (sub_ch <= 0)
556                 return;
557         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
558 };
559
560 static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
561 {
562         int32_t sub_ch = 0;
563
564         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
565
566         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
567         if (sub_ch <= 0)
568                 return;
569         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
570 };
571
572 static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
573                                                                 uint32_t ch,
574                                                                 bool option)
575 {
576         int32_t sub_ch = 0;
577
578         if (option) {
579                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
580         } else {
581                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
582         }
583
584         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
585         if (sub_ch <= 0)
586                 return;
587
588         if (option) {
589                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
590         } else {
591                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
592         }
593 };
594
595 static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, uint32_t ch)
596 {
597         int32_t sub_ch = 0;
598
599         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
600
601         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
602         if (sub_ch <= 0)
603                 return;
604         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
605 };
606
607 static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
608 {
609         int alp_mem_idx;
610         int32_t sub_ch = 0;
611
612         switch (ch) {
613         case 14: /* PRP graphic */
614                 alp_mem_idx = 0;
615                 break;
616         case 15: /* PP graphic */
617                 alp_mem_idx = 1;
618                 break;
619         case 23: /* DP BG SYNC graphic */
620                 alp_mem_idx = 4;
621                 break;
622         case 27: /* DP FG SYNC graphic */
623                 alp_mem_idx = 2;
624                 break;
625         default:
626                 dev_err(ipu->dev, "unsupported correlative channel of local "
627                         "alpha channel\n");
628                 return;
629         }
630
631         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
632
633         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
634         if (sub_ch <= 0)
635                 return;
636         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
637 };
638
639 static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
640 {
641         u32 stride;
642         int32_t sub_ch = 0;
643
644         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
645
646         ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
647         if (sub_ch > 0)
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)
652                 dev_warn(ipu->dev,
653                          "IDMAC%d's ILO exceeds IPU limitation\n", ch);
654         if (stride%8)
655                 dev_warn(ipu->dev,
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);
658         if (sub_ch > 0)
659                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
660                                        stride / 8);
661         stride *= 2;
662         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
663         if (sub_ch > 0)
664                 ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
665                                        stride - 1);
666 };
667
668 static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
669 {
670         int32_t sub_ch = 0;
671
672         id %= 4;
673
674         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
675
676         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
677         if (sub_ch <= 0)
678                 return;
679         ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
680 };
681
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,
687                                         int ch,
688                                         uint32_t pixel_fmt,
689                                         uint32_t width,
690                                         uint32_t height,
691                                         uint32_t stride,
692                                         uint32_t u,
693                                         uint32_t v,
694                                         uint32_t uv_stride,
695                                         uint32_t vertical_offset,
696                                         uint32_t horizontal_offset)
697 {
698         uint32_t u_offset = 0;
699         uint32_t v_offset = 0;
700         uint32_t old_offset = 0;
701         uint32_t u_fix = 0;
702         uint32_t v_fix = 0;
703         int32_t sub_ch = 0;
704
705         switch (pixel_fmt) {
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:
720                 break;
721
722         case IPU_PIX_FMT_YUV420P2:
723         case IPU_PIX_FMT_YUV420P:
724                 if (uv_stride < stride / 2)
725                         uv_stride = stride / 2;
726
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)) :
735                                         u_offset;
736                 v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
737                                         (horizontal_offset / 2) -
738                                         (stride * vertical_offset) - (horizontal_offset)) :
739                                         v_offset;
740
741                 break;
742         case IPU_PIX_FMT_YVU420P:
743                 if (uv_stride < stride / 2)
744                         uv_stride = stride / 2;
745
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)) :
754                                         u_offset;
755                 v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
756                                         (horizontal_offset / 2) -
757                                         (stride * vertical_offset) - (horizontal_offset)) :
758                                         v_offset;
759
760                 break;
761         case IPU_PIX_FMT_YVU422P:
762                 if (uv_stride < stride / 2)
763                         uv_stride = stride / 2;
764
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)) :
773                                         u_offset;
774                 v_fix = v ? (v + (uv_stride * vertical_offset) +
775                                         horizontal_offset / 2 -
776                                         (stride * vertical_offset) - (horizontal_offset)) :
777                                         v_offset;
778                 break;
779         case IPU_PIX_FMT_YUV422P:
780                 if (uv_stride < stride / 2)
781                         uv_stride = stride / 2;
782
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)) :
791                                         u_offset;
792                 v_fix = v ? (v + (uv_stride * vertical_offset) +
793                                         horizontal_offset / 2 -
794                                         (stride * vertical_offset) - (horizontal_offset)) :
795                                         v_offset;
796                 break;
797
798         case IPU_PIX_FMT_YUV444P:
799                 uv_stride = stride;
800                 u_offset = stride * (height - vertical_offset - 1) +
801                                         (stride - horizontal_offset) +
802                                         (uv_stride * vertical_offset) +
803                                         horizontal_offset;
804                 v_offset = u_offset + uv_stride * height;
805                 u_fix = u ? (u + (uv_stride * vertical_offset) +
806                                         horizontal_offset -
807                                         (stride * vertical_offset) -
808                                         (horizontal_offset)) :
809                                         u_offset;
810                 v_fix = v ? (v + (uv_stride * vertical_offset) +
811                                         horizontal_offset -
812                                         (stride * vertical_offset) -
813                                         (horizontal_offset)) :
814                                         v_offset;
815                 break;
816         case IPU_PIX_FMT_NV12:
817                 uv_stride = stride;
818                 u_offset = stride * (height - vertical_offset - 1) +
819                                         (stride - horizontal_offset) +
820                                         (uv_stride * vertical_offset / 2) +
821                                         horizontal_offset;
822                 u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
823                                         horizontal_offset -
824                                         (stride * vertical_offset) - (horizontal_offset)) :
825                                         u_offset;
826
827                 break;
828         default:
829                 dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
830                 break;
831         }
832
833
834
835         if (u_fix > u_offset)
836                 u_offset = u_fix;
837
838         if (v_fix > v_offset)
839                 v_offset = v_fix;
840
841         /* UBO and VBO are 22-bit and 8-byte aligned */
842         if (u_offset/8 > 0x3fffff)
843                 dev_warn(ipu->dev,
844                         "IDMAC%d's U offset exceeds IPU limitation\n", ch);
845         if (v_offset/8 > 0x3fffff)
846                 dev_warn(ipu->dev,
847                         "IDMAC%d's V offset exceeds IPU limitation\n", ch);
848         if (u_offset%8)
849                 dev_warn(ipu->dev,
850                         "IDMAC%d's U offset is not 8-byte aligned\n", ch);
851         if (v_offset%8)
852                 dev_warn(ipu->dev,
853                         "IDMAC%d's V offset is not 8-byte aligned\n", ch);
854
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);
861
862         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
863         if (sub_ch <= 0)
864                 return;
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);
871 };
872
873 static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
874 {
875         int32_t sub_ch = 0;
876
877         ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
878
879         sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
880         if (sub_ch <= 0)
881                 return;
882         ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
883 };
884
885 static inline void _ipu_ch_param_set_bandmode(struct ipu_soc *ipu,
886                         uint32_t ch, uint32_t band_height)
887 {
888         int32_t sub_ch = 0;
889
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);
893         if (sub_ch <= 0)
894                 return;
895         ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch),
896                                         0, 114, 3, band_height - 1);
897
898         dev_dbg(ipu->dev, "BNDM 0x%x, ",
899                  ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 114, 3));
900 }
901 #endif