18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2019 NXP.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/device.h>
78c2ecf20Sopenharmony_ci#include <linux/slab.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "dcss-dev.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define DCSS_DPR_SYSTEM_CTRL0			0x000
128c2ecf20Sopenharmony_ci#define   RUN_EN				BIT(0)
138c2ecf20Sopenharmony_ci#define   SOFT_RESET				BIT(1)
148c2ecf20Sopenharmony_ci#define   REPEAT_EN				BIT(2)
158c2ecf20Sopenharmony_ci#define   SHADOW_LOAD_EN			BIT(3)
168c2ecf20Sopenharmony_ci#define   SW_SHADOW_LOAD_SEL			BIT(4)
178c2ecf20Sopenharmony_ci#define   BCMD2AXI_MSTR_ID_CTRL			BIT(16)
188c2ecf20Sopenharmony_ci#define DCSS_DPR_IRQ_MASK			0x020
198c2ecf20Sopenharmony_ci#define DCSS_DPR_IRQ_MASK_STATUS		0x030
208c2ecf20Sopenharmony_ci#define DCSS_DPR_IRQ_NONMASK_STATUS		0x040
218c2ecf20Sopenharmony_ci#define   IRQ_DPR_CTRL_DONE			BIT(0)
228c2ecf20Sopenharmony_ci#define   IRQ_DPR_RUN				BIT(1)
238c2ecf20Sopenharmony_ci#define   IRQ_DPR_SHADOW_LOADED			BIT(2)
248c2ecf20Sopenharmony_ci#define   IRQ_AXI_READ_ERR			BIT(3)
258c2ecf20Sopenharmony_ci#define   DPR2RTR_YRGB_FIFO_OVFL		BIT(4)
268c2ecf20Sopenharmony_ci#define   DPR2RTR_UV_FIFO_OVFL			BIT(5)
278c2ecf20Sopenharmony_ci#define   DPR2RTR_FIFO_LD_BUF_RDY_YRGB_ERR	BIT(6)
288c2ecf20Sopenharmony_ci#define   DPR2RTR_FIFO_LD_BUF_RDY_UV_ERR	BIT(7)
298c2ecf20Sopenharmony_ci#define DCSS_DPR_MODE_CTRL0			0x050
308c2ecf20Sopenharmony_ci#define   RTR_3BUF_EN				BIT(0)
318c2ecf20Sopenharmony_ci#define   RTR_4LINE_BUF_EN			BIT(1)
328c2ecf20Sopenharmony_ci#define   TILE_TYPE_POS				2
338c2ecf20Sopenharmony_ci#define   TILE_TYPE_MASK			GENMASK(4, 2)
348c2ecf20Sopenharmony_ci#define   YUV_EN				BIT(6)
358c2ecf20Sopenharmony_ci#define   COMP_2PLANE_EN			BIT(7)
368c2ecf20Sopenharmony_ci#define   PIX_SIZE_POS				8
378c2ecf20Sopenharmony_ci#define   PIX_SIZE_MASK				GENMASK(9, 8)
388c2ecf20Sopenharmony_ci#define   PIX_LUMA_UV_SWAP			BIT(10)
398c2ecf20Sopenharmony_ci#define   PIX_UV_SWAP				BIT(11)
408c2ecf20Sopenharmony_ci#define   B_COMP_SEL_POS			12
418c2ecf20Sopenharmony_ci#define   B_COMP_SEL_MASK			GENMASK(13, 12)
428c2ecf20Sopenharmony_ci#define   G_COMP_SEL_POS			14
438c2ecf20Sopenharmony_ci#define   G_COMP_SEL_MASK			GENMASK(15, 14)
448c2ecf20Sopenharmony_ci#define   R_COMP_SEL_POS			16
458c2ecf20Sopenharmony_ci#define   R_COMP_SEL_MASK			GENMASK(17, 16)
468c2ecf20Sopenharmony_ci#define   A_COMP_SEL_POS			18
478c2ecf20Sopenharmony_ci#define   A_COMP_SEL_MASK			GENMASK(19, 18)
488c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_CTRL0			0x070
498c2ecf20Sopenharmony_ci#define   HFLIP_EN				BIT(0)
508c2ecf20Sopenharmony_ci#define   VFLIP_EN				BIT(1)
518c2ecf20Sopenharmony_ci#define   ROT_ENC_POS				2
528c2ecf20Sopenharmony_ci#define   ROT_ENC_MASK				GENMASK(3, 2)
538c2ecf20Sopenharmony_ci#define   ROT_FLIP_ORDER_EN			BIT(4)
548c2ecf20Sopenharmony_ci#define   PITCH_POS				16
558c2ecf20Sopenharmony_ci#define   PITCH_MASK				GENMASK(31, 16)
568c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_1P_CTRL0			0x090
578c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_1P_PIX_X_CTRL		0x0A0
588c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_1P_PIX_Y_CTRL		0x0B0
598c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_1P_BASE_ADDR		0x0C0
608c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_2P_CTRL0			0x0E0
618c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_2P_PIX_X_CTRL		0x0F0
628c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_2P_PIX_Y_CTRL		0x100
638c2ecf20Sopenharmony_ci#define DCSS_DPR_FRAME_2P_BASE_ADDR		0x110
648c2ecf20Sopenharmony_ci#define DCSS_DPR_STATUS_CTRL0			0x130
658c2ecf20Sopenharmony_ci#define   STATUS_MUX_SEL_MASK			GENMASK(2, 0)
668c2ecf20Sopenharmony_ci#define   STATUS_SRC_SEL_POS			16
678c2ecf20Sopenharmony_ci#define   STATUS_SRC_SEL_MASK			GENMASK(18, 16)
688c2ecf20Sopenharmony_ci#define DCSS_DPR_STATUS_CTRL1			0x140
698c2ecf20Sopenharmony_ci#define DCSS_DPR_RTRAM_CTRL0			0x200
708c2ecf20Sopenharmony_ci#define   NUM_ROWS_ACTIVE			BIT(0)
718c2ecf20Sopenharmony_ci#define   THRES_HIGH_POS			1
728c2ecf20Sopenharmony_ci#define   THRES_HIGH_MASK			GENMASK(3, 1)
738c2ecf20Sopenharmony_ci#define   THRES_LOW_POS				4
748c2ecf20Sopenharmony_ci#define   THRES_LOW_MASK			GENMASK(6, 4)
758c2ecf20Sopenharmony_ci#define   ABORT_SEL				BIT(7)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cienum dcss_tile_type {
788c2ecf20Sopenharmony_ci	TILE_LINEAR = 0,
798c2ecf20Sopenharmony_ci	TILE_GPU_STANDARD,
808c2ecf20Sopenharmony_ci	TILE_GPU_SUPER,
818c2ecf20Sopenharmony_ci	TILE_VPU_YUV420,
828c2ecf20Sopenharmony_ci	TILE_VPU_VP9,
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cienum dcss_pix_size {
868c2ecf20Sopenharmony_ci	PIX_SIZE_8,
878c2ecf20Sopenharmony_ci	PIX_SIZE_16,
888c2ecf20Sopenharmony_ci	PIX_SIZE_32,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct dcss_dpr_ch {
928c2ecf20Sopenharmony_ci	struct dcss_dpr *dpr;
938c2ecf20Sopenharmony_ci	void __iomem *base_reg;
948c2ecf20Sopenharmony_ci	u32 base_ofs;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	struct drm_format_info format;
978c2ecf20Sopenharmony_ci	enum dcss_pix_size pix_size;
988c2ecf20Sopenharmony_ci	enum dcss_tile_type tile;
998c2ecf20Sopenharmony_ci	bool rtram_4line_en;
1008c2ecf20Sopenharmony_ci	bool rtram_3buf_en;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	u32 frame_ctrl;
1038c2ecf20Sopenharmony_ci	u32 mode_ctrl;
1048c2ecf20Sopenharmony_ci	u32 sys_ctrl;
1058c2ecf20Sopenharmony_ci	u32 rtram_ctrl;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	bool sys_ctrl_chgd;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	int ch_num;
1108c2ecf20Sopenharmony_ci	int irq;
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistruct dcss_dpr {
1148c2ecf20Sopenharmony_ci	struct device *dev;
1158c2ecf20Sopenharmony_ci	struct dcss_ctxld *ctxld;
1168c2ecf20Sopenharmony_ci	u32  ctx_id;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	struct dcss_dpr_ch ch[3];
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic void dcss_dpr_write(struct dcss_dpr_ch *ch, u32 val, u32 ofs)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct dcss_dpr *dpr = ch->dpr;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	dcss_ctxld_write(dpr->ctxld, dpr->ctx_id, val, ch->base_ofs + ofs);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic int dcss_dpr_ch_init_all(struct dcss_dpr *dpr, unsigned long dpr_base)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch;
1318c2ecf20Sopenharmony_ci	int i;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
1348c2ecf20Sopenharmony_ci		ch = &dpr->ch[i];
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci		ch->base_ofs = dpr_base + i * 0x1000;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci		ch->base_reg = ioremap(ch->base_ofs, SZ_4K);
1398c2ecf20Sopenharmony_ci		if (!ch->base_reg) {
1408c2ecf20Sopenharmony_ci			dev_err(dpr->dev, "dpr: unable to remap ch %d base\n",
1418c2ecf20Sopenharmony_ci				i);
1428c2ecf20Sopenharmony_ci			return -ENOMEM;
1438c2ecf20Sopenharmony_ci		}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci		ch->dpr = dpr;
1468c2ecf20Sopenharmony_ci		ch->ch_num = i;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		dcss_writel(0xff, ch->base_reg + DCSS_DPR_IRQ_MASK);
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	return 0;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciint dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct dcss_dpr *dpr;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	dpr = kzalloc(sizeof(*dpr), GFP_KERNEL);
1598c2ecf20Sopenharmony_ci	if (!dpr)
1608c2ecf20Sopenharmony_ci		return -ENOMEM;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	dcss->dpr = dpr;
1638c2ecf20Sopenharmony_ci	dpr->dev = dcss->dev;
1648c2ecf20Sopenharmony_ci	dpr->ctxld = dcss->ctxld;
1658c2ecf20Sopenharmony_ci	dpr->ctx_id = CTX_SB_HP;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (dcss_dpr_ch_init_all(dpr, dpr_base)) {
1688c2ecf20Sopenharmony_ci		int i;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci		for (i = 0; i < 3; i++) {
1718c2ecf20Sopenharmony_ci			if (dpr->ch[i].base_reg)
1728c2ecf20Sopenharmony_ci				iounmap(dpr->ch[i].base_reg);
1738c2ecf20Sopenharmony_ci		}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		kfree(dpr);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		return -ENOMEM;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return 0;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_civoid dcss_dpr_exit(struct dcss_dpr *dpr)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	int ch_no;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	/* stop DPR on all channels */
1888c2ecf20Sopenharmony_ci	for (ch_no = 0; ch_no < 3; ch_no++) {
1898c2ecf20Sopenharmony_ci		struct dcss_dpr_ch *ch = &dpr->ch[ch_no];
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		dcss_writel(0, ch->base_reg + DCSS_DPR_SYSTEM_CTRL0);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		if (ch->base_reg)
1948c2ecf20Sopenharmony_ci			iounmap(ch->base_reg);
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	kfree(dpr);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic u32 dcss_dpr_x_pix_wide_adjust(struct dcss_dpr_ch *ch, u32 pix_wide,
2018c2ecf20Sopenharmony_ci				      u32 pix_format)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	u8 pix_in_64byte_map[3][5] = {
2048c2ecf20Sopenharmony_ci		/* LIN, GPU_STD, GPU_SUP, VPU_YUV420, VPU_VP9 */
2058c2ecf20Sopenharmony_ci		{   64,       8,       8,          8,     16}, /* PIX_SIZE_8  */
2068c2ecf20Sopenharmony_ci		{   32,       8,       8,          8,      8}, /* PIX_SIZE_16 */
2078c2ecf20Sopenharmony_ci		{   16,       4,       4,          8,      8}, /* PIX_SIZE_32 */
2088c2ecf20Sopenharmony_ci	};
2098c2ecf20Sopenharmony_ci	u32 offset;
2108c2ecf20Sopenharmony_ci	u32 div_64byte_mod, pix_in_64byte;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	pix_in_64byte = pix_in_64byte_map[ch->pix_size][ch->tile];
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	div_64byte_mod = pix_wide % pix_in_64byte;
2158c2ecf20Sopenharmony_ci	offset = (div_64byte_mod == 0) ? 0 : (pix_in_64byte - div_64byte_mod);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return pix_wide + offset;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic u32 dcss_dpr_y_pix_high_adjust(struct dcss_dpr_ch *ch, u32 pix_high,
2218c2ecf20Sopenharmony_ci				      u32 pix_format)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	u8 num_rows_buf = ch->rtram_4line_en ? 4 : 8;
2248c2ecf20Sopenharmony_ci	u32 offset, pix_y_mod;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	pix_y_mod = pix_high % num_rows_buf;
2278c2ecf20Sopenharmony_ci	offset = pix_y_mod ? (num_rows_buf - pix_y_mod) : 0;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	return pix_high + offset;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_civoid dcss_dpr_set_res(struct dcss_dpr *dpr, int ch_num, u32 xres, u32 yres)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch = &dpr->ch[ch_num];
2358c2ecf20Sopenharmony_ci	u32 pix_format = ch->format.format;
2368c2ecf20Sopenharmony_ci	u32 gap = DCSS_DPR_FRAME_2P_BASE_ADDR - DCSS_DPR_FRAME_1P_BASE_ADDR;
2378c2ecf20Sopenharmony_ci	int plane, max_planes = 1;
2388c2ecf20Sopenharmony_ci	u32 pix_x_wide, pix_y_high;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (pix_format == DRM_FORMAT_NV12 ||
2418c2ecf20Sopenharmony_ci	    pix_format == DRM_FORMAT_NV21)
2428c2ecf20Sopenharmony_ci		max_planes = 2;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	for (plane = 0; plane < max_planes; plane++) {
2458c2ecf20Sopenharmony_ci		yres = plane == 1 ? yres >> 1 : yres;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		pix_x_wide = dcss_dpr_x_pix_wide_adjust(ch, xres, pix_format);
2488c2ecf20Sopenharmony_ci		pix_y_high = dcss_dpr_y_pix_high_adjust(ch, yres, pix_format);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, pix_x_wide,
2518c2ecf20Sopenharmony_ci			       DCSS_DPR_FRAME_1P_PIX_X_CTRL + plane * gap);
2528c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, pix_y_high,
2538c2ecf20Sopenharmony_ci			       DCSS_DPR_FRAME_1P_PIX_Y_CTRL + plane * gap);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, 2, DCSS_DPR_FRAME_1P_CTRL0 + plane * gap);
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_civoid dcss_dpr_addr_set(struct dcss_dpr *dpr, int ch_num, u32 luma_base_addr,
2608c2ecf20Sopenharmony_ci		       u32 chroma_base_addr, u16 pitch)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch = &dpr->ch[ch_num];
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	dcss_dpr_write(ch, luma_base_addr, DCSS_DPR_FRAME_1P_BASE_ADDR);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	dcss_dpr_write(ch, chroma_base_addr, DCSS_DPR_FRAME_2P_BASE_ADDR);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	ch->frame_ctrl &= ~PITCH_MASK;
2698c2ecf20Sopenharmony_ci	ch->frame_ctrl |= (((u32)pitch << PITCH_POS) & PITCH_MASK);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic void dcss_dpr_argb_comp_sel(struct dcss_dpr_ch *ch, int a_sel, int r_sel,
2738c2ecf20Sopenharmony_ci				   int g_sel, int b_sel)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	u32 sel;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	sel = ((a_sel << A_COMP_SEL_POS) & A_COMP_SEL_MASK) |
2788c2ecf20Sopenharmony_ci	      ((r_sel << R_COMP_SEL_POS) & R_COMP_SEL_MASK) |
2798c2ecf20Sopenharmony_ci	      ((g_sel << G_COMP_SEL_POS) & G_COMP_SEL_MASK) |
2808c2ecf20Sopenharmony_ci	      ((b_sel << B_COMP_SEL_POS) & B_COMP_SEL_MASK);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~(A_COMP_SEL_MASK | R_COMP_SEL_MASK |
2838c2ecf20Sopenharmony_ci			   G_COMP_SEL_MASK | B_COMP_SEL_MASK);
2848c2ecf20Sopenharmony_ci	ch->mode_ctrl |= sel;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic void dcss_dpr_pix_size_set(struct dcss_dpr_ch *ch,
2888c2ecf20Sopenharmony_ci				  const struct drm_format_info *format)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	u32 val;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	switch (format->format) {
2938c2ecf20Sopenharmony_ci	case DRM_FORMAT_NV12:
2948c2ecf20Sopenharmony_ci	case DRM_FORMAT_NV21:
2958c2ecf20Sopenharmony_ci		val = PIX_SIZE_8;
2968c2ecf20Sopenharmony_ci		break;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	case DRM_FORMAT_UYVY:
2998c2ecf20Sopenharmony_ci	case DRM_FORMAT_VYUY:
3008c2ecf20Sopenharmony_ci	case DRM_FORMAT_YUYV:
3018c2ecf20Sopenharmony_ci	case DRM_FORMAT_YVYU:
3028c2ecf20Sopenharmony_ci		val = PIX_SIZE_16;
3038c2ecf20Sopenharmony_ci		break;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	default:
3068c2ecf20Sopenharmony_ci		val = PIX_SIZE_32;
3078c2ecf20Sopenharmony_ci		break;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	ch->pix_size = val;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~PIX_SIZE_MASK;
3138c2ecf20Sopenharmony_ci	ch->mode_ctrl |= ((val << PIX_SIZE_POS) & PIX_SIZE_MASK);
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic void dcss_dpr_uv_swap(struct dcss_dpr_ch *ch, bool swap)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~PIX_UV_SWAP;
3198c2ecf20Sopenharmony_ci	ch->mode_ctrl |= (swap ? PIX_UV_SWAP : 0);
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic void dcss_dpr_y_uv_swap(struct dcss_dpr_ch *ch, bool swap)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~PIX_LUMA_UV_SWAP;
3258c2ecf20Sopenharmony_ci	ch->mode_ctrl |= (swap ? PIX_LUMA_UV_SWAP : 0);
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic void dcss_dpr_2plane_en(struct dcss_dpr_ch *ch, bool en)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~COMP_2PLANE_EN;
3318c2ecf20Sopenharmony_ci	ch->mode_ctrl |= (en ? COMP_2PLANE_EN : 0);
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic void dcss_dpr_yuv_en(struct dcss_dpr_ch *ch, bool en)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~YUV_EN;
3378c2ecf20Sopenharmony_ci	ch->mode_ctrl |= (en ? YUV_EN : 0);
3388c2ecf20Sopenharmony_ci}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_civoid dcss_dpr_enable(struct dcss_dpr *dpr, int ch_num, bool en)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch = &dpr->ch[ch_num];
3438c2ecf20Sopenharmony_ci	u32 sys_ctrl;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	sys_ctrl = (en ? REPEAT_EN | RUN_EN : 0);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (en) {
3488c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, ch->mode_ctrl, DCSS_DPR_MODE_CTRL0);
3498c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, ch->frame_ctrl, DCSS_DPR_FRAME_CTRL0);
3508c2ecf20Sopenharmony_ci		dcss_dpr_write(ch, ch->rtram_ctrl, DCSS_DPR_RTRAM_CTRL0);
3518c2ecf20Sopenharmony_ci	}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	if (ch->sys_ctrl != sys_ctrl)
3548c2ecf20Sopenharmony_ci		ch->sys_ctrl_chgd = true;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	ch->sys_ctrl = sys_ctrl;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cistruct rgb_comp_sel {
3608c2ecf20Sopenharmony_ci	u32 drm_format;
3618c2ecf20Sopenharmony_ci	int a_sel;
3628c2ecf20Sopenharmony_ci	int r_sel;
3638c2ecf20Sopenharmony_ci	int g_sel;
3648c2ecf20Sopenharmony_ci	int b_sel;
3658c2ecf20Sopenharmony_ci};
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic struct rgb_comp_sel comp_sel_map[] = {
3688c2ecf20Sopenharmony_ci	{DRM_FORMAT_ARGB8888, 3, 2, 1, 0},
3698c2ecf20Sopenharmony_ci	{DRM_FORMAT_XRGB8888, 3, 2, 1, 0},
3708c2ecf20Sopenharmony_ci	{DRM_FORMAT_ABGR8888, 3, 0, 1, 2},
3718c2ecf20Sopenharmony_ci	{DRM_FORMAT_XBGR8888, 3, 0, 1, 2},
3728c2ecf20Sopenharmony_ci	{DRM_FORMAT_RGBA8888, 0, 3, 2, 1},
3738c2ecf20Sopenharmony_ci	{DRM_FORMAT_RGBX8888, 0, 3, 2, 1},
3748c2ecf20Sopenharmony_ci	{DRM_FORMAT_BGRA8888, 0, 1, 2, 3},
3758c2ecf20Sopenharmony_ci	{DRM_FORMAT_BGRX8888, 0, 1, 2, 3},
3768c2ecf20Sopenharmony_ci};
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic int to_comp_sel(u32 pix_fmt, int *a_sel, int *r_sel, int *g_sel,
3798c2ecf20Sopenharmony_ci		       int *b_sel)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	int i;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(comp_sel_map); i++) {
3848c2ecf20Sopenharmony_ci		if (comp_sel_map[i].drm_format == pix_fmt) {
3858c2ecf20Sopenharmony_ci			*a_sel = comp_sel_map[i].a_sel;
3868c2ecf20Sopenharmony_ci			*r_sel = comp_sel_map[i].r_sel;
3878c2ecf20Sopenharmony_ci			*g_sel = comp_sel_map[i].g_sel;
3888c2ecf20Sopenharmony_ci			*b_sel = comp_sel_map[i].b_sel;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci			return 0;
3918c2ecf20Sopenharmony_ci		}
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return -1;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic void dcss_dpr_rtram_set(struct dcss_dpr_ch *ch, u32 pix_format)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	u32 val, mask;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	switch (pix_format) {
4028c2ecf20Sopenharmony_ci	case DRM_FORMAT_NV21:
4038c2ecf20Sopenharmony_ci	case DRM_FORMAT_NV12:
4048c2ecf20Sopenharmony_ci		ch->rtram_3buf_en = true;
4058c2ecf20Sopenharmony_ci		ch->rtram_4line_en = false;
4068c2ecf20Sopenharmony_ci		break;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	default:
4098c2ecf20Sopenharmony_ci		ch->rtram_3buf_en = true;
4108c2ecf20Sopenharmony_ci		ch->rtram_4line_en = true;
4118c2ecf20Sopenharmony_ci		break;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	val = (ch->rtram_4line_en ? RTR_4LINE_BUF_EN : 0);
4158c2ecf20Sopenharmony_ci	val |= (ch->rtram_3buf_en ? RTR_3BUF_EN : 0);
4168c2ecf20Sopenharmony_ci	mask = RTR_4LINE_BUF_EN | RTR_3BUF_EN;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~mask;
4198c2ecf20Sopenharmony_ci	ch->mode_ctrl |= (val & mask);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	val = (ch->rtram_4line_en ? 0 : NUM_ROWS_ACTIVE);
4228c2ecf20Sopenharmony_ci	val |= (3 << THRES_LOW_POS) & THRES_LOW_MASK;
4238c2ecf20Sopenharmony_ci	val |= (4 << THRES_HIGH_POS) & THRES_HIGH_MASK;
4248c2ecf20Sopenharmony_ci	mask = THRES_LOW_MASK | THRES_HIGH_MASK | NUM_ROWS_ACTIVE;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	ch->rtram_ctrl &= ~mask;
4278c2ecf20Sopenharmony_ci	ch->rtram_ctrl |= (val & mask);
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic void dcss_dpr_setup_components(struct dcss_dpr_ch *ch,
4318c2ecf20Sopenharmony_ci				      const struct drm_format_info *format)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	int a_sel, r_sel, g_sel, b_sel;
4348c2ecf20Sopenharmony_ci	bool uv_swap, y_uv_swap;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	switch (format->format) {
4378c2ecf20Sopenharmony_ci	case DRM_FORMAT_YVYU:
4388c2ecf20Sopenharmony_ci		uv_swap = true;
4398c2ecf20Sopenharmony_ci		y_uv_swap = true;
4408c2ecf20Sopenharmony_ci		break;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	case DRM_FORMAT_VYUY:
4438c2ecf20Sopenharmony_ci	case DRM_FORMAT_NV21:
4448c2ecf20Sopenharmony_ci		uv_swap = true;
4458c2ecf20Sopenharmony_ci		y_uv_swap = false;
4468c2ecf20Sopenharmony_ci		break;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	case DRM_FORMAT_YUYV:
4498c2ecf20Sopenharmony_ci		uv_swap = false;
4508c2ecf20Sopenharmony_ci		y_uv_swap = true;
4518c2ecf20Sopenharmony_ci		break;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	default:
4548c2ecf20Sopenharmony_ci		uv_swap = false;
4558c2ecf20Sopenharmony_ci		y_uv_swap = false;
4568c2ecf20Sopenharmony_ci		break;
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	dcss_dpr_uv_swap(ch, uv_swap);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	dcss_dpr_y_uv_swap(ch, y_uv_swap);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	if (!format->is_yuv) {
4648c2ecf20Sopenharmony_ci		if (!to_comp_sel(format->format, &a_sel, &r_sel,
4658c2ecf20Sopenharmony_ci				 &g_sel, &b_sel)) {
4668c2ecf20Sopenharmony_ci			dcss_dpr_argb_comp_sel(ch, a_sel, r_sel, g_sel, b_sel);
4678c2ecf20Sopenharmony_ci		} else {
4688c2ecf20Sopenharmony_ci			dcss_dpr_argb_comp_sel(ch, 3, 2, 1, 0);
4698c2ecf20Sopenharmony_ci		}
4708c2ecf20Sopenharmony_ci	} else {
4718c2ecf20Sopenharmony_ci		dcss_dpr_argb_comp_sel(ch, 0, 0, 0, 0);
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_cistatic void dcss_dpr_tile_set(struct dcss_dpr_ch *ch, uint64_t modifier)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	switch (ch->ch_num) {
4788c2ecf20Sopenharmony_ci	case 0:
4798c2ecf20Sopenharmony_ci		switch (modifier) {
4808c2ecf20Sopenharmony_ci		case DRM_FORMAT_MOD_LINEAR:
4818c2ecf20Sopenharmony_ci			ch->tile = TILE_LINEAR;
4828c2ecf20Sopenharmony_ci			break;
4838c2ecf20Sopenharmony_ci		case DRM_FORMAT_MOD_VIVANTE_TILED:
4848c2ecf20Sopenharmony_ci			ch->tile = TILE_GPU_STANDARD;
4858c2ecf20Sopenharmony_ci			break;
4868c2ecf20Sopenharmony_ci		case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
4878c2ecf20Sopenharmony_ci			ch->tile = TILE_GPU_SUPER;
4888c2ecf20Sopenharmony_ci			break;
4898c2ecf20Sopenharmony_ci		default:
4908c2ecf20Sopenharmony_ci			WARN_ON(1);
4918c2ecf20Sopenharmony_ci			break;
4928c2ecf20Sopenharmony_ci		}
4938c2ecf20Sopenharmony_ci		break;
4948c2ecf20Sopenharmony_ci	case 1:
4958c2ecf20Sopenharmony_ci	case 2:
4968c2ecf20Sopenharmony_ci		ch->tile = TILE_LINEAR;
4978c2ecf20Sopenharmony_ci		break;
4988c2ecf20Sopenharmony_ci	default:
4998c2ecf20Sopenharmony_ci		WARN_ON(1);
5008c2ecf20Sopenharmony_ci		return;
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	ch->mode_ctrl &= ~TILE_TYPE_MASK;
5048c2ecf20Sopenharmony_ci	ch->mode_ctrl |= ((ch->tile << TILE_TYPE_POS) & TILE_TYPE_MASK);
5058c2ecf20Sopenharmony_ci}
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_civoid dcss_dpr_format_set(struct dcss_dpr *dpr, int ch_num,
5088c2ecf20Sopenharmony_ci			 const struct drm_format_info *format, u64 modifier)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch = &dpr->ch[ch_num];
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	ch->format = *format;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	dcss_dpr_yuv_en(ch, format->is_yuv);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	dcss_dpr_pix_size_set(ch, format);
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	dcss_dpr_setup_components(ch, format);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	dcss_dpr_2plane_en(ch, format->num_planes == 2);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	dcss_dpr_rtram_set(ch, format->format);
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	dcss_dpr_tile_set(ch, modifier);
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci/* This function will be called from interrupt context. */
5288c2ecf20Sopenharmony_civoid dcss_dpr_write_sysctrl(struct dcss_dpr *dpr)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	int chnum;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	dcss_ctxld_assert_locked(dpr->ctxld);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	for (chnum = 0; chnum < 3; chnum++) {
5358c2ecf20Sopenharmony_ci		struct dcss_dpr_ch *ch = &dpr->ch[chnum];
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		if (ch->sys_ctrl_chgd) {
5388c2ecf20Sopenharmony_ci			dcss_ctxld_write_irqsafe(dpr->ctxld, dpr->ctx_id,
5398c2ecf20Sopenharmony_ci						 ch->sys_ctrl,
5408c2ecf20Sopenharmony_ci						 ch->base_ofs +
5418c2ecf20Sopenharmony_ci						 DCSS_DPR_SYSTEM_CTRL0);
5428c2ecf20Sopenharmony_ci			ch->sys_ctrl_chgd = false;
5438c2ecf20Sopenharmony_ci		}
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_civoid dcss_dpr_set_rotation(struct dcss_dpr *dpr, int ch_num, u32 rotation)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	struct dcss_dpr_ch *ch = &dpr->ch[ch_num];
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	ch->frame_ctrl &= ~(HFLIP_EN | VFLIP_EN | ROT_ENC_MASK);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_X ? HFLIP_EN : 0;
5548c2ecf20Sopenharmony_ci	ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_Y ? VFLIP_EN : 0;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	if (rotation & DRM_MODE_ROTATE_90)
5578c2ecf20Sopenharmony_ci		ch->frame_ctrl |= 1 << ROT_ENC_POS;
5588c2ecf20Sopenharmony_ci	else if (rotation & DRM_MODE_ROTATE_180)
5598c2ecf20Sopenharmony_ci		ch->frame_ctrl |= 2 << ROT_ENC_POS;
5608c2ecf20Sopenharmony_ci	else if (rotation & DRM_MODE_ROTATE_270)
5618c2ecf20Sopenharmony_ci		ch->frame_ctrl |= 3 << ROT_ENC_POS;
5628c2ecf20Sopenharmony_ci}
563