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