xref: /OK3568_Linux_fs/kernel/drivers/misc/rk628/panel.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 "rk628.h"
9 #include <linux/gpio/consumer.h>
10 #include <linux/backlight.h>
11 
12 #include "panel.h"
13 
14 static int
dsi_panel_parse_cmds(const u8 * data,int blen,struct panel_cmds * pcmds)15 dsi_panel_parse_cmds(const u8 *data, int blen, struct panel_cmds *pcmds)
16 {
17 	unsigned int len;
18 	char *buf, *bp;
19 	struct cmd_ctrl_hdr *dchdr;
20 	int i, cnt;
21 
22 	if (!pcmds)
23 		return -EINVAL;
24 
25 	buf = kmemdup(data, blen, GFP_KERNEL);
26 	if (!buf)
27 		return -ENOMEM;
28 
29 	/* scan init commands */
30 	bp = buf;
31 	len = blen;
32 	cnt = 0;
33 	while (len > sizeof(*dchdr)) {
34 		dchdr = (struct cmd_ctrl_hdr *)bp;
35 
36 		if (dchdr->dlen > len) {
37 			pr_err("%s: error, len=%d", __func__, dchdr->dlen);
38 			return -EINVAL;
39 		}
40 
41 		bp += sizeof(*dchdr);
42 		len -= sizeof(*dchdr);
43 		bp += dchdr->dlen;
44 		len -= dchdr->dlen;
45 		cnt++;
46 	}
47 
48 	if (len != 0) {
49 		pr_err("%s: dcs_cmd=%x len=%d error!", __func__, buf[0], blen);
50 		kfree(buf);
51 		return -EINVAL;
52 	}
53 
54 	pcmds->cmds = kcalloc(cnt, sizeof(struct cmd_desc), GFP_KERNEL);
55 	if (!pcmds->cmds) {
56 		kfree(buf);
57 		return -ENOMEM;
58 	}
59 
60 	pcmds->cmd_cnt = cnt;
61 	pcmds->buf = buf;
62 	pcmds->blen = blen;
63 
64 	bp = buf;
65 	len = blen;
66 	for (i = 0; i < cnt; i++) {
67 		dchdr = (struct cmd_ctrl_hdr *)bp;
68 		len -= sizeof(*dchdr);
69 		bp += sizeof(*dchdr);
70 		pcmds->cmds[i].dchdr = *dchdr;
71 		pcmds->cmds[i].payload = bp;
72 		bp += dchdr->dlen;
73 		len -= dchdr->dlen;
74 	}
75 
76 	return 0;
77 }
78 
dsi_panel_get_cmds(struct rk628 * rk628,struct device_node * dsi_np)79 static int dsi_panel_get_cmds(struct rk628 *rk628, struct device_node *dsi_np)
80 {
81 	struct device_node *np;
82 	const void *data;
83 	int len;
84 	int ret, err;
85 
86 	np = of_find_node_by_name(dsi_np, "rk628-panel");
87 	if (!np)
88 		return -EINVAL;
89 
90 	data = of_get_property(np, "panel-init-sequence", &len);
91 	if (data) {
92 		rk628->panel->on_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL);
93 		if (!rk628->panel->on_cmds)
94 			return -ENOMEM;
95 
96 		err = dsi_panel_parse_cmds(data, len, rk628->panel->on_cmds);
97 		if (err) {
98 			dev_err(rk628->dev, "failed to parse dsi panel init sequence\n");
99 			ret = err;
100 			goto init_err;
101 		}
102 	}
103 
104 	data = of_get_property(np, "panel-exit-sequence", &len);
105 	if (data) {
106 		rk628->panel->off_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL);
107 		if (!rk628->panel->off_cmds) {
108 			ret = -ENOMEM;
109 			goto on_err;
110 		}
111 
112 		err = dsi_panel_parse_cmds(data, len, rk628->panel->off_cmds);
113 		if (err) {
114 			dev_err(rk628->dev, "failed to parse dsi panel exit sequence\n");
115 			ret = err;
116 			goto exit_err;
117 		}
118 	}
119 
120 	return 0;
121 
122 exit_err:
123 	kfree(rk628->panel->off_cmds);
124 on_err:
125 	kfree(rk628->panel->on_cmds->cmds);
126 	kfree(rk628->panel->on_cmds->buf);
127 init_err:
128 	kfree(rk628->panel->on_cmds);
129 
130 	return ret;
131 }
132 
rk628_panel_info_get(struct rk628 * rk628,struct device_node * np)133 int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np)
134 {
135 	struct panel_simple *panel;
136 	struct device *dev = rk628->dev;
137 	struct device_node *backlight;
138 	int ret;
139 
140 	panel = devm_kzalloc(dev, sizeof(struct panel_simple), GFP_KERNEL);
141 	if (!panel)
142 		return -ENOMEM;
143 
144 	panel->supply = devm_regulator_get(dev, "power");
145 	if (IS_ERR(panel->supply)) {
146 		ret = PTR_ERR(panel->supply);
147 		dev_err(dev, "failed to get power regulator: %d\n", ret);
148 		return ret;
149 	}
150 
151 	panel->enable_gpio = devm_gpiod_get_optional(dev, "panel-enable", GPIOD_OUT_LOW);
152 	if (IS_ERR(panel->enable_gpio)) {
153 		ret = PTR_ERR(panel->enable_gpio);
154 		dev_err(dev, "failed to request panel enable GPIO: %d\n", ret);
155 		return ret;
156 	}
157 
158 	panel->reset_gpio = devm_gpiod_get_optional(dev, "panel-reset", GPIOD_OUT_LOW);
159 	if (IS_ERR(panel->reset_gpio)) {
160 		ret = PTR_ERR(panel->reset_gpio);
161 		dev_err(dev, "failed to request panel reset GPIO: %d\n", ret);
162 		return ret;
163 	}
164 
165 	backlight = of_parse_phandle(dev->of_node, "panel-backlight", 0);
166 	if (backlight) {
167 		panel->backlight = of_find_backlight_by_node(backlight);
168 		of_node_put(backlight);
169 
170 		if (!panel->backlight) {
171 			dev_err(dev, "failed to find backlight\n");
172 			return -EPROBE_DEFER;
173 		}
174 
175 	}
176 
177 	rk628->panel = panel;
178 
179 	if (rk628->output_mode == OUTPUT_MODE_DSI) {
180 		ret = dsi_panel_get_cmds(rk628, np);
181 		if (ret) {
182 			dev_err(dev, "failed to get cmds\n");
183 			return ret;
184 		}
185 	}
186 
187 	return 0;
188 }
189 
rk628_panel_prepare(struct rk628 * rk628)190 void rk628_panel_prepare(struct rk628 *rk628)
191 {
192 	int ret;
193 
194 	if (rk628->panel->supply) {
195 		ret = regulator_enable(rk628->panel->supply);
196 		if (ret)
197 			dev_info(rk628->dev, "failed to enable panel power supply\n");
198 	}
199 
200 	if (rk628->panel->enable_gpio) {
201 		gpiod_set_value(rk628->panel->enable_gpio, 0);
202 		mdelay(120);
203 		gpiod_set_value(rk628->panel->enable_gpio, 1);
204 		mdelay(120);
205 	}
206 
207 	if (rk628->panel->reset_gpio) {
208 		gpiod_set_value(rk628->panel->reset_gpio, 0);
209 		mdelay(120);
210 		gpiod_set_value(rk628->panel->reset_gpio, 1);
211 		mdelay(120);
212 		gpiod_set_value(rk628->panel->reset_gpio, 0);
213 		mdelay(120);
214 	}
215 }
216 
rk628_panel_enable(struct rk628 * rk628)217 void rk628_panel_enable(struct rk628 *rk628)
218 {
219 	if (rk628->panel->backlight)
220 		backlight_enable(rk628->panel->backlight);
221 }
222 
rk628_panel_unprepare(struct rk628 * rk628)223 void rk628_panel_unprepare(struct rk628 *rk628)
224 {
225 
226 	if (rk628->panel->reset_gpio) {
227 		gpiod_set_value(rk628->panel->reset_gpio, 1);
228 		mdelay(120);
229 	}
230 
231 	if (rk628->panel->enable_gpio) {
232 		gpiod_set_value(rk628->panel->enable_gpio, 0);
233 		mdelay(120);
234 	}
235 
236 	if (rk628->panel->supply)
237 		regulator_disable(rk628->panel->supply);
238 }
239 
rk628_panel_disable(struct rk628 * rk628)240 void rk628_panel_disable(struct rk628 *rk628)
241 {
242 	if (rk628->panel->backlight)
243 		backlight_disable(rk628->panel->backlight);
244 
245 }
246