xref: /rk3399_rockchip-uboot/drivers/video/drm/display-serdes/serdes-bridge.c (revision cf55f2e8d05973d6046c8006d83cc6dcf08c7b5d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * serdes-bridge.c  --  display bridge for different serdes chips
4  *
5  * Copyright (c) 2023 Rockchip Electronics Co. Ltd.
6  *
7  * Author: luowei <lw@rock-chips.com>
8  */
9 
10 #include "core.h"
11 
12 static void serdes_bridge_init(struct serdes *serdes)
13 {
14 	if (serdes->vpower_supply)
15 		regulator_set_enable(serdes->vpower_supply, true);
16 
17 	if (dm_gpio_is_valid(&serdes->enable_gpio))
18 		dm_gpio_set_value(&serdes->enable_gpio, 1);
19 
20 	mdelay(5);
21 
22 	//video_bridge_set_active(serdes->dev, true);
23 
24 	if (serdes->chip_data->bridge_ops->init)
25 		serdes->chip_data->bridge_ops->init(serdes);
26 
27 	serdes_i2c_set_sequence(serdes);
28 
29 	SERDES_DBG_MFD("%s: %s %s\n", __func__,
30 		       serdes->dev->name,
31 		       serdes->chip_data->name);
32 }
33 
34 static void serdes_bridge_pre_enable(struct rockchip_bridge *bridge)
35 {
36 	struct udevice *dev = bridge->dev;
37 	struct serdes *serdes = dev_get_priv(dev->parent);
38 
39 	//serdes_bridge_init(serdes);
40 
41 	if (serdes->chip_data->bridge_ops->pre_enable)
42 		serdes->chip_data->bridge_ops->pre_enable(serdes);
43 
44 	SERDES_DBG_MFD("%s: %s %s\n", __func__,
45 		       serdes->dev->name,
46 		       serdes->chip_data->name);
47 }
48 
49 static void serdes_bridge_post_disable(struct rockchip_bridge *bridge)
50 {
51 	struct udevice *dev = bridge->dev;
52 	struct serdes *serdes = dev_get_priv(dev->parent);
53 
54 	if (serdes->chip_data->bridge_ops->post_disable)
55 		serdes->chip_data->bridge_ops->post_disable(serdes);
56 
57 	SERDES_DBG_MFD("%s: %s %s\n", __func__,
58 		       serdes->dev->name,
59 		       serdes->chip_data->name);
60 }
61 
62 static void serdes_bridge_enable(struct rockchip_bridge *bridge)
63 {
64 	struct udevice *dev = bridge->dev;
65 	struct serdes *serdes = dev_get_priv(dev->parent);
66 
67 	if (serdes->chip_data->serdes_type == TYPE_DES)
68 		serdes_bridge_init(serdes);
69 
70 	if (serdes->chip_data->bridge_ops->enable)
71 		serdes->chip_data->bridge_ops->enable(serdes);
72 
73 	SERDES_DBG_MFD("%s: %s %s\n", __func__,
74 		       serdes->dev->name,
75 		       serdes->chip_data->name);
76 }
77 
78 static void serdes_bridge_disable(struct rockchip_bridge *bridge)
79 {
80 	struct udevice *dev = bridge->dev;
81 	struct serdes *serdes = dev_get_priv(dev->parent);
82 
83 	if (serdes->chip_data->bridge_ops->disable)
84 		serdes->chip_data->bridge_ops->disable(serdes);
85 
86 	SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name,
87 		       serdes->chip_data->name);
88 }
89 
90 static void serdes_bridge_mode_set(struct rockchip_bridge *bridge,
91 				   const struct drm_display_mode *mode)
92 {
93 	struct udevice *dev = bridge->dev;
94 	struct serdes *serdes = dev_get_priv(dev->parent);
95 
96 	memcpy(&serdes->serdes_bridge->mode, mode,
97 	       sizeof(struct drm_display_mode));
98 
99 	SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name,
100 		       serdes->chip_data->name);
101 }
102 
103 static bool serdes_bridge_detect(struct rockchip_bridge *bridge)
104 {
105 	bool ret = true;
106 	struct udevice *dev = bridge->dev;
107 	struct serdes *serdes = dev_get_priv(dev->parent);
108 
109 	if(serdes->mcu_enable) {
110 		printf("serdes %s detect link status in MCU\n", serdes->dev->name);
111 		return ret;
112 	}
113 
114 	if (serdes->chip_data->bridge_ops->detect)
115 		ret = serdes->chip_data->bridge_ops->detect(serdes, SER_LINKA);
116 
117 	SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name,
118 		       serdes->chip_data->name, (ret == true) ? "detected" : "no detected");
119 
120 	return ret;
121 }
122 
123 struct rockchip_bridge_funcs serdes_bridge_ops = {
124 	.pre_enable = serdes_bridge_pre_enable,
125 	.post_disable = serdes_bridge_post_disable,
126 	.enable = serdes_bridge_enable,
127 	.disable = serdes_bridge_disable,
128 	.mode_set = serdes_bridge_mode_set,
129 	.detect = serdes_bridge_detect,
130 };
131 
132 static int serdes_bridge_probe(struct udevice *dev)
133 {
134 	struct rockchip_bridge *bridge;
135 	struct serdes *serdes = dev_get_priv(dev->parent);
136 	struct mipi_dsi_device *device = dev_get_platdata(dev);
137 
138 	if (!serdes->chip_data->bridge_ops) {
139 		SERDES_DBG_MFD("%s %s no bridge ops\n",
140 			       __func__, serdes->chip_data->name);
141 		return 0;
142 	}
143 
144 	serdes->sel_mipi = dev_read_bool(dev->parent, "sel-mipi");
145 	if (serdes->sel_mipi) {
146 		device->dev = dev;
147 		device->lanes = dev_read_u32_default(dev->parent, "dsi,lanes", 4);
148 		device->format = dev_read_u32_default(dev->parent, "dsi,format",
149 						      MIPI_DSI_FMT_RGB888);
150 		device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
151 		device->channel = dev_read_u32_default(dev->parent, "reg", 0);
152 	}
153 
154 	bridge = calloc(1, sizeof(*bridge));
155 	if (!bridge)
156 		return -ENOMEM;
157 
158 	dev->driver_data = (ulong)bridge;
159 	bridge->dev = dev;
160 	bridge->funcs = &serdes_bridge_ops;
161 
162 	serdes->serdes_bridge->bridge = bridge;
163 
164 	SERDES_DBG_MFD("%s: %s %s bridge=%p name=%s device=%p\n",
165 		       __func__, serdes->dev->name,
166 		       serdes->chip_data->name,
167 		       bridge, bridge->dev->name, device);
168 
169 	return 0;
170 }
171 
172 static const struct udevice_id serdes_of_match[] = {
173 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82)
174 	{ .compatible = "rohm,bu18tl82-bridge",  },
175 #endif
176 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82)
177 	{ .compatible = "rohm,bu18rl82-bridge", },
178 #endif
179 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745)
180 	{ .compatible = "maxim,max96745-bridge", },
181 #endif
182 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755)
183 	{ .compatible = "maxim,max96755-bridge", },
184 #endif
185 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755)
186 	{ .compatible = "maxim,max96789-bridge", },
187 #endif
188 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111)
189 	{ .compatible = "rockchip,rkx111-bridge", },
190 #endif
191 	{ }
192 };
193 
194 U_BOOT_DRIVER(serdes_bridge) = {
195 	.name = "serdes-bridge",
196 	.id = UCLASS_VIDEO_BRIDGE,
197 	.of_match = serdes_of_match,
198 	.probe = serdes_bridge_probe,
199 	.priv_auto_alloc_size = sizeof(struct serdes_bridge),
200 	.platdata_auto_alloc_size = sizeof(struct mipi_dsi_device),
201 };
202