1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Maxim MAX96745 GMSL2 Serializer with eDP1.4a/DP1.4 Input
4 *
5 * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
6 */
7
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_bridge.h>
10 #include <drm/drm_panel.h>
11 #include <drm/drm_print.h>
12 #include <drm/drm_of.h>
13 #include <drm/drm_connector.h>
14 #include <drm/drm_probe_helper.h>
15
16 #include <linux/irq.h>
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/platform_device.h>
20 #include <linux/err.h>
21 #include <linux/extcon-provider.h>
22 #include <linux/of.h>
23 #include <linux/regmap.h>
24 #include <linux/gpio/consumer.h>
25 #include <linux/mfd/max96745.h>
26
27 struct max96745_bridge {
28 struct drm_bridge bridge;
29 struct drm_panel *panel;
30 enum drm_connector_status status;
31
32 struct device *dev;
33 struct max96745 *parent;
34 struct regmap *regmap;
35 struct {
36 struct gpio_desc *gpio;
37 int irq;
38 atomic_t triggered;
39 } lock;
40 };
41
42 #define to_max96745_bridge(x) container_of(x, struct max96745_bridge, x)
43
max96745_bridge_link_locked(struct max96745_bridge * ser)44 static bool max96745_bridge_link_locked(struct max96745_bridge *ser)
45 {
46 u32 val;
47
48 if (ser->lock.gpio)
49 return gpiod_get_value_cansleep(ser->lock.gpio);
50
51 if (regmap_read(ser->regmap, 0x002a, &val))
52 return false;
53
54 if (!FIELD_GET(LINK_LOCKED, val))
55 return false;
56
57 return true;
58 }
59
max96745_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)60 static int max96745_bridge_attach(struct drm_bridge *bridge,
61 enum drm_bridge_attach_flags flags)
62 {
63 struct max96745_bridge *ser = to_max96745_bridge(bridge);
64 int ret;
65
66 ret = drm_of_find_panel_or_bridge(bridge->of_node, 1, -1, &ser->panel,
67 NULL);
68 if (ret < 0 && ret != -ENODEV)
69 return ret;
70
71 if (max96745_bridge_link_locked(ser))
72 ser->status = connector_status_connected;
73 else
74 ser->status = connector_status_disconnected;
75
76 return 0;
77 }
78
max96745_bridge_pre_enable(struct drm_bridge * bridge)79 static void max96745_bridge_pre_enable(struct drm_bridge *bridge)
80 {
81 struct max96745_bridge *ser = to_max96745_bridge(bridge);
82
83 if (ser->panel)
84 drm_panel_prepare(ser->panel);
85 }
86
max96745_bridge_enable(struct drm_bridge * bridge)87 static void max96745_bridge_enable(struct drm_bridge *bridge)
88 {
89 struct max96745_bridge *ser = to_max96745_bridge(bridge);
90 struct max96745 *max96745 = ser->parent;
91 struct drm_display_mode *mode = &bridge->encoder->crtc->state->adjusted_mode;
92 u8 cxtp, tx_rate;
93 u32 reg;
94
95 regmap_read(ser->regmap, 0x0011, ®);
96 cxtp = FIELD_GET(CXTP_A, reg);
97 regmap_read(ser->regmap, 0x0028, ®);
98 tx_rate = FIELD_GET(TX_RATE, reg);
99 if (!cxtp && mode->clock > 95000 && tx_rate == 1) {
100 regmap_update_bits(ser->regmap, 0x0028, TX_RATE,
101 FIELD_PREP(TX_RATE, 2));
102 regmap_update_bits(ser->regmap, 0x0029, RESET_ONESHOT,
103 FIELD_PREP(RESET_ONESHOT, 1));
104 if (regmap_read_poll_timeout(ser->regmap, 0x002a, reg,
105 reg & LINK_LOCKED, 10000, 200000))
106 dev_err(ser->dev, "%s: GMSL link not locked\n", __func__);
107 }
108
109 if (ser->panel)
110 drm_panel_enable(ser->panel);
111
112 extcon_set_state_sync(max96745->extcon, EXTCON_JACK_VIDEO_OUT, true);
113 }
114
max96745_bridge_disable(struct drm_bridge * bridge)115 static void max96745_bridge_disable(struct drm_bridge *bridge)
116 {
117 struct max96745_bridge *ser = to_max96745_bridge(bridge);
118 struct max96745 *max96745 = ser->parent;
119
120 extcon_set_state_sync(max96745->extcon, EXTCON_JACK_VIDEO_OUT, false);
121
122 if (ser->panel)
123 drm_panel_disable(ser->panel);
124 }
125
max96745_bridge_post_disable(struct drm_bridge * bridge)126 static void max96745_bridge_post_disable(struct drm_bridge *bridge)
127 {
128 struct max96745_bridge *ser = to_max96745_bridge(bridge);
129 u8 cxtp, tx_rate, link_locked;
130 u32 reg;
131
132 regmap_read(ser->regmap, 0x002a, ®);
133 link_locked = FIELD_GET(LINK_LOCKED, reg);
134
135 if (ser->panel)
136 drm_panel_unprepare(ser->panel);
137
138 regmap_read(ser->regmap, 0x0011, ®);
139 cxtp = FIELD_GET(CXTP_A, reg);
140 regmap_read(ser->regmap, 0x0028, ®);
141 tx_rate = FIELD_GET(TX_RATE, reg);
142 if (!cxtp && tx_rate == 2) {
143 regmap_update_bits(ser->regmap, 0x0028, TX_RATE,
144 FIELD_PREP(TX_RATE, 1));
145 regmap_update_bits(ser->regmap, 0x0029, RESET_ONESHOT,
146 FIELD_PREP(RESET_ONESHOT, 1));
147 if (link_locked) {
148 if (regmap_read_poll_timeout(ser->regmap, 0x002a, reg,
149 reg & LINK_LOCKED, 10000, 200000))
150 dev_err(ser->dev, "%s: GMSL link not locked\n", __func__);
151 }
152 }
153 }
154
155 static enum drm_connector_status
max96745_bridge_detect(struct drm_bridge * bridge)156 max96745_bridge_detect(struct drm_bridge *bridge)
157 {
158 struct max96745_bridge *ser = to_max96745_bridge(bridge);
159 struct max96745 *max96745 = ser->parent;
160 enum drm_connector_status status = connector_status_connected;
161
162 if (!drm_kms_helper_is_poll_worker())
163 return ser->status;
164
165 if (!max96745_bridge_link_locked(ser)) {
166 status = connector_status_disconnected;
167 goto out;
168 }
169
170 if (extcon_get_state(max96745->extcon, EXTCON_JACK_VIDEO_OUT)) {
171 u32 dprx_trn_status2;
172
173 if (atomic_cmpxchg(&ser->lock.triggered, 1, 0)) {
174 status = connector_status_disconnected;
175 goto out;
176 }
177
178 if (regmap_read(ser->regmap, 0x641a, &dprx_trn_status2)) {
179 status = connector_status_disconnected;
180 goto out;
181 }
182
183 if ((dprx_trn_status2 & DPRX_TRAIN_STATE) != DPRX_TRAIN_STATE) {
184 dev_err(ser->dev, "Training State: 0x%lx\n",
185 FIELD_GET(DPRX_TRAIN_STATE, dprx_trn_status2));
186 status = connector_status_disconnected;
187 goto out;
188 }
189 } else {
190 atomic_set(&ser->lock.triggered, 0);
191 }
192
193 out:
194 ser->status = status;
195 return status;
196 }
197
max96745_bridge_get_modes(struct drm_bridge * bridge,struct drm_connector * connector)198 static int max96745_bridge_get_modes(struct drm_bridge *bridge,
199 struct drm_connector *connector)
200 {
201 struct max96745_bridge *ser = to_max96745_bridge(bridge);
202
203 if (ser->panel)
204 return drm_panel_get_modes(ser->panel, connector);
205
206 return drm_add_modes_noedid(connector, 1920, 1080);
207 }
208
209 static const struct drm_bridge_funcs max96745_bridge_funcs = {
210 .attach = max96745_bridge_attach,
211 .detect = max96745_bridge_detect,
212 .get_modes = max96745_bridge_get_modes,
213 .pre_enable = max96745_bridge_pre_enable,
214 .enable = max96745_bridge_enable,
215 .disable = max96745_bridge_disable,
216 .post_disable = max96745_bridge_post_disable,
217 .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
218 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
219 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
220 .atomic_reset = drm_atomic_helper_bridge_reset,
221 };
222
max96745_bridge_lock_irq_handler(int irq,void * arg)223 static irqreturn_t max96745_bridge_lock_irq_handler(int irq, void *arg)
224 {
225 struct max96745_bridge *ser = arg;
226 struct max96745 *max96745 = ser->parent;
227
228 if (extcon_get_state(max96745->extcon, EXTCON_JACK_VIDEO_OUT))
229 atomic_set(&ser->lock.triggered, 1);
230
231 return IRQ_HANDLED;
232 }
233
max96745_bridge_probe(struct platform_device * pdev)234 static int max96745_bridge_probe(struct platform_device *pdev)
235 {
236 struct device *dev = &pdev->dev;
237 struct max96745_bridge *ser;
238 int ret;
239
240 ser = devm_kzalloc(dev, sizeof(*ser), GFP_KERNEL);
241 if (!ser)
242 return -ENOMEM;
243
244 ser->dev = dev;
245 ser->parent = dev_get_drvdata(dev->parent);
246 platform_set_drvdata(pdev, ser);
247
248 ser->regmap = dev_get_regmap(dev->parent, NULL);
249 if (!ser->regmap)
250 return dev_err_probe(dev, -ENODEV, "failed to get regmap\n");
251
252 ser->lock.gpio = devm_gpiod_get_optional(dev, "lock", GPIOD_IN);
253 if (IS_ERR(ser->lock.gpio))
254 return dev_err_probe(dev, PTR_ERR(ser->lock.gpio),
255 "failed to get lock GPIO\n");
256
257 if (ser->lock.gpio) {
258 ser->lock.irq = gpiod_to_irq(ser->lock.gpio);
259 if (ser->lock.irq < 0)
260 return ser->lock.irq;
261
262 ret = devm_request_threaded_irq(dev, ser->lock.irq, NULL,
263 max96745_bridge_lock_irq_handler,
264 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
265 dev_name(dev), ser);
266 if (ret)
267 return dev_err_probe(dev, ret, "failed to request lock IRQ\n");
268 }
269
270 ser->bridge.funcs = &max96745_bridge_funcs;
271 ser->bridge.of_node = dev->of_node;
272 ser->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_MODES;
273
274 drm_bridge_add(&ser->bridge);
275
276 return 0;
277 }
278
max96745_bridge_remove(struct platform_device * pdev)279 static int max96745_bridge_remove(struct platform_device *pdev)
280 {
281 struct max96745_bridge *ser = platform_get_drvdata(pdev);
282
283 drm_bridge_remove(&ser->bridge);
284
285 return 0;
286 }
287
288 static const struct of_device_id max96745_bridge_of_match[] = {
289 { .compatible = "maxim,max96745-bridge", },
290 {}
291 };
292 MODULE_DEVICE_TABLE(of, max96745_bridge_of_match);
293
294 static struct platform_driver max96745_bridge_driver = {
295 .driver = {
296 .name = "max96745-bridge",
297 .of_match_table = of_match_ptr(max96745_bridge_of_match),
298 },
299 .probe = max96745_bridge_probe,
300 .remove = max96745_bridge_remove,
301 };
302
303 module_platform_driver(max96745_bridge_driver);
304
305 MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
306 MODULE_DESCRIPTION("Maxim MAX96745 GMSL2 Serializer with eDP1.4a/DP1.4 Input");
307 MODULE_LICENSE("GPL");
308