/* SPDX-License-Identifier: GPL-2.0-only */ /* * This file is created based on MT8186 Functional Specification * Chapter number: 6.9 */ #include <console/console.h> #include <edid.h> #include <soc/addressmap.h> #include <soc/ddp.h> static void disp_config_main_path_connection(void) { /* * Main path: * OVL0->RDMA0->COLOR0->CCORR0->AAL0->GAMMA->POSTMASK0->DITHER->DSI0 */ SET32_BITFIELDS(&mmsys_cfg->disp_ovl0_mout_en, DISP_OVL0_MOUT_EN, DISP_OVL0_MOUT_TO_RDMA0); SET32_BITFIELDS(&mmsys_cfg->disp_rdma0_sel_in, DISP_RDMA0_SEL_IN, DISP_RDMA0_FROM_OVL0); SET32_BITFIELDS(&mmsys_cfg->mmsys_ovl_con, DISP_MMSYS_OVL0_CON, DISP_OVL0_GO_BLEND); SET32_BITFIELDS(&mmsys_cfg->disp_rdma0_sout_sel, DISP_RDMA0_SOUT_SEL, DISP_RDMA0_SOUT_TO_COLOR0); SET32_BITFIELDS(&mmsys_cfg->disp_dither0_mout_en, DISP_DITHER0_MOUT_EN, DISP_DITHER0_MOUT_TO_DSI0); SET32_BITFIELDS(&mmsys_cfg->disp_dsi0_sel_in, DISP_DSI0_SEL_IN, DISP_DSI0_FROM_DITHER0); } static void disp_config_main_path_mutex(void) { write32(&disp_mutex->mutex[0].mod, MUTEX_MOD_MAIN_PATH); /* Clock source from DSI0 */ write32(&disp_mutex->mutex[0].ctl, MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 6)); write32(&disp_mutex->mutex[0].en, BIT(0)); } static void ovl_layer_smi_id_en(u32 idx) { SET32_BITFIELDS(&disp_ovl[idx]->datapath_con, SMI_ID_EN, SMI_ID_EN_VAL); } static void ccorr_config(u32 width, u32 height) { struct disp_ccorr_regs *const regs = disp_ccorr; write32(®s->size, width << 16 | height); /* Disable relay mode */ SET32_BITFIELDS(®s->cfg, PQ_CFG_RELAY_MODE, 0); SET32_BITFIELDS(®s->cfg, PQ_CFG_ENGINE_EN, PQ_ENGINE_EN); write32(®s->en, PQ_EN); } static void aal_config(u32 width, u32 height) { struct disp_aal_regs *const regs = disp_aal; write32(®s->size, width << 16 | height); write32(®s->output_size, width << 16 | height); /* Enable relay mode */ SET32_BITFIELDS(®s->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE); SET32_BITFIELDS(®s->cfg, PQ_CFG_ENGINE_EN, 0); write32(®s->en, PQ_EN); } static void gamma_config(u32 width, u32 height) { struct disp_gamma_regs *const regs = disp_gamma; write32(®s->size, width << 16 | height); /* Disable relay mode */ SET32_BITFIELDS(®s->cfg, PQ_CFG_RELAY_MODE, 0); write32(®s->en, PQ_EN); } static void postmask_config(u32 width, u32 height) { struct disp_postmask_regs *const regs = disp_postmask; write32(®s->size, width << 16 | height); /* Enable relay mode */ SET32_BITFIELDS(®s->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE); write32(®s->en, PQ_EN); } static void dither_config(u32 width, u32 height) { struct disp_dither_regs *const regs = disp_dither; write32(®s->size, width << 16 | height); /* Enable relay mode */ SET32_BITFIELDS(®s->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE); write32(®s->en, PQ_EN); } static void main_disp_path_setup(u32 width, u32 height, u32 vrefresh) { u32 pixel_clk = width * height * vrefresh; /* One ovl in main path */ ovl_set_roi(0, width, height, 0xff0000ff); ovl_layer_smi_id_en(0); rdma_config(width, height, pixel_clk, 5 * KiB); color_start(width, height); ccorr_config(width, height); aal_config(width, height); gamma_config(width, height); postmask_config(width, height); dither_config(width, height); disp_config_main_path_connection(); disp_config_main_path_mutex(); } static void disp_clock_on(void) { clrbits32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_DISP_ALL); clrbits32(&mmsys_cfg->mmsys_cg_con2, CG_CON2_DISP_ALL); } void mtk_ddp_init(void) { disp_clock_on(); /* Turn off M4U port */ write32((void *)(SMI_LARB0 + SMI_LARB_PORT_L0_OVL_RDMA0), 0); } void mtk_ddp_mode_set(const struct edid *edid, enum disp_path_sel path) { u32 fmt = OVL_INFMT_RGBA8888; u32 bpp = edid->framebuffer_bits_per_pixel / 8; u32 width = edid->mode.ha; u32 height = edid->mode.va; u32 vrefresh = edid->mode.refresh; printk(BIOS_INFO, "%s: display resolution: %ux%u@%u bpp %u\n", __func__, width, height, vrefresh, bpp); if (!vrefresh) { vrefresh = 60; printk(BIOS_INFO, "%s: invalid vrefresh; setting to %u\n", __func__, vrefresh); } main_disp_path_setup(width, height, vrefresh); rdma_start(); ovl_layer_config(fmt, bpp, width, height); }