1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver. 4 * 5 * Copyright (c) 2013 Samsung Electronics Co., Ltd 6 * 7 * Inki Dae, <inki.dae@samsung.com> 8 * Donghwa Lee, <dh09.lee@samsung.com> 9 * Joongmock Shin <jmock.shin@samsung.com> 10 * Eunchul Kim <chulspro.kim@samsung.com> 11 * Tomasz Figa <t.figa@samsung.com> 12 * Andrzej Hajda <a.hajda@samsung.com> 13 */ 14 15 #include <drm/drmP.h> 16 #include <drm/drm_mipi_dsi.h> 17 #include <drm/drm_panel.h> 18 19 #include <linux/gpio/consumer.h> 20 #include <linux/regulator/consumer.h> 21 22 #include <video/mipi_display.h> 23 #include <video/of_videomode.h> 24 #include <video/videomode.h> 25 26 #define LDI_MTP_LENGTH 24 27 #define GAMMA_LEVEL_NUM 25 28 #define GAMMA_TABLE_LEN 26 29 30 #define PANELCTL_SS_MASK (1 << 5) 31 #define PANELCTL_SS_1_800 (0 << 5) 32 #define PANELCTL_SS_800_1 (1 << 5) 33 #define PANELCTL_GTCON_MASK (7 << 2) 34 #define PANELCTL_GTCON_110 (6 << 2) 35 #define PANELCTL_GTCON_111 (7 << 2) 36 37 #define PANELCTL_CLK1_CON_MASK (7 << 3) 38 #define PANELCTL_CLK1_000 (0 << 3) 39 #define PANELCTL_CLK1_001 (1 << 3) 40 #define PANELCTL_CLK2_CON_MASK (7 << 0) 41 #define PANELCTL_CLK2_000 (0 << 0) 42 #define PANELCTL_CLK2_001 (1 << 0) 43 44 #define PANELCTL_INT1_CON_MASK (7 << 3) 45 #define PANELCTL_INT1_000 (0 << 3) 46 #define PANELCTL_INT1_001 (1 << 3) 47 #define PANELCTL_INT2_CON_MASK (7 << 0) 48 #define PANELCTL_INT2_000 (0 << 0) 49 #define PANELCTL_INT2_001 (1 << 0) 50 51 #define PANELCTL_BICTL_CON_MASK (7 << 3) 52 #define PANELCTL_BICTL_000 (0 << 3) 53 #define PANELCTL_BICTL_001 (1 << 3) 54 #define PANELCTL_BICTLB_CON_MASK (7 << 0) 55 #define PANELCTL_BICTLB_000 (0 << 0) 56 #define PANELCTL_BICTLB_001 (1 << 0) 57 58 #define PANELCTL_EM_CLK1_CON_MASK (7 << 3) 59 #define PANELCTL_EM_CLK1_110 (6 << 3) 60 #define PANELCTL_EM_CLK1_111 (7 << 3) 61 #define PANELCTL_EM_CLK1B_CON_MASK (7 << 0) 62 #define PANELCTL_EM_CLK1B_110 (6 << 0) 63 #define PANELCTL_EM_CLK1B_111 (7 << 0) 64 65 #define PANELCTL_EM_CLK2_CON_MASK (7 << 3) 66 #define PANELCTL_EM_CLK2_110 (6 << 3) 67 #define PANELCTL_EM_CLK2_111 (7 << 3) 68 #define PANELCTL_EM_CLK2B_CON_MASK (7 << 0) 69 #define PANELCTL_EM_CLK2B_110 (6 << 0) 70 #define PANELCTL_EM_CLK2B_111 (7 << 0) 71 72 #define PANELCTL_EM_INT1_CON_MASK (7 << 3) 73 #define PANELCTL_EM_INT1_000 (0 << 3) 74 #define PANELCTL_EM_INT1_001 (1 << 3) 75 #define PANELCTL_EM_INT2_CON_MASK (7 << 0) 76 #define PANELCTL_EM_INT2_000 (0 << 0) 77 #define PANELCTL_EM_INT2_001 (1 << 0) 78 79 #define AID_DISABLE (0x4) 80 #define AID_1 (0x5) 81 #define AID_2 (0x6) 82 #define AID_3 (0x7) 83 84 typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN]; 85 86 struct s6e8aa0_variant { 87 u8 version; 88 const s6e8aa0_gamma_table *gamma_tables; 89 }; 90 91 struct s6e8aa0 { 92 struct device *dev; 93 struct drm_panel panel; 94 95 struct regulator_bulk_data supplies[2]; 96 struct gpio_desc *reset_gpio; 97 u32 power_on_delay; 98 u32 reset_delay; 99 u32 init_delay; 100 bool flip_horizontal; 101 bool flip_vertical; 102 struct videomode vm; 103 u32 width_mm; 104 u32 height_mm; 105 106 u8 version; 107 u8 id; 108 const struct s6e8aa0_variant *variant; 109 int brightness; 110 111 /* This field is tested by functions directly accessing DSI bus before 112 * transfer, transfer is skipped if it is set. In case of transfer 113 * failure or unexpected response the field is set to error value. 114 * Such construct allows to eliminate many checks in higher level 115 * functions. 116 */ 117 int error; 118 }; 119 120 static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel) 121 { 122 return container_of(panel, struct s6e8aa0, panel); 123 } 124 125 static int s6e8aa0_clear_error(struct s6e8aa0 *ctx) 126 { 127 int ret = ctx->error; 128 129 ctx->error = 0; 130 return ret; 131 } 132 133 static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len) 134 { 135 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 136 ssize_t ret; 137 138 if (ctx->error < 0) 139 return; 140 141 ret = mipi_dsi_dcs_write_buffer(dsi, data, len); 142 if (ret < 0) { 143 dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret, 144 (int)len, data); 145 ctx->error = ret; 146 } 147 } 148 149 static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len) 150 { 151 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 152 int ret; 153 154 if (ctx->error < 0) 155 return ctx->error; 156 157 ret = mipi_dsi_dcs_read(dsi, cmd, data, len); 158 if (ret < 0) { 159 dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd); 160 ctx->error = ret; 161 } 162 163 return ret; 164 } 165 166 #define s6e8aa0_dcs_write_seq(ctx, seq...) \ 167 ({\ 168 const u8 d[] = { seq };\ 169 BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\ 170 s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\ 171 }) 172 173 #define s6e8aa0_dcs_write_seq_static(ctx, seq...) \ 174 ({\ 175 static const u8 d[] = { seq };\ 176 s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\ 177 }) 178 179 static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx) 180 { 181 s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a); 182 } 183 184 static void s6e8aa0_panel_cond_set_v142(struct s6e8aa0 *ctx) 185 { 186 static const u8 aids[] = { 187 0x04, 0x04, 0x04, 0x04, 0x04, 0x60, 0x80, 0xA0 188 }; 189 u8 aid = aids[ctx->id >> 5]; 190 u8 cfg = 0x3d; 191 u8 clk_con = 0xc8; 192 u8 int_con = 0x08; 193 u8 bictl_con = 0x48; 194 u8 em_clk1_con = 0xff; 195 u8 em_clk2_con = 0xff; 196 u8 em_int_con = 0xc8; 197 198 if (ctx->flip_vertical) { 199 /* GTCON */ 200 cfg &= ~(PANELCTL_GTCON_MASK); 201 cfg |= (PANELCTL_GTCON_110); 202 } 203 204 if (ctx->flip_horizontal) { 205 /* SS */ 206 cfg &= ~(PANELCTL_SS_MASK); 207 cfg |= (PANELCTL_SS_1_800); 208 } 209 210 if (ctx->flip_horizontal || ctx->flip_vertical) { 211 /* CLK1,2_CON */ 212 clk_con &= ~(PANELCTL_CLK1_CON_MASK | 213 PANELCTL_CLK2_CON_MASK); 214 clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001); 215 216 /* INT1,2_CON */ 217 int_con &= ~(PANELCTL_INT1_CON_MASK | 218 PANELCTL_INT2_CON_MASK); 219 int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001); 220 221 /* BICTL,B_CON */ 222 bictl_con &= ~(PANELCTL_BICTL_CON_MASK | 223 PANELCTL_BICTLB_CON_MASK); 224 bictl_con |= (PANELCTL_BICTL_000 | 225 PANELCTL_BICTLB_001); 226 227 /* EM_CLK1,1B_CON */ 228 em_clk1_con &= ~(PANELCTL_EM_CLK1_CON_MASK | 229 PANELCTL_EM_CLK1B_CON_MASK); 230 em_clk1_con |= (PANELCTL_EM_CLK1_110 | 231 PANELCTL_EM_CLK1B_110); 232 233 /* EM_CLK2,2B_CON */ 234 em_clk2_con &= ~(PANELCTL_EM_CLK2_CON_MASK | 235 PANELCTL_EM_CLK2B_CON_MASK); 236 em_clk2_con |= (PANELCTL_EM_CLK2_110 | 237 PANELCTL_EM_CLK2B_110); 238 239 /* EM_INT1,2_CON */ 240 em_int_con &= ~(PANELCTL_EM_INT1_CON_MASK | 241 PANELCTL_EM_INT2_CON_MASK); 242 em_int_con |= (PANELCTL_EM_INT1_000 | 243 PANELCTL_EM_INT2_001); 244 } 245 246 s6e8aa0_dcs_write_seq(ctx, 247 0xf8, cfg, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 248 0x3c, 0x78, 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 249 0x00, 0x20, aid, 0x08, 0x6e, 0x00, 0x00, 0x00, 250 0x02, 0x07, 0x07, 0x23, 0x23, 0xc0, clk_con, int_con, 251 bictl_con, 0xc1, 0x00, 0xc1, em_clk1_con, em_clk2_con, 252 em_int_con); 253 } 254 255 static void s6e8aa0_panel_cond_set(struct s6e8aa0 *ctx) 256 { 257 if (ctx->version < 142) 258 s6e8aa0_dcs_write_seq_static(ctx, 259 0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00, 260 0x3c, 0x78, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00, 261 0x00, 0x00, 0x04, 0x08, 0x6e, 0x00, 0x00, 0x00, 262 0x00, 0x07, 0x07, 0x23, 0x6e, 0xc0, 0xc1, 0x01, 263 0x81, 0xc1, 0x00, 0xc3, 0xf6, 0xf6, 0xc1 264 ); 265 else 266 s6e8aa0_panel_cond_set_v142(ctx); 267 } 268 269 static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx) 270 { 271 s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d); 272 } 273 274 static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx) 275 { 276 s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00); 277 } 278 279 static void s6e8aa0_etc_pentile_control(struct s6e8aa0 *ctx) 280 { 281 static const u8 pent32[] = { 282 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xc0, 0x44, 0x44, 0xc0, 0x00 283 }; 284 285 static const u8 pent142[] = { 286 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, 0x00 287 }; 288 289 if (ctx->version < 142) 290 s6e8aa0_dcs_write(ctx, pent32, ARRAY_SIZE(pent32)); 291 else 292 s6e8aa0_dcs_write(ctx, pent142, ARRAY_SIZE(pent142)); 293 } 294 295 static void s6e8aa0_etc_power_control(struct s6e8aa0 *ctx) 296 { 297 static const u8 pwr142[] = { 298 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x1e, 0x33, 0x02 299 }; 300 301 static const u8 pwr32[] = { 302 0xf4, 0xcf, 0x0a, 0x15, 0x10, 0x19, 0x33, 0x02 303 }; 304 305 if (ctx->version < 142) 306 s6e8aa0_dcs_write(ctx, pwr32, ARRAY_SIZE(pwr32)); 307 else 308 s6e8aa0_dcs_write(ctx, pwr142, ARRAY_SIZE(pwr142)); 309 } 310 311 static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx) 312 { 313 u8 id = ctx->id ? 0 : 0x95; 314 315 s6e8aa0_dcs_write_seq(ctx, 0xb1, 0x04, id); 316 } 317 318 static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx) 319 { 320 u8 br; 321 322 switch (ctx->brightness) { 323 case 0 ... 6: /* 30cd ~ 100cd */ 324 br = 0xdf; 325 break; 326 case 7 ... 11: /* 120cd ~ 150cd */ 327 br = 0xdd; 328 break; 329 case 12 ... 15: /* 180cd ~ 210cd */ 330 default: 331 br = 0xd9; 332 break; 333 case 16 ... 24: /* 240cd ~ 300cd */ 334 br = 0xd0; 335 break; 336 } 337 338 s6e8aa0_dcs_write_seq(ctx, 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 339 0xc4, 0x0f, 0x40, 0x41, br, 0x00, 0x60, 0x19); 340 } 341 342 static void s6e8aa0_elvss_nvm_set(struct s6e8aa0 *ctx) 343 { 344 if (ctx->version < 142) 345 s6e8aa0_dcs_write_seq_static(ctx, 346 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 0xc4, 0x07, 347 0x40, 0x41, 0xc1, 0x00, 0x60, 0x19); 348 else 349 s6e8aa0_elvss_nvm_set_v142(ctx); 350 }; 351 352 static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx) 353 { 354 s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a); 355 } 356 357 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v142[GAMMA_LEVEL_NUM] = { 358 { 359 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x62, 0x55, 0x55, 360 0xaf, 0xb1, 0xb1, 0xbd, 0xce, 0xb7, 0x9a, 0xb1, 361 0x90, 0xb2, 0xc4, 0xae, 0x00, 0x60, 0x00, 0x40, 362 0x00, 0x70, 363 }, { 364 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x74, 0x68, 0x69, 365 0xb8, 0xc1, 0xb7, 0xbd, 0xcd, 0xb8, 0x93, 0xab, 366 0x88, 0xb4, 0xc4, 0xb1, 0x00, 0x6b, 0x00, 0x4d, 367 0x00, 0x7d, 368 }, { 369 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x95, 0x8a, 0x89, 370 0xb4, 0xc6, 0xb2, 0xc5, 0xd2, 0xbf, 0x90, 0xa8, 371 0x85, 0xb5, 0xc4, 0xb3, 0x00, 0x7b, 0x00, 0x5d, 372 0x00, 0x8f, 373 }, { 374 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9f, 0x98, 0x92, 375 0xb3, 0xc4, 0xb0, 0xbc, 0xcc, 0xb4, 0x91, 0xa6, 376 0x87, 0xb5, 0xc5, 0xb4, 0x00, 0x87, 0x00, 0x6a, 377 0x00, 0x9e, 378 }, { 379 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x99, 0x93, 0x8b, 380 0xb2, 0xc2, 0xb0, 0xbd, 0xce, 0xb4, 0x90, 0xa6, 381 0x87, 0xb3, 0xc3, 0xb2, 0x00, 0x8d, 0x00, 0x70, 382 0x00, 0xa4, 383 }, { 384 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xa5, 0x99, 385 0xb2, 0xc2, 0xb0, 0xbb, 0xcd, 0xb1, 0x93, 0xa7, 386 0x8a, 0xb2, 0xc1, 0xb0, 0x00, 0x92, 0x00, 0x75, 387 0x00, 0xaa, 388 }, { 389 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xa0, 0x93, 390 0xb6, 0xc4, 0xb4, 0xb5, 0xc8, 0xaa, 0x94, 0xa9, 391 0x8c, 0xb2, 0xc0, 0xb0, 0x00, 0x97, 0x00, 0x7a, 392 0x00, 0xaf, 393 }, { 394 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xa7, 0x96, 395 0xb3, 0xc2, 0xb0, 0xba, 0xcb, 0xb0, 0x94, 0xa8, 396 0x8c, 0xb0, 0xbf, 0xaf, 0x00, 0x9f, 0x00, 0x83, 397 0x00, 0xb9, 398 }, { 399 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9d, 0xa2, 0x90, 400 0xb6, 0xc5, 0xb3, 0xb8, 0xc9, 0xae, 0x94, 0xa8, 401 0x8d, 0xaf, 0xbd, 0xad, 0x00, 0xa4, 0x00, 0x88, 402 0x00, 0xbf, 403 }, { 404 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xac, 0x97, 405 0xb4, 0xc4, 0xb1, 0xbb, 0xcb, 0xb2, 0x93, 0xa7, 406 0x8d, 0xae, 0xbc, 0xad, 0x00, 0xa7, 0x00, 0x8c, 407 0x00, 0xc3, 408 }, { 409 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa2, 0xa9, 0x93, 410 0xb6, 0xc5, 0xb2, 0xba, 0xc9, 0xb0, 0x93, 0xa7, 411 0x8d, 0xae, 0xbb, 0xac, 0x00, 0xab, 0x00, 0x90, 412 0x00, 0xc8, 413 }, { 414 0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9e, 0xa6, 0x8f, 415 0xb7, 0xc6, 0xb3, 0xb8, 0xc8, 0xb0, 0x93, 0xa6, 416 0x8c, 0xae, 0xbb, 0xad, 0x00, 0xae, 0x00, 0x93, 417 0x00, 0xcc, 418 }, { 419 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb4, 0x9c, 420 0xb3, 0xc3, 0xaf, 0xb7, 0xc7, 0xaf, 0x93, 0xa6, 421 0x8c, 0xaf, 0xbc, 0xad, 0x00, 0xb1, 0x00, 0x97, 422 0x00, 0xcf, 423 }, { 424 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xb1, 0x98, 425 0xb1, 0xc2, 0xab, 0xba, 0xc9, 0xb2, 0x93, 0xa6, 426 0x8d, 0xae, 0xba, 0xab, 0x00, 0xb5, 0x00, 0x9b, 427 0x00, 0xd4, 428 }, { 429 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xae, 0x94, 430 0xb2, 0xc3, 0xac, 0xbb, 0xca, 0xb4, 0x91, 0xa4, 431 0x8a, 0xae, 0xba, 0xac, 0x00, 0xb8, 0x00, 0x9e, 432 0x00, 0xd8, 433 }, { 434 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb7, 0x9c, 435 0xae, 0xc0, 0xa9, 0xba, 0xc9, 0xb3, 0x92, 0xa5, 436 0x8b, 0xad, 0xb9, 0xab, 0x00, 0xbb, 0x00, 0xa1, 437 0x00, 0xdc, 438 }, { 439 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb4, 0x97, 440 0xb0, 0xc1, 0xaa, 0xb9, 0xc8, 0xb2, 0x92, 0xa5, 441 0x8c, 0xae, 0xb9, 0xab, 0x00, 0xbe, 0x00, 0xa4, 442 0x00, 0xdf, 443 }, { 444 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94, 445 0xb0, 0xc2, 0xab, 0xbb, 0xc9, 0xb3, 0x91, 0xa4, 446 0x8b, 0xad, 0xb8, 0xaa, 0x00, 0xc1, 0x00, 0xa8, 447 0x00, 0xe2, 448 }, { 449 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94, 450 0xae, 0xbf, 0xa8, 0xb9, 0xc8, 0xb3, 0x92, 0xa4, 451 0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xc4, 0x00, 0xab, 452 0x00, 0xe6, 453 }, { 454 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb6, 0x98, 455 0xaf, 0xc0, 0xa8, 0xb8, 0xc7, 0xb2, 0x93, 0xa5, 456 0x8d, 0xad, 0xb7, 0xa9, 0x00, 0xc7, 0x00, 0xae, 457 0x00, 0xe9, 458 }, { 459 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95, 460 0xaf, 0xc1, 0xa9, 0xb9, 0xc8, 0xb3, 0x92, 0xa4, 461 0x8b, 0xad, 0xb7, 0xaa, 0x00, 0xc9, 0x00, 0xb0, 462 0x00, 0xec, 463 }, { 464 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95, 465 0xac, 0xbe, 0xa6, 0xbb, 0xc9, 0xb4, 0x90, 0xa3, 466 0x8a, 0xad, 0xb7, 0xa9, 0x00, 0xcc, 0x00, 0xb4, 467 0x00, 0xf0, 468 }, { 469 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xb0, 0x91, 470 0xae, 0xc0, 0xa6, 0xba, 0xc8, 0xb4, 0x91, 0xa4, 471 0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xcf, 0x00, 0xb7, 472 0x00, 0xf3, 473 }, { 474 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb8, 0x98, 475 0xab, 0xbd, 0xa4, 0xbb, 0xc9, 0xb5, 0x91, 0xa3, 476 0x8b, 0xac, 0xb6, 0xa8, 0x00, 0xd1, 0x00, 0xb9, 477 0x00, 0xf6, 478 }, { 479 0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb5, 0x95, 480 0xa9, 0xbc, 0xa1, 0xbb, 0xc9, 0xb5, 0x91, 0xa3, 481 0x8a, 0xad, 0xb6, 0xa8, 0x00, 0xd6, 0x00, 0xbf, 482 0x00, 0xfc, 483 }, 484 }; 485 486 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v96[GAMMA_LEVEL_NUM] = { 487 { 488 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 489 0xdf, 0x1f, 0xd7, 0xdc, 0xb7, 0xe1, 0xc0, 0xaf, 490 0xc4, 0xd2, 0xd0, 0xcf, 0x00, 0x4d, 0x00, 0x40, 491 0x00, 0x5f, 492 }, { 493 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 494 0xd5, 0x35, 0xcf, 0xdc, 0xc1, 0xe1, 0xbf, 0xb3, 495 0xc1, 0xd2, 0xd1, 0xce, 0x00, 0x53, 0x00, 0x46, 496 0x00, 0x67, 497 }, { 498 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 499 0xd2, 0x64, 0xcf, 0xdb, 0xc6, 0xe1, 0xbd, 0xb3, 500 0xbd, 0xd2, 0xd2, 0xce, 0x00, 0x59, 0x00, 0x4b, 501 0x00, 0x6e, 502 }, { 503 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 504 0xd0, 0x7c, 0xcf, 0xdb, 0xc9, 0xe0, 0xbc, 0xb4, 505 0xbb, 0xcf, 0xd1, 0xcc, 0x00, 0x5f, 0x00, 0x50, 506 0x00, 0x75, 507 }, { 508 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 509 0xd0, 0x8e, 0xd1, 0xdb, 0xcc, 0xdf, 0xbb, 0xb6, 510 0xb9, 0xd0, 0xd1, 0xcd, 0x00, 0x63, 0x00, 0x54, 511 0x00, 0x7a, 512 }, { 513 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 514 0xd1, 0x9e, 0xd5, 0xda, 0xcd, 0xdd, 0xbb, 0xb7, 515 0xb9, 0xce, 0xce, 0xc9, 0x00, 0x68, 0x00, 0x59, 516 0x00, 0x81, 517 }, { 518 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff, 519 0xd0, 0xa5, 0xd6, 0xda, 0xcf, 0xdd, 0xbb, 0xb7, 520 0xb8, 0xcc, 0xcd, 0xc7, 0x00, 0x6c, 0x00, 0x5c, 521 0x00, 0x86, 522 }, { 523 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xfe, 524 0xd0, 0xae, 0xd7, 0xd9, 0xd0, 0xdb, 0xb9, 0xb6, 525 0xb5, 0xca, 0xcc, 0xc5, 0x00, 0x74, 0x00, 0x63, 526 0x00, 0x90, 527 }, { 528 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf9, 529 0xcf, 0xb0, 0xd6, 0xd9, 0xd1, 0xdb, 0xb9, 0xb6, 530 0xb4, 0xca, 0xcb, 0xc5, 0x00, 0x77, 0x00, 0x66, 531 0x00, 0x94, 532 }, { 533 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf7, 534 0xcf, 0xb3, 0xd7, 0xd8, 0xd1, 0xd9, 0xb7, 0xb6, 535 0xb3, 0xc9, 0xca, 0xc3, 0x00, 0x7b, 0x00, 0x69, 536 0x00, 0x99, 537 538 }, { 539 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfd, 0x2f, 0xf7, 540 0xdf, 0xb5, 0xd6, 0xd8, 0xd1, 0xd8, 0xb6, 0xb5, 541 0xb2, 0xca, 0xcb, 0xc4, 0x00, 0x7e, 0x00, 0x6c, 542 0x00, 0x9d, 543 }, { 544 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfa, 0x2f, 0xf5, 545 0xce, 0xb6, 0xd5, 0xd7, 0xd2, 0xd8, 0xb6, 0xb4, 546 0xb0, 0xc7, 0xc9, 0xc1, 0x00, 0x84, 0x00, 0x71, 547 0x00, 0xa5, 548 }, { 549 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf7, 0x2f, 0xf2, 550 0xce, 0xb9, 0xd5, 0xd8, 0xd2, 0xd8, 0xb4, 0xb4, 551 0xaf, 0xc7, 0xc9, 0xc1, 0x00, 0x87, 0x00, 0x73, 552 0x00, 0xa8, 553 }, { 554 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf5, 0x2f, 0xf0, 555 0xdf, 0xba, 0xd5, 0xd7, 0xd2, 0xd7, 0xb4, 0xb4, 556 0xaf, 0xc5, 0xc7, 0xbf, 0x00, 0x8a, 0x00, 0x76, 557 0x00, 0xac, 558 }, { 559 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf2, 0x2f, 0xed, 560 0xcE, 0xbb, 0xd4, 0xd6, 0xd2, 0xd6, 0xb5, 0xb4, 561 0xaF, 0xc5, 0xc7, 0xbf, 0x00, 0x8c, 0x00, 0x78, 562 0x00, 0xaf, 563 }, { 564 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x2f, 0xeb, 565 0xcd, 0xbb, 0xd2, 0xd7, 0xd3, 0xd6, 0xb3, 0xb4, 566 0xae, 0xc5, 0xc6, 0xbe, 0x00, 0x91, 0x00, 0x7d, 567 0x00, 0xb6, 568 }, { 569 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xee, 0x2f, 0xea, 570 0xce, 0xbd, 0xd4, 0xd6, 0xd2, 0xd5, 0xb2, 0xb3, 571 0xad, 0xc3, 0xc4, 0xbb, 0x00, 0x94, 0x00, 0x7f, 572 0x00, 0xba, 573 }, { 574 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xec, 0x2f, 0xe8, 575 0xce, 0xbe, 0xd3, 0xd6, 0xd3, 0xd5, 0xb2, 0xb2, 576 0xac, 0xc3, 0xc5, 0xbc, 0x00, 0x96, 0x00, 0x81, 577 0x00, 0xbd, 578 }, { 579 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xeb, 0x2f, 0xe7, 580 0xce, 0xbf, 0xd3, 0xd6, 0xd2, 0xd5, 0xb1, 0xb2, 581 0xab, 0xc2, 0xc4, 0xbb, 0x00, 0x99, 0x00, 0x83, 582 0x00, 0xc0, 583 }, { 584 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x5f, 0xe9, 585 0xca, 0xbf, 0xd3, 0xd5, 0xd2, 0xd4, 0xb2, 0xb2, 586 0xab, 0xc1, 0xc4, 0xba, 0x00, 0x9b, 0x00, 0x85, 587 0x00, 0xc3, 588 }, { 589 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xea, 0x5f, 0xe8, 590 0xee, 0xbf, 0xd2, 0xd5, 0xd2, 0xd4, 0xb1, 0xb2, 591 0xab, 0xc1, 0xc2, 0xb9, 0x00, 0x9D, 0x00, 0x87, 592 0x00, 0xc6, 593 }, { 594 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe9, 0x5f, 0xe7, 595 0xcd, 0xbf, 0xd2, 0xd6, 0xd2, 0xd4, 0xb1, 0xb2, 596 0xab, 0xbe, 0xc0, 0xb7, 0x00, 0xa1, 0x00, 0x8a, 597 0x00, 0xca, 598 }, { 599 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x61, 0xe6, 600 0xcd, 0xbf, 0xd1, 0xd6, 0xd3, 0xd4, 0xaf, 0xb0, 601 0xa9, 0xbe, 0xc1, 0xb7, 0x00, 0xa3, 0x00, 0x8b, 602 0x00, 0xce, 603 }, { 604 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x62, 0xe5, 605 0xcc, 0xc0, 0xd0, 0xd6, 0xd2, 0xd4, 0xaf, 0xb1, 606 0xa9, 0xbd, 0xc0, 0xb6, 0x00, 0xa5, 0x00, 0x8d, 607 0x00, 0xd0, 608 }, { 609 0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe7, 0x7f, 0xe3, 610 0xcc, 0xc1, 0xd0, 0xd5, 0xd3, 0xd3, 0xae, 0xaf, 611 0xa8, 0xbe, 0xc0, 0xb7, 0x00, 0xa8, 0x00, 0x90, 612 0x00, 0xd3, 613 } 614 }; 615 616 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v32[GAMMA_LEVEL_NUM] = { 617 { 618 0xfa, 0x01, 0x43, 0x14, 0x45, 0x72, 0x5e, 0x6b, 619 0xa1, 0xa7, 0x9a, 0xb4, 0xcb, 0xb8, 0x92, 0xac, 620 0x97, 0xb4, 0xc3, 0xb5, 0x00, 0x4e, 0x00, 0x37, 621 0x00, 0x58, 622 }, { 623 0xfa, 0x01, 0x43, 0x14, 0x45, 0x85, 0x71, 0x7d, 624 0xa6, 0xb6, 0xa1, 0xb5, 0xca, 0xba, 0x93, 0xac, 625 0x98, 0xb2, 0xc0, 0xaf, 0x00, 0x59, 0x00, 0x43, 626 0x00, 0x64, 627 }, { 628 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa4, 0x94, 0x9e, 629 0xa0, 0xbb, 0x9c, 0xc3, 0xd2, 0xc6, 0x93, 0xaa, 630 0x95, 0xb7, 0xc2, 0xb4, 0x00, 0x65, 0x00, 0x50, 631 0x00, 0x74, 632 }, { 633 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa1, 0xa6, 634 0xa0, 0xb9, 0x9b, 0xc3, 0xd1, 0xc8, 0x90, 0xa6, 635 0x90, 0xbb, 0xc3, 0xb7, 0x00, 0x6f, 0x00, 0x5b, 636 0x00, 0x80, 637 }, { 638 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa6, 0x9d, 0x9f, 639 0x9f, 0xb8, 0x9a, 0xc7, 0xd5, 0xcc, 0x90, 0xa5, 640 0x8f, 0xb8, 0xc1, 0xb6, 0x00, 0x74, 0x00, 0x60, 641 0x00, 0x85, 642 }, { 643 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb3, 0xae, 0xae, 644 0x9e, 0xb7, 0x9a, 0xc8, 0xd6, 0xce, 0x91, 0xa6, 645 0x90, 0xb6, 0xc0, 0xb3, 0x00, 0x78, 0x00, 0x65, 646 0x00, 0x8a, 647 }, { 648 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa9, 0xa8, 649 0xa3, 0xb9, 0x9e, 0xc4, 0xd3, 0xcb, 0x94, 0xa6, 650 0x90, 0xb6, 0xbf, 0xb3, 0x00, 0x7c, 0x00, 0x69, 651 0x00, 0x8e, 652 }, { 653 0xfa, 0x01, 0x43, 0x14, 0x45, 0xaf, 0xaf, 0xa9, 654 0xa5, 0xbc, 0xa2, 0xc7, 0xd5, 0xcd, 0x93, 0xa5, 655 0x8f, 0xb4, 0xbd, 0xb1, 0x00, 0x83, 0x00, 0x70, 656 0x00, 0x96, 657 }, { 658 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xab, 0xa3, 659 0xaa, 0xbf, 0xa7, 0xc5, 0xd3, 0xcb, 0x93, 0xa5, 660 0x8f, 0xb2, 0xbb, 0xb0, 0x00, 0x86, 0x00, 0x74, 661 0x00, 0x9b, 662 }, { 663 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xb5, 0xab, 664 0xab, 0xc0, 0xa9, 0xc7, 0xd4, 0xcc, 0x94, 0xa4, 665 0x8f, 0xb1, 0xbb, 0xaf, 0x00, 0x8a, 0x00, 0x77, 666 0x00, 0x9e, 667 }, { 668 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb2, 0xa7, 669 0xae, 0xc2, 0xab, 0xc5, 0xd3, 0xca, 0x93, 0xa4, 670 0x8f, 0xb1, 0xba, 0xae, 0x00, 0x8d, 0x00, 0x7b, 671 0x00, 0xa2, 672 }, { 673 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xaf, 0xa3, 674 0xb0, 0xc3, 0xae, 0xc4, 0xd1, 0xc8, 0x93, 0xa4, 675 0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x8f, 0x00, 0x7d, 676 0x00, 0xa5, 677 }, { 678 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbd, 0xaf, 679 0xae, 0xc1, 0xab, 0xc2, 0xd0, 0xc6, 0x94, 0xa4, 680 0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x92, 0x00, 0x80, 681 0x00, 0xa8, 682 }, { 683 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xb9, 0xac, 684 0xad, 0xc1, 0xab, 0xc4, 0xd1, 0xc7, 0x95, 0xa4, 685 0x90, 0xb0, 0xb9, 0xad, 0x00, 0x95, 0x00, 0x84, 686 0x00, 0xac, 687 }, { 688 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb6, 0xa7, 689 0xaf, 0xc2, 0xae, 0xc5, 0xd1, 0xc7, 0x93, 0xa3, 690 0x8e, 0xb0, 0xb9, 0xad, 0x00, 0x98, 0x00, 0x86, 691 0x00, 0xaf, 692 }, { 693 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbf, 0xaf, 694 0xad, 0xc1, 0xab, 0xc3, 0xd0, 0xc6, 0x94, 0xa3, 695 0x8f, 0xaf, 0xb8, 0xac, 0x00, 0x9a, 0x00, 0x89, 696 0x00, 0xb2, 697 }, { 698 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xbc, 0xac, 699 0xaf, 0xc2, 0xad, 0xc2, 0xcf, 0xc4, 0x94, 0xa3, 700 0x90, 0xaf, 0xb8, 0xad, 0x00, 0x9c, 0x00, 0x8b, 701 0x00, 0xb5, 702 }, { 703 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7, 704 0xb1, 0xc4, 0xaf, 0xc3, 0xcf, 0xc5, 0x94, 0xa3, 705 0x8f, 0xae, 0xb7, 0xac, 0x00, 0x9f, 0x00, 0x8e, 706 0x00, 0xb8, 707 }, { 708 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7, 709 0xaf, 0xc2, 0xad, 0xc1, 0xce, 0xc3, 0x95, 0xa3, 710 0x90, 0xad, 0xb6, 0xab, 0x00, 0xa2, 0x00, 0x91, 711 0x00, 0xbb, 712 }, { 713 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xbe, 0xac, 714 0xb1, 0xc4, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa4, 715 0x91, 0xad, 0xb6, 0xab, 0x00, 0xa4, 0x00, 0x93, 716 0x00, 0xbd, 717 }, { 718 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8, 719 0xb3, 0xc5, 0xb2, 0xc1, 0xcd, 0xc2, 0x95, 0xa3, 720 0x90, 0xad, 0xb6, 0xab, 0x00, 0xa6, 0x00, 0x95, 721 0x00, 0xc0, 722 }, { 723 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8, 724 0xb0, 0xc3, 0xaf, 0xc2, 0xce, 0xc2, 0x94, 0xa2, 725 0x90, 0xac, 0xb6, 0xab, 0x00, 0xa8, 0x00, 0x98, 726 0x00, 0xc3, 727 }, { 728 0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xb8, 0xa5, 729 0xb3, 0xc5, 0xb2, 0xc1, 0xcc, 0xc0, 0x95, 0xa2, 730 0x90, 0xad, 0xb6, 0xab, 0x00, 0xaa, 0x00, 0x9a, 731 0x00, 0xc5, 732 }, { 733 0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xc0, 0xac, 734 0xb0, 0xc3, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa2, 735 0x90, 0xac, 0xb5, 0xa9, 0x00, 0xac, 0x00, 0x9c, 736 0x00, 0xc8, 737 }, { 738 0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbd, 0xa8, 739 0xaf, 0xc2, 0xaf, 0xc1, 0xcc, 0xc0, 0x95, 0xa2, 740 0x90, 0xac, 0xb5, 0xaa, 0x00, 0xb1, 0x00, 0xa1, 741 0x00, 0xcc, 742 }, 743 }; 744 745 static const struct s6e8aa0_variant s6e8aa0_variants[] = { 746 { 747 .version = 32, 748 .gamma_tables = s6e8aa0_gamma_tables_v32, 749 }, { 750 .version = 96, 751 .gamma_tables = s6e8aa0_gamma_tables_v96, 752 }, { 753 .version = 142, 754 .gamma_tables = s6e8aa0_gamma_tables_v142, 755 }, { 756 .version = 210, 757 .gamma_tables = s6e8aa0_gamma_tables_v142, 758 } 759 }; 760 761 static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx) 762 { 763 const u8 *gamma; 764 765 if (ctx->error) 766 return; 767 768 gamma = ctx->variant->gamma_tables[ctx->brightness]; 769 770 if (ctx->version >= 142) 771 s6e8aa0_elvss_nvm_set(ctx); 772 773 s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN); 774 775 /* update gamma table. */ 776 s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03); 777 } 778 779 static void s6e8aa0_panel_init(struct s6e8aa0 *ctx) 780 { 781 s6e8aa0_apply_level_1_key(ctx); 782 s6e8aa0_apply_level_2_key(ctx); 783 msleep(20); 784 785 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE); 786 msleep(40); 787 788 s6e8aa0_panel_cond_set(ctx); 789 s6e8aa0_display_condition_set(ctx); 790 s6e8aa0_brightness_set(ctx); 791 s6e8aa0_etc_source_control(ctx); 792 s6e8aa0_etc_pentile_control(ctx); 793 s6e8aa0_elvss_nvm_set(ctx); 794 s6e8aa0_etc_power_control(ctx); 795 s6e8aa0_etc_elvss_control(ctx); 796 msleep(ctx->init_delay); 797 } 798 799 static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx, 800 u16 size) 801 { 802 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 803 int ret; 804 805 if (ctx->error < 0) 806 return; 807 808 ret = mipi_dsi_set_maximum_return_packet_size(dsi, size); 809 if (ret < 0) { 810 dev_err(ctx->dev, 811 "error %d setting maximum return packet size to %d\n", 812 ret, size); 813 ctx->error = ret; 814 } 815 } 816 817 static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx) 818 { 819 u8 id[3]; 820 int ret, i; 821 822 ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id)); 823 if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) { 824 dev_err(ctx->dev, "read id failed\n"); 825 ctx->error = -EIO; 826 return; 827 } 828 829 dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]); 830 831 for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) { 832 if (id[1] == s6e8aa0_variants[i].version) 833 break; 834 } 835 if (i >= ARRAY_SIZE(s6e8aa0_variants)) { 836 dev_err(ctx->dev, "unsupported display version %d\n", id[1]); 837 ctx->error = -EINVAL; 838 return; 839 } 840 841 ctx->variant = &s6e8aa0_variants[i]; 842 ctx->version = id[1]; 843 ctx->id = id[2]; 844 } 845 846 static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx) 847 { 848 s6e8aa0_set_maximum_return_packet_size(ctx, 3); 849 s6e8aa0_read_mtp_id(ctx); 850 s6e8aa0_panel_init(ctx); 851 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON); 852 } 853 854 static int s6e8aa0_power_on(struct s6e8aa0 *ctx) 855 { 856 int ret; 857 858 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 859 if (ret < 0) 860 return ret; 861 862 msleep(ctx->power_on_delay); 863 864 gpiod_set_value(ctx->reset_gpio, 0); 865 usleep_range(10000, 11000); 866 gpiod_set_value(ctx->reset_gpio, 1); 867 868 msleep(ctx->reset_delay); 869 870 return 0; 871 } 872 873 static int s6e8aa0_power_off(struct s6e8aa0 *ctx) 874 { 875 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 876 } 877 878 static int s6e8aa0_disable(struct drm_panel *panel) 879 { 880 return 0; 881 } 882 883 static int s6e8aa0_unprepare(struct drm_panel *panel) 884 { 885 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel); 886 887 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE); 888 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF); 889 msleep(40); 890 891 s6e8aa0_clear_error(ctx); 892 893 return s6e8aa0_power_off(ctx); 894 } 895 896 static int s6e8aa0_prepare(struct drm_panel *panel) 897 { 898 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel); 899 int ret; 900 901 ret = s6e8aa0_power_on(ctx); 902 if (ret < 0) 903 return ret; 904 905 s6e8aa0_set_sequence(ctx); 906 ret = ctx->error; 907 908 if (ret < 0) 909 s6e8aa0_unprepare(panel); 910 911 return ret; 912 } 913 914 static int s6e8aa0_enable(struct drm_panel *panel) 915 { 916 return 0; 917 } 918 919 static int s6e8aa0_get_modes(struct drm_panel *panel) 920 { 921 struct drm_connector *connector = panel->connector; 922 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel); 923 struct drm_display_mode *mode; 924 925 mode = drm_mode_create(connector->dev); 926 if (!mode) { 927 DRM_ERROR("failed to create a new display mode\n"); 928 return 0; 929 } 930 931 drm_display_mode_from_videomode(&ctx->vm, mode); 932 mode->width_mm = ctx->width_mm; 933 mode->height_mm = ctx->height_mm; 934 connector->display_info.width_mm = mode->width_mm; 935 connector->display_info.height_mm = mode->height_mm; 936 937 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 938 drm_mode_probed_add(connector, mode); 939 940 return 1; 941 } 942 943 static const struct drm_panel_funcs s6e8aa0_drm_funcs = { 944 .disable = s6e8aa0_disable, 945 .unprepare = s6e8aa0_unprepare, 946 .prepare = s6e8aa0_prepare, 947 .enable = s6e8aa0_enable, 948 .get_modes = s6e8aa0_get_modes, 949 }; 950 951 static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx) 952 { 953 struct device *dev = ctx->dev; 954 struct device_node *np = dev->of_node; 955 int ret; 956 957 ret = of_get_videomode(np, &ctx->vm, 0); 958 if (ret < 0) 959 return ret; 960 961 of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay); 962 of_property_read_u32(np, "reset-delay", &ctx->reset_delay); 963 of_property_read_u32(np, "init-delay", &ctx->init_delay); 964 of_property_read_u32(np, "panel-width-mm", &ctx->width_mm); 965 of_property_read_u32(np, "panel-height-mm", &ctx->height_mm); 966 967 ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal"); 968 ctx->flip_vertical = of_property_read_bool(np, "flip-vertical"); 969 970 return 0; 971 } 972 973 static int s6e8aa0_probe(struct mipi_dsi_device *dsi) 974 { 975 struct device *dev = &dsi->dev; 976 struct s6e8aa0 *ctx; 977 int ret; 978 979 ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL); 980 if (!ctx) 981 return -ENOMEM; 982 983 mipi_dsi_set_drvdata(dsi, ctx); 984 985 ctx->dev = dev; 986 987 dsi->lanes = 4; 988 dsi->format = MIPI_DSI_FMT_RGB888; 989 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST 990 | MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP 991 | MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET 992 | MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT; 993 994 ret = s6e8aa0_parse_dt(ctx); 995 if (ret < 0) 996 return ret; 997 998 ctx->supplies[0].supply = "vdd3"; 999 ctx->supplies[1].supply = "vci"; 1000 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 1001 ctx->supplies); 1002 if (ret < 0) { 1003 dev_err(dev, "failed to get regulators: %d\n", ret); 1004 return ret; 1005 } 1006 1007 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 1008 if (IS_ERR(ctx->reset_gpio)) { 1009 dev_err(dev, "cannot get reset-gpios %ld\n", 1010 PTR_ERR(ctx->reset_gpio)); 1011 return PTR_ERR(ctx->reset_gpio); 1012 } 1013 1014 ctx->brightness = GAMMA_LEVEL_NUM - 1; 1015 1016 drm_panel_init(&ctx->panel); 1017 ctx->panel.dev = dev; 1018 ctx->panel.funcs = &s6e8aa0_drm_funcs; 1019 1020 ret = drm_panel_add(&ctx->panel); 1021 if (ret < 0) 1022 return ret; 1023 1024 ret = mipi_dsi_attach(dsi); 1025 if (ret < 0) 1026 drm_panel_remove(&ctx->panel); 1027 1028 return ret; 1029 } 1030 1031 static int s6e8aa0_remove(struct mipi_dsi_device *dsi) 1032 { 1033 struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi); 1034 1035 mipi_dsi_detach(dsi); 1036 drm_panel_remove(&ctx->panel); 1037 1038 return 0; 1039 } 1040 1041 static const struct of_device_id s6e8aa0_of_match[] = { 1042 { .compatible = "samsung,s6e8aa0" }, 1043 { } 1044 }; 1045 MODULE_DEVICE_TABLE(of, s6e8aa0_of_match); 1046 1047 static struct mipi_dsi_driver s6e8aa0_driver = { 1048 .probe = s6e8aa0_probe, 1049 .remove = s6e8aa0_remove, 1050 .driver = { 1051 .name = "panel-samsung-s6e8aa0", 1052 .of_match_table = s6e8aa0_of_match, 1053 }, 1054 }; 1055 module_mipi_dsi_driver(s6e8aa0_driver); 1056 1057 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>"); 1058 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 1059 MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>"); 1060 MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>"); 1061 MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>"); 1062 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>"); 1063 MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver"); 1064 MODULE_LICENSE("GPL v2"); 1065