xref: /linux/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c (revision 460e462d22542adfafd8a5bc979437df73f1cbf3)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2016 InforceComputing
4  * Author: Vinay Simha BN <simhavcs@gmail.com>
5  *
6  * Copyright (C) 2016 Linaro Ltd
7  * Author: Sumit Semwal <sumit.semwal@linaro.org>
8  */
9 
10 #include <linux/backlight.h>
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/regulator/consumer.h>
16 
17 #include <video/mipi_display.h>
18 
19 #include <drm/drm_crtc.h>
20 #include <drm/drm_mipi_dsi.h>
21 #include <drm/drm_modes.h>
22 #include <drm/drm_panel.h>
23 
24 static const char * const regulator_names[] = {
25 	"vddp",
26 	"iovcc"
27 };
28 
29 struct jdi_panel {
30 	struct drm_panel base;
31 	struct mipi_dsi_device *dsi;
32 
33 	struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
34 
35 	struct gpio_desc *enable_gpio;
36 	struct gpio_desc *reset_gpio;
37 	struct gpio_desc *dcdc_en_gpio;
38 	struct backlight_device *backlight;
39 
40 	bool prepared;
41 	bool enabled;
42 
43 	const struct drm_display_mode *mode;
44 };
45 
46 static inline struct jdi_panel *to_jdi_panel(struct drm_panel *panel)
47 {
48 	return container_of(panel, struct jdi_panel, base);
49 }
50 
51 static int jdi_panel_init(struct jdi_panel *jdi)
52 {
53 	struct mipi_dsi_device *dsi = jdi->dsi;
54 	struct device *dev = &jdi->dsi->dev;
55 	int ret;
56 
57 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
58 
59 	ret = mipi_dsi_dcs_soft_reset(dsi);
60 	if (ret < 0)
61 		return ret;
62 
63 	usleep_range(10000, 20000);
64 
65 	ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
66 	if (ret < 0) {
67 		dev_err(dev, "failed to set pixel format: %d\n", ret);
68 		return ret;
69 	}
70 
71 	ret = mipi_dsi_dcs_set_column_address(dsi, 0, jdi->mode->hdisplay - 1);
72 	if (ret < 0) {
73 		dev_err(dev, "failed to set column address: %d\n", ret);
74 		return ret;
75 	}
76 
77 	ret = mipi_dsi_dcs_set_page_address(dsi, 0, jdi->mode->vdisplay - 1);
78 	if (ret < 0) {
79 		dev_err(dev, "failed to set page address: %d\n", ret);
80 		return ret;
81 	}
82 
83 	/*
84 	 * BIT(5) BCTRL = 1 Backlight Control Block On, Brightness registers
85 	 *                  are active
86 	 * BIT(3) BL = 1    Backlight Control On
87 	 * BIT(2) DD = 0    Display Dimming is Off
88 	 */
89 	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
90 				 (u8[]){ 0x24 }, 1);
91 	if (ret < 0) {
92 		dev_err(dev, "failed to write control display: %d\n", ret);
93 		return ret;
94 	}
95 
96 	/* CABC off */
97 	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,
98 				 (u8[]){ 0x00 }, 1);
99 	if (ret < 0) {
100 		dev_err(dev, "failed to set cabc off: %d\n", ret);
101 		return ret;
102 	}
103 
104 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
105 	if (ret < 0) {
106 		dev_err(dev, "failed to set exit sleep mode: %d\n", ret);
107 		return ret;
108 	}
109 
110 	msleep(120);
111 
112 	ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x00}, 2);
113 	if (ret < 0) {
114 		dev_err(dev, "failed to set mcap: %d\n", ret);
115 		return ret;
116 	}
117 
118 	mdelay(10);
119 
120 	/* Interface setting, video mode */
121 	ret = mipi_dsi_generic_write(dsi, (u8[])
122 				     {0xB3, 0x26, 0x08, 0x00, 0x20, 0x00}, 6);
123 	if (ret < 0) {
124 		dev_err(dev, "failed to set display interface setting: %d\n"
125 			, ret);
126 		return ret;
127 	}
128 
129 	mdelay(20);
130 
131 	ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x03}, 2);
132 	if (ret < 0) {
133 		dev_err(dev, "failed to set default values for mcap: %d\n"
134 			, ret);
135 		return ret;
136 	}
137 
138 	return 0;
139 }
140 
141 static int jdi_panel_on(struct jdi_panel *jdi)
142 {
143 	struct mipi_dsi_device *dsi = jdi->dsi;
144 	struct device *dev = &jdi->dsi->dev;
145 	int ret;
146 
147 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
148 
149 	ret = mipi_dsi_dcs_set_display_on(dsi);
150 	if (ret < 0)
151 		dev_err(dev, "failed to set display on: %d\n", ret);
152 
153 	return ret;
154 }
155 
156 static void jdi_panel_off(struct jdi_panel *jdi)
157 {
158 	struct mipi_dsi_device *dsi = jdi->dsi;
159 	struct device *dev = &jdi->dsi->dev;
160 	int ret;
161 
162 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
163 
164 	ret = mipi_dsi_dcs_set_display_off(dsi);
165 	if (ret < 0)
166 		dev_err(dev, "failed to set display off: %d\n", ret);
167 
168 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
169 	if (ret < 0)
170 		dev_err(dev, "failed to enter sleep mode: %d\n", ret);
171 
172 	msleep(100);
173 }
174 
175 static int jdi_panel_disable(struct drm_panel *panel)
176 {
177 	struct jdi_panel *jdi = to_jdi_panel(panel);
178 
179 	if (!jdi->enabled)
180 		return 0;
181 
182 	backlight_disable(jdi->backlight);
183 
184 	jdi->enabled = false;
185 
186 	return 0;
187 }
188 
189 static int jdi_panel_unprepare(struct drm_panel *panel)
190 {
191 	struct jdi_panel *jdi = to_jdi_panel(panel);
192 	struct device *dev = &jdi->dsi->dev;
193 	int ret;
194 
195 	if (!jdi->prepared)
196 		return 0;
197 
198 	jdi_panel_off(jdi);
199 
200 	ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
201 	if (ret < 0)
202 		dev_err(dev, "regulator disable failed, %d\n", ret);
203 
204 	gpiod_set_value(jdi->enable_gpio, 0);
205 
206 	gpiod_set_value(jdi->reset_gpio, 1);
207 
208 	gpiod_set_value(jdi->dcdc_en_gpio, 0);
209 
210 	jdi->prepared = false;
211 
212 	return 0;
213 }
214 
215 static int jdi_panel_prepare(struct drm_panel *panel)
216 {
217 	struct jdi_panel *jdi = to_jdi_panel(panel);
218 	struct device *dev = &jdi->dsi->dev;
219 	int ret;
220 
221 	if (jdi->prepared)
222 		return 0;
223 
224 	ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
225 	if (ret < 0) {
226 		dev_err(dev, "regulator enable failed, %d\n", ret);
227 		return ret;
228 	}
229 
230 	msleep(20);
231 
232 	gpiod_set_value(jdi->dcdc_en_gpio, 1);
233 	usleep_range(10, 20);
234 
235 	gpiod_set_value(jdi->reset_gpio, 0);
236 	usleep_range(10, 20);
237 
238 	gpiod_set_value(jdi->enable_gpio, 1);
239 	usleep_range(10, 20);
240 
241 	ret = jdi_panel_init(jdi);
242 	if (ret < 0) {
243 		dev_err(dev, "failed to init panel: %d\n", ret);
244 		goto poweroff;
245 	}
246 
247 	ret = jdi_panel_on(jdi);
248 	if (ret < 0) {
249 		dev_err(dev, "failed to set panel on: %d\n", ret);
250 		goto poweroff;
251 	}
252 
253 	jdi->prepared = true;
254 
255 	return 0;
256 
257 poweroff:
258 	ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
259 	if (ret < 0)
260 		dev_err(dev, "regulator disable failed, %d\n", ret);
261 
262 	gpiod_set_value(jdi->enable_gpio, 0);
263 
264 	gpiod_set_value(jdi->reset_gpio, 1);
265 
266 	gpiod_set_value(jdi->dcdc_en_gpio, 0);
267 
268 	return ret;
269 }
270 
271 static int jdi_panel_enable(struct drm_panel *panel)
272 {
273 	struct jdi_panel *jdi = to_jdi_panel(panel);
274 
275 	if (jdi->enabled)
276 		return 0;
277 
278 	backlight_enable(jdi->backlight);
279 
280 	jdi->enabled = true;
281 
282 	return 0;
283 }
284 
285 static const struct drm_display_mode default_mode = {
286 		.clock = 155493,
287 		.hdisplay = 1200,
288 		.hsync_start = 1200 + 48,
289 		.hsync_end = 1200 + 48 + 32,
290 		.htotal = 1200 + 48 + 32 + 60,
291 		.vdisplay = 1920,
292 		.vsync_start = 1920 + 3,
293 		.vsync_end = 1920 + 3 + 5,
294 		.vtotal = 1920 + 3 + 5 + 6,
295 		.flags = 0,
296 };
297 
298 static int jdi_panel_get_modes(struct drm_panel *panel,
299 			       struct drm_connector *connector)
300 {
301 	struct drm_display_mode *mode;
302 	struct jdi_panel *jdi = to_jdi_panel(panel);
303 	struct device *dev = &jdi->dsi->dev;
304 
305 	mode = drm_mode_duplicate(connector->dev, &default_mode);
306 	if (!mode) {
307 		dev_err(dev, "failed to add mode %ux%ux@%u\n",
308 			default_mode.hdisplay, default_mode.vdisplay,
309 			drm_mode_vrefresh(&default_mode));
310 		return -ENOMEM;
311 	}
312 
313 	drm_mode_set_name(mode);
314 
315 	drm_mode_probed_add(connector, mode);
316 
317 	connector->display_info.width_mm = 95;
318 	connector->display_info.height_mm = 151;
319 
320 	return 1;
321 }
322 
323 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl)
324 {
325 	struct mipi_dsi_device *dsi = bl_get_data(bl);
326 	int ret;
327 	u16 brightness = bl->props.brightness;
328 
329 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
330 
331 	ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
332 	if (ret < 0)
333 		return ret;
334 
335 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
336 
337 	return brightness & 0xff;
338 }
339 
340 static int dsi_dcs_bl_update_status(struct backlight_device *bl)
341 {
342 	struct mipi_dsi_device *dsi = bl_get_data(bl);
343 	int ret;
344 
345 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
346 
347 	ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
348 	if (ret < 0)
349 		return ret;
350 
351 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
352 
353 	return 0;
354 }
355 
356 static const struct backlight_ops dsi_bl_ops = {
357 	.update_status = dsi_dcs_bl_update_status,
358 	.get_brightness = dsi_dcs_bl_get_brightness,
359 };
360 
361 static struct backlight_device *
362 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
363 {
364 	struct device *dev = &dsi->dev;
365 	struct backlight_properties props;
366 
367 	memset(&props, 0, sizeof(props));
368 	props.type = BACKLIGHT_RAW;
369 	props.brightness = 255;
370 	props.max_brightness = 255;
371 
372 	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
373 					      &dsi_bl_ops, &props);
374 }
375 
376 static const struct drm_panel_funcs jdi_panel_funcs = {
377 	.disable = jdi_panel_disable,
378 	.unprepare = jdi_panel_unprepare,
379 	.prepare = jdi_panel_prepare,
380 	.enable = jdi_panel_enable,
381 	.get_modes = jdi_panel_get_modes,
382 };
383 
384 static const struct of_device_id jdi_of_match[] = {
385 	{ .compatible = "jdi,lt070me05000", },
386 	{ }
387 };
388 MODULE_DEVICE_TABLE(of, jdi_of_match);
389 
390 static int jdi_panel_add(struct jdi_panel *jdi)
391 {
392 	struct device *dev = &jdi->dsi->dev;
393 	int ret;
394 	unsigned int i;
395 
396 	jdi->mode = &default_mode;
397 
398 	for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++)
399 		jdi->supplies[i].supply = regulator_names[i];
400 
401 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
402 				      jdi->supplies);
403 	if (ret < 0)
404 		return dev_err_probe(dev, ret,
405 				     "failed to init regulator, ret=%d\n", ret);
406 
407 	jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
408 	if (IS_ERR(jdi->enable_gpio)) {
409 		return dev_err_probe(dev, PTR_ERR(jdi->enable_gpio),
410 				     "cannot get enable-gpio %d\n", ret);
411 	}
412 
413 	jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
414 	if (IS_ERR(jdi->reset_gpio))
415 		return dev_err_probe(dev, PTR_ERR(jdi->reset_gpio),
416 				     "cannot get reset-gpios %d\n", ret);
417 
418 	jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
419 	if (IS_ERR(jdi->dcdc_en_gpio))
420 		return dev_err_probe(dev, PTR_ERR(jdi->dcdc_en_gpio),
421 				     "cannot get dcdc-en-gpio %d\n", ret);
422 
423 	jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
424 	if (IS_ERR(jdi->backlight))
425 		return dev_err_probe(dev, PTR_ERR(jdi->backlight),
426 				     "failed to register backlight %d\n", ret);
427 
428 	drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
429 		       DRM_MODE_CONNECTOR_DSI);
430 
431 	drm_panel_add(&jdi->base);
432 
433 	return 0;
434 }
435 
436 static void jdi_panel_del(struct jdi_panel *jdi)
437 {
438 	if (jdi->base.dev)
439 		drm_panel_remove(&jdi->base);
440 }
441 
442 static int jdi_panel_probe(struct mipi_dsi_device *dsi)
443 {
444 	struct jdi_panel *jdi;
445 	int ret;
446 
447 	dsi->lanes = 4;
448 	dsi->format = MIPI_DSI_FMT_RGB888;
449 	dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
450 			   MIPI_DSI_CLOCK_NON_CONTINUOUS;
451 
452 	jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL);
453 	if (!jdi)
454 		return -ENOMEM;
455 
456 	mipi_dsi_set_drvdata(dsi, jdi);
457 
458 	jdi->dsi = dsi;
459 
460 	ret = jdi_panel_add(jdi);
461 	if (ret < 0)
462 		return ret;
463 
464 	ret = mipi_dsi_attach(dsi);
465 	if (ret < 0) {
466 		jdi_panel_del(jdi);
467 		return ret;
468 	}
469 
470 	return 0;
471 }
472 
473 static void jdi_panel_remove(struct mipi_dsi_device *dsi)
474 {
475 	struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
476 	int ret;
477 
478 	ret = jdi_panel_disable(&jdi->base);
479 	if (ret < 0)
480 		dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
481 
482 	ret = mipi_dsi_detach(dsi);
483 	if (ret < 0)
484 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
485 			ret);
486 
487 	jdi_panel_del(jdi);
488 }
489 
490 static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
491 {
492 	struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
493 
494 	jdi_panel_disable(&jdi->base);
495 }
496 
497 static struct mipi_dsi_driver jdi_panel_driver = {
498 	.driver = {
499 		.name = "panel-jdi-lt070me05000",
500 		.of_match_table = jdi_of_match,
501 	},
502 	.probe = jdi_panel_probe,
503 	.remove = jdi_panel_remove,
504 	.shutdown = jdi_panel_shutdown,
505 };
506 module_mipi_dsi_driver(jdi_panel_driver);
507 
508 MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
509 MODULE_AUTHOR("Vinay Simha BN <simhavcs@gmail.com>");
510 MODULE_DESCRIPTION("JDI LT070ME05000 WUXGA");
511 MODULE_LICENSE("GPL v2");
512