soc/mediatek/mt8196: Add DDP driver

Add DDP (display data pipe) driver that supports main path to eDP panel.

TEST=build pass and firmware display ok
BUG=b:343351631
Signed-off-by: Nancy Lin <nancy.lin@mediatek.corp-partner.google.com>
Change-Id: I006911e83d940c1eec7135a6a0c36fbfa2aad466
Reviewed-on: https://review.coreboot.org/c/coreboot/+/85950
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-by: Yidi Lin <yidilin@google.com>
This commit is contained in:
Nancy Lin 2024-12-10 15:50:38 +08:00 committed by Yidi Lin
commit fb2655d06a
5 changed files with 802 additions and 0 deletions

View file

@ -51,6 +51,8 @@ romstage-y += thermal.c
romstage-y += thermal_sram.c
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c
ramstage-y += ddp.c
ramstage-y += ../common/display.c
ramstage-y += ../common/dpm_v2.c
ramstage-y += ../common/dp/dptx_common.c ../common/dp/dptx_hal_common.c
ramstage-y += dptx.c dptx_hal.c dp_intf.c
@ -66,6 +68,7 @@ ramstage-$(CONFIG_COMMONLIB_STORAGE_MMC) += msdc.c
ramstage-y += ../common/mt6363.c mt6363.c
ramstage-y += ../common/mt6363_sdmadc.c
ramstage-y += ../common/mt6373.c mt6373.c
ramstage-y += mtcmos.c
ramstage-y += ../common/mtk_fsp.c
ramstage-y += soc.c
ramstage-y += ../common/spm.c spm.c

View file

