xref: /linux/drivers/gpu/drm/panel/panel-synaptics-r63353.c (revision 41c177cf354126a22443b5c80cec9fdd313e67e1)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Synaptics R63353 Controller driver
4  *
5  * Copyright (C) 2020 BSH Hausgerate GmbH
6  */
7 
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/err.h>
11 #include <linux/errno.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/media-bus-format.h>
16 
17 #include <linux/gpio/consumer.h>
18 #include <linux/regulator/consumer.h>
19 
20 #include <drm/drm_mipi_dsi.h>
21 #include <drm/drm_modes.h>
22 #include <drm/drm_panel.h>
23 
24 #include <video/mipi_display.h>
25 
26 #define R63353_INSTR(...) { \
27 		.len = sizeof((u8[]) {__VA_ARGS__}), \
28 		.data = (u8[]){__VA_ARGS__} \
29 	}
30 
31 struct r63353_instr {
32 	size_t len;
33 	const u8 *data;
34 };
35 
36 static const struct r63353_instr sharp_ls068b3sx02_init[] = {
37 	R63353_INSTR(0x51, 0xff),
38 	R63353_INSTR(0x53, 0x0c),
39 	R63353_INSTR(0x55, 0x00),
40 	R63353_INSTR(0x84, 0x00),
41 	R63353_INSTR(0x29),
42 };
43 
44 struct r63353_desc {
45 	const char *name;
46 	const struct r63353_instr *init;
47 	const size_t init_length;
48 	const struct drm_display_mode *mode;
49 	u32 width_mm;
50 	u32 height_mm;
51 };
52 
53 struct r63353_panel {
54 	struct drm_panel base;
55 	struct mipi_dsi_device *dsi;
56 
57 	struct gpio_desc *reset_gpio;
58 	struct regulator *dvdd;
59 	struct regulator *avdd;
60 
61 	struct r63353_desc *pdata;
62 };
63 
to_r63353_panel(struct drm_panel * panel)64 static inline struct r63353_panel *to_r63353_panel(struct drm_panel *panel)
65 {
66 	return container_of(panel, struct r63353_panel, base);
67 }
68 
r63353_panel_power_on(struct r63353_panel * rpanel)69 static int r63353_panel_power_on(struct r63353_panel *rpanel)
70 {
71 	struct mipi_dsi_device *dsi = rpanel->dsi;
72 	struct device *dev = &dsi->dev;
73 	int ret;
74 
75 	ret = regulator_enable(rpanel->avdd);
76 	if (ret) {
77 		dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret);
78 		return ret;
79 	}
80 
81 	usleep_range(15000, 25000);
82 
83 	ret = regulator_enable(rpanel->dvdd);
84 	if (ret) {
85 		dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret);
86 		regulator_disable(rpanel->avdd);
87 		return ret;
88 	}
89 
90 	usleep_range(300000, 350000);
91 	gpiod_set_value(rpanel->reset_gpio, 1);
92 	usleep_range(15000, 25000);
93 
94 	return 0;
95 }
96 
r63353_panel_power_off(struct r63353_panel * rpanel)97 static int r63353_panel_power_off(struct r63353_panel *rpanel)
98 {
99 	gpiod_set_value(rpanel->reset_gpio, 0);
100 	regulator_disable(rpanel->dvdd);
101 	regulator_disable(rpanel->avdd);
102 
103 	return 0;
104 }
105 
r63353_panel_activate(struct r63353_panel * rpanel)106 static int r63353_panel_activate(struct r63353_panel *rpanel)
107 {
108 	struct mipi_dsi_device *dsi = rpanel->dsi;
109 	struct device *dev = &dsi->dev;
110 	int i, ret;
111 
112 	ret = mipi_dsi_dcs_soft_reset(dsi);
113 	if (ret < 0) {
114 		dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
115 		goto fail;
116 	}
117 
118 	usleep_range(15000, 17000);
119 
120 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
121 	if (ret < 0) {
122 		dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
123 		goto fail;
124 	}
125 
126 	for (i = 0; i < rpanel->pdata->init_length; i++) {
127 		const struct r63353_instr *instr = &rpanel->pdata->init[i];
128 
129 		ret = mipi_dsi_dcs_write_buffer(dsi, instr->data, instr->len);
130 		if (ret < 0)
131 			goto fail;
132 	}
133 
134 	msleep(120);
135 
136 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
137 	if (ret < 0) {
138 		dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
139 		goto fail;
140 	}
141 
142 	usleep_range(5000, 10000);
143 
144 	ret = mipi_dsi_dcs_set_display_on(dsi);
145 	if (ret < 0) {
146 		dev_err(dev, "Failed to set display ON (%d)\n", ret);
147 		goto fail;
148 	}
149 
150 	return 0;
151 
152 fail:
153 	gpiod_set_value(rpanel->reset_gpio, 0);
154 
155 	return ret;
156 }
157 
r63353_panel_prepare(struct drm_panel * panel)158 static int r63353_panel_prepare(struct drm_panel *panel)
159 {
160 	struct r63353_panel *rpanel = to_r63353_panel(panel);
161 	struct mipi_dsi_device *dsi = rpanel->dsi;
162 	struct device *dev = &dsi->dev;
163 	int ret;
164 
165 	dev_dbg(dev, "Preparing\n");
166 
167 	ret = r63353_panel_power_on(rpanel);
168 	if (ret)
169 		return ret;
170 
171 	ret = r63353_panel_activate(rpanel);
172 	if (ret) {
173 		r63353_panel_power_off(rpanel);
174 		return ret;
175 	}
176 
177 	dev_dbg(dev, "Prepared\n");
178 	return 0;
179 }
180 
r63353_panel_deactivate(struct r63353_panel * rpanel)181 static int r63353_panel_deactivate(struct r63353_panel *rpanel)
182 {
183 	struct mipi_dsi_device *dsi = rpanel->dsi;
184 	struct device *dev = &dsi->dev;
185 	int ret;
186 
187 	ret = mipi_dsi_dcs_set_display_off(dsi);
188 	if (ret < 0) {
189 		dev_err(dev, "Failed to set display OFF (%d)\n", ret);
190 		return ret;
191 	}
192 
193 	usleep_range(5000, 10000);
194 
195 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
196 	if (ret < 0) {
197 		dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
198 		return ret;
199 	}
200 
201 	return 0;
202 }
203 
r63353_panel_unprepare(struct drm_panel * panel)204 static int r63353_panel_unprepare(struct drm_panel *panel)
205 {
206 	struct r63353_panel *rpanel = to_r63353_panel(panel);
207 
208 	r63353_panel_deactivate(rpanel);
209 	r63353_panel_power_off(rpanel);
210 
211 	return 0;
212 }
213 
214 static const struct drm_display_mode sharp_ls068b3sx02_timing = {
215 	.clock = 70000,
216 	.hdisplay = 640,
217 	.hsync_start = 640 + 35,
218 	.hsync_end = 640 + 35 + 2,
219 	.htotal = 640 + 35 + 2 + 150,
220 	.vdisplay = 1280,
221 	.vsync_start = 1280 + 2,
222 	.vsync_end = 1280 + 2 + 4,
223 	.vtotal = 1280 + 2 + 4 + 0,
224 };
225 
r63353_panel_get_modes(struct drm_panel * panel,struct drm_connector * connector)226 static int r63353_panel_get_modes(struct drm_panel *panel,
227 				  struct drm_connector *connector)
228 {
229 	struct r63353_panel *rpanel = to_r63353_panel(panel);
230 	struct drm_display_mode *mode;
231 	static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
232 
233 	mode = drm_mode_duplicate(connector->dev, rpanel->pdata->mode);
234 	if (!mode)
235 		return -ENOMEM;
236 
237 	drm_mode_set_name(mode);
238 	drm_mode_probed_add(connector, mode);
239 
240 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
241 	connector->display_info.width_mm = rpanel->pdata->width_mm;
242 	connector->display_info.height_mm = rpanel->pdata->height_mm;
243 
244 	drm_display_info_set_bus_formats(&connector->display_info,
245 					 &bus_format, 1);
246 
247 	return 1;
248 }
249 
250 static const struct drm_panel_funcs r63353_panel_funcs = {
251 	.prepare = r63353_panel_prepare,
252 	.unprepare = r63353_panel_unprepare,
253 	.get_modes = r63353_panel_get_modes,
254 };
255 
r63353_panel_probe(struct mipi_dsi_device * dsi)256 static int r63353_panel_probe(struct mipi_dsi_device *dsi)
257 {
258 	int ret = 0;
259 	struct device *dev = &dsi->dev;
260 	struct r63353_panel *panel;
261 
262 	panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
263 	if (!panel)
264 		return -ENOMEM;
265 
266 	mipi_dsi_set_drvdata(dsi, panel);
267 	panel->dsi = dsi;
268 	panel->pdata = (struct r63353_desc *)of_device_get_match_data(dev);
269 
270 	dev_info(dev, "Panel %s\n", panel->pdata->name);
271 
272 	dsi->lanes = 2;
273 	dsi->format = MIPI_DSI_FMT_RGB888;
274 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
275 			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
276 			  MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET;
277 
278 	panel->dvdd = devm_regulator_get(dev, "dvdd");
279 	if (IS_ERR(panel->dvdd))
280 		return PTR_ERR(panel->dvdd);
281 	panel->avdd = devm_regulator_get(dev, "avdd");
282 	if (IS_ERR(panel->avdd))
283 		return PTR_ERR(panel->avdd);
284 
285 	panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
286 	if (IS_ERR(panel->reset_gpio)) {
287 		dev_err(dev, "failed to get RESET GPIO\n");
288 		return PTR_ERR(panel->reset_gpio);
289 	}
290 
291 	drm_panel_init(&panel->base, dev, &r63353_panel_funcs,
292 		       DRM_MODE_CONNECTOR_DSI);
293 
294 	panel->base.prepare_prev_first = true;
295 	ret = drm_panel_of_backlight(&panel->base);
296 	if (ret)
297 		return ret;
298 
299 	drm_panel_add(&panel->base);
300 
301 	ret = mipi_dsi_attach(dsi);
302 	if (ret < 0) {
303 		dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
304 		drm_panel_remove(&panel->base);
305 		return ret;
306 	}
307 
308 	return ret;
309 }
310 
r63353_panel_remove(struct mipi_dsi_device * dsi)311 static void r63353_panel_remove(struct mipi_dsi_device *dsi)
312 {
313 	struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
314 	struct device *dev = &dsi->dev;
315 	int ret;
316 
317 	ret = mipi_dsi_detach(dsi);
318 	if (ret < 0)
319 		dev_err(dev, "Failed to detach from host (%d)\n", ret);
320 
321 	drm_panel_remove(&rpanel->base);
322 }
323 
r63353_panel_shutdown(struct mipi_dsi_device * dsi)324 static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
325 {
326 	struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
327 
328 	r63353_panel_unprepare(&rpanel->base);
329 }
330 
331 static const struct r63353_desc sharp_ls068b3sx02_data = {
332 	.name = "Sharp LS068B3SX02",
333 	.mode = &sharp_ls068b3sx02_timing,
334 	.init = sharp_ls068b3sx02_init,
335 	.init_length = ARRAY_SIZE(sharp_ls068b3sx02_init),
336 	.width_mm = 68,
337 	.height_mm = 159,
338 };
339 
340 static const struct of_device_id r63353_of_match[] = {
341 	{ .compatible = "sharp,ls068b3sx02", .data = &sharp_ls068b3sx02_data },
342 	{ }
343 };
344 
345 MODULE_DEVICE_TABLE(of, r63353_of_match);
346 
347 static struct mipi_dsi_driver r63353_panel_driver = {
348 	.driver = {
349 		   .name = "r63353-dsi",
350 		   .of_match_table = r63353_of_match,
351 	},
352 	.probe = r63353_panel_probe,
353 	.remove = r63353_panel_remove,
354 	.shutdown = r63353_panel_shutdown,
355 };
356 
357 module_mipi_dsi_driver(r63353_panel_driver);
358 
359 MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>");
360 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
361 MODULE_DESCRIPTION("Synaptics R63353 Controller Driver");
362 MODULE_LICENSE("GPL");
363