root/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_sharp_nt_panel
  2. sharp_nt_panel_init
  3. sharp_nt_panel_on
  4. sharp_nt_panel_off
  5. sharp_nt_panel_disable
  6. sharp_nt_panel_unprepare
  7. sharp_nt_panel_prepare
  8. sharp_nt_panel_enable
  9. sharp_nt_panel_get_modes
  10. sharp_nt_panel_add
  11. sharp_nt_panel_del
  12. sharp_nt_panel_probe
  13. sharp_nt_panel_remove
  14. sharp_nt_panel_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2015 Red Hat
   4  * Copyright (C) 2015 Sony Mobile Communications Inc.
   5  * Author: Werner Johansson <werner.johansson@sonymobile.com>
   6  *
   7  * Based on AUO panel driver by Rob Clark <robdclark@gmail.com>
   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_device.h>
  21 #include <drm/drm_mipi_dsi.h>
  22 #include <drm/drm_panel.h>
  23 
  24 struct sharp_nt_panel {
  25         struct drm_panel base;
  26         struct mipi_dsi_device *dsi;
  27 
  28         struct backlight_device *backlight;
  29         struct regulator *supply;
  30         struct gpio_desc *reset_gpio;
  31 
  32         bool prepared;
  33         bool enabled;
  34 
  35         const struct drm_display_mode *mode;
  36 };
  37 
  38 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
  39 {
  40         return container_of(panel, struct sharp_nt_panel, base);
  41 }
  42 
  43 static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt)
  44 {
  45         struct mipi_dsi_device *dsi = sharp_nt->dsi;
  46         int ret;
  47 
  48         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  49 
  50         ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
  51         if (ret < 0)
  52                 return ret;
  53 
  54         msleep(120);
  55 
  56         /* Novatek two-lane operation */
  57         ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1);
  58         if (ret < 0)
  59                 return ret;
  60 
  61         /* Set both MCU and RGB I/F to 24bpp */
  62         ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT |
  63                                         (MIPI_DCS_PIXEL_FMT_24BIT << 4));
  64         if (ret < 0)
  65                 return ret;
  66 
  67         return 0;
  68 }
  69 
  70 static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt)
  71 {
  72         struct mipi_dsi_device *dsi = sharp_nt->dsi;
  73         int ret;
  74 
  75         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  76 
  77         ret = mipi_dsi_dcs_set_display_on(dsi);
  78         if (ret < 0)
  79                 return ret;
  80 
  81         return 0;
  82 }
  83 
  84 static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt)
  85 {
  86         struct mipi_dsi_device *dsi = sharp_nt->dsi;
  87         int ret;
  88 
  89         dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  90 
  91         ret = mipi_dsi_dcs_set_display_off(dsi);
  92         if (ret < 0)
  93                 return ret;
  94 
  95         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
  96         if (ret < 0)
  97                 return ret;
  98 
  99         return 0;
 100 }
 101 
 102 
 103 static int sharp_nt_panel_disable(struct drm_panel *panel)
 104 {
 105         struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
 106 
 107         if (!sharp_nt->enabled)
 108                 return 0;
 109 
 110         backlight_disable(sharp_nt->backlight);
 111 
 112         sharp_nt->enabled = false;
 113 
 114         return 0;
 115 }
 116 
 117 static int sharp_nt_panel_unprepare(struct drm_panel *panel)
 118 {
 119         struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
 120         int ret;
 121 
 122         if (!sharp_nt->prepared)
 123                 return 0;
 124 
 125         ret = sharp_nt_panel_off(sharp_nt);
 126         if (ret < 0) {
 127                 dev_err(panel->dev, "failed to set panel off: %d\n", ret);
 128                 return ret;
 129         }
 130 
 131         regulator_disable(sharp_nt->supply);
 132         if (sharp_nt->reset_gpio)
 133                 gpiod_set_value(sharp_nt->reset_gpio, 0);
 134 
 135         sharp_nt->prepared = false;
 136 
 137         return 0;
 138 }
 139 
 140 static int sharp_nt_panel_prepare(struct drm_panel *panel)
 141 {
 142         struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
 143         int ret;
 144 
 145         if (sharp_nt->prepared)
 146                 return 0;
 147 
 148         ret = regulator_enable(sharp_nt->supply);
 149         if (ret < 0)
 150                 return ret;
 151 
 152         msleep(20);
 153 
 154         if (sharp_nt->reset_gpio) {
 155                 gpiod_set_value(sharp_nt->reset_gpio, 1);
 156                 msleep(1);
 157                 gpiod_set_value(sharp_nt->reset_gpio, 0);
 158                 msleep(1);
 159                 gpiod_set_value(sharp_nt->reset_gpio, 1);
 160                 msleep(10);
 161         }
 162 
 163         ret = sharp_nt_panel_init(sharp_nt);
 164         if (ret < 0) {
 165                 dev_err(panel->dev, "failed to init panel: %d\n", ret);
 166                 goto poweroff;
 167         }
 168 
 169         ret = sharp_nt_panel_on(sharp_nt);
 170         if (ret < 0) {
 171                 dev_err(panel->dev, "failed to set panel on: %d\n", ret);
 172                 goto poweroff;
 173         }
 174 
 175         sharp_nt->prepared = true;
 176 
 177         return 0;
 178 
 179 poweroff:
 180         regulator_disable(sharp_nt->supply);
 181         if (sharp_nt->reset_gpio)
 182                 gpiod_set_value(sharp_nt->reset_gpio, 0);
 183         return ret;
 184 }
 185 
 186 static int sharp_nt_panel_enable(struct drm_panel *panel)
 187 {
 188         struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
 189 
 190         if (sharp_nt->enabled)
 191                 return 0;
 192 
 193         backlight_enable(sharp_nt->backlight);
 194 
 195         sharp_nt->enabled = true;
 196 
 197         return 0;
 198 }
 199 
 200 static const struct drm_display_mode default_mode = {
 201         .clock = 41118,
 202         .hdisplay = 540,
 203         .hsync_start = 540 + 48,
 204         .hsync_end = 540 + 48 + 80,
 205         .htotal = 540 + 48 + 80 + 32,
 206         .vdisplay = 960,
 207         .vsync_start = 960 + 3,
 208         .vsync_end = 960 + 3 + 15,
 209         .vtotal = 960 + 3 + 15 + 1,
 210         .vrefresh = 60,
 211 };
 212 
 213 static int sharp_nt_panel_get_modes(struct drm_panel *panel)
 214 {
 215         struct drm_display_mode *mode;
 216 
 217         mode = drm_mode_duplicate(panel->drm, &default_mode);
 218         if (!mode) {
 219                 dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
 220                                 default_mode.hdisplay, default_mode.vdisplay,
 221                                 default_mode.vrefresh);
 222                 return -ENOMEM;
 223         }
 224 
 225         drm_mode_set_name(mode);
 226 
 227         drm_mode_probed_add(panel->connector, mode);
 228 
 229         panel->connector->display_info.width_mm = 54;
 230         panel->connector->display_info.height_mm = 95;
 231 
 232         return 1;
 233 }
 234 
 235 static const struct drm_panel_funcs sharp_nt_panel_funcs = {
 236         .disable = sharp_nt_panel_disable,
 237         .unprepare = sharp_nt_panel_unprepare,
 238         .prepare = sharp_nt_panel_prepare,
 239         .enable = sharp_nt_panel_enable,
 240         .get_modes = sharp_nt_panel_get_modes,
 241 };
 242 
 243 static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
 244 {
 245         struct device *dev = &sharp_nt->dsi->dev;
 246 
 247         sharp_nt->mode = &default_mode;
 248 
 249         sharp_nt->supply = devm_regulator_get(dev, "avdd");
 250         if (IS_ERR(sharp_nt->supply))
 251                 return PTR_ERR(sharp_nt->supply);
 252 
 253         sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
 254         if (IS_ERR(sharp_nt->reset_gpio)) {
 255                 dev_err(dev, "cannot get reset-gpios %ld\n",
 256                         PTR_ERR(sharp_nt->reset_gpio));
 257                 sharp_nt->reset_gpio = NULL;
 258         } else {
 259                 gpiod_set_value(sharp_nt->reset_gpio, 0);
 260         }
 261 
 262         sharp_nt->backlight = devm_of_find_backlight(dev);
 263 
 264         if (IS_ERR(sharp_nt->backlight))
 265                 return PTR_ERR(sharp_nt->backlight);
 266 
 267         drm_panel_init(&sharp_nt->base);
 268         sharp_nt->base.funcs = &sharp_nt_panel_funcs;
 269         sharp_nt->base.dev = &sharp_nt->dsi->dev;
 270 
 271         return drm_panel_add(&sharp_nt->base);
 272 }
 273 
 274 static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt)
 275 {
 276         if (sharp_nt->base.dev)
 277                 drm_panel_remove(&sharp_nt->base);
 278 }
 279 
 280 static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
 281 {
 282         struct sharp_nt_panel *sharp_nt;
 283         int ret;
 284 
 285         dsi->lanes = 2;
 286         dsi->format = MIPI_DSI_FMT_RGB888;
 287         dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
 288                         MIPI_DSI_MODE_VIDEO_HSE |
 289                         MIPI_DSI_CLOCK_NON_CONTINUOUS |
 290                         MIPI_DSI_MODE_EOT_PACKET;
 291 
 292         sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
 293         if (!sharp_nt)
 294                 return -ENOMEM;
 295 
 296         mipi_dsi_set_drvdata(dsi, sharp_nt);
 297 
 298         sharp_nt->dsi = dsi;
 299 
 300         ret = sharp_nt_panel_add(sharp_nt);
 301         if (ret < 0)
 302                 return ret;
 303 
 304         return mipi_dsi_attach(dsi);
 305 }
 306 
 307 static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
 308 {
 309         struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
 310         int ret;
 311 
 312         ret = sharp_nt_panel_disable(&sharp_nt->base);
 313         if (ret < 0)
 314                 dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
 315 
 316         ret = mipi_dsi_detach(dsi);
 317         if (ret < 0)
 318                 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 319 
 320         sharp_nt_panel_del(sharp_nt);
 321 
 322         return 0;
 323 }
 324 
 325 static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
 326 {
 327         struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
 328 
 329         sharp_nt_panel_disable(&sharp_nt->base);
 330 }
 331 
 332 static const struct of_device_id sharp_nt_of_match[] = {
 333         { .compatible = "sharp,ls043t1le01-qhd", },
 334         { }
 335 };
 336 MODULE_DEVICE_TABLE(of, sharp_nt_of_match);
 337 
 338 static struct mipi_dsi_driver sharp_nt_panel_driver = {
 339         .driver = {
 340                 .name = "panel-sharp-ls043t1le01-qhd",
 341                 .of_match_table = sharp_nt_of_match,
 342         },
 343         .probe = sharp_nt_panel_probe,
 344         .remove = sharp_nt_panel_remove,
 345         .shutdown = sharp_nt_panel_shutdown,
 346 };
 347 module_mipi_dsi_driver(sharp_nt_panel_driver);
 348 
 349 MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>");
 350 MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver");
 351 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */