xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/panel-rohm-bu18rl82.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Rohm BU18RL82-based panel driver
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 bu18rl82;
26 
27 struct panel_desc {
28 	const char *name;
29 	int (*prepare)(struct bu18rl82 *rl82);
30 	int (*unprepare)(struct bu18rl82 *rl82);
31 	int (*enable)(struct bu18rl82 *rl82);
32 	int (*disable)(struct bu18rl82 *rl82);
33 	int (*backlight_enable)(struct bu18rl82 *rl82);
34 	int (*backlight_disable)(struct bu18rl82 *rl82);
35 };
36 
37 struct bu18rl82 {
38 	struct udevice *dev;
39 	struct udevice *backlight;
40 	const struct panel_desc *desc;
41 };
42 
bu18rl82_panel_prepare(struct rockchip_panel * panel)43 static void bu18rl82_panel_prepare(struct rockchip_panel *panel)
44 {
45 	struct bu18rl82 *rl82 = dev_get_priv(panel->dev);
46 	const struct panel_desc *desc = rl82->desc;
47 
48 	if (desc->prepare)
49 		desc->prepare(rl82);
50 }
51 
bu18rl82_panel_unprepare(struct rockchip_panel * panel)52 static void bu18rl82_panel_unprepare(struct rockchip_panel *panel)
53 {
54 	struct bu18rl82 *rl82 = dev_get_priv(panel->dev);
55 	const struct panel_desc *desc = rl82->desc;
56 
57 	if (desc->unprepare)
58 		desc->unprepare(rl82);
59 }
60 
bu18rl82_panel_enable(struct rockchip_panel * panel)61 static void bu18rl82_panel_enable(struct rockchip_panel *panel)
62 {
63 	struct bu18rl82 *rl82 = dev_get_priv(panel->dev);
64 	const struct panel_desc *desc = rl82->desc;
65 
66 	if (desc->enable)
67 		desc->enable(rl82);
68 
69 	if (rl82->backlight)
70 		backlight_enable(rl82->backlight);
71 
72 	if (desc->backlight_enable)
73 		desc->backlight_enable(rl82);
74 }
75 
bu18rl82_panel_disable(struct rockchip_panel * panel)76 static void bu18rl82_panel_disable(struct rockchip_panel *panel)
77 {
78 	struct bu18rl82 *rl82 = dev_get_priv(panel->dev);
79 	const struct panel_desc *desc = rl82->desc;
80 
81 	if (desc->backlight_disable)
82 		desc->backlight_disable(rl82);
83 
84 	if (rl82->backlight)
85 		backlight_disable(rl82->backlight);
86 
87 	if (desc->disable)
88 		desc->disable(rl82);
89 }
90 
91 static const struct rockchip_panel_funcs bu18rl82_panel_funcs = {
92 	.prepare = bu18rl82_panel_prepare,
93 	.unprepare = bu18rl82_panel_unprepare,
94 	.enable = bu18rl82_panel_enable,
95 	.disable = bu18rl82_panel_disable,
96 };
97 
bu18rl82_probe(struct udevice * dev)98 static int bu18rl82_probe(struct udevice *dev)
99 {
100 	struct bu18rl82 *rl82 = dev_get_priv(dev);
101 	struct rockchip_panel *panel;
102 	int ret;
103 
104 	ret = i2c_set_chip_offset_len(dev, 2);
105 	if (ret)
106 		return ret;
107 
108 	rl82->dev = dev;
109 	rl82->desc = (const struct panel_desc *)dev_get_driver_data(dev);
110 
111 	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
112 					   "backlight", &rl82->backlight);
113 	if (ret && ret != -ENOENT) {
114 		dev_err(dev, "%s: Cannot get backlight: %d\n", __func__, ret);
115 		return ret;
116 	}
117 
118 	panel = calloc(1, sizeof(*panel));
119 	if (!panel)
120 		return -ENOMEM;
121 
122 	dev->driver_data = (ulong)panel;
123 	panel->dev = dev;
124 	panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
125 	panel->funcs = &bu18rl82_panel_funcs;
126 
127 	return 0;
128 }
129 
130 #define rohm_deserializer_write(rl82, reg, val) do {			\
131 		int ret;						\
132 		ret = dm_i2c_reg_write(rl82->dev, reg, val);		\
133 		if (ret) {						\
134 			dev_err(rl82->dev,				\
135 				"failed to set register 0x%04x\n",	\
136 				reg);					\
137 			return ret;					\
138 		}							\
139 	} while (0)
140 
csot_mg1561b01_prepare(struct bu18rl82 * rl82)141 static int csot_mg1561b01_prepare(struct bu18rl82 *rl82)
142 {
143 	const struct reg_sequence {
144 		u16 reg;
145 		u8 def;
146 	} regs[] = {
147 		{ 0x0011, 0x03 }, { 0x0012, 0x03 },
148 		{ 0x001f, 0x02 }, { 0x0020, 0x02 },
149 		{ 0x0031, 0x41 }, { 0x0032, 0x41 },
150 		{ 0x0073, 0x80 }, { 0x0074, 0x07 },
151 		{ 0x007b, 0x38 }, { 0x007c, 0x04 },
152 		{ 0x0079, 0x0a },
153 		{ 0x0429, 0x0a }, { 0x045d, 0x01 },
154 		{ 0x0529, 0x0a }, { 0x055d, 0x01 },
155 		{ 0x060a, 0xb0 }, { 0x060b, 0xff }, { 0x060c, 0xff },
156 		{ 0x0644, 0x18 }, { 0x0645, 0x01 }, { 0x0646, 0x2d },
157 	};
158 	int i;
159 
160 	for (i = 0; i < ARRAY_SIZE(regs); i++)
161 		rohm_deserializer_write(rl82, regs[i].reg, regs[i].def);
162 
163 	/* BL_PWM - GPIO0 */
164 	rohm_deserializer_write(rl82, 0x0057, 0x00);
165 	rohm_deserializer_write(rl82, 0x0058, 0x02);
166 
167 	/* TP_INT - GPIO3 */
168 	rohm_deserializer_write(rl82, 0x0060, 0x08);
169 	rohm_deserializer_write(rl82, 0x042e, 0x05);
170 
171 	/* TP_RST - GPIO4 */
172 	rohm_deserializer_write(rl82, 0x0063, 0x00);
173 	rohm_deserializer_write(rl82, 0x0064, 0x01);
174 
175 	return 0;
176 }
177 
csot_mg1561b01_unprepare(struct bu18rl82 * rl82)178 static int csot_mg1561b01_unprepare(struct bu18rl82 *rl82)
179 {
180 	/* TP_RST - GPIO4 */
181 	rohm_deserializer_write(rl82, 0x0064, 0x00);
182 
183 	return 0;
184 }
185 
csot_mg1561b01_enable(struct bu18rl82 * rl82)186 static int csot_mg1561b01_enable(struct bu18rl82 *rl82)
187 {
188 	rohm_deserializer_write(rl82, 0x0091, 0x03);
189 	rohm_deserializer_write(rl82, 0x0090, 0x01);
190 
191 	return 0;
192 }
193 
csot_mg1561b01_disable(struct bu18rl82 * rl82)194 static int csot_mg1561b01_disable(struct bu18rl82 *rl82)
195 {
196 	rohm_deserializer_write(rl82, 0x0090, 0x00);
197 	rohm_deserializer_write(rl82, 0x0091, 0x00);
198 
199 	return 0;
200 }
201 
csot_mg1561b01_backlight_enable(struct bu18rl82 * rl82)202 static int csot_mg1561b01_backlight_enable(struct bu18rl82 *rl82)
203 {
204 	/* BL_EN - GPIO1 */
205 	rohm_deserializer_write(rl82, 0x005a, 0x00);
206 	rohm_deserializer_write(rl82, 0x005b, 0x01);
207 
208 	return 0;
209 }
210 
csot_mg1561b01_backlight_disable(struct bu18rl82 * rl82)211 static int csot_mg1561b01_backlight_disable(struct bu18rl82 *rl82)
212 {
213 	/* BL_EN - GPIO1 */
214 	rohm_deserializer_write(rl82, 0x005b, 0x00);
215 
216 	return 0;
217 }
218 
219 static const struct panel_desc csot_mg1561b01 = {
220 	.name			= "csot,mg1561b01",
221 	.prepare		= csot_mg1561b01_prepare,
222 	.unprepare		= csot_mg1561b01_unprepare,
223 	.enable			= csot_mg1561b01_enable,
224 	.disable		= csot_mg1561b01_disable,
225 	.backlight_enable	= csot_mg1561b01_backlight_enable,
226 	.backlight_disable	= csot_mg1561b01_backlight_disable,
227 };
228 
touch_china_v123awf3_r1_prepare(struct bu18rl82 * rl82)229 static int touch_china_v123awf3_r1_prepare(struct bu18rl82 *rl82)
230 {
231 	const struct reg_sequence {
232 		u16 reg;
233 		u8 def;
234 	} regs[] = {
235 		{ 0x0011, 0x03 }, { 0x0012, 0x03 },
236 		{ 0x001f, 0x02 }, { 0x0020, 0x02 },
237 		{ 0x0031, 0x48 }, { 0x0032, 0x48 },
238 		{ 0x0073, 0x80 }, { 0x0074, 0x07 },
239 		{ 0x007b, 0xd0 }, { 0x007c, 0x02 },
240 		{ 0x0079, 0x0a },
241 		{ 0x0429, 0x0a }, { 0x045d, 0x01 },
242 		{ 0x0529, 0x0a }, { 0x055d, 0x01 },
243 		{ 0x060a, 0xb0 }, { 0x060b, 0xff }, { 0x060c, 0xff },
244 		{ 0x0644, 0x90 }, { 0x0646, 0xd2 },
245 	};
246 	int i;
247 
248 	for (i = 0; i < ARRAY_SIZE(regs); i++)
249 		rohm_deserializer_write(rl82, regs[i].reg, regs[i].def);
250 
251 	/* TP_INT - GPIO4 */
252 	rohm_deserializer_write(rl82, 0x0063, 0x08);
253 	rohm_deserializer_write(rl82, 0x042f, 0x06);
254 
255 	/* TP_RST - GPIO3 */
256 	rohm_deserializer_write(rl82, 0x0060, 0x00);
257 	rohm_deserializer_write(rl82, 0x0061, 0x00);
258 
259 	/* LCD_BIAS_EN - GPIO2 */
260 	rohm_deserializer_write(rl82, 0x005d, 0x00);
261 	rohm_deserializer_write(rl82, 0x005e, 0x01);
262 	mdelay(6);
263 
264 	return 0;
265 }
266 
touch_china_v123awf3_r1_unprepare(struct bu18rl82 * rl82)267 static int touch_china_v123awf3_r1_unprepare(struct bu18rl82 *rl82)
268 {
269 	/* LCD_BIAS_EN - GPIO2 */
270 	rohm_deserializer_write(rl82, 0x005e, 0x00);
271 
272 	return 0;
273 }
274 
touch_china_v123awf3_r1_enable(struct bu18rl82 * rl82)275 static int touch_china_v123awf3_r1_enable(struct bu18rl82 *rl82)
276 {
277 	rohm_deserializer_write(rl82, 0x0091, 0x03);
278 	rohm_deserializer_write(rl82, 0x0090, 0x01);
279 
280 	/* RSEX - GPIO5 */
281 	rohm_deserializer_write(rl82, 0x0066, 0x00);
282 	rohm_deserializer_write(rl82, 0x0067, 0x01);
283 	/* TP_RST - GPIO3 */
284 	rohm_deserializer_write(rl82, 0x0060, 0x00);
285 	rohm_deserializer_write(rl82, 0x0061, 0x01);
286 	mdelay(20);
287 	/* LCD_PON - GPIO1 */
288 	rohm_deserializer_write(rl82, 0x005a, 0x00);
289 	rohm_deserializer_write(rl82, 0x005b, 0x01);
290 
291 	return 0;
292 }
293 
touch_china_v123awf3_r1_disable(struct bu18rl82 * rl82)294 static int touch_china_v123awf3_r1_disable(struct bu18rl82 *rl82)
295 {
296 	rohm_deserializer_write(rl82, 0x0090, 0x00);
297 	rohm_deserializer_write(rl82, 0x0091, 0x00);
298 
299 	/* LCD_PON - GPIO1 */
300 	rohm_deserializer_write(rl82, 0x005b, 0x00);
301 	mdelay(100);
302 	/* TP_RST - GPIO3 */
303 	rohm_deserializer_write(rl82, 0x0061, 0x00);
304 	/* RSEX - GPIO5 */
305 	rohm_deserializer_write(rl82, 0x0067, 0x00);
306 
307 	return 0;
308 }
309 
touch_china_v123awf3_r1_backlight_enable(struct bu18rl82 * rl82)310 static int touch_china_v123awf3_r1_backlight_enable(struct bu18rl82 *rl82)
311 {
312 	/* BL_PWM - GPIO0 */
313 	rohm_deserializer_write(rl82, 0x0057, 0x00);
314 	rohm_deserializer_write(rl82, 0x0058, 0x02);
315 
316 	return 0;
317 }
318 
touch_china_v123awf3_r1_backlight_disable(struct bu18rl82 * rl82)319 static int touch_china_v123awf3_r1_backlight_disable(struct bu18rl82 *rl82)
320 {
321 	/* BL_PWM - GPIO0 */
322 	rohm_deserializer_write(rl82, 0x0058, 0x00);
323 
324 	return 0;
325 }
326 
327 static const struct panel_desc touch_china_v123awf3_r1 = {
328 	.name			= "touch-china,v123awf3-r1",
329 	.prepare		= touch_china_v123awf3_r1_prepare,
330 	.unprepare		= touch_china_v123awf3_r1_unprepare,
331 	.enable			= touch_china_v123awf3_r1_enable,
332 	.disable		= touch_china_v123awf3_r1_disable,
333 	.backlight_enable	= touch_china_v123awf3_r1_backlight_enable,
334 	.backlight_disable	= touch_china_v123awf3_r1_backlight_disable,
335 };
336 
337 static const struct udevice_id bu18rl82_of_match[] = {
338 	{ .compatible = "csot,mg1561b01", .data = (ulong)&csot_mg1561b01 },
339 	{ .compatible = "touch-china,v123awf3-r1", .data = (ulong)&touch_china_v123awf3_r1 },
340 	{}
341 };
342 
343 U_BOOT_DRIVER(panel_rohm_bu18rl82) = {
344 	.name = "panel-rohm-bu18rl82",
345 	.id = UCLASS_PANEL,
346 	.of_match = bu18rl82_of_match,
347 	.probe = bu18rl82_probe,
348 	.priv_auto_alloc_size = sizeof(struct bu18rl82),
349 };
350