• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&regs->size, width << 16 | height);
68 	clrsetbits32(&regs->cfg, PQ_ENGINE_EN, PQ_RELAY_MODE);
69 	write32(&regs->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(&regs->size, width << 16 | height);
77 	write32(&regs->output_size, width << 16 | height);
78 	clrsetbits32(&regs->cfg, PQ_ENGINE_EN, PQ_RELAY_MODE);
79 	write32(&regs->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(&regs->size, width << 16 | height);
87 	setbits32(&regs->cfg, PQ_RELAY_MODE);
88 	write32(&regs->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(&regs->size, width << 16 | height);
96 	setbits32(&regs->cfg, PQ_RELAY_MODE);
97 	write32(&regs->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(&regs->size, width << 16 | height);
105 	setbits32(&regs->cfg, PQ_RELAY_MODE);
106 	write32(&regs->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