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