root/drivers/gpu/drm/panel/panel-sitronix-st7789v.c

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

DEFINITIONS

This source file includes following definitions.
  1. panel_to_st7789v
  2. st7789v_spi_write
  3. st7789v_write_command
  4. st7789v_write_data
  5. st7789v_get_modes
  6. st7789v_prepare
  7. st7789v_enable
  8. st7789v_disable
  9. st7789v_unprepare
  10. st7789v_probe
  11. st7789v_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2017 Free Electrons
   4  */
   5 
   6 #include <linux/backlight.h>
   7 #include <linux/delay.h>
   8 #include <linux/gpio/consumer.h>
   9 #include <linux/module.h>
  10 #include <linux/regulator/consumer.h>
  11 #include <linux/spi/spi.h>
  12 
  13 #include <video/mipi_display.h>
  14 
  15 #include <drm/drm_device.h>
  16 #include <drm/drm_modes.h>
  17 #include <drm/drm_panel.h>
  18 
  19 #define ST7789V_COLMOD_RGB_FMT_18BITS           (6 << 4)
  20 #define ST7789V_COLMOD_CTRL_FMT_18BITS          (6 << 0)
  21 
  22 #define ST7789V_RAMCTRL_CMD             0xb0
  23 #define ST7789V_RAMCTRL_RM_RGB                  BIT(4)
  24 #define ST7789V_RAMCTRL_DM_RGB                  BIT(0)
  25 #define ST7789V_RAMCTRL_MAGIC                   (3 << 6)
  26 #define ST7789V_RAMCTRL_EPF(n)                  (((n) & 3) << 4)
  27 
  28 #define ST7789V_RGBCTRL_CMD             0xb1
  29 #define ST7789V_RGBCTRL_WO                      BIT(7)
  30 #define ST7789V_RGBCTRL_RCM(n)                  (((n) & 3) << 5)
  31 #define ST7789V_RGBCTRL_VSYNC_HIGH              BIT(3)
  32 #define ST7789V_RGBCTRL_HSYNC_HIGH              BIT(2)
  33 #define ST7789V_RGBCTRL_PCLK_HIGH               BIT(1)
  34 #define ST7789V_RGBCTRL_VBP(n)                  ((n) & 0x7f)
  35 #define ST7789V_RGBCTRL_HBP(n)                  ((n) & 0x1f)
  36 
  37 #define ST7789V_PORCTRL_CMD             0xb2
  38 #define ST7789V_PORCTRL_IDLE_BP(n)              (((n) & 0xf) << 4)
  39 #define ST7789V_PORCTRL_IDLE_FP(n)              ((n) & 0xf)
  40 #define ST7789V_PORCTRL_PARTIAL_BP(n)           (((n) & 0xf) << 4)
  41 #define ST7789V_PORCTRL_PARTIAL_FP(n)           ((n) & 0xf)
  42 
  43 #define ST7789V_GCTRL_CMD               0xb7
  44 #define ST7789V_GCTRL_VGHS(n)                   (((n) & 7) << 4)
  45 #define ST7789V_GCTRL_VGLS(n)                   ((n) & 7)
  46 
  47 #define ST7789V_VCOMS_CMD               0xbb
  48 
  49 #define ST7789V_LCMCTRL_CMD             0xc0
  50 #define ST7789V_LCMCTRL_XBGR                    BIT(5)
  51 #define ST7789V_LCMCTRL_XMX                     BIT(3)
  52 #define ST7789V_LCMCTRL_XMH                     BIT(2)
  53 
  54 #define ST7789V_VDVVRHEN_CMD            0xc2
  55 #define ST7789V_VDVVRHEN_CMDEN                  BIT(0)
  56 
  57 #define ST7789V_VRHS_CMD                0xc3
  58 
  59 #define ST7789V_VDVS_CMD                0xc4
  60 
  61 #define ST7789V_FRCTRL2_CMD             0xc6
  62 
  63 #define ST7789V_PWCTRL1_CMD             0xd0
  64 #define ST7789V_PWCTRL1_MAGIC                   0xa4
  65 #define ST7789V_PWCTRL1_AVDD(n)                 (((n) & 3) << 6)
  66 #define ST7789V_PWCTRL1_AVCL(n)                 (((n) & 3) << 4)
  67 #define ST7789V_PWCTRL1_VDS(n)                  ((n) & 3)
  68 
  69 #define ST7789V_PVGAMCTRL_CMD           0xe0
  70 #define ST7789V_PVGAMCTRL_JP0(n)                (((n) & 3) << 4)
  71 #define ST7789V_PVGAMCTRL_JP1(n)                (((n) & 3) << 4)
  72 #define ST7789V_PVGAMCTRL_VP0(n)                ((n) & 0xf)
  73 #define ST7789V_PVGAMCTRL_VP1(n)                ((n) & 0x3f)
  74 #define ST7789V_PVGAMCTRL_VP2(n)                ((n) & 0x3f)
  75 #define ST7789V_PVGAMCTRL_VP4(n)                ((n) & 0x1f)
  76 #define ST7789V_PVGAMCTRL_VP6(n)                ((n) & 0x1f)
  77 #define ST7789V_PVGAMCTRL_VP13(n)               ((n) & 0xf)
  78 #define ST7789V_PVGAMCTRL_VP20(n)               ((n) & 0x7f)
  79 #define ST7789V_PVGAMCTRL_VP27(n)               ((n) & 7)
  80 #define ST7789V_PVGAMCTRL_VP36(n)               (((n) & 7) << 4)
  81 #define ST7789V_PVGAMCTRL_VP43(n)               ((n) & 0x7f)
  82 #define ST7789V_PVGAMCTRL_VP50(n)               ((n) & 0xf)
  83 #define ST7789V_PVGAMCTRL_VP57(n)               ((n) & 0x1f)
  84 #define ST7789V_PVGAMCTRL_VP59(n)               ((n) & 0x1f)
  85 #define ST7789V_PVGAMCTRL_VP61(n)               ((n) & 0x3f)
  86 #define ST7789V_PVGAMCTRL_VP62(n)               ((n) & 0x3f)
  87 #define ST7789V_PVGAMCTRL_VP63(n)               (((n) & 0xf) << 4)
  88 
  89 #define ST7789V_NVGAMCTRL_CMD           0xe1
  90 #define ST7789V_NVGAMCTRL_JN0(n)                (((n) & 3) << 4)
  91 #define ST7789V_NVGAMCTRL_JN1(n)                (((n) & 3) << 4)
  92 #define ST7789V_NVGAMCTRL_VN0(n)                ((n) & 0xf)
  93 #define ST7789V_NVGAMCTRL_VN1(n)                ((n) & 0x3f)
  94 #define ST7789V_NVGAMCTRL_VN2(n)                ((n) & 0x3f)
  95 #define ST7789V_NVGAMCTRL_VN4(n)                ((n) & 0x1f)
  96 #define ST7789V_NVGAMCTRL_VN6(n)                ((n) & 0x1f)
  97 #define ST7789V_NVGAMCTRL_VN13(n)               ((n) & 0xf)
  98 #define ST7789V_NVGAMCTRL_VN20(n)               ((n) & 0x7f)
  99 #define ST7789V_NVGAMCTRL_VN27(n)               ((n) & 7)
 100 #define ST7789V_NVGAMCTRL_VN36(n)               (((n) & 7) << 4)
 101 #define ST7789V_NVGAMCTRL_VN43(n)               ((n) & 0x7f)
 102 #define ST7789V_NVGAMCTRL_VN50(n)               ((n) & 0xf)
 103 #define ST7789V_NVGAMCTRL_VN57(n)               ((n) & 0x1f)
 104 #define ST7789V_NVGAMCTRL_VN59(n)               ((n) & 0x1f)
 105 #define ST7789V_NVGAMCTRL_VN61(n)               ((n) & 0x3f)
 106 #define ST7789V_NVGAMCTRL_VN62(n)               ((n) & 0x3f)
 107 #define ST7789V_NVGAMCTRL_VN63(n)               (((n) & 0xf) << 4)
 108 
 109 #define ST7789V_TEST(val, func)                 \
 110         do {                                    \
 111                 if ((val = (func)))             \
 112                         return val;             \
 113         } while (0)
 114 
 115 struct st7789v {
 116         struct drm_panel panel;
 117         struct spi_device *spi;
 118         struct gpio_desc *reset;
 119         struct backlight_device *backlight;
 120         struct regulator *power;
 121 };
 122 
 123 enum st7789v_prefix {
 124         ST7789V_COMMAND = 0,
 125         ST7789V_DATA = 1,
 126 };
 127 
 128 static inline struct st7789v *panel_to_st7789v(struct drm_panel *panel)
 129 {
 130         return container_of(panel, struct st7789v, panel);
 131 }
 132 
 133 static int st7789v_spi_write(struct st7789v *ctx, enum st7789v_prefix prefix,
 134                              u8 data)
 135 {
 136         struct spi_transfer xfer = { };
 137         struct spi_message msg;
 138         u16 txbuf = ((prefix & 1) << 8) | data;
 139 
 140         spi_message_init(&msg);
 141 
 142         xfer.tx_buf = &txbuf;
 143         xfer.bits_per_word = 9;
 144         xfer.len = sizeof(txbuf);
 145 
 146         spi_message_add_tail(&xfer, &msg);
 147         return spi_sync(ctx->spi, &msg);
 148 }
 149 
 150 static int st7789v_write_command(struct st7789v *ctx, u8 cmd)
 151 {
 152         return st7789v_spi_write(ctx, ST7789V_COMMAND, cmd);
 153 }
 154 
 155 static int st7789v_write_data(struct st7789v *ctx, u8 cmd)
 156 {
 157         return st7789v_spi_write(ctx, ST7789V_DATA, cmd);
 158 }
 159 
 160 static const struct drm_display_mode default_mode = {
 161         .clock = 7000,
 162         .hdisplay = 240,
 163         .hsync_start = 240 + 38,
 164         .hsync_end = 240 + 38 + 10,
 165         .htotal = 240 + 38 + 10 + 10,
 166         .vdisplay = 320,
 167         .vsync_start = 320 + 8,
 168         .vsync_end = 320 + 8 + 4,
 169         .vtotal = 320 + 8 + 4 + 4,
 170         .vrefresh = 60,
 171 };
 172 
 173 static int st7789v_get_modes(struct drm_panel *panel)
 174 {
 175         struct drm_connector *connector = panel->connector;
 176         struct drm_display_mode *mode;
 177 
 178         mode = drm_mode_duplicate(panel->drm, &default_mode);
 179         if (!mode) {
 180                 dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
 181                         default_mode.hdisplay, default_mode.vdisplay,
 182                         default_mode.vrefresh);
 183                 return -ENOMEM;
 184         }
 185 
 186         drm_mode_set_name(mode);
 187 
 188         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 189         drm_mode_probed_add(connector, mode);
 190 
 191         panel->connector->display_info.width_mm = 61;
 192         panel->connector->display_info.height_mm = 103;
 193 
 194         return 1;
 195 }
 196 
 197 static int st7789v_prepare(struct drm_panel *panel)
 198 {
 199         struct st7789v *ctx = panel_to_st7789v(panel);
 200         int ret;
 201 
 202         ret = regulator_enable(ctx->power);
 203         if (ret)
 204                 return ret;
 205 
 206         gpiod_set_value(ctx->reset, 1);
 207         msleep(30);
 208         gpiod_set_value(ctx->reset, 0);
 209         msleep(120);
 210 
 211         ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_EXIT_SLEEP_MODE));
 212 
 213         /* We need to wait 120ms after a sleep out command */
 214         msleep(120);
 215 
 216         ST7789V_TEST(ret, st7789v_write_command(ctx,
 217                                                 MIPI_DCS_SET_ADDRESS_MODE));
 218         ST7789V_TEST(ret, st7789v_write_data(ctx, 0));
 219 
 220         ST7789V_TEST(ret, st7789v_write_command(ctx,
 221                                                 MIPI_DCS_SET_PIXEL_FORMAT));
 222         ST7789V_TEST(ret, st7789v_write_data(ctx,
 223                                              (MIPI_DCS_PIXEL_FMT_18BIT << 4) |
 224                                              (MIPI_DCS_PIXEL_FMT_18BIT)));
 225 
 226         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PORCTRL_CMD));
 227         ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc));
 228         ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc));
 229         ST7789V_TEST(ret, st7789v_write_data(ctx, 0));
 230         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PORCTRL_IDLE_BP(3) |
 231                                              ST7789V_PORCTRL_IDLE_FP(3)));
 232         ST7789V_TEST(ret, st7789v_write_data(ctx,
 233                                              ST7789V_PORCTRL_PARTIAL_BP(3) |
 234                                              ST7789V_PORCTRL_PARTIAL_FP(3)));
 235 
 236         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_GCTRL_CMD));
 237         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_GCTRL_VGLS(5) |
 238                                              ST7789V_GCTRL_VGHS(3)));
 239 
 240         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VCOMS_CMD));
 241         ST7789V_TEST(ret, st7789v_write_data(ctx, 0x2b));
 242 
 243         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_LCMCTRL_CMD));
 244         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_LCMCTRL_XMH |
 245                                              ST7789V_LCMCTRL_XMX |
 246                                              ST7789V_LCMCTRL_XBGR));
 247 
 248         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVVRHEN_CMD));
 249         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_VDVVRHEN_CMDEN));
 250 
 251         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VRHS_CMD));
 252         ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf));
 253 
 254         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVS_CMD));
 255         ST7789V_TEST(ret, st7789v_write_data(ctx, 0x20));
 256 
 257         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_FRCTRL2_CMD));
 258         ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf));
 259 
 260         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PWCTRL1_CMD));
 261         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_MAGIC));
 262         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_AVDD(2) |
 263                                              ST7789V_PWCTRL1_AVCL(2) |
 264                                              ST7789V_PWCTRL1_VDS(1)));
 265 
 266         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PVGAMCTRL_CMD));
 267         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP63(0xd)));
 268         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP1(0xca)));
 269         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP2(0xe)));
 270         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP4(8)));
 271         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP6(9)));
 272         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP13(7)));
 273         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP20(0x2d)));
 274         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP27(0xb) |
 275                                              ST7789V_PVGAMCTRL_VP36(3)));
 276         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP43(0x3d)));
 277         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_JP1(3) |
 278                                              ST7789V_PVGAMCTRL_VP50(4)));
 279         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP57(0xa)));
 280         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP59(0xa)));
 281         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP61(0x1b)));
 282         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP62(0x28)));
 283 
 284         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_NVGAMCTRL_CMD));
 285         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN63(0xd)));
 286         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN1(0xca)));
 287         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN2(0xf)));
 288         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN4(8)));
 289         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN6(8)));
 290         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN13(7)));
 291         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN20(0x2e)));
 292         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN27(0xc) |
 293                                              ST7789V_NVGAMCTRL_VN36(5)));
 294         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN43(0x40)));
 295         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_JN1(3) |
 296                                              ST7789V_NVGAMCTRL_VN50(4)));
 297         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN57(9)));
 298         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN59(0xb)));
 299         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN61(0x1b)));
 300         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN62(0x28)));
 301 
 302         ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_INVERT_MODE));
 303 
 304         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RAMCTRL_CMD));
 305         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_DM_RGB |
 306                                              ST7789V_RAMCTRL_RM_RGB));
 307         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_EPF(3) |
 308                                              ST7789V_RAMCTRL_MAGIC));
 309 
 310         ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RGBCTRL_CMD));
 311         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_WO |
 312                                              ST7789V_RGBCTRL_RCM(2) |
 313                                              ST7789V_RGBCTRL_VSYNC_HIGH |
 314                                              ST7789V_RGBCTRL_HSYNC_HIGH |
 315                                              ST7789V_RGBCTRL_PCLK_HIGH));
 316         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_VBP(8)));
 317         ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_HBP(20)));
 318 
 319         return 0;
 320 }
 321 
 322 static int st7789v_enable(struct drm_panel *panel)
 323 {
 324         struct st7789v *ctx = panel_to_st7789v(panel);
 325 
 326         if (ctx->backlight) {
 327                 ctx->backlight->props.state &= ~BL_CORE_FBBLANK;
 328                 ctx->backlight->props.power = FB_BLANK_UNBLANK;
 329                 backlight_update_status(ctx->backlight);
 330         }
 331 
 332         return st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_ON);
 333 }
 334 
 335 static int st7789v_disable(struct drm_panel *panel)
 336 {
 337         struct st7789v *ctx = panel_to_st7789v(panel);
 338         int ret;
 339 
 340         ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_OFF));
 341 
 342         if (ctx->backlight) {
 343                 ctx->backlight->props.power = FB_BLANK_POWERDOWN;
 344                 ctx->backlight->props.state |= BL_CORE_FBBLANK;
 345                 backlight_update_status(ctx->backlight);
 346         }
 347 
 348         return 0;
 349 }
 350 
 351 static int st7789v_unprepare(struct drm_panel *panel)
 352 {
 353         struct st7789v *ctx = panel_to_st7789v(panel);
 354         int ret;
 355 
 356         ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_SLEEP_MODE));
 357 
 358         regulator_disable(ctx->power);
 359 
 360         return 0;
 361 }
 362 
 363 static const struct drm_panel_funcs st7789v_drm_funcs = {
 364         .disable        = st7789v_disable,
 365         .enable         = st7789v_enable,
 366         .get_modes      = st7789v_get_modes,
 367         .prepare        = st7789v_prepare,
 368         .unprepare      = st7789v_unprepare,
 369 };
 370 
 371 static int st7789v_probe(struct spi_device *spi)
 372 {
 373         struct device_node *backlight;
 374         struct st7789v *ctx;
 375         int ret;
 376 
 377         ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL);
 378         if (!ctx)
 379                 return -ENOMEM;
 380 
 381         spi_set_drvdata(spi, ctx);
 382         ctx->spi = spi;
 383 
 384         drm_panel_init(&ctx->panel);
 385         ctx->panel.dev = &spi->dev;
 386         ctx->panel.funcs = &st7789v_drm_funcs;
 387 
 388         ctx->power = devm_regulator_get(&spi->dev, "power");
 389         if (IS_ERR(ctx->power))
 390                 return PTR_ERR(ctx->power);
 391 
 392         ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
 393         if (IS_ERR(ctx->reset)) {
 394                 dev_err(&spi->dev, "Couldn't get our reset line\n");
 395                 return PTR_ERR(ctx->reset);
 396         }
 397 
 398         backlight = of_parse_phandle(spi->dev.of_node, "backlight", 0);
 399         if (backlight) {
 400                 ctx->backlight = of_find_backlight_by_node(backlight);
 401                 of_node_put(backlight);
 402 
 403                 if (!ctx->backlight)
 404                         return -EPROBE_DEFER;
 405         }
 406 
 407         ret = drm_panel_add(&ctx->panel);
 408         if (ret < 0)
 409                 goto err_free_backlight;
 410 
 411         return 0;
 412 
 413 err_free_backlight:
 414         if (ctx->backlight)
 415                 put_device(&ctx->backlight->dev);
 416 
 417         return ret;
 418 }
 419 
 420 static int st7789v_remove(struct spi_device *spi)
 421 {
 422         struct st7789v *ctx = spi_get_drvdata(spi);
 423 
 424         drm_panel_remove(&ctx->panel);
 425 
 426         if (ctx->backlight)
 427                 put_device(&ctx->backlight->dev);
 428 
 429         return 0;
 430 }
 431 
 432 static const struct of_device_id st7789v_of_match[] = {
 433         { .compatible = "sitronix,st7789v" },
 434         { }
 435 };
 436 MODULE_DEVICE_TABLE(of, st7789v_of_match);
 437 
 438 static struct spi_driver st7789v_driver = {
 439         .probe = st7789v_probe,
 440         .remove = st7789v_remove,
 441         .driver = {
 442                 .name = "st7789v",
 443                 .of_match_table = st7789v_of_match,
 444         },
 445 };
 446 module_spi_driver(st7789v_driver);
 447 
 448 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
 449 MODULE_DESCRIPTION("Sitronix st7789v LCD Driver");
 450 MODULE_LICENSE("GPL v2");

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