xref: /rk3399_rockchip-uboot/drivers/video/drm/panel-maxim-max96752f.c (revision 17d5ed3ee9dbbcbae06ad3a291a8f61c3cde3d5b)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
222 static const struct udevice_id max96752f_of_match[] = {
223 	{ .compatible = "boe,av156fht-l83", .data = (ulong)&boe_av156fht_l83 },
224 	{}
225 };
226 
227 U_BOOT_DRIVER(max96752f) = {
228 	.name = "max96752f",
229 	.id = UCLASS_PANEL,
230 	.of_match = max96752f_of_match,
231 	.probe = max96752f_probe,
232 	.priv_auto_alloc_size = sizeof(struct max96752f),
233 };
234