Linux-libre 4.14.12-gnu
[librecmc/linux-libre.git] / drivers / gpu / ipu-v3 / ipu-cpmem.c
1 /*
2  * Copyright (C) 2012 Mentor Graphics Inc.
3  * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
4  *
5  * The code contained herein is licensed under the GNU General Public
6  * License. You may obtain a copy of the GNU General Public License
7  * Version 2 or later at the following locations:
8  *
9  * http://www.opensource.org/licenses/gpl-license.html
10  * http://www.gnu.org/copyleft/gpl.html
11  */
12 #include <linux/types.h>
13 #include <linux/bitrev.h>
14 #include <linux/io.h>
15 #include <drm/drm_fourcc.h>
16 #include "ipu-prv.h"
17
18 struct ipu_cpmem_word {
19         u32 data[5];
20         u32 res[3];
21 };
22
23 struct ipu_ch_param {
24         struct ipu_cpmem_word word[2];
25 };
26
27 struct ipu_cpmem {
28         struct ipu_ch_param __iomem *base;
29         u32 module;
30         spinlock_t lock;
31         int use_count;
32         struct ipu_soc *ipu;
33 };
34
35 #define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
36
37 #define IPU_FIELD_UBO           IPU_CPMEM_WORD(0, 46, 22)
38 #define IPU_FIELD_VBO           IPU_CPMEM_WORD(0, 68, 22)
39 #define IPU_FIELD_IOX           IPU_CPMEM_WORD(0, 90, 4)
40 #define IPU_FIELD_RDRW          IPU_CPMEM_WORD(0, 94, 1)
41 #define IPU_FIELD_SO            IPU_CPMEM_WORD(0, 113, 1)
42 #define IPU_FIELD_SLY           IPU_CPMEM_WORD(1, 102, 14)
43 #define IPU_FIELD_SLUV          IPU_CPMEM_WORD(1, 128, 14)
44
45 #define IPU_FIELD_XV            IPU_CPMEM_WORD(0, 0, 10)
46 #define IPU_FIELD_YV            IPU_CPMEM_WORD(0, 10, 9)
47 #define IPU_FIELD_XB            IPU_CPMEM_WORD(0, 19, 13)
48 #define IPU_FIELD_YB            IPU_CPMEM_WORD(0, 32, 12)
49 #define IPU_FIELD_NSB_B         IPU_CPMEM_WORD(0, 44, 1)
50 #define IPU_FIELD_CF            IPU_CPMEM_WORD(0, 45, 1)
51 #define IPU_FIELD_SX            IPU_CPMEM_WORD(0, 46, 12)
52 #define IPU_FIELD_SY            IPU_CPMEM_WORD(0, 58, 11)
53 #define IPU_FIELD_NS            IPU_CPMEM_WORD(0, 69, 10)
54 #define IPU_FIELD_SDX           IPU_CPMEM_WORD(0, 79, 7)
55 #define IPU_FIELD_SM            IPU_CPMEM_WORD(0, 86, 10)
56 #define IPU_FIELD_SCC           IPU_CPMEM_WORD(0, 96, 1)
57 #define IPU_FIELD_SCE           IPU_CPMEM_WORD(0, 97, 1)
58 #define IPU_FIELD_SDY           IPU_CPMEM_WORD(0, 98, 7)
59 #define IPU_FIELD_SDRX          IPU_CPMEM_WORD(0, 105, 1)
60 #define IPU_FIELD_SDRY          IPU_CPMEM_WORD(0, 106, 1)
61 #define IPU_FIELD_BPP           IPU_CPMEM_WORD(0, 107, 3)
62 #define IPU_FIELD_DEC_SEL       IPU_CPMEM_WORD(0, 110, 2)
63 #define IPU_FIELD_DIM           IPU_CPMEM_WORD(0, 112, 1)
64 #define IPU_FIELD_BNDM          IPU_CPMEM_WORD(0, 114, 3)
65 #define IPU_FIELD_BM            IPU_CPMEM_WORD(0, 117, 2)
66 #define IPU_FIELD_ROT           IPU_CPMEM_WORD(0, 119, 1)
67 #define IPU_FIELD_ROT_HF_VF     IPU_CPMEM_WORD(0, 119, 3)
68 #define IPU_FIELD_HF            IPU_CPMEM_WORD(0, 120, 1)
69 #define IPU_FIELD_VF            IPU_CPMEM_WORD(0, 121, 1)
70 #define IPU_FIELD_THE           IPU_CPMEM_WORD(0, 122, 1)
71 #define IPU_FIELD_CAP           IPU_CPMEM_WORD(0, 123, 1)
72 #define IPU_FIELD_CAE           IPU_CPMEM_WORD(0, 124, 1)
73 #define IPU_FIELD_FW            IPU_CPMEM_WORD(0, 125, 13)
74 #define IPU_FIELD_FH            IPU_CPMEM_WORD(0, 138, 12)
75 #define IPU_FIELD_EBA0          IPU_CPMEM_WORD(1, 0, 29)
76 #define IPU_FIELD_EBA1          IPU_CPMEM_WORD(1, 29, 29)
77 #define IPU_FIELD_ILO           IPU_CPMEM_WORD(1, 58, 20)
78 #define IPU_FIELD_NPB           IPU_CPMEM_WORD(1, 78, 7)
79 #define IPU_FIELD_PFS           IPU_CPMEM_WORD(1, 85, 4)
80 #define IPU_FIELD_ALU           IPU_CPMEM_WORD(1, 89, 1)
81 #define IPU_FIELD_ALBM          IPU_CPMEM_WORD(1, 90, 3)
82 #define IPU_FIELD_ID            IPU_CPMEM_WORD(1, 93, 2)
83 #define IPU_FIELD_TH            IPU_CPMEM_WORD(1, 95, 7)
84 #define IPU_FIELD_SL            IPU_CPMEM_WORD(1, 102, 14)
85 #define IPU_FIELD_WID0          IPU_CPMEM_WORD(1, 116, 3)
86 #define IPU_FIELD_WID1          IPU_CPMEM_WORD(1, 119, 3)
87 #define IPU_FIELD_WID2          IPU_CPMEM_WORD(1, 122, 3)
88 #define IPU_FIELD_WID3          IPU_CPMEM_WORD(1, 125, 3)
89 #define IPU_FIELD_OFS0          IPU_CPMEM_WORD(1, 128, 5)
90 #define IPU_FIELD_OFS1          IPU_CPMEM_WORD(1, 133, 5)
91 #define IPU_FIELD_OFS2          IPU_CPMEM_WORD(1, 138, 5)
92 #define IPU_FIELD_OFS3          IPU_CPMEM_WORD(1, 143, 5)
93 #define IPU_FIELD_SXYS          IPU_CPMEM_WORD(1, 148, 1)
94 #define IPU_FIELD_CRE           IPU_CPMEM_WORD(1, 149, 1)
95 #define IPU_FIELD_DEC_SEL2      IPU_CPMEM_WORD(1, 150, 1)
96
97 static inline struct ipu_ch_param __iomem *
98 ipu_get_cpmem(struct ipuv3_channel *ch)
99 {
100         struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
101
102         return cpmem->base + ch->num;
103 }
104
105 static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
106 {
107         struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
108         u32 bit = (wbs >> 8) % 160;
109         u32 size = wbs & 0xff;
110         u32 word = (wbs >> 8) / 160;
111         u32 i = bit / 32;
112         u32 ofs = bit % 32;
113         u32 mask = (1 << size) - 1;
114         u32 val;
115
116         pr_debug("%s %d %d %d\n", __func__, word, bit , size);
117
118         val = readl(&base->word[word].data[i]);
119         val &= ~(mask << ofs);
120         val |= v << ofs;
121         writel(val, &base->word[word].data[i]);
122
123         if ((bit + size - 1) / 32 > i) {
124                 val = readl(&base->word[word].data[i + 1]);
125                 val &= ~(mask >> (ofs ? (32 - ofs) : 0));
126                 val |= v >> (ofs ? (32 - ofs) : 0);
127                 writel(val, &base->word[word].data[i + 1]);
128         }
129 }
130
131 static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
132 {
133         struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
134         u32 bit = (wbs >> 8) % 160;
135         u32 size = wbs & 0xff;
136         u32 word = (wbs >> 8) / 160;
137         u32 i = bit / 32;
138         u32 ofs = bit % 32;
139         u32 mask = (1 << size) - 1;
140         u32 val = 0;
141
142         pr_debug("%s %d %d %d\n", __func__, word, bit , size);
143
144         val = (readl(&base->word[word].data[i]) >> ofs) & mask;
145
146         if ((bit + size - 1) / 32 > i) {
147                 u32 tmp;
148
149                 tmp = readl(&base->word[word].data[i + 1]);
150                 tmp &= mask >> (ofs ? (32 - ofs) : 0);
151                 val |= tmp << (ofs ? (32 - ofs) : 0);
152         }
153
154         return val;
155 }
156
157 /*
158  * The V4L2 spec defines packed RGB formats in memory byte order, which from
159  * point of view of the IPU corresponds to little-endian words with the first
160  * component in the least significant bits.
161  * The DRM pixel formats and IPU internal representation are ordered the other
162  * way around, with the first named component ordered at the most significant
163  * bits. Further, V4L2 formats are not well defined:
164  *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
165  * We choose the interpretation which matches GStreamer behavior.
166  */
167 static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
168 {
169         switch (pixelformat) {
170         case V4L2_PIX_FMT_RGB565:
171                 /*
172                  * Here we choose the 'corrected' interpretation of RGBP, a
173                  * little-endian 16-bit word with the red component at the most
174                  * significant bits:
175                  * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
176                  */
177                 return DRM_FORMAT_RGB565;
178         case V4L2_PIX_FMT_BGR24:
179                 /* B G R <=> [24:0] R:G:B */
180                 return DRM_FORMAT_RGB888;
181         case V4L2_PIX_FMT_RGB24:
182                 /* R G B <=> [24:0] B:G:R */
183                 return DRM_FORMAT_BGR888;
184         case V4L2_PIX_FMT_BGR32:
185                 /* B G R A <=> [32:0] A:B:G:R */
186                 return DRM_FORMAT_XRGB8888;
187         case V4L2_PIX_FMT_RGB32:
188                 /* R G B A <=> [32:0] A:B:G:R */
189                 return DRM_FORMAT_XBGR8888;
190         case V4L2_PIX_FMT_UYVY:
191                 return DRM_FORMAT_UYVY;
192         case V4L2_PIX_FMT_YUYV:
193                 return DRM_FORMAT_YUYV;
194         case V4L2_PIX_FMT_YUV420:
195                 return DRM_FORMAT_YUV420;
196         case V4L2_PIX_FMT_YUV422P:
197                 return DRM_FORMAT_YUV422;
198         case V4L2_PIX_FMT_YVU420:
199                 return DRM_FORMAT_YVU420;
200         case V4L2_PIX_FMT_NV12:
201                 return DRM_FORMAT_NV12;
202         case V4L2_PIX_FMT_NV16:
203                 return DRM_FORMAT_NV16;
204         }
205
206         return -EINVAL;
207 }
208
209 void ipu_cpmem_zero(struct ipuv3_channel *ch)
210 {
211         struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
212         void __iomem *base = p;
213         int i;
214
215         for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
216                 writel(0, base + i * sizeof(u32));
217 }
218 EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
219
220 void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
221 {
222         ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
223         ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
224 }
225 EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
226
227 void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
228 {
229         ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
230 }
231 EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
232
233 void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
234 {
235         ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
236 }
237 EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
238
239 void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
240 {
241         struct ipu_soc *ipu = ch->ipu;
242         u32 val;
243
244         if (ipu->ipu_type == IPUV3EX)
245                 ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
246
247         val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
248         val |= 1 << (ch->num % 32);
249         ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
250 };
251 EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
252
253 void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
254 {
255         if (bufnum)
256                 ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
257         else
258                 ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
259 }
260 EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
261
262 void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
263 {
264         ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
265         ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
266 }
267 EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
268
269 void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
270 {
271         ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
272         ipu_ch_param_write_field(ch, IPU_FIELD_ILO, stride / 8);
273         ipu_ch_param_write_field(ch, IPU_FIELD_SLY, (stride * 2) - 1);
274 };
275 EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
276
277 void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
278 {
279         id &= 0x3;
280         ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
281 }
282 EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
283
284 int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
285 {
286         return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
287 }
288 EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
289
290 void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
291 {
292         ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
293 };
294 EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
295
296 void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
297 {
298         ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
299 }
300 EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
301
302 void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
303                             enum ipu_rotate_mode rot)
304 {
305         u32 temp_rot = bitrev8(rot) >> 5;
306
307         ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
308 }
309 EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
310
311 int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
312                              const struct ipu_rgb *rgb)
313 {
314         int bpp = 0, npb = 0, ro, go, bo, to;
315
316         ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
317         go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
318         bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
319         to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
320
321         ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
322         ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
323         ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
324         ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
325         ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
326         ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
327
328         if (rgb->transp.length) {
329                 ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
330                                 rgb->transp.length - 1);
331                 ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
332         } else {
333                 ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
334                 ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
335                                 rgb->bits_per_pixel);
336         }
337
338         switch (rgb->bits_per_pixel) {
339         case 32:
340                 bpp = 0;
341                 npb = 15;
342                 break;
343         case 24:
344                 bpp = 1;
345                 npb = 19;
346                 break;
347         case 16:
348                 bpp = 3;
349                 npb = 31;
350                 break;
351         case 8:
352                 bpp = 5;
353                 npb = 63;
354                 break;
355         default:
356                 return -EINVAL;
357         }
358         ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
359         ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
360         ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
361
362         return 0;
363 }
364 EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
365
366 int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
367 {
368         int bpp = 0, npb = 0;
369
370         switch (width) {
371         case 32:
372                 bpp = 0;
373                 npb = 15;
374                 break;
375         case 24:
376                 bpp = 1;
377                 npb = 19;
378                 break;
379         case 16:
380                 bpp = 3;
381                 npb = 31;
382                 break;
383         case 8:
384                 bpp = 5;
385                 npb = 63;
386                 break;
387         default:
388                 return -EINVAL;
389         }
390
391         ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
392         ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
393         ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
394
395         return 0;
396 }
397 EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
398
399 void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
400 {
401         switch (pixel_format) {
402         case V4L2_PIX_FMT_UYVY:
403                 ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
404                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
405                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
406                 break;
407         case V4L2_PIX_FMT_YUYV:
408                 ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
409                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
410                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
411                 break;
412         }
413 }
414 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
415
416 void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
417                                    unsigned int uv_stride,
418                                    unsigned int u_offset, unsigned int v_offset)
419 {
420         ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
421         ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
422         ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
423 }
424 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
425
426 static const struct ipu_rgb def_xrgb_32 = {
427         .red    = { .offset = 16, .length = 8, },
428         .green  = { .offset =  8, .length = 8, },
429         .blue   = { .offset =  0, .length = 8, },
430         .transp = { .offset = 24, .length = 8, },
431         .bits_per_pixel = 32,
432 };
433
434 static const struct ipu_rgb def_xbgr_32 = {
435         .red    = { .offset =  0, .length = 8, },
436         .green  = { .offset =  8, .length = 8, },
437         .blue   = { .offset = 16, .length = 8, },
438         .transp = { .offset = 24, .length = 8, },
439         .bits_per_pixel = 32,
440 };
441
442 static const struct ipu_rgb def_rgbx_32 = {
443         .red    = { .offset = 24, .length = 8, },
444         .green  = { .offset = 16, .length = 8, },
445         .blue   = { .offset =  8, .length = 8, },
446         .transp = { .offset =  0, .length = 8, },
447         .bits_per_pixel = 32,
448 };
449
450 static const struct ipu_rgb def_bgrx_32 = {
451         .red    = { .offset =  8, .length = 8, },
452         .green  = { .offset = 16, .length = 8, },
453         .blue   = { .offset = 24, .length = 8, },
454         .transp = { .offset =  0, .length = 8, },
455         .bits_per_pixel = 32,
456 };
457
458 static const struct ipu_rgb def_rgb_24 = {
459         .red    = { .offset = 16, .length = 8, },
460         .green  = { .offset =  8, .length = 8, },
461         .blue   = { .offset =  0, .length = 8, },
462         .transp = { .offset =  0, .length = 0, },
463         .bits_per_pixel = 24,
464 };
465
466 static const struct ipu_rgb def_bgr_24 = {
467         .red    = { .offset =  0, .length = 8, },
468         .green  = { .offset =  8, .length = 8, },
469         .blue   = { .offset = 16, .length = 8, },
470         .transp = { .offset =  0, .length = 0, },
471         .bits_per_pixel = 24,
472 };
473
474 static const struct ipu_rgb def_rgb_16 = {
475         .red    = { .offset = 11, .length = 5, },
476         .green  = { .offset =  5, .length = 6, },
477         .blue   = { .offset =  0, .length = 5, },
478         .transp = { .offset =  0, .length = 0, },
479         .bits_per_pixel = 16,
480 };
481
482 static const struct ipu_rgb def_bgr_16 = {
483         .red    = { .offset =  0, .length = 5, },
484         .green  = { .offset =  5, .length = 6, },
485         .blue   = { .offset = 11, .length = 5, },
486         .transp = { .offset =  0, .length = 0, },
487         .bits_per_pixel = 16,
488 };
489
490 static const struct ipu_rgb def_argb_16 = {
491         .red    = { .offset = 10, .length = 5, },
492         .green  = { .offset =  5, .length = 5, },
493         .blue   = { .offset =  0, .length = 5, },
494         .transp = { .offset = 15, .length = 1, },
495         .bits_per_pixel = 16,
496 };
497
498 static const struct ipu_rgb def_argb_16_4444 = {
499         .red    = { .offset =  8, .length = 4, },
500         .green  = { .offset =  4, .length = 4, },
501         .blue   = { .offset =  0, .length = 4, },
502         .transp = { .offset = 12, .length = 4, },
503         .bits_per_pixel = 16,
504 };
505
506 static const struct ipu_rgb def_abgr_16 = {
507         .red    = { .offset =  0, .length = 5, },
508         .green  = { .offset =  5, .length = 5, },
509         .blue   = { .offset = 10, .length = 5, },
510         .transp = { .offset = 15, .length = 1, },
511         .bits_per_pixel = 16,
512 };
513
514 static const struct ipu_rgb def_rgba_16 = {
515         .red    = { .offset = 11, .length = 5, },
516         .green  = { .offset =  6, .length = 5, },
517         .blue   = { .offset =  1, .length = 5, },
518         .transp = { .offset =  0, .length = 1, },
519         .bits_per_pixel = 16,
520 };
521
522 static const struct ipu_rgb def_bgra_16 = {
523         .red    = { .offset =  1, .length = 5, },
524         .green  = { .offset =  6, .length = 5, },
525         .blue   = { .offset = 11, .length = 5, },
526         .transp = { .offset =  0, .length = 1, },
527         .bits_per_pixel = 16,
528 };
529
530 #define Y_OFFSET(pix, x, y)     ((x) + pix->width * (y))
531 #define U_OFFSET(pix, x, y)     ((pix->width * pix->height) +           \
532                                  (pix->width * (y) / 4) + (x) / 2)
533 #define V_OFFSET(pix, x, y)     ((pix->width * pix->height) +           \
534                                  (pix->width * pix->height / 4) +       \
535                                  (pix->width * (y) / 4) + (x) / 2)
536 #define U2_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
537                                  (pix->width * (y) / 2) + (x) / 2)
538 #define V2_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
539                                  (pix->width * pix->height / 2) +       \
540                                  (pix->width * (y) / 2) + (x) / 2)
541 #define UV_OFFSET(pix, x, y)    ((pix->width * pix->height) +   \
542                                  (pix->width * (y) / 2) + (x))
543 #define UV2_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
544                                  (pix->width * y) + (x))
545
546 #define NUM_ALPHA_CHANNELS      7
547
548 /* See Table 37-12. Alpha channels mapping. */
549 static int ipu_channel_albm(int ch_num)
550 {
551         switch (ch_num) {
552         case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
553         case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
554         case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
555         case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
556         case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
557         case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
558         case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
559         default:
560                 return -EINVAL;
561         }
562 }
563
564 static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
565 {
566         struct ipu_soc *ipu = ch->ipu;
567         int albm;
568         u32 val;
569
570         albm = ipu_channel_albm(ch->num);
571         if (albm < 0)
572                 return;
573
574         ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
575         ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
576         ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
577
578         val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
579         val |= BIT(ch->num);
580         ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
581 }
582
583 int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
584 {
585         switch (drm_fourcc) {
586         case DRM_FORMAT_YUV420:
587         case DRM_FORMAT_YVU420:
588                 /* pix format */
589                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
590                 /* burst size */
591                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
592                 break;
593         case DRM_FORMAT_YUV422:
594         case DRM_FORMAT_YVU422:
595                 /* pix format */
596                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
597                 /* burst size */
598                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
599                 break;
600         case DRM_FORMAT_YUV444:
601         case DRM_FORMAT_YVU444:
602                 /* pix format */
603                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
604                 /* burst size */
605                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
606                 break;
607         case DRM_FORMAT_NV12:
608                 /* pix format */
609                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
610                 /* burst size */
611                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
612                 break;
613         case DRM_FORMAT_NV16:
614                 /* pix format */
615                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
616                 /* burst size */
617                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
618                 break;
619         case DRM_FORMAT_UYVY:
620                 /* bits/pixel */
621                 ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
622                 /* pix format */
623                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
624                 /* burst size */
625                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
626                 break;
627         case DRM_FORMAT_YUYV:
628                 /* bits/pixel */
629                 ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
630                 /* pix format */
631                 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
632                 /* burst size */
633                 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
634                 break;
635         case DRM_FORMAT_ABGR8888:
636         case DRM_FORMAT_XBGR8888:
637                 ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
638                 break;
639         case DRM_FORMAT_ARGB8888:
640         case DRM_FORMAT_XRGB8888:
641                 ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
642                 break;
643         case DRM_FORMAT_RGBA8888:
644         case DRM_FORMAT_RGBX8888:
645         case DRM_FORMAT_RGBX8888_A8:
646                 ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
647                 break;
648         case DRM_FORMAT_BGRA8888:
649         case DRM_FORMAT_BGRX8888:
650         case DRM_FORMAT_BGRX8888_A8:
651                 ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
652                 break;
653         case DRM_FORMAT_BGR888:
654         case DRM_FORMAT_BGR888_A8:
655                 ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
656                 break;
657         case DRM_FORMAT_RGB888:
658         case DRM_FORMAT_RGB888_A8:
659                 ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
660                 break;
661         case DRM_FORMAT_RGB565:
662         case DRM_FORMAT_RGB565_A8:
663                 ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
664                 break;
665         case DRM_FORMAT_BGR565:
666         case DRM_FORMAT_BGR565_A8:
667                 ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
668                 break;
669         case DRM_FORMAT_ARGB1555:
670                 ipu_cpmem_set_format_rgb(ch, &def_argb_16);
671                 break;
672         case DRM_FORMAT_ABGR1555:
673                 ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
674                 break;
675         case DRM_FORMAT_RGBA5551:
676                 ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
677                 break;
678         case DRM_FORMAT_BGRA5551:
679                 ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
680                 break;
681         case DRM_FORMAT_ARGB4444:
682                 ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
683                 break;
684         default:
685                 return -EINVAL;
686         }
687
688         switch (drm_fourcc) {
689         case DRM_FORMAT_RGB565_A8:
690         case DRM_FORMAT_BGR565_A8:
691         case DRM_FORMAT_RGB888_A8:
692         case DRM_FORMAT_BGR888_A8:
693         case DRM_FORMAT_RGBX8888_A8:
694         case DRM_FORMAT_BGRX8888_A8:
695                 ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
696                 ipu_cpmem_set_separate_alpha(ch);
697                 break;
698         default:
699                 break;
700         }
701
702         return 0;
703 }
704 EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
705
706 int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
707 {
708         struct v4l2_pix_format *pix = &image->pix;
709         int offset, u_offset, v_offset;
710         int ret = 0;
711
712         pr_debug("%s: resolution: %dx%d stride: %d\n",
713                  __func__, pix->width, pix->height,
714                  pix->bytesperline);
715
716         ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
717         ipu_cpmem_set_stride(ch, pix->bytesperline);
718
719         ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
720
721         switch (pix->pixelformat) {
722         case V4L2_PIX_FMT_YUV420:
723                 offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
724                 u_offset = U_OFFSET(pix, image->rect.left,
725                                     image->rect.top) - offset;
726                 v_offset = V_OFFSET(pix, image->rect.left,
727                                     image->rect.top) - offset;
728
729                 ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
730                                               u_offset, v_offset);
731                 break;
732         case V4L2_PIX_FMT_YVU420:
733                 offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
734                 u_offset = U_OFFSET(pix, image->rect.left,
735                                     image->rect.top) - offset;
736                 v_offset = V_OFFSET(pix, image->rect.left,
737                                     image->rect.top) - offset;
738
739                 ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
740                                               v_offset, u_offset);
741                 break;
742         case V4L2_PIX_FMT_YUV422P:
743                 offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
744                 u_offset = U2_OFFSET(pix, image->rect.left,
745                                      image->rect.top) - offset;
746                 v_offset = V2_OFFSET(pix, image->rect.left,
747                                      image->rect.top) - offset;
748
749                 ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
750                                               u_offset, v_offset);
751                 break;
752         case V4L2_PIX_FMT_NV12:
753                 offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
754                 u_offset = UV_OFFSET(pix, image->rect.left,
755                                      image->rect.top) - offset;
756                 v_offset = 0;
757
758                 ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
759                                               u_offset, v_offset);
760                 break;
761         case V4L2_PIX_FMT_NV16:
762                 offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
763                 u_offset = UV2_OFFSET(pix, image->rect.left,
764                                       image->rect.top) - offset;
765                 v_offset = 0;
766
767                 ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
768                                               u_offset, v_offset);
769                 break;
770         case V4L2_PIX_FMT_UYVY:
771         case V4L2_PIX_FMT_YUYV:
772         case V4L2_PIX_FMT_RGB565:
773                 offset = image->rect.left * 2 +
774                         image->rect.top * pix->bytesperline;
775                 break;
776         case V4L2_PIX_FMT_RGB32:
777         case V4L2_PIX_FMT_BGR32:
778                 offset = image->rect.left * 4 +
779                         image->rect.top * pix->bytesperline;
780                 break;
781         case V4L2_PIX_FMT_RGB24:
782         case V4L2_PIX_FMT_BGR24:
783                 offset = image->rect.left * 3 +
784                         image->rect.top * pix->bytesperline;
785                 break;
786         case V4L2_PIX_FMT_SBGGR8:
787         case V4L2_PIX_FMT_SGBRG8:
788         case V4L2_PIX_FMT_SGRBG8:
789         case V4L2_PIX_FMT_SRGGB8:
790                 offset = image->rect.left + image->rect.top * pix->bytesperline;
791                 break;
792         case V4L2_PIX_FMT_SBGGR16:
793         case V4L2_PIX_FMT_SGBRG16:
794         case V4L2_PIX_FMT_SGRBG16:
795         case V4L2_PIX_FMT_SRGGB16:
796                 offset = image->rect.left * 2 +
797                          image->rect.top * pix->bytesperline;
798                 break;
799         default:
800                 /* This should not happen */
801                 WARN_ON(1);
802                 offset = 0;
803                 ret = -EINVAL;
804         }
805
806         ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
807         ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
808
809         return ret;
810 }
811 EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
812
813 void ipu_cpmem_dump(struct ipuv3_channel *ch)
814 {
815         struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
816         struct ipu_soc *ipu = ch->ipu;
817         int chno = ch->num;
818
819         dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
820                 readl(&p->word[0].data[0]),
821                 readl(&p->word[0].data[1]),
822                 readl(&p->word[0].data[2]),
823                 readl(&p->word[0].data[3]),
824                 readl(&p->word[0].data[4]));
825         dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
826                 readl(&p->word[1].data[0]),
827                 readl(&p->word[1].data[1]),
828                 readl(&p->word[1].data[2]),
829                 readl(&p->word[1].data[3]),
830                 readl(&p->word[1].data[4]));
831         dev_dbg(ipu->dev, "PFS 0x%x, ",
832                  ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
833         dev_dbg(ipu->dev, "BPP 0x%x, ",
834                 ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
835         dev_dbg(ipu->dev, "NPB 0x%x\n",
836                  ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
837
838         dev_dbg(ipu->dev, "FW %d, ",
839                  ipu_ch_param_read_field(ch, IPU_FIELD_FW));
840         dev_dbg(ipu->dev, "FH %d, ",
841                  ipu_ch_param_read_field(ch, IPU_FIELD_FH));
842         dev_dbg(ipu->dev, "EBA0 0x%x\n",
843                  ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
844         dev_dbg(ipu->dev, "EBA1 0x%x\n",
845                  ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
846         dev_dbg(ipu->dev, "Stride %d\n",
847                  ipu_ch_param_read_field(ch, IPU_FIELD_SL));
848         dev_dbg(ipu->dev, "scan_order %d\n",
849                  ipu_ch_param_read_field(ch, IPU_FIELD_SO));
850         dev_dbg(ipu->dev, "uv_stride %d\n",
851                  ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
852         dev_dbg(ipu->dev, "u_offset 0x%x\n",
853                  ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
854         dev_dbg(ipu->dev, "v_offset 0x%x\n",
855                  ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
856
857         dev_dbg(ipu->dev, "Width0 %d+1, ",
858                  ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
859         dev_dbg(ipu->dev, "Width1 %d+1, ",
860                  ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
861         dev_dbg(ipu->dev, "Width2 %d+1, ",
862                  ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
863         dev_dbg(ipu->dev, "Width3 %d+1, ",
864                  ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
865         dev_dbg(ipu->dev, "Offset0 %d, ",
866                  ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
867         dev_dbg(ipu->dev, "Offset1 %d, ",
868                  ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
869         dev_dbg(ipu->dev, "Offset2 %d, ",
870                  ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
871         dev_dbg(ipu->dev, "Offset3 %d\n",
872                  ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
873 }
874 EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
875
876 int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
877 {
878         struct ipu_cpmem *cpmem;
879
880         cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
881         if (!cpmem)
882                 return -ENOMEM;
883
884         ipu->cpmem_priv = cpmem;
885
886         spin_lock_init(&cpmem->lock);
887         cpmem->base = devm_ioremap(dev, base, SZ_128K);
888         if (!cpmem->base)
889                 return -ENOMEM;
890
891         dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
892                 base, cpmem->base);
893         cpmem->ipu = ipu;
894
895         return 0;
896 }
897
898 void ipu_cpmem_exit(struct ipu_soc *ipu)
899 {
900 }