xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/max96745.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <max96745.h>
11 #include <video_bridge.h>
12 #include <linux/iopoll.h>
13 
14 #include "rockchip_bridge.h"
15 #include "rockchip_display.h"
16 #include "rockchip_panel.h"
17 
max96745_bridge_link_locked(struct udevice * dev)18 static bool max96745_bridge_link_locked(struct udevice *dev)
19 {
20 	int ret;
21 
22 	ret = dm_i2c_reg_read(dev->parent, 0x002a);
23 	if (ret < 0)
24 		return false;
25 
26 	if (!FIELD_GET(LINK_LOCKED, ret))
27 		return false;
28 
29 	return true;
30 }
31 
max96745_bridge_detect(struct rockchip_bridge * bridge)32 static bool max96745_bridge_detect(struct rockchip_bridge *bridge)
33 {
34 	return max96745_bridge_link_locked(bridge->dev);
35 }
36 
max96745_bridge_enable(struct rockchip_bridge * bridge)37 static void max96745_bridge_enable(struct rockchip_bridge *bridge)
38 {
39 	struct udevice *dev = bridge->dev;
40 	struct drm_display_mode *mode = &bridge->state->conn_state.mode;
41 	u8 cxtp, tx_rate;
42 	int ret;
43 
44 	ret = dm_i2c_reg_read(dev->parent, 0x0011);
45 	if (ret < 0)
46 		return;
47 
48 	cxtp = FIELD_GET(CXTP_A, ret);
49 
50 	ret = dm_i2c_reg_read(dev->parent, 0x0028);
51 	if (ret < 0)
52 		return;
53 
54 	tx_rate = FIELD_GET(TX_RATE, ret);
55 
56 	if (!cxtp && mode->clock > 95000 && tx_rate == 1) {
57 		ret = dm_i2c_reg_clrset(dev->parent, 0x0028, TX_RATE,
58 					FIELD_PREP(TX_RATE, 2));
59 		if (ret < 0)
60 			return;
61 
62 		ret = dm_i2c_reg_clrset(dev->parent, 0x0029, RESET_ONESHOT,
63 					FIELD_PREP(RESET_ONESHOT, 1));
64 		if (ret < 0)
65 			return;
66 
67 		if (readx_poll_timeout(max96745_bridge_link_locked, dev, ret,
68 				       ret, 200000))
69 			dev_err(dev, "%s: GMSL link not locked\n", __func__);
70 	}
71 }
72 
max96745_bridge_post_disable(struct rockchip_bridge * bridge)73 static void max96745_bridge_post_disable(struct rockchip_bridge *bridge)
74 {
75 	struct udevice *dev = bridge->dev;
76 	u8 cxtp, tx_rate;
77 	int ret;
78 
79 	ret = dm_i2c_reg_read(dev->parent, 0x0011);
80 	if (ret < 0)
81 		return;
82 
83 	cxtp = FIELD_GET(CXTP_A, ret);
84 
85 	ret = dm_i2c_reg_read(dev->parent, 0x0028);
86 	if (ret < 0)
87 		return;
88 
89 	tx_rate = FIELD_GET(TX_RATE, ret);
90 
91 	if (!cxtp && tx_rate == 2) {
92 		ret = dm_i2c_reg_clrset(dev->parent, 0x0028, TX_RATE,
93 					FIELD_PREP(TX_RATE, 1));
94 		if (ret < 0)
95 			return;
96 
97 		ret = dm_i2c_reg_clrset(dev->parent, 0x0029, RESET_ONESHOT,
98 					FIELD_PREP(RESET_ONESHOT, 1));
99 		if (ret < 0)
100 			return;
101 
102 		if (readx_poll_timeout(max96745_bridge_link_locked, dev, ret,
103 				       ret, 200000))
104 			dev_err(dev, "%s: GMSL link not locked\n", __func__);
105 	}
106 }
107 
108 static const struct rockchip_bridge_funcs max96745_bridge_funcs = {
109 	.detect		= max96745_bridge_detect,
110 	.enable		= max96745_bridge_enable,
111 	.post_disable	= max96745_bridge_post_disable,
112 };
113 
max96745_bridge_probe(struct udevice * dev)114 static int max96745_bridge_probe(struct udevice *dev)
115 {
116 	struct rockchip_bridge *bridge;
117 
118 	bridge = calloc(1, sizeof(*bridge));
119 	if (!bridge)
120 		return -ENOMEM;
121 
122 	dev->driver_data = (ulong)bridge;
123 	bridge->dev = dev;
124 	bridge->funcs = &max96745_bridge_funcs;
125 
126 	return 0;
127 }
128 
129 static const struct udevice_id max96745_bridge_of_match[] = {
130 	{ .compatible = "maxim,max96745-bridge", },
131 	{ }
132 };
133 
134 U_BOOT_DRIVER(max96745_bridge) = {
135 	.name = "max96745_bridge",
136 	.id = UCLASS_VIDEO_BRIDGE,
137 	.of_match = max96745_bridge_of_match,
138 	.probe = max96745_bridge_probe,
139 };
140