xref: /openbmc/linux/drivers/gpu/drm/tegra/dpaux.c (revision 293d5b43)
1 /*
2  * Copyright (C) 2013 NVIDIA Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 
9 #include <linux/clk.h>
10 #include <linux/delay.h>
11 #include <linux/gpio.h>
12 #include <linux/interrupt.h>
13 #include <linux/io.h>
14 #include <linux/of_gpio.h>
15 #include <linux/pinctrl/pinconf-generic.h>
16 #include <linux/pinctrl/pinctrl.h>
17 #include <linux/pinctrl/pinmux.h>
18 #include <linux/platform_device.h>
19 #include <linux/reset.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/workqueue.h>
22 
23 #include <drm/drm_dp_helper.h>
24 #include <drm/drm_panel.h>
25 
26 #include "dpaux.h"
27 #include "drm.h"
28 
29 static DEFINE_MUTEX(dpaux_lock);
30 static LIST_HEAD(dpaux_list);
31 
32 struct tegra_dpaux {
33 	struct drm_dp_aux aux;
34 	struct device *dev;
35 
36 	void __iomem *regs;
37 	int irq;
38 
39 	struct tegra_output *output;
40 
41 	struct reset_control *rst;
42 	struct clk *clk_parent;
43 	struct clk *clk;
44 
45 	struct regulator *vdd;
46 
47 	struct completion complete;
48 	struct work_struct work;
49 	struct list_head list;
50 
51 #ifdef CONFIG_GENERIC_PINCONF
52 	struct pinctrl_dev *pinctrl;
53 	struct pinctrl_desc desc;
54 #endif
55 };
56 
57 static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
58 {
59 	return container_of(aux, struct tegra_dpaux, aux);
60 }
61 
62 static inline struct tegra_dpaux *work_to_dpaux(struct work_struct *work)
63 {
64 	return container_of(work, struct tegra_dpaux, work);
65 }
66 
67 static inline u32 tegra_dpaux_readl(struct tegra_dpaux *dpaux,
68 				    unsigned long offset)
69 {
70 	return readl(dpaux->regs + (offset << 2));
71 }
72 
73 static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
74 				      u32 value, unsigned long offset)
75 {
76 	writel(value, dpaux->regs + (offset << 2));
77 }
78 
79 static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
80 				   size_t size)
81 {
82 	size_t i, j;
83 
84 	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
85 		size_t num = min_t(size_t, size - i * 4, 4);
86 		u32 value = 0;
87 
88 		for (j = 0; j < num; j++)
89 			value |= buffer[i * 4 + j] << (j * 8);
90 
91 		tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXDATA_WRITE(i));
92 	}
93 }
94 
95 static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
96 				  size_t size)
97 {
98 	size_t i, j;
99 
100 	for (i = 0; i < DIV_ROUND_UP(size, 4); i++) {
101 		size_t num = min_t(size_t, size - i * 4, 4);
102 		u32 value;
103 
104 		value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXDATA_READ(i));
105 
106 		for (j = 0; j < num; j++)
107 			buffer[i * 4 + j] = value >> (j * 8);
108 	}
109 }
110 
111 static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
112 				    struct drm_dp_aux_msg *msg)
113 {
114 	unsigned long timeout = msecs_to_jiffies(250);
115 	struct tegra_dpaux *dpaux = to_dpaux(aux);
116 	unsigned long status;
117 	ssize_t ret = 0;
118 	u32 value;
119 
120 	/* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */
121 	if (msg->size > 16)
122 		return -EINVAL;
123 
124 	/*
125 	 * Allow zero-sized messages only for I2C, in which case they specify
126 	 * address-only transactions.
127 	 */
128 	if (msg->size < 1) {
129 		switch (msg->request & ~DP_AUX_I2C_MOT) {
130 		case DP_AUX_I2C_WRITE_STATUS_UPDATE:
131 		case DP_AUX_I2C_WRITE:
132 		case DP_AUX_I2C_READ:
133 			value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY;
134 			break;
135 
136 		default:
137 			return -EINVAL;
138 		}
139 	} else {
140 		/* For non-zero-sized messages, set the CMDLEN field. */
141 		value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
142 	}
143 
144 	switch (msg->request & ~DP_AUX_I2C_MOT) {
145 	case DP_AUX_I2C_WRITE:
146 		if (msg->request & DP_AUX_I2C_MOT)
147 			value |= DPAUX_DP_AUXCTL_CMD_MOT_WR;
148 		else
149 			value |= DPAUX_DP_AUXCTL_CMD_I2C_WR;
150 
151 		break;
152 
153 	case DP_AUX_I2C_READ:
154 		if (msg->request & DP_AUX_I2C_MOT)
155 			value |= DPAUX_DP_AUXCTL_CMD_MOT_RD;
156 		else
157 			value |= DPAUX_DP_AUXCTL_CMD_I2C_RD;
158 
159 		break;
160 
161 	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
162 		if (msg->request & DP_AUX_I2C_MOT)
163 			value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ;
164 		else
165 			value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ;
166 
167 		break;
168 
169 	case DP_AUX_NATIVE_WRITE:
170 		value |= DPAUX_DP_AUXCTL_CMD_AUX_WR;
171 		break;
172 
173 	case DP_AUX_NATIVE_READ:
174 		value |= DPAUX_DP_AUXCTL_CMD_AUX_RD;
175 		break;
176 
177 	default:
178 		return -EINVAL;
179 	}
180 
181 	tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
182 	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
183 
184 	if ((msg->request & DP_AUX_I2C_READ) == 0) {
185 		tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
186 		ret = msg->size;
187 	}
188 
189 	/* start transaction */
190 	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
191 	value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
192 	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
193 
194 	status = wait_for_completion_timeout(&dpaux->complete, timeout);
195 	if (!status)
196 		return -ETIMEDOUT;
197 
198 	/* read status and clear errors */
199 	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
200 	tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);
201 
202 	if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
203 		return -ETIMEDOUT;
204 
205 	if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
206 	    (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
207 	    (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
208 		return -EIO;
209 
210 	switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
211 	case 0x00:
212 		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
213 		break;
214 
215 	case 0x01:
216 		msg->reply = DP_AUX_NATIVE_REPLY_NACK;
217 		break;
218 
219 	case 0x02:
220 		msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
221 		break;
222 
223 	case 0x04:
224 		msg->reply = DP_AUX_I2C_REPLY_NACK;
225 		break;
226 
227 	case 0x08:
228 		msg->reply = DP_AUX_I2C_REPLY_DEFER;
229 		break;
230 	}
231 
232 	if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) {
233 		if (msg->request & DP_AUX_I2C_READ) {
234 			size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
235 
236 			if (WARN_ON(count != msg->size))
237 				count = min_t(size_t, count, msg->size);
238 
239 			tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
240 			ret = count;
241 		}
242 	}
243 
244 	return ret;
245 }
246 
247 static void tegra_dpaux_hotplug(struct work_struct *work)
248 {
249 	struct tegra_dpaux *dpaux = work_to_dpaux(work);
250 
251 	if (dpaux->output)
252 		drm_helper_hpd_irq_event(dpaux->output->connector.dev);
253 }
254 
255 static irqreturn_t tegra_dpaux_irq(int irq, void *data)
256 {
257 	struct tegra_dpaux *dpaux = data;
258 	irqreturn_t ret = IRQ_HANDLED;
259 	u32 value;
260 
261 	/* clear interrupts */
262 	value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
263 	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
264 
265 	if (value & (DPAUX_INTR_PLUG_EVENT | DPAUX_INTR_UNPLUG_EVENT))
266 		schedule_work(&dpaux->work);
267 
268 	if (value & DPAUX_INTR_IRQ_EVENT) {
269 		/* TODO: handle this */
270 	}
271 
272 	if (value & DPAUX_INTR_AUX_DONE)
273 		complete(&dpaux->complete);
274 
275 	return ret;
276 }
277 
278 enum tegra_dpaux_functions {
279 	DPAUX_PADCTL_FUNC_AUX,
280 	DPAUX_PADCTL_FUNC_I2C,
281 	DPAUX_PADCTL_FUNC_OFF,
282 };
283 
284 static void tegra_dpaux_pad_power_down(struct tegra_dpaux *dpaux)
285 {
286 	u32 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
287 
288 	value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
289 
290 	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
291 }
292 
293 static void tegra_dpaux_pad_power_up(struct tegra_dpaux *dpaux)
294 {
295 	u32 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
296 
297 	value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
298 
299 	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
300 }
301 
302 static int tegra_dpaux_pad_config(struct tegra_dpaux *dpaux, unsigned function)
303 {
304 	u32 value;
305 
306 	switch (function) {
307 	case DPAUX_PADCTL_FUNC_AUX:
308 		value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
309 			DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
310 			DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
311 			DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
312 			DPAUX_HYBRID_PADCTL_MODE_AUX;
313 		break;
314 
315 	case DPAUX_PADCTL_FUNC_I2C:
316 		value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV |
317 			DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
318 			DPAUX_HYBRID_PADCTL_MODE_I2C;
319 		break;
320 
321 	case DPAUX_PADCTL_FUNC_OFF:
322 		tegra_dpaux_pad_power_down(dpaux);
323 		return 0;
324 
325 	default:
326 		return -ENOTSUPP;
327 	}
328 
329 	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
330 	tegra_dpaux_pad_power_up(dpaux);
331 
332 	return 0;
333 }
334 
335 #ifdef CONFIG_GENERIC_PINCONF
336 static const struct pinctrl_pin_desc tegra_dpaux_pins[] = {
337 	PINCTRL_PIN(0, "DP_AUX_CHx_P"),
338 	PINCTRL_PIN(1, "DP_AUX_CHx_N"),
339 };
340 
341 static const unsigned tegra_dpaux_pin_numbers[] = { 0, 1 };
342 
343 static const char * const tegra_dpaux_groups[] = {
344 	"dpaux-io",
345 };
346 
347 static const char * const tegra_dpaux_functions[] = {
348 	"aux",
349 	"i2c",
350 	"off",
351 };
352 
353 static int tegra_dpaux_get_groups_count(struct pinctrl_dev *pinctrl)
354 {
355 	return ARRAY_SIZE(tegra_dpaux_groups);
356 }
357 
358 static const char *tegra_dpaux_get_group_name(struct pinctrl_dev *pinctrl,
359 					      unsigned int group)
360 {
361 	return tegra_dpaux_groups[group];
362 }
363 
364 static int tegra_dpaux_get_group_pins(struct pinctrl_dev *pinctrl,
365 				      unsigned group, const unsigned **pins,
366 				      unsigned *num_pins)
367 {
368 	*pins = tegra_dpaux_pin_numbers;
369 	*num_pins = ARRAY_SIZE(tegra_dpaux_pin_numbers);
370 
371 	return 0;
372 }
373 
374 static const struct pinctrl_ops tegra_dpaux_pinctrl_ops = {
375 	.get_groups_count = tegra_dpaux_get_groups_count,
376 	.get_group_name = tegra_dpaux_get_group_name,
377 	.get_group_pins = tegra_dpaux_get_group_pins,
378 	.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
379 	.dt_free_map = pinconf_generic_dt_free_map,
380 };
381 
382 static int tegra_dpaux_get_functions_count(struct pinctrl_dev *pinctrl)
383 {
384 	return ARRAY_SIZE(tegra_dpaux_functions);
385 }
386 
387 static const char *tegra_dpaux_get_function_name(struct pinctrl_dev *pinctrl,
388 						 unsigned int function)
389 {
390 	return tegra_dpaux_functions[function];
391 }
392 
393 static int tegra_dpaux_get_function_groups(struct pinctrl_dev *pinctrl,
394 					   unsigned int function,
395 					   const char * const **groups,
396 					   unsigned * const num_groups)
397 {
398 	*num_groups = ARRAY_SIZE(tegra_dpaux_groups);
399 	*groups = tegra_dpaux_groups;
400 
401 	return 0;
402 }
403 
404 static int tegra_dpaux_set_mux(struct pinctrl_dev *pinctrl,
405 			       unsigned int function, unsigned int group)
406 {
407 	struct tegra_dpaux *dpaux = pinctrl_dev_get_drvdata(pinctrl);
408 
409 	return tegra_dpaux_pad_config(dpaux, function);
410 }
411 
412 static const struct pinmux_ops tegra_dpaux_pinmux_ops = {
413 	.get_functions_count = tegra_dpaux_get_functions_count,
414 	.get_function_name = tegra_dpaux_get_function_name,
415 	.get_function_groups = tegra_dpaux_get_function_groups,
416 	.set_mux = tegra_dpaux_set_mux,
417 };
418 #endif
419 
420 static int tegra_dpaux_probe(struct platform_device *pdev)
421 {
422 	struct tegra_dpaux *dpaux;
423 	struct resource *regs;
424 	u32 value;
425 	int err;
426 
427 	dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
428 	if (!dpaux)
429 		return -ENOMEM;
430 
431 	INIT_WORK(&dpaux->work, tegra_dpaux_hotplug);
432 	init_completion(&dpaux->complete);
433 	INIT_LIST_HEAD(&dpaux->list);
434 	dpaux->dev = &pdev->dev;
435 
436 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
437 	dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
438 	if (IS_ERR(dpaux->regs))
439 		return PTR_ERR(dpaux->regs);
440 
441 	dpaux->irq = platform_get_irq(pdev, 0);
442 	if (dpaux->irq < 0) {
443 		dev_err(&pdev->dev, "failed to get IRQ\n");
444 		return -ENXIO;
445 	}
446 
447 	if (!pdev->dev.pm_domain) {
448 		dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
449 		if (IS_ERR(dpaux->rst)) {
450 			dev_err(&pdev->dev,
451 				"failed to get reset control: %ld\n",
452 				PTR_ERR(dpaux->rst));
453 			return PTR_ERR(dpaux->rst);
454 		}
455 	}
456 
457 	dpaux->clk = devm_clk_get(&pdev->dev, NULL);
458 	if (IS_ERR(dpaux->clk)) {
459 		dev_err(&pdev->dev, "failed to get module clock: %ld\n",
460 			PTR_ERR(dpaux->clk));
461 		return PTR_ERR(dpaux->clk);
462 	}
463 
464 	err = clk_prepare_enable(dpaux->clk);
465 	if (err < 0) {
466 		dev_err(&pdev->dev, "failed to enable module clock: %d\n",
467 			err);
468 		return err;
469 	}
470 
471 	if (dpaux->rst)
472 		reset_control_deassert(dpaux->rst);
473 
474 	dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
475 	if (IS_ERR(dpaux->clk_parent)) {
476 		dev_err(&pdev->dev, "failed to get parent clock: %ld\n",
477 			PTR_ERR(dpaux->clk_parent));
478 		err = PTR_ERR(dpaux->clk_parent);
479 		goto assert_reset;
480 	}
481 
482 	err = clk_prepare_enable(dpaux->clk_parent);
483 	if (err < 0) {
484 		dev_err(&pdev->dev, "failed to enable parent clock: %d\n",
485 			err);
486 		goto assert_reset;
487 	}
488 
489 	err = clk_set_rate(dpaux->clk_parent, 270000000);
490 	if (err < 0) {
491 		dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
492 			err);
493 		goto disable_parent_clk;
494 	}
495 
496 	dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
497 	if (IS_ERR(dpaux->vdd)) {
498 		dev_err(&pdev->dev, "failed to get VDD supply: %ld\n",
499 			PTR_ERR(dpaux->vdd));
500 		err = PTR_ERR(dpaux->vdd);
501 		goto disable_parent_clk;
502 	}
503 
504 	err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
505 			       dev_name(dpaux->dev), dpaux);
506 	if (err < 0) {
507 		dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
508 			dpaux->irq, err);
509 		goto disable_parent_clk;
510 	}
511 
512 	disable_irq(dpaux->irq);
513 
514 	dpaux->aux.transfer = tegra_dpaux_transfer;
515 	dpaux->aux.dev = &pdev->dev;
516 
517 	err = drm_dp_aux_register(&dpaux->aux);
518 	if (err < 0)
519 		goto disable_parent_clk;
520 
521 	/*
522 	 * Assume that by default the DPAUX/I2C pads will be used for HDMI,
523 	 * so power them up and configure them in I2C mode.
524 	 *
525 	 * The DPAUX code paths reconfigure the pads in AUX mode, but there
526 	 * is no possibility to perform the I2C mode configuration in the
527 	 * HDMI path.
528 	 */
529 	err = tegra_dpaux_pad_config(dpaux, DPAUX_HYBRID_PADCTL_MODE_I2C);
530 	if (err < 0)
531 		return err;
532 
533 #ifdef CONFIG_GENERIC_PINCONF
534 	dpaux->desc.name = dev_name(&pdev->dev);
535 	dpaux->desc.pins = tegra_dpaux_pins;
536 	dpaux->desc.npins = ARRAY_SIZE(tegra_dpaux_pins);
537 	dpaux->desc.pctlops = &tegra_dpaux_pinctrl_ops;
538 	dpaux->desc.pmxops = &tegra_dpaux_pinmux_ops;
539 	dpaux->desc.owner = THIS_MODULE;
540 
541 	dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
542 	if (!dpaux->pinctrl) {
543 		dev_err(&pdev->dev, "failed to register pincontrol\n");
544 		return -ENODEV;
545 	}
546 #endif
547 	/* enable and clear all interrupts */
548 	value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
549 		DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
550 	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
551 	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
552 
553 	mutex_lock(&dpaux_lock);
554 	list_add_tail(&dpaux->list, &dpaux_list);
555 	mutex_unlock(&dpaux_lock);
556 
557 	platform_set_drvdata(pdev, dpaux);
558 
559 	return 0;
560 
561 disable_parent_clk:
562 	clk_disable_unprepare(dpaux->clk_parent);
563 assert_reset:
564 	if (dpaux->rst)
565 		reset_control_assert(dpaux->rst);
566 
567 	clk_disable_unprepare(dpaux->clk);
568 
569 	return err;
570 }
571 
572 static int tegra_dpaux_remove(struct platform_device *pdev)
573 {
574 	struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
575 
576 	/* make sure pads are powered down when not in use */
577 	tegra_dpaux_pad_power_down(dpaux);
578 
579 	drm_dp_aux_unregister(&dpaux->aux);
580 
581 	mutex_lock(&dpaux_lock);
582 	list_del(&dpaux->list);
583 	mutex_unlock(&dpaux_lock);
584 
585 	cancel_work_sync(&dpaux->work);
586 
587 	clk_disable_unprepare(dpaux->clk_parent);
588 
589 	if (dpaux->rst)
590 		reset_control_assert(dpaux->rst);
591 
592 	clk_disable_unprepare(dpaux->clk);
593 
594 	return 0;
595 }
596 
597 static const struct of_device_id tegra_dpaux_of_match[] = {
598 	{ .compatible = "nvidia,tegra210-dpaux", },
599 	{ .compatible = "nvidia,tegra124-dpaux", },
600 	{ },
601 };
602 MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
603 
604 struct platform_driver tegra_dpaux_driver = {
605 	.driver = {
606 		.name = "tegra-dpaux",
607 		.of_match_table = tegra_dpaux_of_match,
608 	},
609 	.probe = tegra_dpaux_probe,
610 	.remove = tegra_dpaux_remove,
611 };
612 
613 struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)
614 {
615 	struct tegra_dpaux *dpaux;
616 
617 	mutex_lock(&dpaux_lock);
618 
619 	list_for_each_entry(dpaux, &dpaux_list, list)
620 		if (np == dpaux->dev->of_node) {
621 			mutex_unlock(&dpaux_lock);
622 			return &dpaux->aux;
623 		}
624 
625 	mutex_unlock(&dpaux_lock);
626 
627 	return NULL;
628 }
629 
630 int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output)
631 {
632 	struct tegra_dpaux *dpaux = to_dpaux(aux);
633 	unsigned long timeout;
634 	int err;
635 
636 	output->connector.polled = DRM_CONNECTOR_POLL_HPD;
637 	dpaux->output = output;
638 
639 	err = regulator_enable(dpaux->vdd);
640 	if (err < 0)
641 		return err;
642 
643 	timeout = jiffies + msecs_to_jiffies(250);
644 
645 	while (time_before(jiffies, timeout)) {
646 		enum drm_connector_status status;
647 
648 		status = drm_dp_aux_detect(aux);
649 		if (status == connector_status_connected) {
650 			enable_irq(dpaux->irq);
651 			return 0;
652 		}
653 
654 		usleep_range(1000, 2000);
655 	}
656 
657 	return -ETIMEDOUT;
658 }
659 
660 int drm_dp_aux_detach(struct drm_dp_aux *aux)
661 {
662 	struct tegra_dpaux *dpaux = to_dpaux(aux);
663 	unsigned long timeout;
664 	int err;
665 
666 	disable_irq(dpaux->irq);
667 
668 	err = regulator_disable(dpaux->vdd);
669 	if (err < 0)
670 		return err;
671 
672 	timeout = jiffies + msecs_to_jiffies(250);
673 
674 	while (time_before(jiffies, timeout)) {
675 		enum drm_connector_status status;
676 
677 		status = drm_dp_aux_detect(aux);
678 		if (status == connector_status_disconnected) {
679 			dpaux->output = NULL;
680 			return 0;
681 		}
682 
683 		usleep_range(1000, 2000);
684 	}
685 
686 	return -ETIMEDOUT;
687 }
688 
689 enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
690 {
691 	struct tegra_dpaux *dpaux = to_dpaux(aux);
692 	u32 value;
693 
694 	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
695 
696 	if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
697 		return connector_status_connected;
698 
699 	return connector_status_disconnected;
700 }
701 
702 int drm_dp_aux_enable(struct drm_dp_aux *aux)
703 {
704 	struct tegra_dpaux *dpaux = to_dpaux(aux);
705 
706 	return tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_AUX);
707 }
708 
709 int drm_dp_aux_disable(struct drm_dp_aux *aux)
710 {
711 	struct tegra_dpaux *dpaux = to_dpaux(aux);
712 
713 	tegra_dpaux_pad_power_down(dpaux);
714 
715 	return 0;
716 }
717 
718 int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding)
719 {
720 	int err;
721 
722 	err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
723 				 encoding);
724 	if (err < 0)
725 		return err;
726 
727 	return 0;
728 }
729 
730 int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
731 		     u8 pattern)
732 {
733 	u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
734 	u8 status[DP_LINK_STATUS_SIZE], values[4];
735 	unsigned int i;
736 	int err;
737 
738 	err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
739 	if (err < 0)
740 		return err;
741 
742 	if (tp == DP_TRAINING_PATTERN_DISABLE)
743 		return 0;
744 
745 	for (i = 0; i < link->num_lanes; i++)
746 		values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
747 			    DP_TRAIN_PRE_EMPH_LEVEL_0 |
748 			    DP_TRAIN_MAX_SWING_REACHED |
749 			    DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
750 
751 	err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values,
752 				link->num_lanes);
753 	if (err < 0)
754 		return err;
755 
756 	usleep_range(500, 1000);
757 
758 	err = drm_dp_dpcd_read_link_status(aux, status);
759 	if (err < 0)
760 		return err;
761 
762 	switch (tp) {
763 	case DP_TRAINING_PATTERN_1:
764 		if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
765 			return -EAGAIN;
766 
767 		break;
768 
769 	case DP_TRAINING_PATTERN_2:
770 		if (!drm_dp_channel_eq_ok(status, link->num_lanes))
771 			return -EAGAIN;
772 
773 		break;
774 
775 	default:
776 		dev_err(aux->dev, "unsupported training pattern %u\n", tp);
777 		return -EINVAL;
778 	}
779 
780 	err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET, 0);
781 	if (err < 0)
782 		return err;
783 
784 	return 0;
785 }
786