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