Linux Audio

Check our new training course

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