cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipu-cpmem.c (28718B)


      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->bytesperline * (y))
    589#define U_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    590				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
    591#define V_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    592				 (pix->bytesperline * pix->height / 4) + \
    593				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
    594#define U2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    595				 (pix->bytesperline * (y) / 2) + (x) / 2)
    596#define V2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    597				 (pix->bytesperline * pix->height / 2) + \
    598				 (pix->bytesperline * (y) / 2) + (x) / 2)
    599#define UV_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    600				 (pix->bytesperline * ((y) / 2)) + (x))
    601#define UV2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
    602				 (pix->bytesperline * y) + (x))
    603
    604#define NUM_ALPHA_CHANNELS	7
    605
    606/* See Table 37-12. Alpha channels mapping. */
    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}