1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2019, Amarula Solutions. 4 * Author: Jagan Teki <jagan@amarulasolutions.com> 5 */ 6 7 #include <drm/drm_mipi_dbi.h> 8 #include <drm/drm_mipi_dsi.h> 9 #include <drm/drm_modes.h> 10 #include <drm/drm_panel.h> 11 12 #include <linux/bitfield.h> 13 #include <linux/gpio/consumer.h> 14 #include <linux/delay.h> 15 #include <linux/module.h> 16 #include <linux/of.h> 17 #include <linux/regulator/consumer.h> 18 #include <linux/spi/spi.h> 19 20 #include <video/mipi_display.h> 21 22 /* Command2 BKx selection command */ 23 #define ST7701_CMD2BKX_SEL 0xFF 24 #define ST7701_CMD1 0 25 #define ST7701_CMD2 BIT(4) 26 #define ST7701_CMD2BK_MASK GENMASK(3, 0) 27 28 /* Command2, BK0 commands */ 29 #define ST7701_CMD2_BK0_PVGAMCTRL 0xB0 /* Positive Voltage Gamma Control */ 30 #define ST7701_CMD2_BK0_NVGAMCTRL 0xB1 /* Negative Voltage Gamma Control */ 31 #define ST7701_CMD2_BK0_LNESET 0xC0 /* Display Line setting */ 32 #define ST7701_CMD2_BK0_PORCTRL 0xC1 /* Porch control */ 33 #define ST7701_CMD2_BK0_INVSEL 0xC2 /* Inversion selection, Frame Rate Control */ 34 35 /* Command2, BK1 commands */ 36 #define ST7701_CMD2_BK1_VRHS 0xB0 /* Vop amplitude setting */ 37 #define ST7701_CMD2_BK1_VCOM 0xB1 /* VCOM amplitude setting */ 38 #define ST7701_CMD2_BK1_VGHSS 0xB2 /* VGH Voltage setting */ 39 #define ST7701_CMD2_BK1_TESTCMD 0xB3 /* TEST Command Setting */ 40 #define ST7701_CMD2_BK1_VGLS 0xB5 /* VGL Voltage setting */ 41 #define ST7701_CMD2_BK1_PWCTLR1 0xB7 /* Power Control 1 */ 42 #define ST7701_CMD2_BK1_PWCTLR2 0xB8 /* Power Control 2 */ 43 #define ST7701_CMD2_BK1_SPD1 0xC1 /* Source pre_drive timing set1 */ 44 #define ST7701_CMD2_BK1_SPD2 0xC2 /* Source EQ2 Setting */ 45 #define ST7701_CMD2_BK1_MIPISET1 0xD0 /* MIPI Setting 1 */ 46 47 /* Command2, BK0 bytes */ 48 #define ST7701_CMD2_BK0_GAMCTRL_AJ_MASK GENMASK(7, 6) 49 #define ST7701_CMD2_BK0_GAMCTRL_VC0_MASK GENMASK(3, 0) 50 #define ST7701_CMD2_BK0_GAMCTRL_VC4_MASK GENMASK(5, 0) 51 #define ST7701_CMD2_BK0_GAMCTRL_VC8_MASK GENMASK(5, 0) 52 #define ST7701_CMD2_BK0_GAMCTRL_VC16_MASK GENMASK(4, 0) 53 #define ST7701_CMD2_BK0_GAMCTRL_VC24_MASK GENMASK(4, 0) 54 #define ST7701_CMD2_BK0_GAMCTRL_VC52_MASK GENMASK(3, 0) 55 #define ST7701_CMD2_BK0_GAMCTRL_VC80_MASK GENMASK(5, 0) 56 #define ST7701_CMD2_BK0_GAMCTRL_VC108_MASK GENMASK(3, 0) 57 #define ST7701_CMD2_BK0_GAMCTRL_VC147_MASK GENMASK(3, 0) 58 #define ST7701_CMD2_BK0_GAMCTRL_VC175_MASK GENMASK(5, 0) 59 #define ST7701_CMD2_BK0_GAMCTRL_VC203_MASK GENMASK(3, 0) 60 #define ST7701_CMD2_BK0_GAMCTRL_VC231_MASK GENMASK(4, 0) 61 #define ST7701_CMD2_BK0_GAMCTRL_VC239_MASK GENMASK(4, 0) 62 #define ST7701_CMD2_BK0_GAMCTRL_VC247_MASK GENMASK(5, 0) 63 #define ST7701_CMD2_BK0_GAMCTRL_VC251_MASK GENMASK(5, 0) 64 #define ST7701_CMD2_BK0_GAMCTRL_VC255_MASK GENMASK(4, 0) 65 #define ST7701_CMD2_BK0_LNESET_LINE_MASK GENMASK(6, 0) 66 #define ST7701_CMD2_BK0_LNESET_LDE_EN BIT(7) 67 #define ST7701_CMD2_BK0_LNESET_LINEDELTA GENMASK(1, 0) 68 #define ST7701_CMD2_BK0_PORCTRL_VBP_MASK GENMASK(7, 0) 69 #define ST7701_CMD2_BK0_PORCTRL_VFP_MASK GENMASK(7, 0) 70 #define ST7701_CMD2_BK0_INVSEL_ONES_MASK GENMASK(5, 4) 71 #define ST7701_CMD2_BK0_INVSEL_NLINV_MASK GENMASK(2, 0) 72 #define ST7701_CMD2_BK0_INVSEL_RTNI_MASK GENMASK(4, 0) 73 74 /* Command2, BK1 bytes */ 75 #define ST7701_CMD2_BK1_VRHA_MASK GENMASK(7, 0) 76 #define ST7701_CMD2_BK1_VCOM_MASK GENMASK(7, 0) 77 #define ST7701_CMD2_BK1_VGHSS_MASK GENMASK(3, 0) 78 #define ST7701_CMD2_BK1_TESTCMD_VAL BIT(7) 79 #define ST7701_CMD2_BK1_VGLS_ONES BIT(6) 80 #define ST7701_CMD2_BK1_VGLS_MASK GENMASK(3, 0) 81 #define ST7701_CMD2_BK1_PWRCTRL1_AP_MASK GENMASK(7, 6) 82 #define ST7701_CMD2_BK1_PWRCTRL1_APIS_MASK GENMASK(3, 2) 83 #define ST7701_CMD2_BK1_PWRCTRL1_APOS_MASK GENMASK(1, 0) 84 #define ST7701_CMD2_BK1_PWRCTRL2_AVDD_MASK GENMASK(5, 4) 85 #define ST7701_CMD2_BK1_PWRCTRL2_AVCL_MASK GENMASK(1, 0) 86 #define ST7701_CMD2_BK1_SPD1_ONES_MASK GENMASK(6, 4) 87 #define ST7701_CMD2_BK1_SPD1_T2D_MASK GENMASK(3, 0) 88 #define ST7701_CMD2_BK1_SPD2_ONES_MASK GENMASK(6, 4) 89 #define ST7701_CMD2_BK1_SPD2_T3D_MASK GENMASK(3, 0) 90 #define ST7701_CMD2_BK1_MIPISET1_ONES BIT(7) 91 #define ST7701_CMD2_BK1_MIPISET1_EOT_EN BIT(3) 92 93 #define CFIELD_PREP(_mask, _val) \ 94 (((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask)) 95 96 enum op_bias { 97 OP_BIAS_OFF = 0, 98 OP_BIAS_MIN, 99 OP_BIAS_MIDDLE, 100 OP_BIAS_MAX 101 }; 102 103 struct st7701; 104 105 struct st7701_panel_desc { 106 const struct drm_display_mode *mode; 107 unsigned int lanes; 108 enum mipi_dsi_pixel_format format; 109 unsigned int panel_sleep_delay; 110 111 /* TFT matrix driver configuration, panel specific. */ 112 const u8 pv_gamma[16]; /* Positive voltage gamma control */ 113 const u8 nv_gamma[16]; /* Negative voltage gamma control */ 114 const u8 nlinv; /* Inversion selection */ 115 const u32 vop_uv; /* Vop in uV */ 116 const u32 vcom_uv; /* Vcom in uV */ 117 const u16 vgh_mv; /* Vgh in mV */ 118 const s16 vgl_mv; /* Vgl in mV */ 119 const u16 avdd_mv; /* Avdd in mV */ 120 const s16 avcl_mv; /* Avcl in mV */ 121 const enum op_bias gamma_op_bias; 122 const enum op_bias input_op_bias; 123 const enum op_bias output_op_bias; 124 const u16 t2d_ns; /* T2D in ns */ 125 const u16 t3d_ns; /* T3D in ns */ 126 const bool eot_en; 127 128 /* GIP sequence, fully custom and undocumented. */ 129 void (*gip_sequence)(struct st7701 *st7701); 130 }; 131 132 struct st7701 { 133 struct drm_panel panel; 134 struct mipi_dsi_device *dsi; 135 struct mipi_dbi dbi; 136 const struct st7701_panel_desc *desc; 137 138 struct regulator_bulk_data supplies[2]; 139 struct gpio_desc *reset; 140 unsigned int sleep_delay; 141 enum drm_panel_orientation orientation; 142 143 int (*write_command)(struct st7701 *st7701, u8 cmd, const u8 *seq, 144 size_t len); 145 }; 146 147 static inline struct st7701 *panel_to_st7701(struct drm_panel *panel) 148 { 149 return container_of(panel, struct st7701, panel); 150 } 151 152 static int st7701_dsi_write(struct st7701 *st7701, u8 cmd, const u8 *seq, 153 size_t len) 154 { 155 return mipi_dsi_dcs_write(st7701->dsi, cmd, seq, len); 156 } 157 158 static int st7701_dbi_write(struct st7701 *st7701, u8 cmd, const u8 *seq, 159 size_t len) 160 { 161 return mipi_dbi_command_stackbuf(&st7701->dbi, cmd, seq, len); 162 } 163 164 #define ST7701_WRITE(st7701, cmd, seq...) \ 165 { \ 166 const u8 d[] = { seq }; \ 167 st7701->write_command(st7701, cmd, d, ARRAY_SIZE(d)); \ 168 } 169 170 static u8 st7701_vgls_map(struct st7701 *st7701) 171 { 172 const struct st7701_panel_desc *desc = st7701->desc; 173 struct { 174 s32 vgl; 175 u8 val; 176 } map[16] = { 177 { -7060, 0x0 }, { -7470, 0x1 }, 178 { -7910, 0x2 }, { -8140, 0x3 }, 179 { -8650, 0x4 }, { -8920, 0x5 }, 180 { -9210, 0x6 }, { -9510, 0x7 }, 181 { -9830, 0x8 }, { -10170, 0x9 }, 182 { -10530, 0xa }, { -10910, 0xb }, 183 { -11310, 0xc }, { -11730, 0xd }, 184 { -12200, 0xe }, { -12690, 0xf } 185 }; 186 int i; 187 188 for (i = 0; i < ARRAY_SIZE(map); i++) 189 if (desc->vgl_mv == map[i].vgl) 190 return map[i].val; 191 192 return 0; 193 } 194 195 static void st7701_switch_cmd_bkx(struct st7701 *st7701, bool cmd2, u8 bkx) 196 { 197 u8 val; 198 199 if (cmd2) 200 val = ST7701_CMD2 | FIELD_PREP(ST7701_CMD2BK_MASK, bkx); 201 else 202 val = ST7701_CMD1; 203 204 ST7701_WRITE(st7701, ST7701_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, val); 205 } 206 207 static void st7701_init_sequence(struct st7701 *st7701) 208 { 209 const struct st7701_panel_desc *desc = st7701->desc; 210 const struct drm_display_mode *mode = desc->mode; 211 const u8 linecount8 = mode->vdisplay / 8; 212 const u8 linecountrem2 = (mode->vdisplay % 8) / 2; 213 214 ST7701_WRITE(st7701, MIPI_DCS_SOFT_RESET, 0x00); 215 216 /* We need to wait 5ms before sending new commands */ 217 msleep(5); 218 219 ST7701_WRITE(st7701, MIPI_DCS_EXIT_SLEEP_MODE, 0x00); 220 221 msleep(st7701->sleep_delay); 222 223 /* Command2, BK0 */ 224 st7701_switch_cmd_bkx(st7701, true, 0); 225 226 st7701->write_command(st7701, ST7701_CMD2_BK0_PVGAMCTRL, desc->pv_gamma, 227 ARRAY_SIZE(desc->pv_gamma)); 228 st7701->write_command(st7701, ST7701_CMD2_BK0_NVGAMCTRL, desc->nv_gamma, 229 ARRAY_SIZE(desc->nv_gamma)); 230 /* 231 * Vertical line count configuration: 232 * Line[6:0]: select number of vertical lines of the TFT matrix in 233 * multiples of 8 lines 234 * LDE_EN: enable sub-8-line granularity line count 235 * Line_delta[1:0]: add 0/2/4/6 extra lines to line count selected 236 * using Line[6:0] 237 * 238 * Total number of vertical lines: 239 * LN = ((Line[6:0] + 1) * 8) + (LDE_EN ? Line_delta[1:0] * 2 : 0) 240 */ 241 ST7701_WRITE(st7701, ST7701_CMD2_BK0_LNESET, 242 FIELD_PREP(ST7701_CMD2_BK0_LNESET_LINE_MASK, linecount8 - 1) | 243 (linecountrem2 ? ST7701_CMD2_BK0_LNESET_LDE_EN : 0), 244 FIELD_PREP(ST7701_CMD2_BK0_LNESET_LINEDELTA, linecountrem2)); 245 ST7701_WRITE(st7701, ST7701_CMD2_BK0_PORCTRL, 246 FIELD_PREP(ST7701_CMD2_BK0_PORCTRL_VBP_MASK, 247 mode->vtotal - mode->vsync_end), 248 FIELD_PREP(ST7701_CMD2_BK0_PORCTRL_VFP_MASK, 249 mode->vsync_start - mode->vdisplay)); 250 /* 251 * Horizontal pixel count configuration: 252 * PCLK = 512 + (RTNI[4:0] * 16) 253 * The PCLK is number of pixel clock per line, which matches 254 * mode htotal. The minimum is 512 PCLK. 255 */ 256 ST7701_WRITE(st7701, ST7701_CMD2_BK0_INVSEL, 257 ST7701_CMD2_BK0_INVSEL_ONES_MASK | 258 FIELD_PREP(ST7701_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv), 259 FIELD_PREP(ST7701_CMD2_BK0_INVSEL_RTNI_MASK, 260 (clamp((u32)mode->htotal, 512U, 1008U) - 512) / 16)); 261 262 /* Command2, BK1 */ 263 st7701_switch_cmd_bkx(st7701, true, 1); 264 265 /* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */ 266 ST7701_WRITE(st7701, ST7701_CMD2_BK1_VRHS, 267 FIELD_PREP(ST7701_CMD2_BK1_VRHA_MASK, 268 DIV_ROUND_CLOSEST(desc->vop_uv - 3537500, 12500))); 269 270 /* Vcom = 0.1V + (VCOM[7:0] * 0.0125V) */ 271 ST7701_WRITE(st7701, ST7701_CMD2_BK1_VCOM, 272 FIELD_PREP(ST7701_CMD2_BK1_VCOM_MASK, 273 DIV_ROUND_CLOSEST(desc->vcom_uv - 100000, 12500))); 274 275 /* Vgh = 11.5V + (VGHSS[7:0] * 0.5V) */ 276 ST7701_WRITE(st7701, ST7701_CMD2_BK1_VGHSS, 277 FIELD_PREP(ST7701_CMD2_BK1_VGHSS_MASK, 278 DIV_ROUND_CLOSEST(clamp(desc->vgh_mv, 279 (u16)11500, 280 (u16)17000) - 11500, 281 500))); 282 283 ST7701_WRITE(st7701, ST7701_CMD2_BK1_TESTCMD, ST7701_CMD2_BK1_TESTCMD_VAL); 284 285 /* Vgl is non-linear */ 286 ST7701_WRITE(st7701, ST7701_CMD2_BK1_VGLS, 287 ST7701_CMD2_BK1_VGLS_ONES | 288 FIELD_PREP(ST7701_CMD2_BK1_VGLS_MASK, st7701_vgls_map(st7701))); 289 290 ST7701_WRITE(st7701, ST7701_CMD2_BK1_PWCTLR1, 291 FIELD_PREP(ST7701_CMD2_BK1_PWRCTRL1_AP_MASK, 292 desc->gamma_op_bias) | 293 FIELD_PREP(ST7701_CMD2_BK1_PWRCTRL1_APIS_MASK, 294 desc->input_op_bias) | 295 FIELD_PREP(ST7701_CMD2_BK1_PWRCTRL1_APOS_MASK, 296 desc->output_op_bias)); 297 298 /* Avdd = 6.2V + (AVDD[1:0] * 0.2V) , Avcl = -4.4V - (AVCL[1:0] * 0.2V) */ 299 ST7701_WRITE(st7701, ST7701_CMD2_BK1_PWCTLR2, 300 FIELD_PREP(ST7701_CMD2_BK1_PWRCTRL2_AVDD_MASK, 301 DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) | 302 FIELD_PREP(ST7701_CMD2_BK1_PWRCTRL2_AVCL_MASK, 303 DIV_ROUND_CLOSEST(-4400 - desc->avcl_mv, 200))); 304 305 /* T2D = 0.2us * T2D[3:0] */ 306 ST7701_WRITE(st7701, ST7701_CMD2_BK1_SPD1, 307 ST7701_CMD2_BK1_SPD1_ONES_MASK | 308 FIELD_PREP(ST7701_CMD2_BK1_SPD1_T2D_MASK, 309 DIV_ROUND_CLOSEST(desc->t2d_ns, 200))); 310 311 /* T3D = 4us + (0.8us * T3D[3:0]) */ 312 ST7701_WRITE(st7701, ST7701_CMD2_BK1_SPD2, 313 ST7701_CMD2_BK1_SPD2_ONES_MASK | 314 FIELD_PREP(ST7701_CMD2_BK1_SPD2_T3D_MASK, 315 DIV_ROUND_CLOSEST(desc->t3d_ns - 4000, 800))); 316 317 ST7701_WRITE(st7701, ST7701_CMD2_BK1_MIPISET1, 318 ST7701_CMD2_BK1_MIPISET1_ONES | 319 (desc->eot_en ? ST7701_CMD2_BK1_MIPISET1_EOT_EN : 0)); 320 } 321 322 static void ts8550b_gip_sequence(struct st7701 *st7701) 323 { 324 /** 325 * ST7701_SPEC_V1.2 is unable to provide enough information above this 326 * specific command sequence, so grab the same from vendor BSP driver. 327 */ 328 ST7701_WRITE(st7701, 0xE0, 0x00, 0x00, 0x02); 329 ST7701_WRITE(st7701, 0xE1, 0x0B, 0x00, 0x0D, 0x00, 0x0C, 0x00, 0x0E, 330 0x00, 0x00, 0x44, 0x44); 331 ST7701_WRITE(st7701, 0xE2, 0x33, 0x33, 0x44, 0x44, 0x64, 0x00, 0x66, 332 0x00, 0x65, 0x00, 0x67, 0x00, 0x00); 333 ST7701_WRITE(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33); 334 ST7701_WRITE(st7701, 0xE4, 0x44, 0x44); 335 ST7701_WRITE(st7701, 0xE5, 0x0C, 0x78, 0x3C, 0xA0, 0x0E, 0x78, 0x3C, 336 0xA0, 0x10, 0x78, 0x3C, 0xA0, 0x12, 0x78, 0x3C, 0xA0); 337 ST7701_WRITE(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33); 338 ST7701_WRITE(st7701, 0xE7, 0x44, 0x44); 339 ST7701_WRITE(st7701, 0xE8, 0x0D, 0x78, 0x3C, 0xA0, 0x0F, 0x78, 0x3C, 340 0xA0, 0x11, 0x78, 0x3C, 0xA0, 0x13, 0x78, 0x3C, 0xA0); 341 ST7701_WRITE(st7701, 0xEB, 0x02, 0x02, 0x39, 0x39, 0xEE, 0x44, 0x00); 342 ST7701_WRITE(st7701, 0xEC, 0x00, 0x00); 343 ST7701_WRITE(st7701, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF, 344 0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF); 345 } 346 347 static void dmt028vghmcmi_1a_gip_sequence(struct st7701 *st7701) 348 { 349 ST7701_WRITE(st7701, 0xEE, 0x42); 350 ST7701_WRITE(st7701, 0xE0, 0x00, 0x00, 0x02); 351 352 ST7701_WRITE(st7701, 0xE1, 353 0x04, 0xA0, 0x06, 0xA0, 354 0x05, 0xA0, 0x07, 0xA0, 355 0x00, 0x44, 0x44); 356 ST7701_WRITE(st7701, 0xE2, 357 0x00, 0x00, 0x00, 0x00, 358 0x00, 0x00, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00); 360 ST7701_WRITE(st7701, 0xE3, 361 0x00, 0x00, 0x22, 0x22); 362 ST7701_WRITE(st7701, 0xE4, 0x44, 0x44); 363 ST7701_WRITE(st7701, 0xE5, 364 0x0C, 0x90, 0xA0, 0xA0, 365 0x0E, 0x92, 0xA0, 0xA0, 366 0x08, 0x8C, 0xA0, 0xA0, 367 0x0A, 0x8E, 0xA0, 0xA0); 368 ST7701_WRITE(st7701, 0xE6, 369 0x00, 0x00, 0x22, 0x22); 370 ST7701_WRITE(st7701, 0xE7, 0x44, 0x44); 371 ST7701_WRITE(st7701, 0xE8, 372 0x0D, 0x91, 0xA0, 0xA0, 373 0x0F, 0x93, 0xA0, 0xA0, 374 0x09, 0x8D, 0xA0, 0xA0, 375 0x0B, 0x8F, 0xA0, 0xA0); 376 ST7701_WRITE(st7701, 0xEB, 377 0x00, 0x00, 0xE4, 0xE4, 378 0x44, 0x00, 0x00); 379 ST7701_WRITE(st7701, 0xED, 380 0xFF, 0xF5, 0x47, 0x6F, 381 0x0B, 0xA1, 0xAB, 0xFF, 382 0xFF, 0xBA, 0x1A, 0xB0, 383 0xF6, 0x74, 0x5F, 0xFF); 384 ST7701_WRITE(st7701, 0xEF, 385 0x08, 0x08, 0x08, 0x40, 386 0x3F, 0x64); 387 388 st7701_switch_cmd_bkx(st7701, false, 0); 389 390 st7701_switch_cmd_bkx(st7701, true, 3); 391 ST7701_WRITE(st7701, 0xE6, 0x7C); 392 ST7701_WRITE(st7701, 0xE8, 0x00, 0x0E); 393 394 st7701_switch_cmd_bkx(st7701, false, 0); 395 ST7701_WRITE(st7701, 0x11); 396 msleep(120); 397 398 st7701_switch_cmd_bkx(st7701, true, 3); 399 ST7701_WRITE(st7701, 0xE8, 0x00, 0x0C); 400 msleep(10); 401 ST7701_WRITE(st7701, 0xE8, 0x00, 0x00); 402 403 st7701_switch_cmd_bkx(st7701, false, 0); 404 ST7701_WRITE(st7701, 0x11); 405 msleep(120); 406 ST7701_WRITE(st7701, 0xE8, 0x00, 0x00); 407 408 st7701_switch_cmd_bkx(st7701, false, 0); 409 410 ST7701_WRITE(st7701, 0x3A, 0x70); 411 } 412 413 static void kd50t048a_gip_sequence(struct st7701 *st7701) 414 { 415 /** 416 * ST7701_SPEC_V1.2 is unable to provide enough information above this 417 * specific command sequence, so grab the same from vendor BSP driver. 418 */ 419 ST7701_WRITE(st7701, 0xE0, 0x00, 0x00, 0x02); 420 ST7701_WRITE(st7701, 0xE1, 0x08, 0x00, 0x0A, 0x00, 0x07, 0x00, 0x09, 421 0x00, 0x00, 0x33, 0x33); 422 ST7701_WRITE(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 424 ST7701_WRITE(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33); 425 ST7701_WRITE(st7701, 0xE4, 0x44, 0x44); 426 ST7701_WRITE(st7701, 0xE5, 0x0E, 0x60, 0xA0, 0xA0, 0x10, 0x60, 0xA0, 427 0xA0, 0x0A, 0x60, 0xA0, 0xA0, 0x0C, 0x60, 0xA0, 0xA0); 428 ST7701_WRITE(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33); 429 ST7701_WRITE(st7701, 0xE7, 0x44, 0x44); 430 ST7701_WRITE(st7701, 0xE8, 0x0D, 0x60, 0xA0, 0xA0, 0x0F, 0x60, 0xA0, 431 0xA0, 0x09, 0x60, 0xA0, 0xA0, 0x0B, 0x60, 0xA0, 0xA0); 432 ST7701_WRITE(st7701, 0xEB, 0x02, 0x01, 0xE4, 0xE4, 0x44, 0x00, 0x40); 433 ST7701_WRITE(st7701, 0xEC, 0x02, 0x01); 434 ST7701_WRITE(st7701, 0xED, 0xAB, 0x89, 0x76, 0x54, 0x01, 0xFF, 0xFF, 435 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA); 436 } 437 438 static void rg_arc_gip_sequence(struct st7701 *st7701) 439 { 440 st7701_switch_cmd_bkx(st7701, true, 3); 441 ST7701_WRITE(st7701, 0xEF, 0x08); 442 st7701_switch_cmd_bkx(st7701, true, 0); 443 ST7701_WRITE(st7701, 0xC7, 0x04); 444 ST7701_WRITE(st7701, 0xCC, 0x38); 445 st7701_switch_cmd_bkx(st7701, true, 1); 446 ST7701_WRITE(st7701, 0xB9, 0x10); 447 ST7701_WRITE(st7701, 0xBC, 0x03); 448 ST7701_WRITE(st7701, 0xC0, 0x89); 449 ST7701_WRITE(st7701, 0xE0, 0x00, 0x00, 0x02); 450 ST7701_WRITE(st7701, 0xE1, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 451 0x00, 0x00, 0x20, 0x20); 452 ST7701_WRITE(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 454 ST7701_WRITE(st7701, 0xE3, 0x00, 0x00, 0x33, 0x00); 455 ST7701_WRITE(st7701, 0xE4, 0x22, 0x00); 456 ST7701_WRITE(st7701, 0xE5, 0x04, 0x5C, 0xA0, 0xA0, 0x06, 0x5C, 0xA0, 457 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 458 ST7701_WRITE(st7701, 0xE6, 0x00, 0x00, 0x33, 0x00); 459 ST7701_WRITE(st7701, 0xE7, 0x22, 0x00); 460 ST7701_WRITE(st7701, 0xE8, 0x05, 0x5C, 0xA0, 0xA0, 0x07, 0x5C, 0xA0, 461 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 462 ST7701_WRITE(st7701, 0xEB, 0x02, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00); 463 ST7701_WRITE(st7701, 0xEC, 0x00, 0x00); 464 ST7701_WRITE(st7701, 0xED, 0xFA, 0x45, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 465 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x54, 0xAF); 466 ST7701_WRITE(st7701, 0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54); 467 st7701_switch_cmd_bkx(st7701, false, 0); 468 ST7701_WRITE(st7701, MIPI_DCS_SET_ADDRESS_MODE, 0x17); 469 ST7701_WRITE(st7701, MIPI_DCS_SET_PIXEL_FORMAT, 0x77); 470 ST7701_WRITE(st7701, MIPI_DCS_EXIT_SLEEP_MODE, 0x00); 471 msleep(120); 472 } 473 474 static void rg28xx_gip_sequence(struct st7701 *st7701) 475 { 476 st7701_switch_cmd_bkx(st7701, true, 3); 477 ST7701_WRITE(st7701, 0xEF, 0x08); 478 479 st7701_switch_cmd_bkx(st7701, true, 0); 480 ST7701_WRITE(st7701, 0xC3, 0x02, 0x10, 0x02); 481 ST7701_WRITE(st7701, 0xC7, 0x04); 482 ST7701_WRITE(st7701, 0xCC, 0x10); 483 484 st7701_switch_cmd_bkx(st7701, true, 1); 485 ST7701_WRITE(st7701, 0xEE, 0x42); 486 ST7701_WRITE(st7701, 0xE0, 0x00, 0x00, 0x02); 487 488 ST7701_WRITE(st7701, 0xE1, 0x04, 0xA0, 0x06, 0xA0, 0x05, 0xA0, 0x07, 0xA0, 489 0x00, 0x44, 0x44); 490 ST7701_WRITE(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 491 0x00, 0x00, 0x00, 0x00); 492 ST7701_WRITE(st7701, 0xE3, 0x00, 0x00, 0x22, 0x22); 493 ST7701_WRITE(st7701, 0xE4, 0x44, 0x44); 494 ST7701_WRITE(st7701, 0xE5, 0x0C, 0x90, 0xA0, 0xA0, 0x0E, 0x92, 0xA0, 0xA0, 495 0x08, 0x8C, 0xA0, 0xA0, 0x0A, 0x8E, 0xA0, 0xA0); 496 ST7701_WRITE(st7701, 0xE6, 0x00, 0x00, 0x22, 0x22); 497 ST7701_WRITE(st7701, 0xE7, 0x44, 0x44); 498 ST7701_WRITE(st7701, 0xE8, 0x0D, 0x91, 0xA0, 0xA0, 0x0F, 0x93, 0xA0, 0xA0, 499 0x09, 0x8D, 0xA0, 0xA0, 0x0B, 0x8F, 0xA0, 0xA0); 500 ST7701_WRITE(st7701, 0xEB, 0x00, 0x00, 0xE4, 0xE4, 0x44, 0x00, 0x40); 501 ST7701_WRITE(st7701, 0xED, 0xFF, 0xF5, 0x47, 0x6F, 0x0B, 0xA1, 0xBA, 0xFF, 502 0xFF, 0xAB, 0x1A, 0xB0, 0xF6, 0x74, 0x5F, 0xFF); 503 ST7701_WRITE(st7701, 0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54); 504 505 st7701_switch_cmd_bkx(st7701, false, 0); 506 507 st7701_switch_cmd_bkx(st7701, true, 3); 508 ST7701_WRITE(st7701, 0xE6, 0x16); 509 ST7701_WRITE(st7701, 0xE8, 0x00, 0x0E); 510 511 st7701_switch_cmd_bkx(st7701, false, 0); 512 ST7701_WRITE(st7701, MIPI_DCS_SET_ADDRESS_MODE, 0x10); 513 ST7701_WRITE(st7701, MIPI_DCS_EXIT_SLEEP_MODE); 514 msleep(120); 515 516 st7701_switch_cmd_bkx(st7701, true, 3); 517 ST7701_WRITE(st7701, 0xE8, 0x00, 0x0C); 518 msleep(10); 519 ST7701_WRITE(st7701, 0xE8, 0x00, 0x00); 520 st7701_switch_cmd_bkx(st7701, false, 0); 521 } 522 523 static void wf40eswaa6mnn0_gip_sequence(struct st7701 *st7701) 524 { 525 ST7701_WRITE(st7701, 0xE0, 0x00, 0x28, 0x02); 526 ST7701_WRITE(st7701, 0xE1, 0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 527 0x00, 0x00, 0x44, 0x44); 528 ST7701_WRITE(st7701, 0xE2, 0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 529 0x00, 0xEC, 0xA0, 0x00, 0x00); 530 ST7701_WRITE(st7701, 0xE3, 0x00, 0x00, 0x11, 0x11); 531 ST7701_WRITE(st7701, 0xE4, 0x44, 0x44); 532 ST7701_WRITE(st7701, 0xE5, 0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 533 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0); 534 ST7701_WRITE(st7701, 0xE6, 0x00, 0x00, 0x11, 0x11); 535 ST7701_WRITE(st7701, 0xE7, 0x44, 0x44); 536 ST7701_WRITE(st7701, 0xE8, 0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 537 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0); 538 ST7701_WRITE(st7701, 0xEB, 0x00, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40); 539 ST7701_WRITE(st7701, 0xEC, 0x3C, 0x00); 540 ST7701_WRITE(st7701, 0xED, 0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 541 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA); 542 ST7701_WRITE(st7701, MIPI_DCS_SET_ADDRESS_MODE, 0); 543 } 544 545 static int st7701_prepare(struct drm_panel *panel) 546 { 547 struct st7701 *st7701 = panel_to_st7701(panel); 548 int ret; 549 550 gpiod_set_value(st7701->reset, 0); 551 552 ret = regulator_bulk_enable(ARRAY_SIZE(st7701->supplies), 553 st7701->supplies); 554 if (ret < 0) 555 return ret; 556 msleep(20); 557 558 gpiod_set_value(st7701->reset, 1); 559 msleep(150); 560 561 st7701_init_sequence(st7701); 562 563 if (st7701->desc->gip_sequence) 564 st7701->desc->gip_sequence(st7701); 565 566 /* Disable Command2 */ 567 st7701_switch_cmd_bkx(st7701, false, 0); 568 569 return 0; 570 } 571 572 static int st7701_enable(struct drm_panel *panel) 573 { 574 struct st7701 *st7701 = panel_to_st7701(panel); 575 576 ST7701_WRITE(st7701, MIPI_DCS_SET_DISPLAY_ON, 0x00); 577 578 return 0; 579 } 580 581 static int st7701_disable(struct drm_panel *panel) 582 { 583 struct st7701 *st7701 = panel_to_st7701(panel); 584 585 ST7701_WRITE(st7701, MIPI_DCS_SET_DISPLAY_OFF, 0x00); 586 587 return 0; 588 } 589 590 static int st7701_unprepare(struct drm_panel *panel) 591 { 592 struct st7701 *st7701 = panel_to_st7701(panel); 593 594 ST7701_WRITE(st7701, MIPI_DCS_ENTER_SLEEP_MODE, 0x00); 595 596 msleep(st7701->sleep_delay); 597 598 gpiod_set_value(st7701->reset, 0); 599 600 /** 601 * During the Resetting period, the display will be blanked 602 * (The display is entering blanking sequence, which maximum 603 * time is 120 ms, when Reset Starts in Sleep Out –mode. The 604 * display remains the blank state in Sleep In –mode.) and 605 * then return to Default condition for Hardware Reset. 606 * 607 * So we need wait sleep_delay time to make sure reset completed. 608 */ 609 msleep(st7701->sleep_delay); 610 611 regulator_bulk_disable(ARRAY_SIZE(st7701->supplies), st7701->supplies); 612 613 return 0; 614 } 615 616 static int st7701_get_modes(struct drm_panel *panel, 617 struct drm_connector *connector) 618 { 619 struct st7701 *st7701 = panel_to_st7701(panel); 620 const struct drm_display_mode *desc_mode = st7701->desc->mode; 621 struct drm_display_mode *mode; 622 623 mode = drm_mode_duplicate(connector->dev, desc_mode); 624 if (!mode) { 625 dev_err(panel->dev, "failed to add mode %ux%u@%u\n", 626 desc_mode->hdisplay, desc_mode->vdisplay, 627 drm_mode_vrefresh(desc_mode)); 628 return -ENOMEM; 629 } 630 631 drm_mode_set_name(mode); 632 drm_mode_probed_add(connector, mode); 633 634 connector->display_info.width_mm = desc_mode->width_mm; 635 connector->display_info.height_mm = desc_mode->height_mm; 636 637 /* 638 * TODO: Remove once all drm drivers call 639 * drm_connector_set_orientation_from_panel() 640 */ 641 drm_connector_set_panel_orientation(connector, st7701->orientation); 642 643 return 1; 644 } 645 646 static enum drm_panel_orientation st7701_get_orientation(struct drm_panel *panel) 647 { 648 struct st7701 *st7701 = panel_to_st7701(panel); 649 650 return st7701->orientation; 651 } 652 653 static const struct drm_panel_funcs st7701_funcs = { 654 .disable = st7701_disable, 655 .unprepare = st7701_unprepare, 656 .prepare = st7701_prepare, 657 .enable = st7701_enable, 658 .get_modes = st7701_get_modes, 659 .get_orientation = st7701_get_orientation, 660 }; 661 662 static const struct drm_display_mode ts8550b_mode = { 663 .clock = 27500, 664 665 .hdisplay = 480, 666 .hsync_start = 480 + 38, 667 .hsync_end = 480 + 38 + 12, 668 .htotal = 480 + 38 + 12 + 12, 669 670 .vdisplay = 854, 671 .vsync_start = 854 + 18, 672 .vsync_end = 854 + 18 + 8, 673 .vtotal = 854 + 18 + 8 + 4, 674 675 .width_mm = 69, 676 .height_mm = 139, 677 678 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 679 }; 680 681 static const struct st7701_panel_desc ts8550b_desc = { 682 .mode = &ts8550b_mode, 683 .lanes = 2, 684 .format = MIPI_DSI_FMT_RGB888, 685 .panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */ 686 687 .pv_gamma = { 688 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 689 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 690 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 691 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe), 692 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 693 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15), 694 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf), 695 696 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 697 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 698 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8), 699 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8), 700 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 701 702 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), 703 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23), 704 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), 705 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 706 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), 707 708 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12), 709 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 710 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b), 711 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 712 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34), 713 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 714 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 715 }, 716 .nv_gamma = { 717 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 718 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 719 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 720 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe), 721 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) | 722 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15), 723 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf), 724 725 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 726 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13), 727 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7), 728 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9), 729 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 730 731 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), 732 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22), 733 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), 734 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 735 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10), 736 737 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe), 738 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 739 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c), 740 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 741 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34), 742 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 743 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 744 }, 745 .nlinv = 7, 746 .vop_uv = 4400000, 747 .vcom_uv = 337500, 748 .vgh_mv = 15000, 749 .vgl_mv = -9510, 750 .avdd_mv = 6600, 751 .avcl_mv = -4400, 752 .gamma_op_bias = OP_BIAS_MAX, 753 .input_op_bias = OP_BIAS_MIN, 754 .output_op_bias = OP_BIAS_MIN, 755 .t2d_ns = 1600, 756 .t3d_ns = 10400, 757 .eot_en = true, 758 .gip_sequence = ts8550b_gip_sequence, 759 }; 760 761 static const struct drm_display_mode dmt028vghmcmi_1a_mode = { 762 .clock = 22325, 763 764 .hdisplay = 480, 765 .hsync_start = 480 + 40, 766 .hsync_end = 480 + 40 + 4, 767 .htotal = 480 + 40 + 4 + 20, 768 769 .vdisplay = 640, 770 .vsync_start = 640 + 2, 771 .vsync_end = 640 + 2 + 40, 772 .vtotal = 640 + 2 + 40 + 16, 773 774 .width_mm = 56, 775 .height_mm = 78, 776 777 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 778 779 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 780 }; 781 782 static const struct st7701_panel_desc dmt028vghmcmi_1a_desc = { 783 .mode = &dmt028vghmcmi_1a_mode, 784 .lanes = 2, 785 .format = MIPI_DSI_FMT_RGB888, 786 .panel_sleep_delay = 5, /* panel need extra 5ms for sleep out cmd */ 787 788 .pv_gamma = { 789 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 790 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 791 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 792 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x10), 793 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 794 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x17), 795 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd), 796 797 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 798 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 799 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), 800 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x5), 801 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 802 803 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7), 804 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1f), 805 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), 806 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 807 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11), 808 809 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe), 810 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 811 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x29), 812 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 813 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), 814 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 815 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 816 }, 817 .nv_gamma = { 818 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 819 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 820 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 821 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd), 822 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 823 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14), 824 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xe), 825 826 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 827 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 828 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), 829 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x4), 830 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 831 832 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), 833 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20), 834 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5), 835 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 836 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), 837 838 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x13), 839 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 840 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x26), 841 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 842 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), 843 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 844 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 845 }, 846 .nlinv = 1, 847 .vop_uv = 4800000, 848 .vcom_uv = 1650000, 849 .vgh_mv = 15000, 850 .vgl_mv = -10170, 851 .avdd_mv = 6600, 852 .avcl_mv = -4400, 853 .gamma_op_bias = OP_BIAS_MIDDLE, 854 .input_op_bias = OP_BIAS_MIN, 855 .output_op_bias = OP_BIAS_MIN, 856 .t2d_ns = 1600, 857 .t3d_ns = 10400, 858 .eot_en = true, 859 .gip_sequence = dmt028vghmcmi_1a_gip_sequence, 860 }; 861 862 static const struct drm_display_mode kd50t048a_mode = { 863 .clock = 27500, 864 865 .hdisplay = 480, 866 .hsync_start = 480 + 2, 867 .hsync_end = 480 + 2 + 10, 868 .htotal = 480 + 2 + 10 + 2, 869 870 .vdisplay = 854, 871 .vsync_start = 854 + 2, 872 .vsync_end = 854 + 2 + 2, 873 .vtotal = 854 + 2 + 2 + 17, 874 875 .width_mm = 69, 876 .height_mm = 139, 877 878 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 879 }; 880 881 static const struct st7701_panel_desc kd50t048a_desc = { 882 .mode = &kd50t048a_mode, 883 .lanes = 2, 884 .format = MIPI_DSI_FMT_RGB888, 885 .panel_sleep_delay = 0, 886 887 .pv_gamma = { 888 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 889 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 890 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 891 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd), 892 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 893 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14), 894 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd), 895 896 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 897 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10), 898 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5), 899 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x2), 900 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 901 902 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), 903 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1e), 904 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5), 905 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 906 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), 907 908 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11), 909 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 2) | 910 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x23), 911 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 912 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29), 913 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 914 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18) 915 }, 916 .nv_gamma = { 917 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 918 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 919 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 920 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xc), 921 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 922 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14), 923 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xc), 924 925 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 926 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10), 927 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5), 928 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x3), 929 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 930 931 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7), 932 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20), 933 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5), 934 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 935 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), 936 937 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11), 938 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 2) | 939 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x24), 940 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 941 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29), 942 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 943 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18) 944 }, 945 .nlinv = 1, 946 .vop_uv = 4887500, 947 .vcom_uv = 937500, 948 .vgh_mv = 15000, 949 .vgl_mv = -9510, 950 .avdd_mv = 6600, 951 .avcl_mv = -4400, 952 .gamma_op_bias = OP_BIAS_MIDDLE, 953 .input_op_bias = OP_BIAS_MIN, 954 .output_op_bias = OP_BIAS_MIN, 955 .t2d_ns = 1600, 956 .t3d_ns = 10400, 957 .eot_en = true, 958 .gip_sequence = kd50t048a_gip_sequence, 959 }; 960 961 static const struct drm_display_mode rg_arc_mode = { 962 .clock = 25600, 963 964 .hdisplay = 480, 965 .hsync_start = 480 + 60, 966 .hsync_end = 480 + 60 + 42, 967 .htotal = 480 + 60 + 42 + 60, 968 969 .vdisplay = 640, 970 .vsync_start = 640 + 10, 971 .vsync_end = 640 + 10 + 4, 972 .vtotal = 640 + 10 + 4 + 16, 973 974 .width_mm = 63, 975 .height_mm = 84, 976 977 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 978 }; 979 980 static const struct st7701_panel_desc rg_arc_desc = { 981 .mode = &rg_arc_mode, 982 .lanes = 2, 983 .format = MIPI_DSI_FMT_RGB888, 984 .panel_sleep_delay = 80, 985 986 .pv_gamma = { 987 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x01) | 988 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 989 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 990 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x16), 991 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 992 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1d), 993 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0e), 994 995 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 996 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x12), 997 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x06), 998 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x0c), 999 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x0a), 1000 1001 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x09), 1002 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x25), 1003 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x00), 1004 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1005 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x03), 1006 1007 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x00), 1008 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1009 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x3f), 1010 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1011 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x3f), 1012 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1013 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1c) 1014 }, 1015 .nv_gamma = { 1016 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x01) | 1017 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 1018 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1019 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x16), 1020 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1021 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1e), 1022 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0e), 1023 1024 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1025 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 1026 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x06), 1027 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x0c), 1028 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x08), 1029 1030 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x09), 1031 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x26), 1032 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x00), 1033 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1034 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x15), 1035 1036 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x00), 1037 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1038 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x3f), 1039 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1040 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x3f), 1041 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1042 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1c) 1043 }, 1044 .nlinv = 0, 1045 .vop_uv = 4500000, 1046 .vcom_uv = 762500, 1047 .vgh_mv = 15000, 1048 .vgl_mv = -9510, 1049 .avdd_mv = 6600, 1050 .avcl_mv = -4400, 1051 .gamma_op_bias = OP_BIAS_MIDDLE, 1052 .input_op_bias = OP_BIAS_MIN, 1053 .output_op_bias = OP_BIAS_MIN, 1054 .t2d_ns = 1600, 1055 .t3d_ns = 10400, 1056 .eot_en = true, 1057 .gip_sequence = rg_arc_gip_sequence, 1058 }; 1059 1060 static const struct drm_display_mode rg28xx_mode = { 1061 .clock = 22325, 1062 1063 .hdisplay = 480, 1064 .hsync_start = 480 + 40, 1065 .hsync_end = 480 + 40 + 4, 1066 .htotal = 480 + 40 + 4 + 20, 1067 1068 .vdisplay = 640, 1069 .vsync_start = 640 + 2, 1070 .vsync_end = 640 + 2 + 40, 1071 .vtotal = 640 + 2 + 40 + 16, 1072 1073 .width_mm = 44, 1074 .height_mm = 58, 1075 1076 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 1077 1078 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 1079 }; 1080 1081 static const struct st7701_panel_desc rg28xx_desc = { 1082 .mode = &rg28xx_mode, 1083 1084 .panel_sleep_delay = 80, 1085 1086 .pv_gamma = { 1087 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1088 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 1089 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1090 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x10), 1091 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1092 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x17), 1093 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd), 1094 1095 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1096 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 1097 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), 1098 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x5), 1099 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 1100 1101 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7), 1102 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1f), 1103 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), 1104 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1105 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11), 1106 1107 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe), 1108 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1109 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x29), 1110 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1111 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), 1112 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1113 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 1114 }, 1115 .nv_gamma = { 1116 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1117 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0), 1118 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1119 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd), 1120 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1121 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14), 1122 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xe), 1123 1124 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1125 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), 1126 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), 1127 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x4), 1128 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), 1129 1130 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), 1131 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20), 1132 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5), 1133 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1134 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), 1135 1136 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x13), 1137 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1138 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x26), 1139 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1140 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), 1141 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1142 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 1143 }, 1144 .nlinv = 7, 1145 .vop_uv = 4800000, 1146 .vcom_uv = 1512500, 1147 .vgh_mv = 15000, 1148 .vgl_mv = -11730, 1149 .avdd_mv = 6600, 1150 .avcl_mv = -4400, 1151 .gamma_op_bias = OP_BIAS_MIDDLE, 1152 .input_op_bias = OP_BIAS_MIN, 1153 .output_op_bias = OP_BIAS_MIN, 1154 .t2d_ns = 1600, 1155 .t3d_ns = 10400, 1156 .eot_en = true, 1157 .gip_sequence = rg28xx_gip_sequence, 1158 }; 1159 1160 static const struct drm_display_mode wf40eswaa6mnn0_mode = { 1161 .clock = 18306, 1162 1163 .hdisplay = 480, 1164 .hsync_start = 480 + 2, 1165 .hsync_end = 480 + 2 + 45, 1166 .htotal = 480 + 2 + 45 + 13, 1167 1168 .vdisplay = 480, 1169 .vsync_start = 480 + 2, 1170 .vsync_end = 480 + 2 + 70, 1171 .vtotal = 480 + 2 + 70 + 13, 1172 1173 .width_mm = 72, 1174 .height_mm = 70, 1175 1176 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 1177 1178 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 1179 }; 1180 1181 static const struct st7701_panel_desc wf40eswaa6mnn0_desc = { 1182 .mode = &wf40eswaa6mnn0_mode, 1183 .lanes = 2, 1184 .format = MIPI_DSI_FMT_RGB888, 1185 .panel_sleep_delay = 0, 1186 1187 .pv_gamma = { 1188 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1189 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x1), 1190 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1191 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x08), 1192 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1193 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x10), 1194 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0c), 1195 1196 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1197 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10), 1198 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x08), 1199 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x10), 1200 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x0c), 1201 1202 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x08), 1203 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22), 1204 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x04), 1205 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1206 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x14), 1207 1208 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12), 1209 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1210 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0xb3), 1211 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1212 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x3a), 1213 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1214 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) 1215 }, 1216 .nv_gamma = { 1217 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1218 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13), 1219 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1220 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x19), 1221 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1222 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1f), 1223 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0x0f), 1224 1225 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1226 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x14), 1227 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x07), 1228 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x07), 1229 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x08), 1230 1231 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x07), 1232 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22), 1233 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x02), 1234 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1235 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0xf), 1236 1237 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0x0f), 1238 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1239 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0xa3), 1240 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1241 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29), 1242 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | 1243 CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x0d) 1244 }, 1245 .nlinv = 3, 1246 .vop_uv = 4737500, 1247 .vcom_uv = 662500, 1248 .vgh_mv = 15000, 1249 .vgl_mv = -10170, 1250 .avdd_mv = 6600, 1251 .avcl_mv = -4600, 1252 .gamma_op_bias = OP_BIAS_MIDDLE, 1253 .input_op_bias = OP_BIAS_MIDDLE, 1254 .output_op_bias = OP_BIAS_MIN, 1255 .t2d_ns = 1600, 1256 .t3d_ns = 10400, 1257 .eot_en = true, 1258 .gip_sequence = wf40eswaa6mnn0_gip_sequence, 1259 }; 1260 1261 static void st7701_cleanup(void *data) 1262 { 1263 struct st7701 *st7701 = (struct st7701 *)data; 1264 1265 drm_panel_remove(&st7701->panel); 1266 drm_panel_disable(&st7701->panel); 1267 drm_panel_unprepare(&st7701->panel); 1268 } 1269 1270 static int st7701_probe(struct device *dev, int connector_type) 1271 { 1272 const struct st7701_panel_desc *desc; 1273 struct st7701 *st7701; 1274 int ret; 1275 1276 st7701 = devm_drm_panel_alloc(dev, struct st7701, panel, &st7701_funcs, 1277 connector_type); 1278 if (IS_ERR(st7701)) 1279 return PTR_ERR(st7701); 1280 1281 desc = of_device_get_match_data(dev); 1282 if (!desc) 1283 return -ENODEV; 1284 1285 st7701->supplies[0].supply = "VCC"; 1286 st7701->supplies[1].supply = "IOVCC"; 1287 1288 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st7701->supplies), 1289 st7701->supplies); 1290 if (ret < 0) 1291 return ret; 1292 1293 st7701->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 1294 if (IS_ERR(st7701->reset)) { 1295 dev_err(dev, "Couldn't get our reset GPIO\n"); 1296 return PTR_ERR(st7701->reset); 1297 } 1298 1299 ret = of_drm_get_panel_orientation(dev->of_node, &st7701->orientation); 1300 if (ret < 0) 1301 return dev_err_probe(dev, ret, "Failed to get orientation\n"); 1302 1303 st7701->panel.prepare_prev_first = true; 1304 1305 /** 1306 * Once sleep out has been issued, ST7701 IC required to wait 120ms 1307 * before initiating new commands. 1308 * 1309 * On top of that some panels might need an extra delay to wait, so 1310 * add panel specific delay for those cases. As now this panel specific 1311 * delay information is referenced from those panel BSP driver, example 1312 * ts8550b and there is no valid documentation for that. 1313 */ 1314 st7701->sleep_delay = 120 + desc->panel_sleep_delay; 1315 1316 ret = drm_panel_of_backlight(&st7701->panel); 1317 if (ret) 1318 return ret; 1319 1320 drm_panel_add(&st7701->panel); 1321 1322 dev_set_drvdata(dev, st7701); 1323 st7701->desc = desc; 1324 1325 return devm_add_action_or_reset(dev, st7701_cleanup, st7701); 1326 } 1327 1328 static int st7701_dsi_probe(struct mipi_dsi_device *dsi) 1329 { 1330 struct st7701 *st7701; 1331 int err; 1332 1333 err = st7701_probe(&dsi->dev, DRM_MODE_CONNECTOR_DSI); 1334 if (err) 1335 return err; 1336 1337 st7701 = dev_get_drvdata(&dsi->dev); 1338 st7701->dsi = dsi; 1339 st7701->write_command = st7701_dsi_write; 1340 1341 if (!st7701->desc->lanes) 1342 return dev_err_probe(&dsi->dev, -EINVAL, "This panel is not for MIPI DSI\n"); 1343 1344 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 1345 MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS; 1346 dsi->format = st7701->desc->format; 1347 dsi->lanes = st7701->desc->lanes; 1348 1349 err = mipi_dsi_attach(dsi); 1350 if (err) 1351 return dev_err_probe(&dsi->dev, err, "Failed to init MIPI DSI\n"); 1352 1353 return 0; 1354 } 1355 1356 static int st7701_spi_probe(struct spi_device *spi) 1357 { 1358 struct st7701 *st7701; 1359 struct gpio_desc *dc; 1360 int err; 1361 1362 err = st7701_probe(&spi->dev, DRM_MODE_CONNECTOR_DPI); 1363 if (err) 1364 return err; 1365 1366 st7701 = dev_get_drvdata(&spi->dev); 1367 st7701->write_command = st7701_dbi_write; 1368 1369 dc = devm_gpiod_get_optional(&spi->dev, "dc", GPIOD_OUT_LOW); 1370 if (IS_ERR(dc)) 1371 return dev_err_probe(&spi->dev, PTR_ERR(dc), "Failed to get GPIO for D/CX\n"); 1372 1373 err = mipi_dbi_spi_init(spi, &st7701->dbi, dc); 1374 if (err) 1375 return dev_err_probe(&spi->dev, err, "Failed to init MIPI DBI\n"); 1376 st7701->dbi.read_commands = NULL; 1377 1378 return 0; 1379 } 1380 1381 static void st7701_dsi_remove(struct mipi_dsi_device *dsi) 1382 { 1383 mipi_dsi_detach(dsi); 1384 } 1385 1386 static const struct of_device_id st7701_dsi_of_match[] = { 1387 { .compatible = "anbernic,rg-arc-panel", .data = &rg_arc_desc }, 1388 { .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc }, 1389 { .compatible = "elida,kd50t048a", .data = &kd50t048a_desc }, 1390 { .compatible = "techstar,ts8550b", .data = &ts8550b_desc }, 1391 { .compatible = "winstar,wf40eswaa6mnn0", .data = &wf40eswaa6mnn0_desc }, 1392 { } 1393 }; 1394 MODULE_DEVICE_TABLE(of, st7701_dsi_of_match); 1395 1396 static const struct of_device_id st7701_spi_of_match[] = { 1397 { .compatible = "anbernic,rg28xx-panel", .data = &rg28xx_desc }, 1398 { /* sentinel */ } 1399 }; 1400 MODULE_DEVICE_TABLE(of, st7701_spi_of_match); 1401 1402 static const struct spi_device_id st7701_spi_ids[] = { 1403 { "rg28xx-panel" }, 1404 { /* sentinel */ } 1405 }; 1406 MODULE_DEVICE_TABLE(spi, st7701_spi_ids); 1407 1408 static struct mipi_dsi_driver st7701_dsi_driver = { 1409 .probe = st7701_dsi_probe, 1410 .remove = st7701_dsi_remove, 1411 .driver = { 1412 .name = "st7701", 1413 .of_match_table = st7701_dsi_of_match, 1414 }, 1415 }; 1416 1417 static struct spi_driver st7701_spi_driver = { 1418 .probe = st7701_spi_probe, 1419 .id_table = st7701_spi_ids, 1420 .driver = { 1421 .name = "st7701", 1422 .of_match_table = st7701_spi_of_match, 1423 }, 1424 }; 1425 1426 static int __init st7701_driver_init(void) 1427 { 1428 int err; 1429 1430 if (IS_ENABLED(CONFIG_SPI)) { 1431 err = spi_register_driver(&st7701_spi_driver); 1432 if (err) 1433 return err; 1434 } 1435 1436 if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) { 1437 err = mipi_dsi_driver_register(&st7701_dsi_driver); 1438 if (err) { 1439 if (IS_ENABLED(CONFIG_SPI)) 1440 spi_unregister_driver(&st7701_spi_driver); 1441 return err; 1442 } 1443 } 1444 1445 return 0; 1446 } 1447 module_init(st7701_driver_init); 1448 1449 static void __exit st7701_driver_exit(void) 1450 { 1451 if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) 1452 mipi_dsi_driver_unregister(&st7701_dsi_driver); 1453 1454 if (IS_ENABLED(CONFIG_SPI)) 1455 spi_unregister_driver(&st7701_spi_driver); 1456 } 1457 module_exit(st7701_driver_exit); 1458 1459 MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>"); 1460 MODULE_AUTHOR("Hironori KIKUCHI <kikuchan98@gmail.com>"); 1461 MODULE_DESCRIPTION("Sitronix ST7701 LCD Panel Driver"); 1462 MODULE_LICENSE("GPL"); 1463