162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2019 NXP. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/device.h> 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "dcss-dev.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define DCSS_DPR_SYSTEM_CTRL0 0x000 1262306a36Sopenharmony_ci#define RUN_EN BIT(0) 1362306a36Sopenharmony_ci#define SOFT_RESET BIT(1) 1462306a36Sopenharmony_ci#define REPEAT_EN BIT(2) 1562306a36Sopenharmony_ci#define SHADOW_LOAD_EN BIT(3) 1662306a36Sopenharmony_ci#define SW_SHADOW_LOAD_SEL BIT(4) 1762306a36Sopenharmony_ci#define BCMD2AXI_MSTR_ID_CTRL BIT(16) 1862306a36Sopenharmony_ci#define DCSS_DPR_IRQ_MASK 0x020 1962306a36Sopenharmony_ci#define DCSS_DPR_IRQ_MASK_STATUS 0x030 2062306a36Sopenharmony_ci#define DCSS_DPR_IRQ_NONMASK_STATUS 0x040 2162306a36Sopenharmony_ci#define IRQ_DPR_CTRL_DONE BIT(0) 2262306a36Sopenharmony_ci#define IRQ_DPR_RUN BIT(1) 2362306a36Sopenharmony_ci#define IRQ_DPR_SHADOW_LOADED BIT(2) 2462306a36Sopenharmony_ci#define IRQ_AXI_READ_ERR BIT(3) 2562306a36Sopenharmony_ci#define DPR2RTR_YRGB_FIFO_OVFL BIT(4) 2662306a36Sopenharmony_ci#define DPR2RTR_UV_FIFO_OVFL BIT(5) 2762306a36Sopenharmony_ci#define DPR2RTR_FIFO_LD_BUF_RDY_YRGB_ERR BIT(6) 2862306a36Sopenharmony_ci#define DPR2RTR_FIFO_LD_BUF_RDY_UV_ERR BIT(7) 2962306a36Sopenharmony_ci#define DCSS_DPR_MODE_CTRL0 0x050 3062306a36Sopenharmony_ci#define RTR_3BUF_EN BIT(0) 3162306a36Sopenharmony_ci#define RTR_4LINE_BUF_EN BIT(1) 3262306a36Sopenharmony_ci#define TILE_TYPE_POS 2 3362306a36Sopenharmony_ci#define TILE_TYPE_MASK GENMASK(4, 2) 3462306a36Sopenharmony_ci#define YUV_EN BIT(6) 3562306a36Sopenharmony_ci#define COMP_2PLANE_EN BIT(7) 3662306a36Sopenharmony_ci#define PIX_SIZE_POS 8 3762306a36Sopenharmony_ci#define PIX_SIZE_MASK GENMASK(9, 8) 3862306a36Sopenharmony_ci#define PIX_LUMA_UV_SWAP BIT(10) 3962306a36Sopenharmony_ci#define PIX_UV_SWAP BIT(11) 4062306a36Sopenharmony_ci#define B_COMP_SEL_POS 12 4162306a36Sopenharmony_ci#define B_COMP_SEL_MASK GENMASK(13, 12) 4262306a36Sopenharmony_ci#define G_COMP_SEL_POS 14 4362306a36Sopenharmony_ci#define G_COMP_SEL_MASK GENMASK(15, 14) 4462306a36Sopenharmony_ci#define R_COMP_SEL_POS 16 4562306a36Sopenharmony_ci#define R_COMP_SEL_MASK GENMASK(17, 16) 4662306a36Sopenharmony_ci#define A_COMP_SEL_POS 18 4762306a36Sopenharmony_ci#define A_COMP_SEL_MASK GENMASK(19, 18) 4862306a36Sopenharmony_ci#define DCSS_DPR_FRAME_CTRL0 0x070 4962306a36Sopenharmony_ci#define HFLIP_EN BIT(0) 5062306a36Sopenharmony_ci#define VFLIP_EN BIT(1) 5162306a36Sopenharmony_ci#define ROT_ENC_POS 2 5262306a36Sopenharmony_ci#define ROT_ENC_MASK GENMASK(3, 2) 5362306a36Sopenharmony_ci#define ROT_FLIP_ORDER_EN BIT(4) 5462306a36Sopenharmony_ci#define PITCH_POS 16 5562306a36Sopenharmony_ci#define PITCH_MASK GENMASK(31, 16) 5662306a36Sopenharmony_ci#define DCSS_DPR_FRAME_1P_CTRL0 0x090 5762306a36Sopenharmony_ci#define DCSS_DPR_FRAME_1P_PIX_X_CTRL 0x0A0 5862306a36Sopenharmony_ci#define DCSS_DPR_FRAME_1P_PIX_Y_CTRL 0x0B0 5962306a36Sopenharmony_ci#define DCSS_DPR_FRAME_1P_BASE_ADDR 0x0C0 6062306a36Sopenharmony_ci#define DCSS_DPR_FRAME_2P_CTRL0 0x0E0 6162306a36Sopenharmony_ci#define DCSS_DPR_FRAME_2P_PIX_X_CTRL 0x0F0 6262306a36Sopenharmony_ci#define DCSS_DPR_FRAME_2P_PIX_Y_CTRL 0x100 6362306a36Sopenharmony_ci#define DCSS_DPR_FRAME_2P_BASE_ADDR 0x110 6462306a36Sopenharmony_ci#define DCSS_DPR_STATUS_CTRL0 0x130 6562306a36Sopenharmony_ci#define STATUS_MUX_SEL_MASK GENMASK(2, 0) 6662306a36Sopenharmony_ci#define STATUS_SRC_SEL_POS 16 6762306a36Sopenharmony_ci#define STATUS_SRC_SEL_MASK GENMASK(18, 16) 6862306a36Sopenharmony_ci#define DCSS_DPR_STATUS_CTRL1 0x140 6962306a36Sopenharmony_ci#define DCSS_DPR_RTRAM_CTRL0 0x200 7062306a36Sopenharmony_ci#define NUM_ROWS_ACTIVE BIT(0) 7162306a36Sopenharmony_ci#define THRES_HIGH_POS 1 7262306a36Sopenharmony_ci#define THRES_HIGH_MASK GENMASK(3, 1) 7362306a36Sopenharmony_ci#define THRES_LOW_POS 4 7462306a36Sopenharmony_ci#define THRES_LOW_MASK GENMASK(6, 4) 7562306a36Sopenharmony_ci#define ABORT_SEL BIT(7) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cienum dcss_tile_type { 7862306a36Sopenharmony_ci TILE_LINEAR = 0, 7962306a36Sopenharmony_ci TILE_GPU_STANDARD, 8062306a36Sopenharmony_ci TILE_GPU_SUPER, 8162306a36Sopenharmony_ci TILE_VPU_YUV420, 8262306a36Sopenharmony_ci TILE_VPU_VP9, 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cienum dcss_pix_size { 8662306a36Sopenharmony_ci PIX_SIZE_8, 8762306a36Sopenharmony_ci PIX_SIZE_16, 8862306a36Sopenharmony_ci PIX_SIZE_32, 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct dcss_dpr_ch { 9262306a36Sopenharmony_ci struct dcss_dpr *dpr; 9362306a36Sopenharmony_ci void __iomem *base_reg; 9462306a36Sopenharmony_ci u32 base_ofs; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci struct drm_format_info format; 9762306a36Sopenharmony_ci enum dcss_pix_size pix_size; 9862306a36Sopenharmony_ci enum dcss_tile_type tile; 9962306a36Sopenharmony_ci bool rtram_4line_en; 10062306a36Sopenharmony_ci bool rtram_3buf_en; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci u32 frame_ctrl; 10362306a36Sopenharmony_ci u32 mode_ctrl; 10462306a36Sopenharmony_ci u32 sys_ctrl; 10562306a36Sopenharmony_ci u32 rtram_ctrl; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci bool sys_ctrl_chgd; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci int ch_num; 11062306a36Sopenharmony_ci int irq; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistruct dcss_dpr { 11462306a36Sopenharmony_ci struct device *dev; 11562306a36Sopenharmony_ci struct dcss_ctxld *ctxld; 11662306a36Sopenharmony_ci u32 ctx_id; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci struct dcss_dpr_ch ch[3]; 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic void dcss_dpr_write(struct dcss_dpr_ch *ch, u32 val, u32 ofs) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct dcss_dpr *dpr = ch->dpr; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci dcss_ctxld_write(dpr->ctxld, dpr->ctx_id, val, ch->base_ofs + ofs); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic int dcss_dpr_ch_init_all(struct dcss_dpr *dpr, unsigned long dpr_base) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci struct dcss_dpr_ch *ch; 13162306a36Sopenharmony_ci int i; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 13462306a36Sopenharmony_ci ch = &dpr->ch[i]; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ch->base_ofs = dpr_base + i * 0x1000; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci ch->base_reg = ioremap(ch->base_ofs, SZ_4K); 13962306a36Sopenharmony_ci if (!ch->base_reg) { 14062306a36Sopenharmony_ci dev_err(dpr->dev, "dpr: unable to remap ch %d base\n", 14162306a36Sopenharmony_ci i); 14262306a36Sopenharmony_ci return -ENOMEM; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci ch->dpr = dpr; 14662306a36Sopenharmony_ci ch->ch_num = i; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci dcss_writel(0xff, ch->base_reg + DCSS_DPR_IRQ_MASK); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return 0; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciint dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct dcss_dpr *dpr; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci dpr = kzalloc(sizeof(*dpr), GFP_KERNEL); 15962306a36Sopenharmony_ci if (!dpr) 16062306a36Sopenharmony_ci return -ENOMEM; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci dcss->dpr = dpr; 16362306a36Sopenharmony_ci dpr->dev = dcss->dev; 16462306a36Sopenharmony_ci dpr->ctxld = dcss->ctxld; 16562306a36Sopenharmony_ci dpr->ctx_id = CTX_SB_HP; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (dcss_dpr_ch_init_all(dpr, dpr_base)) { 16862306a36Sopenharmony_ci int i; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 17162306a36Sopenharmony_ci if (dpr->ch[i].base_reg) 17262306a36Sopenharmony_ci iounmap(dpr->ch[i].base_reg); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci kfree(dpr); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci return -ENOMEM; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return 0; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_civoid dcss_dpr_exit(struct dcss_dpr *dpr) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci int ch_no; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* stop DPR on all channels */ 18862306a36Sopenharmony_ci for (ch_no = 0; ch_no < 3; ch_no++) { 18962306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_no]; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci dcss_writel(0, ch->base_reg + DCSS_DPR_SYSTEM_CTRL0); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (ch->base_reg) 19462306a36Sopenharmony_ci iounmap(ch->base_reg); 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci kfree(dpr); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic u32 dcss_dpr_x_pix_wide_adjust(struct dcss_dpr_ch *ch, u32 pix_wide, 20162306a36Sopenharmony_ci u32 pix_format) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci u8 pix_in_64byte_map[3][5] = { 20462306a36Sopenharmony_ci /* LIN, GPU_STD, GPU_SUP, VPU_YUV420, VPU_VP9 */ 20562306a36Sopenharmony_ci { 64, 8, 8, 8, 16}, /* PIX_SIZE_8 */ 20662306a36Sopenharmony_ci { 32, 8, 8, 8, 8}, /* PIX_SIZE_16 */ 20762306a36Sopenharmony_ci { 16, 4, 4, 8, 8}, /* PIX_SIZE_32 */ 20862306a36Sopenharmony_ci }; 20962306a36Sopenharmony_ci u32 offset; 21062306a36Sopenharmony_ci u32 div_64byte_mod, pix_in_64byte; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci pix_in_64byte = pix_in_64byte_map[ch->pix_size][ch->tile]; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci div_64byte_mod = pix_wide % pix_in_64byte; 21562306a36Sopenharmony_ci offset = (div_64byte_mod == 0) ? 0 : (pix_in_64byte - div_64byte_mod); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci return pix_wide + offset; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic u32 dcss_dpr_y_pix_high_adjust(struct dcss_dpr_ch *ch, u32 pix_high, 22162306a36Sopenharmony_ci u32 pix_format) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci u8 num_rows_buf = ch->rtram_4line_en ? 4 : 8; 22462306a36Sopenharmony_ci u32 offset, pix_y_mod; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci pix_y_mod = pix_high % num_rows_buf; 22762306a36Sopenharmony_ci offset = pix_y_mod ? (num_rows_buf - pix_y_mod) : 0; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return pix_high + offset; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_civoid dcss_dpr_set_res(struct dcss_dpr *dpr, int ch_num, u32 xres, u32 yres) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; 23562306a36Sopenharmony_ci u32 pix_format = ch->format.format; 23662306a36Sopenharmony_ci u32 gap = DCSS_DPR_FRAME_2P_BASE_ADDR - DCSS_DPR_FRAME_1P_BASE_ADDR; 23762306a36Sopenharmony_ci int plane, max_planes = 1; 23862306a36Sopenharmony_ci u32 pix_x_wide, pix_y_high; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (pix_format == DRM_FORMAT_NV12 || 24162306a36Sopenharmony_ci pix_format == DRM_FORMAT_NV21) 24262306a36Sopenharmony_ci max_planes = 2; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci for (plane = 0; plane < max_planes; plane++) { 24562306a36Sopenharmony_ci yres = plane == 1 ? yres >> 1 : yres; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci pix_x_wide = dcss_dpr_x_pix_wide_adjust(ch, xres, pix_format); 24862306a36Sopenharmony_ci pix_y_high = dcss_dpr_y_pix_high_adjust(ch, yres, pix_format); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci dcss_dpr_write(ch, pix_x_wide, 25162306a36Sopenharmony_ci DCSS_DPR_FRAME_1P_PIX_X_CTRL + plane * gap); 25262306a36Sopenharmony_ci dcss_dpr_write(ch, pix_y_high, 25362306a36Sopenharmony_ci DCSS_DPR_FRAME_1P_PIX_Y_CTRL + plane * gap); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci dcss_dpr_write(ch, 2, DCSS_DPR_FRAME_1P_CTRL0 + plane * gap); 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_civoid dcss_dpr_addr_set(struct dcss_dpr *dpr, int ch_num, u32 luma_base_addr, 26062306a36Sopenharmony_ci u32 chroma_base_addr, u16 pitch) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci dcss_dpr_write(ch, luma_base_addr, DCSS_DPR_FRAME_1P_BASE_ADDR); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci dcss_dpr_write(ch, chroma_base_addr, DCSS_DPR_FRAME_2P_BASE_ADDR); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci ch->frame_ctrl &= ~PITCH_MASK; 26962306a36Sopenharmony_ci ch->frame_ctrl |= (((u32)pitch << PITCH_POS) & PITCH_MASK); 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic void dcss_dpr_argb_comp_sel(struct dcss_dpr_ch *ch, int a_sel, int r_sel, 27362306a36Sopenharmony_ci int g_sel, int b_sel) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci u32 sel; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci sel = ((a_sel << A_COMP_SEL_POS) & A_COMP_SEL_MASK) | 27862306a36Sopenharmony_ci ((r_sel << R_COMP_SEL_POS) & R_COMP_SEL_MASK) | 27962306a36Sopenharmony_ci ((g_sel << G_COMP_SEL_POS) & G_COMP_SEL_MASK) | 28062306a36Sopenharmony_ci ((b_sel << B_COMP_SEL_POS) & B_COMP_SEL_MASK); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci ch->mode_ctrl &= ~(A_COMP_SEL_MASK | R_COMP_SEL_MASK | 28362306a36Sopenharmony_ci G_COMP_SEL_MASK | B_COMP_SEL_MASK); 28462306a36Sopenharmony_ci ch->mode_ctrl |= sel; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic void dcss_dpr_pix_size_set(struct dcss_dpr_ch *ch, 28862306a36Sopenharmony_ci const struct drm_format_info *format) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci u32 val; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci switch (format->format) { 29362306a36Sopenharmony_ci case DRM_FORMAT_NV12: 29462306a36Sopenharmony_ci case DRM_FORMAT_NV21: 29562306a36Sopenharmony_ci val = PIX_SIZE_8; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci case DRM_FORMAT_UYVY: 29962306a36Sopenharmony_ci case DRM_FORMAT_VYUY: 30062306a36Sopenharmony_ci case DRM_FORMAT_YUYV: 30162306a36Sopenharmony_ci case DRM_FORMAT_YVYU: 30262306a36Sopenharmony_ci val = PIX_SIZE_16; 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci default: 30662306a36Sopenharmony_ci val = PIX_SIZE_32; 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci ch->pix_size = val; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ch->mode_ctrl &= ~PIX_SIZE_MASK; 31362306a36Sopenharmony_ci ch->mode_ctrl |= ((val << PIX_SIZE_POS) & PIX_SIZE_MASK); 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic void dcss_dpr_uv_swap(struct dcss_dpr_ch *ch, bool swap) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci ch->mode_ctrl &= ~PIX_UV_SWAP; 31962306a36Sopenharmony_ci ch->mode_ctrl |= (swap ? PIX_UV_SWAP : 0); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void dcss_dpr_y_uv_swap(struct dcss_dpr_ch *ch, bool swap) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci ch->mode_ctrl &= ~PIX_LUMA_UV_SWAP; 32562306a36Sopenharmony_ci ch->mode_ctrl |= (swap ? PIX_LUMA_UV_SWAP : 0); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic void dcss_dpr_2plane_en(struct dcss_dpr_ch *ch, bool en) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci ch->mode_ctrl &= ~COMP_2PLANE_EN; 33162306a36Sopenharmony_ci ch->mode_ctrl |= (en ? COMP_2PLANE_EN : 0); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void dcss_dpr_yuv_en(struct dcss_dpr_ch *ch, bool en) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci ch->mode_ctrl &= ~YUV_EN; 33762306a36Sopenharmony_ci ch->mode_ctrl |= (en ? YUV_EN : 0); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_civoid dcss_dpr_enable(struct dcss_dpr *dpr, int ch_num, bool en) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; 34362306a36Sopenharmony_ci u32 sys_ctrl; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci sys_ctrl = (en ? REPEAT_EN | RUN_EN : 0); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (en) { 34862306a36Sopenharmony_ci dcss_dpr_write(ch, ch->mode_ctrl, DCSS_DPR_MODE_CTRL0); 34962306a36Sopenharmony_ci dcss_dpr_write(ch, ch->frame_ctrl, DCSS_DPR_FRAME_CTRL0); 35062306a36Sopenharmony_ci dcss_dpr_write(ch, ch->rtram_ctrl, DCSS_DPR_RTRAM_CTRL0); 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (ch->sys_ctrl != sys_ctrl) 35462306a36Sopenharmony_ci ch->sys_ctrl_chgd = true; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci ch->sys_ctrl = sys_ctrl; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistruct rgb_comp_sel { 36062306a36Sopenharmony_ci u32 drm_format; 36162306a36Sopenharmony_ci int a_sel; 36262306a36Sopenharmony_ci int r_sel; 36362306a36Sopenharmony_ci int g_sel; 36462306a36Sopenharmony_ci int b_sel; 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic struct rgb_comp_sel comp_sel_map[] = { 36862306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 3, 2, 1, 0}, 36962306a36Sopenharmony_ci {DRM_FORMAT_XRGB8888, 3, 2, 1, 0}, 37062306a36Sopenharmony_ci {DRM_FORMAT_ABGR8888, 3, 0, 1, 2}, 37162306a36Sopenharmony_ci {DRM_FORMAT_XBGR8888, 3, 0, 1, 2}, 37262306a36Sopenharmony_ci {DRM_FORMAT_RGBA8888, 0, 3, 2, 1}, 37362306a36Sopenharmony_ci {DRM_FORMAT_RGBX8888, 0, 3, 2, 1}, 37462306a36Sopenharmony_ci {DRM_FORMAT_BGRA8888, 0, 1, 2, 3}, 37562306a36Sopenharmony_ci {DRM_FORMAT_BGRX8888, 0, 1, 2, 3}, 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic int to_comp_sel(u32 pix_fmt, int *a_sel, int *r_sel, int *g_sel, 37962306a36Sopenharmony_ci int *b_sel) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci int i; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(comp_sel_map); i++) { 38462306a36Sopenharmony_ci if (comp_sel_map[i].drm_format == pix_fmt) { 38562306a36Sopenharmony_ci *a_sel = comp_sel_map[i].a_sel; 38662306a36Sopenharmony_ci *r_sel = comp_sel_map[i].r_sel; 38762306a36Sopenharmony_ci *g_sel = comp_sel_map[i].g_sel; 38862306a36Sopenharmony_ci *b_sel = comp_sel_map[i].b_sel; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return -1; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic void dcss_dpr_rtram_set(struct dcss_dpr_ch *ch, u32 pix_format) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci u32 val, mask; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci switch (pix_format) { 40262306a36Sopenharmony_ci case DRM_FORMAT_NV21: 40362306a36Sopenharmony_ci case DRM_FORMAT_NV12: 40462306a36Sopenharmony_ci ch->rtram_3buf_en = true; 40562306a36Sopenharmony_ci ch->rtram_4line_en = false; 40662306a36Sopenharmony_ci break; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci default: 40962306a36Sopenharmony_ci ch->rtram_3buf_en = true; 41062306a36Sopenharmony_ci ch->rtram_4line_en = true; 41162306a36Sopenharmony_ci break; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci val = (ch->rtram_4line_en ? RTR_4LINE_BUF_EN : 0); 41562306a36Sopenharmony_ci val |= (ch->rtram_3buf_en ? RTR_3BUF_EN : 0); 41662306a36Sopenharmony_ci mask = RTR_4LINE_BUF_EN | RTR_3BUF_EN; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci ch->mode_ctrl &= ~mask; 41962306a36Sopenharmony_ci ch->mode_ctrl |= (val & mask); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci val = (ch->rtram_4line_en ? 0 : NUM_ROWS_ACTIVE); 42262306a36Sopenharmony_ci val |= (3 << THRES_LOW_POS) & THRES_LOW_MASK; 42362306a36Sopenharmony_ci val |= (4 << THRES_HIGH_POS) & THRES_HIGH_MASK; 42462306a36Sopenharmony_ci mask = THRES_LOW_MASK | THRES_HIGH_MASK | NUM_ROWS_ACTIVE; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci ch->rtram_ctrl &= ~mask; 42762306a36Sopenharmony_ci ch->rtram_ctrl |= (val & mask); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic void dcss_dpr_setup_components(struct dcss_dpr_ch *ch, 43162306a36Sopenharmony_ci const struct drm_format_info *format) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci int a_sel, r_sel, g_sel, b_sel; 43462306a36Sopenharmony_ci bool uv_swap, y_uv_swap; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci switch (format->format) { 43762306a36Sopenharmony_ci case DRM_FORMAT_YVYU: 43862306a36Sopenharmony_ci uv_swap = true; 43962306a36Sopenharmony_ci y_uv_swap = true; 44062306a36Sopenharmony_ci break; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci case DRM_FORMAT_VYUY: 44362306a36Sopenharmony_ci case DRM_FORMAT_NV21: 44462306a36Sopenharmony_ci uv_swap = true; 44562306a36Sopenharmony_ci y_uv_swap = false; 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci case DRM_FORMAT_YUYV: 44962306a36Sopenharmony_ci uv_swap = false; 45062306a36Sopenharmony_ci y_uv_swap = true; 45162306a36Sopenharmony_ci break; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci default: 45462306a36Sopenharmony_ci uv_swap = false; 45562306a36Sopenharmony_ci y_uv_swap = false; 45662306a36Sopenharmony_ci break; 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci dcss_dpr_uv_swap(ch, uv_swap); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci dcss_dpr_y_uv_swap(ch, y_uv_swap); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (!format->is_yuv) { 46462306a36Sopenharmony_ci if (!to_comp_sel(format->format, &a_sel, &r_sel, 46562306a36Sopenharmony_ci &g_sel, &b_sel)) { 46662306a36Sopenharmony_ci dcss_dpr_argb_comp_sel(ch, a_sel, r_sel, g_sel, b_sel); 46762306a36Sopenharmony_ci } else { 46862306a36Sopenharmony_ci dcss_dpr_argb_comp_sel(ch, 3, 2, 1, 0); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci } else { 47162306a36Sopenharmony_ci dcss_dpr_argb_comp_sel(ch, 0, 0, 0, 0); 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic void dcss_dpr_tile_set(struct dcss_dpr_ch *ch, uint64_t modifier) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci switch (ch->ch_num) { 47862306a36Sopenharmony_ci case 0: 47962306a36Sopenharmony_ci switch (modifier) { 48062306a36Sopenharmony_ci case DRM_FORMAT_MOD_LINEAR: 48162306a36Sopenharmony_ci ch->tile = TILE_LINEAR; 48262306a36Sopenharmony_ci break; 48362306a36Sopenharmony_ci case DRM_FORMAT_MOD_VIVANTE_TILED: 48462306a36Sopenharmony_ci ch->tile = TILE_GPU_STANDARD; 48562306a36Sopenharmony_ci break; 48662306a36Sopenharmony_ci case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: 48762306a36Sopenharmony_ci ch->tile = TILE_GPU_SUPER; 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci default: 49062306a36Sopenharmony_ci WARN_ON(1); 49162306a36Sopenharmony_ci break; 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci break; 49462306a36Sopenharmony_ci case 1: 49562306a36Sopenharmony_ci case 2: 49662306a36Sopenharmony_ci ch->tile = TILE_LINEAR; 49762306a36Sopenharmony_ci break; 49862306a36Sopenharmony_ci default: 49962306a36Sopenharmony_ci WARN_ON(1); 50062306a36Sopenharmony_ci return; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci ch->mode_ctrl &= ~TILE_TYPE_MASK; 50462306a36Sopenharmony_ci ch->mode_ctrl |= ((ch->tile << TILE_TYPE_POS) & TILE_TYPE_MASK); 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_civoid dcss_dpr_format_set(struct dcss_dpr *dpr, int ch_num, 50862306a36Sopenharmony_ci const struct drm_format_info *format, u64 modifier) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ch->format = *format; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci dcss_dpr_yuv_en(ch, format->is_yuv); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci dcss_dpr_pix_size_set(ch, format); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci dcss_dpr_setup_components(ch, format); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci dcss_dpr_2plane_en(ch, format->num_planes == 2); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci dcss_dpr_rtram_set(ch, format->format); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci dcss_dpr_tile_set(ch, modifier); 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci/* This function will be called from interrupt context. */ 52862306a36Sopenharmony_civoid dcss_dpr_write_sysctrl(struct dcss_dpr *dpr) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci int chnum; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci dcss_ctxld_assert_locked(dpr->ctxld); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci for (chnum = 0; chnum < 3; chnum++) { 53562306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[chnum]; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (ch->sys_ctrl_chgd) { 53862306a36Sopenharmony_ci dcss_ctxld_write_irqsafe(dpr->ctxld, dpr->ctx_id, 53962306a36Sopenharmony_ci ch->sys_ctrl, 54062306a36Sopenharmony_ci ch->base_ofs + 54162306a36Sopenharmony_ci DCSS_DPR_SYSTEM_CTRL0); 54262306a36Sopenharmony_ci ch->sys_ctrl_chgd = false; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_civoid dcss_dpr_set_rotation(struct dcss_dpr *dpr, int ch_num, u32 rotation) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci ch->frame_ctrl &= ~(HFLIP_EN | VFLIP_EN | ROT_ENC_MASK); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_X ? HFLIP_EN : 0; 55462306a36Sopenharmony_ci ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_Y ? VFLIP_EN : 0; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (rotation & DRM_MODE_ROTATE_90) 55762306a36Sopenharmony_ci ch->frame_ctrl |= 1 << ROT_ENC_POS; 55862306a36Sopenharmony_ci else if (rotation & DRM_MODE_ROTATE_180) 55962306a36Sopenharmony_ci ch->frame_ctrl |= 2 << ROT_ENC_POS; 56062306a36Sopenharmony_ci else if (rotation & DRM_MODE_ROTATE_270) 56162306a36Sopenharmony_ci ch->frame_ctrl |= 3 << ROT_ENC_POS; 56262306a36Sopenharmony_ci} 563