Loading...
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
88typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
89
90struct s6e8aa0_variant {
91 u8 version;
92 const s6e8aa0_gamma_table *gamma_tables;
93};
94
95struct 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
124static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
125{
126 return container_of(panel, struct s6e8aa0, panel);
127}
128
129static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
130{
131 int ret = ctx->error;
132
133 ctx->error = 0;
134 return ret;
135}
136
137static 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
153static 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
183static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
184{
185 s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
186}
187
188static 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
259static 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
273static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
274{
275 s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
276}
277
278static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
279{
280 s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
281}
282
283static 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
299static 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
315static 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
322static 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
346static 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
356static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
357{
358 s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
359}
360
361static 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
490static 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
620static 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
749static 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
765static 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
783static 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
803static 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
821static 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
850static 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
858static 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
877static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
878{
879 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
880}
881
882static int s6e8aa0_disable(struct drm_panel *panel)
883{
884 return 0;
885}
886
887static 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
900static 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
918static int s6e8aa0_enable(struct drm_panel *panel)
919{
920 return 0;
921}
922
923static 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
947static 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
955static 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
977static 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
1035static 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
1045static const struct of_device_id s6e8aa0_of_match[] = {
1046 { .compatible = "samsung,s6e8aa0" },
1047 { }
1048};
1049MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1050
1051static 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};
1059module_mipi_dsi_driver(s6e8aa0_driver);
1060
1061MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1062MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1063MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1064MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1065MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1066MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1067MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1068MODULE_LICENSE("GPL v2");
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
87typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
88
89struct s6e8aa0_variant {
90 u8 version;
91 const s6e8aa0_gamma_table *gamma_tables;
92};
93
94struct 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
123static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
124{
125 return container_of(panel, struct s6e8aa0, panel);
126}
127
128static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
129{
130 int ret = ctx->error;
131
132 ctx->error = 0;
133 return ret;
134}
135
136static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
137{
138 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
139 ssize_t ret;
140
141 if (ctx->error < 0)
142 return;
143
144 ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
145 if (ret < 0) {
146 dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
147 (int)len, data);
148 ctx->error = ret;
149 }
150}
151
152static 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
182static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
183{
184 s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
185}
186
187static 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
258static 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
272static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
273{
274 s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
275}
276
277static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
278{
279 s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
280}
281
282static 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
298static 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
314static 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
321static 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
345static 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
355static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
356{
357 s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
358}
359
360static 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
489static 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
619static 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
748static 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
764static 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
782static 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
802static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
803 u16 size)
804{
805 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
806 int ret;
807
808 if (ctx->error < 0)
809 return;
810
811 ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
812 if (ret < 0) {
813 dev_err(ctx->dev,
814 "error %d setting maximum return packet size to %d\n",
815 ret, size);
816 ctx->error = ret;
817 }
818}
819
820static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
821{
822 u8 id[3];
823 int ret, i;
824
825 ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
826 if (ret < ARRAY_SIZE(id) || id[0] == 0x00) {
827 dev_err(ctx->dev, "read id failed\n");
828 ctx->error = -EIO;
829 return;
830 }
831
832 dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
833
834 for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
835 if (id[1] == s6e8aa0_variants[i].version)
836 break;
837 }
838 if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
839 dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
840 ctx->error = -EINVAL;
841 return;
842 }
843
844 ctx->variant = &s6e8aa0_variants[i];
845 ctx->version = id[1];
846 ctx->id = id[2];
847}
848
849static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
850{
851 s6e8aa0_set_maximum_return_packet_size(ctx, 3);
852 s6e8aa0_read_mtp_id(ctx);
853 s6e8aa0_panel_init(ctx);
854 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
855}
856
857static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
858{
859 int ret;
860
861 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
862 if (ret < 0)
863 return ret;
864
865 msleep(ctx->power_on_delay);
866
867 gpiod_set_value(ctx->reset_gpio, 0);
868 usleep_range(10000, 11000);
869 gpiod_set_value(ctx->reset_gpio, 1);
870
871 msleep(ctx->reset_delay);
872
873 return 0;
874}
875
876static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
877{
878 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
879}
880
881static int s6e8aa0_disable(struct drm_panel *panel)
882{
883 return 0;
884}
885
886static int s6e8aa0_unprepare(struct drm_panel *panel)
887{
888 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
889
890 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
891 s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
892 msleep(40);
893
894 s6e8aa0_clear_error(ctx);
895
896 return s6e8aa0_power_off(ctx);
897}
898
899static int s6e8aa0_prepare(struct drm_panel *panel)
900{
901 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
902 int ret;
903
904 ret = s6e8aa0_power_on(ctx);
905 if (ret < 0)
906 return ret;
907
908 s6e8aa0_set_sequence(ctx);
909 ret = ctx->error;
910
911 if (ret < 0)
912 s6e8aa0_unprepare(panel);
913
914 return ret;
915}
916
917static int s6e8aa0_enable(struct drm_panel *panel)
918{
919 return 0;
920}
921
922static int s6e8aa0_get_modes(struct drm_panel *panel)
923{
924 struct drm_connector *connector = panel->connector;
925 struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
926 struct drm_display_mode *mode;
927
928 mode = drm_mode_create(connector->dev);
929 if (!mode) {
930 DRM_ERROR("failed to create a new display mode\n");
931 return 0;
932 }
933
934 drm_display_mode_from_videomode(&ctx->vm, mode);
935 mode->width_mm = ctx->width_mm;
936 mode->height_mm = ctx->height_mm;
937 connector->display_info.width_mm = mode->width_mm;
938 connector->display_info.height_mm = mode->height_mm;
939
940 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
941 drm_mode_probed_add(connector, mode);
942
943 return 1;
944}
945
946static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
947 .disable = s6e8aa0_disable,
948 .unprepare = s6e8aa0_unprepare,
949 .prepare = s6e8aa0_prepare,
950 .enable = s6e8aa0_enable,
951 .get_modes = s6e8aa0_get_modes,
952};
953
954static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
955{
956 struct device *dev = ctx->dev;
957 struct device_node *np = dev->of_node;
958 int ret;
959
960 ret = of_get_videomode(np, &ctx->vm, 0);
961 if (ret < 0)
962 return ret;
963
964 of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
965 of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
966 of_property_read_u32(np, "init-delay", &ctx->init_delay);
967 of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
968 of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
969
970 ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
971 ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
972
973 return 0;
974}
975
976static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
977{
978 struct device *dev = &dsi->dev;
979 struct s6e8aa0 *ctx;
980 int ret;
981
982 ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
983 if (!ctx)
984 return -ENOMEM;
985
986 mipi_dsi_set_drvdata(dsi, ctx);
987
988 ctx->dev = dev;
989
990 dsi->lanes = 4;
991 dsi->format = MIPI_DSI_FMT_RGB888;
992 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
993 | MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
994 | MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
995 | MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
996
997 ret = s6e8aa0_parse_dt(ctx);
998 if (ret < 0)
999 return ret;
1000
1001 ctx->supplies[0].supply = "vdd3";
1002 ctx->supplies[1].supply = "vci";
1003 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
1004 ctx->supplies);
1005 if (ret < 0) {
1006 dev_err(dev, "failed to get regulators: %d\n", ret);
1007 return ret;
1008 }
1009
1010 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
1011 if (IS_ERR(ctx->reset_gpio)) {
1012 dev_err(dev, "cannot get reset-gpios %ld\n",
1013 PTR_ERR(ctx->reset_gpio));
1014 return PTR_ERR(ctx->reset_gpio);
1015 }
1016
1017 ctx->brightness = GAMMA_LEVEL_NUM - 1;
1018
1019 drm_panel_init(&ctx->panel);
1020 ctx->panel.dev = dev;
1021 ctx->panel.funcs = &s6e8aa0_drm_funcs;
1022
1023 ret = drm_panel_add(&ctx->panel);
1024 if (ret < 0)
1025 return ret;
1026
1027 ret = mipi_dsi_attach(dsi);
1028 if (ret < 0)
1029 drm_panel_remove(&ctx->panel);
1030
1031 return ret;
1032}
1033
1034static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
1035{
1036 struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
1037
1038 mipi_dsi_detach(dsi);
1039 drm_panel_remove(&ctx->panel);
1040
1041 return 0;
1042}
1043
1044static const struct of_device_id s6e8aa0_of_match[] = {
1045 { .compatible = "samsung,s6e8aa0" },
1046 { }
1047};
1048MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1049
1050static struct mipi_dsi_driver s6e8aa0_driver = {
1051 .probe = s6e8aa0_probe,
1052 .remove = s6e8aa0_remove,
1053 .driver = {
1054 .name = "panel-samsung-s6e8aa0",
1055 .of_match_table = s6e8aa0_of_match,
1056 },
1057};
1058module_mipi_dsi_driver(s6e8aa0_driver);
1059
1060MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1061MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1062MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1063MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1064MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1065MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1066MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1067MODULE_LICENSE("GPL v2");