1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <edid.h>
6 #include <soc/addressmap.h>
7 #include <soc/ddp.h>
8
disp_config_main_path_connection(void)9 static void disp_config_main_path_connection(void)
10 {
11 /* ovl0->ovl0_2l */
12 write32(&mmsys_cfg->mmsys_ovl_mout_en,
13 (DISP_OVL0_GO_BG | DISP_OVL0_2L_GO_BLEND));
14 write32(&mmsys_cfg->ovl0_2l_mout_en, OVL0_MOUT_EN_DISP_RDMA0);
15 write32(&mmsys_cfg->rdma0_sel_in, RDMA0_SEL_IN_OVL0_2L);
16 write32(&mmsys_cfg->rdma0_sout_sel, RDMA0_SOUT_COLOR0);
17 write32(&mmsys_cfg->ccorr0_sout_sel, CCORR0_SOUT_AAL0);
18 write32(&mmsys_cfg->aal0_sel_in, AAL0_SEL_IN_CCORR0);
19 write32(&mmsys_cfg->dither0_mout_en, DITHER0_MOUT_DSI0);
20 write32(&mmsys_cfg->dsi0_sel_in, DSI0_SEL_IN_DITHER0);
21 }
22
disp_config_main_path_mutex(void)23 static void disp_config_main_path_mutex(void)
24 {
25 write32(&disp_mutex->mutex[0].mod, MUTEX_MOD_MAIN_PATH);
26
27 /* Clock source from DSI0 */
28 write32(&disp_mutex->mutex[0].ctl,
29 MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 6));
30 write32(&disp_mutex->mutex[0].en, BIT(0));
31 }
32
ovl_bgclr_in_sel(u32 idx)33 static void ovl_bgclr_in_sel(u32 idx)
34 {
35 setbits32(&disp_ovl[idx]->datapath_con, BIT(2));
36 }
37
ovl_layer_smi_id_en(u32 idx)38 static void ovl_layer_smi_id_en(u32 idx)
39 {
40 printk(BIOS_INFO, "%s\n", __func__);
41
42 setbits32(&disp_ovl[idx]->datapath_con, BIT(0));
43 }
44
ccorr_config(u32 width,u32 height)45 static void ccorr_config(u32 width, u32 height)
46 {
47 struct disp_ccorr_regs *const regs = disp_ccorr;
48 int enable_relay = 0;
49
50 printk(BIOS_INFO, "%s\n", __func__);
51
52 write32(®s->size, width << 16 | height);
53
54 if (enable_relay) {
55 setbits32(®s->cfg, PQ_RELAY_MODE);
56 clrbits32(®s->cfg, PQ_ENGINE_EN);
57 } else {
58 clrbits32(®s->cfg, PQ_RELAY_MODE);
59 setbits32(®s->cfg, PQ_ENGINE_EN);
60 }
61
62 write32(®s->en, PQ_EN);
63 }
64
aal_config(u32 width,u32 height)65 static void aal_config(u32 width, u32 height)
66 {
67 struct disp_aal_regs *const regs = disp_aal;
68 int enable_relay = 1;
69
70 printk(BIOS_INFO, "%s\n", __func__);
71
72 write32(®s->size, width << 16 | height);
73 write32(®s->output_size, width << 16 | height);
74
75 if (enable_relay) {
76 setbits32(®s->cfg, PQ_RELAY_MODE);
77 clrbits32(®s->cfg, PQ_ENGINE_EN);
78 } else {
79 clrbits32(®s->cfg, PQ_RELAY_MODE);
80 setbits32(®s->cfg, PQ_ENGINE_EN);
81 }
82
83 write32(®s->en, PQ_EN);
84 }
85
gamma_config(u32 width,u32 height)86 static void gamma_config(u32 width, u32 height)
87 {
88 struct disp_gamma_regs *const regs = disp_gamma;
89 int enable_relay = 0;
90
91 printk(BIOS_INFO, "%s\n", __func__);
92
93 write32(®s->size, width << 16 | height);
94
95 if (enable_relay)
96 setbits32(®s->cfg, PQ_RELAY_MODE);
97 else
98 clrbits32(®s->cfg, PQ_RELAY_MODE);
99
100 write32(®s->en, PQ_EN);
101 }
102
postmask_config(u32 width,u32 height)103 static void postmask_config(u32 width, u32 height)
104 {
105 struct disp_postmask_regs *const regs = disp_postmask;
106 int enable_relay = 1;
107
108 printk(BIOS_INFO, "%s\n", __func__);
109
110 write32(®s->size, width << 16 | height);
111
112 if (enable_relay)
113 setbits32(®s->cfg, PQ_RELAY_MODE);
114 else
115 clrbits32(®s->cfg, PQ_RELAY_MODE);
116
117 write32(®s->en, PQ_EN);
118 }
119
dither_config(u32 width,u32 height)120 static void dither_config(u32 width, u32 height)
121 {
122 struct disp_dither_regs *const regs = disp_dither;
123 int enable_relay = 1;
124
125 printk(BIOS_INFO, "%s\n", __func__);
126
127 write32(®s->size, width << 16 | height);
128
129 if (enable_relay)
130 setbits32(®s->cfg, PQ_RELAY_MODE);
131 else
132 clrbits32(®s->cfg, PQ_RELAY_MODE);
133
134 write32(®s->en, PQ_EN);
135 }
136
137
main_disp_path_setup(u32 width,u32 height,u32 vrefresh)138 static void main_disp_path_setup(u32 width, u32 height, u32 vrefresh)
139 {
140 u32 idx = 0;
141 u32 pixel_clk = width * height * vrefresh;
142
143 printk(BIOS_INFO, "%s\n", __func__);
144
145 for (idx = 0; idx < MAIN_PATH_OVL_NR; idx++) {
146 ovl_set_roi(idx, width, height, idx ? 0 : 0xff0000ff);
147 ovl_layer_smi_id_en(idx);
148 }
149
150 rdma_config(width, height, pixel_clk, 5 * KiB);
151 color_start(width, height);
152 ccorr_config(width, height);
153 aal_config(width, height);
154 gamma_config(width, height);
155 postmask_config(width, height);
156 dither_config(width, height);
157 disp_config_main_path_connection();
158 disp_config_main_path_mutex();
159 }
160
disp_clock_on(void)161 static void disp_clock_on(void)
162 {
163 clrbits32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_DISP_ALL);
164
165 clrbits32(&mmsys_cfg->mmsys_cg_con1, CG_CON1_DISP_ALL);
166
167 clrbits32(&mmsys_cfg->mmsys_cg_con2, CG_CON2_DISP_ALL);
168 }
169
mtk_ddp_init(void)170 void mtk_ddp_init(void)
171 {
172 disp_clock_on();
173 /* Turn off M4U port. */
174 write32((void *)(SMI_LARB0 + SMI_LARB_PORT_L0_OVL_RDMA0), 0);
175 }
176
mtk_ddp_mode_set(const struct edid * edid)177 void mtk_ddp_mode_set(const struct edid *edid)
178 {
179 u32 fmt = OVL_INFMT_RGBA8888;
180 u32 bpp = edid->framebuffer_bits_per_pixel / 8;
181 u32 width = edid->mode.ha;
182 u32 height = edid->mode.va;
183 u32 vrefresh = edid->mode.refresh;
184
185 printk(BIOS_INFO, "%s display resolution: %dx%d@%d bpp %d\n",
186 __func__, width, height, vrefresh, bpp);
187
188 if (!vrefresh) {
189 vrefresh = 60;
190 printk(BIOS_INFO, "%s invalid vrefresh %d\n",
191 __func__, vrefresh);
192 }
193
194 main_disp_path_setup(width, height, vrefresh);
195 rdma_start();
196 ovl_layer_config(fmt, bpp, width, height);
197 ovl_bgclr_in_sel(1);
198 }
199