blob: 5e6c11c4be323f1654384f291fa74b56ca62f644 [file] [log] [blame]
Anton Bamburad6a6dd92024-01-31 08:57:16 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Samsung LTL106HL02-001 DSI panel driver
4 *
5 * Copyright (c) 2020 Anton Bambura <jenneron@protonmail.com>
6 * Copyright (c) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
7 * Copyright (c) 2024 Jonas Schwöbel <jonasschwoebel@yahoo.de>
8 */
9
10#include <backlight.h>
11#include <dm.h>
12#include <panel.h>
13#include <log.h>
14#include <mipi_dsi.h>
15#include <asm/gpio.h>
16#include <linux/delay.h>
17#include <power/regulator.h>
18
19struct samsung_ltl106hl02_priv {
20 struct udevice *vdd;
21 struct udevice *backlight;
22
23 struct gpio_desc reset_gpio;
24};
25
26static struct display_timing default_timing = {
27 .pixelclock.typ = 137000000,
28 .hactive.typ = 1920,
29 .hfront_porch.typ = 32,
30 .hback_porch.typ = 64,
31 .hsync_len.typ = 32,
32 .vactive.typ = 1080,
33 .vfront_porch.typ = 2,
34 .vback_porch.typ = 26,
35 .vsync_len.typ = 3,
36};
37
38static int samsung_ltl106hl02_enable_backlight(struct udevice *dev)
39{
40 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
41 struct mipi_dsi_device *dsi = plat->device;
42 int ret;
43
44 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
45 if (ret < 0) {
46 log_debug("%s: failed to exit sleep mode: %d\n",
47 __func__, ret);
48 return ret;
49 }
50 mdelay(70);
51
52 ret = mipi_dsi_dcs_set_display_on(dsi);
53 if (ret < 0) {
54 log_debug("%s: failed to enable display: %d\n",
55 __func__, ret);
56 return ret;
57 }
58 mdelay(5);
59
60 return 0;
61}
62
63static int samsung_ltl106hl02_set_backlight(struct udevice *dev, int percent)
64{
65 struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev);
66 int ret;
67
68 ret = backlight_enable(priv->backlight);
69 if (ret)
70 return ret;
71
72 return backlight_set_brightness(priv->backlight, percent);
73}
74
75static int samsung_ltl106hl02_timings(struct udevice *dev,
76 struct display_timing *timing)
77{
78 memcpy(timing, &default_timing, sizeof(*timing));
79 return 0;
80}
81
82static int samsung_ltl106hl02_of_to_plat(struct udevice *dev)
83{
84 struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev);
85 int ret;
86
87 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
88 "backlight", &priv->backlight);
89 if (ret) {
90 log_debug("%s: cannot get backlight: ret = %d\n",
91 __func__, ret);
92 return ret;
93 }
94
95 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
96 "vdd-supply", &priv->vdd);
97 if (ret)
98 log_debug("%s: cannot get vdd-supply: error %d\n",
99 __func__, ret);
100
101 ret = gpio_request_by_name(dev, "reset-gpios", 0,
102 &priv->reset_gpio, GPIOD_IS_OUT);
103 if (ret)
104 log_debug("%s: cannot get reset-gpios: error %d\n",
105 __func__, ret);
106
107 return 0;
108}
109
110static int samsung_ltl106hl02_hw_init(struct udevice *dev)
111{
112 struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev);
113
114 dm_gpio_set_value(&priv->reset_gpio, 1);
115 regulator_set_enable_if_allowed(priv->vdd, 1);
116
117 /* Dataheets states at least 8.5 msec for vdd stabilization */
118 mdelay(10);
119
120 dm_gpio_set_value(&priv->reset_gpio, 0);
121
122 return 0;
123}
124
125static int samsung_ltl106hl02_probe(struct udevice *dev)
126{
127 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
128
129 /* fill characteristics of DSI data link */
130 plat->lanes = 4;
131 plat->format = MIPI_DSI_FMT_RGB888;
132 plat->mode_flags = MIPI_DSI_MODE_VIDEO;
133
134 return samsung_ltl106hl02_hw_init(dev);
135}
136
137static const struct panel_ops samsung_ltl106hl02_ops = {
138 .enable_backlight = samsung_ltl106hl02_enable_backlight,
139 .set_backlight = samsung_ltl106hl02_set_backlight,
140 .get_display_timing = samsung_ltl106hl02_timings,
141};
142
143static const struct udevice_id samsung_ltl106hl02_ids[] = {
144 { .compatible = "samsung,ltl106hl02-001" },
145 { }
146};
147
148U_BOOT_DRIVER(samsung_ltl106hl02) = {
149 .name = "samsung_ltl106hl02",
150 .id = UCLASS_PANEL,
151 .of_match = samsung_ltl106hl02_ids,
152 .ops = &samsung_ltl106hl02_ops,
153 .of_to_plat = samsung_ltl106hl02_of_to_plat,
154 .probe = samsung_ltl106hl02_probe,
155 .plat_auto = sizeof(struct mipi_dsi_panel_plat),
156 .priv_auto = sizeof(struct samsung_ltl106hl02_priv),
157};