xref: /aosp_15_r20/external/coreboot/src/soc/qualcomm/sc7180/display/dsi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <mipi/dsi.h>
4 #include <mipi/panel.h>
5 #include <device/mmio.h>
6 #include <console/console.h>
7 #include <assert.h>
8 #include <edid.h>
9 #include <delay.h>
10 #include <symbols.h>
11 #include <types.h>
12 #include <string.h>
13 #include <soc/display/mipi_dsi.h>
14 #include <soc/display/mdssreg.h>
15 #include <soc/display/dsi_phy.h>
16 
17 #define DSI_DMA_STREAM1 0x0
18 #define DSI_EMBED_MODE1 0x1
19 #define DSI_POWER_MODE2 0x1
20 #define DSI_PACK_TYPE1 0x0
21 #define DSI_VC1 0x0
22 #define DSI_DT1 0x0
23 #define DSI_WC1 0x0
24 #define DSI_EOF_BLLP_PWR 0x9
25 #define DSI_DMA_TRIGGER_SEL 0x4
26 #define TRAFFIC_MODE 0x1
27 
28 #define DSI_EN 0x1
29 #define DSI_CLKLN_EN 0x1
30 #define DSI_VIDEO_EN 0x1
31 
32 #define HS_TX_TO 0xEA60
33 #define TIMER_RESOLUTION 0x4
34 #define DSI_PAYLOAD_BYTE_BOUND 256
35 #define DSI_PAYLOAD_SIZE_ALIGN 4
36 #define DSI_CMD_DMA_TPG_EN  BIT(1)
37 #define DSI_TPG_DMA_FIFO_MODE BIT(2)
38 #define DSI_CMD_DMA_PATTERN_SEL (BIT(16) | BIT(17))
39 
mdss_dsi_host_init(int num_of_lanes)40 static void mdss_dsi_host_init(int num_of_lanes)
41 {
42 	uint8_t dlnx_en;
43 	uint32_t ctrl_mode = BIT(8) | BIT(0); /* Enable DSI and CLKlane. */
44 
45 	switch (num_of_lanes) {
46 	default:
47 	case 1:
48 		dlnx_en = 1;
49 		break;
50 
51 	case 2:
52 		dlnx_en = 3;
53 		break;
54 
55 	case 3:
56 		dlnx_en = 7;
57 		break;
58 
59 	case 4:
60 		dlnx_en = 0x0F;
61 		break;
62 	}
63 
64 	/*
65 	 * Need to send pixel data before sending the ON commands
66 	 * so need to configure controller to VIDEO MODE.
67 	 */
68 	ctrl_mode |= BIT(1);
69 
70 	mdss_dsi_clock_config();
71 	write32(&dsi0->trig_ctrl, DSI_DMA_STREAM1 << 8 | DSI_DMA_TRIGGER_SEL);
72 	write32(&dsi0->ctrl, dlnx_en << 4 | ctrl_mode);
73 	write32(&dsi0->cmd_mode_dma_ctrl,
74 		DSI_EMBED_MODE1 << 28 | DSI_POWER_MODE2 << 26 |
75 		DSI_PACK_TYPE1 << 24 | DSI_VC1 << 22 | DSI_DT1 << 16 | DSI_WC1);
76 	write32(&dsi0->eot_packet_ctrl, 0x1);
77 }
78 
mdss_dsi_reset(void)79 static void mdss_dsi_reset(void)
80 {
81 	/*
82 	 * Disable DSI Controller, DSI lane states,
83 	 * DSI command-mode and DSI video-mode engines
84 	 */
85 	write32(&dsi0->ctrl, 0x0);
86 
87 	/* DSI soft reset */
88 	write32(&dsi0->soft_reset, 0x1);
89 	write32(&dsi0->soft_reset, 0x0);
90 
91 	/* set hs timer count speed */
92 	write32(&dsi0->hs_timer_ctrl, HS_TX_TO | TIMER_RESOLUTION << 16);
93 
94 	/* dma fifo reset */
95 	write32(&dsi0->tpg_dma_fifo_reset, 0x1);
96 	write32(&dsi0->tpg_dma_fifo_reset, 0x0);
97 }
98 
mdss_dsi_video_mode_config(struct edid * edid,uint32_t bpp)99 void mdss_dsi_video_mode_config(struct edid *edid, uint32_t bpp)
100 {
101 	uint16_t dst_format;
102 	uint8_t lane_en = 15; /* Enable 4 lanes by default */
103 
104 	switch (bpp) {
105 	case 16:
106 		dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
107 		break;
108 	case 18:
109 		dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
110 		break;
111 	case 24:
112 	default:
113 		dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
114 		break;
115 	}
116 
117 	write32(&dsi0->video_mode_active_h,
118 		((edid->mode.ha + edid->mode.hbl - edid->mode.hso) << 16) |
119 		 (edid->mode.hbl - edid->mode.hso));
120 
121 	write32(&dsi0->video_mode_active_v,
122 		((edid->mode.va + edid->mode.vbl - edid->mode.vso) << 16) |
123 		 (edid->mode.vbl - edid->mode.vso));
124 
125 	write32(&dsi0->video_mode_active_total,
126 		((edid->mode.va + edid->mode.vbl - 1) << 16) |
127 		 (edid->mode.ha + edid->mode.hbl - 1));
128 
129 	write32(&dsi0->video_mode_active_hsync, (edid->mode.hspw << 16));
130 	write32(&dsi0->video_mode_active_vsync, 0x0);
131 	write32(&dsi0->video_mode_active_vsync_vpos, edid->mode.vspw << 16);
132 
133 	write32(&dsi0->video_mode_ctrl,
134 			DSI_EOF_BLLP_PWR << 12 | dst_format << 4 | TRAFFIC_MODE << 8);
135 
136 	write32(&dsi0->hs_timer_ctrl, HS_TX_TO | TIMER_RESOLUTION << 16);
137 
138 	write32(&dsi0->ctrl, lane_en << 4 | DSI_VIDEO_EN << 1 | DSI_EN | DSI_CLKLN_EN << 8);
139 }
140 
mdss_dsi_config(struct edid * edid,uint32_t num_of_lanes,uint32_t bpp)141 enum cb_err mdss_dsi_config(struct edid *edid, uint32_t num_of_lanes, uint32_t bpp)
142 {
143 	mdss_dsi_reset();
144 	if ((mdss_dsi_phy_10nm_init(edid, num_of_lanes, bpp)) != 0) {
145 		printk(BIOS_ERR, "dsi phy setup returned error\n");
146 		return CB_ERR;
147 	}
148 
149 	mdss_dsi_host_init(num_of_lanes);
150 
151 	return CB_SUCCESS;
152 }
153 
mdss_dsi_clock_config(void)154 void mdss_dsi_clock_config(void)
155 {
156 	/* Clock for AHI Bus Master, for DMA out from memory */
157 	write32(&dsi0->clk_ctrl, 0);
158 	setbits32(&dsi0->clk_ctrl, DSI_AHBM_SCLK_ON | DSI_FORCE_ON_DYN_AHBM_HCLK);
159 
160 	/* Clock for MDP/DSI, for DMA out from MDP */
161 	setbits32(&dsi0->clk_ctrl, DSI_PCLK_ON);
162 
163 	/* Clock for rest of DSI */
164 	setbits32(&dsi0->clk_ctrl, DSI_AHBS_HCLK_ON | DSI_DSICLK_ON |
165 		  DSI_BYTECLK_ON | DSI_ESCCLK_ON);
166 }
167 
mdss_dsi_set_intr(void)168 static void mdss_dsi_set_intr(void)
169 {
170 	write32(&dsi0->int_ctrl, 0x0);
171 
172 	/* Enable all HW interrupts. */
173 	setbits32(&dsi0->int_ctrl, DSI_CMD_MODE_DMA_DONE_MASK | DSI_CMD_MODE_MDP_DONE_MASK |
174 			DSI_VIDEO_MODE_DONE_MASK | DSI_ERROR_MASK | DSI_BTA_DONE_MASK);
175 }
176 
mdss_dsi_cmd_dma_trigger_for_panel(void)177 static int mdss_dsi_cmd_dma_trigger_for_panel(void)
178 {
179 	uint32_t read_value;
180 	uint32_t count = 0;
181 	int status = 0;
182 
183 	mdss_dsi_set_intr();
184 	write32(&dsi0->cmd_mode_dma_sw_trigger, 0x1);
185 	dsb();
186 
187 	read_value = read32(&dsi0->int_ctrl) & 0x1;
188 
189 	while (read_value != 0x1) {
190 		read_value = read32(&dsi0->int_ctrl) & 0x1;
191 		count++;
192 		if (count > 0xffff) {
193 			status = -1;
194 			printk(BIOS_ERR,
195 				"Panel CMD: count :%d command mode dma test failed\n", count);
196 			printk(BIOS_ERR,
197 			       "Panel CMD: read value = %x, addr=%p\n",
198 			       read_value, (&dsi0->int_ctrl));
199 			return status;
200 		}
201 	}
202 
203 	write32(&dsi0->int_ctrl, (read32(&dsi0->int_ctrl) | 0x01000001));
204 	return status;
205 }
206 
mdss_dsi_send_init_cmd(enum mipi_dsi_transaction type,const u8 * body,u8 len)207 static enum cb_err mdss_dsi_send_init_cmd(enum mipi_dsi_transaction type, const u8 *body,
208 					  u8 len)
209 {
210 	uint8_t *pload = _dma_coherent;
211 	uint32_t size;
212 	enum cb_err ret = CB_SUCCESS;
213 	int data = 0;
214 	uint32_t *bp = NULL;
215 
216 	if (len > 2) {
217 		pload[0] = len;
218 		pload[1] = 0;
219 		pload[2] = type;
220 		pload[3] = BIT(7) | BIT(6);
221 
222 		/* The payload size has to be a multiple of 4 */
223 		memcpy(pload + 4, body, len);
224 		size = ALIGN_UP(len + 4, DSI_PAYLOAD_SIZE_ALIGN);
225 		memset(pload + 4 + len, 0, size - 4 - len);
226 		assert(size < DSI_PAYLOAD_BYTE_BOUND);
227 	} else {
228 		pload[0] = body[0];
229 		pload[1] = len > 1 ? body[1] : 0;
230 		pload[2] = type;
231 		pload[3] = BIT(7);
232 		size = 4;
233 	}
234 
235 	bp = (uint32_t *)pload;
236 
237 	/* Enable custom pattern stored in TPG DMA FIFO */
238 	data = DSI_CMD_DMA_PATTERN_SEL;
239 
240 	/* select CMD_DMA_FIFO_MODE to 1 */
241 	data |= DSI_TPG_DMA_FIFO_MODE;
242 	data |= DSI_CMD_DMA_TPG_EN;
243 
244 	write32(&dsi0->test_pattern_gen_ctrl, data);
245 	for (int j = 0; j < size; j += 4) {
246 		write32(&dsi0->test_pattern_gen_cmd_dma_init_val, *bp);
247 		bp++;
248 	}
249 
250 	if ((size % 8) != 0)
251 		write32(&dsi0->test_pattern_gen_cmd_dma_init_val, 0x0);
252 
253 	write32(&dsi0->dma_cmd_length, size);
254 	write32(&dsi0->cmd_mode_dma_sw_trigger, 0x1);
255 	if (mdss_dsi_cmd_dma_trigger_for_panel())
256 		ret = CB_ERR;
257 
258 	/* Reset the DMA TPG FIFO */
259 	write32(&dsi0->tpg_dma_fifo_reset, 0x1);
260 	write32(&dsi0->tpg_dma_fifo_reset, 0x0);
261 
262 	/* Disable CMD_DMA_TPG */
263 	write32(&dsi0->test_pattern_gen_ctrl, 0x0);
264 
265 	udelay(80);
266 
267 	return ret;
268 }
269 
mdss_dsi_clear_intr(void)270 static void mdss_dsi_clear_intr(void)
271 {
272 	write32(&dsi0->int_ctrl, 0x0);
273 
274 	/* Clear all the hardware interrupts */
275 	setbits32(&dsi0->int_ctrl, DSI_CMD_MODE_DMA_DONE_AK | DSI_CMD_MODE_MDP_DONE_AK |
276 			DSI_VIDEO_MODE_DONE_AK |  DSI_BTA_DONE_AK | DSI_ERROR_AK);
277 	write32(&dsi0->err_int_mask0, 0x13FF3BFF);
278 }
279 
mdss_dsi_panel_initialize(const u8 * init_cmds)280 enum cb_err mdss_dsi_panel_initialize(const u8 *init_cmds)
281 {
282 	uint32_t ctrl_mode = 0;
283 
284 	assert(init_cmds != NULL);
285 	ctrl_mode = read32(&dsi0->ctrl);
286 
287 	/* Enable command mode before sending the commands */
288 	write32(&dsi0->ctrl, ctrl_mode | 0x04);
289 
290 	enum cb_err ret = mipi_panel_parse_init_commands(init_cmds, mdss_dsi_send_init_cmd);
291 	write32(&dsi0->ctrl, ctrl_mode);
292 	mdss_dsi_clear_intr();
293 
294 	return ret;
295 }
296