xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/panel-maxim-max96752f.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Maxim MAX96752F GMSL2 Deserializer
4  *
5  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
6  */
7 
8 #include <config.h>
9 #include <common.h>
10 #include <backlight.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #include <video.h>
14 
15 #include <asm/gpio.h>
16 #include <dm/device.h>
17 #include <dm/read.h>
18 #include <dm/pinctrl.h>
19 #include <dm/uclass-id.h>
20 #include <linux/media-bus-format.h>
21 
22 #include "rockchip_display.h"
23 #include "rockchip_panel.h"
24 
25 struct max96752f;
26 
27 struct panel_desc {
28 	const char *name;
29 	int (*prepare)(struct max96752f *max96752f);
30 	int (*unprepare)(struct max96752f *max96752f);
31 	int (*enable)(struct max96752f *max96752f);
32 	int (*disable)(struct max96752f *max96752f);
33 	int (*backlight_enable)(struct max96752f *max96752f);
34 	int (*backlight_disable)(struct max96752f *max96752f);
35 };
36 
37 struct max96752f {
38 	struct udevice *dev;
39 	struct udevice *serializer;
40 	struct udevice *backlight;
41 
42 	const struct panel_desc *desc;
43 };
44 
max96752f_panel_prepare(struct rockchip_panel * panel)45 static void max96752f_panel_prepare(struct rockchip_panel *panel)
46 {
47 	struct max96752f *max96752f = dev_get_priv(panel->dev);
48 	const struct panel_desc *desc = max96752f->desc;
49 
50 	if (desc->prepare)
51 		desc->prepare(max96752f);
52 }
53 
max96752f_panel_unprepare(struct rockchip_panel * panel)54 static void max96752f_panel_unprepare(struct rockchip_panel *panel)
55 {
56 	struct max96752f *max96752f = dev_get_priv(panel->dev);
57 	const struct panel_desc *desc = max96752f->desc;
58 
59 	if (desc->unprepare)
60 		desc->unprepare(max96752f);
61 }
62 
max96752f_panel_enable(struct rockchip_panel * panel)63 static void max96752f_panel_enable(struct rockchip_panel *panel)
64 {
65 	struct max96752f *max96752f = dev_get_priv(panel->dev);
66 	const struct panel_desc *desc = max96752f->desc;
67 
68 	if (desc->enable)
69 		desc->enable(max96752f);
70 
71 	if (max96752f->backlight)
72 		backlight_enable(max96752f->backlight);
73 
74 	if (desc->backlight_enable)
75 		desc->backlight_enable(max96752f);
76 }
77 
max96752f_panel_disable(struct rockchip_panel * panel)78 static void max96752f_panel_disable(struct rockchip_panel *panel)
79 {
80 	struct max96752f *max96752f = dev_get_priv(panel->dev);
81 	const struct panel_desc *desc = max96752f->desc;
82 
83 	if (desc->backlight_disable)
84 		desc->backlight_disable(max96752f);
85 
86 	if (max96752f->backlight)
87 		backlight_disable(max96752f->backlight);
88 
89 	if (desc->disable)
90 		desc->disable(max96752f);
91 }
92 
93 static const struct rockchip_panel_funcs max96752f_panel_funcs = {
94 	.prepare = max96752f_panel_prepare,
95 	.unprepare = max96752f_panel_unprepare,
96 	.enable = max96752f_panel_enable,
97 	.disable = max96752f_panel_disable,
98 };
99 
max96752f_probe(struct udevice * dev)100 static int max96752f_probe(struct udevice *dev)
101 {
102 	struct max96752f *max96752f = dev_get_priv(dev);
103 	struct rockchip_panel *panel;
104 	int ret;
105 
106 	ret = i2c_set_chip_offset_len(dev, 2);
107 	if (ret)
108 		return ret;
109 
110 	max96752f->dev = dev;
111 	max96752f->serializer = dev->parent->parent;
112 	max96752f->desc = (const struct panel_desc *)dev_get_driver_data(dev);
113 
114 	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
115 					   "backlight", &max96752f->backlight);
116 	if (ret && ret != -ENOENT) {
117 		dev_err(dev, "%s: Cannot get backlight: %d\n", __func__, ret);
118 		return ret;
119 	}
120 
121 	panel = calloc(1, sizeof(*panel));
122 	if (!panel)
123 		return -ENOMEM;
124 
125 	dev->driver_data = (ulong)panel;
126 	panel->dev = dev;
127 	panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
128 	panel->funcs = &max96752f_panel_funcs;
129 
130 	return 0;
131 }
132 
133 #define maxim_serializer_write(max96752f, reg, val) do {	\
134 		int ret;					\
135 		ret = dm_i2c_reg_write(max96752f->serializer,	\
136 				       reg, val);		\
137 		if (ret)					\
138 			return ret;				\
139 	} while (0)
140 
141 #define maxim_deserializer_write(max96752f, reg, val) do {	\
142 		int ret;					\
143 		ret = dm_i2c_reg_write(max96752f->dev,		\
144 				       reg, val);		\
145 		if (ret)					\
146 			return ret;				\
147 	} while (0)
148 
boe_av156fht_l83_panel_prepare(struct max96752f * max96752f)149 static int boe_av156fht_l83_panel_prepare(struct max96752f *max96752f)
150 {
151 	maxim_deserializer_write(max96752f, 0x0002, 0x43);
152 	maxim_deserializer_write(max96752f, 0x0140, 0x20);
153 
154 	maxim_deserializer_write(max96752f, 0x01ce, 0x5e);	/* oldi */
155 	maxim_deserializer_write(max96752f, 0x020c, 0x84);	/* bl_pwm */
156 	maxim_deserializer_write(max96752f, 0x0206, 0x83);	/* tp_int */
157 
158 	maxim_deserializer_write(max96752f, 0x0215, 0x90);	/* lcd_en */
159 	mdelay(20);
160 
161 	return 0;
162 }
163 
boe_av156fht_l83_panel_unprepare(struct max96752f * max96752f)164 static int boe_av156fht_l83_panel_unprepare(struct max96752f *max96752f)
165 {
166 	maxim_deserializer_write(max96752f, 0x0215, 0x80);	/* lcd_en */
167 
168 	return 0;
169 }
170 
boe_av156fht_l83_panel_enable(struct max96752f * max96752f)171 static int boe_av156fht_l83_panel_enable(struct max96752f *max96752f)
172 {
173 	maxim_deserializer_write(max96752f, 0x0227, 0x90);	/* lcd_rst */
174 	mdelay(20);
175 	maxim_deserializer_write(max96752f, 0x020f, 0x90);	/* tp_rst */
176 	mdelay(100);
177 	maxim_deserializer_write(max96752f, 0x0221, 0x90);	/* lcd_stb */
178 	mdelay(60);
179 	maxim_deserializer_write(max96752f, 0x0212, 0x90);	/* bl_current_ctl */
180 	maxim_deserializer_write(max96752f, 0x0209, 0x90);	/* bl_en */
181 
182 	return 0;
183 }
184 
boe_av156fht_l83_panel_disable(struct max96752f * max96752f)185 static int boe_av156fht_l83_panel_disable(struct max96752f *max96752f)
186 {
187 	maxim_deserializer_write(max96752f, 0x0209, 0x80);	/* bl_en */
188 	maxim_deserializer_write(max96752f, 0x0212, 0x80);	/* bl_current_ctl */
189 	maxim_deserializer_write(max96752f, 0x0221, 0x80);	/* lcd_stb */
190 	maxim_deserializer_write(max96752f, 0x020f, 0x80);	/* tp_rst */
191 	maxim_deserializer_write(max96752f, 0x0227, 0x80);	/* lcd_rst */
192 
193 	return 0;
194 }
195 
boe_av156fht_l83_panel_backlight_enable(struct max96752f * max96752f)196 static int boe_av156fht_l83_panel_backlight_enable(struct max96752f *max96752f)
197 {
198 	maxim_deserializer_write(max96752f, 0x0212, 0x90);	/* bl_current_ctl */
199 	maxim_deserializer_write(max96752f, 0x0209, 0x90);	/* bl_en */
200 
201 	return 0;
202 }
203 
boe_av156fht_l83_panel_backlight_disable(struct max96752f * max96752f)204 static int boe_av156fht_l83_panel_backlight_disable(struct max96752f *max96752f)
205 {
206 	maxim_deserializer_write(max96752f, 0x0209, 0x80);	/* bl_en */
207 	maxim_deserializer_write(max96752f, 0x0212, 0x80);	/* bl_current_ctl */
208 
209 	return 0;
210 }
211 
212 static const struct panel_desc boe_av156fht_l83 = {
213 	.name			= "boe-av156fht-l83",
214 	.prepare		= boe_av156fht_l83_panel_prepare,
215 	.unprepare		= boe_av156fht_l83_panel_unprepare,
216 	.enable			= boe_av156fht_l83_panel_enable,
217 	.disable		= boe_av156fht_l83_panel_disable,
218 	.backlight_enable	= boe_av156fht_l83_panel_backlight_enable,
219 	.backlight_disable	= boe_av156fht_l83_panel_backlight_disable,
220 };
221 
hannstar_hsd123jpw3_a15_prepare(struct max96752f * max96752f)222 static int hannstar_hsd123jpw3_a15_prepare(struct max96752f *max96752f)
223 {
224 	maxim_deserializer_write(max96752f, 0x0002, 0x43);
225 	maxim_deserializer_write(max96752f, 0x0140, 0x20);
226 	maxim_deserializer_write(max96752f, 0x01ce, 0x5e);
227 
228 	maxim_deserializer_write(max96752f, 0x0203, 0x83);	/* GPIO1  <- TP_INT */
229 	maxim_deserializer_write(max96752f, 0x0206, 0x84);      /* GPIO2  -> TP_RST */
230 	maxim_deserializer_write(max96752f, 0x0224, 0x84);	/* GPIO12 -> LCD_BL_PWM */
231 
232 	return 0;
233 }
234 
hannstar_hsd123jpw3_a15_unprepare(struct max96752f * max96752f)235 static int hannstar_hsd123jpw3_a15_unprepare(struct max96752f *max96752f)
236 {
237 	return 0;
238 }
239 
hannstar_hsd123jpw3_a15_enable(struct max96752f * max96752f)240 static int hannstar_hsd123jpw3_a15_enable(struct max96752f *max96752f)
241 {
242 	maxim_deserializer_write(max96752f, 0x0221, 0x10);	/* GPIO11 -> LCD_RESET */
243 	mdelay(20);
244 
245 	return 0;
246 }
247 
hannstar_hsd123jpw3_a15_disable(struct max96752f * max96752f)248 static int hannstar_hsd123jpw3_a15_disable(struct max96752f *max96752f)
249 {
250 	maxim_deserializer_write(max96752f, 0x0221, 0x00);	/* GPIO11 -> LCD_RESET */
251 	mdelay(20);
252 
253 	return 0;
254 }
255 
256 static const struct panel_desc hannstar_hsd123jpw3_a15 = {
257 	.name			= "hannstar,hsd123jpw3-a15",
258 	.prepare		= hannstar_hsd123jpw3_a15_prepare,
259 	.unprepare		= hannstar_hsd123jpw3_a15_unprepare,
260 	.enable			= hannstar_hsd123jpw3_a15_enable,
261 	.disable		= hannstar_hsd123jpw3_a15_disable,
262 };
263 
ogm_101fhbllm01_prepare(struct max96752f * max96752f)264 static int ogm_101fhbllm01_prepare(struct max96752f *max96752f)
265 {
266 	maxim_deserializer_write(max96752f, 0x01ce, 0x5e);
267 
268 	maxim_deserializer_write(max96752f, 0x0203, 0x84);	/* GPIO1 -> BL_PWM */
269 	maxim_deserializer_write(max96752f, 0x0206, 0x84);	/* GPIO2 -> TP_RST */
270 	maxim_deserializer_write(max96752f, 0x0209, 0x83);	/* GPIO3 <- TP_INT */
271 
272 	maxim_deserializer_write(max96752f, 0x0001, 0x02);
273 
274 	return 0;
275 }
276 
ogm_101fhbllm01_unprepare(struct max96752f * max96752f)277 static int ogm_101fhbllm01_unprepare(struct max96752f *max96752f)
278 {
279 	maxim_deserializer_write(max96752f, 0x0001, 0x01);
280 
281 	return 0;
282 }
283 
284 static const struct panel_desc ogm_101fhbllm01 = {
285 	.name			= "ogm,101fhbllm01",
286 	.prepare		= ogm_101fhbllm01_prepare,
287 	.unprepare		= ogm_101fhbllm01_unprepare,
288 };
289 
290 static const struct udevice_id max96752f_of_match[] = {
291 	{ .compatible = "boe,av156fht-l83", .data = (ulong)&boe_av156fht_l83 },
292 	{ .compatible = "hannstar,hsd123jpw3-a15", .data = (ulong)&hannstar_hsd123jpw3_a15 },
293 	{ .compatible = "ogm,101fhbllm01", .data = (ulong)&ogm_101fhbllm01 },
294 	{}
295 };
296 
297 U_BOOT_DRIVER(max96752f) = {
298 	.name = "max96752f",
299 	.id = UCLASS_PANEL,
300 	.of_match = max96752f_of_match,
301 	.probe = max96752f_probe,
302 	.priv_auto_alloc_size = sizeof(struct max96752f),
303 };
304