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