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