]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/video/renesas-r61307.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / video / renesas-r61307.c
CommitLineData
dcee478a
SR
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Renesas R61307 panel driver
4 *
5 * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
6 */
7
d678a59d 8#include <common.h>
dcee478a
SR
9#include <backlight.h>
10#include <dm.h>
11#include <panel.h>
12#include <log.h>
13#include <misc.h>
14#include <mipi_display.h>
15#include <mipi_dsi.h>
16#include <asm/gpio.h>
17#include <linux/delay.h>
18#include <linux/err.h>
19#include <power/regulator.h>
20
21/*
81f3a665 22 * The datasheet is not publicly available, all values are
dcee478a
SR
23 * taken from the downstream. If you have access to datasheets,
24 * corrections are welcome.
25 */
26
27#define R61307_MACP 0xB0 /* Manufacturer CMD Protect */
28
29#define R61307_INVERSION 0xC1
30#define R61307_GAMMA_SET_A 0xC8 /* Gamma Setting A */
31#define R61307_GAMMA_SET_B 0xC9 /* Gamma Setting B */
32#define R61307_GAMMA_SET_C 0xCA /* Gamma Setting C */
33#define R61307_CONTRAST_SET 0xCC
34
35struct renesas_r61307_priv {
36 struct udevice *vcc;
37 struct udevice *iovcc;
38
39 struct udevice *backlight;
40
41 struct gpio_desc reset_gpio;
42
43 bool dig_cont_adj;
44 bool inversion;
45 u32 gamma;
46};
47
48static const u8 macp_on[] = {
49 R61307_MACP, 0x03
50};
51
52static const u8 macp_off[] = {
53 R61307_MACP, 0x04
54};
55
56static const u8 address_mode[] = {
57 MIPI_DCS_SET_ADDRESS_MODE
58};
59
60static const u8 contrast_setting[] = {
61 R61307_CONTRAST_SET,
62 0xdc, 0xb4, 0xff
63};
64
65static const u8 column_inversion[] = {
66 R61307_INVERSION,
67 0x00, 0x50, 0x03, 0x22,
68 0x16, 0x06, 0x60, 0x11
69};
70
71static const u8 line_inversion[] = {
72 R61307_INVERSION,
73 0x00, 0x10, 0x03, 0x22,
74 0x16, 0x06, 0x60, 0x01
75};
76
77static const u8 gamma_setting[][25] = {
78 {},
79 {
80 R61307_GAMMA_SET_A,
81 0x00, 0x06, 0x0a, 0x0f,
82 0x14, 0x1f, 0x1f, 0x17,
83 0x12, 0x0c, 0x09, 0x06,
84 0x00, 0x06, 0x0a, 0x0f,
85 0x14, 0x1f, 0x1f, 0x17,
86 0x12, 0x0c, 0x09, 0x06
87 },
88 {
89 R61307_GAMMA_SET_A,
90 0x00, 0x05, 0x0b, 0x0f,
91 0x11, 0x1d, 0x20, 0x18,
92 0x18, 0x09, 0x07, 0x06,
93 0x00, 0x05, 0x0b, 0x0f,
94 0x11, 0x1d, 0x20, 0x18,
95 0x18, 0x09, 0x07, 0x06
96 },
97 {
98 R61307_GAMMA_SET_A,
99 0x0b, 0x0d, 0x10, 0x14,
100 0x13, 0x1d, 0x20, 0x18,
101 0x12, 0x09, 0x07, 0x06,
102 0x0a, 0x0c, 0x10, 0x14,
103 0x13, 0x1d, 0x20, 0x18,
104 0x12, 0x09, 0x07, 0x06
105 },
106};
107
108static struct display_timing default_timing = {
109 .pixelclock.typ = 62000000,
110 .hactive.typ = 768,
111 .hfront_porch.typ = 116,
112 .hback_porch.typ = 81,
113 .hsync_len.typ = 5,
114 .vactive.typ = 1024,
115 .vfront_porch.typ = 24,
116 .vback_porch.typ = 8,
117 .vsync_len.typ = 2,
118};
119
120static int renesas_r61307_enable_backlight(struct udevice *dev)
dcee478a
SR
121{
122 struct renesas_r61307_priv *priv = dev_get_priv(dev);
123 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
124 struct mipi_dsi_device *dsi = plat->device;
125 int ret;
126
127 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
128 if (ret < 0) {
129 log_err("failed to exit sleep mode: %d\n", ret);
130 return ret;
131 }
132
133 mdelay(80);
134
135 mipi_dsi_dcs_write_buffer(dsi, address_mode,
136 sizeof(address_mode));
137
138 mdelay(20);
139
140 ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
141 if (ret < 0) {
142 log_err("failed to set pixel format: %d\n", ret);
143 return ret;
144 }
145
146 /* MACP Off */
147 mipi_dsi_generic_write(dsi, macp_off, sizeof(macp_off));
148
149 if (priv->dig_cont_adj)
150 mipi_dsi_generic_write(dsi, contrast_setting,
151 sizeof(contrast_setting));
152
153 if (priv->gamma)
154 mipi_dsi_generic_write(dsi, gamma_setting[priv->gamma],
155 sizeof(gamma_setting[priv->gamma]));
156
157 if (priv->inversion)
158 mipi_dsi_generic_write(dsi, column_inversion,
159 sizeof(column_inversion));
160 else
161 mipi_dsi_generic_write(dsi, line_inversion,
162 sizeof(line_inversion));
163
164 /* MACP On */
165 mipi_dsi_generic_write(dsi, macp_on, sizeof(macp_on));
166
167 ret = mipi_dsi_dcs_set_display_on(dsi);
168 if (ret < 0) {
169 log_err("failed to set display on: %d\n", ret);
170 return ret;
171 }
dcee478a
SR
172 mdelay(50);
173
9970634f
SR
174 return 0;
175}
176
177static int renesas_r61307_set_backlight(struct udevice *dev, int percent)
178{
179 struct renesas_r61307_priv *priv = dev_get_priv(dev);
180 int ret;
181
dcee478a
SR
182 ret = backlight_enable(priv->backlight);
183 if (ret)
184 return ret;
185
9970634f 186 mdelay(5);
dcee478a 187
9970634f 188 return backlight_set_brightness(priv->backlight, percent);
dcee478a
SR
189}
190
191static int renesas_r61307_timings(struct udevice *dev,
192 struct display_timing *timing)
193{
194 memcpy(timing, &default_timing, sizeof(*timing));
195 return 0;
196}
197
198static int renesas_r61307_of_to_plat(struct udevice *dev)
199{
200 struct renesas_r61307_priv *priv = dev_get_priv(dev);
201 int ret;
202
203 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
204 "backlight", &priv->backlight);
205 if (ret) {
206 log_err("Cannot get backlight: ret = %d\n", ret);
207 return ret;
208 }
209
210 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
211 "vcc-supply", &priv->vcc);
212 if (ret) {
213 log_err("Cannot get vcc-supply: ret = %d\n", ret);
214 return ret;
215 }
216
217 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
218 "iovcc-supply", &priv->iovcc);
219 if (ret) {
220 log_err("Cannot get iovcc-supply: ret = %d\n", ret);
221 return ret;
222 }
223
224 ret = gpio_request_by_name(dev, "reset-gpios", 0,
225 &priv->reset_gpio, GPIOD_IS_OUT);
226 if (ret) {
227 log_err("Could not decode reser-gpios (%d)\n", ret);
228 return ret;
229 }
230
231 priv->dig_cont_adj = dev_read_bool(dev, "renesas,contrast");
232 priv->inversion = dev_read_bool(dev, "renesas,inversion");
233 priv->gamma = dev_read_u32_default(dev, "renesas,gamma", 0);
234
235 return 0;
236}
237
9970634f
SR
238static int renesas_r61307_hw_init(struct udevice *dev)
239{
240 struct renesas_r61307_priv *priv = dev_get_priv(dev);
241 int ret;
242
243 ret = regulator_set_enable_if_allowed(priv->vcc, 1);
244 if (ret) {
245 log_debug("%s: enabling vcc-supply failed (%d)\n",
246 __func__, ret);
247 return ret;
248 }
249 mdelay(5);
250
251 ret = regulator_set_enable_if_allowed(priv->iovcc, 1);
252 if (ret) {
253 log_debug("%s: enabling iovcc-supply failed (%d)\n",
254 __func__, ret);
255 return ret;
256 }
257
258 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
259 if (ret) {
260 log_debug("%s: changing reset-gpio failed (%d)\n",
261 __func__, ret);
262 return ret;
263 }
264 mdelay(5);
265
266 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
267 if (ret) {
268 log_debug("%s: changing reset-gpio failed (%d)\n",
269 __func__, ret);
270 return ret;
271 }
272
273 mdelay(5);
274
275 return 0;
276}
277
dcee478a
SR
278static int renesas_r61307_probe(struct udevice *dev)
279{
280 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
281
282 /* fill characteristics of DSI data link */
283 plat->lanes = 4;
284 plat->format = MIPI_DSI_FMT_RGB888;
285 plat->mode_flags = MIPI_DSI_MODE_VIDEO;
286
9970634f 287 return renesas_r61307_hw_init(dev);
dcee478a
SR
288}
289
290static const struct panel_ops renesas_r61307_ops = {
291 .enable_backlight = renesas_r61307_enable_backlight,
292 .set_backlight = renesas_r61307_set_backlight,
293 .get_display_timing = renesas_r61307_timings,
294};
295
296static const struct udevice_id renesas_r61307_ids[] = {
297 { .compatible = "koe,tx13d100vm0eaa" },
298 { .compatible = "hitachi,tx13d100vm0eaa" },
299 { }
300};
301
302U_BOOT_DRIVER(renesas_r61307) = {
303 .name = "renesas_r61307",
304 .id = UCLASS_PANEL,
305 .of_match = renesas_r61307_ids,
306 .ops = &renesas_r61307_ops,
307 .of_to_plat = renesas_r61307_of_to_plat,
308 .probe = renesas_r61307_probe,
309 .plat_auto = sizeof(struct mipi_dsi_panel_plat),
310 .priv_auto = sizeof(struct renesas_r61307_priv),
311};