@ -0,0 +1,312 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <console/console.h>
#include <device/mmio.h>
#include <edid.h>
#include <soc/addressmap.h>
#include <soc/ddp.h>
#define SIZE(w, h) ((u32)(h) << 16 | (w))
static void blender_config(struct blender *reg, u16 width, u16 height,
enum mtk_disp_blender_layer type)
{
setbits32(&reg->shadow_ctl, BIT(2));
switch (type) {
case FIRST_BLENDER:
clrsetbits32(&reg->datapath_con, BIT(4) | BIT(5), BIT(5));
break;
case LAST_BLENDER:
clrsetbits32(&reg->datapath_con, BIT(0) | BIT(4) | BIT(5), BIT(0) | BIT(4));
break;
case SINGLE_BLENDER:
clrsetbits32(&reg->datapath_con, BIT(4) | BIT(5), BIT(4));
break;
case OTHER_BLENDER:
clrsetbits32(&reg->datapath_con, BIT(0) | BIT(4) | BIT(5), BIT(0) | BIT(5));
break;
default:
printk(BIOS_ERR, "%s: unknown blender type %d\n", __func__, type);
break;
}
write32(&reg->roi_size, SIZE(width, height));
write32(&reg->bld_l_size, SIZE(width, height));
write32(&reg->bg_clr, 0xFF000000);
}
static void blender_start(struct blender *reg)
{
setbits32(&reg->bld_en, BIT(0));
}
static void outproc_config(struct outproc *reg, u16 width, u16 height)
{
setbits32(&reg->shadow_ctl, BIT(2));
setbits32(&reg->datapath_con, BIT(26));
write32(&reg->roi_size, SIZE(width, height));
}
static void outproc_start(struct outproc *reg)
{
setbits32(&reg->outproc_en, BIT(0));
}
static void mdp_rsz_config(struct disp_mdp_rsz_regs *reg, u16 width, u16 height)
{
write32(&reg->input_size, SIZE(width, height));
write32(&reg->output_size, SIZE(width, height));
}
static void mdp_rsz_start(struct disp_mdp_rsz_regs *reg)
{
clrbits32(&reg->en, BIT(0));
}
static void postmask_config(struct disp_postmask_regs *reg, u16 width, u16 height)
{
write32(&reg->size, SIZE(width, height));
setbits32(&reg->cfg, BIT(0));
}
static void postmask_start(struct disp_postmask_regs *reg)
{
setbits32(&reg->en, BIT(0));
}
static void tdshp_config(struct disp_tdshp_regs *reg, u16 width, u16 height)
{
write32(&reg->input_size, SIZE(width, height));
write32(&reg->output_size, SIZE(width, height));
write32(&reg->output_offset, 0x0);
write32(&reg->cfg, 0x1);
setbits32(&reg->tdshp_00, BIT(31));
}
static void tdshp_start(struct disp_tdshp_regs *reg)
{
setbits32(&reg->ctrl, BIT(0));
}
static void ccorr_config(struct disp_ccorr_regs *reg, u16 width, u16 height)
{
write32(&reg->size, SIZE(width, height));
setbits32(&reg->cfg, BIT(1));
}
static void ccorr_start(struct disp_ccorr_regs *reg)
{
setbits32(&reg->en, BIT(0));
}
static void gamma_config(struct disp_gamma_regs *reg, u16 width, u16 height)
{
write32(&reg->size, SIZE(width, height));
}
static void gamma_start(struct disp_gamma_regs *reg)
{
setbits32(&reg->en, BIT(0));
}
static void dither_config(struct disp_dither_regs *reg, u16 width, u16 height)
{
write32(&reg->size, SIZE(width, height));
setbits32(&reg->cfg, BIT(0));
}
static void dither_start(struct disp_dither_regs *reg)
{
setbits32(&reg->en, BIT(0));
}
static void disp_config_main_path_connection(enum disp_path_sel path)
{
/* ovlsys */
setbits32(&ovlsys_cfg->bypass_mux_shadow, BIT(0));
write32(&ovlsys_cfg->cb_con, 0xFF << 16);
setbits32(&ovlsys_cfg->rsz_in_cb2, BIT(1));
setbits32(&ovlsys_cfg->exdma_out_cb3, BIT(2));
setbits32(&ovlsys_cfg->blender_out_cb4, BIT(0));
setbits32(&ovlsys_cfg->outproc_out_cb0, BIT(0));
/* dispsys */
write32(&mmsys_cfg->bypass_mux_shadow, 0xFF << 16 | BIT(0));
setbits32(&mmsys_cfg->pq_in_cb0, BIT(0));
setbits32(&mmsys_cfg->disp_mdp_rsz0_mout, BIT(0));
write32(&mmsys_cfg->disp_tdshp0_sout, 0x2);
write32(&mmsys_cfg->disp_ccorr0_sel, 0x2);
write32(&mmsys_cfg->disp_ccorr0_sout, 0x1);
write32(&mmsys_cfg->disp_ccorr1_sel, 0x1);
write32(&mmsys_cfg->disp_ccorr1_sout, 0x1);
write32(&mmsys_cfg->disp_gamma0_sel, 0x1);
write32(&mmsys_cfg->disp_postmask_sout, 0x0);
setbits32(&mmsys_cfg->pq_out_cb0, BIT(1));
setbits32(&mmsys_cfg->panel_comp_out_cb1, BIT(1));
/* dispsys1 */
write32(&mmsys1_cfg->bypass_mux_shadow, 0xFF << 16 | BIT(0));
setbits32(&mmsys1_cfg->splitter_in_cb1, BIT(5));
setbits32(&mmsys1_cfg->splitter_out_cb9, BIT(10));
setbits32(&mmsys1_cfg->comp_out_cb6, BIT(0));
if (path == DISP_PATH_EDP)
setbits32(&mmsys1_cfg->merge_out_cb0, BIT(9));
else
setbits32(&mmsys1_cfg->merge_out_cb0, BIT(0));
}
static void async_config(u16 width, u16 height)
{
write32(&ovlsys_cfg->relay5_size, SIZE(width, height));
write32(&mmsys_cfg->dl_in_relay0, BIT(30) | SIZE(width, height));
write32(&mmsys_cfg->dl_out_relay1, BIT(30) | SIZE(width, height));
write32(&mmsys1_cfg->dl_in_relay21, BIT(30) | SIZE(width, height));
}
static void disp_config_main_path_mutex(enum disp_path_sel path)
{
u32 val;
/* ovlsys mutex */
write32(&mmsys_mutex[OVL0]->mutex[0].mod, MUTEX_MOD_OVL_MAIN_PATH);
write32(&mmsys_mutex[OVL0]->mutex[0].mod1, MUTEX_MOD1_OVL_MAIN_PATH);
/* dispsys mutex */
write32(&mmsys_mutex[DISP0]->mutex[0].mod, MUTEX_MOD_DISP_MAIN_PATH);
write32(&mmsys_mutex[DISP0]->mutex[0].mod1, MUTEX_MOD1_DISP_MAIN_PATH);
/* dispsys1 mutex */
if (path == DISP_PATH_EDP)
write32(&mmsys_mutex[DISP1]->mutex[0].mod, MUTEX_MOD_DISP1_MAIN_PATH_EDP);
else
write32(&mmsys_mutex[DISP1]->mutex[0].mod, MUTEX_MOD_DISP1_MAIN_PATH_DSI0);
/* mutex source from DVO */
if (path == DISP_PATH_EDP)
val = MUTEX_SOF_DVO | (MUTEX_SOF_DVO << 7);
else
val = MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 7);
write32(&mmsys_mutex[OVL0]->mutex[0].ctl, val);
write32(&mmsys_mutex[DISP0]->mutex[0].ctl, val);
write32(&mmsys_mutex[DISP1]->mutex[0].ctl, val);
/* mutex enable */
write32(&mmsys_mutex[OVL0]->mutex[0].en, BIT(0));
write32(&mmsys_mutex[DISP0]->mutex[0].en, BIT(0));
write32(&mmsys_mutex[DISP1]->mutex[0].en, BIT(0));
}
static void main_disp_path_setup(u16 width, u16 height, u32 vrefresh, enum disp_path_sel path)
{
int i;
enum mtk_disp_blender_layer blender_type[ARRAY_SIZE(blenders)] = {
FIRST_BLENDER,
OTHER_BLENDER,
OTHER_BLENDER,
LAST_BLENDER,
};
/* ovlsys config */
for (i = 0; i < ARRAY_SIZE(blenders); i++) {
blender_config(blenders[i], width, height, blender_type[i]);
blender_start(blenders[i]);
}
outproc_config(outproc0_reg, width, height);
outproc_start(outproc0_reg);
/* disp config */
mdp_rsz_config(disp_mdp_rsz0_reg, width, height);
mdp_rsz_start(disp_mdp_rsz0_reg);
tdshp_config(disp_tdshp0_reg, width, height);
tdshp_start(disp_tdshp0_reg);
ccorr_config(disp_ccorr0_reg, width, height);
ccorr_start(disp_ccorr0_reg);
ccorr_config(disp_ccorr1_reg, width, height);
ccorr_start(disp_ccorr1_reg);
gamma_config(disp_gamma0_reg, width, height);
gamma_start(disp_gamma0_reg);
postmask_config(disp_postmask0_reg, width, height);
postmask_start(disp_postmask0_reg);
dither_config(disp_dither0_reg, width, height);
dither_start(disp_dither0_reg);
/* async config */
async_config(width, height);
/* path connect */
disp_config_main_path_connection(path);
/* mutex config */
disp_config_main_path_mutex(path);
}
static void disp_clock_on(void)
{
clrbits32(&mmsys_cfg->mmsys_cg_con0, CG_CON_ALL);
clrbits32(&mmsys_cfg->mmsys_cg_con1, CG_CON_ALL);
clrbits32(&mmsys_cfg->mmsys_cg_con2, CG_CON_ALL);
clrbits32(&mmsys1_cfg->mmsys_cg_con0, CG_CON_ALL);
clrbits32(&mmsys1_cfg->mmsys_cg_con1, CG_CON_ALL);
clrbits32(&mmsys1_cfg->mmsys_cg_con2, CG_CON_ALL);
clrbits32(&ovlsys_cfg->mmsys_cg_con0, CG_CON_ALL);
clrbits32(&ovlsys_cfg->mmsys_cg_con1, CG_CON_ALL);
clrbits32(&ovlsys_cfg->mmsys_cg_con2, CG_CON_ALL);
}
static void ovlsys_layer_config(u32 fmt, u32 bpp, u16 width, u16 height)
{
/* exdma config */
write32(&exdma2_reg->roi_size, SIZE(width, height));
write32(&exdma2_reg->ovl_l_size, SIZE(width, height));
write32(&exdma2_reg->pitch, (width * bpp) & 0xFFFF);
write32(&exdma2_reg->ovl_l_clrfmt, fmt);
/* exdma start */
clrsetbits32(&exdma2_reg->rdma_burst_ctl, BIT(28) | BIT(30) | BIT(31),
BIT(28) | BIT(31));
setbits32(&exdma2_reg->dummy, BIT(2) | BIT(3));
setbits32(&exdma2_reg->datapath_con, BIT(0) | BIT(24) | BIT(25));
clrsetbits32(&exdma2_reg->ovl_mout, BIT(0) | BIT(1), BIT(1));
write32(&exdma2_reg->gdrdy_period, 0xFFFFFFFF);
/* Enable layer */
setbits32(&exdma2_reg->rdma0_ctl, BIT(0));
setbits32(&blenders[0]->bld_l_fmt, fmt);
}
void mtk_ddp_init(void)
{
disp_clock_on();
}
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_DEBUG, "%s: display resolution: %ux%u@%u bpp %u\n", __func__, width, height,
vrefresh, bpp);
if (!vrefresh) {
if (!width || !height)
vrefresh = 60;
else
vrefresh = edid->mode.pixel_clock * 1000 /
((width + edid->mode.hbl) * (height + edid->mode.vbl));
printk(BIOS_WARNING, "%s: vrefresh is not provided; using %u\n", __func__,
vrefresh);
}
if (width > 0x1FFF || height > 0x1FFF)
printk(BIOS_WARNING, "%s: w/h: %d/%d exceed hw limit %u\n", __func__,
width, height, 0x1FFF);
main_disp_path_setup(width, height, vrefresh, path);
ovlsys_layer_config(fmt, bpp, width, height);
}

