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
serdes_bridge_init(struct serdes * serdes)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
serdes_bridge_pre_enable(struct rockchip_bridge * bridge)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
serdes_bridge_post_disable(struct rockchip_bridge * bridge)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
serdes_bridge_enable(struct rockchip_bridge * bridge)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
serdes_bridge_disable(struct rockchip_bridge * bridge)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
serdes_bridge_mode_set(struct rockchip_bridge * bridge,const struct drm_display_mode * mode)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
serdes_bridge_detect(struct rockchip_bridge * bridge)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",
111 serdes->dev->name);
112 return ret;
113 }
114
115 if (serdes->chip_data->bridge_ops->detect)
116 ret = serdes->chip_data->bridge_ops->detect(serdes, SER_LINKA);
117
118 SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name,
119 serdes->chip_data->name, (ret == true) ? "detected" : "no detected");
120
121 return ret;
122 }
123
124 struct rockchip_bridge_funcs serdes_bridge_ops = {
125 .pre_enable = serdes_bridge_pre_enable,
126 .post_disable = serdes_bridge_post_disable,
127 .enable = serdes_bridge_enable,
128 .disable = serdes_bridge_disable,
129 .mode_set = serdes_bridge_mode_set,
130 .detect = serdes_bridge_detect,
131 };
132
serdes_bridge_probe(struct udevice * dev)133 static int serdes_bridge_probe(struct udevice *dev)
134 {
135 struct rockchip_bridge *bridge;
136 struct serdes *serdes = dev_get_priv(dev->parent);
137 struct mipi_dsi_device *device = dev_get_platdata(dev);
138
139 if (!serdes->chip_data->bridge_ops) {
140 SERDES_DBG_MFD("%s %s no bridge ops\n",
141 __func__, serdes->chip_data->name);
142 return 0;
143 }
144
145 serdes->sel_mipi = dev_read_bool(dev->parent, "sel-mipi");
146 if (serdes->sel_mipi) {
147 device->dev = dev;
148 device->lanes = dev_read_u32_default(dev->parent, "dsi,lanes", 4);
149 device->format = dev_read_u32_default(dev->parent, "dsi,format",
150 MIPI_DSI_FMT_RGB888);
151 device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
152 device->channel = dev_read_u32_default(dev->parent, "reg", 0);
153 }
154
155 bridge = calloc(1, sizeof(*bridge));
156 if (!bridge)
157 return -ENOMEM;
158
159 dev->driver_data = (ulong)bridge;
160 bridge->dev = dev;
161 bridge->funcs = &serdes_bridge_ops;
162
163 serdes->serdes_bridge->bridge = bridge;
164
165 SERDES_DBG_MFD("%s: %s %s bridge=%p name=%s device=%p\n",
166 __func__, serdes->dev->name,
167 serdes->chip_data->name,
168 bridge, bridge->dev->name, device);
169
170 return 0;
171 }
172
173 static const struct udevice_id serdes_of_match[] = {
174 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82)
175 { .compatible = "rohm,bu18tl82-bridge", },
176 #endif
177 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82)
178 { .compatible = "rohm,bu18rl82-bridge", },
179 #endif
180 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745)
181 { .compatible = "maxim,max96745-bridge", },
182 #endif
183 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755)
184 { .compatible = "maxim,max96755-bridge", },
185 #endif
186 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755)
187 { .compatible = "maxim,max96789-bridge", },
188 #endif
189 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111)
190 { .compatible = "rockchip,rkx111-bridge", },
191 #endif
192 { }
193 };
194
195 U_BOOT_DRIVER(serdes_bridge) = {
196 .name = "serdes-bridge",
197 .id = UCLASS_VIDEO_BRIDGE,
198 .of_match = serdes_of_match,
199 .probe = serdes_bridge_probe,
200 .priv_auto_alloc_size = sizeof(struct serdes_bridge),
201 .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device),
202 };
203