xref: /rk3399_rockchip-uboot/drivers/video/drm/rk628/panel.c (revision 2f6c020d95ebda22b28d3a31f574ec547a9281fb)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Guochun Huang <hero.huang@rock-chips.com>
6  */
7 
8 #include <drm/drm_mipi_dsi.h>
9 
10 #include <config.h>
11 #include <common.h>
12 #include <errno.h>
13 #include <malloc.h>
14 #include <video.h>
15 #include <backlight.h>
16 #include <spi.h>
17 #include <asm/gpio.h>
18 #include <dm/device.h>
19 #include <dm/read.h>
20 #include <dm/uclass.h>
21 #include <dm/uclass-id.h>
22 #include <linux/media-bus-format.h>
23 #include <power/regulator.h>
24 
25 #include "rk628.h"
26 #include "panel.h"
27 
28 void *kmemdup(const void *src, size_t len, gfp_t gfp)
29 {
30 	void *p;
31 
32 	p = kmalloc(len, gfp);
33 	if (p)
34 		memcpy(p, src, len);
35 	return p;
36 }
37 
38 static int
39 dsi_panel_parse_cmds(const u8 *data, int blen, struct panel_cmds *pcmds)
40 {
41 	unsigned int len;
42 	u8 *buf, *bp;
43 	struct cmd_ctrl_hdr *dchdr;
44 	int i, cnt;
45 
46 	if (!pcmds)
47 		return -EINVAL;
48 
49 	buf = kmemdup(data, blen, GFP_KERNEL);
50 	if (!buf)
51 		return -ENOMEM;
52 
53 	/* scan init commands */
54 	bp = buf;
55 	len = blen;
56 	cnt = 0;
57 	while (len > sizeof(*dchdr)) {
58 		dchdr = (struct cmd_ctrl_hdr *)bp;
59 
60 		if (dchdr->dlen > len) {
61 			pr_err("%s: error, len=%d", __func__, dchdr->dlen);
62 			return -EINVAL;
63 		}
64 
65 		bp += sizeof(*dchdr);
66 		len -= sizeof(*dchdr);
67 		bp += dchdr->dlen;
68 		len -= dchdr->dlen;
69 		cnt++;
70 	}
71 
72 	if (len != 0) {
73 		pr_err("%s: dcs_cmd=%x len=%d error!", __func__, buf[0], blen);
74 		kfree(buf);
75 		return -EINVAL;
76 	}
77 
78 	pcmds->cmds = kcalloc(cnt, sizeof(struct cmd_desc), GFP_KERNEL);
79 	if (!pcmds->cmds) {
80 		kfree(buf);
81 		return -ENOMEM;
82 	}
83 
84 	pcmds->cmd_cnt = cnt;
85 	pcmds->buf = buf;
86 	pcmds->blen = blen;
87 
88 	bp = buf;
89 	len = blen;
90 	for (i = 0; i < cnt; i++) {
91 		dchdr = (struct cmd_ctrl_hdr *)bp;
92 		len -= sizeof(*dchdr);
93 		bp += sizeof(*dchdr);
94 		pcmds->cmds[i].dchdr = *dchdr;
95 		pcmds->cmds[i].payload = bp;
96 		bp += dchdr->dlen;
97 		len -= dchdr->dlen;
98 	}
99 
100 	return 0;
101 }
102 
103 static int dsi_panel_get_cmds(struct rk628 *rk628, ofnode dsi_np)
104 {
105 	ofnode np;
106 	const void *data;
107 	int len;
108 	int ret, err;
109 
110 	np = ofnode_find_subnode(dsi_np, "rk628-panel");
111 	if (!ofnode_valid(np))
112 		return -EINVAL;
113 
114 	data = ofnode_get_property(np, "panel-init-sequence", &len);
115 	if (data) {
116 		rk628->panel->on_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL);
117 		if (!rk628->panel->on_cmds)
118 			return -ENOMEM;
119 
120 		err = dsi_panel_parse_cmds(data, len, rk628->panel->on_cmds);
121 		if (err) {
122 			printf("rk628 failed to parse dsi panel init sequence\n");
123 			ret = err;
124 			goto init_err;
125 		}
126 	}
127 
128 	data = ofnode_get_property(np, "panel-exit-sequence", &len);
129 	if (data) {
130 		rk628->panel->off_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL);
131 		if (!rk628->panel->off_cmds) {
132 			ret = -ENOMEM;
133 			goto on_err;
134 		}
135 
136 		err = dsi_panel_parse_cmds(data, len, rk628->panel->off_cmds);
137 		if (err) {
138 			printf("rk628 failed to parse dsi panel exit sequence\n");
139 			ret = err;
140 			goto exit_err;
141 		}
142 	}
143 
144 	return 0;
145 
146 exit_err:
147 	kfree(rk628->panel->off_cmds);
148 on_err:
149 	kfree(rk628->panel->on_cmds->cmds);
150 	kfree(rk628->panel->on_cmds->buf);
151 init_err:
152 	kfree(rk628->panel->on_cmds);
153 
154 	return ret;
155 }
156 
157 int rk628_panel_info_get(struct rk628 *rk628, ofnode np)
158 {
159 	struct rk628_panel_simple *panel;
160 	struct udevice *dev = rk628->dev;
161 	int ret;
162 
163 	panel = devm_kzalloc(dev, sizeof(struct rk628_panel_simple), GFP_KERNEL);
164 	if (!panel)
165 		return -ENOMEM;
166 
167 	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "panel-power-supply", &panel->supply);
168 	if (ret && ret != -ENOENT) {
169 		printf("rk628 failed to get power supply: %d\n", ret);
170 		return ret;
171 	}
172 
173 	ret = gpio_request_by_name(dev, "panel-enable-gpios", 0,
174 				   &panel->enable_gpio, GPIOD_IS_OUT);
175 	if (ret && ret != -ENOENT) {
176 		printf("%s: Cannot get enable GPIO: %d\n", __func__, ret);
177 		return ret;
178 	}
179 
180 	ret = gpio_request_by_name(dev, "panel-reset-gpios", 0,
181 				   &panel->reset_gpio, GPIOD_IS_OUT);
182 	if (ret && ret != -ENOENT) {
183 		printf("%s: Cannot get reset GPIO: %d\n", __func__, ret);
184 		return ret;
185 	}
186 
187 	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
188 					   "panel-backlight", &panel->backlight);
189 	if (ret && ret != -ENOENT) {
190 		printf("%s: Cannot get backlight: %d\n", __func__, ret);
191 		return ret;
192 	}
193 
194 	panel->delay.prepare = dev_read_u32_default(dev, "panel-prepare-delay-ms", 0);
195 	panel->delay.enable = dev_read_u32_default(dev, "panel-enable-delay-ms", 0);
196 	panel->delay.disable = dev_read_u32_default(dev, "panel-disable-delay-ms", 0);
197 	panel->delay.unprepare = dev_read_u32_default(dev, "panel-unprepare-delay-ms", 0);
198 	panel->delay.reset = dev_read_u32_default(dev, "panel-reset-delay-ms", 0);
199 	panel->delay.init = dev_read_u32_default(dev, "panel-init-delay-ms", 0);
200 
201 	rk628->panel = panel;
202 
203 	if (rk628_output_is_dsi(rk628)) {
204 		ret = dsi_panel_get_cmds(rk628, np);
205 		if (ret) {
206 			dev_err(dev, "failed to get cmds\n");
207 			return ret;
208 		}
209 	}
210 
211 	return 0;
212 }
213 
214 void rk628_panel_prepare(struct rk628 *rk628)
215 {
216 	struct rk628_panel_simple *p = rk628->panel;
217 
218 	if (!p)
219 		return;
220 
221 	if (p->supply)
222 		regulator_set_enable(p->supply, 1);
223 
224 	if (dm_gpio_is_valid(&p->enable_gpio))
225 		dm_gpio_set_value(&p->enable_gpio, 1);
226 
227 	if (p->delay.prepare)
228 		mdelay(p->delay.prepare);
229 
230 	if (dm_gpio_is_valid(&p->reset_gpio))
231 		dm_gpio_set_value(&p->reset_gpio, 1);
232 
233 	if (p->delay.reset)
234 		mdelay(p->delay.reset);
235 
236 	if (dm_gpio_is_valid(&p->reset_gpio))
237 		dm_gpio_set_value(&p->reset_gpio, 0);
238 
239 	if (p->delay.init)
240 		mdelay(p->delay.init);
241 }
242 
243 void rk628_panel_enable(struct rk628 *rk628)
244 {
245 	struct rk628_panel_simple *p = rk628->panel;
246 
247 	if (!p)
248 		return;
249 
250 	if (p->delay.enable)
251 		mdelay(p->delay.enable);
252 
253 
254 	if (p->backlight)
255 		backlight_enable(p->backlight);
256 }
257 
258 void rk628_panel_unprepare(struct rk628 *rk628)
259 {
260 	struct rk628_panel_simple *p = rk628->panel;
261 
262 	if (!p)
263 		return;
264 
265 	if (dm_gpio_is_valid(&p->reset_gpio))
266 		dm_gpio_set_value(&p->reset_gpio, 1);
267 
268 	if (dm_gpio_is_valid(&p->enable_gpio))
269 		dm_gpio_set_value(&p->enable_gpio, 0);
270 
271 	if (rk628->panel->supply)
272 		regulator_set_enable(p->supply, 0);
273 
274 	if (p->delay.unprepare)
275 		mdelay(p->delay.unprepare);
276 }
277 
278 void rk628_panel_disable(struct rk628 *rk628)
279 {
280 	struct rk628_panel_simple *p = rk628->panel;
281 
282 	if (!p)
283 		return;
284 
285 	if (p->backlight)
286 		backlight_disable(p->backlight);
287 
288 	if (p->delay.disable)
289 		mdelay(p->delay.disable);
290 }
291