drm/connector: Change DRM card alias from underscore to hyphen
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / panel / panel-himax-hx8394.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for panels based on Himax HX8394 controller, such as:
4  *
5  * - HannStar HSD060BHW4 5.99" MIPI-DSI panel
6  *
7  * Copyright (C) 2021 Kamil Trzciński
8  *
9  * Based on drivers/gpu/drm/panel/panel-sitronix-st7703.c
10  * Copyright (C) Purism SPC 2019
11  */
12
13 #include <linux/delay.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/media-bus-format.h>
16 #include <linux/mod_devicetable.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/regulator/consumer.h>
20
21 #include <video/mipi_display.h>
22
23 #include <drm/drm_mipi_dsi.h>
24 #include <drm/drm_modes.h>
25 #include <drm/drm_panel.h>
26
27 #define DRV_NAME "panel-himax-hx8394"
28
29 /* Manufacturer specific commands sent via DSI, listed in HX8394-F datasheet */
30 #define HX8394_CMD_SETSEQUENCE    0xb0
31 #define HX8394_CMD_SETPOWER       0xb1
32 #define HX8394_CMD_SETDISP        0xb2
33 #define HX8394_CMD_SETCYC         0xb4
34 #define HX8394_CMD_SETVCOM        0xb6
35 #define HX8394_CMD_SETTE          0xb7
36 #define HX8394_CMD_SETSENSOR      0xb8
37 #define HX8394_CMD_SETEXTC        0xb9
38 #define HX8394_CMD_SETMIPI        0xba
39 #define HX8394_CMD_SETOTP         0xbb
40 #define HX8394_CMD_SETREGBANK     0xbd
41 #define HX8394_CMD_UNKNOWN1       0xc0
42 #define HX8394_CMD_SETDGCLUT      0xc1
43 #define HX8394_CMD_SETID          0xc3
44 #define HX8394_CMD_SETDDB         0xc4
45 #define HX8394_CMD_UNKNOWN2       0xc6
46 #define HX8394_CMD_SETCABC        0xc9
47 #define HX8394_CMD_SETCABCGAIN    0xca
48 #define HX8394_CMD_SETPANEL       0xcc
49 #define HX8394_CMD_SETOFFSET      0xd2
50 #define HX8394_CMD_SETGIP0        0xd3
51 #define HX8394_CMD_UNKNOWN3       0xd4
52 #define HX8394_CMD_SETGIP1        0xd5
53 #define HX8394_CMD_SETGIP2        0xd6
54 #define HX8394_CMD_SETGPO         0xd6
55 #define HX8394_CMD_SETSCALING     0xdd
56 #define HX8394_CMD_SETIDLE        0xdf
57 #define HX8394_CMD_SETGAMMA       0xe0
58 #define HX8394_CMD_SETCHEMODE_DYN 0xe4
59 #define HX8394_CMD_SETCHE         0xe5
60 #define HX8394_CMD_SETCESEL       0xe6
61 #define HX8394_CMD_SET_SP_CMD     0xe9
62 #define HX8394_CMD_SETREADINDEX   0xfe
63 #define HX8394_CMD_GETSPIREAD     0xff
64
65 struct hx8394 {
66         struct device *dev;
67         struct drm_panel panel;
68         struct gpio_desc *reset_gpio;
69         struct regulator *vcc;
70         struct regulator *iovcc;
71         bool prepared;
72
73         const struct hx8394_panel_desc *desc;
74 };
75
76 struct hx8394_panel_desc {
77         const struct drm_display_mode *mode;
78         unsigned int lanes;
79         unsigned long mode_flags;
80         enum mipi_dsi_pixel_format format;
81         int (*init_sequence)(struct hx8394 *ctx);
82 };
83
84 static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
85 {
86         return container_of(panel, struct hx8394, panel);
87 }
88
89 static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
90 {
91         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
92
93         /* 5.19.8 SETEXTC: Set extension command (B9h) */
94         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC,
95                                0xff, 0x83, 0x94);
96
97         /* 5.19.2 SETPOWER: Set power (B1h) */
98         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
99                                0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
100
101         /* 5.19.9 SETMIPI: Set MIPI control (BAh) */
102         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI,
103                                0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
104
105         /* 5.19.3 SETDISP: Set display related register (B2h) */
106         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP,
107                                0x00, 0x80, 0x78, 0x0c, 0x07);
108
109         /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
110         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC,
111                                0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55,
112                                0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c,
113                                0x7c);
114
115         /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
116         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0,
117                                0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10,
118                                0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00,
119                                0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00,
120                                0x00, 0x0c, 0x40);
121
122         /* 5.19.20 Set GIP Option1 (D5h) */
123         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1,
124                                0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01,
125                                0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18,
126                                0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
127                                0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
128                                0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
129
130         /* 5.19.21 Set GIP Option2 (D6h) */
131         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2,
132                                0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06,
133                                0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18,
134                                0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
135                                0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
136                                0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
137
138         /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
139         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA,
140                                0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f,
141                                0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a,
142                                0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00,
143                                0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31,
144                                0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f,
145                                0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b,
146                                0x4a, 0x4c, 0x4b, 0x7f);
147
148         /* 5.19.17 SETPANEL (CCh) */
149         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL,
150                                0x0b);
151
152         /* Unknown command, not listed in the HX8394-F datasheet */
153         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1,
154                                0x1f, 0x31);
155
156         /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
157         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM,
158                                0x7d, 0x7d);
159
160         /* Unknown command, not listed in the HX8394-F datasheet */
161         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
162                                0x02);
163
164         /* 5.19.11 Set register bank (BDh) */
165         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
166                                0x01);
167
168         /* 5.19.2 SETPOWER: Set power (B1h) */
169         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
170                                0x00);
171
172         /* 5.19.11 Set register bank (BDh) */
173         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
174                                0x00);
175
176         /* Unknown command, not listed in the HX8394-F datasheet */
177         mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
178                                0xed);
179
180         return 0;
181 }
182
183 static const struct drm_display_mode hsd060bhw4_mode = {
184         .hdisplay    = 720,
185         .hsync_start = 720 + 40,
186         .hsync_end   = 720 + 40 + 46,
187         .htotal      = 720 + 40 + 46 + 40,
188         .vdisplay    = 1440,
189         .vsync_start = 1440 + 9,
190         .vsync_end   = 1440 + 9 + 7,
191         .vtotal      = 1440 + 9 + 7 + 7,
192         .clock       = 74250,
193         .flags       = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
194         .width_mm    = 68,
195         .height_mm   = 136,
196 };
197
198 static const struct hx8394_panel_desc hsd060bhw4_desc = {
199         .mode = &hsd060bhw4_mode,
200         .lanes = 4,
201         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
202         .format = MIPI_DSI_FMT_RGB888,
203         .init_sequence = hsd060bhw4_init_sequence,
204 };
205
206 static int hx8394_enable(struct drm_panel *panel)
207 {
208         struct hx8394 *ctx = panel_to_hx8394(panel);
209         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
210         int ret;
211
212         ret = ctx->desc->init_sequence(ctx);
213         if (ret) {
214                 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
215                 return ret;
216         }
217
218         ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
219         if (ret) {
220                 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
221                 return ret;
222         }
223
224         /* Panel is operational 120 msec after reset */
225         msleep(120);
226
227         ret = mipi_dsi_dcs_set_display_on(dsi);
228         if (ret) {
229                 dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
230                 goto sleep_in;
231         }
232
233         return 0;
234
235 sleep_in:
236         /* This will probably fail, but let's try orderly power off anyway. */
237         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
238         if (!ret)
239                 msleep(50);
240
241         return ret;
242 }
243
244 static int hx8394_disable(struct drm_panel *panel)
245 {
246         struct hx8394 *ctx = panel_to_hx8394(panel);
247         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
248         int ret;
249
250         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
251         if (ret) {
252                 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
253                 return ret;
254         }
255
256         msleep(50); /* about 3 frames */
257
258         return 0;
259 }
260
261 static int hx8394_unprepare(struct drm_panel *panel)
262 {
263         struct hx8394 *ctx = panel_to_hx8394(panel);
264
265         if (!ctx->prepared)
266                 return 0;
267
268         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
269
270         regulator_disable(ctx->iovcc);
271         regulator_disable(ctx->vcc);
272
273         ctx->prepared = false;
274
275         return 0;
276 }
277
278 static int hx8394_prepare(struct drm_panel *panel)
279 {
280         struct hx8394 *ctx = panel_to_hx8394(panel);
281         int ret;
282
283         if (ctx->prepared)
284                 return 0;
285
286         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
287
288         ret = regulator_enable(ctx->vcc);
289         if (ret) {
290                 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
291                 return ret;
292         }
293
294         ret = regulator_enable(ctx->iovcc);
295         if (ret) {
296                 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
297                 goto disable_vcc;
298         }
299
300         gpiod_set_value_cansleep(ctx->reset_gpio, 0);
301
302         msleep(180);
303
304         ctx->prepared = true;
305
306         return 0;
307
308 disable_vcc:
309         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
310         regulator_disable(ctx->vcc);
311         return ret;
312 }
313
314 static int hx8394_get_modes(struct drm_panel *panel,
315                             struct drm_connector *connector)
316 {
317         struct hx8394 *ctx = panel_to_hx8394(panel);
318         struct drm_display_mode *mode;
319
320         mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
321         if (!mode) {
322                 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
323                         ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
324                         drm_mode_vrefresh(ctx->desc->mode));
325                 return -ENOMEM;
326         }
327
328         drm_mode_set_name(mode);
329
330         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
331         connector->display_info.width_mm = mode->width_mm;
332         connector->display_info.height_mm = mode->height_mm;
333         drm_mode_probed_add(connector, mode);
334
335         return 1;
336 }
337
338 static const struct drm_panel_funcs hx8394_drm_funcs = {
339         .disable   = hx8394_disable,
340         .unprepare = hx8394_unprepare,
341         .prepare   = hx8394_prepare,
342         .enable    = hx8394_enable,
343         .get_modes = hx8394_get_modes,
344 };
345
346 static int hx8394_probe(struct mipi_dsi_device *dsi)
347 {
348         struct device *dev = &dsi->dev;
349         struct hx8394 *ctx;
350         int ret;
351
352         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
353         if (!ctx)
354                 return -ENOMEM;
355
356         ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
357         if (IS_ERR(ctx->reset_gpio))
358                 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
359                                      "Failed to get reset gpio\n");
360
361         mipi_dsi_set_drvdata(dsi, ctx);
362
363         ctx->dev = dev;
364         ctx->desc = of_device_get_match_data(dev);
365
366         dsi->mode_flags = ctx->desc->mode_flags;
367         dsi->format = ctx->desc->format;
368         dsi->lanes = ctx->desc->lanes;
369
370         ctx->vcc = devm_regulator_get(dev, "vcc");
371         if (IS_ERR(ctx->vcc))
372                 return dev_err_probe(dev, PTR_ERR(ctx->vcc),
373                                      "Failed to request vcc regulator\n");
374
375         ctx->iovcc = devm_regulator_get(dev, "iovcc");
376         if (IS_ERR(ctx->iovcc))
377                 return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
378                                      "Failed to request iovcc regulator\n");
379
380         drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
381                        DRM_MODE_CONNECTOR_DSI);
382
383         ret = drm_panel_of_backlight(&ctx->panel);
384         if (ret)
385                 return ret;
386
387         drm_panel_add(&ctx->panel);
388
389         ret = mipi_dsi_attach(dsi);
390         if (ret < 0) {
391                 dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
392                 drm_panel_remove(&ctx->panel);
393                 return ret;
394         }
395
396         dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
397                 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
398                 drm_mode_vrefresh(ctx->desc->mode),
399                 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
400
401         return 0;
402 }
403
404 static void hx8394_shutdown(struct mipi_dsi_device *dsi)
405 {
406         struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
407         int ret;
408
409         ret = drm_panel_disable(&ctx->panel);
410         if (ret < 0)
411                 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
412
413         ret = drm_panel_unprepare(&ctx->panel);
414         if (ret < 0)
415                 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
416 }
417
418 static void hx8394_remove(struct mipi_dsi_device *dsi)
419 {
420         struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
421         int ret;
422
423         hx8394_shutdown(dsi);
424
425         ret = mipi_dsi_detach(dsi);
426         if (ret < 0)
427                 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
428
429         drm_panel_remove(&ctx->panel);
430 }
431
432 static const struct of_device_id hx8394_of_match[] = {
433         { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
434         { /* sentinel */ }
435 };
436 MODULE_DEVICE_TABLE(of, hx8394_of_match);
437
438 static struct mipi_dsi_driver hx8394_driver = {
439         .probe  = hx8394_probe,
440         .remove = hx8394_remove,
441         .shutdown = hx8394_shutdown,
442         .driver = {
443                 .name = DRV_NAME,
444                 .of_match_table = hx8394_of_match,
445         },
446 };
447 module_mipi_dsi_driver(hx8394_driver);
448
449 MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
450 MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
451 MODULE_LICENSE("GPL");