panel-sitronix-st7703.c (18484B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Driver for panels based on Sitronix ST7703 controller, souch as: 4 * 5 * - Rocktech jh057n00900 5.5" MIPI-DSI panel 6 * 7 * Copyright (C) Purism SPC 2019 8 */ 9 10#include <linux/debugfs.h> 11#include <linux/delay.h> 12#include <linux/gpio/consumer.h> 13#include <linux/media-bus-format.h> 14#include <linux/mod_devicetable.h> 15#include <linux/module.h> 16#include <linux/of_device.h> 17#include <linux/regulator/consumer.h> 18 19#include <video/display_timing.h> 20#include <video/mipi_display.h> 21 22#include <drm/drm_mipi_dsi.h> 23#include <drm/drm_modes.h> 24#include <drm/drm_panel.h> 25 26#define DRV_NAME "panel-sitronix-st7703" 27 28/* Manufacturer specific Commands send via DSI */ 29#define ST7703_CMD_ALL_PIXEL_OFF 0x22 30#define ST7703_CMD_ALL_PIXEL_ON 0x23 31#define ST7703_CMD_SETDISP 0xB2 32#define ST7703_CMD_SETRGBIF 0xB3 33#define ST7703_CMD_SETCYC 0xB4 34#define ST7703_CMD_SETBGP 0xB5 35#define ST7703_CMD_SETVCOM 0xB6 36#define ST7703_CMD_SETOTP 0xB7 37#define ST7703_CMD_SETPOWER_EXT 0xB8 38#define ST7703_CMD_SETEXTC 0xB9 39#define ST7703_CMD_SETMIPI 0xBA 40#define ST7703_CMD_SETVDC 0xBC 41#define ST7703_CMD_UNKNOWN_BF 0xBF 42#define ST7703_CMD_SETSCR 0xC0 43#define ST7703_CMD_SETPOWER 0xC1 44#define ST7703_CMD_SETPANEL 0xCC 45#define ST7703_CMD_UNKNOWN_C6 0xC6 46#define ST7703_CMD_SETGAMMA 0xE0 47#define ST7703_CMD_SETEQ 0xE3 48#define ST7703_CMD_SETGIP1 0xE9 49#define ST7703_CMD_SETGIP2 0xEA 50 51struct st7703 { 52 struct device *dev; 53 struct drm_panel panel; 54 struct gpio_desc *reset_gpio; 55 struct regulator *vcc; 56 struct regulator *iovcc; 57 bool prepared; 58 59 struct dentry *debugfs; 60 const struct st7703_panel_desc *desc; 61}; 62 63struct st7703_panel_desc { 64 const struct drm_display_mode *mode; 65 unsigned int lanes; 66 unsigned long mode_flags; 67 enum mipi_dsi_pixel_format format; 68 int (*init_sequence)(struct st7703 *ctx); 69}; 70 71static inline struct st7703 *panel_to_st7703(struct drm_panel *panel) 72{ 73 return container_of(panel, struct st7703, panel); 74} 75 76#define dsi_generic_write_seq(dsi, seq...) do { \ 77 static const u8 d[] = { seq }; \ 78 int ret; \ 79 ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ 80 if (ret < 0) \ 81 return ret; \ 82 } while (0) 83 84static int jh057n_init_sequence(struct st7703 *ctx) 85{ 86 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 87 88 /* 89 * Init sequence was supplied by the panel vendor. Most of the commands 90 * resemble the ST7703 but the number of parameters often don't match 91 * so it's likely a clone. 92 */ 93 dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC, 94 0xF1, 0x12, 0x83); 95 dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF, 96 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, 97 0x00, 0x00); 98 dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR, 99 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, 100 0x00); 101 dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); 102 dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); 103 dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 104 dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); 105 dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ, 106 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, 107 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); 108 dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08); 109 msleep(20); 110 111 dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F); 112 dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 113 dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1, 114 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, 115 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 116 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 117 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 118 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 119 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 120 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 122 dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2, 123 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 124 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 125 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 126 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 127 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 130 0xA5, 0x00, 0x00, 0x00, 0x00); 131 dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA, 132 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, 133 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, 134 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 135 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 136 0x11, 0x18); 137 138 return 0; 139} 140 141static const struct drm_display_mode jh057n00900_mode = { 142 .hdisplay = 720, 143 .hsync_start = 720 + 90, 144 .hsync_end = 720 + 90 + 20, 145 .htotal = 720 + 90 + 20 + 20, 146 .vdisplay = 1440, 147 .vsync_start = 1440 + 20, 148 .vsync_end = 1440 + 20 + 4, 149 .vtotal = 1440 + 20 + 4 + 12, 150 .clock = 75276, 151 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 152 .width_mm = 65, 153 .height_mm = 130, 154}; 155 156static const struct st7703_panel_desc jh057n00900_panel_desc = { 157 .mode = &jh057n00900_mode, 158 .lanes = 4, 159 .mode_flags = MIPI_DSI_MODE_VIDEO | 160 MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, 161 .format = MIPI_DSI_FMT_RGB888, 162 .init_sequence = jh057n_init_sequence, 163}; 164 165#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \ 166 static const u8 d[] = { seq }; \ 167 int ret; \ 168 ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \ 169 if (ret < 0) \ 170 return ret; \ 171 } while (0) 172 173 174static int xbd599_init_sequence(struct st7703 *ctx) 175{ 176 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 177 178 /* 179 * Init sequence was supplied by the panel vendor. 180 */ 181 182 /* Magic sequence to unlock user commands below. */ 183 dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83); 184 185 dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 186 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */ 187 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */ 188 0x05, /* IHSRX = x6 (Low High Speed driving ability) */ 189 0xF9, /* TX_CLK_SEL = fDSICLK/16 */ 190 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */ 191 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */ 192 /* The rest is undocumented in ST7703 datasheet */ 193 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 194 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 195 0x4F, 0x11, 0x00, 0x00, 0x37); 196 197 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 198 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */ 199 0x22, /* DT = 15ms XDK_ECP = x2 */ 200 0x20, /* PFM_DC_DIV = /1 */ 201 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */); 202 203 /* RGB I/F porch timing */ 204 dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 205 0x10, /* VBP_RGB_GEN */ 206 0x10, /* VFP_RGB_GEN */ 207 0x05, /* DE_BP_RGB_GEN */ 208 0x05, /* DE_FP_RGB_GEN */ 209 /* The rest is undocumented in ST7703 datasheet */ 210 0x03, 0xFF, 211 0x00, 0x00, 212 0x00, 0x00); 213 214 /* Source driving settings. */ 215 dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 216 0x73, /* N_POPON */ 217 0x73, /* N_NOPON */ 218 0x50, /* I_POPON */ 219 0x50, /* I_NOPON */ 220 0x00, /* SCR[31,24] */ 221 0xC0, /* SCR[23,16] */ 222 0x08, /* SCR[15,8] */ 223 0x70, /* SCR[7,0] */ 224 0x00 /* Undocumented */); 225 226 /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */ 227 dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); 228 229 /* 230 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan) 231 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR) 232 */ 233 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); 234 235 /* Zig-Zag Type C column inversion. */ 236 dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 237 238 /* Set display resolution. */ 239 dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 240 0xF0, /* NL = 240 */ 241 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD, 242 * RESO_SEL = 720RGB 243 */ 244 0xF0 /* WHITE_GND_EN = 1 (GND), 245 * WHITE_FRAME_SEL = 7 frames, 246 * ISC = 0 frames 247 */); 248 249 dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 250 0x00, /* PNOEQ */ 251 0x00, /* NNOEQ */ 252 0x0B, /* PEQGND */ 253 0x0B, /* NEQGND */ 254 0x10, /* PEQVCI */ 255 0x10, /* NEQVCI */ 256 0x00, /* PEQVCI1 */ 257 0x00, /* NEQVCI1 */ 258 0x00, /* reserved */ 259 0x00, /* reserved */ 260 0xFF, /* reserved */ 261 0x00, /* reserved */ 262 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */ 263 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in) 264 * VEDIO_NO_CHECK_EN = 0 265 * ESD_WHITE_GND_EN = 0 266 * ESD_DET_TIME_SEL = 0 frames 267 */); 268 269 /* Undocumented command. */ 270 dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00); 271 272 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 273 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */ 274 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */ 275 0x32, /* VRP */ 276 0x32, /* VRN */ 277 0x77, /* reserved */ 278 0xF1, /* APS = 1 (small), 279 * VGL_DET_EN = 1, VGH_DET_EN = 1, 280 * VGL_TURBO = 1, VGH_TURBO = 1 281 */ 282 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */ 283 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */ 284 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */ 285 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */ 286 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */ 287 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */); 288 289 /* Reference voltage. */ 290 dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 291 0x07, /* VREF_SEL = 4.2V */ 292 0x07 /* NVREF_SEL = 4.2V */); 293 msleep(20); 294 295 dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 296 0x2C, /* VCOMDC_F = -0.67V */ 297 0x2C /* VCOMDC_B = -0.67V */); 298 299 /* Undocumented command. */ 300 dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 301 302 /* This command is to set forward GIP timing. */ 303 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 304 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12, 305 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 306 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 307 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 308 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 309 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 310 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 312 313 /* This command is to set backward GIP timing. */ 314 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 315 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 317 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 318 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 319 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 322 0xA5, 0x00, 0x00, 0x00, 0x00); 323 324 /* Adjust the gamma characteristics of the panel. */ 325 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 326 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35, 327 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12, 328 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 329 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 330 0x12, 0x18); 331 332 return 0; 333} 334 335static const struct drm_display_mode xbd599_mode = { 336 .hdisplay = 720, 337 .hsync_start = 720 + 40, 338 .hsync_end = 720 + 40 + 40, 339 .htotal = 720 + 40 + 40 + 40, 340 .vdisplay = 1440, 341 .vsync_start = 1440 + 18, 342 .vsync_end = 1440 + 18 + 10, 343 .vtotal = 1440 + 18 + 10 + 17, 344 .clock = 69000, 345 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 346 .width_mm = 68, 347 .height_mm = 136, 348}; 349 350static const struct st7703_panel_desc xbd599_desc = { 351 .mode = &xbd599_mode, 352 .lanes = 4, 353 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, 354 .format = MIPI_DSI_FMT_RGB888, 355 .init_sequence = xbd599_init_sequence, 356}; 357 358static int st7703_enable(struct drm_panel *panel) 359{ 360 struct st7703 *ctx = panel_to_st7703(panel); 361 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 362 int ret; 363 364 ret = ctx->desc->init_sequence(ctx); 365 if (ret < 0) { 366 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); 367 return ret; 368 } 369 370 msleep(20); 371 372 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 373 if (ret < 0) { 374 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); 375 return ret; 376 } 377 378 /* Panel is operational 120 msec after reset */ 379 msleep(60); 380 381 ret = mipi_dsi_dcs_set_display_on(dsi); 382 if (ret) 383 return ret; 384 385 dev_dbg(ctx->dev, "Panel init sequence done\n"); 386 387 return 0; 388} 389 390static int st7703_disable(struct drm_panel *panel) 391{ 392 struct st7703 *ctx = panel_to_st7703(panel); 393 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 394 int ret; 395 396 ret = mipi_dsi_dcs_set_display_off(dsi); 397 if (ret < 0) 398 dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret); 399 400 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 401 if (ret < 0) 402 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); 403 404 return 0; 405} 406 407static int st7703_unprepare(struct drm_panel *panel) 408{ 409 struct st7703 *ctx = panel_to_st7703(panel); 410 411 if (!ctx->prepared) 412 return 0; 413 414 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 415 regulator_disable(ctx->iovcc); 416 regulator_disable(ctx->vcc); 417 ctx->prepared = false; 418 419 return 0; 420} 421 422static int st7703_prepare(struct drm_panel *panel) 423{ 424 struct st7703 *ctx = panel_to_st7703(panel); 425 int ret; 426 427 if (ctx->prepared) 428 return 0; 429 430 dev_dbg(ctx->dev, "Resetting the panel\n"); 431 ret = regulator_enable(ctx->vcc); 432 if (ret < 0) { 433 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret); 434 return ret; 435 } 436 ret = regulator_enable(ctx->iovcc); 437 if (ret < 0) { 438 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); 439 goto disable_vcc; 440 } 441 442 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 443 usleep_range(20, 40); 444 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 445 msleep(20); 446 447 ctx->prepared = true; 448 449 return 0; 450 451disable_vcc: 452 regulator_disable(ctx->vcc); 453 return ret; 454} 455 456static const u32 mantix_bus_formats[] = { 457 MEDIA_BUS_FMT_RGB888_1X24, 458}; 459 460static int st7703_get_modes(struct drm_panel *panel, 461 struct drm_connector *connector) 462{ 463 struct st7703 *ctx = panel_to_st7703(panel); 464 struct drm_display_mode *mode; 465 466 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); 467 if (!mode) { 468 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", 469 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 470 drm_mode_vrefresh(ctx->desc->mode)); 471 return -ENOMEM; 472 } 473 474 drm_mode_set_name(mode); 475 476 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 477 connector->display_info.width_mm = mode->width_mm; 478 connector->display_info.height_mm = mode->height_mm; 479 drm_mode_probed_add(connector, mode); 480 481 drm_display_info_set_bus_formats(&connector->display_info, 482 mantix_bus_formats, 483 ARRAY_SIZE(mantix_bus_formats)); 484 485 return 1; 486} 487 488static const struct drm_panel_funcs st7703_drm_funcs = { 489 .disable = st7703_disable, 490 .unprepare = st7703_unprepare, 491 .prepare = st7703_prepare, 492 .enable = st7703_enable, 493 .get_modes = st7703_get_modes, 494}; 495 496static int allpixelson_set(void *data, u64 val) 497{ 498 struct st7703 *ctx = data; 499 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 500 501 dev_dbg(ctx->dev, "Setting all pixels on\n"); 502 dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); 503 msleep(val * 1000); 504 /* Reset the panel to get video back */ 505 drm_panel_disable(&ctx->panel); 506 drm_panel_unprepare(&ctx->panel); 507 drm_panel_prepare(&ctx->panel); 508 drm_panel_enable(&ctx->panel); 509 510 return 0; 511} 512 513DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL, 514 allpixelson_set, "%llu\n"); 515 516static void st7703_debugfs_init(struct st7703 *ctx) 517{ 518 ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL); 519 520 debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx, 521 &allpixelson_fops); 522} 523 524static void st7703_debugfs_remove(struct st7703 *ctx) 525{ 526 debugfs_remove_recursive(ctx->debugfs); 527 ctx->debugfs = NULL; 528} 529 530static int st7703_probe(struct mipi_dsi_device *dsi) 531{ 532 struct device *dev = &dsi->dev; 533 struct st7703 *ctx; 534 int ret; 535 536 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 537 if (!ctx) 538 return -ENOMEM; 539 540 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 541 if (IS_ERR(ctx->reset_gpio)) 542 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n"); 543 544 mipi_dsi_set_drvdata(dsi, ctx); 545 546 ctx->dev = dev; 547 ctx->desc = of_device_get_match_data(dev); 548 549 dsi->mode_flags = ctx->desc->mode_flags; 550 dsi->format = ctx->desc->format; 551 dsi->lanes = ctx->desc->lanes; 552 553 ctx->vcc = devm_regulator_get(dev, "vcc"); 554 if (IS_ERR(ctx->vcc)) 555 return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n"); 556 557 ctx->iovcc = devm_regulator_get(dev, "iovcc"); 558 if (IS_ERR(ctx->iovcc)) 559 return dev_err_probe(dev, PTR_ERR(ctx->iovcc), 560 "Failed to request iovcc regulator\n"); 561 562 drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs, 563 DRM_MODE_CONNECTOR_DSI); 564 565 ret = drm_panel_of_backlight(&ctx->panel); 566 if (ret) 567 return ret; 568 569 drm_panel_add(&ctx->panel); 570 571 ret = mipi_dsi_attach(dsi); 572 if (ret < 0) { 573 dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret); 574 drm_panel_remove(&ctx->panel); 575 return ret; 576 } 577 578 dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", 579 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 580 drm_mode_vrefresh(ctx->desc->mode), 581 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); 582 583 st7703_debugfs_init(ctx); 584 return 0; 585} 586 587static void st7703_shutdown(struct mipi_dsi_device *dsi) 588{ 589 struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); 590 int ret; 591 592 ret = drm_panel_unprepare(&ctx->panel); 593 if (ret < 0) 594 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); 595 596 ret = drm_panel_disable(&ctx->panel); 597 if (ret < 0) 598 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); 599} 600 601static int st7703_remove(struct mipi_dsi_device *dsi) 602{ 603 struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); 604 int ret; 605 606 st7703_shutdown(dsi); 607 608 ret = mipi_dsi_detach(dsi); 609 if (ret < 0) 610 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 611 612 drm_panel_remove(&ctx->panel); 613 614 st7703_debugfs_remove(ctx); 615 616 return 0; 617} 618 619static const struct of_device_id st7703_of_match[] = { 620 { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc }, 621 { .compatible = "xingbangda,xbd599", .data = &xbd599_desc }, 622 { /* sentinel */ } 623}; 624MODULE_DEVICE_TABLE(of, st7703_of_match); 625 626static struct mipi_dsi_driver st7703_driver = { 627 .probe = st7703_probe, 628 .remove = st7703_remove, 629 .shutdown = st7703_shutdown, 630 .driver = { 631 .name = DRV_NAME, 632 .of_match_table = st7703_of_match, 633 }, 634}; 635module_mipi_dsi_driver(st7703_driver); 636 637MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); 638MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels"); 639MODULE_LICENSE("GPL v2");