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