1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Driver for panels based on Himax HX83102 controller, such as:
4 *
5 * - Starry 10.51" WUXGA MIPI-DSI panel
6 *
7 * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c
8 */
9
10 #include <linux/delay.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/regulator/consumer.h>
15
16 #include <drm/drm_connector.h>
17 #include <drm/drm_crtc.h>
18 #include <drm/drm_mipi_dsi.h>
19 #include <drm/drm_panel.h>
20
21 #include <video/mipi_display.h>
22
23 /* Manufacturer specific DSI commands */
24 #define HX83102_SETPOWER 0xb1
25 #define HX83102_SETDISP 0xb2
26 #define HX83102_SETCYC 0xb4
27 #define HX83102_SETEXTC 0xb9
28 #define HX83102_SETMIPI 0xba
29 #define HX83102_SETVDC 0xbc
30 #define HX83102_SETBANK 0xbd
31 #define HX83102_UNKNOWN_BE 0xbe
32 #define HX83102_SETPTBA 0xbf
33 #define HX83102_SETSTBA 0xc0
34 #define HX83102_SETTCON 0xc7
35 #define HX83102_SETRAMDMY 0xc8
36 #define HX83102_SETPWM 0xc9
37 #define HX83102_SETCLOCK 0xcb
38 #define HX83102_SETPANEL 0xcc
39 #define HX83102_SETCASCADE 0xd0
40 #define HX83102_SETPCTRL 0xd1
41 #define HX83102_UNKNOWN_D2 0xd2
42 #define HX83102_SETGIP0 0xd3
43 #define HX83102_SETGIP1 0xd5
44 #define HX83102_SETGIP2 0xd6
45 #define HX83102_SETGIP3 0xd8
46 #define HX83102_SETGMA 0xe0
47 #define HX83102_UNKNOWN_E1 0xe1
48 #define HX83102_SETTP1 0xe7
49 #define HX83102_SETSPCCMD 0xe9
50
51 struct hx83102 {
52 struct drm_panel base;
53 struct mipi_dsi_device *dsi;
54
55 const struct hx83102_panel_desc *desc;
56
57 enum drm_panel_orientation orientation;
58 struct regulator *pp1800;
59 struct regulator *avee;
60 struct regulator *avdd;
61 struct gpio_desc *enable_gpio;
62 };
63
64 struct hx83102_panel_desc {
65 const struct drm_display_mode *modes;
66
67 /**
68 * @width_mm: width of the panel's active display area
69 * @height_mm: height of the panel's active display area
70 */
71 struct {
72 unsigned int width_mm;
73 unsigned int height_mm;
74 } size;
75
76 int (*init)(struct hx83102 *ctx);
77 };
78
panel_to_hx83102(struct drm_panel * panel)79 static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel)
80 {
81 return container_of(panel, struct hx83102, base);
82 }
83
hx83102_enable_extended_cmds(struct mipi_dsi_multi_context * dsi_ctx,bool enable)84 static void hx83102_enable_extended_cmds(struct mipi_dsi_multi_context *dsi_ctx, bool enable)
85 {
86 if (enable)
87 mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x21, 0x55, 0x00);
88 else
89 mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x00, 0x00, 0x00);
90 }
91
starry_himax83102_j02_init(struct hx83102 * ctx)92 static int starry_himax83102_j02_init(struct hx83102 *ctx)
93 {
94 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
95
96 hx83102_enable_extended_cmds(&dsi_ctx, true);
97 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1,
98 0x31, 0xd7, 0x2f, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11,
99 0x65, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x74,
100 0x33);
101 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00,
102 0x12, 0x72, 0x3c, 0xa3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xf5);
103 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x76, 0x76, 0x76, 0x76, 0x76,
104 0x76, 0x63, 0x5c, 0x63, 0x5c, 0x01, 0x9e);
105 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
106 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
107 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
108 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
109 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
110 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
111 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x11, 0x22,
112 0xa0, 0x61, 0x08, 0xf5, 0x03);
113 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
114 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
115 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
116 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
117 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
118 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
119 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
120 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x33);
121 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);
122 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
123 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
124 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
125 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c,
126 0xff);
127 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f);
128 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3b, 0x12, 0x12, 0x03, 0x03,
130 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32,
131 0x17, 0x94, 0x07, 0x94, 0x00, 0x00);
132 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
133 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1a, 0x1a, 0x1b,
134 0x1b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21,
135 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
136 0x18, 0x18, 0x18, 0x18, 0x18);
137 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
138 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
139 0x1b, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28,
140 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
141 0x18, 0x18, 0x18, 0x18, 0x18);
142 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0,
143 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa,
144 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa,
145 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0);
146 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x09, 0x14, 0x1e, 0x26, 0x48,
147 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, 0x98,
148 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1e, 0x26,
149 0x48, 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f,
150 0x98, 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73);
151 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x0e, 0x10, 0x10, 0x21, 0x2b, 0x9a,
152 0x02, 0x54, 0x9a, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05,
153 0x02, 0x02, 0x10);
154 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
155 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
156 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
157 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3c, 0xfa);
158 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x80, 0x0c, 0x01);
160 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x28, 0x01, 0x7e, 0x0f,
161 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40);
162 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
163 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0,
164 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0);
165 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x04, 0xfe, 0x04, 0xfe, 0x04,
166 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20,
167 0x9e, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
168 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
169 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
170 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
171 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
172 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00,
173 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00,
174 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8,
175 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00);
176 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
177 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
178 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
179 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
180 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
181 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
182 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
183 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
184 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
185
186 return dsi_ctx.accum_err;
187 };
188
boe_nv110wum_init(struct hx83102 * ctx)189 static int boe_nv110wum_init(struct hx83102 *ctx)
190 {
191 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
192
193 msleep(60);
194
195 hx83102_enable_extended_cmds(&dsi_ctx, true);
196 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xaf, 0xaf, 0x2b, 0xeb, 0x42,
197 0xe1, 0x4d, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, 0x00,
198 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x9a, 0x33);
199 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
200 0x71, 0x3c, 0xa3, 0x11, 0x00, 0x00, 0x00, 0x88, 0xf5, 0x22, 0x8f);
201 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x49, 0x49, 0x32, 0x32, 0x14, 0x32,
202 0x84, 0x6e, 0x84, 0x6e, 0x01, 0x9c);
203 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
204 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
205 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
206 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
207 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
208 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x84);
209 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x00, 0x00, 0xa0,
210 0x61, 0x08, 0xf5, 0x03);
211 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
212 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
213 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
214 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
215 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
216 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
217 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01);
218 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
219 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
220 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
221 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
222 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
223 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, 0xff);
224 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f, 0x11);
225 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,
226 0x08, 0x04, 0x08, 0x37, 0x37, 0x64, 0x4b, 0x11, 0x11, 0x03, 0x03, 0x32,
227 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x10, 0x0a, 0x00, 0x0a, 0x32, 0x17, 0x98,
228 0x07, 0x98, 0x00, 0x00);
229 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1e,
230 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x07, 0x06,
231 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00,
232 0x01, 0x00, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
233 0x18, 0x18);
234 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
235 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0);
236 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c,
237 0x44, 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0,
238 0xa0, 0x4f, 0x58, 0x64, 0x73, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, 0x44,
239 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, 0xa0,
240 0x4f, 0x58, 0x64, 0x73);
241 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
242 0x00, 0x53, 0x9b, 0x14, 0x14);
243 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x11, 0x00, 0x00, 0x89, 0x30, 0x80,
244 0x07, 0x80, 0x02, 0x58, 0x00, 0x14, 0x02, 0x58, 0x02, 0x58, 0x02, 0x00,
245 0x02, 0x2c, 0x00, 0x20, 0x02, 0x02, 0x00, 0x08, 0x00, 0x0c, 0x05, 0x0e,
246 0x04, 0x94, 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, 0x06, 0x0b,
247 0x0b, 0x33, 0x0e);
248 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
249 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
250 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
251 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);
252 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
253 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x96);
254 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc9);
255 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x84);
256 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
257 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd1);
258 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0xf6, 0x2b, 0x34, 0x2b, 0x74, 0x3b,
259 0x74, 0x6b, 0x74);
260 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
261 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
262 0x7e, 0x10, 0xa0, 0x00, 0x00);
263 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
264 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x02, 0x00, 0xbb, 0x11);
265 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0,
266 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0);
267 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
268 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x65,
269 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);
270 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
271 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
272 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,
273 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00);
274 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
275 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
276 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
277 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
278 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
279 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
280 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
281 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
282 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
283 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
284 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
285 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
286 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
287 hx83102_enable_extended_cmds(&dsi_ctx, false);
288
289 mipi_dsi_msleep(&dsi_ctx, 50);
290
291 return dsi_ctx.accum_err;
292 };
293
ivo_t109nw41_init(struct hx83102 * ctx)294 static int ivo_t109nw41_init(struct hx83102 *ctx)
295 {
296 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
297
298 msleep(60);
299
300 hx83102_enable_extended_cmds(&dsi_ctx, true);
301 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xed, 0xed, 0x27, 0xe7, 0x52,
302 0xf5, 0x39, 0x36, 0x36, 0x36, 0x36, 0x32, 0x8b, 0x11, 0x65, 0x00, 0x88,
303 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0xd6, 0x33);
304 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,
305 0x71, 0x3c, 0xa3, 0x22, 0x20, 0x00, 0x00, 0x88, 0x01);
306 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x35, 0x35, 0x43, 0x43, 0x35, 0x35,
307 0x30, 0x7a, 0x30, 0x7a, 0x01, 0x9d);
308 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);
309 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);
310 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
311 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);
312 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);
313 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);
314 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x34, 0x34, 0x22, 0x11, 0x22, 0xa0,
315 0x31, 0x08, 0xf5, 0x03);
316 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);
317 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);
318 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
319 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd3);
320 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x22);
321 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
322 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
323 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);
324 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
325 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);
326 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);
327 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);
328 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
329 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);
330 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
331 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c,
332 0xff);
333 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08,
334 0x08, 0x08, 0x08, 0x37, 0x07, 0x64, 0x7c, 0x11, 0x11, 0x03, 0x03, 0x32,
335 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x17, 0x97, 0x07, 0x97, 0x32, 0x00, 0x02,
336 0x00, 0x02, 0x00, 0x00);
337 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x25, 0x24, 0x25, 0x24, 0x18, 0x18,
338 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02,
339 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f,
340 0x1f, 0x1f, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
341 0x18, 0x18);
342 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
343 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
346 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x07, 0x10, 0x17, 0x1c, 0x33,
347 0x48, 0x50, 0x57, 0x50, 0x68, 0x6e, 0x71, 0x7f, 0x81, 0x8a, 0x8e, 0x9b,
348 0x9c, 0x4d, 0x56, 0x5d, 0x73, 0x00, 0x07, 0x10, 0x17, 0x1c, 0x33, 0x48,
349 0x50, 0x57, 0x50, 0x68, 0x6e, 0x71, 0x7f, 0x81, 0x8a, 0x8e, 0x9b, 0x9c,
350 0x4d, 0x56, 0x5d, 0x73);
351 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,
352 0x00, 0x4f, 0xa0, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0a, 0x02,
353 0x02, 0x00, 0x33, 0x02, 0x04, 0x18, 0x01);
354 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
355 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd);
356 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);
357 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x04, 0x00, 0x00);
358 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
360 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
362 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,
363 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00);
364 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);
365 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2);
366 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x79);
367 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
368 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);
369 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,
370 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x6e,
371 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
372 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);
373 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
374 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,
375 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,
376 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
378 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);
379 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);
380 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
381 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);
382 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
383 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
384 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);
385 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);
386 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
387 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);
388 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);
389 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);
390 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);
391 mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);
392 hx83102_enable_extended_cmds(&dsi_ctx, false);
393
394 mipi_dsi_msleep(&dsi_ctx, 60);
395
396 return dsi_ctx.accum_err;
397 };
398
399 static const struct drm_display_mode starry_mode = {
400 .clock = 162680,
401 .hdisplay = 1200,
402 .hsync_start = 1200 + 60,
403 .hsync_end = 1200 + 60 + 20,
404 .htotal = 1200 + 60 + 20 + 40,
405 .vdisplay = 1920,
406 .vsync_start = 1920 + 116,
407 .vsync_end = 1920 + 116 + 8,
408 .vtotal = 1920 + 116 + 8 + 12,
409 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
410 };
411
412 static const struct hx83102_panel_desc starry_desc = {
413 .modes = &starry_mode,
414 .size = {
415 .width_mm = 141,
416 .height_mm = 226,
417 },
418 .init = starry_himax83102_j02_init,
419 };
420
421 static const struct drm_display_mode boe_tv110wum_default_mode = {
422 .clock = 167700,
423 .hdisplay = 1200,
424 .hsync_start = 1200 + 75,
425 .hsync_end = 1200 + 75 + 20,
426 .htotal = 1200 + 75 + 20 + 65,
427 .vdisplay = 1920,
428 .vsync_start = 1920 + 115,
429 .vsync_end = 1920 + 115 + 8,
430 .vtotal = 1920 + 115 + 8 + 12,
431 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
432 };
433
434 static const struct hx83102_panel_desc boe_nv110wum_desc = {
435 .modes = &boe_tv110wum_default_mode,
436 .size = {
437 .width_mm = 147,
438 .height_mm = 235,
439 },
440 .init = boe_nv110wum_init,
441 };
442
443 static const struct drm_display_mode ivo_t109nw41_default_mode = {
444 .clock = 167700,
445 .hdisplay = 1200,
446 .hsync_start = 1200 + 75,
447 .hsync_end = 1200 + 75 + 20,
448 .htotal = 1200 + 75 + 20 + 65,
449 .vdisplay = 1920,
450 .vsync_start = 1920 + 115,
451 .vsync_end = 1920 + 115 + 8,
452 .vtotal = 1920 + 115 + 8 + 12,
453 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
454 };
455
456 static const struct hx83102_panel_desc ivo_t109nw41_desc = {
457 .modes = &ivo_t109nw41_default_mode,
458 .size = {
459 .width_mm = 147,
460 .height_mm = 235,
461 },
462 .init = ivo_t109nw41_init,
463 };
464
hx83102_enable(struct drm_panel * panel)465 static int hx83102_enable(struct drm_panel *panel)
466 {
467 msleep(130);
468 return 0;
469 }
470
hx83102_disable(struct drm_panel * panel)471 static int hx83102_disable(struct drm_panel *panel)
472 {
473 struct hx83102 *ctx = panel_to_hx83102(panel);
474 struct mipi_dsi_device *dsi = ctx->dsi;
475 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
476
477 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
478
479 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
480 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
481
482 mipi_dsi_msleep(&dsi_ctx, 150);
483
484 return dsi_ctx.accum_err;
485 }
486
hx83102_unprepare(struct drm_panel * panel)487 static int hx83102_unprepare(struct drm_panel *panel)
488 {
489 struct hx83102 *ctx = panel_to_hx83102(panel);
490
491 gpiod_set_value(ctx->enable_gpio, 0);
492 usleep_range(1000, 2000);
493 regulator_disable(ctx->avee);
494 regulator_disable(ctx->avdd);
495 usleep_range(5000, 7000);
496 regulator_disable(ctx->pp1800);
497
498 return 0;
499 }
500
hx83102_prepare(struct drm_panel * panel)501 static int hx83102_prepare(struct drm_panel *panel)
502 {
503 struct hx83102 *ctx = panel_to_hx83102(panel);
504 struct mipi_dsi_device *dsi = ctx->dsi;
505 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
506
507 gpiod_set_value(ctx->enable_gpio, 0);
508 usleep_range(1000, 1500);
509
510 dsi_ctx.accum_err = regulator_enable(ctx->pp1800);
511 if (dsi_ctx.accum_err)
512 return dsi_ctx.accum_err;
513
514 usleep_range(3000, 5000);
515
516 dsi_ctx.accum_err = regulator_enable(ctx->avdd);
517 if (dsi_ctx.accum_err)
518 goto poweroff1v8;
519 dsi_ctx.accum_err = regulator_enable(ctx->avee);
520 if (dsi_ctx.accum_err)
521 goto poweroffavdd;
522
523 usleep_range(10000, 11000);
524
525 mipi_dsi_dcs_nop_multi(&dsi_ctx);
526 if (dsi_ctx.accum_err)
527 goto poweroff;
528
529 usleep_range(1000, 2000);
530
531 gpiod_set_value(ctx->enable_gpio, 1);
532 usleep_range(1000, 2000);
533 gpiod_set_value(ctx->enable_gpio, 0);
534 usleep_range(1000, 2000);
535 gpiod_set_value(ctx->enable_gpio, 1);
536 usleep_range(6000, 10000);
537
538 dsi_ctx.accum_err = ctx->desc->init(ctx);
539
540 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
541 mipi_dsi_msleep(&dsi_ctx, 120);
542 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
543 if (dsi_ctx.accum_err)
544 goto poweroff;
545
546 return 0;
547
548 poweroff:
549 gpiod_set_value(ctx->enable_gpio, 0);
550 regulator_disable(ctx->avee);
551 poweroffavdd:
552 regulator_disable(ctx->avdd);
553 poweroff1v8:
554 usleep_range(5000, 7000);
555 regulator_disable(ctx->pp1800);
556
557 return dsi_ctx.accum_err;
558 }
559
hx83102_get_modes(struct drm_panel * panel,struct drm_connector * connector)560 static int hx83102_get_modes(struct drm_panel *panel,
561 struct drm_connector *connector)
562 {
563 struct hx83102 *ctx = panel_to_hx83102(panel);
564 const struct drm_display_mode *m = ctx->desc->modes;
565 struct drm_display_mode *mode;
566
567 mode = drm_mode_duplicate(connector->dev, m);
568 if (!mode)
569 return -ENOMEM;
570
571 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
572 drm_mode_set_name(mode);
573 drm_mode_probed_add(connector, mode);
574
575 connector->display_info.width_mm = ctx->desc->size.width_mm;
576 connector->display_info.height_mm = ctx->desc->size.height_mm;
577 connector->display_info.bpc = 8;
578
579 return 1;
580 }
581
hx83102_get_orientation(struct drm_panel * panel)582 static enum drm_panel_orientation hx83102_get_orientation(struct drm_panel *panel)
583 {
584 struct hx83102 *ctx = panel_to_hx83102(panel);
585
586 return ctx->orientation;
587 }
588
589 static const struct drm_panel_funcs hx83102_drm_funcs = {
590 .disable = hx83102_disable,
591 .unprepare = hx83102_unprepare,
592 .prepare = hx83102_prepare,
593 .enable = hx83102_enable,
594 .get_modes = hx83102_get_modes,
595 .get_orientation = hx83102_get_orientation,
596 };
597
hx83102_panel_add(struct hx83102 * ctx)598 static int hx83102_panel_add(struct hx83102 *ctx)
599 {
600 struct device *dev = &ctx->dsi->dev;
601 int err;
602
603 ctx->avdd = devm_regulator_get(dev, "avdd");
604 if (IS_ERR(ctx->avdd))
605 return PTR_ERR(ctx->avdd);
606
607 ctx->avee = devm_regulator_get(dev, "avee");
608 if (IS_ERR(ctx->avee))
609 return PTR_ERR(ctx->avee);
610
611 ctx->pp1800 = devm_regulator_get(dev, "pp1800");
612 if (IS_ERR(ctx->pp1800))
613 return PTR_ERR(ctx->pp1800);
614
615 ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
616 if (IS_ERR(ctx->enable_gpio))
617 return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "Cannot get enable GPIO\n");
618
619 ctx->base.prepare_prev_first = true;
620
621 drm_panel_init(&ctx->base, dev, &hx83102_drm_funcs,
622 DRM_MODE_CONNECTOR_DSI);
623 err = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
624 if (err < 0)
625 return dev_err_probe(dev, err, "failed to get orientation\n");
626
627 err = drm_panel_of_backlight(&ctx->base);
628 if (err)
629 return err;
630
631 ctx->base.funcs = &hx83102_drm_funcs;
632 ctx->base.dev = &ctx->dsi->dev;
633
634 drm_panel_add(&ctx->base);
635
636 return 0;
637 }
638
hx83102_probe(struct mipi_dsi_device * dsi)639 static int hx83102_probe(struct mipi_dsi_device *dsi)
640 {
641 struct hx83102 *ctx;
642 int ret;
643 const struct hx83102_panel_desc *desc;
644
645 ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
646 if (!ctx)
647 return -ENOMEM;
648
649 desc = of_device_get_match_data(&dsi->dev);
650 dsi->lanes = 4;
651 dsi->format = MIPI_DSI_FMT_RGB888;
652 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
653 MIPI_DSI_MODE_LPM;
654 ctx->desc = desc;
655 ctx->dsi = dsi;
656 ret = hx83102_panel_add(ctx);
657 if (ret < 0)
658 return ret;
659
660 mipi_dsi_set_drvdata(dsi, ctx);
661
662 ret = mipi_dsi_attach(dsi);
663 if (ret)
664 drm_panel_remove(&ctx->base);
665
666 return ret;
667 }
668
hx83102_remove(struct mipi_dsi_device * dsi)669 static void hx83102_remove(struct mipi_dsi_device *dsi)
670 {
671 struct hx83102 *ctx = mipi_dsi_get_drvdata(dsi);
672 int ret;
673
674 ret = mipi_dsi_detach(dsi);
675 if (ret < 0)
676 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
677
678 if (ctx->base.dev)
679 drm_panel_remove(&ctx->base);
680 }
681
682 static const struct of_device_id hx83102_of_match[] = {
683 { .compatible = "boe,nv110wum-l60",
684 .data = &boe_nv110wum_desc
685 },
686 { .compatible = "ivo,t109nw41",
687 .data = &ivo_t109nw41_desc
688 },
689 { .compatible = "starry,himax83102-j02",
690 .data = &starry_desc
691 },
692 { /* sentinel */ }
693 };
694 MODULE_DEVICE_TABLE(of, hx83102_of_match);
695
696 static struct mipi_dsi_driver hx83102_driver = {
697 .probe = hx83102_probe,
698 .remove = hx83102_remove,
699 .driver = {
700 .name = "panel-himax-hx83102",
701 .of_match_table = hx83102_of_match,
702 },
703 };
704 module_mipi_dsi_driver(hx83102_driver);
705
706 MODULE_AUTHOR("Cong Yang <yangcong5@huaqin.corp-partner.google.com>");
707 MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels");
708 MODULE_LICENSE("GPL");
709