Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver.
0004  *
0005  * Copyright (c) 2013 Samsung Electronics Co., Ltd
0006  *
0007  * Inki Dae, <inki.dae@samsung.com>
0008  * Donghwa Lee, <dh09.lee@samsung.com>
0009  * Joongmock Shin <jmock.shin@samsung.com>
0010  * Eunchul Kim <chulspro.kim@samsung.com>
0011  * Tomasz Figa <t.figa@samsung.com>
0012  * Andrzej Hajda <a.hajda@samsung.com>
0013 */
0014 
0015 #include <linux/delay.h>
0016 #include <linux/gpio/consumer.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/regulator/consumer.h>
0020 
0021 #include <video/mipi_display.h>
0022 #include <video/of_videomode.h>
0023 #include <video/videomode.h>
0024 
0025 #include <drm/drm_mipi_dsi.h>
0026 #include <drm/drm_modes.h>
0027 #include <drm/drm_panel.h>
0028 
0029 #define LDI_MTP_LENGTH          24
0030 #define GAMMA_LEVEL_NUM         25
0031 #define GAMMA_TABLE_LEN         26
0032 
0033 #define PANELCTL_SS_MASK        (1 << 5)
0034 #define PANELCTL_SS_1_800       (0 << 5)
0035 #define PANELCTL_SS_800_1       (1 << 5)
0036 #define PANELCTL_GTCON_MASK     (7 << 2)
0037 #define PANELCTL_GTCON_110      (6 << 2)
0038 #define PANELCTL_GTCON_111      (7 << 2)
0039 
0040 #define PANELCTL_CLK1_CON_MASK      (7 << 3)
0041 #define PANELCTL_CLK1_000       (0 << 3)
0042 #define PANELCTL_CLK1_001       (1 << 3)
0043 #define PANELCTL_CLK2_CON_MASK      (7 << 0)
0044 #define PANELCTL_CLK2_000       (0 << 0)
0045 #define PANELCTL_CLK2_001       (1 << 0)
0046 
0047 #define PANELCTL_INT1_CON_MASK      (7 << 3)
0048 #define PANELCTL_INT1_000       (0 << 3)
0049 #define PANELCTL_INT1_001       (1 << 3)
0050 #define PANELCTL_INT2_CON_MASK      (7 << 0)
0051 #define PANELCTL_INT2_000       (0 << 0)
0052 #define PANELCTL_INT2_001       (1 << 0)
0053 
0054 #define PANELCTL_BICTL_CON_MASK     (7 << 3)
0055 #define PANELCTL_BICTL_000      (0 << 3)
0056 #define PANELCTL_BICTL_001      (1 << 3)
0057 #define PANELCTL_BICTLB_CON_MASK    (7 << 0)
0058 #define PANELCTL_BICTLB_000     (0 << 0)
0059 #define PANELCTL_BICTLB_001     (1 << 0)
0060 
0061 #define PANELCTL_EM_CLK1_CON_MASK   (7 << 3)
0062 #define PANELCTL_EM_CLK1_110        (6 << 3)
0063 #define PANELCTL_EM_CLK1_111        (7 << 3)
0064 #define PANELCTL_EM_CLK1B_CON_MASK  (7 << 0)
0065 #define PANELCTL_EM_CLK1B_110       (6 << 0)
0066 #define PANELCTL_EM_CLK1B_111       (7 << 0)
0067 
0068 #define PANELCTL_EM_CLK2_CON_MASK   (7 << 3)
0069 #define PANELCTL_EM_CLK2_110        (6 << 3)
0070 #define PANELCTL_EM_CLK2_111        (7 << 3)
0071 #define PANELCTL_EM_CLK2B_CON_MASK  (7 << 0)
0072 #define PANELCTL_EM_CLK2B_110       (6 << 0)
0073 #define PANELCTL_EM_CLK2B_111       (7 << 0)
0074 
0075 #define PANELCTL_EM_INT1_CON_MASK   (7 << 3)
0076 #define PANELCTL_EM_INT1_000        (0 << 3)
0077 #define PANELCTL_EM_INT1_001        (1 << 3)
0078 #define PANELCTL_EM_INT2_CON_MASK   (7 << 0)
0079 #define PANELCTL_EM_INT2_000        (0 << 0)
0080 #define PANELCTL_EM_INT2_001        (1 << 0)
0081 
0082 #define AID_DISABLE         (0x4)
0083 #define AID_1               (0x5)
0084 #define AID_2               (0x6)
0085 #define AID_3               (0x7)
0086 
0087 typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
0088 
0089 struct s6e8aa0_variant {
0090     u8 version;
0091     const s6e8aa0_gamma_table *gamma_tables;
0092 };
0093 
0094 struct s6e8aa0 {
0095     struct device *dev;
0096     struct drm_panel panel;
0097 
0098     struct regulator_bulk_data supplies[2];
0099     struct gpio_desc *reset_gpio;
0100     u32 power_on_delay;
0101     u32 reset_delay;
0102     u32 init_delay;
0103     bool flip_horizontal;
0104     bool flip_vertical;
0105     struct videomode vm;
0106     u32 width_mm;
0107     u32 height_mm;
0108 
0109     u8 version;
0110     u8 id;
0111     const struct s6e8aa0_variant *variant;
0112     int brightness;
0113 
0114     /* This field is tested by functions directly accessing DSI bus before
0115      * transfer, transfer is skipped if it is set. In case of transfer
0116      * failure or unexpected response the field is set to error value.
0117      * Such construct allows to eliminate many checks in higher level
0118      * functions.
0119      */
0120     int error;
0121 };
0122 
0123 static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
0124 {
0125     return container_of(panel, struct s6e8aa0, panel);
0126 }
0127 
0128 static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
0129 {
0130     int ret = ctx->error;
0131 
0132     ctx->error = 0;
0133     return ret;
0134 }
0135 
0136 static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
0137 {
0138     struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0139     ssize_t ret;
0140 
0141     if (ctx->error < 0)
0142         return;
0143 
0144     ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
0145     if (ret < 0) {
0146         dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
0147             (int)len, data);
0148         ctx->error = ret;
0149     }
0150 }
0151 
0152 static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len)
0153 {
0154     struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0155     int ret;
0156 
0157     if (ctx->error < 0)
0158         return ctx->error;
0159 
0160     ret = mipi_dsi_dcs_read(dsi, cmd, data, len);
0161     if (ret < 0) {
0162         dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
0163         ctx->error = ret;
0164     }
0165 
0166     return ret;
0167 }
0168 
0169 #define s6e8aa0_dcs_write_seq(ctx, seq...) \
0170 ({\
0171     const u8 d[] = { seq };\
0172     BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\
0173     s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
0174 })
0175 
0176 #define s6e8aa0_dcs_write_seq_static(ctx, seq...) \
0177 ({\
0178     static const u8 d[] = { seq };\
0179     s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
0180 })
0181 
0182 static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
0183 {
0184     s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
0185 }
0186 
0187 static void s6e8aa0_panel_cond_set_v142(struct s6e8aa0 *ctx)
0188 {
0189     static const u8 aids[] = {
0190         0x04, 0x04, 0x04, 0x04, 0x04, 0x60, 0x80, 0xA0
0191     };
0192     u8 aid = aids[ctx->id >> 5];
0193     u8 cfg = 0x3d;
0194     u8 clk_con = 0xc8;
0195     u8 int_con = 0x08;
0196     u8 bictl_con = 0x48;
0197     u8 em_clk1_con = 0xff;
0198     u8 em_clk2_con = 0xff;
0199     u8 em_int_con = 0xc8;
0200 
0201     if (ctx->flip_vertical) {
0202         /* GTCON */
0203         cfg &= ~(PANELCTL_GTCON_MASK);
0204         cfg |= (PANELCTL_GTCON_110);
0205     }
0206 
0207     if (ctx->flip_horizontal) {
0208         /* SS */
0209         cfg &= ~(PANELCTL_SS_MASK);
0210         cfg |= (PANELCTL_SS_1_800);
0211     }
0212 
0213     if (ctx->flip_horizontal || ctx->flip_vertical) {
0214         /* CLK1,2_CON */
0215         clk_con &= ~(PANELCTL_CLK1_CON_MASK |
0216             PANELCTL_CLK2_CON_MASK);
0217         clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001);
0218 
0219         /* INT1,2_CON */
0220         int_con &= ~(PANELCTL_INT1_CON_MASK |
0221             PANELCTL_INT2_CON_MASK);
0222         int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001);
0223 
0224         /* BICTL,B_CON */
0225         bictl_con &= ~(PANELCTL_BICTL_CON_MASK |
0226             PANELCTL_BICTLB_CON_MASK);
0227         bictl_con |= (PANELCTL_BICTL_000 |
0228             PANELCTL_BICTLB_001);
0229 
0230         /* EM_CLK1,1B_CON */
0231         em_clk1_con &= ~(PANELCTL_EM_CLK1_CON_MASK |
0232             PANELCTL_EM_CLK1B_CON_MASK);
0233         em_clk1_con |= (PANELCTL_EM_CLK1_110 |
0234             PANELCTL_EM_CLK1B_110);
0235 
0236         /* EM_CLK2,2B_CON */
0237         em_clk2_con &= ~(PANELCTL_EM_CLK2_CON_MASK |
0238             PANELCTL_EM_CLK2B_CON_MASK);
0239         em_clk2_con |= (PANELCTL_EM_CLK2_110 |
0240             PANELCTL_EM_CLK2B_110);
0241 
0242         /* EM_INT1,2_CON */
0243         em_int_con &= ~(PANELCTL_EM_INT1_CON_MASK |
0244             PANELCTL_EM_INT2_CON_MASK);
0245         em_int_con |= (PANELCTL_EM_INT1_000 |
0246             PANELCTL_EM_INT2_001);
0247     }
0248 
0249     s6e8aa0_dcs_write_seq(ctx,
0250         0xf8, cfg, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00,
0251         0x3c, 0x78, 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00,
0252         0x00, 0x20, aid, 0x08, 0x6e, 0x00, 0x00, 0x00,
0253         0x02, 0x07, 0x07, 0x23, 0x23, 0xc0, clk_con, int_con,
0254         bictl_con, 0xc1, 0x00, 0xc1, em_clk1_con, em_clk2_con,
0255         em_int_con);
0256 }
0257 
0258 static void s6e8aa0_panel_cond_set(struct s6e8aa0 *ctx)
0259 {
0260     if (ctx->version < 142)
0261         s6e8aa0_dcs_write_seq_static(ctx,
0262             0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00,
0263             0x3c, 0x78, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00,
0264             0x00, 0x00, 0x04, 0x08, 0x6e, 0x00, 0x00, 0x00,
0265             0x00, 0x07, 0x07, 0x23, 0x6e, 0xc0, 0xc1, 0x01,
0266             0x81, 0xc1, 0x00, 0xc3, 0xf6, 0xf6, 0xc1
0267         );
0268     else
0269         s6e8aa0_panel_cond_set_v142(ctx);
0270 }
0271 
0272 static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
0273 {
0274     s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
0275 }
0276 
0277 static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
0278 {
0279     s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
0280 }
0281 
0282 static void s6e8aa0_etc_pentile_control(struct s6e8aa0 *ctx)
0283 {
0284     static const u8 pent32[] = {
0285         0xb6, 0x0c, 0x02, 0x03, 0x32, 0xc0, 0x44, 0x44, 0xc0, 0x00
0286     };
0287 
0288     static const u8 pent142[] = {
0289         0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, 0x00
0290     };
0291 
0292     if (ctx->version < 142)
0293         s6e8aa0_dcs_write(ctx, pent32, ARRAY_SIZE(pent32));
0294     else
0295         s6e8aa0_dcs_write(ctx, pent142, ARRAY_SIZE(pent142));
0296 }
0297 
0298 static void s6e8aa0_etc_power_control(struct s6e8aa0 *ctx)
0299 {
0300     static const u8 pwr142[] = {
0301         0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x1e, 0x33, 0x02
0302     };
0303 
0304     static const u8 pwr32[] = {
0305         0xf4, 0xcf, 0x0a, 0x15, 0x10, 0x19, 0x33, 0x02
0306     };
0307 
0308     if (ctx->version < 142)
0309         s6e8aa0_dcs_write(ctx, pwr32, ARRAY_SIZE(pwr32));
0310     else
0311         s6e8aa0_dcs_write(ctx, pwr142, ARRAY_SIZE(pwr142));
0312 }
0313 
0314 static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx)
0315 {
0316     u8 id = ctx->id ? 0 : 0x95;
0317 
0318     s6e8aa0_dcs_write_seq(ctx, 0xb1, 0x04, id);
0319 }
0320 
0321 static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx)
0322 {
0323     u8 br;
0324 
0325     switch (ctx->brightness) {
0326     case 0 ... 6: /* 30cd ~ 100cd */
0327         br = 0xdf;
0328         break;
0329     case 7 ... 11: /* 120cd ~ 150cd */
0330         br = 0xdd;
0331         break;
0332     case 12 ... 15: /* 180cd ~ 210cd */
0333     default:
0334         br = 0xd9;
0335         break;
0336     case 16 ... 24: /* 240cd ~ 300cd */
0337         br = 0xd0;
0338         break;
0339     }
0340 
0341     s6e8aa0_dcs_write_seq(ctx, 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e,
0342         0xc4, 0x0f, 0x40, 0x41, br, 0x00, 0x60, 0x19);
0343 }
0344 
0345 static void s6e8aa0_elvss_nvm_set(struct s6e8aa0 *ctx)
0346 {
0347     if (ctx->version < 142)
0348         s6e8aa0_dcs_write_seq_static(ctx,
0349             0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 0xc4, 0x07,
0350             0x40, 0x41, 0xc1, 0x00, 0x60, 0x19);
0351     else
0352         s6e8aa0_elvss_nvm_set_v142(ctx);
0353 };
0354 
0355 static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
0356 {
0357     s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
0358 }
0359 
0360 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v142[GAMMA_LEVEL_NUM] = {
0361     {
0362         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x62, 0x55, 0x55,
0363         0xaf, 0xb1, 0xb1, 0xbd, 0xce, 0xb7, 0x9a, 0xb1,
0364         0x90, 0xb2, 0xc4, 0xae, 0x00, 0x60, 0x00, 0x40,
0365         0x00, 0x70,
0366     }, {
0367         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x74, 0x68, 0x69,
0368         0xb8, 0xc1, 0xb7, 0xbd, 0xcd, 0xb8, 0x93, 0xab,
0369         0x88, 0xb4, 0xc4, 0xb1, 0x00, 0x6b, 0x00, 0x4d,
0370         0x00, 0x7d,
0371     }, {
0372         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x95, 0x8a, 0x89,
0373         0xb4, 0xc6, 0xb2, 0xc5, 0xd2, 0xbf, 0x90, 0xa8,
0374         0x85, 0xb5, 0xc4, 0xb3, 0x00, 0x7b, 0x00, 0x5d,
0375         0x00, 0x8f,
0376     }, {
0377         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9f, 0x98, 0x92,
0378         0xb3, 0xc4, 0xb0, 0xbc, 0xcc, 0xb4, 0x91, 0xa6,
0379         0x87, 0xb5, 0xc5, 0xb4, 0x00, 0x87, 0x00, 0x6a,
0380         0x00, 0x9e,
0381     }, {
0382         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x99, 0x93, 0x8b,
0383         0xb2, 0xc2, 0xb0, 0xbd, 0xce, 0xb4, 0x90, 0xa6,
0384         0x87, 0xb3, 0xc3, 0xb2, 0x00, 0x8d, 0x00, 0x70,
0385         0x00, 0xa4,
0386     }, {
0387         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xa5, 0x99,
0388         0xb2, 0xc2, 0xb0, 0xbb, 0xcd, 0xb1, 0x93, 0xa7,
0389         0x8a, 0xb2, 0xc1, 0xb0, 0x00, 0x92, 0x00, 0x75,
0390         0x00, 0xaa,
0391     }, {
0392         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xa0, 0x93,
0393         0xb6, 0xc4, 0xb4, 0xb5, 0xc8, 0xaa, 0x94, 0xa9,
0394         0x8c, 0xb2, 0xc0, 0xb0, 0x00, 0x97, 0x00, 0x7a,
0395         0x00, 0xaf,
0396     }, {
0397         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xa7, 0x96,
0398         0xb3, 0xc2, 0xb0, 0xba, 0xcb, 0xb0, 0x94, 0xa8,
0399         0x8c, 0xb0, 0xbf, 0xaf, 0x00, 0x9f, 0x00, 0x83,
0400         0x00, 0xb9,
0401     }, {
0402         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9d, 0xa2, 0x90,
0403         0xb6, 0xc5, 0xb3, 0xb8, 0xc9, 0xae, 0x94, 0xa8,
0404         0x8d, 0xaf, 0xbd, 0xad, 0x00, 0xa4, 0x00, 0x88,
0405         0x00, 0xbf,
0406     }, {
0407         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xac, 0x97,
0408         0xb4, 0xc4, 0xb1, 0xbb, 0xcb, 0xb2, 0x93, 0xa7,
0409         0x8d, 0xae, 0xbc, 0xad, 0x00, 0xa7, 0x00, 0x8c,
0410         0x00, 0xc3,
0411     }, {
0412         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa2, 0xa9, 0x93,
0413         0xb6, 0xc5, 0xb2, 0xba, 0xc9, 0xb0, 0x93, 0xa7,
0414         0x8d, 0xae, 0xbb, 0xac, 0x00, 0xab, 0x00, 0x90,
0415         0x00, 0xc8,
0416     }, {
0417         0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9e, 0xa6, 0x8f,
0418         0xb7, 0xc6, 0xb3, 0xb8, 0xc8, 0xb0, 0x93, 0xa6,
0419         0x8c, 0xae, 0xbb, 0xad, 0x00, 0xae, 0x00, 0x93,
0420         0x00, 0xcc,
0421     }, {
0422         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb4, 0x9c,
0423         0xb3, 0xc3, 0xaf, 0xb7, 0xc7, 0xaf, 0x93, 0xa6,
0424         0x8c, 0xaf, 0xbc, 0xad, 0x00, 0xb1, 0x00, 0x97,
0425         0x00, 0xcf,
0426     }, {
0427         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xb1, 0x98,
0428         0xb1, 0xc2, 0xab, 0xba, 0xc9, 0xb2, 0x93, 0xa6,
0429         0x8d, 0xae, 0xba, 0xab, 0x00, 0xb5, 0x00, 0x9b,
0430         0x00, 0xd4,
0431     }, {
0432         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xae, 0x94,
0433         0xb2, 0xc3, 0xac, 0xbb, 0xca, 0xb4, 0x91, 0xa4,
0434         0x8a, 0xae, 0xba, 0xac, 0x00, 0xb8, 0x00, 0x9e,
0435         0x00, 0xd8,
0436     }, {
0437         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb7, 0x9c,
0438         0xae, 0xc0, 0xa9, 0xba, 0xc9, 0xb3, 0x92, 0xa5,
0439         0x8b, 0xad, 0xb9, 0xab, 0x00, 0xbb, 0x00, 0xa1,
0440         0x00, 0xdc,
0441     }, {
0442         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb4, 0x97,
0443         0xb0, 0xc1, 0xaa, 0xb9, 0xc8, 0xb2, 0x92, 0xa5,
0444         0x8c, 0xae, 0xb9, 0xab, 0x00, 0xbe, 0x00, 0xa4,
0445         0x00, 0xdf,
0446     }, {
0447         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
0448         0xb0, 0xc2, 0xab, 0xbb, 0xc9, 0xb3, 0x91, 0xa4,
0449         0x8b, 0xad, 0xb8, 0xaa, 0x00, 0xc1, 0x00, 0xa8,
0450         0x00, 0xe2,
0451     }, {
0452         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
0453         0xae, 0xbf, 0xa8, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
0454         0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xc4, 0x00, 0xab,
0455         0x00, 0xe6,
0456     }, {
0457         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb6, 0x98,
0458         0xaf, 0xc0, 0xa8, 0xb8, 0xc7, 0xb2, 0x93, 0xa5,
0459         0x8d, 0xad, 0xb7, 0xa9, 0x00, 0xc7, 0x00, 0xae,
0460         0x00, 0xe9,
0461     }, {
0462         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
0463         0xaf, 0xc1, 0xa9, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
0464         0x8b, 0xad, 0xb7, 0xaa, 0x00, 0xc9, 0x00, 0xb0,
0465         0x00, 0xec,
0466     }, {
0467         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
0468         0xac, 0xbe, 0xa6, 0xbb, 0xc9, 0xb4, 0x90, 0xa3,
0469         0x8a, 0xad, 0xb7, 0xa9, 0x00, 0xcc, 0x00, 0xb4,
0470         0x00, 0xf0,
0471     }, {
0472         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xb0, 0x91,
0473         0xae, 0xc0, 0xa6, 0xba, 0xc8, 0xb4, 0x91, 0xa4,
0474         0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xcf, 0x00, 0xb7,
0475         0x00, 0xf3,
0476     }, {
0477         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb8, 0x98,
0478         0xab, 0xbd, 0xa4, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
0479         0x8b, 0xac, 0xb6, 0xa8, 0x00, 0xd1, 0x00, 0xb9,
0480         0x00, 0xf6,
0481     }, {
0482         0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb5, 0x95,
0483         0xa9, 0xbc, 0xa1, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
0484         0x8a, 0xad, 0xb6, 0xa8, 0x00, 0xd6, 0x00, 0xbf,
0485         0x00, 0xfc,
0486     },
0487 };
0488 
0489 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v96[GAMMA_LEVEL_NUM] = {
0490     {
0491         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0492         0xdf, 0x1f, 0xd7, 0xdc, 0xb7, 0xe1, 0xc0, 0xaf,
0493         0xc4, 0xd2, 0xd0, 0xcf, 0x00, 0x4d, 0x00, 0x40,
0494         0x00, 0x5f,
0495     }, {
0496         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0497         0xd5, 0x35, 0xcf, 0xdc, 0xc1, 0xe1, 0xbf, 0xb3,
0498         0xc1, 0xd2, 0xd1, 0xce, 0x00, 0x53, 0x00, 0x46,
0499         0x00, 0x67,
0500     }, {
0501         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0502         0xd2, 0x64, 0xcf, 0xdb, 0xc6, 0xe1, 0xbd, 0xb3,
0503         0xbd, 0xd2, 0xd2, 0xce, 0x00, 0x59, 0x00, 0x4b,
0504         0x00, 0x6e,
0505     }, {
0506         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0507         0xd0, 0x7c, 0xcf, 0xdb, 0xc9, 0xe0, 0xbc, 0xb4,
0508         0xbb, 0xcf, 0xd1, 0xcc, 0x00, 0x5f, 0x00, 0x50,
0509         0x00, 0x75,
0510     }, {
0511         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0512         0xd0, 0x8e, 0xd1, 0xdb, 0xcc, 0xdf, 0xbb, 0xb6,
0513         0xb9, 0xd0, 0xd1, 0xcd, 0x00, 0x63, 0x00, 0x54,
0514         0x00, 0x7a,
0515     }, {
0516         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0517         0xd1, 0x9e, 0xd5, 0xda, 0xcd, 0xdd, 0xbb, 0xb7,
0518         0xb9, 0xce, 0xce, 0xc9, 0x00, 0x68, 0x00, 0x59,
0519         0x00, 0x81,
0520     }, {
0521         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
0522         0xd0, 0xa5, 0xd6, 0xda, 0xcf, 0xdd, 0xbb, 0xb7,
0523         0xb8, 0xcc, 0xcd, 0xc7, 0x00, 0x6c, 0x00, 0x5c,
0524         0x00, 0x86,
0525     }, {
0526         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xfe,
0527         0xd0, 0xae, 0xd7, 0xd9, 0xd0, 0xdb, 0xb9, 0xb6,
0528         0xb5, 0xca, 0xcc, 0xc5, 0x00, 0x74, 0x00, 0x63,
0529         0x00, 0x90,
0530     }, {
0531         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf9,
0532         0xcf, 0xb0, 0xd6, 0xd9, 0xd1, 0xdb, 0xb9, 0xb6,
0533         0xb4, 0xca, 0xcb, 0xc5, 0x00, 0x77, 0x00, 0x66,
0534         0x00, 0x94,
0535     }, {
0536         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf7,
0537         0xcf, 0xb3, 0xd7, 0xd8, 0xd1, 0xd9, 0xb7, 0xb6,
0538         0xb3, 0xc9, 0xca, 0xc3, 0x00, 0x7b, 0x00, 0x69,
0539         0x00, 0x99,
0540 
0541     }, {
0542         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfd, 0x2f, 0xf7,
0543         0xdf, 0xb5, 0xd6, 0xd8, 0xd1, 0xd8, 0xb6, 0xb5,
0544         0xb2, 0xca, 0xcb, 0xc4, 0x00, 0x7e, 0x00, 0x6c,
0545         0x00, 0x9d,
0546     }, {
0547         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfa, 0x2f, 0xf5,
0548         0xce, 0xb6, 0xd5, 0xd7, 0xd2, 0xd8, 0xb6, 0xb4,
0549         0xb0, 0xc7, 0xc9, 0xc1, 0x00, 0x84, 0x00, 0x71,
0550         0x00, 0xa5,
0551     }, {
0552         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf7, 0x2f, 0xf2,
0553         0xce, 0xb9, 0xd5, 0xd8, 0xd2, 0xd8, 0xb4, 0xb4,
0554         0xaf, 0xc7, 0xc9, 0xc1, 0x00, 0x87, 0x00, 0x73,
0555         0x00, 0xa8,
0556     }, {
0557         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf5, 0x2f, 0xf0,
0558         0xdf, 0xba, 0xd5, 0xd7, 0xd2, 0xd7, 0xb4, 0xb4,
0559         0xaf, 0xc5, 0xc7, 0xbf, 0x00, 0x8a, 0x00, 0x76,
0560         0x00, 0xac,
0561     }, {
0562         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf2, 0x2f, 0xed,
0563         0xcE, 0xbb, 0xd4, 0xd6, 0xd2, 0xd6, 0xb5, 0xb4,
0564         0xaF, 0xc5, 0xc7, 0xbf, 0x00, 0x8c, 0x00, 0x78,
0565         0x00, 0xaf,
0566     }, {
0567         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x2f, 0xeb,
0568         0xcd, 0xbb, 0xd2, 0xd7, 0xd3, 0xd6, 0xb3, 0xb4,
0569         0xae, 0xc5, 0xc6, 0xbe, 0x00, 0x91, 0x00, 0x7d,
0570         0x00, 0xb6,
0571     }, {
0572         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xee, 0x2f, 0xea,
0573         0xce, 0xbd, 0xd4, 0xd6, 0xd2, 0xd5, 0xb2, 0xb3,
0574         0xad, 0xc3, 0xc4, 0xbb, 0x00, 0x94, 0x00, 0x7f,
0575         0x00, 0xba,
0576     }, {
0577         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xec, 0x2f, 0xe8,
0578         0xce, 0xbe, 0xd3, 0xd6, 0xd3, 0xd5, 0xb2, 0xb2,
0579         0xac, 0xc3, 0xc5, 0xbc, 0x00, 0x96, 0x00, 0x81,
0580         0x00, 0xbd,
0581     }, {
0582         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xeb, 0x2f, 0xe7,
0583         0xce, 0xbf, 0xd3, 0xd6, 0xd2, 0xd5, 0xb1, 0xb2,
0584         0xab, 0xc2, 0xc4, 0xbb, 0x00, 0x99, 0x00, 0x83,
0585         0x00, 0xc0,
0586     }, {
0587         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x5f, 0xe9,
0588         0xca, 0xbf, 0xd3, 0xd5, 0xd2, 0xd4, 0xb2, 0xb2,
0589         0xab, 0xc1, 0xc4, 0xba, 0x00, 0x9b, 0x00, 0x85,
0590         0x00, 0xc3,
0591     }, {
0592         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xea, 0x5f, 0xe8,
0593         0xee, 0xbf, 0xd2, 0xd5, 0xd2, 0xd4, 0xb1, 0xb2,
0594         0xab, 0xc1, 0xc2, 0xb9, 0x00, 0x9D, 0x00, 0x87,
0595         0x00, 0xc6,
0596     }, {
0597         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe9, 0x5f, 0xe7,
0598         0xcd, 0xbf, 0xd2, 0xd6, 0xd2, 0xd4, 0xb1, 0xb2,
0599         0xab, 0xbe, 0xc0, 0xb7, 0x00, 0xa1, 0x00, 0x8a,
0600         0x00, 0xca,
0601     }, {
0602         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x61, 0xe6,
0603         0xcd, 0xbf, 0xd1, 0xd6, 0xd3, 0xd4, 0xaf, 0xb0,
0604         0xa9, 0xbe, 0xc1, 0xb7, 0x00, 0xa3, 0x00, 0x8b,
0605         0x00, 0xce,
0606     }, {
0607         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x62, 0xe5,
0608         0xcc, 0xc0, 0xd0, 0xd6, 0xd2, 0xd4, 0xaf, 0xb1,
0609         0xa9, 0xbd, 0xc0, 0xb6, 0x00, 0xa5, 0x00, 0x8d,
0610         0x00, 0xd0,
0611     }, {
0612         0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe7, 0x7f, 0xe3,
0613         0xcc, 0xc1, 0xd0, 0xd5, 0xd3, 0xd3, 0xae, 0xaf,
0614         0xa8, 0xbe, 0xc0, 0xb7, 0x00, 0xa8, 0x00, 0x90,
0615         0x00, 0xd3,
0616     }
0617 };
0618 
0619 static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v32[GAMMA_LEVEL_NUM] = {
0620     {
0621         0xfa, 0x01, 0x43, 0x14, 0x45, 0x72, 0x5e, 0x6b,
0622         0xa1, 0xa7, 0x9a, 0xb4, 0xcb, 0xb8, 0x92, 0xac,
0623         0x97, 0xb4, 0xc3, 0xb5, 0x00, 0x4e, 0x00, 0x37,
0624         0x00, 0x58,
0625     }, {
0626         0xfa, 0x01, 0x43, 0x14, 0x45, 0x85, 0x71, 0x7d,
0627         0xa6, 0xb6, 0xa1, 0xb5, 0xca, 0xba, 0x93, 0xac,
0628         0x98, 0xb2, 0xc0, 0xaf, 0x00, 0x59, 0x00, 0x43,
0629         0x00, 0x64,
0630     }, {
0631         0xfa, 0x01, 0x43, 0x14, 0x45, 0xa4, 0x94, 0x9e,
0632         0xa0, 0xbb, 0x9c, 0xc3, 0xd2, 0xc6, 0x93, 0xaa,
0633         0x95, 0xb7, 0xc2, 0xb4, 0x00, 0x65, 0x00, 0x50,
0634         0x00, 0x74,
0635     }, {
0636         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa1, 0xa6,
0637         0xa0, 0xb9, 0x9b, 0xc3, 0xd1, 0xc8, 0x90, 0xa6,
0638         0x90, 0xbb, 0xc3, 0xb7, 0x00, 0x6f, 0x00, 0x5b,
0639         0x00, 0x80,
0640     }, {
0641         0xfa, 0x01, 0x43, 0x14, 0x45, 0xa6, 0x9d, 0x9f,
0642         0x9f, 0xb8, 0x9a, 0xc7, 0xd5, 0xcc, 0x90, 0xa5,
0643         0x8f, 0xb8, 0xc1, 0xb6, 0x00, 0x74, 0x00, 0x60,
0644         0x00, 0x85,
0645     }, {
0646         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb3, 0xae, 0xae,
0647         0x9e, 0xb7, 0x9a, 0xc8, 0xd6, 0xce, 0x91, 0xa6,
0648         0x90, 0xb6, 0xc0, 0xb3, 0x00, 0x78, 0x00, 0x65,
0649         0x00, 0x8a,
0650     }, {
0651         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa9, 0xa8,
0652         0xa3, 0xb9, 0x9e, 0xc4, 0xd3, 0xcb, 0x94, 0xa6,
0653         0x90, 0xb6, 0xbf, 0xb3, 0x00, 0x7c, 0x00, 0x69,
0654         0x00, 0x8e,
0655     }, {
0656         0xfa, 0x01, 0x43, 0x14, 0x45, 0xaf, 0xaf, 0xa9,
0657         0xa5, 0xbc, 0xa2, 0xc7, 0xd5, 0xcd, 0x93, 0xa5,
0658         0x8f, 0xb4, 0xbd, 0xb1, 0x00, 0x83, 0x00, 0x70,
0659         0x00, 0x96,
0660     }, {
0661         0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xab, 0xa3,
0662         0xaa, 0xbf, 0xa7, 0xc5, 0xd3, 0xcb, 0x93, 0xa5,
0663         0x8f, 0xb2, 0xbb, 0xb0, 0x00, 0x86, 0x00, 0x74,
0664         0x00, 0x9b,
0665     }, {
0666         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xb5, 0xab,
0667         0xab, 0xc0, 0xa9, 0xc7, 0xd4, 0xcc, 0x94, 0xa4,
0668         0x8f, 0xb1, 0xbb, 0xaf, 0x00, 0x8a, 0x00, 0x77,
0669         0x00, 0x9e,
0670     }, {
0671         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb2, 0xa7,
0672         0xae, 0xc2, 0xab, 0xc5, 0xd3, 0xca, 0x93, 0xa4,
0673         0x8f, 0xb1, 0xba, 0xae, 0x00, 0x8d, 0x00, 0x7b,
0674         0x00, 0xa2,
0675     }, {
0676         0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xaf, 0xa3,
0677         0xb0, 0xc3, 0xae, 0xc4, 0xd1, 0xc8, 0x93, 0xa4,
0678         0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x8f, 0x00, 0x7d,
0679         0x00, 0xa5,
0680     }, {
0681         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbd, 0xaf,
0682         0xae, 0xc1, 0xab, 0xc2, 0xd0, 0xc6, 0x94, 0xa4,
0683         0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x92, 0x00, 0x80,
0684         0x00, 0xa8,
0685     }, {
0686         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xb9, 0xac,
0687         0xad, 0xc1, 0xab, 0xc4, 0xd1, 0xc7, 0x95, 0xa4,
0688         0x90, 0xb0, 0xb9, 0xad, 0x00, 0x95, 0x00, 0x84,
0689         0x00, 0xac,
0690     }, {
0691         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb6, 0xa7,
0692         0xaf, 0xc2, 0xae, 0xc5, 0xd1, 0xc7, 0x93, 0xa3,
0693         0x8e, 0xb0, 0xb9, 0xad, 0x00, 0x98, 0x00, 0x86,
0694         0x00, 0xaf,
0695     }, {
0696         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbf, 0xaf,
0697         0xad, 0xc1, 0xab, 0xc3, 0xd0, 0xc6, 0x94, 0xa3,
0698         0x8f, 0xaf, 0xb8, 0xac, 0x00, 0x9a, 0x00, 0x89,
0699         0x00, 0xb2,
0700     }, {
0701         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xbc, 0xac,
0702         0xaf, 0xc2, 0xad, 0xc2, 0xcf, 0xc4, 0x94, 0xa3,
0703         0x90, 0xaf, 0xb8, 0xad, 0x00, 0x9c, 0x00, 0x8b,
0704         0x00, 0xb5,
0705     }, {
0706         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
0707         0xb1, 0xc4, 0xaf, 0xc3, 0xcf, 0xc5, 0x94, 0xa3,
0708         0x8f, 0xae, 0xb7, 0xac, 0x00, 0x9f, 0x00, 0x8e,
0709         0x00, 0xb8,
0710     }, {
0711         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
0712         0xaf, 0xc2, 0xad, 0xc1, 0xce, 0xc3, 0x95, 0xa3,
0713         0x90, 0xad, 0xb6, 0xab, 0x00, 0xa2, 0x00, 0x91,
0714         0x00, 0xbb,
0715     }, {
0716         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xbe, 0xac,
0717         0xb1, 0xc4, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa4,
0718         0x91, 0xad, 0xb6, 0xab, 0x00, 0xa4, 0x00, 0x93,
0719         0x00, 0xbd,
0720     }, {
0721         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
0722         0xb3, 0xc5, 0xb2, 0xc1, 0xcd, 0xc2, 0x95, 0xa3,
0723         0x90, 0xad, 0xb6, 0xab, 0x00, 0xa6, 0x00, 0x95,
0724         0x00, 0xc0,
0725     }, {
0726         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
0727         0xb0, 0xc3, 0xaf, 0xc2, 0xce, 0xc2, 0x94, 0xa2,
0728         0x90, 0xac, 0xb6, 0xab, 0x00, 0xa8, 0x00, 0x98,
0729         0x00, 0xc3,
0730     }, {
0731         0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xb8, 0xa5,
0732         0xb3, 0xc5, 0xb2, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
0733         0x90, 0xad, 0xb6, 0xab, 0x00, 0xaa, 0x00, 0x9a,
0734         0x00, 0xc5,
0735     }, {
0736         0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xc0, 0xac,
0737         0xb0, 0xc3, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa2,
0738         0x90, 0xac, 0xb5, 0xa9, 0x00, 0xac, 0x00, 0x9c,
0739         0x00, 0xc8,
0740     }, {
0741         0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbd, 0xa8,
0742         0xaf, 0xc2, 0xaf, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
0743         0x90, 0xac, 0xb5, 0xaa, 0x00, 0xb1, 0x00, 0xa1,
0744         0x00, 0xcc,
0745     },
0746 };
0747 
0748 static const struct s6e8aa0_variant s6e8aa0_variants[] = {
0749     {
0750         .version = 32,
0751         .gamma_tables = s6e8aa0_gamma_tables_v32,
0752     }, {
0753         .version = 96,
0754         .gamma_tables = s6e8aa0_gamma_tables_v96,
0755     }, {
0756         .version = 142,
0757         .gamma_tables = s6e8aa0_gamma_tables_v142,
0758     }, {
0759         .version = 210,
0760         .gamma_tables = s6e8aa0_gamma_tables_v142,
0761     }
0762 };
0763 
0764 static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx)
0765 {
0766     const u8 *gamma;
0767 
0768     if (ctx->error)
0769         return;
0770 
0771     gamma = ctx->variant->gamma_tables[ctx->brightness];
0772 
0773     if (ctx->version >= 142)
0774         s6e8aa0_elvss_nvm_set(ctx);
0775 
0776     s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN);
0777 
0778     /* update gamma table. */
0779     s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03);
0780 }
0781 
0782 static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
0783 {
0784     s6e8aa0_apply_level_1_key(ctx);
0785     s6e8aa0_apply_level_2_key(ctx);
0786     msleep(20);
0787 
0788     s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
0789     msleep(40);
0790 
0791     s6e8aa0_panel_cond_set(ctx);
0792     s6e8aa0_display_condition_set(ctx);
0793     s6e8aa0_brightness_set(ctx);
0794     s6e8aa0_etc_source_control(ctx);
0795     s6e8aa0_etc_pentile_control(ctx);
0796     s6e8aa0_elvss_nvm_set(ctx);
0797     s6e8aa0_etc_power_control(ctx);
0798     s6e8aa0_etc_elvss_control(ctx);
0799     msleep(ctx->init_delay);
0800 }
0801 
0802 static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
0803                            u16 size)
0804 {
0805     struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0806     int ret;
0807 
0808     if (ctx->error < 0)
0809         return;
0810 
0811     ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
0812     if (ret < 0) {
0813         dev_err(ctx->dev,
0814             "error %d setting maximum return packet size to %d\n",
0815             ret, size);
0816         ctx->error = ret;
0817     }
0818 }
0819 
0820 static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
0821 {
0822     u8 id[3];
0823     int ret, i;
0824 
0825     ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
0826     if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) {
0827         dev_err(ctx->dev, "read id failed\n");
0828         ctx->error = -EIO;
0829         return;
0830     }
0831 
0832     dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
0833 
0834     for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
0835         if (id[1] == s6e8aa0_variants[i].version)
0836             break;
0837     }
0838     if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
0839         dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
0840         ctx->error = -EINVAL;
0841         return;
0842     }
0843 
0844     ctx->variant = &s6e8aa0_variants[i];
0845     ctx->version = id[1];
0846     ctx->id = id[2];
0847 }
0848 
0849 static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
0850 {
0851     s6e8aa0_set_maximum_return_packet_size(ctx, 3);
0852     s6e8aa0_read_mtp_id(ctx);
0853     s6e8aa0_panel_init(ctx);
0854     s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
0855 }
0856 
0857 static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
0858 {
0859     int ret;
0860 
0861     ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
0862     if (ret < 0)
0863         return ret;
0864 
0865     msleep(ctx->power_on_delay);
0866 
0867     gpiod_set_value(ctx->reset_gpio, 0);
0868     usleep_range(10000, 11000);
0869     gpiod_set_value(ctx->reset_gpio, 1);
0870 
0871     msleep(ctx->reset_delay);
0872 
0873     return 0;
0874 }
0875 
0876 static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
0877 {
0878     return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
0879 }
0880 
0881 static int s6e8aa0_disable(struct drm_panel *panel)
0882 {
0883     return 0;
0884 }
0885 
0886 static int s6e8aa0_unprepare(struct drm_panel *panel)
0887 {
0888     struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
0889 
0890     s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
0891     s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
0892     msleep(40);
0893 
0894     s6e8aa0_clear_error(ctx);
0895 
0896     return s6e8aa0_power_off(ctx);
0897 }
0898 
0899 static int s6e8aa0_prepare(struct drm_panel *panel)
0900 {
0901     struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
0902     int ret;
0903 
0904     ret = s6e8aa0_power_on(ctx);
0905     if (ret < 0)
0906         return ret;
0907 
0908     s6e8aa0_set_sequence(ctx);
0909     ret = ctx->error;
0910 
0911     if (ret < 0)
0912         s6e8aa0_unprepare(panel);
0913 
0914     return ret;
0915 }
0916 
0917 static int s6e8aa0_enable(struct drm_panel *panel)
0918 {
0919     return 0;
0920 }
0921 
0922 static int s6e8aa0_get_modes(struct drm_panel *panel,
0923                  struct drm_connector *connector)
0924 {
0925     struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
0926     struct drm_display_mode *mode;
0927 
0928     mode = drm_mode_create(connector->dev);
0929     if (!mode) {
0930         dev_err(panel->dev, "failed to create a new display mode\n");
0931         return 0;
0932     }
0933 
0934     drm_display_mode_from_videomode(&ctx->vm, mode);
0935     mode->width_mm = ctx->width_mm;
0936     mode->height_mm = ctx->height_mm;
0937     connector->display_info.width_mm = mode->width_mm;
0938     connector->display_info.height_mm = mode->height_mm;
0939 
0940     mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0941     drm_mode_probed_add(connector, mode);
0942 
0943     return 1;
0944 }
0945 
0946 static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
0947     .disable = s6e8aa0_disable,
0948     .unprepare = s6e8aa0_unprepare,
0949     .prepare = s6e8aa0_prepare,
0950     .enable = s6e8aa0_enable,
0951     .get_modes = s6e8aa0_get_modes,
0952 };
0953 
0954 static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
0955 {
0956     struct device *dev = ctx->dev;
0957     struct device_node *np = dev->of_node;
0958     int ret;
0959 
0960     ret = of_get_videomode(np, &ctx->vm, 0);
0961     if (ret < 0)
0962         return ret;
0963 
0964     of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
0965     of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
0966     of_property_read_u32(np, "init-delay", &ctx->init_delay);
0967     of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
0968     of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
0969 
0970     ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
0971     ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
0972 
0973     return 0;
0974 }
0975 
0976 static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
0977 {
0978     struct device *dev = &dsi->dev;
0979     struct s6e8aa0 *ctx;
0980     int ret;
0981 
0982     ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
0983     if (!ctx)
0984         return -ENOMEM;
0985 
0986     mipi_dsi_set_drvdata(dsi, ctx);
0987 
0988     ctx->dev = dev;
0989 
0990     dsi->lanes = 4;
0991     dsi->format = MIPI_DSI_FMT_RGB888;
0992     dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
0993         | MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP
0994         | MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET
0995         | MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
0996 
0997     ret = s6e8aa0_parse_dt(ctx);
0998     if (ret < 0)
0999         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 
1031 static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
1032 {
1033     struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
1034 
1035     mipi_dsi_detach(dsi);
1036     drm_panel_remove(&ctx->panel);
1037 
1038     return 0;
1039 }
1040 
1041 static const struct of_device_id s6e8aa0_of_match[] = {
1042     { .compatible = "samsung,s6e8aa0" },
1043     { }
1044 };
1045 MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1046 
1047 static struct mipi_dsi_driver s6e8aa0_driver = {
1048     .probe = s6e8aa0_probe,
1049     .remove = s6e8aa0_remove,
1050     .driver = {
1051         .name = "panel-samsung-s6e8aa0",
1052         .of_match_table = s6e8aa0_of_match,
1053     },
1054 };
1055 module_mipi_dsi_driver(s6e8aa0_driver);
1056 
1057 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1058 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1059 MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1060 MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1061 MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1062 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1063 MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1064 MODULE_LICENSE("GPL v2");