[go: nahoru, domu]

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