xref: /linux/drivers/gpu/ipu-v3/ipu-cpmem.c (revision 7cca7c80)
1fcaf2036SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27d2691daSSteve Longerbeam /*
37d2691daSSteve Longerbeam  * Copyright (C) 2012 Mentor Graphics Inc.
47d2691daSSteve Longerbeam  * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
57d2691daSSteve Longerbeam  */
67d2691daSSteve Longerbeam #include <linux/types.h>
77d2691daSSteve Longerbeam #include <linux/bitrev.h>
87d2691daSSteve Longerbeam #include <linux/io.h>
94cfea3c1SPhilipp Zabel #include <linux/sizes.h>
107d2691daSSteve Longerbeam #include <drm/drm_fourcc.h>
117d2691daSSteve Longerbeam #include "ipu-prv.h"
127d2691daSSteve Longerbeam 
137d2691daSSteve Longerbeam struct ipu_cpmem_word {
147d2691daSSteve Longerbeam 	u32 data[5];
157d2691daSSteve Longerbeam 	u32 res[3];
167d2691daSSteve Longerbeam };
177d2691daSSteve Longerbeam 
187d2691daSSteve Longerbeam struct ipu_ch_param {
197d2691daSSteve Longerbeam 	struct ipu_cpmem_word word[2];
207d2691daSSteve Longerbeam };
217d2691daSSteve Longerbeam 
227d2691daSSteve Longerbeam struct ipu_cpmem {
237d2691daSSteve Longerbeam 	struct ipu_ch_param __iomem *base;
247d2691daSSteve Longerbeam 	u32 module;
257d2691daSSteve Longerbeam 	spinlock_t lock;
267d2691daSSteve Longerbeam 	int use_count;
277d2691daSSteve Longerbeam 	struct ipu_soc *ipu;
287d2691daSSteve Longerbeam };
297d2691daSSteve Longerbeam 
307d2691daSSteve Longerbeam #define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
317d2691daSSteve Longerbeam 
327d2691daSSteve Longerbeam #define IPU_FIELD_UBO		IPU_CPMEM_WORD(0, 46, 22)
337d2691daSSteve Longerbeam #define IPU_FIELD_VBO		IPU_CPMEM_WORD(0, 68, 22)
347d2691daSSteve Longerbeam #define IPU_FIELD_IOX		IPU_CPMEM_WORD(0, 90, 4)
357d2691daSSteve Longerbeam #define IPU_FIELD_RDRW		IPU_CPMEM_WORD(0, 94, 1)
367d2691daSSteve Longerbeam #define IPU_FIELD_SO		IPU_CPMEM_WORD(0, 113, 1)
377d2691daSSteve Longerbeam #define IPU_FIELD_SLY		IPU_CPMEM_WORD(1, 102, 14)
387d2691daSSteve Longerbeam #define IPU_FIELD_SLUV		IPU_CPMEM_WORD(1, 128, 14)
397d2691daSSteve Longerbeam 
407d2691daSSteve Longerbeam #define IPU_FIELD_XV		IPU_CPMEM_WORD(0, 0, 10)
417d2691daSSteve Longerbeam #define IPU_FIELD_YV		IPU_CPMEM_WORD(0, 10, 9)
427d2691daSSteve Longerbeam #define IPU_FIELD_XB		IPU_CPMEM_WORD(0, 19, 13)
437d2691daSSteve Longerbeam #define IPU_FIELD_YB		IPU_CPMEM_WORD(0, 32, 12)
447d2691daSSteve Longerbeam #define IPU_FIELD_NSB_B		IPU_CPMEM_WORD(0, 44, 1)
457d2691daSSteve Longerbeam #define IPU_FIELD_CF		IPU_CPMEM_WORD(0, 45, 1)
467d2691daSSteve Longerbeam #define IPU_FIELD_SX		IPU_CPMEM_WORD(0, 46, 12)
477d2691daSSteve Longerbeam #define IPU_FIELD_SY		IPU_CPMEM_WORD(0, 58, 11)
487d2691daSSteve Longerbeam #define IPU_FIELD_NS		IPU_CPMEM_WORD(0, 69, 10)
497d2691daSSteve Longerbeam #define IPU_FIELD_SDX		IPU_CPMEM_WORD(0, 79, 7)
507d2691daSSteve Longerbeam #define IPU_FIELD_SM		IPU_CPMEM_WORD(0, 86, 10)
517d2691daSSteve Longerbeam #define IPU_FIELD_SCC		IPU_CPMEM_WORD(0, 96, 1)
527d2691daSSteve Longerbeam #define IPU_FIELD_SCE		IPU_CPMEM_WORD(0, 97, 1)
537d2691daSSteve Longerbeam #define IPU_FIELD_SDY		IPU_CPMEM_WORD(0, 98, 7)
547d2691daSSteve Longerbeam #define IPU_FIELD_SDRX		IPU_CPMEM_WORD(0, 105, 1)
557d2691daSSteve Longerbeam #define IPU_FIELD_SDRY		IPU_CPMEM_WORD(0, 106, 1)
567d2691daSSteve Longerbeam #define IPU_FIELD_BPP		IPU_CPMEM_WORD(0, 107, 3)
577d2691daSSteve Longerbeam #define IPU_FIELD_DEC_SEL	IPU_CPMEM_WORD(0, 110, 2)
587d2691daSSteve Longerbeam #define IPU_FIELD_DIM		IPU_CPMEM_WORD(0, 112, 1)
597d2691daSSteve Longerbeam #define IPU_FIELD_BNDM		IPU_CPMEM_WORD(0, 114, 3)
607d2691daSSteve Longerbeam #define IPU_FIELD_BM		IPU_CPMEM_WORD(0, 117, 2)
617d2691daSSteve Longerbeam #define IPU_FIELD_ROT		IPU_CPMEM_WORD(0, 119, 1)
62c42d37caSSteve Longerbeam #define IPU_FIELD_ROT_HF_VF	IPU_CPMEM_WORD(0, 119, 3)
637d2691daSSteve Longerbeam #define IPU_FIELD_HF		IPU_CPMEM_WORD(0, 120, 1)
647d2691daSSteve Longerbeam #define IPU_FIELD_VF		IPU_CPMEM_WORD(0, 121, 1)
657d2691daSSteve Longerbeam #define IPU_FIELD_THE		IPU_CPMEM_WORD(0, 122, 1)
667d2691daSSteve Longerbeam #define IPU_FIELD_CAP		IPU_CPMEM_WORD(0, 123, 1)
677d2691daSSteve Longerbeam #define IPU_FIELD_CAE		IPU_CPMEM_WORD(0, 124, 1)
687d2691daSSteve Longerbeam #define IPU_FIELD_FW		IPU_CPMEM_WORD(0, 125, 13)
697d2691daSSteve Longerbeam #define IPU_FIELD_FH		IPU_CPMEM_WORD(0, 138, 12)
707d2691daSSteve Longerbeam #define IPU_FIELD_EBA0		IPU_CPMEM_WORD(1, 0, 29)
717d2691daSSteve Longerbeam #define IPU_FIELD_EBA1		IPU_CPMEM_WORD(1, 29, 29)
727d2691daSSteve Longerbeam #define IPU_FIELD_ILO		IPU_CPMEM_WORD(1, 58, 20)
737d2691daSSteve Longerbeam #define IPU_FIELD_NPB		IPU_CPMEM_WORD(1, 78, 7)
747d2691daSSteve Longerbeam #define IPU_FIELD_PFS		IPU_CPMEM_WORD(1, 85, 4)
757d2691daSSteve Longerbeam #define IPU_FIELD_ALU		IPU_CPMEM_WORD(1, 89, 1)
767d2691daSSteve Longerbeam #define IPU_FIELD_ALBM		IPU_CPMEM_WORD(1, 90, 3)
777d2691daSSteve Longerbeam #define IPU_FIELD_ID		IPU_CPMEM_WORD(1, 93, 2)
787d2691daSSteve Longerbeam #define IPU_FIELD_TH		IPU_CPMEM_WORD(1, 95, 7)
797d2691daSSteve Longerbeam #define IPU_FIELD_SL		IPU_CPMEM_WORD(1, 102, 14)
807d2691daSSteve Longerbeam #define IPU_FIELD_WID0		IPU_CPMEM_WORD(1, 116, 3)
817d2691daSSteve Longerbeam #define IPU_FIELD_WID1		IPU_CPMEM_WORD(1, 119, 3)
827d2691daSSteve Longerbeam #define IPU_FIELD_WID2		IPU_CPMEM_WORD(1, 122, 3)
837d2691daSSteve Longerbeam #define IPU_FIELD_WID3		IPU_CPMEM_WORD(1, 125, 3)
847d2691daSSteve Longerbeam #define IPU_FIELD_OFS0		IPU_CPMEM_WORD(1, 128, 5)
857d2691daSSteve Longerbeam #define IPU_FIELD_OFS1		IPU_CPMEM_WORD(1, 133, 5)
867d2691daSSteve Longerbeam #define IPU_FIELD_OFS2		IPU_CPMEM_WORD(1, 138, 5)
877d2691daSSteve Longerbeam #define IPU_FIELD_OFS3		IPU_CPMEM_WORD(1, 143, 5)
887d2691daSSteve Longerbeam #define IPU_FIELD_SXYS		IPU_CPMEM_WORD(1, 148, 1)
897d2691daSSteve Longerbeam #define IPU_FIELD_CRE		IPU_CPMEM_WORD(1, 149, 1)
907d2691daSSteve Longerbeam #define IPU_FIELD_DEC_SEL2	IPU_CPMEM_WORD(1, 150, 1)
917d2691daSSteve Longerbeam 
927d2691daSSteve Longerbeam static inline struct ipu_ch_param __iomem *
ipu_get_cpmem(struct ipuv3_channel * ch)937d2691daSSteve Longerbeam ipu_get_cpmem(struct ipuv3_channel *ch)
947d2691daSSteve Longerbeam {
957d2691daSSteve Longerbeam 	struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
967d2691daSSteve Longerbeam 
977d2691daSSteve Longerbeam 	return cpmem->base + ch->num;
987d2691daSSteve Longerbeam }
997d2691daSSteve Longerbeam 
ipu_ch_param_write_field(struct ipuv3_channel * ch,u32 wbs,u32 v)1007d2691daSSteve Longerbeam static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
1017d2691daSSteve Longerbeam {
1027d2691daSSteve Longerbeam 	struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1037d2691daSSteve Longerbeam 	u32 bit = (wbs >> 8) % 160;
1047d2691daSSteve Longerbeam 	u32 size = wbs & 0xff;
1057d2691daSSteve Longerbeam 	u32 word = (wbs >> 8) / 160;
1067d2691daSSteve Longerbeam 	u32 i = bit / 32;
1077d2691daSSteve Longerbeam 	u32 ofs = bit % 32;
1087d2691daSSteve Longerbeam 	u32 mask = (1 << size) - 1;
1097d2691daSSteve Longerbeam 	u32 val;
1107d2691daSSteve Longerbeam 
1117d2691daSSteve Longerbeam 	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1127d2691daSSteve Longerbeam 
1137d2691daSSteve Longerbeam 	val = readl(&base->word[word].data[i]);
1147d2691daSSteve Longerbeam 	val &= ~(mask << ofs);
1157d2691daSSteve Longerbeam 	val |= v << ofs;
1167d2691daSSteve Longerbeam 	writel(val, &base->word[word].data[i]);
1177d2691daSSteve Longerbeam 
1187d2691daSSteve Longerbeam 	if ((bit + size - 1) / 32 > i) {
1197d2691daSSteve Longerbeam 		val = readl(&base->word[word].data[i + 1]);
1207d2691daSSteve Longerbeam 		val &= ~(mask >> (ofs ? (32 - ofs) : 0));
1217d2691daSSteve Longerbeam 		val |= v >> (ofs ? (32 - ofs) : 0);
1227d2691daSSteve Longerbeam 		writel(val, &base->word[word].data[i + 1]);
1237d2691daSSteve Longerbeam 	}
1247d2691daSSteve Longerbeam }
1257d2691daSSteve Longerbeam 
ipu_ch_param_read_field(struct ipuv3_channel * ch,u32 wbs)1267d2691daSSteve Longerbeam static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
1277d2691daSSteve Longerbeam {
1287d2691daSSteve Longerbeam 	struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1297d2691daSSteve Longerbeam 	u32 bit = (wbs >> 8) % 160;
1307d2691daSSteve Longerbeam 	u32 size = wbs & 0xff;
1317d2691daSSteve Longerbeam 	u32 word = (wbs >> 8) / 160;
1327d2691daSSteve Longerbeam 	u32 i = bit / 32;
1337d2691daSSteve Longerbeam 	u32 ofs = bit % 32;
1347d2691daSSteve Longerbeam 	u32 mask = (1 << size) - 1;
1357d2691daSSteve Longerbeam 	u32 val = 0;
1367d2691daSSteve Longerbeam 
1377d2691daSSteve Longerbeam 	pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1387d2691daSSteve Longerbeam 
1397d2691daSSteve Longerbeam 	val = (readl(&base->word[word].data[i]) >> ofs) & mask;
1407d2691daSSteve Longerbeam 
1417d2691daSSteve Longerbeam 	if ((bit + size - 1) / 32 > i) {
1427d2691daSSteve Longerbeam 		u32 tmp;
1437d2691daSSteve Longerbeam 
1447d2691daSSteve Longerbeam 		tmp = readl(&base->word[word].data[i + 1]);
1457d2691daSSteve Longerbeam 		tmp &= mask >> (ofs ? (32 - ofs) : 0);
1467d2691daSSteve Longerbeam 		val |= tmp << (ofs ? (32 - ofs) : 0);
1477d2691daSSteve Longerbeam 	}
1487d2691daSSteve Longerbeam 
1497d2691daSSteve Longerbeam 	return val;
1507d2691daSSteve Longerbeam }
1517d2691daSSteve Longerbeam 
1527d2691daSSteve Longerbeam /*
1537d2691daSSteve Longerbeam  * The V4L2 spec defines packed RGB formats in memory byte order, which from
1547d2691daSSteve Longerbeam  * point of view of the IPU corresponds to little-endian words with the first
1557d2691daSSteve Longerbeam  * component in the least significant bits.
1567d2691daSSteve Longerbeam  * The DRM pixel formats and IPU internal representation are ordered the other
1577d2691daSSteve Longerbeam  * way around, with the first named component ordered at the most significant
1587d2691daSSteve Longerbeam  * bits. Further, V4L2 formats are not well defined:
1594a3d0cb0SMauro Carvalho Chehab  *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
1607d2691daSSteve Longerbeam  * We choose the interpretation which matches GStreamer behavior.
1617d2691daSSteve Longerbeam  */
v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)1627d2691daSSteve Longerbeam static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
1637d2691daSSteve Longerbeam {
1647d2691daSSteve Longerbeam 	switch (pixelformat) {
1657d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_RGB565:
1667d2691daSSteve Longerbeam 		/*
1677d2691daSSteve Longerbeam 		 * Here we choose the 'corrected' interpretation of RGBP, a
1687d2691daSSteve Longerbeam 		 * little-endian 16-bit word with the red component at the most
1697d2691daSSteve Longerbeam 		 * significant bits:
1707d2691daSSteve Longerbeam 		 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
1717d2691daSSteve Longerbeam 		 */
1727d2691daSSteve Longerbeam 		return DRM_FORMAT_RGB565;
1737d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_BGR24:
1747d2691daSSteve Longerbeam 		/* B G R <=> [24:0] R:G:B */
1757d2691daSSteve Longerbeam 		return DRM_FORMAT_RGB888;
1767d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_RGB24:
1777d2691daSSteve Longerbeam 		/* R G B <=> [24:0] B:G:R */
1787d2691daSSteve Longerbeam 		return DRM_FORMAT_BGR888;
1797d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_BGR32:
1807d2691daSSteve Longerbeam 		/* B G R A <=> [32:0] A:B:G:R */
1817d2691daSSteve Longerbeam 		return DRM_FORMAT_XRGB8888;
1827d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_RGB32:
1837d2691daSSteve Longerbeam 		/* R G B A <=> [32:0] A:B:G:R */
1847d2691daSSteve Longerbeam 		return DRM_FORMAT_XBGR8888;
185a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_ABGR32:
186a5995717SPhilipp Zabel 		/* B G R A <=> [32:0] A:R:G:B */
187a5995717SPhilipp Zabel 		return DRM_FORMAT_ARGB8888;
1885c41bb60SPhilipp Zabel 	case V4L2_PIX_FMT_XBGR32:
1895c41bb60SPhilipp Zabel 		/* B G R X <=> [32:0] X:R:G:B */
1905c41bb60SPhilipp Zabel 		return DRM_FORMAT_XRGB8888;
191a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_BGRA32:
192a5995717SPhilipp Zabel 		/* A B G R <=> [32:0] R:G:B:A */
193a5995717SPhilipp Zabel 		return DRM_FORMAT_RGBA8888;
194a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_BGRX32:
195a5995717SPhilipp Zabel 		/* X B G R <=> [32:0] R:G:B:X */
196a5995717SPhilipp Zabel 		return DRM_FORMAT_RGBX8888;
197a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_RGBA32:
198a5995717SPhilipp Zabel 		/* R G B A <=> [32:0] A:B:G:R */
199a5995717SPhilipp Zabel 		return DRM_FORMAT_ABGR8888;
200a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_RGBX32:
201a5995717SPhilipp Zabel 		/* R G B X <=> [32:0] X:B:G:R */
202a5995717SPhilipp Zabel 		return DRM_FORMAT_XBGR8888;
203a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_ARGB32:
204a5995717SPhilipp Zabel 		/* A R G B <=> [32:0] B:G:R:A */
205a5995717SPhilipp Zabel 		return DRM_FORMAT_BGRA8888;
2065c41bb60SPhilipp Zabel 	case V4L2_PIX_FMT_XRGB32:
2075c41bb60SPhilipp Zabel 		/* X R G B <=> [32:0] B:G:R:X */
2085c41bb60SPhilipp Zabel 		return DRM_FORMAT_BGRX8888;
2097d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_UYVY:
2107d2691daSSteve Longerbeam 		return DRM_FORMAT_UYVY;
2117d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YUYV:
2127d2691daSSteve Longerbeam 		return DRM_FORMAT_YUYV;
2137d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YUV420:
2147d2691daSSteve Longerbeam 		return DRM_FORMAT_YUV420;
2159a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_YUV422P:
2169a34cef0SSteve Longerbeam 		return DRM_FORMAT_YUV422;
2177d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YVU420:
2187d2691daSSteve Longerbeam 		return DRM_FORMAT_YVU420;
2199a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_NV12:
2209a34cef0SSteve Longerbeam 		return DRM_FORMAT_NV12;
2219a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_NV16:
2229a34cef0SSteve Longerbeam 		return DRM_FORMAT_NV16;
2237d2691daSSteve Longerbeam 	}
2247d2691daSSteve Longerbeam 
2257d2691daSSteve Longerbeam 	return -EINVAL;
2267d2691daSSteve Longerbeam }
2277d2691daSSteve Longerbeam 
ipu_cpmem_zero(struct ipuv3_channel * ch)2287d2691daSSteve Longerbeam void ipu_cpmem_zero(struct ipuv3_channel *ch)
2297d2691daSSteve Longerbeam {
2307d2691daSSteve Longerbeam 	struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
2317d2691daSSteve Longerbeam 	void __iomem *base = p;
2327d2691daSSteve Longerbeam 	int i;
2337d2691daSSteve Longerbeam 
2347d2691daSSteve Longerbeam 	for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
2357d2691daSSteve Longerbeam 		writel(0, base + i * sizeof(u32));
2367d2691daSSteve Longerbeam }
2377d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
2387d2691daSSteve Longerbeam 
ipu_cpmem_set_resolution(struct ipuv3_channel * ch,int xres,int yres)2397d2691daSSteve Longerbeam void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
2407d2691daSSteve Longerbeam {
2417d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
2427d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
2437d2691daSSteve Longerbeam }
2447d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
2457d2691daSSteve Longerbeam 
ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel * ch)246e1e9733cSPhilipp Zabel void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
247e1e9733cSPhilipp Zabel {
248e1e9733cSPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
249e1e9733cSPhilipp Zabel }
250e1e9733cSPhilipp Zabel EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
251e1e9733cSPhilipp Zabel 
ipu_cpmem_set_stride(struct ipuv3_channel * ch,int stride)2527d2691daSSteve Longerbeam void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
2537d2691daSSteve Longerbeam {
2547d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
2557d2691daSSteve Longerbeam }
2567d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
2577d2691daSSteve Longerbeam 
ipu_cpmem_set_high_priority(struct ipuv3_channel * ch)2587d2691daSSteve Longerbeam void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
2597d2691daSSteve Longerbeam {
2607d2691daSSteve Longerbeam 	struct ipu_soc *ipu = ch->ipu;
2617d2691daSSteve Longerbeam 	u32 val;
2627d2691daSSteve Longerbeam 
2637d2691daSSteve Longerbeam 	if (ipu->ipu_type == IPUV3EX)
2647d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
2657d2691daSSteve Longerbeam 
2667d2691daSSteve Longerbeam 	val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
2677d2691daSSteve Longerbeam 	val |= 1 << (ch->num % 32);
2687d2691daSSteve Longerbeam 	ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
2697d2691daSSteve Longerbeam };
2707d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
2717d2691daSSteve Longerbeam 
ipu_cpmem_set_buffer(struct ipuv3_channel * ch,int bufnum,dma_addr_t buf)2727d2691daSSteve Longerbeam void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
2737d2691daSSteve Longerbeam {
27422ec0808SSteve Longerbeam 	WARN_ON_ONCE(buf & 0x7);
27522ec0808SSteve Longerbeam 
2767d2691daSSteve Longerbeam 	if (bufnum)
2777d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
2787d2691daSSteve Longerbeam 	else
2797d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
2807d2691daSSteve Longerbeam }
2817d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
2827d2691daSSteve Longerbeam 
ipu_cpmem_set_uv_offset(struct ipuv3_channel * ch,u32 u_off,u32 v_off)283e5e8690fSSteve Longerbeam void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
284e5e8690fSSteve Longerbeam {
28522ec0808SSteve Longerbeam 	WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
28622ec0808SSteve Longerbeam 
287e5e8690fSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
288e5e8690fSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
289e5e8690fSSteve Longerbeam }
290e5e8690fSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
291e5e8690fSSteve Longerbeam 
ipu_cpmem_interlaced_scan(struct ipuv3_channel * ch,int stride,u32 pixelformat)2929b5c8d5fSSteve Longerbeam void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
2939b5c8d5fSSteve Longerbeam 			       u32 pixelformat)
2947d2691daSSteve Longerbeam {
2959b5c8d5fSSteve Longerbeam 	u32 ilo, sly, sluv;
2964e3c5d7eSPhilipp Zabel 
2974e3c5d7eSPhilipp Zabel 	if (stride < 0) {
2984e3c5d7eSPhilipp Zabel 		stride = -stride;
2994e3c5d7eSPhilipp Zabel 		ilo = 0x100000 - (stride / 8);
3004e3c5d7eSPhilipp Zabel 	} else {
3014e3c5d7eSPhilipp Zabel 		ilo = stride / 8;
3024e3c5d7eSPhilipp Zabel 	}
3034e3c5d7eSPhilipp Zabel 
3044e3c5d7eSPhilipp Zabel 	sly = (stride * 2) - 1;
3054e3c5d7eSPhilipp Zabel 
3069b5c8d5fSSteve Longerbeam 	switch (pixelformat) {
3079b5c8d5fSSteve Longerbeam 	case V4L2_PIX_FMT_YUV420:
3089b5c8d5fSSteve Longerbeam 	case V4L2_PIX_FMT_YVU420:
3099b5c8d5fSSteve Longerbeam 		sluv = stride / 2 - 1;
3109b5c8d5fSSteve Longerbeam 		break;
3119b5c8d5fSSteve Longerbeam 	case V4L2_PIX_FMT_NV12:
3129b5c8d5fSSteve Longerbeam 		sluv = stride - 1;
3139b5c8d5fSSteve Longerbeam 		break;
3149b5c8d5fSSteve Longerbeam 	case V4L2_PIX_FMT_YUV422P:
3159b5c8d5fSSteve Longerbeam 		sluv = stride - 1;
3169b5c8d5fSSteve Longerbeam 		break;
3179b5c8d5fSSteve Longerbeam 	case V4L2_PIX_FMT_NV16:
3189b5c8d5fSSteve Longerbeam 		sluv = stride * 2 - 1;
3199b5c8d5fSSteve Longerbeam 		break;
3209b5c8d5fSSteve Longerbeam 	default:
3219b5c8d5fSSteve Longerbeam 		sluv = 0;
3229b5c8d5fSSteve Longerbeam 		break;
3239b5c8d5fSSteve Longerbeam 	}
3249b5c8d5fSSteve Longerbeam 
3257d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
3264e3c5d7eSPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
3274e3c5d7eSPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
3289b5c8d5fSSteve Longerbeam 	if (sluv)
3299b5c8d5fSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
3307d2691daSSteve Longerbeam };
3317d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
3327d2691daSSteve Longerbeam 
ipu_cpmem_set_axi_id(struct ipuv3_channel * ch,u32 id)333555f0e66SSteve Longerbeam void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
334555f0e66SSteve Longerbeam {
335555f0e66SSteve Longerbeam 	id &= 0x3;
336555f0e66SSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
337555f0e66SSteve Longerbeam }
338555f0e66SSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
339555f0e66SSteve Longerbeam 
ipu_cpmem_get_burstsize(struct ipuv3_channel * ch)34003085911SSteve Longerbeam int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
34103085911SSteve Longerbeam {
34203085911SSteve Longerbeam 	return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
34303085911SSteve Longerbeam }
34403085911SSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
34503085911SSteve Longerbeam 
ipu_cpmem_set_burstsize(struct ipuv3_channel * ch,int burstsize)3467d2691daSSteve Longerbeam void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
3477d2691daSSteve Longerbeam {
3487d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
3497d2691daSSteve Longerbeam };
3507d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
3517d2691daSSteve Longerbeam 
ipu_cpmem_set_block_mode(struct ipuv3_channel * ch)3529b9da0beSSteve Longerbeam void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
3539b9da0beSSteve Longerbeam {
3549b9da0beSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
3559b9da0beSSteve Longerbeam }
3569b9da0beSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
3579b9da0beSSteve Longerbeam 
ipu_cpmem_set_rotation(struct ipuv3_channel * ch,enum ipu_rotate_mode rot)358c42d37caSSteve Longerbeam void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
359c42d37caSSteve Longerbeam 			    enum ipu_rotate_mode rot)
360c42d37caSSteve Longerbeam {
361c42d37caSSteve Longerbeam 	u32 temp_rot = bitrev8(rot) >> 5;
362c42d37caSSteve Longerbeam 
363c42d37caSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
364c42d37caSSteve Longerbeam }
365c42d37caSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
366c42d37caSSteve Longerbeam 
ipu_cpmem_set_format_rgb(struct ipuv3_channel * ch,const struct ipu_rgb * rgb)3677d2691daSSteve Longerbeam int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
3687d2691daSSteve Longerbeam 			     const struct ipu_rgb *rgb)
3697d2691daSSteve Longerbeam {
3707d2691daSSteve Longerbeam 	int bpp = 0, npb = 0, ro, go, bo, to;
3717d2691daSSteve Longerbeam 
3727d2691daSSteve Longerbeam 	ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
3737d2691daSSteve Longerbeam 	go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
3747d2691daSSteve Longerbeam 	bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
3757d2691daSSteve Longerbeam 	to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
3767d2691daSSteve Longerbeam 
3777d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
3787d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
3797d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
3807d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
3817d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
3827d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
3837d2691daSSteve Longerbeam 
3847d2691daSSteve Longerbeam 	if (rgb->transp.length) {
3857d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
3867d2691daSSteve Longerbeam 				rgb->transp.length - 1);
3877d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
3887d2691daSSteve Longerbeam 	} else {
3897d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
3907d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
3917d2691daSSteve Longerbeam 				rgb->bits_per_pixel);
3927d2691daSSteve Longerbeam 	}
3937d2691daSSteve Longerbeam 
3947d2691daSSteve Longerbeam 	switch (rgb->bits_per_pixel) {
3957d2691daSSteve Longerbeam 	case 32:
3967d2691daSSteve Longerbeam 		bpp = 0;
3977d2691daSSteve Longerbeam 		npb = 15;
3987d2691daSSteve Longerbeam 		break;
3997d2691daSSteve Longerbeam 	case 24:
4007d2691daSSteve Longerbeam 		bpp = 1;
4017d2691daSSteve Longerbeam 		npb = 19;
4027d2691daSSteve Longerbeam 		break;
4037d2691daSSteve Longerbeam 	case 16:
4047d2691daSSteve Longerbeam 		bpp = 3;
4057d2691daSSteve Longerbeam 		npb = 31;
4067d2691daSSteve Longerbeam 		break;
4077d2691daSSteve Longerbeam 	case 8:
4087d2691daSSteve Longerbeam 		bpp = 5;
4097d2691daSSteve Longerbeam 		npb = 63;
4107d2691daSSteve Longerbeam 		break;
4117d2691daSSteve Longerbeam 	default:
4127d2691daSSteve Longerbeam 		return -EINVAL;
4137d2691daSSteve Longerbeam 	}
4147d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
4157d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
4167d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
4177d2691daSSteve Longerbeam 
4187d2691daSSteve Longerbeam 	return 0;
4197d2691daSSteve Longerbeam }
4207d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
4217d2691daSSteve Longerbeam 
ipu_cpmem_set_format_passthrough(struct ipuv3_channel * ch,int width)4227d2691daSSteve Longerbeam int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
4237d2691daSSteve Longerbeam {
4247d2691daSSteve Longerbeam 	int bpp = 0, npb = 0;
4257d2691daSSteve Longerbeam 
4267d2691daSSteve Longerbeam 	switch (width) {
4277d2691daSSteve Longerbeam 	case 32:
4287d2691daSSteve Longerbeam 		bpp = 0;
4297d2691daSSteve Longerbeam 		npb = 15;
4307d2691daSSteve Longerbeam 		break;
4317d2691daSSteve Longerbeam 	case 24:
4327d2691daSSteve Longerbeam 		bpp = 1;
4337d2691daSSteve Longerbeam 		npb = 19;
4347d2691daSSteve Longerbeam 		break;
4357d2691daSSteve Longerbeam 	case 16:
4367d2691daSSteve Longerbeam 		bpp = 3;
4377d2691daSSteve Longerbeam 		npb = 31;
4387d2691daSSteve Longerbeam 		break;
4397d2691daSSteve Longerbeam 	case 8:
4407d2691daSSteve Longerbeam 		bpp = 5;
4417d2691daSSteve Longerbeam 		npb = 63;
4427d2691daSSteve Longerbeam 		break;
4437d2691daSSteve Longerbeam 	default:
4447d2691daSSteve Longerbeam 		return -EINVAL;
4457d2691daSSteve Longerbeam 	}
4467d2691daSSteve Longerbeam 
4477d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
4487d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
4497d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
4507d2691daSSteve Longerbeam 
4517d2691daSSteve Longerbeam 	return 0;
4527d2691daSSteve Longerbeam }
4537d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
4547d2691daSSteve Longerbeam 
ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel * ch,u32 pixel_format)4557d2691daSSteve Longerbeam void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
4567d2691daSSteve Longerbeam {
4577d2691daSSteve Longerbeam 	switch (pixel_format) {
4587d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_UYVY:
4597d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
4607d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
4617d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
4627d2691daSSteve Longerbeam 		break;
4637d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YUYV:
4647d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
4657d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
4667d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
4677d2691daSSteve Longerbeam 		break;
4687d2691daSSteve Longerbeam 	}
4697d2691daSSteve Longerbeam }
4707d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
4717d2691daSSteve Longerbeam 
ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel * ch,unsigned int uv_stride,unsigned int u_offset,unsigned int v_offset)4727d2691daSSteve Longerbeam void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
47390195c36SPhilipp Zabel 				   unsigned int uv_stride,
47490195c36SPhilipp Zabel 				   unsigned int u_offset, unsigned int v_offset)
4757d2691daSSteve Longerbeam {
47622ec0808SSteve Longerbeam 	WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
47722ec0808SSteve Longerbeam 
47890195c36SPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
4797d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
4807d2691daSSteve Longerbeam 	ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
4817d2691daSSteve Longerbeam }
4827d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
4837d2691daSSteve Longerbeam 
484067f4aa4SPhilipp Zabel static const struct ipu_rgb def_xrgb_32 = {
4857d2691daSSteve Longerbeam 	.red	= { .offset = 16, .length = 8, },
4867d2691daSSteve Longerbeam 	.green	= { .offset =  8, .length = 8, },
4877d2691daSSteve Longerbeam 	.blue	= { .offset =  0, .length = 8, },
4887d2691daSSteve Longerbeam 	.transp = { .offset = 24, .length = 8, },
4897d2691daSSteve Longerbeam 	.bits_per_pixel = 32,
4907d2691daSSteve Longerbeam };
4917d2691daSSteve Longerbeam 
492067f4aa4SPhilipp Zabel static const struct ipu_rgb def_xbgr_32 = {
4937d2691daSSteve Longerbeam 	.red	= { .offset =  0, .length = 8, },
4947d2691daSSteve Longerbeam 	.green	= { .offset =  8, .length = 8, },
4957d2691daSSteve Longerbeam 	.blue	= { .offset = 16, .length = 8, },
4967d2691daSSteve Longerbeam 	.transp = { .offset = 24, .length = 8, },
4977d2691daSSteve Longerbeam 	.bits_per_pixel = 32,
4987d2691daSSteve Longerbeam };
4997d2691daSSteve Longerbeam 
500067f4aa4SPhilipp Zabel static const struct ipu_rgb def_rgbx_32 = {
501067f4aa4SPhilipp Zabel 	.red	= { .offset = 24, .length = 8, },
502067f4aa4SPhilipp Zabel 	.green	= { .offset = 16, .length = 8, },
503067f4aa4SPhilipp Zabel 	.blue	= { .offset =  8, .length = 8, },
504067f4aa4SPhilipp Zabel 	.transp = { .offset =  0, .length = 8, },
505067f4aa4SPhilipp Zabel 	.bits_per_pixel = 32,
506067f4aa4SPhilipp Zabel };
507067f4aa4SPhilipp Zabel 
508067f4aa4SPhilipp Zabel static const struct ipu_rgb def_bgrx_32 = {
509067f4aa4SPhilipp Zabel 	.red	= { .offset =  8, .length = 8, },
510067f4aa4SPhilipp Zabel 	.green	= { .offset = 16, .length = 8, },
511067f4aa4SPhilipp Zabel 	.blue	= { .offset = 24, .length = 8, },
512067f4aa4SPhilipp Zabel 	.transp = { .offset =  0, .length = 8, },
513067f4aa4SPhilipp Zabel 	.bits_per_pixel = 32,
514067f4aa4SPhilipp Zabel };
515067f4aa4SPhilipp Zabel 
5167d2691daSSteve Longerbeam static const struct ipu_rgb def_rgb_24 = {
5177d2691daSSteve Longerbeam 	.red	= { .offset = 16, .length = 8, },
5187d2691daSSteve Longerbeam 	.green	= { .offset =  8, .length = 8, },
5197d2691daSSteve Longerbeam 	.blue	= { .offset =  0, .length = 8, },
5207d2691daSSteve Longerbeam 	.transp = { .offset =  0, .length = 0, },
5217d2691daSSteve Longerbeam 	.bits_per_pixel = 24,
5227d2691daSSteve Longerbeam };
5237d2691daSSteve Longerbeam 
5247d2691daSSteve Longerbeam static const struct ipu_rgb def_bgr_24 = {
5257d2691daSSteve Longerbeam 	.red	= { .offset =  0, .length = 8, },
5267d2691daSSteve Longerbeam 	.green	= { .offset =  8, .length = 8, },
5277d2691daSSteve Longerbeam 	.blue	= { .offset = 16, .length = 8, },
5287d2691daSSteve Longerbeam 	.transp = { .offset =  0, .length = 0, },
5297d2691daSSteve Longerbeam 	.bits_per_pixel = 24,
5307d2691daSSteve Longerbeam };
5317d2691daSSteve Longerbeam 
5327d2691daSSteve Longerbeam static const struct ipu_rgb def_rgb_16 = {
5337d2691daSSteve Longerbeam 	.red	= { .offset = 11, .length = 5, },
5347d2691daSSteve Longerbeam 	.green	= { .offset =  5, .length = 6, },
5357d2691daSSteve Longerbeam 	.blue	= { .offset =  0, .length = 5, },
5367d2691daSSteve Longerbeam 	.transp = { .offset =  0, .length = 0, },
5377d2691daSSteve Longerbeam 	.bits_per_pixel = 16,
5387d2691daSSteve Longerbeam };
5397d2691daSSteve Longerbeam 
5407d2691daSSteve Longerbeam static const struct ipu_rgb def_bgr_16 = {
5417d2691daSSteve Longerbeam 	.red	= { .offset =  0, .length = 5, },
5427d2691daSSteve Longerbeam 	.green	= { .offset =  5, .length = 6, },
5437d2691daSSteve Longerbeam 	.blue	= { .offset = 11, .length = 5, },
5447d2691daSSteve Longerbeam 	.transp = { .offset =  0, .length = 0, },
5457d2691daSSteve Longerbeam 	.bits_per_pixel = 16,
5467d2691daSSteve Longerbeam };
5477d2691daSSteve Longerbeam 
5480cb8b757SPhilipp Zabel static const struct ipu_rgb def_argb_16 = {
5490cb8b757SPhilipp Zabel 	.red	= { .offset = 10, .length = 5, },
5500cb8b757SPhilipp Zabel 	.green	= { .offset =  5, .length = 5, },
5510cb8b757SPhilipp Zabel 	.blue	= { .offset =  0, .length = 5, },
5520cb8b757SPhilipp Zabel 	.transp = { .offset = 15, .length = 1, },
5530cb8b757SPhilipp Zabel 	.bits_per_pixel = 16,
5540cb8b757SPhilipp Zabel };
5550cb8b757SPhilipp Zabel 
5567d2e8a20SLucas Stach static const struct ipu_rgb def_argb_16_4444 = {
5577d2e8a20SLucas Stach 	.red	= { .offset =  8, .length = 4, },
5587d2e8a20SLucas Stach 	.green	= { .offset =  4, .length = 4, },
5597d2e8a20SLucas Stach 	.blue	= { .offset =  0, .length = 4, },
5607d2e8a20SLucas Stach 	.transp = { .offset = 12, .length = 4, },
5617d2e8a20SLucas Stach 	.bits_per_pixel = 16,
5627d2e8a20SLucas Stach };
5637d2e8a20SLucas Stach 
5640cb8b757SPhilipp Zabel static const struct ipu_rgb def_abgr_16 = {
5650cb8b757SPhilipp Zabel 	.red	= { .offset =  0, .length = 5, },
5660cb8b757SPhilipp Zabel 	.green	= { .offset =  5, .length = 5, },
5670cb8b757SPhilipp Zabel 	.blue	= { .offset = 10, .length = 5, },
5680cb8b757SPhilipp Zabel 	.transp = { .offset = 15, .length = 1, },
5690cb8b757SPhilipp Zabel 	.bits_per_pixel = 16,
5700cb8b757SPhilipp Zabel };
5710cb8b757SPhilipp Zabel 
5720cb8b757SPhilipp Zabel static const struct ipu_rgb def_rgba_16 = {
5730cb8b757SPhilipp Zabel 	.red	= { .offset = 11, .length = 5, },
5740cb8b757SPhilipp Zabel 	.green	= { .offset =  6, .length = 5, },
5750cb8b757SPhilipp Zabel 	.blue	= { .offset =  1, .length = 5, },
5760cb8b757SPhilipp Zabel 	.transp = { .offset =  0, .length = 1, },
5770cb8b757SPhilipp Zabel 	.bits_per_pixel = 16,
5780cb8b757SPhilipp Zabel };
5790cb8b757SPhilipp Zabel 
5800cb8b757SPhilipp Zabel static const struct ipu_rgb def_bgra_16 = {
5810cb8b757SPhilipp Zabel 	.red	= { .offset =  1, .length = 5, },
5820cb8b757SPhilipp Zabel 	.green	= { .offset =  6, .length = 5, },
5830cb8b757SPhilipp Zabel 	.blue	= { .offset = 11, .length = 5, },
5840cb8b757SPhilipp Zabel 	.transp = { .offset =  0, .length = 1, },
5850cb8b757SPhilipp Zabel 	.bits_per_pixel = 16,
5860cb8b757SPhilipp Zabel };
5870cb8b757SPhilipp Zabel 
588*7cca7c80SKrzysztof Hałasa #define Y_OFFSET(pix, x, y)	((x) + pix->bytesperline * (y))
589*7cca7c80SKrzysztof Hałasa #define U_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
590*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
591*7cca7c80SKrzysztof Hałasa #define V_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
592*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * pix->height / 4) + \
593*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
594*7cca7c80SKrzysztof Hałasa #define U2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
595*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * (y) / 2) + (x) / 2)
596*7cca7c80SKrzysztof Hałasa #define V2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
597*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * pix->height / 2) + \
598*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * (y) / 2) + (x) / 2)
599*7cca7c80SKrzysztof Hałasa #define UV_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
600*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * ((y) / 2)) + (x))
601*7cca7c80SKrzysztof Hałasa #define UV2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
602*7cca7c80SKrzysztof Hałasa 				 (pix->bytesperline * y) + (x))
6037d2691daSSteve Longerbeam 
604e72db3b1SPhilipp Zabel #define NUM_ALPHA_CHANNELS	7
605e72db3b1SPhilipp Zabel 
606e72db3b1SPhilipp Zabel /* See Table 37-12. Alpha channels mapping. */
ipu_channel_albm(int ch_num)607e72db3b1SPhilipp Zabel static int ipu_channel_albm(int ch_num)
608e72db3b1SPhilipp Zabel {
609e72db3b1SPhilipp Zabel 	switch (ch_num) {
610e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:	return 0;
611e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_G_MEM_IC_PP:		return 1;
612e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_MEM_FG_SYNC:		return 2;
613e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_MEM_FG_ASYNC:	return 3;
614e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_MEM_BG_SYNC:		return 4;
615e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_MEM_BG_ASYNC:	return 5;
616e72db3b1SPhilipp Zabel 	case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
617e72db3b1SPhilipp Zabel 	default:
618e72db3b1SPhilipp Zabel 		return -EINVAL;
619e72db3b1SPhilipp Zabel 	}
620e72db3b1SPhilipp Zabel }
621e72db3b1SPhilipp Zabel 
ipu_cpmem_set_separate_alpha(struct ipuv3_channel * ch)622e72db3b1SPhilipp Zabel static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
623e72db3b1SPhilipp Zabel {
624e72db3b1SPhilipp Zabel 	struct ipu_soc *ipu = ch->ipu;
625e72db3b1SPhilipp Zabel 	int albm;
626e72db3b1SPhilipp Zabel 	u32 val;
627e72db3b1SPhilipp Zabel 
628e72db3b1SPhilipp Zabel 	albm = ipu_channel_albm(ch->num);
629e72db3b1SPhilipp Zabel 	if (albm < 0)
630e72db3b1SPhilipp Zabel 		return;
631e72db3b1SPhilipp Zabel 
632e72db3b1SPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
633e72db3b1SPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
634e72db3b1SPhilipp Zabel 	ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
635e72db3b1SPhilipp Zabel 
636e72db3b1SPhilipp Zabel 	val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
637e72db3b1SPhilipp Zabel 	val |= BIT(ch->num);
638e72db3b1SPhilipp Zabel 	ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
639e72db3b1SPhilipp Zabel }
640e72db3b1SPhilipp Zabel 
ipu_cpmem_set_fmt(struct ipuv3_channel * ch,u32 drm_fourcc)6417d2691daSSteve Longerbeam int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
6427d2691daSSteve Longerbeam {
6437d2691daSSteve Longerbeam 	switch (drm_fourcc) {
6447d2691daSSteve Longerbeam 	case DRM_FORMAT_YUV420:
6457d2691daSSteve Longerbeam 	case DRM_FORMAT_YVU420:
6467d2691daSSteve Longerbeam 		/* pix format */
6477d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
6487d2691daSSteve Longerbeam 		/* burst size */
6497d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6507d2691daSSteve Longerbeam 		break;
6519a34cef0SSteve Longerbeam 	case DRM_FORMAT_YUV422:
6529a34cef0SSteve Longerbeam 	case DRM_FORMAT_YVU422:
6539a34cef0SSteve Longerbeam 		/* pix format */
6549a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
6559a34cef0SSteve Longerbeam 		/* burst size */
6569a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6579a34cef0SSteve Longerbeam 		break;
658c9d508c2SPhilipp Zabel 	case DRM_FORMAT_YUV444:
659c9d508c2SPhilipp Zabel 	case DRM_FORMAT_YVU444:
660c9d508c2SPhilipp Zabel 		/* pix format */
661c9d508c2SPhilipp Zabel 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
662c9d508c2SPhilipp Zabel 		/* burst size */
663c9d508c2SPhilipp Zabel 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
664c9d508c2SPhilipp Zabel 		break;
6659a34cef0SSteve Longerbeam 	case DRM_FORMAT_NV12:
6669a34cef0SSteve Longerbeam 		/* pix format */
6679a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
6689a34cef0SSteve Longerbeam 		/* burst size */
6699a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6709a34cef0SSteve Longerbeam 		break;
6719a34cef0SSteve Longerbeam 	case DRM_FORMAT_NV16:
6729a34cef0SSteve Longerbeam 		/* pix format */
6739a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
6749a34cef0SSteve Longerbeam 		/* burst size */
6759a34cef0SSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6769a34cef0SSteve Longerbeam 		break;
6777d2691daSSteve Longerbeam 	case DRM_FORMAT_UYVY:
6787d2691daSSteve Longerbeam 		/* bits/pixel */
6797d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
6807d2691daSSteve Longerbeam 		/* pix format */
6817d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
6827d2691daSSteve Longerbeam 		/* burst size */
6837d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6847d2691daSSteve Longerbeam 		break;
6857d2691daSSteve Longerbeam 	case DRM_FORMAT_YUYV:
6867d2691daSSteve Longerbeam 		/* bits/pixel */
6877d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
6887d2691daSSteve Longerbeam 		/* pix format */
6897d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
6907d2691daSSteve Longerbeam 		/* burst size */
6917d2691daSSteve Longerbeam 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
6927d2691daSSteve Longerbeam 		break;
6937d2691daSSteve Longerbeam 	case DRM_FORMAT_ABGR8888:
6947d2691daSSteve Longerbeam 	case DRM_FORMAT_XBGR8888:
695067f4aa4SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
6967d2691daSSteve Longerbeam 		break;
6977d2691daSSteve Longerbeam 	case DRM_FORMAT_ARGB8888:
6987d2691daSSteve Longerbeam 	case DRM_FORMAT_XRGB8888:
699067f4aa4SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
700067f4aa4SPhilipp Zabel 		break;
701067f4aa4SPhilipp Zabel 	case DRM_FORMAT_RGBA8888:
702067f4aa4SPhilipp Zabel 	case DRM_FORMAT_RGBX8888:
703e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGBX8888_A8:
704067f4aa4SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
705067f4aa4SPhilipp Zabel 		break;
706067f4aa4SPhilipp Zabel 	case DRM_FORMAT_BGRA8888:
707067f4aa4SPhilipp Zabel 	case DRM_FORMAT_BGRX8888:
708e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGRX8888_A8:
709067f4aa4SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
7107d2691daSSteve Longerbeam 		break;
7117d2691daSSteve Longerbeam 	case DRM_FORMAT_BGR888:
712e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGR888_A8:
7137d2691daSSteve Longerbeam 		ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
7147d2691daSSteve Longerbeam 		break;
7157d2691daSSteve Longerbeam 	case DRM_FORMAT_RGB888:
716e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGB888_A8:
7177d2691daSSteve Longerbeam 		ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
7187d2691daSSteve Longerbeam 		break;
7197d2691daSSteve Longerbeam 	case DRM_FORMAT_RGB565:
720e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGB565_A8:
7217d2691daSSteve Longerbeam 		ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
7227d2691daSSteve Longerbeam 		break;
7237d2691daSSteve Longerbeam 	case DRM_FORMAT_BGR565:
724e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGR565_A8:
7257d2691daSSteve Longerbeam 		ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
7267d2691daSSteve Longerbeam 		break;
7270cb8b757SPhilipp Zabel 	case DRM_FORMAT_ARGB1555:
7280cb8b757SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_argb_16);
7290cb8b757SPhilipp Zabel 		break;
7300cb8b757SPhilipp Zabel 	case DRM_FORMAT_ABGR1555:
7310cb8b757SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
7320cb8b757SPhilipp Zabel 		break;
7330cb8b757SPhilipp Zabel 	case DRM_FORMAT_RGBA5551:
7340cb8b757SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
7350cb8b757SPhilipp Zabel 		break;
7360cb8b757SPhilipp Zabel 	case DRM_FORMAT_BGRA5551:
7370cb8b757SPhilipp Zabel 		ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
7380cb8b757SPhilipp Zabel 		break;
7397d2e8a20SLucas Stach 	case DRM_FORMAT_ARGB4444:
7407d2e8a20SLucas Stach 		ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
7417d2e8a20SLucas Stach 		break;
7427d2691daSSteve Longerbeam 	default:
7437d2691daSSteve Longerbeam 		return -EINVAL;
7447d2691daSSteve Longerbeam 	}
7457d2691daSSteve Longerbeam 
746e72db3b1SPhilipp Zabel 	switch (drm_fourcc) {
747e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGB565_A8:
748e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGR565_A8:
749e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGB888_A8:
750e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGR888_A8:
751e72db3b1SPhilipp Zabel 	case DRM_FORMAT_RGBX8888_A8:
752e72db3b1SPhilipp Zabel 	case DRM_FORMAT_BGRX8888_A8:
753e72db3b1SPhilipp Zabel 		ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
754e72db3b1SPhilipp Zabel 		ipu_cpmem_set_separate_alpha(ch);
755e72db3b1SPhilipp Zabel 		break;
756e72db3b1SPhilipp Zabel 	default:
757e72db3b1SPhilipp Zabel 		break;
758e72db3b1SPhilipp Zabel 	}
759e72db3b1SPhilipp Zabel 
7607d2691daSSteve Longerbeam 	return 0;
7617d2691daSSteve Longerbeam }
7627d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
7637d2691daSSteve Longerbeam 
ipu_cpmem_set_image(struct ipuv3_channel * ch,struct ipu_image * image)7647d2691daSSteve Longerbeam int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
7657d2691daSSteve Longerbeam {
7667d2691daSSteve Longerbeam 	struct v4l2_pix_format *pix = &image->pix;
7679a34cef0SSteve Longerbeam 	int offset, u_offset, v_offset;
7685cd43371SPhilipp Zabel 	int ret = 0;
7697d2691daSSteve Longerbeam 
7707d2691daSSteve Longerbeam 	pr_debug("%s: resolution: %dx%d stride: %d\n",
7717d2691daSSteve Longerbeam 		 __func__, pix->width, pix->height,
7727d2691daSSteve Longerbeam 		 pix->bytesperline);
7737d2691daSSteve Longerbeam 
7747d2691daSSteve Longerbeam 	ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
7757d2691daSSteve Longerbeam 	ipu_cpmem_set_stride(ch, pix->bytesperline);
7767d2691daSSteve Longerbeam 
7777d2691daSSteve Longerbeam 	ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
7787d2691daSSteve Longerbeam 
7797d2691daSSteve Longerbeam 	switch (pix->pixelformat) {
7807d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YUV420:
78190195c36SPhilipp Zabel 		offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
782dec408fdSSteve Longerbeam 		u_offset = image->u_offset ?
783dec408fdSSteve Longerbeam 			image->u_offset : U_OFFSET(pix, image->rect.left,
78490195c36SPhilipp Zabel 						   image->rect.top) - offset;
785dec408fdSSteve Longerbeam 		v_offset = image->v_offset ?
786dec408fdSSteve Longerbeam 			image->v_offset : V_OFFSET(pix, image->rect.left,
78790195c36SPhilipp Zabel 						   image->rect.top) - offset;
78890195c36SPhilipp Zabel 
78990195c36SPhilipp Zabel 		ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
79090195c36SPhilipp Zabel 					      u_offset, v_offset);
79190195c36SPhilipp Zabel 		break;
7927d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YVU420:
7939a34cef0SSteve Longerbeam 		offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
794dec408fdSSteve Longerbeam 		u_offset = image->u_offset ?
795dec408fdSSteve Longerbeam 			image->u_offset : V_OFFSET(pix, image->rect.left,
7969a34cef0SSteve Longerbeam 						   image->rect.top) - offset;
797dec408fdSSteve Longerbeam 		v_offset = image->v_offset ?
798dec408fdSSteve Longerbeam 			image->v_offset : U_OFFSET(pix, image->rect.left,
7999a34cef0SSteve Longerbeam 						   image->rect.top) - offset;
8007d2691daSSteve Longerbeam 
80190195c36SPhilipp Zabel 		ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
802dec408fdSSteve Longerbeam 					      u_offset, v_offset);
8039a34cef0SSteve Longerbeam 		break;
8049a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_YUV422P:
8059a34cef0SSteve Longerbeam 		offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
806dec408fdSSteve Longerbeam 		u_offset = image->u_offset ?
807dec408fdSSteve Longerbeam 			image->u_offset : U2_OFFSET(pix, image->rect.left,
8089a34cef0SSteve Longerbeam 						    image->rect.top) - offset;
809dec408fdSSteve Longerbeam 		v_offset = image->v_offset ?
810dec408fdSSteve Longerbeam 			image->v_offset : V2_OFFSET(pix, image->rect.left,
8119a34cef0SSteve Longerbeam 						    image->rect.top) - offset;
8129a34cef0SSteve Longerbeam 
81390195c36SPhilipp Zabel 		ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
8149a34cef0SSteve Longerbeam 					      u_offset, v_offset);
8159a34cef0SSteve Longerbeam 		break;
8169a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_NV12:
8179a34cef0SSteve Longerbeam 		offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
818dec408fdSSteve Longerbeam 		u_offset = image->u_offset ?
819dec408fdSSteve Longerbeam 			image->u_offset : UV_OFFSET(pix, image->rect.left,
8209a34cef0SSteve Longerbeam 						    image->rect.top) - offset;
821dec408fdSSteve Longerbeam 		v_offset = image->v_offset ? image->v_offset : 0;
8229a34cef0SSteve Longerbeam 
82390195c36SPhilipp Zabel 		ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
8249a34cef0SSteve Longerbeam 					      u_offset, v_offset);
8259a34cef0SSteve Longerbeam 		break;
8269a34cef0SSteve Longerbeam 	case V4L2_PIX_FMT_NV16:
8279a34cef0SSteve Longerbeam 		offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
828dec408fdSSteve Longerbeam 		u_offset = image->u_offset ?
829dec408fdSSteve Longerbeam 			image->u_offset : UV2_OFFSET(pix, image->rect.left,
8309a34cef0SSteve Longerbeam 						     image->rect.top) - offset;
831dec408fdSSteve Longerbeam 		v_offset = image->v_offset ? image->v_offset : 0;
8329a34cef0SSteve Longerbeam 
83390195c36SPhilipp Zabel 		ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
8349a34cef0SSteve Longerbeam 					      u_offset, v_offset);
8357d2691daSSteve Longerbeam 		break;
8367d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_UYVY:
8377d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_YUYV:
8382094b603SSteve Longerbeam 	case V4L2_PIX_FMT_RGB565:
8392094b603SSteve Longerbeam 		offset = image->rect.left * 2 +
8402094b603SSteve Longerbeam 			image->rect.top * pix->bytesperline;
8417d2691daSSteve Longerbeam 		break;
8427d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_RGB32:
8437d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_BGR32:
844a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_ABGR32:
8455c41bb60SPhilipp Zabel 	case V4L2_PIX_FMT_XBGR32:
846a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_BGRA32:
847a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_BGRX32:
848a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_RGBA32:
849a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_RGBX32:
850a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_ARGB32:
851a5995717SPhilipp Zabel 	case V4L2_PIX_FMT_XRGB32:
8522094b603SSteve Longerbeam 		offset = image->rect.left * 4 +
8532094b603SSteve Longerbeam 			image->rect.top * pix->bytesperline;
8547d2691daSSteve Longerbeam 		break;
8557d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_RGB24:
8567d2691daSSteve Longerbeam 	case V4L2_PIX_FMT_BGR24:
8572094b603SSteve Longerbeam 		offset = image->rect.left * 3 +
8582094b603SSteve Longerbeam 			image->rect.top * pix->bytesperline;
8597d2691daSSteve Longerbeam 		break;
8601762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SBGGR8:
8611762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SGBRG8:
8621762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SGRBG8:
8631762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SRGGB8:
8646d36b7feSPhilipp Zabel 	case V4L2_PIX_FMT_GREY:
8651762ed65SPhilipp Zabel 		offset = image->rect.left + image->rect.top * pix->bytesperline;
8661762ed65SPhilipp Zabel 		break;
8671762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SBGGR16:
8681762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SGBRG16:
8691762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SGRBG16:
8701762ed65SPhilipp Zabel 	case V4L2_PIX_FMT_SRGGB16:
87158a22fc4SPhilipp Zabel 	case V4L2_PIX_FMT_Y16:
8721762ed65SPhilipp Zabel 		offset = image->rect.left * 2 +
8731762ed65SPhilipp Zabel 			 image->rect.top * pix->bytesperline;
8741762ed65SPhilipp Zabel 		break;
8757d2691daSSteve Longerbeam 	default:
8765cd43371SPhilipp Zabel 		/* This should not happen */
8775cd43371SPhilipp Zabel 		WARN_ON(1);
8785cd43371SPhilipp Zabel 		offset = 0;
8795cd43371SPhilipp Zabel 		ret = -EINVAL;
8807d2691daSSteve Longerbeam 	}
8817d2691daSSteve Longerbeam 
8829a34cef0SSteve Longerbeam 	ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
8839a34cef0SSteve Longerbeam 	ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
8849a34cef0SSteve Longerbeam 
8855cd43371SPhilipp Zabel 	return ret;
8867d2691daSSteve Longerbeam }
8877d2691daSSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
8887d2691daSSteve Longerbeam 
ipu_cpmem_dump(struct ipuv3_channel * ch)88960c04456SSteve Longerbeam void ipu_cpmem_dump(struct ipuv3_channel *ch)
89060c04456SSteve Longerbeam {
89160c04456SSteve Longerbeam 	struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
89260c04456SSteve Longerbeam 	struct ipu_soc *ipu = ch->ipu;
89360c04456SSteve Longerbeam 	int chno = ch->num;
89460c04456SSteve Longerbeam 
89560c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
89660c04456SSteve Longerbeam 		readl(&p->word[0].data[0]),
89760c04456SSteve Longerbeam 		readl(&p->word[0].data[1]),
89860c04456SSteve Longerbeam 		readl(&p->word[0].data[2]),
89960c04456SSteve Longerbeam 		readl(&p->word[0].data[3]),
90060c04456SSteve Longerbeam 		readl(&p->word[0].data[4]));
90160c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
90260c04456SSteve Longerbeam 		readl(&p->word[1].data[0]),
90360c04456SSteve Longerbeam 		readl(&p->word[1].data[1]),
90460c04456SSteve Longerbeam 		readl(&p->word[1].data[2]),
90560c04456SSteve Longerbeam 		readl(&p->word[1].data[3]),
90660c04456SSteve Longerbeam 		readl(&p->word[1].data[4]));
90760c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "PFS 0x%x, ",
90860c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
90960c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "BPP 0x%x, ",
91060c04456SSteve Longerbeam 		ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
91160c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "NPB 0x%x\n",
91260c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
91360c04456SSteve Longerbeam 
91460c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "FW %d, ",
91560c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_FW));
91660c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "FH %d, ",
91760c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_FH));
91860c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "EBA0 0x%x\n",
91960c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
92060c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "EBA1 0x%x\n",
92160c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
92260c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Stride %d\n",
92360c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_SL));
92460c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "scan_order %d\n",
92560c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_SO));
92660c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "uv_stride %d\n",
92760c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
92860c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "u_offset 0x%x\n",
92960c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
93060c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "v_offset 0x%x\n",
93160c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
93260c04456SSteve Longerbeam 
93360c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Width0 %d+1, ",
93460c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
93560c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Width1 %d+1, ",
93660c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
93760c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Width2 %d+1, ",
93860c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
93960c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Width3 %d+1, ",
94060c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
94160c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Offset0 %d, ",
94260c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
94360c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Offset1 %d, ",
94460c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
94560c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Offset2 %d, ",
94660c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
94760c04456SSteve Longerbeam 	dev_dbg(ipu->dev, "Offset3 %d\n",
94860c04456SSteve Longerbeam 		 ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
94960c04456SSteve Longerbeam }
95060c04456SSteve Longerbeam EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
95160c04456SSteve Longerbeam 
ipu_cpmem_init(struct ipu_soc * ipu,struct device * dev,unsigned long base)9527d2691daSSteve Longerbeam int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
9537d2691daSSteve Longerbeam {
9547d2691daSSteve Longerbeam 	struct ipu_cpmem *cpmem;
9557d2691daSSteve Longerbeam 
9567d2691daSSteve Longerbeam 	cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
9577d2691daSSteve Longerbeam 	if (!cpmem)
9587d2691daSSteve Longerbeam 		return -ENOMEM;
9597d2691daSSteve Longerbeam 
9607d2691daSSteve Longerbeam 	ipu->cpmem_priv = cpmem;
9617d2691daSSteve Longerbeam 
9627d2691daSSteve Longerbeam 	spin_lock_init(&cpmem->lock);
9637d2691daSSteve Longerbeam 	cpmem->base = devm_ioremap(dev, base, SZ_128K);
9647d2691daSSteve Longerbeam 	if (!cpmem->base)
9657d2691daSSteve Longerbeam 		return -ENOMEM;
9667d2691daSSteve Longerbeam 
9677d2691daSSteve Longerbeam 	dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
9687d2691daSSteve Longerbeam 		base, cpmem->base);
9697d2691daSSteve Longerbeam 	cpmem->ipu = ipu;
9707d2691daSSteve Longerbeam 
9717d2691daSSteve Longerbeam 	return 0;
9727d2691daSSteve Longerbeam }
9737d2691daSSteve Longerbeam 
ipu_cpmem_exit(struct ipu_soc * ipu)9747d2691daSSteve Longerbeam void ipu_cpmem_exit(struct ipu_soc *ipu)
9757d2691daSSteve Longerbeam {
9767d2691daSSteve Longerbeam }
977