xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_panel.c (revision 514e00a960f8a815e0c86931b498063c6fc4ef76)
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 	struct drm_dsc_picture_parameter_set *pps = NULL;
218 
219 	if (!cmds)
220 		return -EINVAL;
221 
222 	for (i = 0; i < cmds->cmd_cnt; i++) {
223 		struct rockchip_cmd_desc *desc = &cmds->cmds[i];
224 		const struct rockchip_cmd_header *header = &desc->header;
225 
226 		switch (header->data_type) {
227 		case MIPI_DSI_COMPRESSION_MODE:
228 			ret = mipi_dsi_compression_mode(dsi, desc->payload[0]);
229 			break;
230 		case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
231 		case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
232 		case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
233 		case MIPI_DSI_GENERIC_LONG_WRITE:
234 			ret = mipi_dsi_generic_write(dsi, desc->payload,
235 						     header->payload_length);
236 			break;
237 		case MIPI_DSI_DCS_SHORT_WRITE:
238 		case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
239 		case MIPI_DSI_DCS_LONG_WRITE:
240 			ret = mipi_dsi_dcs_write_buffer(dsi, desc->payload,
241 							header->payload_length);
242 			break;
243 		case MIPI_DSI_PICTURE_PARAMETER_SET:
244 			pps = kzalloc(sizeof(*pps), GFP_KERNEL);
245 			if (!pps)
246 				return -ENOMEM;
247 
248 			memcpy(pps, desc->payload, header->payload_length);
249 			ret = mipi_dsi_picture_parameter_set(dsi, pps);
250 			kfree(pps);
251 			break;
252 		default:
253 			printf("unsupport command data type: %d\n",
254 			       header->data_type);
255 			return -EINVAL;
256 		}
257 
258 		if (ret < 0) {
259 			printf("failed to write cmd%d: %d\n", i, ret);
260 			return ret;
261 		}
262 
263 		if (header->delay_ms)
264 			mdelay(header->delay_ms);
265 	}
266 
267 	return 0;
268 }
269 
270 static void panel_simple_prepare(struct rockchip_panel *panel)
271 {
272 	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
273 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
274 	struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev);
275 	int ret;
276 
277 	if (priv->prepared)
278 		return;
279 
280 	if (priv->power_supply)
281 		regulator_set_enable(priv->power_supply, !plat->power_invert);
282 
283 	if (dm_gpio_is_valid(&priv->enable_gpio))
284 		dm_gpio_set_value(&priv->enable_gpio, 1);
285 
286 	if (plat->delay.prepare)
287 		mdelay(plat->delay.prepare);
288 
289 	if (dm_gpio_is_valid(&priv->reset_gpio))
290 		dm_gpio_set_value(&priv->reset_gpio, 1);
291 
292 	if (plat->delay.reset)
293 		mdelay(plat->delay.reset);
294 
295 	if (dm_gpio_is_valid(&priv->reset_gpio))
296 		dm_gpio_set_value(&priv->reset_gpio, 0);
297 
298 	if (plat->delay.init)
299 		mdelay(plat->delay.init);
300 
301 	if (plat->on_cmds) {
302 		if (priv->cmd_type == CMD_TYPE_SPI)
303 			ret = rockchip_panel_send_spi_cmds(panel->state,
304 							   plat->on_cmds);
305 		else if (priv->cmd_type == CMD_TYPE_MCU)
306 			ret = rockchip_panel_send_mcu_cmds(panel->state,
307 							   plat->on_cmds);
308 		else
309 			ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds);
310 		if (ret)
311 			printf("failed to send on cmds: %d\n", ret);
312 	}
313 
314 	priv->prepared = true;
315 }
316 
317 static void panel_simple_unprepare(struct rockchip_panel *panel)
318 {
319 	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
320 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
321 	struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev);
322 	int ret;
323 
324 	if (!priv->prepared)
325 		return;
326 
327 	if (plat->off_cmds) {
328 		if (priv->cmd_type == CMD_TYPE_SPI)
329 			ret = rockchip_panel_send_spi_cmds(panel->state,
330 							   plat->off_cmds);
331 		else if (priv->cmd_type == CMD_TYPE_MCU)
332 			ret = rockchip_panel_send_mcu_cmds(panel->state,
333 							   plat->off_cmds);
334 		else
335 			ret = rockchip_panel_send_dsi_cmds(dsi, plat->off_cmds);
336 		if (ret)
337 			printf("failed to send off cmds: %d\n", ret);
338 	}
339 
340 	if (dm_gpio_is_valid(&priv->reset_gpio))
341 		dm_gpio_set_value(&priv->reset_gpio, 1);
342 
343 	if (dm_gpio_is_valid(&priv->enable_gpio))
344 		dm_gpio_set_value(&priv->enable_gpio, 0);
345 
346 	if (priv->power_supply)
347 		regulator_set_enable(priv->power_supply, plat->power_invert);
348 
349 	if (plat->delay.unprepare)
350 		mdelay(plat->delay.unprepare);
351 
352 	priv->prepared = false;
353 }
354 
355 static void panel_simple_enable(struct rockchip_panel *panel)
356 {
357 	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
358 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
359 
360 	if (priv->enabled)
361 		return;
362 
363 	if (plat->delay.enable)
364 		mdelay(plat->delay.enable);
365 
366 	if (priv->backlight)
367 		backlight_enable(priv->backlight);
368 
369 	priv->enabled = true;
370 }
371 
372 static void panel_simple_disable(struct rockchip_panel *panel)
373 {
374 	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
375 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
376 
377 	if (!priv->enabled)
378 		return;
379 
380 	if (priv->backlight)
381 		backlight_disable(priv->backlight);
382 
383 	if (plat->delay.disable)
384 		mdelay(plat->delay.disable);
385 
386 	priv->enabled = false;
387 }
388 
389 static void panel_simple_init(struct rockchip_panel *panel)
390 {
391 	struct display_state *state = panel->state;
392 	struct connector_state *conn_state = &state->conn_state;
393 
394 	conn_state->bus_format = panel->bus_format;
395 }
396 
397 static const struct rockchip_panel_funcs rockchip_panel_funcs = {
398 	.init = panel_simple_init,
399 	.prepare = panel_simple_prepare,
400 	.unprepare = panel_simple_unprepare,
401 	.enable = panel_simple_enable,
402 	.disable = panel_simple_disable,
403 };
404 
405 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
406 {
407 	struct rockchip_panel_plat *plat = dev_get_platdata(dev);
408 	const void *data;
409 	int len = 0;
410 	int ret;
411 
412 	plat->power_invert = dev_read_bool(dev, "power-invert");
413 
414 	plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0);
415 	plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0);
416 	plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0);
417 	plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0);
418 	plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0);
419 	plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0);
420 
421 	plat->bus_format = dev_read_u32_default(dev, "bus-format",
422 						MEDIA_BUS_FMT_RBG888_1X24);
423 	plat->bpc = dev_read_u32_default(dev, "bpc", 8);
424 
425 	data = dev_read_prop(dev, "panel-init-sequence", &len);
426 	if (data) {
427 		plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
428 		if (!plat->on_cmds)
429 			return -ENOMEM;
430 
431 		ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds);
432 		if (ret) {
433 			printf("failed to parse panel init sequence\n");
434 			goto free_on_cmds;
435 		}
436 	}
437 
438 	data = dev_read_prop(dev, "panel-exit-sequence", &len);
439 	if (data) {
440 		plat->off_cmds = calloc(1, sizeof(*plat->off_cmds));
441 		if (!plat->off_cmds) {
442 			ret = -ENOMEM;
443 			goto free_on_cmds;
444 		}
445 
446 		ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds);
447 		if (ret) {
448 			printf("failed to parse panel exit sequence\n");
449 			goto free_cmds;
450 		}
451 	}
452 
453 	return 0;
454 
455 free_cmds:
456 	free(plat->off_cmds);
457 free_on_cmds:
458 	free(plat->on_cmds);
459 	return ret;
460 }
461 
462 static int rockchip_panel_probe(struct udevice *dev)
463 {
464 	struct rockchip_panel_priv *priv = dev_get_priv(dev);
465 	struct rockchip_panel_plat *plat = dev_get_platdata(dev);
466 	struct rockchip_panel *panel;
467 	int ret;
468 	const char *cmd_type;
469 
470 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
471 				   &priv->enable_gpio, GPIOD_IS_OUT);
472 	if (ret && ret != -ENOENT) {
473 		printf("%s: Cannot get enable GPIO: %d\n", __func__, ret);
474 		return ret;
475 	}
476 
477 	ret = gpio_request_by_name(dev, "reset-gpios", 0,
478 				   &priv->reset_gpio, GPIOD_IS_OUT);
479 	if (ret && ret != -ENOENT) {
480 		printf("%s: Cannot get reset GPIO: %d\n", __func__, ret);
481 		return ret;
482 	}
483 
484 	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
485 					   "backlight", &priv->backlight);
486 	if (ret && ret != -ENOENT) {
487 		printf("%s: Cannot get backlight: %d\n", __func__, ret);
488 		return ret;
489 	}
490 
491 	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
492 					   "power-supply", &priv->power_supply);
493 	if (ret && ret != -ENOENT) {
494 		printf("%s: Cannot get power supply: %d\n", __func__, ret);
495 		return ret;
496 	}
497 
498 	ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type);
499 	if (ret)
500 		priv->cmd_type = CMD_TYPE_DEFAULT;
501 	else
502 		priv->cmd_type = get_panel_cmd_type(cmd_type);
503 
504 	if (priv->cmd_type == CMD_TYPE_SPI) {
505 		ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0,
506 					   &priv->spi_sdi_gpio, GPIOD_IS_OUT);
507 		if (ret && ret != -ENOENT) {
508 			printf("%s: Cannot get spi sdi GPIO: %d\n",
509 			       __func__, ret);
510 			return ret;
511 		}
512 		ret = gpio_request_by_name(dev, "spi-scl-gpios", 0,
513 					   &priv->spi_scl_gpio, GPIOD_IS_OUT);
514 		if (ret && ret != -ENOENT) {
515 			printf("%s: Cannot get spi scl GPIO: %d\n",
516 			       __func__, ret);
517 			return ret;
518 		}
519 		ret = gpio_request_by_name(dev, "spi-cs-gpios", 0,
520 					   &priv->spi_cs_gpio, GPIOD_IS_OUT);
521 		if (ret && ret != -ENOENT) {
522 			printf("%s: Cannot get spi cs GPIO: %d\n",
523 			       __func__, ret);
524 			return ret;
525 		}
526 		dm_gpio_set_value(&priv->spi_sdi_gpio, 1);
527 		dm_gpio_set_value(&priv->spi_scl_gpio, 1);
528 		dm_gpio_set_value(&priv->spi_cs_gpio, 1);
529 		dm_gpio_set_value(&priv->reset_gpio, 0);
530 	}
531 
532 	panel = calloc(1, sizeof(*panel));
533 	if (!panel)
534 		return -ENOMEM;
535 
536 	dev->driver_data = (ulong)panel;
537 	panel->dev = dev;
538 	panel->bus_format = plat->bus_format;
539 	panel->bpc = plat->bpc;
540 	panel->funcs = &rockchip_panel_funcs;
541 
542 	return 0;
543 }
544 
545 static const struct udevice_id rockchip_panel_ids[] = {
546 	{ .compatible = "simple-panel", },
547 	{ .compatible = "simple-panel-dsi", },
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