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