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