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