0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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
0115
0116
0117
0118
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
0203 cfg &= ~(PANELCTL_GTCON_MASK);
0204 cfg |= (PANELCTL_GTCON_110);
0205 }
0206
0207 if (ctx->flip_horizontal) {
0208
0209 cfg &= ~(PANELCTL_SS_MASK);
0210 cfg |= (PANELCTL_SS_1_800);
0211 }
0212
0213 if (ctx->flip_horizontal || ctx->flip_vertical) {
0214
0215 clk_con &= ~(PANELCTL_CLK1_CON_MASK |
0216 PANELCTL_CLK2_CON_MASK);
0217 clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001);
0218
0219
0220 int_con &= ~(PANELCTL_INT1_CON_MASK |
0221 PANELCTL_INT2_CON_MASK);
0222 int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001);
0223
0224
0225 bictl_con &= ~(PANELCTL_BICTL_CON_MASK |
0226 PANELCTL_BICTLB_CON_MASK);
0227 bictl_con |= (PANELCTL_BICTL_000 |
0228 PANELCTL_BICTLB_001);
0229
0230
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
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
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:
0327 br = 0xdf;
0328 break;
0329 case 7 ... 11:
0330 br = 0xdd;
0331 break;
0332 case 12 ... 15:
0333 default:
0334 br = 0xd9;
0335 break;
0336 case 16 ... 24:
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
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");