1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2016 InforceComputing
6 * Copyright (C) 2016 Linaro Ltd
10 #include <linux/backlight.h>
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/module.h>
15 #include <linux/regulator/consumer.h>
17 #include <video/mipi_display.h>
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>
24 static const char * const regulator_names[] = {
30 struct drm_panel base;
31 struct mipi_dsi_device *dsi;
33 struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
35 struct gpio_desc *enable_gpio;
36 struct gpio_desc *reset_gpio;
37 struct gpio_desc *dcdc_en_gpio;
38 struct backlight_device *backlight;
40 const struct drm_display_mode *mode;
43 static inline struct jdi_panel *to_jdi_panel(struct drm_panel *panel)
45 return container_of(panel, struct jdi_panel, base);
48 static int jdi_panel_init(struct jdi_panel *jdi)
50 struct mipi_dsi_device *dsi = jdi->dsi;
51 struct device *dev = &jdi->dsi->dev;
54 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
56 ret = mipi_dsi_dcs_soft_reset(dsi);
60 usleep_range(10000, 20000);
62 ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
64 dev_err(dev, "failed to set pixel format: %d\n", ret);
68 ret = mipi_dsi_dcs_set_column_address(dsi, 0, jdi->mode->hdisplay - 1);
70 dev_err(dev, "failed to set column address: %d\n", ret);
74 ret = mipi_dsi_dcs_set_page_address(dsi, 0, jdi->mode->vdisplay - 1);
76 dev_err(dev, "failed to set page address: %d\n", ret);
81 * BIT(5) BCTRL = 1 Backlight Control Block On, Brightness registers
83 * BIT(3) BL = 1 Backlight Control On
84 * BIT(2) DD = 0 Display Dimming is Off
86 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
89 dev_err(dev, "failed to write control display: %d\n", ret);
94 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,
97 dev_err(dev, "failed to set cabc off: %d\n", ret);
101 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
103 dev_err(dev, "failed to set exit sleep mode: %d\n", ret);
109 ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x00}, 2);
111 dev_err(dev, "failed to set mcap: %d\n", ret);
117 /* Interface setting, video mode */
118 ret = mipi_dsi_generic_write(dsi, (u8[])
119 {0xB3, 0x26, 0x08, 0x00, 0x20, 0x00}, 6);
121 dev_err(dev, "failed to set display interface setting: %d\n"
128 ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x03}, 2);
130 dev_err(dev, "failed to set default values for mcap: %d\n"
138 static int jdi_panel_on(struct jdi_panel *jdi)
140 struct mipi_dsi_device *dsi = jdi->dsi;
141 struct device *dev = &jdi->dsi->dev;
144 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
146 ret = mipi_dsi_dcs_set_display_on(dsi);
148 dev_err(dev, "failed to set display on: %d\n", ret);
153 static void jdi_panel_off(struct jdi_panel *jdi)
155 struct mipi_dsi_device *dsi = jdi->dsi;
156 struct device *dev = &jdi->dsi->dev;
159 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
161 ret = mipi_dsi_dcs_set_display_off(dsi);
163 dev_err(dev, "failed to set display off: %d\n", ret);
165 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
167 dev_err(dev, "failed to enter sleep mode: %d\n", ret);
172 static int jdi_panel_disable(struct drm_panel *panel)
174 struct jdi_panel *jdi = to_jdi_panel(panel);
176 backlight_disable(jdi->backlight);
181 static int jdi_panel_unprepare(struct drm_panel *panel)
183 struct jdi_panel *jdi = to_jdi_panel(panel);
184 struct device *dev = &jdi->dsi->dev;
189 ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
191 dev_err(dev, "regulator disable failed, %d\n", ret);
193 gpiod_set_value(jdi->enable_gpio, 0);
195 gpiod_set_value(jdi->reset_gpio, 1);
197 gpiod_set_value(jdi->dcdc_en_gpio, 0);
202 static int jdi_panel_prepare(struct drm_panel *panel)
204 struct jdi_panel *jdi = to_jdi_panel(panel);
205 struct device *dev = &jdi->dsi->dev;
208 ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
210 dev_err(dev, "regulator enable failed, %d\n", ret);
216 gpiod_set_value(jdi->dcdc_en_gpio, 1);
217 usleep_range(10, 20);
219 gpiod_set_value(jdi->reset_gpio, 0);
220 usleep_range(10, 20);
222 gpiod_set_value(jdi->enable_gpio, 1);
223 usleep_range(10, 20);
225 ret = jdi_panel_init(jdi);
227 dev_err(dev, "failed to init panel: %d\n", ret);
231 ret = jdi_panel_on(jdi);
233 dev_err(dev, "failed to set panel on: %d\n", ret);
240 ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
242 dev_err(dev, "regulator disable failed, %d\n", ret);
244 gpiod_set_value(jdi->enable_gpio, 0);
246 gpiod_set_value(jdi->reset_gpio, 1);
248 gpiod_set_value(jdi->dcdc_en_gpio, 0);
253 static int jdi_panel_enable(struct drm_panel *panel)
255 struct jdi_panel *jdi = to_jdi_panel(panel);
257 backlight_enable(jdi->backlight);
262 static const struct drm_display_mode default_mode = {
265 .hsync_start = 1200 + 48,
266 .hsync_end = 1200 + 48 + 32,
267 .htotal = 1200 + 48 + 32 + 60,
269 .vsync_start = 1920 + 3,
270 .vsync_end = 1920 + 3 + 5,
271 .vtotal = 1920 + 3 + 5 + 6,
275 static int jdi_panel_get_modes(struct drm_panel *panel,
276 struct drm_connector *connector)
278 struct drm_display_mode *mode;
279 struct jdi_panel *jdi = to_jdi_panel(panel);
280 struct device *dev = &jdi->dsi->dev;
282 mode = drm_mode_duplicate(connector->dev, &default_mode);
284 dev_err(dev, "failed to add mode %ux%ux@%u\n",
285 default_mode.hdisplay, default_mode.vdisplay,
286 drm_mode_vrefresh(&default_mode));
290 drm_mode_set_name(mode);
292 drm_mode_probed_add(connector, mode);
294 connector->display_info.width_mm = 95;
295 connector->display_info.height_mm = 151;
300 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl)
302 struct mipi_dsi_device *dsi = bl_get_data(bl);
304 u16 brightness = bl->props.brightness;
306 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
308 ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
312 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
314 return brightness & 0xff;
317 static int dsi_dcs_bl_update_status(struct backlight_device *bl)
319 struct mipi_dsi_device *dsi = bl_get_data(bl);
322 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
324 ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
328 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
333 static const struct backlight_ops dsi_bl_ops = {
334 .update_status = dsi_dcs_bl_update_status,
335 .get_brightness = dsi_dcs_bl_get_brightness,
338 static struct backlight_device *
339 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
341 struct device *dev = &dsi->dev;
342 struct backlight_properties props;
344 memset(&props, 0, sizeof(props));
345 props.type = BACKLIGHT_RAW;
346 props.brightness = 255;
347 props.max_brightness = 255;
349 return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
350 &dsi_bl_ops, &props);
353 static const struct drm_panel_funcs jdi_panel_funcs = {
354 .disable = jdi_panel_disable,
355 .unprepare = jdi_panel_unprepare,
356 .prepare = jdi_panel_prepare,
357 .enable = jdi_panel_enable,
358 .get_modes = jdi_panel_get_modes,
361 static const struct of_device_id jdi_of_match[] = {
362 { .compatible = "jdi,lt070me05000", },
365 MODULE_DEVICE_TABLE(of, jdi_of_match);
367 static int jdi_panel_add(struct jdi_panel *jdi)
369 struct device *dev = &jdi->dsi->dev;
373 jdi->mode = &default_mode;
375 for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++)
376 jdi->supplies[i].supply = regulator_names[i];
378 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
381 return dev_err_probe(dev, ret,
382 "failed to init regulator, ret=%d\n", ret);
384 jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
385 if (IS_ERR(jdi->enable_gpio)) {
386 return dev_err_probe(dev, PTR_ERR(jdi->enable_gpio),
387 "cannot get enable-gpio %d\n", ret);
390 jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
391 if (IS_ERR(jdi->reset_gpio))
392 return dev_err_probe(dev, PTR_ERR(jdi->reset_gpio),
393 "cannot get reset-gpios %d\n", ret);
395 jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
396 if (IS_ERR(jdi->dcdc_en_gpio))
397 return dev_err_probe(dev, PTR_ERR(jdi->dcdc_en_gpio),
398 "cannot get dcdc-en-gpio %d\n", ret);
400 jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
401 if (IS_ERR(jdi->backlight))
402 return dev_err_probe(dev, PTR_ERR(jdi->backlight),
403 "failed to register backlight %d\n", ret);
405 drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
406 DRM_MODE_CONNECTOR_DSI);
408 drm_panel_add(&jdi->base);
413 static void jdi_panel_del(struct jdi_panel *jdi)
416 drm_panel_remove(&jdi->base);
419 static int jdi_panel_probe(struct mipi_dsi_device *dsi)
421 struct jdi_panel *jdi;
425 dsi->format = MIPI_DSI_FMT_RGB888;
426 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
427 MIPI_DSI_CLOCK_NON_CONTINUOUS;
429 jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL);
433 mipi_dsi_set_drvdata(dsi, jdi);
437 ret = jdi_panel_add(jdi);
441 ret = mipi_dsi_attach(dsi);
450 static void jdi_panel_remove(struct mipi_dsi_device *dsi)
452 struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
455 ret = mipi_dsi_detach(dsi);
457 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
463 static struct mipi_dsi_driver jdi_panel_driver = {
465 .name = "panel-jdi-lt070me05000",
466 .of_match_table = jdi_of_match,
468 .probe = jdi_panel_probe,
469 .remove = jdi_panel_remove,
471 module_mipi_dsi_driver(jdi_panel_driver);
475 MODULE_DESCRIPTION("JDI LT070ME05000 WUXGA");
476 MODULE_LICENSE("GPL v2");