1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <errno.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <max96755f.h>
11*4882a593Smuzhiyun #include <video_bridge.h>
12*4882a593Smuzhiyun #include <drm/drm_mipi_dsi.h>
13*4882a593Smuzhiyun #include <dm/of_access.h>
14*4882a593Smuzhiyun #include <linux/media-bus-format.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "rockchip_bridge.h"
17*4882a593Smuzhiyun #include "rockchip_display.h"
18*4882a593Smuzhiyun #include "rockchip_panel.h"
19*4882a593Smuzhiyun
max96755f_mipi_dsi_rx_config(struct max96755f_priv * priv)20*4882a593Smuzhiyun static void max96755f_mipi_dsi_rx_config(struct max96755f_priv *priv)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun struct drm_display_mode *mode = &priv->mode;
23*4882a593Smuzhiyun u32 hfp, hsa, hbp, hact;
24*4882a593Smuzhiyun u32 vact, vsa, vfp, vbp;
25*4882a593Smuzhiyun u8 lane_map;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun dm_i2c_reg_clrset(priv->dev, 0x0331, NUM_LANES,
28*4882a593Smuzhiyun FIELD_PREP(NUM_LANES, priv->num_lanes - 1));
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun lane_map = (priv->dsi_lane_map[0] & 0xff) << 4 |
31*4882a593Smuzhiyun (priv->dsi_lane_map[1] & 0xff) << 6 |
32*4882a593Smuzhiyun (priv->dsi_lane_map[2] & 0xff) << 0 |
33*4882a593Smuzhiyun (priv->dsi_lane_map[3] & 0xff) << 2;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x0332, lane_map);
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun if (!priv->dpi_deskew_en)
38*4882a593Smuzhiyun return;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun vact = mode->vdisplay;
41*4882a593Smuzhiyun vsa = mode->vsync_end - mode->vsync_start;
42*4882a593Smuzhiyun vfp = mode->vsync_start - mode->vdisplay;
43*4882a593Smuzhiyun vbp = mode->vtotal - mode->vsync_end;
44*4882a593Smuzhiyun hact = mode->hdisplay;
45*4882a593Smuzhiyun hsa = mode->hsync_end - mode->hsync_start;
46*4882a593Smuzhiyun hfp = mode->hsync_start - mode->hdisplay;
47*4882a593Smuzhiyun hbp = mode->htotal - mode->hsync_end;
48*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03A4, 0xc1);
49*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x0385, FIELD_PREP(DPI_HSYNC_WIDTH_L, hsa));
50*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x0386, FIELD_PREP(DPI_VYSNC_WIDTH_L, vsa));
51*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x0387,
52*4882a593Smuzhiyun FIELD_PREP(DPI_VSYNC_WIDTH_H, (vsa >> 8)) |
53*4882a593Smuzhiyun FIELD_PREP(DPI_HSYNC_WIDTH_H, (hsa >> 8)));
54*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03a5, FIELD_PREP(DPI_VFP_L, vfp));
55*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03a6,
56*4882a593Smuzhiyun FIELD_PREP(DPI_VBP_L, vbp) |
57*4882a593Smuzhiyun FIELD_PREP(DPI_VFP_H, (vfp >> 8)));
58*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03a7, FIELD_PREP(DPI_VBP_H, (vbp >> 4)));
59*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03a8, FIELD_PREP(DPI_VACT_L, vact));
60*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03a9, FIELD_PREP(DPI_VACT_H, (vact >> 8)));
61*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03aa, FIELD_PREP(DPI_HFP_L, hfp));
62*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03ab,
63*4882a593Smuzhiyun FIELD_PREP(DPI_HBP_L, hbp) |
64*4882a593Smuzhiyun FIELD_PREP(DPI_HFP_H, (hfp >> 7)));
65*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03ac, FIELD_PREP(DPI_HBP_H, (hbp >> 4)));
66*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03ad, FIELD_PREP(DPI_HACT_L, hact));
67*4882a593Smuzhiyun dm_i2c_reg_write(priv->dev, 0x03ae, FIELD_PREP(DPI_HACT_H, (hact >> 8)));
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
max96755f_bridge_enable(struct rockchip_bridge * bridge)70*4882a593Smuzhiyun static void max96755f_bridge_enable(struct rockchip_bridge *bridge)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct udevice *dev = bridge->dev;
73*4882a593Smuzhiyun struct max96755f_priv *priv = dev_get_priv(dev->parent);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun max96755f_mipi_dsi_rx_config(priv);
76*4882a593Smuzhiyun if (priv->split_mode) {
77*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0010,
78*4882a593Smuzhiyun RESET_ONESHOT | AUTO_LINK | LINK_CFG,
79*4882a593Smuzhiyun FIELD_PREP(RESET_ONESHOT, 1) |
80*4882a593Smuzhiyun FIELD_PREP(AUTO_LINK, 0) |
81*4882a593Smuzhiyun FIELD_PREP(LINK_CFG, SPLITTER_MODE));
82*4882a593Smuzhiyun mdelay(50);
83*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0053,
84*4882a593Smuzhiyun TX_SPLIT_MASK_B | TX_SPLIT_MASK_A | TX_STR_SEL,
85*4882a593Smuzhiyun FIELD_PREP(TX_SPLIT_MASK_B, 0) |
86*4882a593Smuzhiyun FIELD_PREP(TX_SPLIT_MASK_A, 1) |
87*4882a593Smuzhiyun FIELD_PREP(TX_STR_SEL, 0));
88*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0057,
89*4882a593Smuzhiyun TX_SPLIT_MASK_B | TX_SPLIT_MASK_A | TX_STR_SEL,
90*4882a593Smuzhiyun FIELD_PREP(TX_SPLIT_MASK_B, 1) |
91*4882a593Smuzhiyun FIELD_PREP(TX_SPLIT_MASK_A, 0) |
92*4882a593Smuzhiyun FIELD_PREP(TX_STR_SEL, 1));
93*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x032a,
94*4882a593Smuzhiyun DV_SWP_AB | DV_CONV | DV_SPL | DV_EN,
95*4882a593Smuzhiyun FIELD_PREP(DV_SWP_AB, priv->dv_swp_ab) |
96*4882a593Smuzhiyun FIELD_PREP(DV_CONV, 1) |
97*4882a593Smuzhiyun FIELD_PREP(DV_SPL, 1) |
98*4882a593Smuzhiyun FIELD_PREP(DV_EN, 1));
99*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0311,
100*4882a593Smuzhiyun START_PORTAX | START_PORTAY,
101*4882a593Smuzhiyun FIELD_PREP(START_PORTAX, 1) |
102*4882a593Smuzhiyun FIELD_PREP(START_PORTAY, 1));
103*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0002,
104*4882a593Smuzhiyun VID_TX_EN_X | VID_TX_EN_Y,
105*4882a593Smuzhiyun FIELD_PREP(VID_TX_EN_X, 1) |
106*4882a593Smuzhiyun FIELD_PREP(VID_TX_EN_Y, 1));
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun } else {
109*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0002, VID_TX_EN_X,
110*4882a593Smuzhiyun FIELD_PREP(VID_TX_EN_X, 1));
111*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0311, START_PORTAX,
112*4882a593Smuzhiyun FIELD_PREP(START_PORTAX, 1));
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0010, RESET_ONESHOT,
116*4882a593Smuzhiyun FIELD_PREP(RESET_ONESHOT, 1));
117*4882a593Smuzhiyun mdelay(100);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
max96755f_bridge_disable(struct rockchip_bridge * bridge)120*4882a593Smuzhiyun static void max96755f_bridge_disable(struct rockchip_bridge *bridge)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun struct udevice *dev = bridge->dev;
123*4882a593Smuzhiyun struct max96755f_priv *priv = dev_get_priv(dev->parent);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0002, VID_TX_EN_X,
126*4882a593Smuzhiyun FIELD_PREP(VID_TX_EN_X, 0));
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun if (priv->split_mode)
129*4882a593Smuzhiyun dm_i2c_reg_clrset(dev->parent, 0x0010,
130*4882a593Smuzhiyun AUTO_LINK | LINK_CFG,
131*4882a593Smuzhiyun FIELD_PREP(AUTO_LINK, 0) |
132*4882a593Smuzhiyun FIELD_PREP(LINK_CFG, LINKA));
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
max96755f_bridge_mode_set(struct rockchip_bridge * bridge,const struct drm_display_mode * mode)135*4882a593Smuzhiyun static void max96755f_bridge_mode_set(struct rockchip_bridge *bridge,
136*4882a593Smuzhiyun const struct drm_display_mode *mode)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun struct udevice *dev = bridge->dev;
139*4882a593Smuzhiyun struct max96755f_priv *priv = dev_get_priv(dev->parent);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun memcpy(&priv->mode, mode, sizeof(struct drm_display_mode));
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
max96755f_bridge_detect(struct rockchip_bridge * bridge)144*4882a593Smuzhiyun static bool max96755f_bridge_detect(struct rockchip_bridge *bridge)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun struct max96755f_priv *priv = dev_get_priv(bridge->dev->parent);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (!dm_gpio_get_value(&priv->lock_gpio))
149*4882a593Smuzhiyun return false;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun return true;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun static const struct rockchip_bridge_funcs max96755f_bridge_funcs = {
155*4882a593Smuzhiyun .enable = max96755f_bridge_enable,
156*4882a593Smuzhiyun .disable = max96755f_bridge_disable,
157*4882a593Smuzhiyun .mode_set = max96755f_bridge_mode_set,
158*4882a593Smuzhiyun .detect = max96755f_bridge_detect,
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun
max96755f_bridge_bind(struct udevice * dev)161*4882a593Smuzhiyun static int max96755f_bridge_bind(struct udevice *dev)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun struct mipi_dsi_device *device = dev_get_platdata(dev);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun device->dev = dev;
166*4882a593Smuzhiyun device->lanes = dev_read_u32_default(dev, "dsi,lanes", 4);
167*4882a593Smuzhiyun device->format = dev_read_u32_default(dev, "dsi,format",
168*4882a593Smuzhiyun MIPI_DSI_FMT_RGB888);
169*4882a593Smuzhiyun device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
170*4882a593Smuzhiyun device->channel = dev_read_u32_default(dev, "reg", 0);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
max96755f_bridge_probe(struct udevice * dev)175*4882a593Smuzhiyun static int max96755f_bridge_probe(struct udevice *dev)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun struct rockchip_bridge *bridge;
178*4882a593Smuzhiyun struct max96755f_priv *priv = dev_get_priv(dev->parent);
179*4882a593Smuzhiyun const struct device_node *np = ofnode_to_np(dev->node);
180*4882a593Smuzhiyun int i, len, ret;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun bridge = calloc(1, sizeof(*bridge));
183*4882a593Smuzhiyun if (!bridge)
184*4882a593Smuzhiyun return -ENOMEM;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun dev->driver_data = (ulong)bridge;
187*4882a593Smuzhiyun bridge->dev = dev;
188*4882a593Smuzhiyun bridge->funcs = &max96755f_bridge_funcs;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun priv->num_lanes = dev_read_u32_default(dev, "dsi,lanes", 4);
191*4882a593Smuzhiyun priv->dv_swp_ab = dev_read_bool(dev, "vd-swap-ab");
192*4882a593Smuzhiyun priv->dpi_deskew_en = dev_read_bool(dev, "dpi-deskew-en");
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun for ( i = 0; i < priv->num_lanes; i++)
195*4882a593Smuzhiyun priv->dsi_lane_map[i] = i;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (of_find_property(np, "maxim,dsi-lane-map", &len)) {
198*4882a593Smuzhiyun len /= sizeof(u32);
199*4882a593Smuzhiyun if (priv->num_lanes != len) {
200*4882a593Smuzhiyun printf("invalid number of lane map\n");
201*4882a593Smuzhiyun return -EINVAL;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun ret = of_read_u32_array(np, "maxim,dsi-lane-map",
206*4882a593Smuzhiyun priv->dsi_lane_map, priv->num_lanes);
207*4882a593Smuzhiyun if (ret) {
208*4882a593Smuzhiyun printf("get dsi lane map failed\n");
209*4882a593Smuzhiyun return -EINVAL;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun ret = gpio_request_by_name(dev, "lock-gpios", 0, &priv->lock_gpio,
213*4882a593Smuzhiyun GPIOD_IS_IN);
214*4882a593Smuzhiyun if (ret) {
215*4882a593Smuzhiyun dev_err(dev, "failed to get lock GPIO: %d\n", ret);
216*4882a593Smuzhiyun return ret;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun static const struct udevice_id max96755f_bridge_of_match[] = {
223*4882a593Smuzhiyun { .compatible = "maxim,max96755f-bridge", },
224*4882a593Smuzhiyun { }
225*4882a593Smuzhiyun };
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun U_BOOT_DRIVER(max96755f_bridge) = {
228*4882a593Smuzhiyun .name = "max96755f_bridge",
229*4882a593Smuzhiyun .id = UCLASS_VIDEO_BRIDGE,
230*4882a593Smuzhiyun .of_match = max96755f_bridge_of_match,
231*4882a593Smuzhiyun .probe = max96755f_bridge_probe,
232*4882a593Smuzhiyun .bind = max96755f_bridge_bind,
233*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device),
234*4882a593Smuzhiyun };
235