View file

@ -192,10 +192,27 @@ enum {
MMVOTE_BASE = IO_PHYS + 0x21B00000,
MMPC_BASE = IO_PHYS + 0x21B50000,
MMSYS_CONFIG_BASE = IO_PHYS + 0x22000000,
MMSYS_MUTEX_BASE = IO_PHYS + 0x22020000,
DISP_CCORR0_BASE = IO_PHYS + 0x22090000,
DISP_CCORR1_BASE = IO_PHYS + 0x220A0000,
DISP_COLOR0_BASE = IO_PHYS + 0x220F0000,
DISP_DITHER0_BASE = IO_PHYS + 0x22110000,
DISP_GAMMA0_BASE = IO_PHYS + 0x22130000,
DISP_POSTMASK0_BASE = IO_PHYS + 0x22180000,
DISP_MDP_RSZ0_BASE = IO_PHYS + 0x221A0000,
DISP_TDSHP0_BASE = IO_PHYS + 0x221E0000,
MMSYS1_CONFIG_BASE = IO_PHYS + 0x22400000,
MMSYS1_MUTEX_BASE = IO_PHYS + 0x22420000,
DSI0_BASE = IO_PHYS + 0x22490000,
DISP_DVO0 = IO_PHYS + 0x224C0000,
OVLSYS_CONFIG_BASE = IO_PHYS + 0x22800000,
OVLSYS_MUTEX_BASE = IO_PHYS + 0x22820000,
OVLSYS_EXDMA2_BASE = IO_PHYS + 0x22850000,
OVLSYS_BLENDER1_BASE = IO_PHYS + 0x228E0000,
OVLSYS_BLENDER2_BASE = IO_PHYS + 0x228F0000,
OVLSYS_BLENDER3_BASE = IO_PHYS + 0x22900000,
OVLSYS_BLENDER4_BASE = IO_PHYS + 0x22910000,
OVLSYS_OUTPROC0_BASE = IO_PHYS + 0x22970000,
OVLSYS1_CONFIG_BASE = IO_PHYS + 0x22C00000,
DISP_VDISP_AO_CONFIG_BASE = IO_PHYS + 0x2E800000,
EDP_CLK_BASE = IO_PHYS + 0x21B50000,

View file

@ -0,0 +1,462 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef _SOC_MEDIATEK_MT8196_DDP_H_
#define _SOC_MEDIATEK_MT8196_DDP_H_
#include <soc/addressmap.h>
#include <soc/display.h>
#include <types.h>
#define CG_CON_ALL 0xFFFFFFFF
struct ovlsys_cfg {
u32 reserved_0x000[64];
u32 mmsys_cg_con0;
u32 mmsys_cg_set0;
u32 mmsys_cg_clr0;
u32 reserved_0x10c;
u32 mmsys_cg_con1;
u32 mmsys_cg_set1;
u32 mmsys_cg_clr1;
u32 reserved_0x11c;
u32 mmsys_cg_con2;
u32 mmsys_cg_set2;
u32 mmsys_cg_clr2;
u32 reserved_0x12c[92];
u32 relay5_size;
u32 reserved_0x2a0[640];
u32 bypass_mux_shadow;
u32 reserved_0xca4;
u32 reserved_0xca8;
u32 cb_con;
u32 reserved_0xcb0[88];
u32 blender_out_cb4;
u32 reserved_0xe14;
u32 reserved_0xe18;
u32 reserved_0xe1c[17];
u32 reserved_0xe60;
u32 reserved_0xe64;
u32 exdma_out_cb3;
u32 reserved_0xe6c[41];
u32 outproc_out_cb0;
u32 reserved_0xf14;
u32 reserved_0xf18[22];
u32 rsz_in_cb2;
};
check_member(ovlsys_cfg, mmsys_cg_con0, 0x100);
check_member(ovlsys_cfg, mmsys_cg_con1, 0x110);
check_member(ovlsys_cfg, mmsys_cg_con2, 0x120);
check_member(ovlsys_cfg, relay5_size, 0x29C);
check_member(ovlsys_cfg, bypass_mux_shadow, 0xCA0);
check_member(ovlsys_cfg, cb_con, 0xCAC);
check_member(ovlsys_cfg, blender_out_cb4, 0xE10);
check_member(ovlsys_cfg, exdma_out_cb3, 0xE68);
check_member(ovlsys_cfg, outproc_out_cb0, 0xF10);
check_member(ovlsys_cfg, rsz_in_cb2, 0xF70);
static struct ovlsys_cfg *const ovlsys_cfg = (void *)OVLSYS_CONFIG_BASE;
struct dispsys_cfg {
u32 reserved_0x000[64];
u32 mmsys_cg_con0;
u32 mmsys_cg_set0;
u32 mmsys_cg_clr0;
u32 reserved_0x10c;
u32 mmsys_cg_con1;
u32 mmsys_cg_set1;
u32 mmsys_cg_clr1;
u32 reserved_0x11c;
u32 mmsys_cg_con2;
u32 mmsys_cg_set2;
u32 mmsys_cg_clr2;
u32 reserved_0x12c[53];
u32 dl_in_relay0;
u32 reserved_0x204[25];
u32 dl_out_relay1;
u32 reserved_0x26c[625];
u32 bypass_mux_shadow;
u32 reserved_0xc34[61];
u32 disp_ccorr0_sel;
u32 disp_ccorr0_sout;
u32 disp_ccorr1_sel;
u32 disp_ccorr1_sout;
u32 reserved_0xd38[8];
u32 disp_gamma0_sel;
u32 reserved_0xd5c[3];
u32 disp_postmask_sout;
u32 reserved_0xd6c;
u32 disp_tdshp0_sout;
u32 reserved_0xd74;
u32 disp_mdp_rsz0_mout;
u32 reserved_0xd7c[2];
u32 panel_comp_out_cb1;
u32 reserved_0xd88[18];
u32 pq_in_cb0;
u32 reserved_0xdd4[26];
u32 pq_out_cb0;
u32 pq_out_cb1;
u32 pq_out_cb2;
u32 reserved_0xe40[3];
u32 pq_out_cb6;
};
check_member(dispsys_cfg, mmsys_cg_con0, 0x100);
check_member(dispsys_cfg, mmsys_cg_con1, 0x110);
check_member(dispsys_cfg, mmsys_cg_con2, 0x120);
check_member(dispsys_cfg, dl_in_relay0, 0x200);
check_member(dispsys_cfg, dl_out_relay1, 0x268);
check_member(dispsys_cfg, bypass_mux_shadow, 0xC30);
check_member(dispsys_cfg, disp_ccorr0_sel, 0xD28);
check_member(dispsys_cfg, disp_gamma0_sel, 0xD58);
check_member(dispsys_cfg, disp_postmask_sout, 0xD68);
check_member(dispsys_cfg, disp_tdshp0_sout, 0xD70);
check_member(dispsys_cfg, panel_comp_out_cb1, 0xD84);
check_member(dispsys_cfg, pq_in_cb0, 0xDD0);
check_member(dispsys_cfg, pq_out_cb0, 0xE3C);
check_member(dispsys_cfg, pq_out_cb6, 0xE54);
static struct dispsys_cfg *const mmsys_cfg = (void *)MMSYS_CONFIG_BASE;
struct dispsys1_cfg {
u32 reserved_0x000[64];
u32 mmsys_cg_con0;
u32 mmsys_cg_set0;
u32 mmsys_cg_clr0;
u32 reserved_0x10c;
u32 mmsys_cg_con1;
u32 mmsys_cg_set1;
u32 mmsys_cg_clr1;
u32 reserved_0x11c;
u32 mmsys_cg_con2;
u32 mmsys_cg_set2;
u32 mmsys_cg_clr2;
u32 reserved_0x12c[54];
u32 dl_in_relay21;
u32 reserved_0x208[700];
u32 bypass_mux_shadow;
u32 reserved_0xcfc[13];
u32 comp_out_cb6;
u32 reserved_0xd34[38];
u32 merge_out_cb0;
u32 reserved_0xdd0[55];
u32 splitter_in_cb1;
u32 reserved_0xeb0[45];
u32 splitter_out_cb9;
};
check_member(dispsys1_cfg, mmsys_cg_con0, 0x100);
check_member(dispsys1_cfg, mmsys_cg_con1, 0x110);
check_member(dispsys1_cfg, mmsys_cg_con2, 0x120);
check_member(dispsys1_cfg, dl_in_relay21, 0x204);
check_member(dispsys1_cfg, bypass_mux_shadow, 0xCF8);
check_member(dispsys1_cfg, comp_out_cb6, 0xD30);
check_member(dispsys1_cfg, merge_out_cb0, 0xDCC);
check_member(dispsys1_cfg, splitter_in_cb1, 0xEAC);
check_member(dispsys1_cfg, splitter_out_cb9, 0xF64);
static struct dispsys1_cfg *const mmsys1_cfg = (void *)MMSYS1_CONFIG_BASE;
struct exdma {
u32 reserved_0x000[5];
u32 datapath_con;
u32 reserved_0x018[2];
u32 ovl_en;
u32 reserved_0x024[3];
u32 roi_size;
u32 reserved_0x034[3];
u32 ovl_l_en;
u32 reserved_0x044;
u32 ovl_l_size;
u32 reserved_0x04c;
u32 ovl_l_clrfmt;
u32 reserved_0x054[43];
u32 rdma0_ctl;
u32 reserved_0x104[60];
u32 rdma_burst_ctl;
u32 reserved_0x1F8[2];
u32 dummy;
u32 reserved_0x204;
u32 gdrdy_period;
u32 reserved_0x20c[57];
u32 pitch_msb;
u32 pitch;
u32 reserved_0x2f8[2];
u32 ovl_con;
u32 reserved_0x304[783];
u32 ovl_addr;
u32 reserved_0xf44[43];
u32 ovl_mout;
};
check_member(exdma, datapath_con, 0x014);
check_member(exdma, ovl_en, 0x020);
check_member(exdma, roi_size, 0x030);
check_member(exdma, ovl_l_en, 0x040);
check_member(exdma, ovl_l_size, 0x048);
check_member(exdma, ovl_l_clrfmt, 0x050);
check_member(exdma, rdma0_ctl, 0x100);
check_member(exdma, rdma_burst_ctl, 0x1F4);
check_member(exdma, dummy, 0x200);
check_member(exdma, gdrdy_period, 0x208);
check_member(exdma, pitch_msb, 0x2F0);
check_member(exdma, pitch, 0x2F4);
check_member(exdma, ovl_addr, 0xF40);
check_member(exdma, ovl_mout, 0xFF0);
static struct exdma *const exdma2_reg = (void *)OVLSYS_EXDMA2_BASE;
struct blender {
u32 reserved_0x000[4];
u32 datapath_con;
u32 reserved_0x014[3];
u32 bld_en;
u32 reserved_0x024;
u32 shadow_ctl;
u32 reserved_0x02c;
u32 roi_size;
u32 reserved_0x034[3];
u32 bld_l_en;
u32 reserved_0x044;
u32 bld_l_size;
u32 reserved_0x04c;
u32 bld_l_fmt;
u32 reserved_0x054[44];
u32 bg_clr;
u32 reserved_0x108[62];
u32 bld_l_con2;
};
check_member(blender, datapath_con, 0x010);
check_member(blender, bld_en, 0x020);
check_member(blender, shadow_ctl, 0x028);
check_member(blender, roi_size, 0x030);
check_member(blender, bld_l_en, 0x040);
check_member(blender, bld_l_size, 0x048);
check_member(blender, bld_l_fmt, 0x050);
check_member(blender, bg_clr, 0x104);
check_member(blender, bld_l_con2, 0x200);
static struct blender *const blenders[] = {
(void *)OVLSYS_BLENDER1_BASE,
(void *)OVLSYS_BLENDER2_BASE,
(void *)OVLSYS_BLENDER3_BASE,
(void *)OVLSYS_BLENDER4_BASE,
};
struct outproc {
u32 reserved_0x000[4];
u32 datapath_con;
u32 reserved_0x014[3];
u32 outproc_en;
u32 reserved_0x024;
u32 shadow_ctl;
u32 reserved_0x02c;
u32 roi_size;
};
check_member(outproc, datapath_con, 0x010);
check_member(outproc, outproc_en, 0x020);
check_member(outproc, shadow_ctl, 0x028);
check_member(outproc, roi_size, 0x030);
static struct outproc *const outproc0_reg = (void *)OVLSYS_OUTPROC0_BASE;
struct disp_mutex {
u32 inten;
u32 intsta;
u32 reserved0[6];
struct {
u32 en;
u32 dummy;
u32 dummy1;
u32 rst;
u32 ctl;
u32 mod;
u32 mod1;
u32 reserved;
} mutex[12];
};
enum mmsys {
DISP0,
DISP1,
OVL0,
};
static struct disp_mutex *const mmsys_mutex[] = {
[DISP0] = (void *)MMSYS_MUTEX_BASE,
[DISP1] = (void *)MMSYS1_MUTEX_BASE,
[OVL0] = (void *)OVLSYS_MUTEX_BASE,
};
enum {
OVL_INFMT_RGB565 = 0,
OVL_INFMT_RGB888 = 1,
OVL_INFMT_RGBA8888 = 2,
OVL_INFMT_ARGB8888 = 3,
OVL_INFMT_UYVY = 4,
OVL_INFMT_YUYV = 5,
OVL_INFMT_UNKNOWN = 16,
};
/* OVLSYS mutex module */
enum {
MUTEX_MOD_OVL_EXDMA2 = BIT(2),
MUTEX_MOD_OVL_BLENDER1 = BIT(11),
MUTEX_MOD_OVL_BLENDER2 = BIT(12),
MUTEX_MOD_OVL_BLENDER3 = BIT(13),
MUTEX_MOD_OVL_BLENDER4 = BIT(14),
MUTEX_MOD_OVL_OUTPROC0 = BIT(20),
MUTEX_MOD_OVL_MAIN_PATH = MUTEX_MOD_OVL_EXDMA2 |
MUTEX_MOD_OVL_BLENDER1 |
MUTEX_MOD_OVL_BLENDER2 |
MUTEX_MOD_OVL_BLENDER3 |
MUTEX_MOD_OVL_BLENDER4 |
MUTEX_MOD_OVL_OUTPROC0,
};
enum {
MUTEX_MOD1_OVL_DLO_ASYNC5 = BIT(16),
MUTEX_MOD1_OVL_MAIN_PATH = MUTEX_MOD1_OVL_DLO_ASYNC5,
};
/* DISPSYS mutex module */
enum {
MUTEX_MOD_DISP_CCORR0 = BIT(6),
MUTEX_MOD_DISP_CCORR1 = BIT(7),
MUTEX_MOD_DISP_DITHER0 = BIT(14),
MUTEX_MOD_DISP_DLI_ASYNC0 = BIT(16),
MUTEX_MOD_DISP_MAIN_PATH = MUTEX_MOD_DISP_DLI_ASYNC0 |
MUTEX_MOD_DISP_CCORR0 |
MUTEX_MOD_DISP_CCORR1 |
MUTEX_MOD_DISP_DITHER0,
};
enum {
MUTEX_MOD1_DISP_DLO_ASYNC1 = BIT(1),
MUTEX_MOD1_DISP_GAMMA0 = BIT(9),
MUTEX_MOD1_DISP_POSTMASK0 = BIT(14),
MUTEX_MOD1_DISP_MDP_RSZ0 = BIT(18),
MUTEX_MOD1_DISP_TDSHP0 = BIT(21),
MUTEX_MOD1_DISP_MAIN_PATH = MUTEX_MOD1_DISP_MDP_RSZ0 |
MUTEX_MOD1_DISP_TDSHP0 |
MUTEX_MOD1_DISP_GAMMA0 |
MUTEX_MOD1_DISP_POSTMASK0 |
MUTEX_MOD1_DISP_DLO_ASYNC1,
};
/* DISPSYS1 mutex module */
enum {
MUTEX_MOD_DISP1_DLI_ASYNC21 = BIT(1),
MUTEX_MOD_DISP1_DSI0 = BIT(23),
MUTEX_MOD_DISP1_DVO = BIT(29),
MUTEX_MOD_DISP1_MAIN_PATH_EDP = MUTEX_MOD_DISP1_DLI_ASYNC21 |
MUTEX_MOD_DISP1_DVO,
MUTEX_MOD_DISP1_MAIN_PATH_DSI0 = MUTEX_MOD_DISP1_DLI_ASYNC21 |
MUTEX_MOD_DISP1_DSI0,
};
enum {
MUTEX_SOF_SINGLE_MODE = 0,
MUTEX_SOF_DSI0 = 1,
MUTEX_SOF_DPI0 = 5,
MUTEX_SOF_DVO = 7,
};
enum mtk_disp_blender_layer {
FIRST_BLENDER,
LAST_BLENDER,
SINGLE_BLENDER,
OTHER_BLENDER,
};
struct disp_tdshp_regs {
u32 tdshp_00;
u32 reserved0[63];
u32 ctrl;
u32 reserved1[3];
u32 cfg;
u32 reserved2[3];
u32 input_size;
u32 output_offset;
u32 output_size;
};
check_member(disp_tdshp_regs, output_size, 0x128);
struct disp_ccorr_regs {
u32 en;
u32 reset;
u32 inten;
u32 intsta;
u32 status;
u32 reserved0[3];
u32 cfg;
u32 reserved1[3];
u32 size;
u32 reserved2[27];
u32 shadow;
};
check_member(disp_ccorr_regs, shadow, 0xA0);
struct disp_gamma_regs {
u32 en;
u32 reset;
u32 inten;
u32 intsta;
u32 status;
u32 reserved0[3];
u32 cfg;
u32 reserved1[3];
u32 size;
};
check_member(disp_gamma_regs, size, 0x30);
struct disp_dither_regs {
u32 en;
u32 reset;
u32 inten;
u32 intsta;
u32 status;
u32 reserved0[3];
u32 cfg;
u32 reserved1[3];
u32 size;
u32 reserved2[51];
u32 shadow;
};
check_member(disp_dither_regs, shadow, 0x100);
struct disp_mdp_rsz_regs {
u32 en;
u32 reserved0[3];
u32 input_size;
u32 output_size;
};
check_member(disp_mdp_rsz_regs, output_size, 0x14);
struct disp_postmask_regs {
u32 en;
u32 reserved0[7];
u32 cfg;
u32 reserved1[3];
u32 size;
};
check_member(disp_postmask_regs, size, 0x30);
static struct disp_mdp_rsz_regs *const disp_mdp_rsz0_reg = (void *)DISP_MDP_RSZ0_BASE;
static struct disp_postmask_regs *const disp_postmask0_reg = (void *)DISP_POSTMASK0_BASE;
static struct disp_tdshp_regs *const disp_tdshp0_reg = (void *)DISP_TDSHP0_BASE;
static struct disp_ccorr_regs *const disp_ccorr0_reg = (void *)DISP_CCORR0_BASE;
static struct disp_ccorr_regs *const disp_ccorr1_reg = (void *)DISP_CCORR1_BASE;
static struct disp_gamma_regs *const disp_gamma0_reg = (void *)DISP_GAMMA0_BASE;
static struct disp_dither_regs *const disp_dither0_reg = (void *)DISP_DITHER0_BASE;
#endif

View file

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef SOC_MEDIATEK_MT8196_DSI_H
#define SOC_MEDIATEK_MT8196_DSI_H
#include <soc/dsi_common.h>
#endif