Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2016 InforceComputing
0004  * Author: Vinay Simha BN <simhavcs@gmail.com>
0005  *
0006  * Copyright (C) 2016 Linaro Ltd
0007  * Author: Sumit Semwal <sumit.semwal@linaro.org>
0008  *
0009  * From internet archives, the panel for Nexus 7 2nd Gen, 2013 model is a
0010  * JDI model LT070ME05000, and its data sheet is at:
0011  * http://panelone.net/en/7-0-inch/JDI_LT070ME05000_7.0_inch-datasheet
0012  */
0013 
0014 #include <linux/backlight.h>
0015 #include <linux/delay.h>
0016 #include <linux/gpio/consumer.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/regulator/consumer.h>
0020 
0021 #include <video/mipi_display.h>
0022 
0023 #include <drm/drm_crtc.h>
0024 #include <drm/drm_mipi_dsi.h>
0025 #include <drm/drm_modes.h>
0026 #include <drm/drm_panel.h>
0027 
0028 static const char * const regulator_names[] = {
0029     "vddp",
0030     "iovcc"
0031 };
0032 
0033 struct jdi_panel {
0034     struct drm_panel base;
0035     struct mipi_dsi_device *dsi;
0036 
0037     struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
0038 
0039     struct gpio_desc *enable_gpio;
0040     struct gpio_desc *reset_gpio;
0041     struct gpio_desc *dcdc_en_gpio;
0042     struct backlight_device *backlight;
0043 
0044     bool prepared;
0045     bool enabled;
0046 
0047     const struct drm_display_mode *mode;
0048 };
0049 
0050 static inline struct jdi_panel *to_jdi_panel(struct drm_panel *panel)
0051 {
0052     return container_of(panel, struct jdi_panel, base);
0053 }
0054 
0055 static int jdi_panel_init(struct jdi_panel *jdi)
0056 {
0057     struct mipi_dsi_device *dsi = jdi->dsi;
0058     struct device *dev = &jdi->dsi->dev;
0059     int ret;
0060 
0061     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0062 
0063     ret = mipi_dsi_dcs_soft_reset(dsi);
0064     if (ret < 0)
0065         return ret;
0066 
0067     usleep_range(10000, 20000);
0068 
0069     ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
0070     if (ret < 0) {
0071         dev_err(dev, "failed to set pixel format: %d\n", ret);
0072         return ret;
0073     }
0074 
0075     ret = mipi_dsi_dcs_set_column_address(dsi, 0, jdi->mode->hdisplay - 1);
0076     if (ret < 0) {
0077         dev_err(dev, "failed to set column address: %d\n", ret);
0078         return ret;
0079     }
0080 
0081     ret = mipi_dsi_dcs_set_page_address(dsi, 0, jdi->mode->vdisplay - 1);
0082     if (ret < 0) {
0083         dev_err(dev, "failed to set page address: %d\n", ret);
0084         return ret;
0085     }
0086 
0087     /*
0088      * BIT(5) BCTRL = 1 Backlight Control Block On, Brightness registers
0089      *                  are active
0090      * BIT(3) BL = 1    Backlight Control On
0091      * BIT(2) DD = 0    Display Dimming is Off
0092      */
0093     ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
0094                  (u8[]){ 0x24 }, 1);
0095     if (ret < 0) {
0096         dev_err(dev, "failed to write control display: %d\n", ret);
0097         return ret;
0098     }
0099 
0100     /* CABC off */
0101     ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,
0102                  (u8[]){ 0x00 }, 1);
0103     if (ret < 0) {
0104         dev_err(dev, "failed to set cabc off: %d\n", ret);
0105         return ret;
0106     }
0107 
0108     ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0109     if (ret < 0) {
0110         dev_err(dev, "failed to set exit sleep mode: %d\n", ret);
0111         return ret;
0112     }
0113 
0114     msleep(120);
0115 
0116     ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x00}, 2);
0117     if (ret < 0) {
0118         dev_err(dev, "failed to set mcap: %d\n", ret);
0119         return ret;
0120     }
0121 
0122     mdelay(10);
0123 
0124     /* Interface setting, video mode */
0125     ret = mipi_dsi_generic_write(dsi, (u8[])
0126                      {0xB3, 0x26, 0x08, 0x00, 0x20, 0x00}, 6);
0127     if (ret < 0) {
0128         dev_err(dev, "failed to set display interface setting: %d\n"
0129             , ret);
0130         return ret;
0131     }
0132 
0133     mdelay(20);
0134 
0135     ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x03}, 2);
0136     if (ret < 0) {
0137         dev_err(dev, "failed to set default values for mcap: %d\n"
0138             , ret);
0139         return ret;
0140     }
0141 
0142     return 0;
0143 }
0144 
0145 static int jdi_panel_on(struct jdi_panel *jdi)
0146 {
0147     struct mipi_dsi_device *dsi = jdi->dsi;
0148     struct device *dev = &jdi->dsi->dev;
0149     int ret;
0150 
0151     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0152 
0153     ret = mipi_dsi_dcs_set_display_on(dsi);
0154     if (ret < 0)
0155         dev_err(dev, "failed to set display on: %d\n", ret);
0156 
0157     return ret;
0158 }
0159 
0160 static void jdi_panel_off(struct jdi_panel *jdi)
0161 {
0162     struct mipi_dsi_device *dsi = jdi->dsi;
0163     struct device *dev = &jdi->dsi->dev;
0164     int ret;
0165 
0166     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0167 
0168     ret = mipi_dsi_dcs_set_display_off(dsi);
0169     if (ret < 0)
0170         dev_err(dev, "failed to set display off: %d\n", ret);
0171 
0172     ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0173     if (ret < 0)
0174         dev_err(dev, "failed to enter sleep mode: %d\n", ret);
0175 
0176     msleep(100);
0177 }
0178 
0179 static int jdi_panel_disable(struct drm_panel *panel)
0180 {
0181     struct jdi_panel *jdi = to_jdi_panel(panel);
0182 
0183     if (!jdi->enabled)
0184         return 0;
0185 
0186     backlight_disable(jdi->backlight);
0187 
0188     jdi->enabled = false;
0189 
0190     return 0;
0191 }
0192 
0193 static int jdi_panel_unprepare(struct drm_panel *panel)
0194 {
0195     struct jdi_panel *jdi = to_jdi_panel(panel);
0196     struct device *dev = &jdi->dsi->dev;
0197     int ret;
0198 
0199     if (!jdi->prepared)
0200         return 0;
0201 
0202     jdi_panel_off(jdi);
0203 
0204     ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
0205     if (ret < 0)
0206         dev_err(dev, "regulator disable failed, %d\n", ret);
0207 
0208     gpiod_set_value(jdi->enable_gpio, 0);
0209 
0210     gpiod_set_value(jdi->reset_gpio, 1);
0211 
0212     gpiod_set_value(jdi->dcdc_en_gpio, 0);
0213 
0214     jdi->prepared = false;
0215 
0216     return 0;
0217 }
0218 
0219 static int jdi_panel_prepare(struct drm_panel *panel)
0220 {
0221     struct jdi_panel *jdi = to_jdi_panel(panel);
0222     struct device *dev = &jdi->dsi->dev;
0223     int ret;
0224 
0225     if (jdi->prepared)
0226         return 0;
0227 
0228     ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
0229     if (ret < 0) {
0230         dev_err(dev, "regulator enable failed, %d\n", ret);
0231         return ret;
0232     }
0233 
0234     msleep(20);
0235 
0236     gpiod_set_value(jdi->dcdc_en_gpio, 1);
0237     usleep_range(10, 20);
0238 
0239     gpiod_set_value(jdi->reset_gpio, 0);
0240     usleep_range(10, 20);
0241 
0242     gpiod_set_value(jdi->enable_gpio, 1);
0243     usleep_range(10, 20);
0244 
0245     ret = jdi_panel_init(jdi);
0246     if (ret < 0) {
0247         dev_err(dev, "failed to init panel: %d\n", ret);
0248         goto poweroff;
0249     }
0250 
0251     ret = jdi_panel_on(jdi);
0252     if (ret < 0) {
0253         dev_err(dev, "failed to set panel on: %d\n", ret);
0254         goto poweroff;
0255     }
0256 
0257     jdi->prepared = true;
0258 
0259     return 0;
0260 
0261 poweroff:
0262     ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
0263     if (ret < 0)
0264         dev_err(dev, "regulator disable failed, %d\n", ret);
0265 
0266     gpiod_set_value(jdi->enable_gpio, 0);
0267 
0268     gpiod_set_value(jdi->reset_gpio, 1);
0269 
0270     gpiod_set_value(jdi->dcdc_en_gpio, 0);
0271 
0272     return ret;
0273 }
0274 
0275 static int jdi_panel_enable(struct drm_panel *panel)
0276 {
0277     struct jdi_panel *jdi = to_jdi_panel(panel);
0278 
0279     if (jdi->enabled)
0280         return 0;
0281 
0282     backlight_enable(jdi->backlight);
0283 
0284     jdi->enabled = true;
0285 
0286     return 0;
0287 }
0288 
0289 static const struct drm_display_mode default_mode = {
0290         .clock = 155493,
0291         .hdisplay = 1200,
0292         .hsync_start = 1200 + 48,
0293         .hsync_end = 1200 + 48 + 32,
0294         .htotal = 1200 + 48 + 32 + 60,
0295         .vdisplay = 1920,
0296         .vsync_start = 1920 + 3,
0297         .vsync_end = 1920 + 3 + 5,
0298         .vtotal = 1920 + 3 + 5 + 6,
0299         .flags = 0,
0300 };
0301 
0302 static int jdi_panel_get_modes(struct drm_panel *panel,
0303                    struct drm_connector *connector)
0304 {
0305     struct drm_display_mode *mode;
0306     struct jdi_panel *jdi = to_jdi_panel(panel);
0307     struct device *dev = &jdi->dsi->dev;
0308 
0309     mode = drm_mode_duplicate(connector->dev, &default_mode);
0310     if (!mode) {
0311         dev_err(dev, "failed to add mode %ux%ux@%u\n",
0312             default_mode.hdisplay, default_mode.vdisplay,
0313             drm_mode_vrefresh(&default_mode));
0314         return -ENOMEM;
0315     }
0316 
0317     drm_mode_set_name(mode);
0318 
0319     drm_mode_probed_add(connector, mode);
0320 
0321     connector->display_info.width_mm = 95;
0322     connector->display_info.height_mm = 151;
0323 
0324     return 1;
0325 }
0326 
0327 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl)
0328 {
0329     struct mipi_dsi_device *dsi = bl_get_data(bl);
0330     int ret;
0331     u16 brightness = bl->props.brightness;
0332 
0333     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0334 
0335     ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
0336     if (ret < 0)
0337         return ret;
0338 
0339     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0340 
0341     return brightness & 0xff;
0342 }
0343 
0344 static int dsi_dcs_bl_update_status(struct backlight_device *bl)
0345 {
0346     struct mipi_dsi_device *dsi = bl_get_data(bl);
0347     int ret;
0348 
0349     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0350 
0351     ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
0352     if (ret < 0)
0353         return ret;
0354 
0355     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0356 
0357     return 0;
0358 }
0359 
0360 static const struct backlight_ops dsi_bl_ops = {
0361     .update_status = dsi_dcs_bl_update_status,
0362     .get_brightness = dsi_dcs_bl_get_brightness,
0363 };
0364 
0365 static struct backlight_device *
0366 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
0367 {
0368     struct device *dev = &dsi->dev;
0369     struct backlight_properties props;
0370 
0371     memset(&props, 0, sizeof(props));
0372     props.type = BACKLIGHT_RAW;
0373     props.brightness = 255;
0374     props.max_brightness = 255;
0375 
0376     return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
0377                           &dsi_bl_ops, &props);
0378 }
0379 
0380 static const struct drm_panel_funcs jdi_panel_funcs = {
0381     .disable = jdi_panel_disable,
0382     .unprepare = jdi_panel_unprepare,
0383     .prepare = jdi_panel_prepare,
0384     .enable = jdi_panel_enable,
0385     .get_modes = jdi_panel_get_modes,
0386 };
0387 
0388 static const struct of_device_id jdi_of_match[] = {
0389     { .compatible = "jdi,lt070me05000", },
0390     { }
0391 };
0392 MODULE_DEVICE_TABLE(of, jdi_of_match);
0393 
0394 static int jdi_panel_add(struct jdi_panel *jdi)
0395 {
0396     struct device *dev = &jdi->dsi->dev;
0397     int ret;
0398     unsigned int i;
0399 
0400     jdi->mode = &default_mode;
0401 
0402     for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++)
0403         jdi->supplies[i].supply = regulator_names[i];
0404 
0405     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
0406                       jdi->supplies);
0407     if (ret < 0) {
0408         dev_err(dev, "failed to init regulator, ret=%d\n", ret);
0409         return ret;
0410     }
0411 
0412     jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
0413     if (IS_ERR(jdi->enable_gpio)) {
0414         ret = PTR_ERR(jdi->enable_gpio);
0415         dev_err(dev, "cannot get enable-gpio %d\n", ret);
0416         return ret;
0417     }
0418 
0419     jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0420     if (IS_ERR(jdi->reset_gpio)) {
0421         ret = PTR_ERR(jdi->reset_gpio);
0422         dev_err(dev, "cannot get reset-gpios %d\n", ret);
0423         return ret;
0424     }
0425 
0426     jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
0427     if (IS_ERR(jdi->dcdc_en_gpio)) {
0428         ret = PTR_ERR(jdi->dcdc_en_gpio);
0429         dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret);
0430         return ret;
0431     }
0432 
0433     jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
0434     if (IS_ERR(jdi->backlight)) {
0435         ret = PTR_ERR(jdi->backlight);
0436         dev_err(dev, "failed to register backlight %d\n", ret);
0437         return ret;
0438     }
0439 
0440     drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
0441                DRM_MODE_CONNECTOR_DSI);
0442 
0443     drm_panel_add(&jdi->base);
0444 
0445     return 0;
0446 }
0447 
0448 static void jdi_panel_del(struct jdi_panel *jdi)
0449 {
0450     if (jdi->base.dev)
0451         drm_panel_remove(&jdi->base);
0452 }
0453 
0454 static int jdi_panel_probe(struct mipi_dsi_device *dsi)
0455 {
0456     struct jdi_panel *jdi;
0457     int ret;
0458 
0459     dsi->lanes = 4;
0460     dsi->format = MIPI_DSI_FMT_RGB888;
0461     dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
0462                MIPI_DSI_CLOCK_NON_CONTINUOUS;
0463 
0464     jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL);
0465     if (!jdi)
0466         return -ENOMEM;
0467 
0468     mipi_dsi_set_drvdata(dsi, jdi);
0469 
0470     jdi->dsi = dsi;
0471 
0472     ret = jdi_panel_add(jdi);
0473     if (ret < 0)
0474         return ret;
0475 
0476     ret = mipi_dsi_attach(dsi);
0477     if (ret < 0) {
0478         jdi_panel_del(jdi);
0479         return ret;
0480     }
0481 
0482     return 0;
0483 }
0484 
0485 static int jdi_panel_remove(struct mipi_dsi_device *dsi)
0486 {
0487     struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
0488     int ret;
0489 
0490     ret = jdi_panel_disable(&jdi->base);
0491     if (ret < 0)
0492         dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
0493 
0494     ret = mipi_dsi_detach(dsi);
0495     if (ret < 0)
0496         dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
0497             ret);
0498 
0499     jdi_panel_del(jdi);
0500 
0501     return 0;
0502 }
0503 
0504 static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
0505 {
0506     struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
0507 
0508     jdi_panel_disable(&jdi->base);
0509 }
0510 
0511 static struct mipi_dsi_driver jdi_panel_driver = {
0512     .driver = {
0513         .name = "panel-jdi-lt070me05000",
0514         .of_match_table = jdi_of_match,
0515     },
0516     .probe = jdi_panel_probe,
0517     .remove = jdi_panel_remove,
0518     .shutdown = jdi_panel_shutdown,
0519 };
0520 module_mipi_dsi_driver(jdi_panel_driver);
0521 
0522 MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
0523 MODULE_AUTHOR("Vinay Simha BN <simhavcs@gmail.com>");
0524 MODULE_DESCRIPTION("JDI LT070ME05000 WUXGA");
0525 MODULE_LICENSE("GPL v2");