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