]> Git Repo - J-linux.git/blob - drivers/gpu/drm/panel/panel-himax-hx83102.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / gpu / drm / panel / panel-himax-hx83102.c
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
79 static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel)
80 {
81         return container_of(panel, struct hx83102, base);
82 }
83
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
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
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
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
465 static int hx83102_enable(struct drm_panel *panel)
466 {
467         msleep(130);
468         return 0;
469 }
470
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
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
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
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
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
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
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
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 <[email protected]>");
707 MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels");
708 MODULE_LICENSE("GPL");
This page took 0.0678 seconds and 4 git commands to generate.