xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_panel.c (revision d5f538dc02e53c7267fcd4a914104071fca889b5)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <config.h>
8 #include <common.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <video.h>
12 #include <backlight.h>
13 #include <asm/gpio.h>
14 #include <dm/device.h>
15 #include <dm/read.h>
16 #include <dm/uclass.h>
17 #include <dm/uclass-id.h>
18 #include <linux/media-bus-format.h>
19 #include <power/regulator.h>
20 
21 #include "rockchip_display.h"
22 #include "rockchip_crtc.h"
23 #include "rockchip_connector.h"
24 #include "rockchip_mipi_dsi.h"
25 #include "rockchip_panel.h"
26 
27 struct rockchip_cmd_header {
28 	u8 data_type;
29 	u8 delay_ms;
30 	u8 payload_length;
31 } __packed;
32 
33 struct rockchip_cmd_desc {
34 	struct rockchip_cmd_header header;
35 	const u8 *payload;
36 };
37 
38 struct rockchip_panel_cmds {
39 	struct rockchip_cmd_desc *cmds;
40 	int cmd_cnt;
41 };
42 
43 struct rockchip_panel_plat {
44 	bool power_invert;
45 	u32 bus_format;
46 
47 	struct {
48 		unsigned int prepare;
49 		unsigned int unprepare;
50 		unsigned int enable;
51 		unsigned int disable;
52 		unsigned int reset;
53 		unsigned int init;
54 	} delay;
55 
56 	struct rockchip_panel_cmds *on_cmds;
57 	struct rockchip_panel_cmds *off_cmds;
58 };
59 
60 struct rockchip_panel_priv {
61 	bool prepared;
62 	bool enabled;
63 	struct udevice *power_supply;
64 	struct udevice *backlight;
65 	struct gpio_desc enable_gpio;
66 	struct gpio_desc reset_gpio;
67 
68 	int cmd_type;
69 	struct gpio_desc spi_sdi_gpio;
70 	struct gpio_desc spi_scl_gpio;
71 	struct gpio_desc spi_cs_gpio;
72 };
73 
74 static inline int get_panel_cmd_type(const char *s)
75 {
76 	if (!s)
77 		return -EINVAL;
78 
79 	if (strncmp(s, "spi", 3) == 0)
80 		return CMD_TYPE_SPI;
81 	else if (strncmp(s, "mcu", 3) == 0)
82 		return CMD_TYPE_MCU;
83 
84 	return CMD_TYPE_DEFAULT;
85 }
86 
87 static int rockchip_panel_parse_cmds(const u8 *data, int length,
88 				     struct rockchip_panel_cmds *pcmds)
89 {
90 	int len;
91 	const u8 *buf;
92 	const struct rockchip_cmd_header *header;
93 	int i, cnt = 0;
94 
95 	/* scan commands */
96 	cnt = 0;
97 	buf = data;
98 	len = length;
99 	while (len > sizeof(*header)) {
100 		header = (const struct rockchip_cmd_header *)buf;
101 		buf += sizeof(*header) + header->payload_length;
102 		len -= sizeof(*header) + header->payload_length;
103 		cnt++;
104 	}
105 
106 	pcmds->cmds = calloc(cnt, sizeof(struct rockchip_cmd_desc));
107 	if (!pcmds->cmds)
108 		return -ENOMEM;
109 
110 	pcmds->cmd_cnt = cnt;
111 
112 	buf = data;
113 	len = length;
114 	for (i = 0; i < cnt; i++) {
115 		struct rockchip_cmd_desc *desc = &pcmds->cmds[i];
116 
117 		header = (const struct rockchip_cmd_header *)buf;
118 		length -= sizeof(*header);
119 		buf += sizeof(*header);
120 		desc->header.data_type = header->data_type;
121 		desc->header.delay_ms = header->delay_ms;
122 		desc->header.payload_length = header->payload_length;
123 		desc->payload = buf;
124 		buf += header->payload_length;
125 		length -= header->payload_length;
126 	}
127 
128 	return 0;
129 }
130 
131 static void rockchip_panel_write_spi_cmds(struct rockchip_panel_priv *priv,
132 					  u8 type, int value)
133 {
134 	int i;
135 
136 	dm_gpio_set_value(&priv->spi_cs_gpio, 0);
137 
138 	if (type == 0)
139 		value &= (~(1 << 8));
140 	else
141 		value |= (1 << 8);
142 
143 	for (i = 0; i < 9; i++) {
144 		if (value & 0x100)
145 			dm_gpio_set_value(&priv->spi_sdi_gpio, 1);
146 		else
147 			dm_gpio_set_value(&priv->spi_sdi_gpio, 0);
148 
149 		dm_gpio_set_value(&priv->spi_scl_gpio, 0);
150 		udelay(10);
151 		dm_gpio_set_value(&priv->spi_scl_gpio, 1);
152 		value <<= 1;
153 		udelay(10);
154 	}
155 
156 	dm_gpio_set_value(&priv->spi_cs_gpio, 1);
157 }
158 
159 static int rockchip_panel_send_spi_cmds(struct display_state *state,
160 					struct rockchip_panel_cmds *cmds)
161 {
162 	struct panel_state *panel_state = &state->panel_state;
163 	struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
164 	int i;
165 
166 	if (!cmds)
167 		return -EINVAL;
168 
169 	for (i = 0; i < cmds->cmd_cnt; i++) {
170 		struct rockchip_cmd_desc *desc = &cmds->cmds[i];
171 		int value = 0;
172 
173 		if (desc->header.payload_length == 2)
174 			value = (desc->payload[0] << 8) | desc->payload[1];
175 		else
176 			value = desc->payload[0];
177 		rockchip_panel_write_spi_cmds(priv,
178 					      desc->header.data_type, value);
179 
180 		if (desc->header.delay_ms)
181 			mdelay(desc->header.delay_ms);
182 	}
183 
184 	return 0;
185 }
186 
187 static int rockchip_panel_send_dsi_cmds(struct display_state *state,
188 					struct rockchip_panel_cmds *cmds)
189 {
190 	int i, ret;
191 
192 	if (!cmds)
193 		return -EINVAL;
194 
195 	for (i = 0; i < cmds->cmd_cnt; i++) {
196 		struct rockchip_cmd_desc *desc = &cmds->cmds[i];
197 
198 		switch (desc->header.data_type) {
199 		case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
200 		case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
201 		case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
202 		case MIPI_DSI_GENERIC_LONG_WRITE:
203 			ret = mipi_dsi_generic_write(state, desc->payload,
204 						     desc->header.payload_length);
205 			break;
206 		case MIPI_DSI_DCS_SHORT_WRITE:
207 		case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
208 		case MIPI_DSI_DCS_LONG_WRITE:
209 			ret = mipi_dsi_dcs_write(state, desc->payload,
210 						 desc->header.payload_length);
211 			break;
212 		default:
213 			printf("unsupport command data type: %d\n",
214 			       desc->header.data_type);
215 			return -EINVAL;
216 		}
217 
218 		if (ret) {
219 			printf("failed to write cmd%d: %d\n", i, ret);
220 			return ret;
221 		}
222 
223 		if (desc->header.delay_ms)
224 			mdelay(desc->header.delay_ms);
225 	}
226 
227 	return 0;
228 }
229 
230 static int rockchip_panel_prepare(struct display_state *state)
231 {
232 	struct panel_state *panel_state = &state->panel_state;
233 	struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
234 	struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
235 	int ret;
236 
237 	if (priv->prepared)
238 		return 0;
239 
240 	if (priv->power_supply) {
241 		ret = regulator_set_enable(priv->power_supply,
242 					   !plat->power_invert);
243 		if (ret) {
244 			printf("%s: failed to enable power supply", __func__);
245 			return ret;
246 		}
247 	}
248 
249 	dm_gpio_set_value(&priv->enable_gpio, 1);
250 	mdelay(plat->delay.prepare);
251 
252 	dm_gpio_set_value(&priv->reset_gpio, 1);
253 	mdelay(plat->delay.reset);
254 	dm_gpio_set_value(&priv->reset_gpio, 0);
255 
256 	mdelay(plat->delay.init);
257 
258 	if (plat->on_cmds) {
259 		if (priv->cmd_type == CMD_TYPE_SPI)
260 			ret = rockchip_panel_send_spi_cmds(state,
261 							   plat->on_cmds);
262 		else
263 			ret = rockchip_panel_send_dsi_cmds(state,
264 							   plat->on_cmds);
265 		if (ret)
266 			printf("failed to send on cmds: %d\n", ret);
267 	}
268 
269 	priv->prepared = true;
270 
271 	return 0;
272 }
273 
274 static void rockchip_panel_unprepare(struct display_state *state)
275 {
276 	struct panel_state *panel_state = &state->panel_state;
277 	struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
278 	struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
279 	int ret;
280 
281 	if (!priv->prepared)
282 		return;
283 
284 	if (plat->off_cmds) {
285 		if (priv->cmd_type == CMD_TYPE_SPI)
286 			ret = rockchip_panel_send_spi_cmds(state,
287 							   plat->off_cmds);
288 		else
289 			ret = rockchip_panel_send_dsi_cmds(state,
290 							   plat->off_cmds);
291 		if (ret)
292 			printf("failed to send off cmds: %d\n", ret);
293 	}
294 
295 	dm_gpio_set_value(&priv->reset_gpio, 1);
296 	dm_gpio_set_value(&priv->enable_gpio, 0);
297 
298 	if (priv->power_supply) {
299 		ret = regulator_set_enable(priv->power_supply,
300 					   plat->power_invert);
301 		if (ret)
302 			printf("%s: failed to disable power supply", __func__);
303 	}
304 
305 	mdelay(plat->delay.unprepare);
306 
307 	priv->prepared = false;
308 }
309 
310 static int rockchip_panel_enable(struct display_state *state)
311 {
312 	struct panel_state *panel_state = &state->panel_state;
313 	struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
314 	struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
315 
316 	if (priv->enabled)
317 		return 0;
318 
319 	mdelay(plat->delay.enable);
320 
321 	if (priv->backlight)
322 		backlight_enable(priv->backlight);
323 
324 	priv->enabled = true;
325 
326 	return 0;
327 }
328 
329 static void rockchip_panel_disable(struct display_state *state)
330 {
331 	struct panel_state *panel_state = &state->panel_state;
332 	struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
333 	struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
334 
335 	if (!priv->enabled)
336 		return;
337 
338 	if (priv->backlight)
339 		backlight_disable(priv->backlight);
340 
341 	mdelay(plat->delay.disable);
342 
343 	priv->enabled = false;
344 }
345 
346 static int rockchip_panel_init(struct display_state *state)
347 {
348 	struct connector_state *conn_state = &state->conn_state;
349 	struct panel_state *panel_state = &state->panel_state;
350 	struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
351 
352 	conn_state->bus_format = plat->bus_format;
353 
354 	return 0;
355 }
356 
357 static const struct rockchip_panel_funcs rockchip_panel_funcs = {
358 	.init = rockchip_panel_init,
359 	.prepare = rockchip_panel_prepare,
360 	.unprepare = rockchip_panel_unprepare,
361 	.enable = rockchip_panel_enable,
362 	.disable = rockchip_panel_disable,
363 };
364 
365 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
366 {
367 	struct rockchip_panel_plat *plat = dev_get_platdata(dev);
368 	const void *data;
369 	int len = 0;
370 	int ret;
371 
372 	plat->power_invert = dev_read_bool(dev, "power-invert");
373 
374 	plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0);
375 	plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0);
376 	plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0);
377 	plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0);
378 	plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0);
379 	plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0);
380 
381 	plat->bus_format = dev_read_u32_default(dev, "bus-format",
382 						MEDIA_BUS_FMT_RBG888_1X24);
383 
384 	data = dev_read_prop(dev, "panel-init-sequence", &len);
385 	if (data) {
386 		plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
387 		if (!plat->on_cmds)
388 			return -ENOMEM;
389 
390 		ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds);
391 		if (ret) {
392 			printf("failed to parse panel init sequence\n");
393 			goto free_on_cmds;
394 		}
395 	}
396 
397 	data = dev_read_prop(dev, "panel-exit-sequence", &len);
398 	if (data) {
399 		plat->off_cmds = calloc(1, sizeof(*plat->off_cmds));
400 		if (!plat->off_cmds) {
401 			ret = -ENOMEM;
402 			goto free_on_cmds;
403 		}
404 
405 		ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds);
406 		if (ret) {
407 			printf("failed to parse panel exit sequence\n");
408 			goto free_cmds;
409 		}
410 	}
411 
412 	return 0;
413 
414 free_cmds:
415 	free(plat->off_cmds);
416 free_on_cmds:
417 	free(plat->on_cmds);
418 	return ret;
419 }
420 
421 static int rockchip_panel_probe(struct udevice *dev)
422 {
423 	struct rockchip_panel_priv *priv = dev_get_priv(dev);
424 	int ret;
425 	const char *cmd_type;
426 
427 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
428 				   &priv->enable_gpio, GPIOD_IS_OUT);
429 	if (ret && ret != -ENOENT) {
430 		printf("%s: Cannot get enable GPIO: %d\n", __func__, ret);
431 		return ret;
432 	}
433 
434 	ret = gpio_request_by_name(dev, "reset-gpios", 0,
435 				   &priv->reset_gpio, GPIOD_IS_OUT);
436 	if (ret && ret != -ENOENT) {
437 		printf("%s: Cannot get reset GPIO: %d\n", __func__, ret);
438 		return ret;
439 	}
440 
441 	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
442 					   "backlight", &priv->backlight);
443 	if (ret && ret != -ENOENT) {
444 		printf("%s: Cannot get backlight: %d\n", __func__, ret);
445 		return ret;
446 	}
447 
448 	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
449 					   "power-supply", &priv->power_supply);
450 	if (ret && ret != -ENOENT) {
451 		printf("%s: Cannot get power supply: %d\n", __func__, ret);
452 		return ret;
453 	}
454 
455 	ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type);
456 	if (ret)
457 		priv->cmd_type = CMD_TYPE_DEFAULT;
458 	else
459 		priv->cmd_type = get_panel_cmd_type(cmd_type);
460 
461 	if (priv->cmd_type == CMD_TYPE_SPI) {
462 		ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0,
463 					   &priv->spi_sdi_gpio, GPIOD_IS_OUT);
464 		if (ret && ret != -ENOENT) {
465 			printf("%s: Cannot get spi sdi GPIO: %d\n",
466 			       __func__, ret);
467 			return ret;
468 		}
469 		ret = gpio_request_by_name(dev, "spi-scl-gpios", 0,
470 					   &priv->spi_scl_gpio, GPIOD_IS_OUT);
471 		if (ret && ret != -ENOENT) {
472 			printf("%s: Cannot get spi scl GPIO: %d\n",
473 			       __func__, ret);
474 			return ret;
475 		}
476 		ret = gpio_request_by_name(dev, "spi-cs-gpios", 0,
477 					   &priv->spi_cs_gpio, GPIOD_IS_OUT);
478 		if (ret && ret != -ENOENT) {
479 			printf("%s: Cannot get spi cs GPIO: %d\n",
480 			       __func__, ret);
481 			return ret;
482 		}
483 		dm_gpio_set_value(&priv->spi_sdi_gpio, 1);
484 		dm_gpio_set_value(&priv->spi_scl_gpio, 1);
485 		dm_gpio_set_value(&priv->spi_cs_gpio, 1);
486 		dm_gpio_set_value(&priv->reset_gpio, 0);
487 	}
488 
489 	return 0;
490 }
491 
492 static const struct drm_display_mode auo_b125han03_mode = {
493 	.clock = 146900,
494 	.hdisplay = 1920,
495 	.hsync_start = 1920 + 48,
496 	.hsync_end = 1920 + 48 + 32,
497 	.htotal = 1920 + 48 + 32 + 140,
498 	.vdisplay = 1080,
499 	.vsync_start = 1080 + 2,
500 	.vsync_end = 1080 + 2 + 5,
501 	.vtotal = 1080 + 2 + 5 + 57,
502 	.vrefresh = 60,
503 	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
504 };
505 
506 static const struct rockchip_panel auo_b125han03_data = {
507 	.funcs = &rockchip_panel_funcs,
508 	.data = &auo_b125han03_mode,
509 };
510 
511 static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
512 	.clock = 200000,
513 	.hdisplay = 1536,
514 	.hsync_start = 1536 + 12,
515 	.hsync_end = 1536 + 12 + 16,
516 	.htotal = 1536 + 12 + 16 + 48,
517 	.vdisplay = 2048,
518 	.vsync_start = 2048 + 8,
519 	.vsync_end = 2048 + 8 + 4,
520 	.vtotal = 2048 + 8 + 4 + 8,
521 	.vrefresh = 60,
522 	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
523 };
524 
525 static const struct rockchip_panel lg_lp079qx1_sp0v_data = {
526 	.funcs = &rockchip_panel_funcs,
527 	.data = &lg_lp079qx1_sp0v_mode,
528 };
529 
530 static const struct rockchip_panel rockchip_panel_data = {
531 	.funcs = &rockchip_panel_funcs,
532 };
533 
534 static const struct udevice_id rockchip_panel_ids[] = {
535 	{
536 		.compatible = "auo,b125han03",
537 		.data = (ulong)&auo_b125han03_data,
538 	}, {
539 		.compatible = "lg,lp079qx1-sp0v",
540 		.data = (ulong)&lg_lp079qx1_sp0v_data,
541 	}, {
542 		.compatible = "simple-panel",
543 		.data = (ulong)&rockchip_panel_data,
544 	}, {
545 		.compatible = "simple-panel-dsi",
546 		.data = (ulong)&rockchip_panel_data,
547 	},
548 	{}
549 };
550 
551 U_BOOT_DRIVER(rockchip_panel) = {
552 	.name = "rockchip_panel",
553 	.id = UCLASS_PANEL,
554 	.of_match = rockchip_panel_ids,
555 	.ofdata_to_platdata = rockchip_panel_ofdata_to_platdata,
556 	.probe = rockchip_panel_probe,
557 	.priv_auto_alloc_size = sizeof(struct rockchip_panel_priv),
558 	.platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat),
559 };
560