xref: /linux/drivers/gpu/drm/panel/panel-synaptics-r63353.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce) !
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 mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
110 	int i;
111 
112 	mipi_dsi_dcs_soft_reset_multi(&dsi_ctx);
113 
114 	mipi_dsi_usleep_range(&dsi_ctx, 15000, 17000);
115 
116 	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
117 
118 	for (i = 0; i < rpanel->pdata->init_length; i++) {
119 		const struct r63353_instr *instr = &rpanel->pdata->init[i];
120 
121 		mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, instr->data,
122 						instr->len);
123 	}
124 
125 	mipi_dsi_msleep(&dsi_ctx, 120);
126 
127 	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
128 
129 	mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000);
130 
131 	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
132 
133 	if (dsi_ctx.accum_err)
134 		gpiod_set_value(rpanel->reset_gpio, 0);
135 
136 	return dsi_ctx.accum_err;
137 }
138 
r63353_panel_prepare(struct drm_panel * panel)139 static int r63353_panel_prepare(struct drm_panel *panel)
140 {
141 	struct r63353_panel *rpanel = to_r63353_panel(panel);
142 	struct mipi_dsi_device *dsi = rpanel->dsi;
143 	struct device *dev = &dsi->dev;
144 	int ret;
145 
146 	dev_dbg(dev, "Preparing\n");
147 
148 	ret = r63353_panel_power_on(rpanel);
149 	if (ret)
150 		return ret;
151 
152 	ret = r63353_panel_activate(rpanel);
153 	if (ret) {
154 		r63353_panel_power_off(rpanel);
155 		return ret;
156 	}
157 
158 	dev_dbg(dev, "Prepared\n");
159 	return 0;
160 }
161 
r63353_panel_deactivate(struct r63353_panel * rpanel)162 static void r63353_panel_deactivate(struct r63353_panel *rpanel)
163 {
164 	struct mipi_dsi_device *dsi = rpanel->dsi;
165 	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
166 
167 	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
168 
169 	mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000);
170 
171 	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
172 }
173 
r63353_panel_unprepare(struct drm_panel * panel)174 static int r63353_panel_unprepare(struct drm_panel *panel)
175 {
176 	struct r63353_panel *rpanel = to_r63353_panel(panel);
177 
178 	r63353_panel_deactivate(rpanel);
179 	r63353_panel_power_off(rpanel);
180 
181 	return 0;
182 }
183 
184 static const struct drm_display_mode sharp_ls068b3sx02_timing = {
185 	.clock = 70000,
186 	.hdisplay = 640,
187 	.hsync_start = 640 + 35,
188 	.hsync_end = 640 + 35 + 2,
189 	.htotal = 640 + 35 + 2 + 150,
190 	.vdisplay = 1280,
191 	.vsync_start = 1280 + 2,
192 	.vsync_end = 1280 + 2 + 4,
193 	.vtotal = 1280 + 2 + 4 + 0,
194 };
195 
r63353_panel_get_modes(struct drm_panel * panel,struct drm_connector * connector)196 static int r63353_panel_get_modes(struct drm_panel *panel,
197 				  struct drm_connector *connector)
198 {
199 	struct r63353_panel *rpanel = to_r63353_panel(panel);
200 	struct drm_display_mode *mode;
201 	static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
202 
203 	mode = drm_mode_duplicate(connector->dev, rpanel->pdata->mode);
204 	if (!mode)
205 		return -ENOMEM;
206 
207 	drm_mode_set_name(mode);
208 	drm_mode_probed_add(connector, mode);
209 
210 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
211 	connector->display_info.width_mm = rpanel->pdata->width_mm;
212 	connector->display_info.height_mm = rpanel->pdata->height_mm;
213 
214 	drm_display_info_set_bus_formats(&connector->display_info,
215 					 &bus_format, 1);
216 
217 	return 1;
218 }
219 
220 static const struct drm_panel_funcs r63353_panel_funcs = {
221 	.prepare = r63353_panel_prepare,
222 	.unprepare = r63353_panel_unprepare,
223 	.get_modes = r63353_panel_get_modes,
224 };
225 
r63353_panel_probe(struct mipi_dsi_device * dsi)226 static int r63353_panel_probe(struct mipi_dsi_device *dsi)
227 {
228 	int ret = 0;
229 	struct device *dev = &dsi->dev;
230 	struct r63353_panel *panel;
231 
232 	panel = devm_drm_panel_alloc(dev, struct r63353_panel, base,
233 				     &r63353_panel_funcs,
234 				     DRM_MODE_CONNECTOR_DSI);
235 	if (IS_ERR(panel))
236 		return PTR_ERR(panel);
237 
238 	mipi_dsi_set_drvdata(dsi, panel);
239 	panel->dsi = dsi;
240 	panel->pdata = (struct r63353_desc *)of_device_get_match_data(dev);
241 
242 	dev_info(dev, "Panel %s\n", panel->pdata->name);
243 
244 	dsi->lanes = 2;
245 	dsi->format = MIPI_DSI_FMT_RGB888;
246 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
247 			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
248 			  MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET;
249 
250 	panel->dvdd = devm_regulator_get(dev, "dvdd");
251 	if (IS_ERR(panel->dvdd))
252 		return PTR_ERR(panel->dvdd);
253 	panel->avdd = devm_regulator_get(dev, "avdd");
254 	if (IS_ERR(panel->avdd))
255 		return PTR_ERR(panel->avdd);
256 
257 	panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
258 	if (IS_ERR(panel->reset_gpio)) {
259 		dev_err(dev, "failed to get RESET GPIO\n");
260 		return PTR_ERR(panel->reset_gpio);
261 	}
262 
263 	panel->base.prepare_prev_first = true;
264 	ret = drm_panel_of_backlight(&panel->base);
265 	if (ret)
266 		return ret;
267 
268 	drm_panel_add(&panel->base);
269 
270 	ret = mipi_dsi_attach(dsi);
271 	if (ret < 0) {
272 		dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
273 		drm_panel_remove(&panel->base);
274 		return ret;
275 	}
276 
277 	return ret;
278 }
279 
r63353_panel_remove(struct mipi_dsi_device * dsi)280 static void r63353_panel_remove(struct mipi_dsi_device *dsi)
281 {
282 	struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
283 	struct device *dev = &dsi->dev;
284 	int ret;
285 
286 	ret = mipi_dsi_detach(dsi);
287 	if (ret < 0)
288 		dev_err(dev, "Failed to detach from host (%d)\n", ret);
289 
290 	drm_panel_remove(&rpanel->base);
291 }
292 
r63353_panel_shutdown(struct mipi_dsi_device * dsi)293 static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
294 {
295 	struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
296 
297 	drm_panel_unprepare(&rpanel->base);
298 }
299 
300 static const struct r63353_desc sharp_ls068b3sx02_data = {
301 	.name = "Sharp LS068B3SX02",
302 	.mode = &sharp_ls068b3sx02_timing,
303 	.init = sharp_ls068b3sx02_init,
304 	.init_length = ARRAY_SIZE(sharp_ls068b3sx02_init),
305 	.width_mm = 68,
306 	.height_mm = 159,
307 };
308 
309 static const struct of_device_id r63353_of_match[] = {
310 	{ .compatible = "sharp,ls068b3sx02", .data = &sharp_ls068b3sx02_data },
311 	{ }
312 };
313 
314 MODULE_DEVICE_TABLE(of, r63353_of_match);
315 
316 static struct mipi_dsi_driver r63353_panel_driver = {
317 	.driver = {
318 		   .name = "r63353-dsi",
319 		   .of_match_table = r63353_of_match,
320 	},
321 	.probe = r63353_panel_probe,
322 	.remove = r63353_panel_remove,
323 	.shutdown = r63353_panel_shutdown,
324 };
325 
326 module_mipi_dsi_driver(r63353_panel_driver);
327 
328 MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>");
329 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
330 MODULE_DESCRIPTION("Synaptics R63353 Controller Driver");
331 MODULE_LICENSE("GPL");
332