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