1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2020 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6 #include <common.h>
7 #include <backlight.h>
8 #include <dm.h>
9 #include <mipi_dsi.h>
10 #include <panel.h>
11 #include <asm/gpio.h>
12 #include <dm/device_compat.h>
13 #include <linux/delay.h>
14 #include <power/regulator.h>
15
16 struct tl070wsh30_panel_priv {
17 struct udevice *reg;
18 struct udevice *backlight;
19 struct gpio_desc reset;
20 };
21
22 static const struct display_timing default_timing = {
23 .pixelclock.typ = 47250000,
24 .hactive.typ = 1024,
25 .hfront_porch.typ = 46,
26 .hback_porch.typ = 100,
27 .hsync_len.typ = 80,
28 .vactive.typ = 600,
29 .vfront_porch.typ = 5,
30 .vback_porch.typ = 20,
31 .vsync_len.typ = 5,
32 .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH,
33 };
34
tl070wsh30_panel_enable_backlight(struct udevice * dev)35 static int tl070wsh30_panel_enable_backlight(struct udevice *dev)
36 {
37 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
38 struct mipi_dsi_device *device = plat->device;
39 struct tl070wsh30_panel_priv *priv = dev_get_priv(dev);
40 int ret;
41
42 ret = mipi_dsi_attach(device);
43 if (ret < 0)
44 return ret;
45
46 ret = mipi_dsi_dcs_exit_sleep_mode(device);
47 if (ret)
48 return ret;
49
50 mdelay(200);
51
52 ret = mipi_dsi_dcs_set_display_on(device);
53 if (ret)
54 return ret;
55
56 mdelay(20);
57
58 ret = backlight_enable(priv->backlight);
59 if (ret)
60 return ret;
61
62 return 0;
63 }
64
tl070wsh30_panel_get_display_timing(struct udevice * dev,struct display_timing * timings)65 static int tl070wsh30_panel_get_display_timing(struct udevice *dev,
66 struct display_timing *timings)
67 {
68 memcpy(timings, &default_timing, sizeof(*timings));
69
70 return 0;
71 }
72
tl070wsh30_panel_of_to_plat(struct udevice * dev)73 static int tl070wsh30_panel_of_to_plat(struct udevice *dev)
74 {
75 struct tl070wsh30_panel_priv *priv = dev_get_priv(dev);
76 int ret;
77
78 if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
79 ret = device_get_supply_regulator(dev, "power-supply",
80 &priv->reg);
81 if (ret && ret != -ENOENT) {
82 dev_err(dev, "Warning: cannot get power supply\n");
83 return ret;
84 }
85 }
86
87 ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset,
88 GPIOD_IS_OUT);
89 if (ret) {
90 dev_err(dev, "Warning: cannot get reset GPIO\n");
91 if (ret != -ENOENT)
92 return ret;
93 }
94
95 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
96 "backlight", &priv->backlight);
97 if (ret) {
98 dev_err(dev, "Cannot get backlight: ret=%d\n", ret);
99 return ret;
100 }
101
102 return 0;
103 }
104
tl070wsh30_panel_probe(struct udevice * dev)105 static int tl070wsh30_panel_probe(struct udevice *dev)
106 {
107 struct tl070wsh30_panel_priv *priv = dev_get_priv(dev);
108 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
109 int ret;
110
111 if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
112 ret = regulator_set_enable(priv->reg, true);
113 if (ret)
114 return ret;
115 }
116
117 mdelay(10);
118
119 /* reset panel */
120 dm_gpio_set_value(&priv->reset, true);
121
122 mdelay(10);
123
124 dm_gpio_set_value(&priv->reset, false);
125
126 /* fill characteristics of DSI data link */
127 plat->lanes = 4;
128 plat->format = MIPI_DSI_FMT_RGB888;
129 plat->mode_flags = MIPI_DSI_MODE_VIDEO |
130 MIPI_DSI_MODE_VIDEO_BURST |
131 MIPI_DSI_MODE_LPM;
132
133 return 0;
134 }
135
136 static const struct panel_ops tl070wsh30_panel_ops = {
137 .enable_backlight = tl070wsh30_panel_enable_backlight,
138 .get_display_timing = tl070wsh30_panel_get_display_timing,
139 };
140
141 static const struct udevice_id tl070wsh30_panel_ids[] = {
142 { .compatible = "tdo,tl070wsh30" },
143 { }
144 };
145
146 U_BOOT_DRIVER(tl070wsh30_panel) = {
147 .name = "tl070wsh30_panel",
148 .id = UCLASS_PANEL,
149 .of_match = tl070wsh30_panel_ids,
150 .ops = &tl070wsh30_panel_ops,
151 .of_to_plat = tl070wsh30_panel_of_to_plat,
152 .probe = tl070wsh30_panel_probe,
153 .plat_auto = sizeof(struct mipi_dsi_panel_plat),
154 .priv_auto = sizeof(struct tl070wsh30_panel_priv),
155 };
156