linux/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
<<
>>
Prefs
   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 <linux/delay.h>
  16#include <linux/gpio/consumer.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/regulator/consumer.h>
  20
  21#include <video/mipi_display.h>
  22#include <video/of_videomode.h>
  23#include <video/videomode.h>
  24
  25#include <drm/drm_mipi_dsi.h>
  26#include <drm/drm_modes.h>
  27#include <drm/drm_panel.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_buffer(dsi, data, len);
 145        if (ret < 0) {
 146                dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
 147                        (int)len, 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                                                   u16 size)
 804{
 805        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 806        int ret;
 807
 808        if (ctx->error < 0)
 809                return;
 810
 811        ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
 812        if (ret < 0) {
 813                dev_err(ctx->dev,
 814                        "error %d setting maximum return packet size to %d\n",
 815                        ret, size);
 816                ctx->error = ret;
 817        }
 818}
 819
 820static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
 821{
 822        u8 id[3];
 823        int ret, i;
 824
 825        ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
 826        if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) {
 827                dev_err(ctx->dev, "read id failed\n");
 828                ctx->error = -EIO;
 829                return;
 830        }
 831
 832        dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
 833
 834        for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
 835                if (id[1] == s6e8aa0_variants[i].version)
 836                        break;
 837        }
 838        if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
 839                dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
 840                ctx->error = -EINVAL;
 841                return;
 842        }
 843
 844        ctx->variant = &s6e8aa0_variants[i];
 845        ctx->version = id[1];
 846        ctx->id = id[2];
 847}
 848
 849static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
 850{
 851        s6e8aa0_set_maximum_return_packet_size(ctx, 3);
 852        s6e8aa0_read_mtp_id(ctx);
 853        s6e8aa0_panel_init(ctx);
 854        s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
 855}
 856
 857static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
 858{
 859        int ret;
 860
 861        ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 862        if (ret < 0)
 863                return ret;
 864
 865        msleep(ctx->power_on_delay);
 866
 867        gpiod_set_value(ctx->reset_gpio, 0);
 868        usleep_range(10000, 11000);
 869        gpiod_set_value(ctx->reset_gpio, 1);
 870
 871        msleep(ctx->reset_delay);
 872
 873        return 0;
 874}
 875
 876static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
 877{
 878        return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 879}
 880
 881static int s6e8aa0_disable(struct drm_panel *panel)
 882{
 883        return 0;
 884}
 885
 886static int s6e8aa0_unprepare(struct drm_panel *panel)
 887{
 888        struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 889
 890        s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
 891        s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
 892        msleep(40);
 893
 894        s6e8aa0_clear_error(ctx);
 895
 896        return s6e8aa0_power_off(ctx);
 897}
 898
 899static int s6e8aa0_prepare(struct drm_panel *panel)
 900{
 901        struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 902        int ret;
 903
 904        ret = s6e8aa0_power_on(ctx);
 905        if (ret < 0)
 906                return ret;
 907
 908        s6e8aa0_set_sequence(ctx);
 909        ret = ctx->error;
 910
 911        if (ret < 0)
 912                s6e8aa0_unprepare(panel);
 913
 914        return ret;
 915}
 916
 917static int s6e8aa0_enable(struct drm_panel *panel)
 918{
 919        return 0;
 920}
 921
 922static int s6e8aa0_get_modes(struct drm_panel *panel,
 923                             struct drm_connector *connector)
 924{
 925        struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 926        struct drm_display_mode *mode;
 927
 928        mode = drm_mode_create(connector->dev);
 929        if (!mode) {
 930                dev_err(panel->dev, "failed to create a new display mode\n");
 931                return 0;
 932        }
 933
 934        drm_display_mode_from_videomode(&ctx->vm, mode);
 935        mode->width_mm = ctx->width_mm;
 936        mode->height_mm = ctx->height_mm;
 937        connector->display_info.width_mm = mode->width_mm;
 938        connector->display_info.height_mm = mode->height_mm;
 939
 940        mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 941        drm_mode_probed_add(connector, mode);
 942
 943        return 1;
 944}
 945
 946static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
 947        .disable = s6e8aa0_disable,
 948        .unprepare = s6e8aa0_unprepare,
 949        .prepare = s6e8aa0_prepare,
 950        .enable = s6e8aa0_enable,
 951        .get_modes = s6e8aa0_get_modes,
 952};
 953
 954static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
 955{
 956        struct device *dev = ctx->dev;
 957        struct device_node *np = dev->of_node;
 958        int ret;
 959
 960        ret = of_get_videomode(np, &ctx->vm, 0);
 961        if (ret < 0)
 962                return ret;
 963
 964        of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
 965        of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
 966        of_property_read_u32(np, "init-delay", &ctx->init_delay);
 967        of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
 968        of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
 969
 970        ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
 971        ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
 972
 973        return 0;
 974}
 975
 976static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
 977{
 978        struct device *dev = &dsi->dev;
 979        struct s6e8aa0 *ctx;
 980        int ret;
 981
 982        ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
 983        if (!ctx)
 984                return -ENOMEM;
 985
 986        mipi_dsi_set_drvdata(dsi, ctx);
 987
 988        ctx->dev = dev;
 989
 990        dsi->lanes = 4;
 991        dsi->format = MIPI_DSI_FMT_RGB888;
 992        dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
 993                | MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP
 994                | MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET
 995                | MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
 996
 997        ret = s6e8aa0_parse_dt(ctx);
 998        if (ret < 0)
 999                return ret;
1000
1001        ctx->supplies[0].supply = "vdd3";
1002        ctx->supplies[1].supply = "vci";
1003        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
1004                                      ctx->supplies);
1005        if (ret < 0) {
1006                dev_err(dev, "failed to get regulators: %d\n", ret);
1007                return ret;
1008        }
1009
1010        ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
1011        if (IS_ERR(ctx->reset_gpio)) {
1012                dev_err(dev, "cannot get reset-gpios %ld\n",
1013                        PTR_ERR(ctx->reset_gpio));
1014                return PTR_ERR(ctx->reset_gpio);
1015        }
1016
1017        ctx->brightness = GAMMA_LEVEL_NUM - 1;
1018
1019        drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs,
1020                       DRM_MODE_CONNECTOR_DSI);
1021
1022        drm_panel_add(&ctx->panel);
1023
1024        ret = mipi_dsi_attach(dsi);
1025        if (ret < 0)
1026                drm_panel_remove(&ctx->panel);
1027
1028        return ret;
1029}
1030
1031static 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
1041static const struct of_device_id s6e8aa0_of_match[] = {
1042        { .compatible = "samsung,s6e8aa0" },
1043        { }
1044};
1045MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1046
1047static 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};
1055module_mipi_dsi_driver(s6e8aa0_driver);
1056
1057MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1058MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1059MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1060MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1061MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1062MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1063MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1064MODULE_LICENSE("GPL v2");
1065