root/drivers/gpu/drm/panel/panel-raydium-rm68200.c

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

DEFINITIONS

This source file includes following definitions.
  1. panel_to_rm68200
  2. rm68200_dcs_write_buf
  3. rm68200_dcs_write_cmd
  4. rm68200_init_sequence
  5. rm68200_disable
  6. rm68200_unprepare
  7. rm68200_prepare
  8. rm68200_enable
  9. rm68200_get_modes
  10. rm68200_probe
  11. rm68200_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) STMicroelectronics SA 2017
   4  *
   5  * Authors: Philippe Cornu <philippe.cornu@st.com>
   6  *          Yannick Fertre <yannick.fertre@st.com>
   7  */
   8 
   9 #include <linux/backlight.h>
  10 #include <linux/delay.h>
  11 #include <linux/gpio/consumer.h>
  12 #include <linux/module.h>
  13 #include <linux/regulator/consumer.h>
  14 
  15 #include <video/mipi_display.h>
  16 
  17 #include <drm/drm_mipi_dsi.h>
  18 #include <drm/drm_modes.h>
  19 #include <drm/drm_panel.h>
  20 #include <drm/drm_print.h>
  21 
  22 /*** Manufacturer Command Set ***/
  23 #define MCS_CMD_MODE_SW         0xFE /* CMD Mode Switch */
  24 #define MCS_CMD1_UCS            0x00 /* User Command Set (UCS = CMD1) */
  25 #define MCS_CMD2_P0             0x01 /* Manufacture Command Set Page0 (CMD2 P0) */
  26 #define MCS_CMD2_P1             0x02 /* Manufacture Command Set Page1 (CMD2 P1) */
  27 #define MCS_CMD2_P2             0x03 /* Manufacture Command Set Page2 (CMD2 P2) */
  28 #define MCS_CMD2_P3             0x04 /* Manufacture Command Set Page3 (CMD2 P3) */
  29 
  30 /* CMD2 P0 commands (Display Options and Power) */
  31 #define MCS_STBCTR              0x12 /* TE1 Output Setting Zig-Zag Connection */
  32 #define MCS_SGOPCTR             0x16 /* Source Bias Current */
  33 #define MCS_SDCTR               0x1A /* Source Output Delay Time */
  34 #define MCS_INVCTR              0x1B /* Inversion Type */
  35 #define MCS_EXT_PWR_IC          0x24 /* External PWR IC Control */
  36 #define MCS_SETAVDD             0x27 /* PFM Control for AVDD Output */
  37 #define MCS_SETAVEE             0x29 /* PFM Control for AVEE Output */
  38 #define MCS_BT2CTR              0x2B /* DDVDL Charge Pump Control */
  39 #define MCS_BT3CTR              0x2F /* VGH Charge Pump Control */
  40 #define MCS_BT4CTR              0x34 /* VGL Charge Pump Control */
  41 #define MCS_VCMCTR              0x46 /* VCOM Output Level Control */
  42 #define MCS_SETVGN              0x52 /* VG M/S N Control */
  43 #define MCS_SETVGP              0x54 /* VG M/S P Control */
  44 #define MCS_SW_CTRL             0x5F /* Interface Control for PFM and MIPI */
  45 
  46 /* CMD2 P2 commands (GOA Timing Control) - no description in datasheet */
  47 #define GOA_VSTV1               0x00
  48 #define GOA_VSTV2               0x07
  49 #define GOA_VCLK1               0x0E
  50 #define GOA_VCLK2               0x17
  51 #define GOA_VCLK_OPT1           0x20
  52 #define GOA_BICLK1              0x2A
  53 #define GOA_BICLK2              0x37
  54 #define GOA_BICLK3              0x44
  55 #define GOA_BICLK4              0x4F
  56 #define GOA_BICLK_OPT1          0x5B
  57 #define GOA_BICLK_OPT2          0x60
  58 #define MCS_GOA_GPO1            0x6D
  59 #define MCS_GOA_GPO2            0x71
  60 #define MCS_GOA_EQ              0x74
  61 #define MCS_GOA_CLK_GALLON      0x7C
  62 #define MCS_GOA_FS_SEL0         0x7E
  63 #define MCS_GOA_FS_SEL1         0x87
  64 #define MCS_GOA_FS_SEL2         0x91
  65 #define MCS_GOA_FS_SEL3         0x9B
  66 #define MCS_GOA_BS_SEL0         0xAC
  67 #define MCS_GOA_BS_SEL1         0xB5
  68 #define MCS_GOA_BS_SEL2         0xBF
  69 #define MCS_GOA_BS_SEL3         0xC9
  70 #define MCS_GOA_BS_SEL4         0xD3
  71 
  72 /* CMD2 P3 commands (Gamma) */
  73 #define MCS_GAMMA_VP            0x60 /* Gamma VP1~VP16 */
  74 #define MCS_GAMMA_VN            0x70 /* Gamma VN1~VN16 */
  75 
  76 struct rm68200 {
  77         struct device *dev;
  78         struct drm_panel panel;
  79         struct gpio_desc *reset_gpio;
  80         struct regulator *supply;
  81         struct backlight_device *backlight;
  82         bool prepared;
  83         bool enabled;
  84 };
  85 
  86 static const struct drm_display_mode default_mode = {
  87         .clock = 52582,
  88         .hdisplay = 720,
  89         .hsync_start = 720 + 38,
  90         .hsync_end = 720 + 38 + 8,
  91         .htotal = 720 + 38 + 8 + 38,
  92         .vdisplay = 1280,
  93         .vsync_start = 1280 + 12,
  94         .vsync_end = 1280 + 12 + 4,
  95         .vtotal = 1280 + 12 + 4 + 12,
  96         .vrefresh = 50,
  97         .flags = 0,
  98         .width_mm = 68,
  99         .height_mm = 122,
 100 };
 101 
 102 static inline struct rm68200 *panel_to_rm68200(struct drm_panel *panel)
 103 {
 104         return container_of(panel, struct rm68200, panel);
 105 }
 106 
 107 static void rm68200_dcs_write_buf(struct rm68200 *ctx, const void *data,
 108                                   size_t len)
 109 {
 110         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 111         int err;
 112 
 113         err = mipi_dsi_dcs_write_buffer(dsi, data, len);
 114         if (err < 0)
 115                 DRM_ERROR_RATELIMITED("MIPI DSI DCS write buffer failed: %d\n",
 116                                       err);
 117 }
 118 
 119 static void rm68200_dcs_write_cmd(struct rm68200 *ctx, u8 cmd, u8 value)
 120 {
 121         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 122         int err;
 123 
 124         err = mipi_dsi_dcs_write(dsi, cmd, &value, 1);
 125         if (err < 0)
 126                 DRM_ERROR_RATELIMITED("MIPI DSI DCS write failed: %d\n", err);
 127 }
 128 
 129 #define dcs_write_seq(ctx, seq...)                              \
 130 ({                                                              \
 131         static const u8 d[] = { seq };                          \
 132                                                                 \
 133         rm68200_dcs_write_buf(ctx, d, ARRAY_SIZE(d));           \
 134 })
 135 
 136 /*
 137  * This panel is not able to auto-increment all cmd addresses so for some of
 138  * them, we need to send them one by one...
 139  */
 140 #define dcs_write_cmd_seq(ctx, cmd, seq...)                     \
 141 ({                                                              \
 142         static const u8 d[] = { seq };                          \
 143         unsigned int i;                                         \
 144                                                                 \
 145         for (i = 0; i < ARRAY_SIZE(d) ; i++)                    \
 146                 rm68200_dcs_write_cmd(ctx, cmd + i, d[i]);      \
 147 })
 148 
 149 static void rm68200_init_sequence(struct rm68200 *ctx)
 150 {
 151         /* Enter CMD2 with page 0 */
 152         dcs_write_seq(ctx, MCS_CMD_MODE_SW, MCS_CMD2_P0);
 153         dcs_write_cmd_seq(ctx, MCS_EXT_PWR_IC, 0xC0, 0x53, 0x00);
 154         dcs_write_seq(ctx, MCS_BT2CTR, 0xE5);
 155         dcs_write_seq(ctx, MCS_SETAVDD, 0x0A);
 156         dcs_write_seq(ctx, MCS_SETAVEE, 0x0A);
 157         dcs_write_seq(ctx, MCS_SGOPCTR, 0x52);
 158         dcs_write_seq(ctx, MCS_BT3CTR, 0x53);
 159         dcs_write_seq(ctx, MCS_BT4CTR, 0x5A);
 160         dcs_write_seq(ctx, MCS_INVCTR, 0x00);
 161         dcs_write_seq(ctx, MCS_STBCTR, 0x0A);
 162         dcs_write_seq(ctx, MCS_SDCTR, 0x06);
 163         dcs_write_seq(ctx, MCS_VCMCTR, 0x56);
 164         dcs_write_seq(ctx, MCS_SETVGN, 0xA0, 0x00);
 165         dcs_write_seq(ctx, MCS_SETVGP, 0xA0, 0x00);
 166         dcs_write_seq(ctx, MCS_SW_CTRL, 0x11); /* 2 data lanes, see doc */
 167 
 168         dcs_write_seq(ctx, MCS_CMD_MODE_SW, MCS_CMD2_P2);
 169         dcs_write_seq(ctx, GOA_VSTV1, 0x05);
 170         dcs_write_seq(ctx, 0x02, 0x0B);
 171         dcs_write_seq(ctx, 0x03, 0x0F);
 172         dcs_write_seq(ctx, 0x04, 0x7D, 0x00, 0x50);
 173         dcs_write_cmd_seq(ctx, GOA_VSTV2, 0x05, 0x16, 0x0D, 0x11, 0x7D, 0x00,
 174                           0x50);
 175         dcs_write_cmd_seq(ctx, GOA_VCLK1, 0x07, 0x08, 0x01, 0x02, 0x00, 0x7D,
 176                           0x00, 0x85, 0x08);
 177         dcs_write_cmd_seq(ctx, GOA_VCLK2, 0x03, 0x04, 0x05, 0x06, 0x00, 0x7D,
 178                           0x00, 0x85, 0x08);
 179         dcs_write_seq(ctx, GOA_VCLK_OPT1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 180                       0x00, 0x00, 0x00, 0x00);
 181         dcs_write_cmd_seq(ctx, GOA_BICLK1, 0x07, 0x08);
 182         dcs_write_seq(ctx, 0x2D, 0x01);
 183         dcs_write_seq(ctx, 0x2F, 0x02, 0x00, 0x40, 0x05, 0x08, 0x54, 0x7D,
 184                       0x00);
 185         dcs_write_cmd_seq(ctx, GOA_BICLK2, 0x03, 0x04, 0x05, 0x06, 0x00);
 186         dcs_write_seq(ctx, 0x3D, 0x40);
 187         dcs_write_seq(ctx, 0x3F, 0x05, 0x08, 0x54, 0x7D, 0x00);
 188         dcs_write_seq(ctx, GOA_BICLK3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 189                       0x00, 0x00, 0x00, 0x00, 0x00);
 190         dcs_write_seq(ctx, GOA_BICLK4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 191                       0x00, 0x00);
 192         dcs_write_seq(ctx, 0x58, 0x00, 0x00, 0x00);
 193         dcs_write_seq(ctx, GOA_BICLK_OPT1, 0x00, 0x00, 0x00, 0x00, 0x00);
 194         dcs_write_seq(ctx, GOA_BICLK_OPT2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 195                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
 196         dcs_write_seq(ctx, MCS_GOA_GPO1, 0x00, 0x00, 0x00, 0x00);
 197         dcs_write_seq(ctx, MCS_GOA_GPO2, 0x00, 0x20, 0x00);
 198         dcs_write_seq(ctx, MCS_GOA_EQ, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
 199                       0x00, 0x00);
 200         dcs_write_seq(ctx, MCS_GOA_CLK_GALLON, 0x00, 0x00);
 201         dcs_write_cmd_seq(ctx, MCS_GOA_FS_SEL0, 0xBF, 0x02, 0x06, 0x14, 0x10,
 202                           0x16, 0x12, 0x08, 0x3F);
 203         dcs_write_cmd_seq(ctx, MCS_GOA_FS_SEL1, 0x3F, 0x3F, 0x3F, 0x3F, 0x0C,
 204                           0x0A, 0x0E, 0x3F, 0x3F, 0x00);
 205         dcs_write_cmd_seq(ctx, MCS_GOA_FS_SEL2, 0x04, 0x3F, 0x3F, 0x3F, 0x3F,
 206                           0x05, 0x01, 0x3F, 0x3F, 0x0F);
 207         dcs_write_cmd_seq(ctx, MCS_GOA_FS_SEL3, 0x0B, 0x0D, 0x3F, 0x3F, 0x3F,
 208                           0x3F);
 209         dcs_write_cmd_seq(ctx, 0xA2, 0x3F, 0x09, 0x13, 0x17, 0x11, 0x15);
 210         dcs_write_cmd_seq(ctx, 0xA9, 0x07, 0x03, 0x3F);
 211         dcs_write_cmd_seq(ctx, MCS_GOA_BS_SEL0, 0x3F, 0x05, 0x01, 0x17, 0x13,
 212                           0x15, 0x11, 0x0F, 0x3F);
 213         dcs_write_cmd_seq(ctx, MCS_GOA_BS_SEL1, 0x3F, 0x3F, 0x3F, 0x3F, 0x0B,
 214                           0x0D, 0x09, 0x3F, 0x3F, 0x07);
 215         dcs_write_cmd_seq(ctx, MCS_GOA_BS_SEL2, 0x03, 0x3F, 0x3F, 0x3F, 0x3F,
 216                           0x02, 0x06, 0x3F, 0x3F, 0x08);
 217         dcs_write_cmd_seq(ctx, MCS_GOA_BS_SEL3, 0x0C, 0x0A, 0x3F, 0x3F, 0x3F,
 218                           0x3F, 0x3F, 0x0E, 0x10, 0x14);
 219         dcs_write_cmd_seq(ctx, MCS_GOA_BS_SEL4, 0x12, 0x16, 0x00, 0x04, 0x3F);
 220         dcs_write_seq(ctx, 0xDC, 0x02);
 221         dcs_write_seq(ctx, 0xDE, 0x12);
 222 
 223         dcs_write_seq(ctx, MCS_CMD_MODE_SW, 0x0E); /* No documentation */
 224         dcs_write_seq(ctx, 0x01, 0x75);
 225 
 226         dcs_write_seq(ctx, MCS_CMD_MODE_SW, MCS_CMD2_P3);
 227         dcs_write_cmd_seq(ctx, MCS_GAMMA_VP, 0x00, 0x0C, 0x12, 0x0E, 0x06,
 228                           0x12, 0x0E, 0x0B, 0x15, 0x0B, 0x10, 0x07, 0x0F,
 229                           0x12, 0x0C, 0x00);
 230         dcs_write_cmd_seq(ctx, MCS_GAMMA_VN, 0x00, 0x0C, 0x12, 0x0E, 0x06,
 231                           0x12, 0x0E, 0x0B, 0x15, 0x0B, 0x10, 0x07, 0x0F,
 232                           0x12, 0x0C, 0x00);
 233 
 234         /* Exit CMD2 */
 235         dcs_write_seq(ctx, MCS_CMD_MODE_SW, MCS_CMD1_UCS);
 236 }
 237 
 238 static int rm68200_disable(struct drm_panel *panel)
 239 {
 240         struct rm68200 *ctx = panel_to_rm68200(panel);
 241 
 242         if (!ctx->enabled)
 243                 return 0;
 244 
 245         backlight_disable(ctx->backlight);
 246 
 247         ctx->enabled = false;
 248 
 249         return 0;
 250 }
 251 
 252 static int rm68200_unprepare(struct drm_panel *panel)
 253 {
 254         struct rm68200 *ctx = panel_to_rm68200(panel);
 255         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 256         int ret;
 257 
 258         if (!ctx->prepared)
 259                 return 0;
 260 
 261         ret = mipi_dsi_dcs_set_display_off(dsi);
 262         if (ret)
 263                 DRM_WARN("failed to set display off: %d\n", ret);
 264 
 265         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
 266         if (ret)
 267                 DRM_WARN("failed to enter sleep mode: %d\n", ret);
 268 
 269         msleep(120);
 270 
 271         if (ctx->reset_gpio) {
 272                 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 273                 msleep(20);
 274         }
 275 
 276         regulator_disable(ctx->supply);
 277 
 278         ctx->prepared = false;
 279 
 280         return 0;
 281 }
 282 
 283 static int rm68200_prepare(struct drm_panel *panel)
 284 {
 285         struct rm68200 *ctx = panel_to_rm68200(panel);
 286         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 287         int ret;
 288 
 289         if (ctx->prepared)
 290                 return 0;
 291 
 292         ret = regulator_enable(ctx->supply);
 293         if (ret < 0) {
 294                 DRM_ERROR("failed to enable supply: %d\n", ret);
 295                 return ret;
 296         }
 297 
 298         if (ctx->reset_gpio) {
 299                 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 300                 msleep(20);
 301                 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
 302                 msleep(100);
 303         }
 304 
 305         rm68200_init_sequence(ctx);
 306 
 307         ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
 308         if (ret)
 309                 return ret;
 310 
 311         msleep(125);
 312 
 313         ret = mipi_dsi_dcs_set_display_on(dsi);
 314         if (ret)
 315                 return ret;
 316 
 317         msleep(20);
 318 
 319         ctx->prepared = true;
 320 
 321         return 0;
 322 }
 323 
 324 static int rm68200_enable(struct drm_panel *panel)
 325 {
 326         struct rm68200 *ctx = panel_to_rm68200(panel);
 327 
 328         if (ctx->enabled)
 329                 return 0;
 330 
 331         backlight_enable(ctx->backlight);
 332 
 333         ctx->enabled = true;
 334 
 335         return 0;
 336 }
 337 
 338 static int rm68200_get_modes(struct drm_panel *panel)
 339 {
 340         struct drm_display_mode *mode;
 341 
 342         mode = drm_mode_duplicate(panel->drm, &default_mode);
 343         if (!mode) {
 344                 DRM_ERROR("failed to add mode %ux%ux@%u\n",
 345                           default_mode.hdisplay, default_mode.vdisplay,
 346                           default_mode.vrefresh);
 347                 return -ENOMEM;
 348         }
 349 
 350         drm_mode_set_name(mode);
 351 
 352         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 353         drm_mode_probed_add(panel->connector, mode);
 354 
 355         panel->connector->display_info.width_mm = mode->width_mm;
 356         panel->connector->display_info.height_mm = mode->height_mm;
 357 
 358         return 1;
 359 }
 360 
 361 static const struct drm_panel_funcs rm68200_drm_funcs = {
 362         .disable = rm68200_disable,
 363         .unprepare = rm68200_unprepare,
 364         .prepare = rm68200_prepare,
 365         .enable = rm68200_enable,
 366         .get_modes = rm68200_get_modes,
 367 };
 368 
 369 static int rm68200_probe(struct mipi_dsi_device *dsi)
 370 {
 371         struct device *dev = &dsi->dev;
 372         struct rm68200 *ctx;
 373         int ret;
 374 
 375         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 376         if (!ctx)
 377                 return -ENOMEM;
 378 
 379         ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 380         if (IS_ERR(ctx->reset_gpio)) {
 381                 ret = PTR_ERR(ctx->reset_gpio);
 382                 dev_err(dev, "cannot get reset GPIO: %d\n", ret);
 383                 return ret;
 384         }
 385 
 386         ctx->supply = devm_regulator_get(dev, "power");
 387         if (IS_ERR(ctx->supply)) {
 388                 ret = PTR_ERR(ctx->supply);
 389                 if (ret != -EPROBE_DEFER)
 390                         dev_err(dev, "cannot get regulator: %d\n", ret);
 391                 return ret;
 392         }
 393 
 394         ctx->backlight = devm_of_find_backlight(dev);
 395         if (IS_ERR(ctx->backlight))
 396                 return PTR_ERR(ctx->backlight);
 397 
 398         mipi_dsi_set_drvdata(dsi, ctx);
 399 
 400         ctx->dev = dev;
 401 
 402         dsi->lanes = 2;
 403         dsi->format = MIPI_DSI_FMT_RGB888;
 404         dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
 405                           MIPI_DSI_MODE_LPM;
 406 
 407         drm_panel_init(&ctx->panel);
 408         ctx->panel.dev = dev;
 409         ctx->panel.funcs = &rm68200_drm_funcs;
 410 
 411         drm_panel_add(&ctx->panel);
 412 
 413         ret = mipi_dsi_attach(dsi);
 414         if (ret < 0) {
 415                 dev_err(dev, "mipi_dsi_attach() failed: %d\n", ret);
 416                 drm_panel_remove(&ctx->panel);
 417                 return ret;
 418         }
 419 
 420         return 0;
 421 }
 422 
 423 static int rm68200_remove(struct mipi_dsi_device *dsi)
 424 {
 425         struct rm68200 *ctx = mipi_dsi_get_drvdata(dsi);
 426 
 427         mipi_dsi_detach(dsi);
 428         drm_panel_remove(&ctx->panel);
 429 
 430         return 0;
 431 }
 432 
 433 static const struct of_device_id raydium_rm68200_of_match[] = {
 434         { .compatible = "raydium,rm68200" },
 435         { }
 436 };
 437 MODULE_DEVICE_TABLE(of, raydium_rm68200_of_match);
 438 
 439 static struct mipi_dsi_driver raydium_rm68200_driver = {
 440         .probe = rm68200_probe,
 441         .remove = rm68200_remove,
 442         .driver = {
 443                 .name = "panel-raydium-rm68200",
 444                 .of_match_table = raydium_rm68200_of_match,
 445         },
 446 };
 447 module_mipi_dsi_driver(raydium_rm68200_driver);
 448 
 449 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
 450 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
 451 MODULE_DESCRIPTION("DRM Driver for Raydium RM68200 MIPI DSI panel");
 452 MODULE_LICENSE("GPL v2");

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