1 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
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(enum disp_path_sel path)9 static void disp_config_main_path_connection(enum disp_path_sel path)
10 {
11 /* ovl0 */
12 write32(&mmsys_cfg->mmsys_ovl_mout_en,
13 DISP_OVL0_TO_DISP_RDMA0);
14
15 if (path == DISP_PATH_EDP) {
16 write32(&mmsys_cfg->mmsys_dp_intf0_sel_in,
17 SEL_IN_DP_INTF0_FROM_DISP_DITHER0);
18 write32(&mmsys_cfg->mmsys_dither0_sel_out,
19 SEL_OUT_DISP_DITHER0_TO_DP_INTF0);
20 } else {
21 write32(&mmsys_cfg->mmsys_dsi0_sel_in,
22 SEL_IN_DSI0_FROM_DISP_DITHER0);
23 write32(&mmsys_cfg->mmsys_dither0_sel_out,
24 SEL_OUT_DISP_DITHER0_TO_DSI0);
25 }
26 }
27
disp_config_main_path_mutex(enum disp_path_sel path)28 static void disp_config_main_path_mutex(enum disp_path_sel path)
29 {
30 write32(&disp_mutex->mutex[0].mod, MUTEX_MOD_MAIN_PATH);
31
32 if (path == DISP_PATH_EDP)
33 write32(&disp_mutex->mutex[0].ctl,
34 MUTEX_SOF_DP_INTF0 | (MUTEX_SOF_DP_INTF0 << 7));
35 else
36 write32(&disp_mutex->mutex[0].ctl,
37 MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 7));
38
39 write32(&disp_mutex->mutex[0].en, BIT(0));
40 }
41
ovl_layer_smi_id_en(u32 idx)42 static void ovl_layer_smi_id_en(u32 idx)
43 {
44 setbits32(&disp_ovl[idx]->datapath_con, BIT(0));
45 }
46
ovl_layer_gclast_en(u32 idx)47 static void ovl_layer_gclast_en(u32 idx)
48 {
49 setbits32(&disp_ovl[idx]->datapath_con, BIT(24));
50 setbits32(&disp_ovl[idx]->datapath_con, BIT(25));
51 }
52
ovl_layer_output_clamp_en(u32 idx)53 static void ovl_layer_output_clamp_en(u32 idx)
54 {
55 setbits32(&disp_ovl[idx]->datapath_con, BIT(26));
56 }
57
ovl_layer_en(u32 idx)58 static void ovl_layer_en(u32 idx)
59 {
60 setbits32(&disp_ovl[idx]->en, BIT(0));
61 }
62
ccorr_config(u32 width,u32 height)63 static void ccorr_config(u32 width, u32 height)
64 {
65 struct disp_ccorr_regs *const regs = disp_ccorr;
66
67 write32(®s->size, width << 16 | height);
68 clrsetbits32(®s->cfg, PQ_ENGINE_EN, PQ_RELAY_MODE);
69 write32(®s->en, PQ_EN);
70 }
71
aal_config(u32 width,u32 height)72 static void aal_config(u32 width, u32 height)
73 {
74 struct disp_aal_regs *const regs = disp_aal;
75
76 write32(®s->size, width << 16 | height);
77 write32(®s->output_size, width << 16 | height);
78 clrsetbits32(®s->cfg, PQ_ENGINE_EN, PQ_RELAY_MODE);
79 write32(®s->en, PQ_EN);
80 }
81
gamma_config(u32 width,u32 height)82 static void gamma_config(u32 width, u32 height)
83 {
84 struct disp_gamma_regs *const regs = disp_gamma;
85
86 write32(®s->size, width << 16 | height);
87 setbits32(®s->cfg, PQ_RELAY_MODE);
88 write32(®s->en, PQ_EN);
89 }
90
postmask_config(u32 width,u32 height)91 static void postmask_config(u32 width, u32 height)
92 {
93 struct disp_postmask_regs *const regs = disp_postmask;
94
95 write32(®s->size, width << 16 | height);
96 setbits32(®s->cfg, PQ_RELAY_MODE);
97 write32(®s->en, PQ_EN);
98 }
99
dither_config(u32 width,u32 height)100 static void dither_config(u32 width, u32 height)
101 {
102 struct disp_dither_regs *const regs = disp_dither;
103
104 write32(®s->size, width << 16 | height);
105 setbits32(®s->cfg, PQ_RELAY_MODE);
106 write32(®s->en, PQ_EN);
107 }
108
main_disp_path_setup(u32 width,u32 height,u32 vrefresh,enum disp_path_sel path)109 static void main_disp_path_setup(u32 width, u32 height, u32 vrefresh, enum disp_path_sel path)
110 {
111 u32 idx;
112 const u32 pixel_clk = width * height * vrefresh;
113
114 for (idx = 0; idx < MAIN_PATH_OVL_NR; idx++) {
115 ovl_set_roi(idx, width, height, idx ? 0 : 0xff0000ff);
116 ovl_layer_smi_id_en(idx);
117 ovl_layer_gclast_en(idx);
118 ovl_layer_output_clamp_en(idx);
119 ovl_layer_en(idx);
120 }
121
122 rdma_config(width, height, pixel_clk, 5 * KiB);
123 color_start(width, height);
124 ccorr_config(width, height);
125 aal_config(width, height);
126 gamma_config(width, height);
127 postmask_config(width, height);
128 dither_config(width, height);
129 disp_config_main_path_connection(path);
130 disp_config_main_path_mutex(path);
131 }
132
disp_clock_on(void)133 static void disp_clock_on(void)
134 {
135 clrbits32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_DISP_ALL);
136 clrbits32(&mmsys_cfg->mmsys_cg_con1, CG_CON1_DISP_ALL);
137 clrbits32(&mmsys_cfg->mmsys_cg_con2, CG_CON2_DISP_ALL);
138 }
139
mtk_ddp_init(void)140 void mtk_ddp_init(void)
141 {
142 disp_clock_on();
143
144 /* Turn off M4U port. */
145 write32p(SMI_LARB0 + SMI_LARB_PORT_L0_OVL_RDMA0, 0);
146 }
147
mtk_ddp_mode_set(const struct edid * edid,enum disp_path_sel path)148 void mtk_ddp_mode_set(const struct edid *edid, enum disp_path_sel path)
149 {
150 u32 fmt = OVL_INFMT_RGBA8888;
151 u32 bpp = edid->framebuffer_bits_per_pixel / 8;
152 u32 width = edid->mode.ha;
153 u32 height = edid->mode.va;
154 u32 vrefresh = edid->mode.refresh;
155
156 printk(BIOS_DEBUG, "%s: display resolution: %dx%d@%d bpp %d\n",
157 __func__, width, height, vrefresh, bpp);
158
159 if (!vrefresh) {
160 if (!width || !height)
161 vrefresh = 60;
162 else
163 vrefresh = edid->mode.pixel_clock * 1000 /
164 ((width + edid->mode.hbl) *
165 (height + edid->mode.vbl));
166
167 printk(BIOS_WARNING, "%s: vrefresh is not provided; using %d\n",
168 __func__, vrefresh);
169 }
170
171 main_disp_path_setup(width, height, vrefresh, path);
172 rdma_start();
173 ovl_layer_config(fmt, bpp, width, height);
174 }
175