1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Driver for panels based on Sitronix ST7703 controller, such 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/module.h> 15 #include <linux/of.h> 16 #include <linux/regulator/consumer.h> 17 18 #include <video/display_timing.h> 19 #include <video/mipi_display.h> 20 21 #include <drm/drm_mipi_dsi.h> 22 #include <drm/drm_modes.h> 23 #include <drm/drm_of.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_SETAPID 0xB1 32 #define ST7703_CMD_SETDISP 0xB2 33 #define ST7703_CMD_SETRGBIF 0xB3 34 #define ST7703_CMD_SETCYC 0xB4 35 #define ST7703_CMD_SETBGP 0xB5 36 #define ST7703_CMD_SETVCOM 0xB6 37 #define ST7703_CMD_SETOTP 0xB7 38 #define ST7703_CMD_SETPOWER_EXT 0xB8 39 #define ST7703_CMD_SETEXTC 0xB9 40 #define ST7703_CMD_SETMIPI 0xBA 41 #define ST7703_CMD_SETVDC 0xBC 42 #define ST7703_CMD_UNKNOWN_BF 0xBF 43 #define ST7703_CMD_SETSCR 0xC0 44 #define ST7703_CMD_SETPOWER 0xC1 45 #define ST7703_CMD_SETECO 0xC6 46 #define ST7703_CMD_SETIO 0xC7 47 #define ST7703_CMD_SETCABC 0xC8 48 #define ST7703_CMD_SETPANEL 0xCC 49 #define ST7703_CMD_SETGAMMA 0xE0 50 #define ST7703_CMD_UNKNOWN_E1 0xE1 51 #define ST7703_CMD_SETEQ 0xE3 52 #define ST7703_CMD_SETGIP1 0xE9 53 #define ST7703_CMD_SETGIP2 0xEA 54 #define ST7703_CMD_UNKNOWN_EF 0xEF 55 56 struct st7703 { 57 struct device *dev; 58 struct drm_panel panel; 59 struct gpio_desc *reset_gpio; 60 struct regulator *vcc; 61 struct regulator *iovcc; 62 63 struct dentry *debugfs; 64 const struct st7703_panel_desc *desc; 65 enum drm_panel_orientation orientation; 66 }; 67 68 struct st7703_panel_desc { 69 const struct drm_display_mode *mode; 70 unsigned int lanes; 71 unsigned long mode_flags; 72 enum mipi_dsi_pixel_format format; 73 void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx); 74 }; 75 76 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel) 77 { 78 return container_of(panel, struct st7703, panel); 79 } 80 81 static void jh057n_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 82 { 83 /* 84 * Init sequence was supplied by the panel vendor. Most of the commands 85 * resemble the ST7703 but the number of parameters often don't match 86 * so it's likely a clone. 87 */ 88 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 89 0xF1, 0x12, 0x83); 90 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 91 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, 92 0x00, 0x00); 93 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 94 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, 95 0x00); 96 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E); 97 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B); 98 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 99 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); 100 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 101 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, 102 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); 103 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x08, 0x08); 104 mipi_dsi_msleep(dsi_ctx, 20); 105 106 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x3F, 0x3F); 107 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 108 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 109 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, 110 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 111 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 112 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 113 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 114 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 115 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 117 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 118 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 119 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 120 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 121 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 122 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 125 0xA5, 0x00, 0x00, 0x00, 0x00); 126 mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 127 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, 128 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, 129 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 130 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 131 0x11, 0x18); 132 mipi_dsi_msleep(dsi_ctx, 20); 133 } 134 135 static const struct drm_display_mode jh057n00900_mode = { 136 .hdisplay = 720, 137 .hsync_start = 720 + 90, 138 .hsync_end = 720 + 90 + 20, 139 .htotal = 720 + 90 + 20 + 20, 140 .vdisplay = 1440, 141 .vsync_start = 1440 + 20, 142 .vsync_end = 1440 + 20 + 4, 143 .vtotal = 1440 + 20 + 4 + 12, 144 .clock = 75276, 145 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 146 .width_mm = 65, 147 .height_mm = 130, 148 }; 149 150 static const struct st7703_panel_desc jh057n00900_panel_desc = { 151 .mode = &jh057n00900_mode, 152 .lanes = 4, 153 .mode_flags = MIPI_DSI_MODE_VIDEO | 154 MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, 155 .format = MIPI_DSI_FMT_RGB888, 156 .init_sequence = jh057n_init_sequence, 157 }; 158 159 static void xbd599_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 160 { 161 /* 162 * Init sequence was supplied by the panel vendor. 163 */ 164 165 /* Magic sequence to unlock user commands below. */ 166 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83); 167 168 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 169 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */ 170 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */ 171 0x05, /* IHSRX = x6 (Low High Speed driving ability) */ 172 0xF9, /* TX_CLK_SEL = fDSICLK/16 */ 173 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */ 174 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */ 175 /* The rest is undocumented in ST7703 datasheet */ 176 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 178 0x4F, 0x11, 0x00, 0x00, 0x37); 179 180 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 181 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */ 182 0x22, /* DT = 15ms XDK_ECP = x2 */ 183 0x20, /* PFM_DC_DIV = /1 */ 184 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */); 185 186 /* RGB I/F porch timing */ 187 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 188 0x10, /* VBP_RGB_GEN */ 189 0x10, /* VFP_RGB_GEN */ 190 0x05, /* DE_BP_RGB_GEN */ 191 0x05, /* DE_FP_RGB_GEN */ 192 /* The rest is undocumented in ST7703 datasheet */ 193 0x03, 0xFF, 194 0x00, 0x00, 195 0x00, 0x00); 196 197 /* Source driving settings. */ 198 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 199 0x73, /* N_POPON */ 200 0x73, /* N_NOPON */ 201 0x50, /* I_POPON */ 202 0x50, /* I_NOPON */ 203 0x00, /* SCR[31,24] */ 204 0xC0, /* SCR[23,16] */ 205 0x08, /* SCR[15,8] */ 206 0x70, /* SCR[7,0] */ 207 0x00 /* Undocumented */); 208 209 /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */ 210 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E); 211 212 /* 213 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan) 214 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR) 215 */ 216 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B); 217 218 /* Zig-Zag Type C column inversion. */ 219 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 220 221 /* Set display resolution. */ 222 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 223 0xF0, /* NL = 240 */ 224 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD, 225 * RESO_SEL = 720RGB 226 */ 227 0xF0 /* WHITE_GND_EN = 1 (GND), 228 * WHITE_FRAME_SEL = 7 frames, 229 * ISC = 0 frames 230 */); 231 232 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 233 0x00, /* PNOEQ */ 234 0x00, /* NNOEQ */ 235 0x0B, /* PEQGND */ 236 0x0B, /* NEQGND */ 237 0x10, /* PEQVCI */ 238 0x10, /* NEQVCI */ 239 0x00, /* PEQVCI1 */ 240 0x00, /* NEQVCI1 */ 241 0x00, /* reserved */ 242 0x00, /* reserved */ 243 0xFF, /* reserved */ 244 0x00, /* reserved */ 245 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */ 246 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in) 247 * VEDIO_NO_CHECK_EN = 0 248 * ESD_WHITE_GND_EN = 0 249 * ESD_DET_TIME_SEL = 0 frames 250 */); 251 252 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00); 253 254 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 255 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */ 256 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */ 257 0x32, /* VRP */ 258 0x32, /* VRN */ 259 0x77, /* reserved */ 260 0xF1, /* APS = 1 (small), 261 * VGL_DET_EN = 1, VGH_DET_EN = 1, 262 * VGL_TURBO = 1, VGH_TURBO = 1 263 */ 264 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */ 265 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */ 266 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */ 267 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */ 268 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */ 269 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */); 270 271 /* Reference voltage. */ 272 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 273 0x07, /* VREF_SEL = 4.2V */ 274 0x07 /* NVREF_SEL = 4.2V */); 275 276 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 277 0x2C, /* VCOMDC_F = -0.67V */ 278 0x2C /* VCOMDC_B = -0.67V */); 279 280 /* Undocumented command. */ 281 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 282 283 /* This command is to set forward GIP timing. */ 284 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 285 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12, 286 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 287 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 288 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 289 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 290 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 291 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 293 294 /* This command is to set backward GIP timing. */ 295 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 296 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 297 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 298 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 299 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 300 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 303 0xA5, 0x00, 0x00, 0x00, 0x00); 304 305 /* Adjust the gamma characteristics of the panel. */ 306 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 307 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35, 308 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12, 309 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 310 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 311 0x12, 0x18); 312 } 313 314 static const struct drm_display_mode xbd599_mode = { 315 .hdisplay = 720, 316 .hsync_start = 720 + 40, 317 .hsync_end = 720 + 40 + 40, 318 .htotal = 720 + 40 + 40 + 40, 319 .vdisplay = 1440, 320 .vsync_start = 1440 + 18, 321 .vsync_end = 1440 + 18 + 10, 322 .vtotal = 1440 + 18 + 10 + 17, 323 .clock = 69000, 324 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 325 .width_mm = 68, 326 .height_mm = 136, 327 }; 328 329 static const struct st7703_panel_desc xbd599_desc = { 330 .mode = &xbd599_mode, 331 .lanes = 4, 332 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, 333 .format = MIPI_DSI_FMT_RGB888, 334 .init_sequence = xbd599_init_sequence, 335 }; 336 337 static void rg353v2_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 338 { 339 /* 340 * Init sequence was supplied by the panel vendor. 341 */ 342 343 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 344 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 345 0xda, 0x80); 346 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70); 347 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 348 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 349 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 350 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); 351 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x92, 0x92); 352 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 353 0xf0, 0x63); 354 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 355 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 356 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 357 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 358 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); 359 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 360 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 361 0x00, 0x00, 0x12, 0x50, 0x00); 362 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32, 363 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33, 364 0x33); 365 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 366 0x00, 0xff); 367 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 368 0x00, 0x00); 369 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 370 0x02); 371 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 372 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d, 373 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d, 374 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07, 375 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 376 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a); 377 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 378 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 379 0xc0, 0x10); 380 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00, 381 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80, 382 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 383 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 384 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 385 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 386 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 387 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00); 389 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 390 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 392 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42, 393 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 394 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 0x00); 398 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 399 } 400 401 static const struct drm_display_mode rg353v2_mode = { 402 .hdisplay = 640, 403 .hsync_start = 640 + 40, 404 .hsync_end = 640 + 40 + 2, 405 .htotal = 640 + 40 + 2 + 80, 406 .vdisplay = 480, 407 .vsync_start = 480 + 18, 408 .vsync_end = 480 + 18 + 2, 409 .vtotal = 480 + 18 + 2 + 28, 410 .clock = 24150, 411 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 412 .width_mm = 70, 413 .height_mm = 57, 414 }; 415 416 static const struct st7703_panel_desc rg353v2_desc = { 417 .mode = &rg353v2_mode, 418 .lanes = 4, 419 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 420 MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, 421 .format = MIPI_DSI_FMT_RGB888, 422 .init_sequence = rg353v2_init_sequence, 423 }; 424 425 static void rgb30panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 426 { 427 /* Init sequence extracted from Powkiddy RGB30 BSP kernel. */ 428 429 /* 430 * For some reason this specific panel must be taken out of sleep 431 * before the full init sequence, or else it will not display. 432 */ 433 mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 434 mipi_dsi_msleep(dsi_ctx, 250); 435 436 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 437 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 438 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 439 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 440 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 441 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 442 0x63); 443 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 444 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 445 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 446 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 447 0x00, 0x00, 0x12, 0x70, 0x00); 448 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46); 449 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 450 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 451 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30); 452 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 453 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 454 0xc0, 0x10); 455 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32, 456 0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33, 457 0x33); 458 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); 459 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x88, 0x88); 460 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10, 461 0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86, 462 0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00, 463 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 464 0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88, 465 0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57, 466 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 468 0x00, 0x00, 0x00); 469 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01, 470 0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 471 0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88, 472 0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20, 473 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 474 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 476 0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00, 477 0x00); 478 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f, 479 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10, 480 0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a, 481 0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 482 0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17); 483 } 484 485 static const struct drm_display_mode rgb30panel_mode = { 486 .hdisplay = 720, 487 .hsync_start = 720 + 45, 488 .hsync_end = 720 + 45 + 4, 489 .htotal = 720 + 45 + 4 + 45, 490 .vdisplay = 720, 491 .vsync_start = 720 + 15, 492 .vsync_end = 720 + 15 + 3, 493 .vtotal = 720 + 15 + 3 + 11, 494 .clock = 36570, 495 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 496 .width_mm = 76, 497 .height_mm = 76, 498 }; 499 500 static const struct st7703_panel_desc rgb30panel_desc = { 501 .mode = &rgb30panel_mode, 502 .lanes = 4, 503 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 504 MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, 505 .format = MIPI_DSI_FMT_RGB888, 506 .init_sequence = rgb30panel_init_sequence, 507 }; 508 509 static void rgb10max3_panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 510 { 511 /* Init sequence extracted from Powkiddy RGB10MAX3 BSP kernel. */ 512 513 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 514 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda, 515 0x80); 516 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30); 517 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 518 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 519 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 520 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x04, 0x04); 521 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x78, 0x78); 522 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 523 0x63); 524 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 525 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 526 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 527 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 528 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); 529 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 530 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 531 0x00, 0x00, 0x12, 0x70, 0x00); 532 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32, 533 0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77, 534 0x77); 535 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 536 0x00, 0xff); 537 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 538 0x00, 0x00); 539 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 540 0x02); 541 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 542 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07, 543 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e, 544 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04, 545 0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 546 0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17); 547 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03, 548 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 549 0xc0, 0x10); 550 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00, 551 0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86, 552 0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00, 553 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 554 0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88, 555 0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88, 556 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 558 0x00, 0x00, 0x00); 559 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00, 560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 561 0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88, 562 0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88, 563 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00, 564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 567 0x00); 568 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 569 } 570 571 static const struct drm_display_mode rgb10max3_panel_mode = { 572 .hdisplay = 720, 573 .hsync_start = 720 + 40, 574 .hsync_end = 720 + 40 + 10, 575 .htotal = 720 + 40 + 10 + 40, 576 .vdisplay = 1280, 577 .vsync_start = 1280 + 16, 578 .vsync_end = 1280 + 16 + 4, 579 .vtotal = 1280 + 16 + 4 + 14, 580 .clock = 63800, 581 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 582 .width_mm = 62, 583 .height_mm = 109, 584 }; 585 586 static const struct st7703_panel_desc rgb10max3_panel_desc = { 587 .mode = &rgb10max3_panel_mode, 588 .lanes = 4, 589 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 590 MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, 591 .format = MIPI_DSI_FMT_RGB888, 592 .init_sequence = rgb10max3_panel_init_sequence, 593 }; 594 595 static void gameforcechi_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 596 { 597 /* 598 * Init sequence was supplied by the panel vendor. Panel will not 599 * respond to commands until it is brought out of sleep mode first. 600 */ 601 602 mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 603 mipi_dsi_msleep(dsi_ctx, 250); 604 605 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 606 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9, 607 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 608 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 609 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37); 610 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25); 611 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 612 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a, 613 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 614 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 615 0x00, 0x00, 0x08, 0x70, 0x00); 616 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46); 617 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 618 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 619 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0); 620 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 621 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 622 0xc0, 0x10); 623 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e, 624 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33, 625 0x33); 626 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x10, 0x10); 627 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x6c, 0x7c); 628 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00, 629 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10, 630 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 631 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 632 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 633 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 634 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 635 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 636 0x00, 0x00, 0x00); 637 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 638 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 639 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 640 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42, 641 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10, 642 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 645 0x00); 646 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b, 647 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b, 648 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07, 649 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0, 650 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18); 651 } 652 653 static const struct drm_display_mode gameforcechi_mode = { 654 .hdisplay = 640, 655 .hsync_start = 640 + 40, 656 .hsync_end = 640 + 40 + 2, 657 .htotal = 640 + 40 + 2 + 80, 658 .vdisplay = 480, 659 .vsync_start = 480 + 17, 660 .vsync_end = 480 + 17 + 5, 661 .vtotal = 480 + 17 + 5 + 13, 662 .clock = 23546, 663 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 664 .width_mm = 71, 665 .height_mm = 53, 666 }; 667 668 static const struct st7703_panel_desc gameforcechi_desc = { 669 .mode = &gameforcechi_mode, 670 .lanes = 2, 671 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 672 MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM, 673 .format = MIPI_DSI_FMT_RGB888, 674 .init_sequence = gameforcechi_init_sequence, 675 }; 676 677 static void ayaneo_pocket_ds_lower_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 678 { 679 /* Init sequence extracted from the AYANEO Pocket DS BSP kernel. */ 680 681 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 682 0x87); 683 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x01, 684 0x78); 685 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 686 0x28, 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 687 0x00); 688 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 689 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); 690 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x90, 0x90); 691 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x76, 692 0x22, 0xf0, 0x13); 693 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 694 0x05, 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 695 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, 696 0x00, 0x91, 0x0a, 0x00, 0x00, 0x01, 0x4f, 697 0x01, 0x00, 0x00, 0x37); 698 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); 699 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x10, 700 0x00, 0x80, 0x04); 701 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 702 0x50, 0x50, 0x00, 0x00, 0x12, 0x73, 0x00); 703 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x55, 0x00, 704 0x32, 0x32, 0x77, 0xf1, 0xf7, 0xf7, 0xcc, 705 0xcc, 0x7f, 0x7f, 0x11, 0x11, 0x00, 0x00, 706 0x32); 707 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 708 0x0a, 0x10, 0x01, 0x09, 0x00, 0x00, 0xed, 709 0xc5, 0x00, 0xa5); 710 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 711 0x1e, 0x03); 712 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 713 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x00, 714 0x00, 0x25, 0x31, 0x3f, 0x26, 0x29, 0x04, 715 0x08, 0x0d, 0x0e, 0x12, 0x0f, 0x11, 0x12, 716 0x18, 0x00, 0x00, 0x00, 0x25, 0x31, 0x3f, 717 0x26, 0x29, 0x04, 0x08, 0x0d, 0x0e, 0x12, 718 0x0f, 0x11, 0x12, 0x18); 719 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_E1, 0x11, 0x11, 720 0x91, 0x00, 0x00, 0x00, 0x00); 721 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 722 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x00, 0x00, 723 0x00, 0xff, 0x84, 0xc0, 0x10); 724 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 725 0x04, 0x04, 0x02, 0x80, 0x81, 0x12, 0x31, 726 0x23, 0x2f, 0x80, 0x80, 0x81, 0x27, 0x20, 727 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 728 0x00, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x00, 729 0x88, 0xff, 0x00, 0x22, 0x44, 0x66, 0x88, 730 0x88, 0x88, 0x55, 0x11, 0x88, 0xff, 0x11, 731 0x33, 0x55, 0x77, 0x88, 0x88, 0x88, 0x00, 732 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 733 0x00, 0x00, 0x00, 0x00, 0x00); 734 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x00, 0x00, 735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 736 0x00, 0x00, 0x00, 0x11, 0x55, 0xff, 0x88, 737 0x77, 0x55, 0x33, 0x11, 0x88, 0x88, 0x88, 738 0x00, 0x44, 0xff, 0x88, 0x66, 0x44, 0x22, 739 0x00, 0x88, 0x88, 0x88, 0x23, 0x00, 0x00, 740 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 742 0x00, 0x00, 0x00, 0x20, 0x80, 0x81, 0x00, 743 0x00, 0x00, 0x00); 744 mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 745 0x01); 746 } 747 748 static const struct drm_display_mode ayaneo_pocket_ds_lower_mode = { 749 .hdisplay = 768, 750 .hsync_start = 768 + 110, 751 .hsync_end = 768 + 110 + 45, 752 .htotal = 768 + 110 + 45 + 110, 753 .vdisplay = 1024, 754 .vsync_start = 1024 + 18, 755 .vsync_end = 1024 + 18 + 6, 756 .vtotal = 1024 + 18 + 6 + 16, 757 .clock = 65946, 758 .width_mm = 76, 759 .height_mm = 102, 760 }; 761 762 static const struct st7703_panel_desc ayaneo_pocket_ds_lower_desc = { 763 .mode = &ayaneo_pocket_ds_lower_mode, 764 .lanes = 4, 765 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 766 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM, 767 .format = MIPI_DSI_FMT_RGB888, 768 .init_sequence = ayaneo_pocket_ds_lower_init_sequence, 769 }; 770 771 static int st7703_enable(struct drm_panel *panel) 772 { 773 struct st7703 *ctx = panel_to_st7703(panel); 774 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 775 struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 776 777 ctx->desc->init_sequence(&dsi_ctx); 778 779 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 780 781 /* It takes the controller 120 msec to wake up after sleep. */ 782 mipi_dsi_msleep(&dsi_ctx, 120); 783 784 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 785 786 if (!dsi_ctx.accum_err) 787 dev_dbg(ctx->dev, "Panel init sequence done\n"); 788 789 return dsi_ctx.accum_err; 790 } 791 792 static int st7703_disable(struct drm_panel *panel) 793 { 794 struct st7703 *ctx = panel_to_st7703(panel); 795 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 796 struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 797 798 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 799 800 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 801 802 /* It takes the controller 120 msec to enter sleep mode. */ 803 mipi_dsi_msleep(&dsi_ctx, 120); 804 805 return dsi_ctx.accum_err; 806 } 807 808 static int st7703_unprepare(struct drm_panel *panel) 809 { 810 struct st7703 *ctx = panel_to_st7703(panel); 811 812 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 813 regulator_disable(ctx->iovcc); 814 regulator_disable(ctx->vcc); 815 816 return 0; 817 } 818 819 static int st7703_prepare(struct drm_panel *panel) 820 { 821 struct st7703 *ctx = panel_to_st7703(panel); 822 int ret; 823 824 dev_dbg(ctx->dev, "Resetting the panel\n"); 825 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 826 827 ret = regulator_enable(ctx->iovcc); 828 if (ret < 0) { 829 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); 830 return ret; 831 } 832 833 ret = regulator_enable(ctx->vcc); 834 if (ret < 0) { 835 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret); 836 regulator_disable(ctx->iovcc); 837 return ret; 838 } 839 840 /* Give power supplies time to stabilize before deasserting reset. */ 841 usleep_range(10000, 20000); 842 843 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 844 usleep_range(15000, 20000); 845 846 return 0; 847 } 848 849 static const u32 mantix_bus_formats[] = { 850 MEDIA_BUS_FMT_RGB888_1X24, 851 }; 852 853 static int st7703_get_modes(struct drm_panel *panel, 854 struct drm_connector *connector) 855 { 856 struct st7703 *ctx = panel_to_st7703(panel); 857 struct drm_display_mode *mode; 858 859 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); 860 if (!mode) { 861 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", 862 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 863 drm_mode_vrefresh(ctx->desc->mode)); 864 return -ENOMEM; 865 } 866 867 drm_mode_set_name(mode); 868 869 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 870 connector->display_info.width_mm = mode->width_mm; 871 connector->display_info.height_mm = mode->height_mm; 872 drm_mode_probed_add(connector, mode); 873 874 drm_display_info_set_bus_formats(&connector->display_info, 875 mantix_bus_formats, 876 ARRAY_SIZE(mantix_bus_formats)); 877 878 return 1; 879 } 880 881 static enum drm_panel_orientation st7703_get_orientation(struct drm_panel *panel) 882 { 883 struct st7703 *st7703 = panel_to_st7703(panel); 884 885 return st7703->orientation; 886 } 887 888 static const struct drm_panel_funcs st7703_drm_funcs = { 889 .disable = st7703_disable, 890 .unprepare = st7703_unprepare, 891 .prepare = st7703_prepare, 892 .enable = st7703_enable, 893 .get_modes = st7703_get_modes, 894 .get_orientation = st7703_get_orientation, 895 }; 896 897 static int allpixelson_set(void *data, u64 val) 898 { 899 struct st7703 *ctx = data; 900 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 901 struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 902 903 dev_dbg(ctx->dev, "Setting all pixels on\n"); 904 mipi_dsi_generic_write_seq_multi(&dsi_ctx, ST7703_CMD_ALL_PIXEL_ON); 905 mipi_dsi_msleep(&dsi_ctx, val * 1000); 906 907 /* 908 * Reset the panel to get video back. NOTE: This isn't a 909 * particularly safe thing to do in general because it assumes 910 * that the screen was on to begin with, but this is just a 911 * debugfs file so it's not a huge deal. 912 */ 913 drm_panel_disable(&ctx->panel); 914 drm_panel_unprepare(&ctx->panel); 915 drm_panel_prepare(&ctx->panel); 916 drm_panel_enable(&ctx->panel); 917 918 return dsi_ctx.accum_err; 919 } 920 921 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL, 922 allpixelson_set, "%llu\n"); 923 924 static void st7703_debugfs_init(struct st7703 *ctx) 925 { 926 ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL); 927 928 debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx, 929 &allpixelson_fops); 930 } 931 932 static void st7703_debugfs_remove(struct st7703 *ctx) 933 { 934 debugfs_remove_recursive(ctx->debugfs); 935 ctx->debugfs = NULL; 936 } 937 938 static int st7703_probe(struct mipi_dsi_device *dsi) 939 { 940 struct device *dev = &dsi->dev; 941 struct st7703 *ctx; 942 int ret; 943 944 ctx = devm_drm_panel_alloc(dev, struct st7703, panel, 945 &st7703_drm_funcs, 946 DRM_MODE_CONNECTOR_DSI); 947 if (IS_ERR(ctx)) 948 return PTR_ERR(ctx); 949 950 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 951 if (IS_ERR(ctx->reset_gpio)) 952 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n"); 953 954 mipi_dsi_set_drvdata(dsi, ctx); 955 956 ctx->dev = dev; 957 ctx->desc = of_device_get_match_data(dev); 958 959 dsi->mode_flags = ctx->desc->mode_flags; 960 dsi->format = ctx->desc->format; 961 dsi->lanes = ctx->desc->lanes; 962 963 ctx->vcc = devm_regulator_get(dev, "vcc"); 964 if (IS_ERR(ctx->vcc)) 965 return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n"); 966 967 ctx->iovcc = devm_regulator_get(dev, "iovcc"); 968 if (IS_ERR(ctx->iovcc)) 969 return dev_err_probe(dev, PTR_ERR(ctx->iovcc), 970 "Failed to request iovcc regulator\n"); 971 972 ret = drm_of_get_panel_orientation(dsi->dev.of_node, &ctx->orientation); 973 if (ret < 0) 974 return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n"); 975 976 ret = drm_panel_of_backlight(&ctx->panel); 977 if (ret) 978 return ret; 979 980 drm_panel_add(&ctx->panel); 981 982 ret = mipi_dsi_attach(dsi); 983 if (ret < 0) { 984 dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret); 985 drm_panel_remove(&ctx->panel); 986 return ret; 987 } 988 989 dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", 990 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 991 drm_mode_vrefresh(ctx->desc->mode), 992 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); 993 994 st7703_debugfs_init(ctx); 995 return 0; 996 } 997 998 static void st7703_remove(struct mipi_dsi_device *dsi) 999 { 1000 struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); 1001 int ret; 1002 1003 ret = mipi_dsi_detach(dsi); 1004 if (ret < 0) 1005 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 1006 1007 drm_panel_remove(&ctx->panel); 1008 1009 st7703_debugfs_remove(ctx); 1010 } 1011 1012 static const struct of_device_id st7703_of_match[] = { 1013 { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc }, 1014 { .compatible = "ayaneo,pocket-ds-lower-panel", .data = &ayaneo_pocket_ds_lower_desc }, 1015 { .compatible = "gameforce,chi-panel", .data = &gameforcechi_desc }, 1016 { .compatible = "powkiddy,rgb10max3-panel", .data = &rgb10max3_panel_desc }, 1017 { .compatible = "powkiddy,rgb30-panel", .data = &rgb30panel_desc }, 1018 { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc }, 1019 { .compatible = "xingbangda,xbd599", .data = &xbd599_desc }, 1020 { /* sentinel */ } 1021 }; 1022 MODULE_DEVICE_TABLE(of, st7703_of_match); 1023 1024 static struct mipi_dsi_driver st7703_driver = { 1025 .probe = st7703_probe, 1026 .remove = st7703_remove, 1027 .driver = { 1028 .name = DRV_NAME, 1029 .of_match_table = st7703_of_match, 1030 }, 1031 }; 1032 module_mipi_dsi_driver(st7703_driver); 1033 1034 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); 1035 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels"); 1036 MODULE_LICENSE("GPL v2"); 1037