Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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