blob: 6706ed7d00bea3fc7fdc794c2684f71d0305dd3f [file] [log] [blame]
Rex-BC Chen783e2bf2021-12-17 13:03:32 +08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/*
4 * This file is created based on MT8186 Functional Specification
5 * Chapter number: 6.9
6 */
7
8#include <console/console.h>
9#include <edid.h>
10#include <soc/addressmap.h>
11#include <soc/ddp.h>
12
13static void disp_config_main_path_connection(void)
14{
15 /*
16 * Main path:
17 * OVL0->RDMA0->COLOR0->CCORR0->AAL0->GAMMA->POSTMASK0->DITHER->DSI0
18 */
19 SET32_BITFIELDS(&mmsys_cfg->disp_ovl0_mout_en,
20 DISP_OVL0_MOUT_EN, DISP_OVL0_MOUT_TO_RDMA0);
21 SET32_BITFIELDS(&mmsys_cfg->disp_rdma0_sel_in,
22 DISP_RDMA0_SEL_IN, DISP_RDMA0_FROM_OVL0);
23 SET32_BITFIELDS(&mmsys_cfg->mmsys_ovl_con,
24 DISP_MMSYS_OVL0_CON, DISP_OVL0_GO_BLEND);
25 SET32_BITFIELDS(&mmsys_cfg->disp_rdma0_sout_sel,
26 DISP_RDMA0_SOUT_SEL, DISP_RDMA0_SOUT_TO_COLOR0);
27 SET32_BITFIELDS(&mmsys_cfg->disp_dither0_mout_en,
28 DISP_DITHER0_MOUT_EN, DISP_DITHER0_MOUT_TO_DSI0);
29 SET32_BITFIELDS(&mmsys_cfg->disp_dsi0_sel_in,
30 DISP_DSI0_SEL_IN, DISP_DSI0_FROM_DITHER0);
31}
32
33static void disp_config_main_path_mutex(void)
34{
35 write32(&disp_mutex->mutex[0].mod, MUTEX_MOD_MAIN_PATH);
36
37 /* Clock source from DSI0 */
38 write32(&disp_mutex->mutex[0].ctl,
39 MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 6));
40 write32(&disp_mutex->mutex[0].en, BIT(0));
41}
42
43static void ovl_layer_smi_id_en(u32 idx)
44{
45 SET32_BITFIELDS(&disp_ovl[idx]->datapath_con,
46 SMI_ID_EN, SMI_ID_EN_VAL);
47}
48
49static void ccorr_config(u32 width, u32 height)
50{
51 struct disp_ccorr_regs *const regs = disp_ccorr;
52
53 write32(&regs->size, width << 16 | height);
54
55 /* Disable relay mode */
56 SET32_BITFIELDS(&regs->cfg, PQ_CFG_RELAY_MODE, 0);
57 SET32_BITFIELDS(&regs->cfg, PQ_CFG_ENGINE_EN, PQ_ENGINE_EN);
58
59 write32(&regs->en, PQ_EN);
60}
61
62static void aal_config(u32 width, u32 height)
63{
64 struct disp_aal_regs *const regs = disp_aal;
65
66 write32(&regs->size, width << 16 | height);
67 write32(&regs->output_size, width << 16 | height);
68
69 /* Enable relay mode */
70 SET32_BITFIELDS(&regs->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE);
71 SET32_BITFIELDS(&regs->cfg, PQ_CFG_ENGINE_EN, 0);
72
73 write32(&regs->en, PQ_EN);
74}
75
76static void gamma_config(u32 width, u32 height)
77{
78 struct disp_gamma_regs *const regs = disp_gamma;
79
80 write32(&regs->size, width << 16 | height);
81
82 /* Disable relay mode */
83 SET32_BITFIELDS(&regs->cfg, PQ_CFG_RELAY_MODE, 0);
84
85 write32(&regs->en, PQ_EN);
86}
87
88static void postmask_config(u32 width, u32 height)
89{
90 struct disp_postmask_regs *const regs = disp_postmask;
91
92 write32(&regs->size, width << 16 | height);
93
94 /* Enable relay mode */
95 SET32_BITFIELDS(&regs->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE);
96
97 write32(&regs->en, PQ_EN);
98}
99
100static void dither_config(u32 width, u32 height)
101{
102 struct disp_dither_regs *const regs = disp_dither;
103
104 write32(&regs->size, width << 16 | height);
105
106 /* Enable relay mode */
107 SET32_BITFIELDS(&regs->cfg, PQ_CFG_RELAY_MODE, PQ_RELAY_MODE);
108
109 write32(&regs->en, PQ_EN);
110}
111
112static void main_disp_path_setup(u32 width, u32 height, u32 vrefresh)
113{
114 u32 pixel_clk = width * height * vrefresh;
115
116 /* One ovl in main path */
117 ovl_set_roi(0, width, height, 0xff0000ff);
118 ovl_layer_smi_id_en(0);
119 rdma_config(width, height, pixel_clk, 5 * KiB);
120 color_start(width, height);
121 ccorr_config(width, height);
122 aal_config(width, height);
123 gamma_config(width, height);
124 postmask_config(width, height);
125 dither_config(width, height);
126 disp_config_main_path_connection();
127 disp_config_main_path_mutex();
128}
129
130static void disp_clock_on(void)
131{
132 clrbits32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_DISP_ALL);
133 clrbits32(&mmsys_cfg->mmsys_cg_con2, CG_CON2_DISP_ALL);
134}
135
136void mtk_ddp_init(void)
137{
138 disp_clock_on();
139
140 /* Turn off M4U port */
141 write32((void *)(SMI_LARB0 + SMI_LARB_PORT_L0_OVL_RDMA0), 0);
142}
143
144void mtk_ddp_mode_set(const struct edid *edid)
145{
146 u32 fmt = OVL_INFMT_RGBA8888;
147 u32 bpp = edid->framebuffer_bits_per_pixel / 8;
148 u32 width = edid->mode.ha;
149 u32 height = edid->mode.va;
150 u32 vrefresh = edid->mode.refresh;
151
152 printk(BIOS_INFO, "%s: display resolution: %ux%u@%u bpp %u\n",
153 __func__, width, height, vrefresh, bpp);
154
155 if (!vrefresh) {
156 vrefresh = 60;
157 printk(BIOS_INFO, "%s: invalid vrefresh; setting to %u\n",
158 __func__, vrefresh);
159 }
160
161 main_disp_path_setup(width, height, vrefresh);
162 rdma_start();
163 ovl_layer_config(fmt, bpp, width, height);
164}