1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ed29f942SHoegeun Kwon /*
3ed29f942SHoegeun Kwon  * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
4ed29f942SHoegeun Kwon  *
5ed29f942SHoegeun Kwon  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6ed29f942SHoegeun Kwon  * Donghwa Lee <dh09.lee@samsung.com>
7ed29f942SHoegeun Kwon  * Hyungwon Hwang <human.hwang@samsung.com>
8ed29f942SHoegeun Kwon  * Hoegeun Kwon <hoegeun.kwon@samsung.com>
9ed29f942SHoegeun Kwon  */
10ed29f942SHoegeun Kwon 
11ed29f942SHoegeun Kwon #include <linux/backlight.h>
12cb23eae3SSam Ravnborg #include <linux/delay.h>
13ed29f942SHoegeun Kwon #include <linux/gpio/consumer.h>
14cb23eae3SSam Ravnborg #include <linux/module.h>
15*722d4f06SRob Herring #include <linux/of.h>
16ed29f942SHoegeun Kwon #include <linux/regulator/consumer.h>
17ed29f942SHoegeun Kwon 
18cb23eae3SSam Ravnborg #include <drm/drm_mipi_dsi.h>
19cb23eae3SSam Ravnborg #include <drm/drm_modes.h>
20cb23eae3SSam Ravnborg #include <drm/drm_panel.h>
21cb23eae3SSam Ravnborg 
22ed29f942SHoegeun Kwon #define S6E3HA2_MIN_BRIGHTNESS		0
23ed29f942SHoegeun Kwon #define S6E3HA2_MAX_BRIGHTNESS		100
24ed29f942SHoegeun Kwon #define S6E3HA2_DEFAULT_BRIGHTNESS	80
25ed29f942SHoegeun Kwon 
26ed29f942SHoegeun Kwon #define S6E3HA2_NUM_GAMMA_STEPS		46
27ed29f942SHoegeun Kwon #define S6E3HA2_GAMMA_CMD_CNT		35
28ed29f942SHoegeun Kwon #define S6E3HA2_VINT_STATUS_MAX		10
29ed29f942SHoegeun Kwon 
30ed29f942SHoegeun Kwon static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = {
31ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83,
32ed29f942SHoegeun Kwon 	  0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c,
33ed29f942SHoegeun Kwon 	  0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00,
34ed29f942SHoegeun Kwon 	  0x00, 0x00 },
35ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84,
36ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a,
37ed29f942SHoegeun Kwon 	  0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00,
38ed29f942SHoegeun Kwon 	  0x00, 0x00 },
39ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
40ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a,
41ed29f942SHoegeun Kwon 	  0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00,
42ed29f942SHoegeun Kwon 	  0x00, 0x00 },
43ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
44ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a,
45ed29f942SHoegeun Kwon 	  0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00,
46ed29f942SHoegeun Kwon 	  0x00, 0x00 },
47ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85,
48ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b,
49ed29f942SHoegeun Kwon 	  0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00,
50ed29f942SHoegeun Kwon 	  0x00, 0x00 },
51ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
52ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b,
53ed29f942SHoegeun Kwon 	  0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00,
54ed29f942SHoegeun Kwon 	  0x00, 0x00 },
55ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
56ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89,
57ed29f942SHoegeun Kwon 	  0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00,
58ed29f942SHoegeun Kwon 	  0x00, 0x00 },
59ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
60ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c,
61ed29f942SHoegeun Kwon 	  0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
62ed29f942SHoegeun Kwon 	  0x00, 0x00 },
63ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
64ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88,
65ed29f942SHoegeun Kwon 	  0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
66ed29f942SHoegeun Kwon 	  0x00, 0x00 },
67ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
68ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a,
69ed29f942SHoegeun Kwon 	  0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00,
70ed29f942SHoegeun Kwon 	  0x00, 0x00 },
71ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
72ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b,
73ed29f942SHoegeun Kwon 	  0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00,
74ed29f942SHoegeun Kwon 	  0x00, 0x00 },
75ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
76ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c,
77ed29f942SHoegeun Kwon 	  0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00,
78ed29f942SHoegeun Kwon 	  0x00, 0x00 },
79ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
80ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c,
81ed29f942SHoegeun Kwon 	  0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00,
82ed29f942SHoegeun Kwon 	  0x00, 0x00 },
83ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
84ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
85ed29f942SHoegeun Kwon 	  0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00,
86ed29f942SHoegeun Kwon 	  0x00, 0x00 },
87ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
88ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
89ed29f942SHoegeun Kwon 	  0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00,
90ed29f942SHoegeun Kwon 	  0x00, 0x00 },
91ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
92ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b,
93ed29f942SHoegeun Kwon 	  0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
94ed29f942SHoegeun Kwon 	  0x00, 0x00 },
95ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
96ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e,
97ed29f942SHoegeun Kwon 	  0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
98ed29f942SHoegeun Kwon 	  0x00, 0x00 },
99ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
100ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e,
101ed29f942SHoegeun Kwon 	  0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00,
102ed29f942SHoegeun Kwon 	  0x00, 0x00 },
103ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
104ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d,
105ed29f942SHoegeun Kwon 	  0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
106ed29f942SHoegeun Kwon 	  0x00, 0x00 },
107ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
108ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c,
109ed29f942SHoegeun Kwon 	  0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
110ed29f942SHoegeun Kwon 	  0x00, 0x00 },
111ed29f942SHoegeun Kwon 	{ 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83,
112ed29f942SHoegeun Kwon 	  0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a,
113ed29f942SHoegeun Kwon 	  0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
114ed29f942SHoegeun Kwon 	  0x00, 0x00 },
115ed29f942SHoegeun Kwon 	{ 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83,
116ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a,
117ed29f942SHoegeun Kwon 	  0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
118ed29f942SHoegeun Kwon 	  0x00, 0x00 },
119ed29f942SHoegeun Kwon 	{ 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83,
120ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89,
121ed29f942SHoegeun Kwon 	  0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
122ed29f942SHoegeun Kwon 	  0x00, 0x00 },
123ed29f942SHoegeun Kwon 	{ 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83,
124ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a,
125ed29f942SHoegeun Kwon 	  0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00,
126ed29f942SHoegeun Kwon 	  0x00, 0x00 },
127ed29f942SHoegeun Kwon 	{ 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82,
128ed29f942SHoegeun Kwon 	  0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87,
129ed29f942SHoegeun Kwon 	  0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
130ed29f942SHoegeun Kwon 	  0x00, 0x00 },
131ed29f942SHoegeun Kwon 	{ 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82,
132ed29f942SHoegeun Kwon 	  0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88,
133ed29f942SHoegeun Kwon 	  0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
134ed29f942SHoegeun Kwon 	  0x00, 0x00 },
135ed29f942SHoegeun Kwon 	{ 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83,
136ed29f942SHoegeun Kwon 	  0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89,
137ed29f942SHoegeun Kwon 	  0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
138ed29f942SHoegeun Kwon 	  0x00, 0x00 },
139ed29f942SHoegeun Kwon 	{ 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82,
140ed29f942SHoegeun Kwon 	  0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86,
141ed29f942SHoegeun Kwon 	  0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
142ed29f942SHoegeun Kwon 	  0x00, 0x00 },
143ed29f942SHoegeun Kwon 	{ 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82,
144ed29f942SHoegeun Kwon 	  0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87,
145ed29f942SHoegeun Kwon 	  0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00,
146ed29f942SHoegeun Kwon 	  0x00, 0x00 },
147ed29f942SHoegeun Kwon 	{ 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81,
148ed29f942SHoegeun Kwon 	  0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86,
149ed29f942SHoegeun Kwon 	  0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
150ed29f942SHoegeun Kwon 	  0x00, 0x00 },
151ed29f942SHoegeun Kwon 	{ 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82,
152ed29f942SHoegeun Kwon 	  0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83,
153ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00,
154ed29f942SHoegeun Kwon 	  0x00, 0x00 },
155ed29f942SHoegeun Kwon 	{ 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82,
156ed29f942SHoegeun Kwon 	  0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82,
157ed29f942SHoegeun Kwon 	  0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
158ed29f942SHoegeun Kwon 	  0x00, 0x00 },
159ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
160ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80,
161ed29f942SHoegeun Kwon 	  0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
162ed29f942SHoegeun Kwon 	  0x00, 0x00 },
163ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81,
164ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
165ed29f942SHoegeun Kwon 	  0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
166ed29f942SHoegeun Kwon 	  0x00, 0x00 },
167ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
168ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
169ed29f942SHoegeun Kwon 	  0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
170ed29f942SHoegeun Kwon 	  0x00, 0x00 },
171ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
172ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82,
173ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
174ed29f942SHoegeun Kwon 	  0x00, 0x00 },
175ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
176ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83,
177ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
178ed29f942SHoegeun Kwon 	  0x00, 0x00 },
179ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
180ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83,
181ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
182ed29f942SHoegeun Kwon 	  0x00, 0x00 },
183ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80,
184ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81,
185ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00,
186ed29f942SHoegeun Kwon 	  0x00, 0x00 },
187ed29f942SHoegeun Kwon 	{ 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81,
188ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83,
189ed29f942SHoegeun Kwon 	  0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00,
190ed29f942SHoegeun Kwon 	  0x00, 0x00 },
191ed29f942SHoegeun Kwon 	{ 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80,
192ed29f942SHoegeun Kwon 	  0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80,
193ed29f942SHoegeun Kwon 	  0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
194ed29f942SHoegeun Kwon 	  0x00, 0x00 },
195ed29f942SHoegeun Kwon 	{ 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80,
196ed29f942SHoegeun Kwon 	  0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d,
197ed29f942SHoegeun Kwon 	  0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
198ed29f942SHoegeun Kwon 	  0x00, 0x00 },
199ed29f942SHoegeun Kwon 	{ 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80,
200ed29f942SHoegeun Kwon 	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82,
201ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
202ed29f942SHoegeun Kwon 	  0x00, 0x00 },
203ed29f942SHoegeun Kwon 	{ 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80,
204ed29f942SHoegeun Kwon 	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
205ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
206ed29f942SHoegeun Kwon 	  0x00, 0x00 },
207ed29f942SHoegeun Kwon 	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
208ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
209ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
210ed29f942SHoegeun Kwon 	  0x00, 0x00 },
211ed29f942SHoegeun Kwon 	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
212ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
213ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
214ed29f942SHoegeun Kwon 	  0x00, 0x00 }
215ed29f942SHoegeun Kwon };
216ed29f942SHoegeun Kwon 
217d7b1c018SJason Yan static const unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = {
218ed29f942SHoegeun Kwon 	0x18, 0x19, 0x1a, 0x1b, 0x1c,
219ed29f942SHoegeun Kwon 	0x1d, 0x1e, 0x1f, 0x20, 0x21
220ed29f942SHoegeun Kwon };
221ed29f942SHoegeun Kwon 
222e2af12bfSHoegeun Kwon enum s6e3ha2_type {
223e2af12bfSHoegeun Kwon 	HA2_TYPE,
224e2af12bfSHoegeun Kwon 	HF2_TYPE,
225e2af12bfSHoegeun Kwon };
226e2af12bfSHoegeun Kwon 
227e2af12bfSHoegeun Kwon struct s6e3ha2_panel_desc {
228e2af12bfSHoegeun Kwon 	const struct drm_display_mode *mode;
229e2af12bfSHoegeun Kwon 	enum s6e3ha2_type type;
230e2af12bfSHoegeun Kwon };
231e2af12bfSHoegeun Kwon 
232ed29f942SHoegeun Kwon struct s6e3ha2 {
233ed29f942SHoegeun Kwon 	struct device *dev;
234ed29f942SHoegeun Kwon 	struct drm_panel panel;
235ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev;
236ed29f942SHoegeun Kwon 
237ed29f942SHoegeun Kwon 	struct regulator_bulk_data supplies[2];
238ed29f942SHoegeun Kwon 	struct gpio_desc *reset_gpio;
239ed29f942SHoegeun Kwon 	struct gpio_desc *enable_gpio;
240e2af12bfSHoegeun Kwon 
241e2af12bfSHoegeun Kwon 	const struct s6e3ha2_panel_desc *desc;
242ed29f942SHoegeun Kwon };
243ed29f942SHoegeun Kwon 
s6e3ha2_dcs_write(struct s6e3ha2 * ctx,const void * data,size_t len)244ed29f942SHoegeun Kwon static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)
245ed29f942SHoegeun Kwon {
246ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
247ed29f942SHoegeun Kwon 
248ed29f942SHoegeun Kwon 	return mipi_dsi_dcs_write_buffer(dsi, data, len);
249ed29f942SHoegeun Kwon }
250ed29f942SHoegeun Kwon 
251ed29f942SHoegeun Kwon #define s6e3ha2_dcs_write_seq_static(ctx, seq...) do {	\
252ed29f942SHoegeun Kwon 	static const u8 d[] = { seq };			\
253ed29f942SHoegeun Kwon 	int ret;					\
254ed29f942SHoegeun Kwon 	ret = s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d));	\
255ed29f942SHoegeun Kwon 	if (ret < 0)					\
256ed29f942SHoegeun Kwon 		return ret;				\
257ed29f942SHoegeun Kwon } while (0)
258ed29f942SHoegeun Kwon 
259ed29f942SHoegeun Kwon #define s6e3ha2_call_write_func(ret, func) do {	\
260ed29f942SHoegeun Kwon 	ret = (func);				\
261ed29f942SHoegeun Kwon 	if (ret < 0)				\
262ed29f942SHoegeun Kwon 		return ret;			\
263ed29f942SHoegeun Kwon } while (0)
264ed29f942SHoegeun Kwon 
s6e3ha2_test_key_on_f0(struct s6e3ha2 * ctx)265ed29f942SHoegeun Kwon static int s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx)
266ed29f942SHoegeun Kwon {
267ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
268ed29f942SHoegeun Kwon 	return 0;
269ed29f942SHoegeun Kwon }
270ed29f942SHoegeun Kwon 
s6e3ha2_test_key_off_f0(struct s6e3ha2 * ctx)271ed29f942SHoegeun Kwon static int s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx)
272ed29f942SHoegeun Kwon {
273ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5);
274ed29f942SHoegeun Kwon 	return 0;
275ed29f942SHoegeun Kwon }
276ed29f942SHoegeun Kwon 
s6e3ha2_test_key_on_fc(struct s6e3ha2 * ctx)277ed29f942SHoegeun Kwon static int s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx)
278ed29f942SHoegeun Kwon {
279ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
280ed29f942SHoegeun Kwon 	return 0;
281ed29f942SHoegeun Kwon }
282ed29f942SHoegeun Kwon 
s6e3ha2_test_key_off_fc(struct s6e3ha2 * ctx)283ed29f942SHoegeun Kwon static int s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx)
284ed29f942SHoegeun Kwon {
285ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5);
286ed29f942SHoegeun Kwon 	return 0;
287ed29f942SHoegeun Kwon }
288ed29f942SHoegeun Kwon 
s6e3ha2_single_dsi_set(struct s6e3ha2 * ctx)289ed29f942SHoegeun Kwon static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx)
290ed29f942SHoegeun Kwon {
291ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67);
292ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09);
293ed29f942SHoegeun Kwon 	return 0;
294ed29f942SHoegeun Kwon }
295ed29f942SHoegeun Kwon 
s6e3ha2_freq_calibration(struct s6e3ha2 * ctx)296ed29f942SHoegeun Kwon static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
297ed29f942SHoegeun Kwon {
298ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
299e2af12bfSHoegeun Kwon 	if (ctx->desc->type == HF2_TYPE)
300e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67, 0x40, 0xc5);
301ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
302ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
303ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
304e2af12bfSHoegeun Kwon 
305e2af12bfSHoegeun Kwon 	if (ctx->desc->type == HA2_TYPE)
306e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
307e2af12bfSHoegeun Kwon 						  0x40, 0x80, 0xc0, 0x28, 0x28,
308e2af12bfSHoegeun Kwon 						  0x28, 0x28, 0x39, 0xc5);
309e2af12bfSHoegeun Kwon 	else
310e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x14, 0x6d,
311e2af12bfSHoegeun Kwon 						  0x40, 0x80, 0xc0, 0x28, 0x28,
312e2af12bfSHoegeun Kwon 						  0x28, 0x28, 0x39, 0xc5);
313e2af12bfSHoegeun Kwon 
314ed29f942SHoegeun Kwon 	return 0;
315ed29f942SHoegeun Kwon }
316ed29f942SHoegeun Kwon 
s6e3ha2_aor_control(struct s6e3ha2 * ctx)317ed29f942SHoegeun Kwon static int s6e3ha2_aor_control(struct s6e3ha2 *ctx)
318ed29f942SHoegeun Kwon {
319ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10);
320ed29f942SHoegeun Kwon 	return 0;
321ed29f942SHoegeun Kwon }
322ed29f942SHoegeun Kwon 
s6e3ha2_caps_elvss_set(struct s6e3ha2 * ctx)323ed29f942SHoegeun Kwon static int s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx)
324ed29f942SHoegeun Kwon {
325ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a);
326ed29f942SHoegeun Kwon 	return 0;
327ed29f942SHoegeun Kwon }
328ed29f942SHoegeun Kwon 
s6e3ha2_acl_off(struct s6e3ha2 * ctx)329ed29f942SHoegeun Kwon static int s6e3ha2_acl_off(struct s6e3ha2 *ctx)
330ed29f942SHoegeun Kwon {
331ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00);
332ed29f942SHoegeun Kwon 	return 0;
333ed29f942SHoegeun Kwon }
334ed29f942SHoegeun Kwon 
s6e3ha2_acl_off_opr(struct s6e3ha2 * ctx)335ed29f942SHoegeun Kwon static int s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx)
336ed29f942SHoegeun Kwon {
337ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40);
338ed29f942SHoegeun Kwon 	return 0;
339ed29f942SHoegeun Kwon }
340ed29f942SHoegeun Kwon 
s6e3ha2_test_global(struct s6e3ha2 * ctx)341ed29f942SHoegeun Kwon static int s6e3ha2_test_global(struct s6e3ha2 *ctx)
342ed29f942SHoegeun Kwon {
343ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07);
344ed29f942SHoegeun Kwon 	return 0;
345ed29f942SHoegeun Kwon }
346ed29f942SHoegeun Kwon 
s6e3ha2_test(struct s6e3ha2 * ctx)347ed29f942SHoegeun Kwon static int s6e3ha2_test(struct s6e3ha2 *ctx)
348ed29f942SHoegeun Kwon {
349ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19);
350ed29f942SHoegeun Kwon 	return 0;
351ed29f942SHoegeun Kwon }
352ed29f942SHoegeun Kwon 
s6e3ha2_touch_hsync_on1(struct s6e3ha2 * ctx)353ed29f942SHoegeun Kwon static int s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx)
354ed29f942SHoegeun Kwon {
355ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xbd, 0x33, 0x11, 0x02,
356ed29f942SHoegeun Kwon 					0x16, 0x02, 0x16);
357ed29f942SHoegeun Kwon 	return 0;
358ed29f942SHoegeun Kwon }
359ed29f942SHoegeun Kwon 
s6e3ha2_pentile_control(struct s6e3ha2 * ctx)360ed29f942SHoegeun Kwon static int s6e3ha2_pentile_control(struct s6e3ha2 *ctx)
361ed29f942SHoegeun Kwon {
362ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8);
363ed29f942SHoegeun Kwon 	return 0;
364ed29f942SHoegeun Kwon }
365ed29f942SHoegeun Kwon 
s6e3ha2_poc_global(struct s6e3ha2 * ctx)366ed29f942SHoegeun Kwon static int s6e3ha2_poc_global(struct s6e3ha2 *ctx)
367ed29f942SHoegeun Kwon {
368ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20);
369ed29f942SHoegeun Kwon 	return 0;
370ed29f942SHoegeun Kwon }
371ed29f942SHoegeun Kwon 
s6e3ha2_poc_setting(struct s6e3ha2 * ctx)372ed29f942SHoegeun Kwon static int s6e3ha2_poc_setting(struct s6e3ha2 *ctx)
373ed29f942SHoegeun Kwon {
374ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08);
375ed29f942SHoegeun Kwon 	return 0;
376ed29f942SHoegeun Kwon }
377ed29f942SHoegeun Kwon 
s6e3ha2_pcd_set_off(struct s6e3ha2 * ctx)378ed29f942SHoegeun Kwon static int s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx)
379ed29f942SHoegeun Kwon {
380ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51);
381ed29f942SHoegeun Kwon 	return 0;
382ed29f942SHoegeun Kwon }
383ed29f942SHoegeun Kwon 
s6e3ha2_err_fg_set(struct s6e3ha2 * ctx)384ed29f942SHoegeun Kwon static int s6e3ha2_err_fg_set(struct s6e3ha2 *ctx)
385ed29f942SHoegeun Kwon {
386ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44);
387ed29f942SHoegeun Kwon 	return 0;
388ed29f942SHoegeun Kwon }
389ed29f942SHoegeun Kwon 
s6e3ha2_hbm_off(struct s6e3ha2 * ctx)390ed29f942SHoegeun Kwon static int s6e3ha2_hbm_off(struct s6e3ha2 *ctx)
391ed29f942SHoegeun Kwon {
392ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00);
393ed29f942SHoegeun Kwon 	return 0;
394ed29f942SHoegeun Kwon }
395ed29f942SHoegeun Kwon 
s6e3ha2_te_start_setting(struct s6e3ha2 * ctx)396ed29f942SHoegeun Kwon static int s6e3ha2_te_start_setting(struct s6e3ha2 *ctx)
397ed29f942SHoegeun Kwon {
398ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
399ed29f942SHoegeun Kwon 	return 0;
400ed29f942SHoegeun Kwon }
401ed29f942SHoegeun Kwon 
s6e3ha2_gamma_update(struct s6e3ha2 * ctx)402ed29f942SHoegeun Kwon static int s6e3ha2_gamma_update(struct s6e3ha2 *ctx)
403ed29f942SHoegeun Kwon {
404ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03);
405ed29f942SHoegeun Kwon 	ndelay(100); /* need for 100ns delay */
406ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00);
407ed29f942SHoegeun Kwon 	return 0;
408ed29f942SHoegeun Kwon }
409ed29f942SHoegeun Kwon 
s6e3ha2_get_brightness(struct backlight_device * bl_dev)410ed29f942SHoegeun Kwon static int s6e3ha2_get_brightness(struct backlight_device *bl_dev)
411ed29f942SHoegeun Kwon {
412ed29f942SHoegeun Kwon 	return bl_dev->props.brightness;
413ed29f942SHoegeun Kwon }
414ed29f942SHoegeun Kwon 
s6e3ha2_set_vint(struct s6e3ha2 * ctx)415ed29f942SHoegeun Kwon static int s6e3ha2_set_vint(struct s6e3ha2 *ctx)
416ed29f942SHoegeun Kwon {
417ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev = ctx->bl_dev;
418ed29f942SHoegeun Kwon 	unsigned int brightness = bl_dev->props.brightness;
419ed29f942SHoegeun Kwon 	unsigned char data[] = { 0xf4, 0x8b,
420ed29f942SHoegeun Kwon 			vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) /
421ed29f942SHoegeun Kwon 			S6E3HA2_MAX_BRIGHTNESS] };
422ed29f942SHoegeun Kwon 
423ed29f942SHoegeun Kwon 	return s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data));
424ed29f942SHoegeun Kwon }
425ed29f942SHoegeun Kwon 
s6e3ha2_get_brightness_index(unsigned int brightness)426ed29f942SHoegeun Kwon static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness)
427ed29f942SHoegeun Kwon {
428ed29f942SHoegeun Kwon 	return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) /
429ed29f942SHoegeun Kwon 		S6E3HA2_MAX_BRIGHTNESS;
430ed29f942SHoegeun Kwon }
431ed29f942SHoegeun Kwon 
s6e3ha2_update_gamma(struct s6e3ha2 * ctx,unsigned int brightness)432ed29f942SHoegeun Kwon static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness)
433ed29f942SHoegeun Kwon {
434ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev = ctx->bl_dev;
435ed29f942SHoegeun Kwon 	unsigned int index = s6e3ha2_get_brightness_index(brightness);
436ed29f942SHoegeun Kwon 	u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, };
437ed29f942SHoegeun Kwon 	int ret;
438ed29f942SHoegeun Kwon 
439ed29f942SHoegeun Kwon 	memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT);
440ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret,
441ed29f942SHoegeun Kwon 				s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)));
442ed29f942SHoegeun Kwon 
443ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
444ed29f942SHoegeun Kwon 	bl_dev->props.brightness = brightness;
445ed29f942SHoegeun Kwon 
446ed29f942SHoegeun Kwon 	return 0;
447ed29f942SHoegeun Kwon }
448ed29f942SHoegeun Kwon 
s6e3ha2_set_brightness(struct backlight_device * bl_dev)449ed29f942SHoegeun Kwon static int s6e3ha2_set_brightness(struct backlight_device *bl_dev)
450ed29f942SHoegeun Kwon {
451ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = bl_get_data(bl_dev);
452ed29f942SHoegeun Kwon 	unsigned int brightness = bl_dev->props.brightness;
453ed29f942SHoegeun Kwon 	int ret;
454ed29f942SHoegeun Kwon 
455ed29f942SHoegeun Kwon 	if (brightness < S6E3HA2_MIN_BRIGHTNESS ||
456ed29f942SHoegeun Kwon 		brightness > bl_dev->props.max_brightness) {
457ed29f942SHoegeun Kwon 		dev_err(ctx->dev, "Invalid brightness: %u\n", brightness);
458ed29f942SHoegeun Kwon 		return -EINVAL;
459ed29f942SHoegeun Kwon 	}
460ed29f942SHoegeun Kwon 
461ed29f942SHoegeun Kwon 	if (bl_dev->props.power > FB_BLANK_NORMAL)
462ed29f942SHoegeun Kwon 		return -EPERM;
463ed29f942SHoegeun Kwon 
464ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
465ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_update_gamma(ctx, brightness));
466ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
467ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_set_vint(ctx));
468ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
469ed29f942SHoegeun Kwon 
470ed29f942SHoegeun Kwon 	return 0;
471ed29f942SHoegeun Kwon }
472ed29f942SHoegeun Kwon 
473ed29f942SHoegeun Kwon static const struct backlight_ops s6e3ha2_bl_ops = {
474ed29f942SHoegeun Kwon 	.get_brightness = s6e3ha2_get_brightness,
475ed29f942SHoegeun Kwon 	.update_status = s6e3ha2_set_brightness,
476ed29f942SHoegeun Kwon };
477ed29f942SHoegeun Kwon 
s6e3ha2_panel_init(struct s6e3ha2 * ctx)478ed29f942SHoegeun Kwon static int s6e3ha2_panel_init(struct s6e3ha2 *ctx)
479ed29f942SHoegeun Kwon {
480ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
481ed29f942SHoegeun Kwon 	int ret;
482ed29f942SHoegeun Kwon 
483ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_exit_sleep_mode(dsi));
484ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
485ed29f942SHoegeun Kwon 
486ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
487ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_single_dsi_set(ctx));
488ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
489ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_freq_calibration(ctx));
490ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
491ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
492ed29f942SHoegeun Kwon 
493ed29f942SHoegeun Kwon 	return 0;
494ed29f942SHoegeun Kwon }
495ed29f942SHoegeun Kwon 
s6e3ha2_power_off(struct s6e3ha2 * ctx)496ed29f942SHoegeun Kwon static int s6e3ha2_power_off(struct s6e3ha2 *ctx)
497ed29f942SHoegeun Kwon {
498ed29f942SHoegeun Kwon 	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
499ed29f942SHoegeun Kwon }
500ed29f942SHoegeun Kwon 
s6e3ha2_disable(struct drm_panel * panel)501ed29f942SHoegeun Kwon static int s6e3ha2_disable(struct drm_panel *panel)
502ed29f942SHoegeun Kwon {
503ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
504ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
505ed29f942SHoegeun Kwon 	int ret;
506ed29f942SHoegeun Kwon 
507ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_enter_sleep_mode(dsi));
508ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_off(dsi));
509ed29f942SHoegeun Kwon 
510ed29f942SHoegeun Kwon 	msleep(40);
511ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
512ed29f942SHoegeun Kwon 
513ed29f942SHoegeun Kwon 	return 0;
514ed29f942SHoegeun Kwon }
515ed29f942SHoegeun Kwon 
s6e3ha2_unprepare(struct drm_panel * panel)516ed29f942SHoegeun Kwon static int s6e3ha2_unprepare(struct drm_panel *panel)
517ed29f942SHoegeun Kwon {
518ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
519ed29f942SHoegeun Kwon 
520ed29f942SHoegeun Kwon 	return s6e3ha2_power_off(ctx);
521ed29f942SHoegeun Kwon }
522ed29f942SHoegeun Kwon 
s6e3ha2_power_on(struct s6e3ha2 * ctx)523ed29f942SHoegeun Kwon static int s6e3ha2_power_on(struct s6e3ha2 *ctx)
524ed29f942SHoegeun Kwon {
525ed29f942SHoegeun Kwon 	int ret;
526ed29f942SHoegeun Kwon 
527ed29f942SHoegeun Kwon 	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
528ed29f942SHoegeun Kwon 	if (ret < 0)
529ed29f942SHoegeun Kwon 		return ret;
530ed29f942SHoegeun Kwon 
531ed29f942SHoegeun Kwon 	msleep(120);
532ed29f942SHoegeun Kwon 
533ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->enable_gpio, 0);
534ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
535ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->enable_gpio, 1);
536ed29f942SHoegeun Kwon 
537ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->reset_gpio, 1);
538ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
539ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->reset_gpio, 0);
540ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
541ed29f942SHoegeun Kwon 
542ed29f942SHoegeun Kwon 	return 0;
543ed29f942SHoegeun Kwon }
s6e3ha2_prepare(struct drm_panel * panel)544ed29f942SHoegeun Kwon static int s6e3ha2_prepare(struct drm_panel *panel)
545ed29f942SHoegeun Kwon {
546ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
547ed29f942SHoegeun Kwon 	int ret;
548ed29f942SHoegeun Kwon 
549ed29f942SHoegeun Kwon 	ret = s6e3ha2_power_on(ctx);
550ed29f942SHoegeun Kwon 	if (ret < 0)
551ed29f942SHoegeun Kwon 		return ret;
552ed29f942SHoegeun Kwon 
553ed29f942SHoegeun Kwon 	ret = s6e3ha2_panel_init(ctx);
554ed29f942SHoegeun Kwon 	if (ret < 0)
555ed29f942SHoegeun Kwon 		goto err;
556ed29f942SHoegeun Kwon 
557ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
558ed29f942SHoegeun Kwon 
559ed29f942SHoegeun Kwon 	return 0;
560ed29f942SHoegeun Kwon 
561ed29f942SHoegeun Kwon err:
562ed29f942SHoegeun Kwon 	s6e3ha2_power_off(ctx);
563ed29f942SHoegeun Kwon 	return ret;
564ed29f942SHoegeun Kwon }
565ed29f942SHoegeun Kwon 
s6e3ha2_enable(struct drm_panel * panel)566ed29f942SHoegeun Kwon static int s6e3ha2_enable(struct drm_panel *panel)
567ed29f942SHoegeun Kwon {
568ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
569ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
570ed29f942SHoegeun Kwon 	int ret;
571ed29f942SHoegeun Kwon 
572ed29f942SHoegeun Kwon 	/* common setting */
573ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret,
574ed29f942SHoegeun Kwon 		mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK));
575ed29f942SHoegeun Kwon 
576ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
577ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
578ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_touch_hsync_on1(ctx));
579ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_pentile_control(ctx));
580ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_poc_global(ctx));
581ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_poc_setting(ctx));
582ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
583ed29f942SHoegeun Kwon 
584ed29f942SHoegeun Kwon 	/* pcd setting off for TB */
585ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_pcd_set_off(ctx));
586ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_err_fg_set(ctx));
587ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_te_start_setting(ctx));
588ed29f942SHoegeun Kwon 
589ed29f942SHoegeun Kwon 	/* brightness setting */
590ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_set_brightness(ctx->bl_dev));
591ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
592ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_caps_elvss_set(ctx));
593ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
594ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off(ctx));
595ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off_opr(ctx));
596ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_hbm_off(ctx));
597ed29f942SHoegeun Kwon 
598ed29f942SHoegeun Kwon 	/* elvss temp compensation */
599ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_global(ctx));
600ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test(ctx));
601ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
602ed29f942SHoegeun Kwon 
603ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_on(dsi));
604ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
605ed29f942SHoegeun Kwon 
606ed29f942SHoegeun Kwon 	return 0;
607ed29f942SHoegeun Kwon }
608ed29f942SHoegeun Kwon 
609e2af12bfSHoegeun Kwon static const struct drm_display_mode s6e3ha2_mode = {
610ed29f942SHoegeun Kwon 	.clock = 222372,
611ed29f942SHoegeun Kwon 	.hdisplay = 1440,
612ed29f942SHoegeun Kwon 	.hsync_start = 1440 + 1,
613ed29f942SHoegeun Kwon 	.hsync_end = 1440 + 1 + 1,
614ed29f942SHoegeun Kwon 	.htotal = 1440 + 1 + 1 + 1,
615ed29f942SHoegeun Kwon 	.vdisplay = 2560,
616ed29f942SHoegeun Kwon 	.vsync_start = 2560 + 1,
617ed29f942SHoegeun Kwon 	.vsync_end = 2560 + 1 + 1,
618ed29f942SHoegeun Kwon 	.vtotal = 2560 + 1 + 1 + 15,
619ed29f942SHoegeun Kwon 	.flags = 0,
620ed29f942SHoegeun Kwon };
621ed29f942SHoegeun Kwon 
622e2af12bfSHoegeun Kwon static const struct s6e3ha2_panel_desc samsung_s6e3ha2 = {
623e2af12bfSHoegeun Kwon 	.mode = &s6e3ha2_mode,
624e2af12bfSHoegeun Kwon 	.type = HA2_TYPE,
625e2af12bfSHoegeun Kwon };
626e2af12bfSHoegeun Kwon 
627e2af12bfSHoegeun Kwon static const struct drm_display_mode s6e3hf2_mode = {
628e2af12bfSHoegeun Kwon 	.clock = 247856,
629e2af12bfSHoegeun Kwon 	.hdisplay = 1600,
630e2af12bfSHoegeun Kwon 	.hsync_start = 1600 + 1,
631e2af12bfSHoegeun Kwon 	.hsync_end = 1600 + 1 + 1,
632e2af12bfSHoegeun Kwon 	.htotal = 1600 + 1 + 1 + 1,
633e2af12bfSHoegeun Kwon 	.vdisplay = 2560,
634e2af12bfSHoegeun Kwon 	.vsync_start = 2560 + 1,
635e2af12bfSHoegeun Kwon 	.vsync_end = 2560 + 1 + 1,
636e2af12bfSHoegeun Kwon 	.vtotal = 2560 + 1 + 1 + 15,
637e2af12bfSHoegeun Kwon 	.flags = 0,
638e2af12bfSHoegeun Kwon };
639e2af12bfSHoegeun Kwon 
640e2af12bfSHoegeun Kwon static const struct s6e3ha2_panel_desc samsung_s6e3hf2 = {
641e2af12bfSHoegeun Kwon 	.mode = &s6e3hf2_mode,
642e2af12bfSHoegeun Kwon 	.type = HF2_TYPE,
643e2af12bfSHoegeun Kwon };
644e2af12bfSHoegeun Kwon 
s6e3ha2_get_modes(struct drm_panel * panel,struct drm_connector * connector)6450ce8ddd8SSam Ravnborg static int s6e3ha2_get_modes(struct drm_panel *panel,
6460ce8ddd8SSam Ravnborg 			     struct drm_connector *connector)
647ed29f942SHoegeun Kwon {
648e2af12bfSHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
649ed29f942SHoegeun Kwon 	struct drm_display_mode *mode;
650ed29f942SHoegeun Kwon 
651aa6c4364SSam Ravnborg 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
652ed29f942SHoegeun Kwon 	if (!mode) {
6535936b3bdSSam Ravnborg 		dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
654e2af12bfSHoegeun Kwon 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
6550425662fSVille Syrjälä 			drm_mode_vrefresh(ctx->desc->mode));
656ed29f942SHoegeun Kwon 		return -ENOMEM;
657ed29f942SHoegeun Kwon 	}
658ed29f942SHoegeun Kwon 
659ed29f942SHoegeun Kwon 	drm_mode_set_name(mode);
660ed29f942SHoegeun Kwon 
661ed29f942SHoegeun Kwon 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
662ed29f942SHoegeun Kwon 	drm_mode_probed_add(connector, mode);
663ed29f942SHoegeun Kwon 
664ed29f942SHoegeun Kwon 	connector->display_info.width_mm = 71;
665ed29f942SHoegeun Kwon 	connector->display_info.height_mm = 125;
666ed29f942SHoegeun Kwon 
667ed29f942SHoegeun Kwon 	return 1;
668ed29f942SHoegeun Kwon }
669ed29f942SHoegeun Kwon 
670ed29f942SHoegeun Kwon static const struct drm_panel_funcs s6e3ha2_drm_funcs = {
671ed29f942SHoegeun Kwon 	.disable = s6e3ha2_disable,
672ed29f942SHoegeun Kwon 	.unprepare = s6e3ha2_unprepare,
673ed29f942SHoegeun Kwon 	.prepare = s6e3ha2_prepare,
674ed29f942SHoegeun Kwon 	.enable = s6e3ha2_enable,
675ed29f942SHoegeun Kwon 	.get_modes = s6e3ha2_get_modes,
676ed29f942SHoegeun Kwon };
677ed29f942SHoegeun Kwon 
s6e3ha2_probe(struct mipi_dsi_device * dsi)678ed29f942SHoegeun Kwon static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
679ed29f942SHoegeun Kwon {
680ed29f942SHoegeun Kwon 	struct device *dev = &dsi->dev;
681ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx;
682ed29f942SHoegeun Kwon 	int ret;
683ed29f942SHoegeun Kwon 
684ed29f942SHoegeun Kwon 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
685ed29f942SHoegeun Kwon 	if (!ctx)
686ed29f942SHoegeun Kwon 		return -ENOMEM;
687ed29f942SHoegeun Kwon 
688ed29f942SHoegeun Kwon 	mipi_dsi_set_drvdata(dsi, ctx);
689ed29f942SHoegeun Kwon 
690ed29f942SHoegeun Kwon 	ctx->dev = dev;
691e2af12bfSHoegeun Kwon 	ctx->desc = of_device_get_match_data(dev);
692ed29f942SHoegeun Kwon 
693ed29f942SHoegeun Kwon 	dsi->lanes = 4;
694ed29f942SHoegeun Kwon 	dsi->format = MIPI_DSI_FMT_RGB888;
695996e1defSJagan Teki 	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
696996e1defSJagan Teki 		MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
697996e1defSJagan Teki 		MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET;
698ed29f942SHoegeun Kwon 
699ed29f942SHoegeun Kwon 	ctx->supplies[0].supply = "vdd3";
700ed29f942SHoegeun Kwon 	ctx->supplies[1].supply = "vci";
701ed29f942SHoegeun Kwon 
702ed29f942SHoegeun Kwon 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
703ed29f942SHoegeun Kwon 				      ctx->supplies);
704ed29f942SHoegeun Kwon 	if (ret < 0) {
705ed29f942SHoegeun Kwon 		dev_err(dev, "failed to get regulators: %d\n", ret);
706ed29f942SHoegeun Kwon 		return ret;
707ed29f942SHoegeun Kwon 	}
708ed29f942SHoegeun Kwon 
709ed29f942SHoegeun Kwon 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
710ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->reset_gpio)) {
711ed29f942SHoegeun Kwon 		dev_err(dev, "cannot get reset-gpios %ld\n",
712ed29f942SHoegeun Kwon 			PTR_ERR(ctx->reset_gpio));
713ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->reset_gpio);
714ed29f942SHoegeun Kwon 	}
715ed29f942SHoegeun Kwon 
716ed29f942SHoegeun Kwon 	ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
717ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->enable_gpio)) {
718ed29f942SHoegeun Kwon 		dev_err(dev, "cannot get enable-gpios %ld\n",
719ed29f942SHoegeun Kwon 			PTR_ERR(ctx->enable_gpio));
720ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->enable_gpio);
721ed29f942SHoegeun Kwon 	}
722ed29f942SHoegeun Kwon 
723ed29f942SHoegeun Kwon 	ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,
724ed29f942SHoegeun Kwon 						&s6e3ha2_bl_ops, NULL);
725ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->bl_dev)) {
726ed29f942SHoegeun Kwon 		dev_err(dev, "failed to register backlight device\n");
727ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->bl_dev);
728ed29f942SHoegeun Kwon 	}
729ed29f942SHoegeun Kwon 
730ed29f942SHoegeun Kwon 	ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS;
731ed29f942SHoegeun Kwon 	ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
732ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
733ed29f942SHoegeun Kwon 
7349a2654c0SLaurent Pinchart 	drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs,
7359a2654c0SLaurent Pinchart 		       DRM_MODE_CONNECTOR_DSI);
736a91d0e7dSJagan Teki 	ctx->panel.prepare_prev_first = true;
737ed29f942SHoegeun Kwon 
738c3ee8c65SBernard Zhao 	drm_panel_add(&ctx->panel);
739ed29f942SHoegeun Kwon 
740ed29f942SHoegeun Kwon 	ret = mipi_dsi_attach(dsi);
741ed29f942SHoegeun Kwon 	if (ret < 0)
742ed29f942SHoegeun Kwon 		goto remove_panel;
743ed29f942SHoegeun Kwon 
744ed29f942SHoegeun Kwon 	return ret;
745ed29f942SHoegeun Kwon 
746ed29f942SHoegeun Kwon remove_panel:
747ed29f942SHoegeun Kwon 	drm_panel_remove(&ctx->panel);
748ed29f942SHoegeun Kwon 	backlight_device_unregister(ctx->bl_dev);
749ed29f942SHoegeun Kwon 
750ed29f942SHoegeun Kwon 	return ret;
751ed29f942SHoegeun Kwon }
752ed29f942SHoegeun Kwon 
s6e3ha2_remove(struct mipi_dsi_device * dsi)75379abca2bSUwe Kleine-König static void s6e3ha2_remove(struct mipi_dsi_device *dsi)
754ed29f942SHoegeun Kwon {
755ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
756ed29f942SHoegeun Kwon 
757ed29f942SHoegeun Kwon 	mipi_dsi_detach(dsi);
758ed29f942SHoegeun Kwon 	drm_panel_remove(&ctx->panel);
759ed29f942SHoegeun Kwon 	backlight_device_unregister(ctx->bl_dev);
760ed29f942SHoegeun Kwon }
761ed29f942SHoegeun Kwon 
762ed29f942SHoegeun Kwon static const struct of_device_id s6e3ha2_of_match[] = {
763e2af12bfSHoegeun Kwon 	{ .compatible = "samsung,s6e3ha2", .data = &samsung_s6e3ha2 },
764e2af12bfSHoegeun Kwon 	{ .compatible = "samsung,s6e3hf2", .data = &samsung_s6e3hf2 },
765ed29f942SHoegeun Kwon 	{ }
766ed29f942SHoegeun Kwon };
767ed29f942SHoegeun Kwon MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
768ed29f942SHoegeun Kwon 
769ed29f942SHoegeun Kwon static struct mipi_dsi_driver s6e3ha2_driver = {
770ed29f942SHoegeun Kwon 	.probe = s6e3ha2_probe,
771ed29f942SHoegeun Kwon 	.remove = s6e3ha2_remove,
772ed29f942SHoegeun Kwon 	.driver = {
773ed29f942SHoegeun Kwon 		.name = "panel-samsung-s6e3ha2",
774ed29f942SHoegeun Kwon 		.of_match_table = s6e3ha2_of_match,
775ed29f942SHoegeun Kwon 	},
776ed29f942SHoegeun Kwon };
777ed29f942SHoegeun Kwon module_mipi_dsi_driver(s6e3ha2_driver);
778ed29f942SHoegeun Kwon 
779ed29f942SHoegeun Kwon MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
780ed29f942SHoegeun Kwon MODULE_AUTHOR("Hyungwon Hwang <human.hwang@samsung.com>");
781ed29f942SHoegeun Kwon MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>");
782ed29f942SHoegeun Kwon MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");
783ed29f942SHoegeun Kwon MODULE_LICENSE("GPL v2");
784