1 /*
2  * Copyright (C) 2014 NVIDIA Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 
9 #include <linux/backlight.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/regulator/consumer.h>
14 
15 #include <drm/drmP.h>
16 #include <drm/drm_crtc.h>
17 #include <drm/drm_mipi_dsi.h>
18 #include <drm/drm_panel.h>
19 
20 #include <video/mipi_display.h>
21 
22 #include <linux/host1x.h>
23 
24 struct sharp_panel {
25 	struct drm_panel base;
26 	/* the datasheet refers to them as DSI-LINK1 and DSI-LINK2 */
27 	struct mipi_dsi_device *link1;
28 	struct mipi_dsi_device *link2;
29 
30 	struct backlight_device *backlight;
31 	struct regulator *supply;
32 
33 	bool prepared;
34 	bool enabled;
35 
36 	const struct drm_display_mode *mode;
37 };
38 
39 static inline struct sharp_panel *to_sharp_panel(struct drm_panel *panel)
40 {
41 	return container_of(panel, struct sharp_panel, base);
42 }
43 
44 static int sharp_panel_write(struct sharp_panel *sharp, u16 offset, u8 value)
45 {
46 	u8 payload[3] = { offset >> 8, offset & 0xff, value };
47 	struct mipi_dsi_device *dsi = sharp->link1;
48 	ssize_t err;
49 
50 	err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
51 	if (err < 0) {
52 		dev_err(&dsi->dev, "failed to write %02x to %04x: %zd\n",
53 			value, offset, err);
54 		return err;
55 	}
56 
57 	err = mipi_dsi_dcs_nop(dsi);
58 	if (err < 0) {
59 		dev_err(&dsi->dev, "failed to send DCS nop: %zd\n", err);
60 		return err;
61 	}
62 
63 	usleep_range(10, 20);
64 
65 	return 0;
66 }
67 
68 static __maybe_unused int sharp_panel_read(struct sharp_panel *sharp,
69 					   u16 offset, u8 *value)
70 {
71 	ssize_t err;
72 
73 	cpu_to_be16s(&offset);
74 
75 	err = mipi_dsi_generic_read(sharp->link1, &offset, sizeof(offset),
76 				    value, sizeof(*value));
77 	if (err < 0)
78 		dev_err(&sharp->link1->dev, "failed to read from %04x: %zd\n",
79 			offset, err);
80 
81 	return err;
82 }
83 
84 static int sharp_panel_disable(struct drm_panel *panel)
85 {
86 	struct sharp_panel *sharp = to_sharp_panel(panel);
87 
88 	if (!sharp->enabled)
89 		return 0;
90 
91 	if (sharp->backlight) {
92 		sharp->backlight->props.power = FB_BLANK_POWERDOWN;
93 		backlight_update_status(sharp->backlight);
94 	}
95 
96 	sharp->enabled = false;
97 
98 	return 0;
99 }
100 
101 static int sharp_panel_unprepare(struct drm_panel *panel)
102 {
103 	struct sharp_panel *sharp = to_sharp_panel(panel);
104 	int err;
105 
106 	if (!sharp->prepared)
107 		return 0;
108 
109 	err = mipi_dsi_dcs_set_display_off(sharp->link1);
110 	if (err < 0)
111 		dev_err(panel->dev, "failed to set display off: %d\n", err);
112 
113 	err = mipi_dsi_dcs_enter_sleep_mode(sharp->link1);
114 	if (err < 0)
115 		dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
116 
117 	msleep(120);
118 
119 	regulator_disable(sharp->supply);
120 
121 	sharp->prepared = false;
122 
123 	return 0;
124 }
125 
126 static int sharp_setup_symmetrical_split(struct mipi_dsi_device *left,
127 					 struct mipi_dsi_device *right,
128 					 const struct drm_display_mode *mode)
129 {
130 	int err;
131 
132 	err = mipi_dsi_dcs_set_column_address(left, 0, mode->hdisplay / 2 - 1);
133 	if (err < 0) {
134 		dev_err(&left->dev, "failed to set column address: %d\n", err);
135 		return err;
136 	}
137 
138 	err = mipi_dsi_dcs_set_page_address(left, 0, mode->vdisplay - 1);
139 	if (err < 0) {
140 		dev_err(&left->dev, "failed to set page address: %d\n", err);
141 		return err;
142 	}
143 
144 	err = mipi_dsi_dcs_set_column_address(right, mode->hdisplay / 2,
145 					      mode->hdisplay - 1);
146 	if (err < 0) {
147 		dev_err(&right->dev, "failed to set column address: %d\n", err);
148 		return err;
149 	}
150 
151 	err = mipi_dsi_dcs_set_page_address(right, 0, mode->vdisplay - 1);
152 	if (err < 0) {
153 		dev_err(&right->dev, "failed to set page address: %d\n", err);
154 		return err;
155 	}
156 
157 	return 0;
158 }
159 
160 static int sharp_panel_prepare(struct drm_panel *panel)
161 {
162 	struct sharp_panel *sharp = to_sharp_panel(panel);
163 	u8 format = MIPI_DCS_PIXEL_FMT_24BIT;
164 	int err;
165 
166 	if (sharp->prepared)
167 		return 0;
168 
169 	err = regulator_enable(sharp->supply);
170 	if (err < 0)
171 		return err;
172 
173 	usleep_range(10000, 20000);
174 
175 	err = mipi_dsi_dcs_soft_reset(sharp->link1);
176 	if (err < 0) {
177 		dev_err(panel->dev, "soft reset failed: %d\n", err);
178 		goto poweroff;
179 	}
180 
181 	msleep(120);
182 
183 	err = mipi_dsi_dcs_exit_sleep_mode(sharp->link1);
184 	if (err < 0) {
185 		dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
186 		goto poweroff;
187 	}
188 
189 	/*
190 	 * The MIPI DCS specification mandates this delay only between the
191 	 * exit_sleep_mode and enter_sleep_mode commands, so it isn't strictly
192 	 * necessary here.
193 	 */
194 	/*
195 	msleep(120);
196 	*/
197 
198 	/* set left-right mode */
199 	err = sharp_panel_write(sharp, 0x1000, 0x2a);
200 	if (err < 0) {
201 		dev_err(panel->dev, "failed to set left-right mode: %d\n", err);
202 		goto poweroff;
203 	}
204 
205 	/* enable command mode */
206 	err = sharp_panel_write(sharp, 0x1001, 0x01);
207 	if (err < 0) {
208 		dev_err(panel->dev, "failed to enable command mode: %d\n", err);
209 		goto poweroff;
210 	}
211 
212 	err = mipi_dsi_dcs_set_pixel_format(sharp->link1, format);
213 	if (err < 0) {
214 		dev_err(panel->dev, "failed to set pixel format: %d\n", err);
215 		goto poweroff;
216 	}
217 
218 	/*
219 	 * TODO: The device supports both left-right and even-odd split
220 	 * configurations, but this driver currently supports only the left-
221 	 * right split. To support a different mode a mechanism needs to be
222 	 * put in place to communicate the configuration back to the DSI host
223 	 * controller.
224 	 */
225 	err = sharp_setup_symmetrical_split(sharp->link1, sharp->link2,
226 					    sharp->mode);
227 	if (err < 0) {
228 		dev_err(panel->dev, "failed to set up symmetrical split: %d\n",
229 			err);
230 		goto poweroff;
231 	}
232 
233 	err = mipi_dsi_dcs_set_display_on(sharp->link1);
234 	if (err < 0) {
235 		dev_err(panel->dev, "failed to set display on: %d\n", err);
236 		goto poweroff;
237 	}
238 
239 	sharp->prepared = true;
240 
241 	return 0;
242 
243 poweroff:
244 	regulator_disable(sharp->supply);
245 	return err;
246 }
247 
248 static int sharp_panel_enable(struct drm_panel *panel)
249 {
250 	struct sharp_panel *sharp = to_sharp_panel(panel);
251 
252 	if (sharp->enabled)
253 		return 0;
254 
255 	if (sharp->backlight) {
256 		sharp->backlight->props.power = FB_BLANK_UNBLANK;
257 		backlight_update_status(sharp->backlight);
258 	}
259 
260 	sharp->enabled = true;
261 
262 	return 0;
263 }
264 
265 static const struct drm_display_mode default_mode = {
266 	.clock = 278000,
267 	.hdisplay = 2560,
268 	.hsync_start = 2560 + 128,
269 	.hsync_end = 2560 + 128 + 64,
270 	.htotal = 2560 + 128 + 64 + 64,
271 	.vdisplay = 1600,
272 	.vsync_start = 1600 + 4,
273 	.vsync_end = 1600 + 4 + 8,
274 	.vtotal = 1600 + 4 + 8 + 32,
275 	.vrefresh = 60,
276 };
277 
278 static int sharp_panel_get_modes(struct drm_panel *panel)
279 {
280 	struct drm_display_mode *mode;
281 
282 	mode = drm_mode_duplicate(panel->drm, &default_mode);
283 	if (!mode) {
284 		dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
285 			default_mode.hdisplay, default_mode.vdisplay,
286 			default_mode.vrefresh);
287 		return -ENOMEM;
288 	}
289 
290 	drm_mode_set_name(mode);
291 
292 	drm_mode_probed_add(panel->connector, mode);
293 
294 	panel->connector->display_info.width_mm = 217;
295 	panel->connector->display_info.height_mm = 136;
296 
297 	return 1;
298 }
299 
300 static const struct drm_panel_funcs sharp_panel_funcs = {
301 	.disable = sharp_panel_disable,
302 	.unprepare = sharp_panel_unprepare,
303 	.prepare = sharp_panel_prepare,
304 	.enable = sharp_panel_enable,
305 	.get_modes = sharp_panel_get_modes,
306 };
307 
308 static const struct of_device_id sharp_of_match[] = {
309 	{ .compatible = "sharp,lq101r1sx01", },
310 	{ }
311 };
312 MODULE_DEVICE_TABLE(of, sharp_of_match);
313 
314 static int sharp_panel_add(struct sharp_panel *sharp)
315 {
316 	struct device_node *np;
317 	int err;
318 
319 	sharp->mode = &default_mode;
320 
321 	sharp->supply = devm_regulator_get(&sharp->link1->dev, "power");
322 	if (IS_ERR(sharp->supply))
323 		return PTR_ERR(sharp->supply);
324 
325 	np = of_parse_phandle(sharp->link1->dev.of_node, "backlight", 0);
326 	if (np) {
327 		sharp->backlight = of_find_backlight_by_node(np);
328 		of_node_put(np);
329 
330 		if (!sharp->backlight)
331 			return -EPROBE_DEFER;
332 	}
333 
334 	drm_panel_init(&sharp->base);
335 	sharp->base.funcs = &sharp_panel_funcs;
336 	sharp->base.dev = &sharp->link1->dev;
337 
338 	err = drm_panel_add(&sharp->base);
339 	if (err < 0)
340 		goto put_backlight;
341 
342 	return 0;
343 
344 put_backlight:
345 	if (sharp->backlight)
346 		put_device(&sharp->backlight->dev);
347 
348 	return err;
349 }
350 
351 static void sharp_panel_del(struct sharp_panel *sharp)
352 {
353 	if (sharp->base.dev)
354 		drm_panel_remove(&sharp->base);
355 
356 	if (sharp->backlight)
357 		put_device(&sharp->backlight->dev);
358 
359 	if (sharp->link2)
360 		put_device(&sharp->link2->dev);
361 }
362 
363 static int sharp_panel_probe(struct mipi_dsi_device *dsi)
364 {
365 	struct mipi_dsi_device *secondary = NULL;
366 	struct sharp_panel *sharp;
367 	struct device_node *np;
368 	int err;
369 
370 	dsi->lanes = 4;
371 	dsi->format = MIPI_DSI_FMT_RGB888;
372 	dsi->mode_flags = MIPI_DSI_MODE_LPM;
373 
374 	/* Find DSI-LINK1 */
375 	np = of_parse_phandle(dsi->dev.of_node, "link2", 0);
376 	if (np) {
377 		secondary = of_find_mipi_dsi_device_by_node(np);
378 		of_node_put(np);
379 
380 		if (!secondary)
381 			return -EPROBE_DEFER;
382 	}
383 
384 	/* register a panel for only the DSI-LINK1 interface */
385 	if (secondary) {
386 		sharp = devm_kzalloc(&dsi->dev, sizeof(*sharp), GFP_KERNEL);
387 		if (!sharp) {
388 			put_device(&secondary->dev);
389 			return -ENOMEM;
390 		}
391 
392 		mipi_dsi_set_drvdata(dsi, sharp);
393 
394 		sharp->link2 = secondary;
395 		sharp->link1 = dsi;
396 
397 		err = sharp_panel_add(sharp);
398 		if (err < 0) {
399 			put_device(&secondary->dev);
400 			return err;
401 		}
402 	}
403 
404 	err = mipi_dsi_attach(dsi);
405 	if (err < 0) {
406 		if (secondary)
407 			sharp_panel_del(sharp);
408 
409 		return err;
410 	}
411 
412 	return 0;
413 }
414 
415 static int sharp_panel_remove(struct mipi_dsi_device *dsi)
416 {
417 	struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
418 	int err;
419 
420 	/* only detach from host for the DSI-LINK2 interface */
421 	if (!sharp) {
422 		mipi_dsi_detach(dsi);
423 		return 0;
424 	}
425 
426 	err = sharp_panel_disable(&sharp->base);
427 	if (err < 0)
428 		dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
429 
430 	err = mipi_dsi_detach(dsi);
431 	if (err < 0)
432 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
433 
434 	drm_panel_detach(&sharp->base);
435 	sharp_panel_del(sharp);
436 
437 	return 0;
438 }
439 
440 static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
441 {
442 	struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
443 
444 	/* nothing to do for DSI-LINK2 */
445 	if (!sharp)
446 		return;
447 
448 	sharp_panel_disable(&sharp->base);
449 }
450 
451 static struct mipi_dsi_driver sharp_panel_driver = {
452 	.driver = {
453 		.name = "panel-sharp-lq101r1sx01",
454 		.of_match_table = sharp_of_match,
455 	},
456 	.probe = sharp_panel_probe,
457 	.remove = sharp_panel_remove,
458 	.shutdown = sharp_panel_shutdown,
459 };
460 module_mipi_dsi_driver(sharp_panel_driver);
461 
462 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
463 MODULE_DESCRIPTION("Sharp LQ101R1SX01 panel driver");
464 MODULE_LICENSE("GPL v2");
465