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