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