.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Analogix DP (Display port) core register interface driver. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. |
---|
5 | 6 | * Author: Jingoo Han <jg1.han@samsung.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms of the GNU General Public License as published by the |
---|
9 | | - * Free Software Foundation; either version 2 of the License, or (at your |
---|
10 | | - * option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #include <linux/delay.h> |
---|
.. | .. |
---|
18 | 14 | #include <linux/phy/phy.h> |
---|
19 | 15 | |
---|
20 | 16 | #include <drm/bridge/analogix_dp.h> |
---|
| 17 | +#include <drm/drm_probe_helper.h> |
---|
21 | 18 | |
---|
22 | 19 | #include "analogix_dp_core.h" |
---|
23 | 20 | #include "analogix_dp_reg.h" |
---|
24 | | - |
---|
25 | | -#define COMMON_INT_MASK_1 0 |
---|
26 | | -#define COMMON_INT_MASK_2 0 |
---|
27 | | -#define COMMON_INT_MASK_3 0 |
---|
28 | | -#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) |
---|
29 | 21 | |
---|
30 | 22 | static void analogix_dp_write(struct analogix_dp_device *dp, u32 reg, u32 val) |
---|
31 | 23 | { |
---|
.. | .. |
---|
69 | 61 | analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_1, reg); |
---|
70 | 62 | } |
---|
71 | 63 | |
---|
72 | | -void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) |
---|
| 64 | +static void analogix_dp_set_lane_map(struct analogix_dp_device *dp) |
---|
73 | 65 | { |
---|
74 | | - u32 reg; |
---|
| 66 | + struct video_info *video_info = &dp->video_info; |
---|
| 67 | + u32 i, reg = 0; |
---|
75 | 68 | |
---|
76 | | - if (enable) |
---|
77 | | - reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | |
---|
78 | | - LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; |
---|
79 | | - else |
---|
80 | | - reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | |
---|
81 | | - LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; |
---|
| 69 | + for (i = 0; i < video_info->max_lane_count; i++) |
---|
| 70 | + reg |= video_info->lane_map[i] << (2 * i); |
---|
82 | 71 | |
---|
83 | 72 | analogix_dp_write(dp, ANALOGIX_DP_LANE_MAP, reg); |
---|
84 | 73 | } |
---|
.. | .. |
---|
95 | 84 | |
---|
96 | 85 | if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) { |
---|
97 | 86 | reg = REF_CLK_24M; |
---|
98 | | - if (dp->plat_data->dev_type == RK3288_DP || |
---|
99 | | - dp->plat_data->dev_type == RK3368_EDP) |
---|
| 87 | + if (dp->plat_data->dev_type == RK3288_DP) |
---|
100 | 88 | reg ^= REF_CLK_MASK; |
---|
101 | 89 | |
---|
102 | 90 | analogix_dp_write(dp, ANALOGIX_DP_PLL_REG_1, reg); |
---|
.. | .. |
---|
163 | 151 | |
---|
164 | 152 | usleep_range(20, 30); |
---|
165 | 153 | |
---|
166 | | - analogix_dp_lane_swap(dp, 0); |
---|
| 154 | + analogix_dp_set_lane_map(dp); |
---|
167 | 155 | |
---|
168 | 156 | analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_1, 0x0); |
---|
169 | 157 | analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, 0x40); |
---|
.. | .. |
---|
172 | 160 | |
---|
173 | 161 | analogix_dp_write(dp, ANALOGIX_DP_PKT_SEND_CTL, 0x0); |
---|
174 | 162 | analogix_dp_write(dp, ANALOGIX_DP_HDCP_CTL, 0x0); |
---|
175 | | - |
---|
176 | | - analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_L, 0x5e); |
---|
177 | | - analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_H, 0x1a); |
---|
178 | 163 | |
---|
179 | 164 | analogix_dp_write(dp, ANALOGIX_DP_LINK_DEBUG_CTL, 0x10); |
---|
180 | 165 | |
---|
.. | .. |
---|
196 | 181 | |
---|
197 | 182 | void analogix_dp_config_interrupt(struct analogix_dp_device *dp) |
---|
198 | 183 | { |
---|
199 | | - u32 reg; |
---|
200 | | - |
---|
201 | 184 | /* 0: mask, 1: unmask */ |
---|
202 | | - reg = COMMON_INT_MASK_1; |
---|
203 | | - analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_1, reg); |
---|
204 | | - |
---|
205 | | - reg = COMMON_INT_MASK_2; |
---|
206 | | - analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_2, reg); |
---|
207 | | - |
---|
208 | | - reg = COMMON_INT_MASK_3; |
---|
209 | | - analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_3, reg); |
---|
| 185 | + analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_1, 0); |
---|
| 186 | + analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_2, 0); |
---|
| 187 | + analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_3, 0); |
---|
210 | 188 | |
---|
211 | 189 | if (dp->force_hpd || dp->hpd_gpiod) |
---|
212 | 190 | analogix_dp_mute_hpd_interrupt(dp); |
---|
.. | .. |
---|
220 | 198 | |
---|
221 | 199 | /* 0: mask, 1: unmask */ |
---|
222 | 200 | reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_MASK_4); |
---|
223 | | - reg &= ~COMMON_INT_MASK_4; |
---|
| 201 | + reg &= ~HOTPLUG_CHG; |
---|
224 | 202 | analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg); |
---|
225 | 203 | |
---|
226 | 204 | reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA_MASK); |
---|
.. | .. |
---|
233 | 211 | u32 reg; |
---|
234 | 212 | |
---|
235 | 213 | /* 0: mask, 1: unmask */ |
---|
236 | | - reg = COMMON_INT_MASK_4; |
---|
| 214 | + reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_MASK_4); |
---|
| 215 | + reg |= HOTPLUG_CHG; |
---|
237 | 216 | analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg); |
---|
238 | 217 | |
---|
239 | 218 | reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA_MASK); |
---|
.. | .. |
---|
424 | 403 | if (dp->hpd_gpiod) |
---|
425 | 404 | return; |
---|
426 | 405 | |
---|
427 | | - analogix_dp_clear_hotplug_interrupts(dp); |
---|
| 406 | + analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_H, 0xbb); |
---|
| 407 | + analogix_dp_write(dp, ANALOGIX_DP_HPD_DEGLITCH_L, 0x80); |
---|
428 | 408 | |
---|
429 | 409 | reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3); |
---|
430 | 410 | reg &= ~(F_HPD | HPD_CTRL); |
---|
.. | .. |
---|
440 | 420 | analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg); |
---|
441 | 421 | } |
---|
442 | 422 | |
---|
443 | | -enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) |
---|
| 423 | +static void analogix_dp_handle_hpd_event(struct analogix_dp_device *dp) |
---|
444 | 424 | { |
---|
| 425 | + bool changed = false; |
---|
445 | 426 | u32 reg; |
---|
446 | 427 | |
---|
447 | | - /* Parse hotplug interrupt status register */ |
---|
| 428 | + reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA); |
---|
| 429 | + if (reg & INT_HPD) { |
---|
| 430 | + analogix_dp_write(dp, ANALOGIX_DP_INT_STA, INT_HPD); |
---|
| 431 | + |
---|
| 432 | + memset(&dp->compliance, 0, sizeof(dp->compliance)); |
---|
| 433 | + |
---|
| 434 | + analogix_dp_check_device_service_irq(dp); |
---|
| 435 | + |
---|
| 436 | + if (dp->compliance.test_active && |
---|
| 437 | + dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) { |
---|
| 438 | + analogix_dp_phy_test(dp); |
---|
| 439 | + return; |
---|
| 440 | + } |
---|
| 441 | + } |
---|
| 442 | + |
---|
448 | 443 | reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_STA_4); |
---|
| 444 | + if (reg & HOTPLUG_CHG) { |
---|
| 445 | + analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_STA_4, HOTPLUG_CHG); |
---|
| 446 | + changed = true; |
---|
| 447 | + } |
---|
449 | 448 | |
---|
450 | | - if (reg & PLUG) |
---|
451 | | - return DP_IRQ_TYPE_HP_CABLE_IN; |
---|
| 449 | + if (changed) |
---|
| 450 | + drm_helper_hpd_irq_event(dp->drm_dev); |
---|
| 451 | +} |
---|
452 | 452 | |
---|
453 | | - if (reg & HPD_LOST) |
---|
454 | | - return DP_IRQ_TYPE_HP_CABLE_OUT; |
---|
455 | | - |
---|
456 | | - if (reg & HOTPLUG_CHG) |
---|
457 | | - return DP_IRQ_TYPE_HP_CHANGE; |
---|
458 | | - |
---|
459 | | - return DP_IRQ_TYPE_UNKNOWN; |
---|
| 453 | +void analogix_dp_irq_handler(struct analogix_dp_device *dp) |
---|
| 454 | +{ |
---|
| 455 | + analogix_dp_handle_hpd_event(dp); |
---|
460 | 456 | } |
---|
461 | 457 | |
---|
462 | 458 | void analogix_dp_reset_aux(struct analogix_dp_device *dp) |
---|
.. | .. |
---|
531 | 527 | analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg); |
---|
532 | 528 | } |
---|
533 | 529 | |
---|
534 | | -int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) |
---|
535 | | -{ |
---|
536 | | - int reg; |
---|
537 | | - int retval = 0; |
---|
538 | | - int timeout_loop = 0; |
---|
539 | | - |
---|
540 | | - /* Enable AUX CH operation */ |
---|
541 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_CTL_2); |
---|
542 | | - reg |= AUX_EN; |
---|
543 | | - analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_2, reg); |
---|
544 | | - |
---|
545 | | - /* Is AUX CH command reply received? */ |
---|
546 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA); |
---|
547 | | - while (!(reg & RPLY_RECEIV)) { |
---|
548 | | - timeout_loop++; |
---|
549 | | - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { |
---|
550 | | - dev_err(dp->dev, "AUX CH command reply failed!\n"); |
---|
551 | | - return -ETIMEDOUT; |
---|
552 | | - } |
---|
553 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA); |
---|
554 | | - usleep_range(10, 11); |
---|
555 | | - } |
---|
556 | | - |
---|
557 | | - /* Clear interrupt source for AUX CH command reply */ |
---|
558 | | - analogix_dp_write(dp, ANALOGIX_DP_INT_STA, RPLY_RECEIV); |
---|
559 | | - |
---|
560 | | - /* Clear interrupt source for AUX CH access error */ |
---|
561 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA); |
---|
562 | | - if (reg & AUX_ERR) { |
---|
563 | | - analogix_dp_write(dp, ANALOGIX_DP_INT_STA, AUX_ERR); |
---|
564 | | - return -EREMOTEIO; |
---|
565 | | - } |
---|
566 | | - |
---|
567 | | - /* Check AUX CH error access status */ |
---|
568 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_STA); |
---|
569 | | - if ((reg & AUX_STATUS_MASK) != 0) { |
---|
570 | | - dev_err(dp->dev, "AUX CH error happens: %d\n\n", |
---|
571 | | - reg & AUX_STATUS_MASK); |
---|
572 | | - return -EREMOTEIO; |
---|
573 | | - } |
---|
574 | | - |
---|
575 | | - return retval; |
---|
576 | | -} |
---|
577 | | - |
---|
578 | | -int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, |
---|
579 | | - unsigned int reg_addr, |
---|
580 | | - unsigned char data) |
---|
581 | | -{ |
---|
582 | | - u32 reg; |
---|
583 | | - int i; |
---|
584 | | - int retval; |
---|
585 | | - |
---|
586 | | - for (i = 0; i < 3; i++) { |
---|
587 | | - /* Clear AUX CH data buffer */ |
---|
588 | | - reg = BUF_CLR; |
---|
589 | | - analogix_dp_write(dp, ANALOGIX_DP_BUFFER_DATA_CTL, reg); |
---|
590 | | - |
---|
591 | | - /* Select DPCD device address */ |
---|
592 | | - reg = AUX_ADDR_7_0(reg_addr); |
---|
593 | | - analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_7_0, reg); |
---|
594 | | - reg = AUX_ADDR_15_8(reg_addr); |
---|
595 | | - analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_15_8, reg); |
---|
596 | | - reg = AUX_ADDR_19_16(reg_addr); |
---|
597 | | - analogix_dp_write(dp, ANALOGIX_DP_AUX_ADDR_19_16, reg); |
---|
598 | | - |
---|
599 | | - /* Write data buffer */ |
---|
600 | | - reg = (unsigned int)data; |
---|
601 | | - analogix_dp_write(dp, ANALOGIX_DP_BUF_DATA_0, reg); |
---|
602 | | - |
---|
603 | | - /* |
---|
604 | | - * Set DisplayPort transaction and write 1 byte |
---|
605 | | - * If bit 3 is 1, DisplayPort transaction. |
---|
606 | | - * If Bit 3 is 0, I2C transaction. |
---|
607 | | - */ |
---|
608 | | - reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; |
---|
609 | | - analogix_dp_write(dp, ANALOGIX_DP_AUX_CH_CTL_1, reg); |
---|
610 | | - |
---|
611 | | - /* Start AUX transaction */ |
---|
612 | | - retval = analogix_dp_start_aux_transaction(dp); |
---|
613 | | - if (retval == 0) |
---|
614 | | - break; |
---|
615 | | - |
---|
616 | | - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); |
---|
617 | | - } |
---|
618 | | - |
---|
619 | | - return retval; |
---|
620 | | -} |
---|
621 | | - |
---|
622 | 530 | static void analogix_dp_ssc_enable(struct analogix_dp_device *dp) |
---|
623 | 531 | { |
---|
624 | 532 | u32 reg; |
---|
625 | 533 | |
---|
626 | | - writel(0x17, dp->reg_base + ANALOGIX_DP_SSC_REG); |
---|
| 534 | + /* 4500ppm */ |
---|
| 535 | + writel(0x19, dp->reg_base + ANALOIGX_DP_SSC_REG); |
---|
627 | 536 | /* |
---|
628 | 537 | * To apply updated SSC parameters into SSC operation, |
---|
629 | 538 | * firmware must disable and enable this bit. |
---|
.. | .. |
---|
658 | 567 | analogix_dp_write(dp, ANALOGIX_DP_LINK_BW_SET, bwtype); |
---|
659 | 568 | |
---|
660 | 569 | if (dp->phy) { |
---|
661 | | - union phy_configure_opts phy_cfg; |
---|
| 570 | + union phy_configure_opts phy_cfg = {0}; |
---|
662 | 571 | |
---|
663 | 572 | phy_cfg.dp.lanes = dp->link_train.lane_count; |
---|
664 | | - phy_cfg.dp.link_rate = drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100; |
---|
| 573 | + phy_cfg.dp.link_rate = |
---|
| 574 | + drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100; |
---|
665 | 575 | phy_cfg.dp.ssc = analogix_dp_ssc_supported(dp); |
---|
666 | 576 | phy_cfg.dp.set_lanes = false; |
---|
667 | 577 | phy_cfg.dp.set_rate = true; |
---|
668 | 578 | phy_cfg.dp.set_voltages = false; |
---|
669 | 579 | ret = phy_configure(dp->phy, &phy_cfg); |
---|
670 | 580 | if (ret && ret != -EOPNOTSUPP) { |
---|
671 | | - dev_err(dp->dev, "%s: phy_configure() failed: %d\n", |
---|
| 581 | + dev_err(dp->dev, "%s: phy_configure failed: %d\n", |
---|
672 | 582 | __func__, ret); |
---|
673 | 583 | return; |
---|
674 | 584 | } |
---|
.. | .. |
---|
705 | 615 | analogix_dp_write(dp, ANALOGIX_DP_LANE_COUNT_SET, reg); |
---|
706 | 616 | |
---|
707 | 617 | if (dp->phy) { |
---|
708 | | - union phy_configure_opts phy_cfg; |
---|
| 618 | + union phy_configure_opts phy_cfg = {0}; |
---|
709 | 619 | |
---|
710 | 620 | phy_cfg.dp.lanes = dp->link_train.lane_count; |
---|
711 | 621 | phy_cfg.dp.set_lanes = true; |
---|
.. | .. |
---|
728 | 638 | *count = reg; |
---|
729 | 639 | } |
---|
730 | 640 | |
---|
731 | | -struct swing_pre_emp_ctrl { |
---|
732 | | - u8 amp; |
---|
733 | | - u8 emp; |
---|
734 | | -}; |
---|
735 | | - |
---|
736 | | -static const struct swing_pre_emp_ctrl swing_pre_emp_ctrl_rbr[4][4] = { |
---|
737 | | - /* voltage swing 0, pre-emphasis 0->3 */ |
---|
738 | | - { |
---|
739 | | - { .amp = 0x50, .emp = 0x00 }, |
---|
740 | | - { .amp = 0x6c, .emp = 0x28 }, |
---|
741 | | - { .amp = 0x80, .emp = 0x60 }, |
---|
742 | | - { .amp = 0xb0, .emp = 0xc4 }, |
---|
743 | | - }, |
---|
744 | | - /* voltage swing 1, pre-emphasis 0->3 */ |
---|
745 | | - { |
---|
746 | | - { .amp = 0x78, .emp = 0x00 }, |
---|
747 | | - { .amp = 0xa4, .emp = 0x50 }, |
---|
748 | | - { .amp = 0xcc, .emp = 0xa6 }, |
---|
749 | | - }, |
---|
750 | | - /* voltage swing 2, pre-emphasis 0->3 */ |
---|
751 | | - { |
---|
752 | | - { .amp = 0xa0, .emp = 0x00 }, |
---|
753 | | - { .amp = 0xe4, .emp = 0x72 }, |
---|
754 | | - }, |
---|
755 | | - /* voltage swing 3, pre-emphasis 0->3 */ |
---|
756 | | - { |
---|
757 | | - { .amp = 0xf0, .emp = 0x00 }, |
---|
758 | | - }, |
---|
759 | | -}; |
---|
760 | | - |
---|
761 | | -static const struct swing_pre_emp_ctrl swing_pre_emp_ctrl_hbr[4][4] = { |
---|
762 | | - /* voltage swing 0, pre-emphasis 0->3 */ |
---|
763 | | - { |
---|
764 | | - { .amp = 0x50, .emp = 0x00 }, |
---|
765 | | - { .amp = 0x6c, .emp = 0x34 }, |
---|
766 | | - { .amp = 0x80, .emp = 0x64 }, |
---|
767 | | - { .amp = 0xb8, .emp = 0xdc }, |
---|
768 | | - }, |
---|
769 | | - /* voltage swing 1, pre-emphasis 0->3 */ |
---|
770 | | - { |
---|
771 | | - { .amp = 0x78, .emp = 0x00 }, |
---|
772 | | - { .amp = 0xa8, .emp = 0x58 }, |
---|
773 | | - { .amp = 0xcc, .emp = 0xa8 }, |
---|
774 | | - }, |
---|
775 | | - /* voltage swing 2, pre-emphasis 0->3 */ |
---|
776 | | - { |
---|
777 | | - { .amp = 0xa0, .emp = 0x00 }, |
---|
778 | | - { .amp = 0xdd, .emp = 0x74 }, |
---|
779 | | - }, |
---|
780 | | - /* voltage swing 3, pre-emphasis 0->3 */ |
---|
781 | | - { |
---|
782 | | - { .amp = 0xf0, .emp = 0x00 }, |
---|
783 | | - }, |
---|
784 | | -}; |
---|
785 | | - |
---|
786 | | -static const struct swing_pre_emp_ctrl swing_pre_emp_ctrl_hbr2[4][4] = { |
---|
787 | | - /* voltage swing 0, pre-emphasis 0->3 */ |
---|
788 | | - { |
---|
789 | | - { .amp = 0x64, .emp = 0x1c }, |
---|
790 | | - { .amp = 0x90, .emp = 0x78 }, |
---|
791 | | - { .amp = 0xc4, .emp = 0xe0 }, |
---|
792 | | - { .amp = 0xa0, .emp = 0xa0 }, |
---|
793 | | - }, |
---|
794 | | - /* voltage swing 1, pre-emphasis 0->3 */ |
---|
795 | | - { |
---|
796 | | - { .amp = 0x9c, .emp = 0x3c }, |
---|
797 | | - { .amp = 0xe8, .emp = 0xd0 }, |
---|
798 | | - { .amp = 0xb4, .emp = 0x78 }, |
---|
799 | | - }, |
---|
800 | | - /* voltage swing 2, pre-emphasis 0->3 */ |
---|
801 | | - { |
---|
802 | | - { .amp = 0xe0, .emp = 0x68 }, |
---|
803 | | - { .amp = 0xe8, .emp = 0xd0 }, |
---|
804 | | - }, |
---|
805 | | - /* voltage swing 3, pre-emphasis 0->3 */ |
---|
806 | | - { |
---|
807 | | - { .amp = 0xf0, .emp = 0x00 }, |
---|
808 | | - }, |
---|
809 | | -}; |
---|
810 | | - |
---|
811 | 641 | void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp) |
---|
812 | 642 | { |
---|
813 | 643 | u8 lane; |
---|
.. | .. |
---|
819 | 649 | dp->link_train.training_lane[lane]); |
---|
820 | 650 | |
---|
821 | 651 | if (dp->phy) { |
---|
822 | | - union phy_configure_opts phy_cfg; |
---|
| 652 | + union phy_configure_opts phy_cfg = {0}; |
---|
823 | 653 | |
---|
824 | 654 | for (lane = 0; lane < dp->link_train.lane_count; lane++) { |
---|
825 | 655 | u8 training_lane = dp->link_train.training_lane[lane]; |
---|
.. | .. |
---|
834 | 664 | } |
---|
835 | 665 | |
---|
836 | 666 | phy_cfg.dp.lanes = dp->link_train.lane_count; |
---|
| 667 | + phy_cfg.dp.link_rate = |
---|
| 668 | + drm_dp_bw_code_to_link_rate(dp->link_train.link_rate) / 100; |
---|
837 | 669 | phy_cfg.dp.set_lanes = false; |
---|
838 | 670 | phy_cfg.dp.set_rate = false; |
---|
839 | 671 | phy_cfg.dp.set_voltages = true; |
---|
.. | .. |
---|
842 | 674 | dev_err(dp->dev, "%s: phy_configure() failed: %d\n", |
---|
843 | 675 | __func__, ret); |
---|
844 | 676 | return; |
---|
845 | | - } |
---|
846 | | - } else { |
---|
847 | | - const struct swing_pre_emp_ctrl *ctrl; |
---|
848 | | - |
---|
849 | | - for (lane = 0; lane < dp->link_train.lane_count; lane++) { |
---|
850 | | - u8 training_lane = dp->link_train.training_lane[lane]; |
---|
851 | | - u8 vs, pe; |
---|
852 | | - u32 reg; |
---|
853 | | - |
---|
854 | | - vs = (training_lane & DP_TRAIN_VOLTAGE_SWING_MASK) >> |
---|
855 | | - DP_TRAIN_VOLTAGE_SWING_SHIFT; |
---|
856 | | - pe = (training_lane & DP_TRAIN_PRE_EMPHASIS_MASK) >> |
---|
857 | | - DP_TRAIN_PRE_EMPHASIS_SHIFT; |
---|
858 | | - |
---|
859 | | - switch (dp->link_train.link_rate) { |
---|
860 | | - case DP_LINK_BW_1_62: |
---|
861 | | - ctrl = &swing_pre_emp_ctrl_rbr[vs][pe]; |
---|
862 | | - break; |
---|
863 | | - case DP_LINK_BW_2_7: |
---|
864 | | - ctrl = &swing_pre_emp_ctrl_hbr[vs][pe]; |
---|
865 | | - break; |
---|
866 | | - case DP_LINK_BW_5_4: |
---|
867 | | - default: |
---|
868 | | - ctrl = &swing_pre_emp_ctrl_hbr2[vs][pe]; |
---|
869 | | - break; |
---|
870 | | - } |
---|
871 | | - |
---|
872 | | - switch (lane) { |
---|
873 | | - case 0: |
---|
874 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_ANALOG_CTL_42); |
---|
875 | | - reg |= R_FORCE_CH0_AMP | R_FORCE_CH0_EMP; |
---|
876 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_42, reg); |
---|
877 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_36, ctrl->amp); |
---|
878 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_37, ctrl->emp); |
---|
879 | | - break; |
---|
880 | | - case 1: |
---|
881 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_ANALOG_CTL_42); |
---|
882 | | - reg |= R_FORCE_CH1_AMP | R_FORCE_CH1_EMP; |
---|
883 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_42, reg); |
---|
884 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_39, ctrl->amp); |
---|
885 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_40, ctrl->emp); |
---|
886 | | - break; |
---|
887 | | - case 2: |
---|
888 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_ANALOG_CTL_49); |
---|
889 | | - reg |= R_FORCE_CH2_AMP | R_FORCE_CH2_EMP; |
---|
890 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_49, reg); |
---|
891 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_43, ctrl->amp); |
---|
892 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_44, ctrl->emp); |
---|
893 | | - break; |
---|
894 | | - case 3: |
---|
895 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_ANALOG_CTL_49); |
---|
896 | | - reg |= R_FORCE_CH3_AMP | R_FORCE_CH3_EMP; |
---|
897 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_49, reg); |
---|
898 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_46, ctrl->amp); |
---|
899 | | - analogix_dp_write(dp, ANALOGIX_DP_ANALOG_CTL_47, ctrl->emp); |
---|
900 | | - break; |
---|
901 | | - } |
---|
902 | 677 | } |
---|
903 | 678 | } |
---|
904 | 679 | } |
---|
.. | .. |
---|
925 | 700 | } |
---|
926 | 701 | } |
---|
927 | 702 | |
---|
| 703 | +bool analogix_dp_get_enhanced_mode(struct analogix_dp_device *dp) |
---|
| 704 | +{ |
---|
| 705 | + u32 reg; |
---|
| 706 | + |
---|
| 707 | + reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4); |
---|
| 708 | + |
---|
| 709 | + return !!(reg & ENHANCED); |
---|
| 710 | +} |
---|
| 711 | + |
---|
928 | 712 | void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, |
---|
929 | 713 | enum pattern_set pattern) |
---|
930 | 714 | { |
---|
.. | .. |
---|
949 | 733 | break; |
---|
950 | 734 | case TRAINING_PTN3: |
---|
951 | 735 | reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN3; |
---|
| 736 | + analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg); |
---|
| 737 | + break; |
---|
| 738 | + case TEST_PATTERN_80BIT: |
---|
| 739 | + reg = 0x3e0f83e0; |
---|
| 740 | + analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN0, reg); |
---|
| 741 | + reg = 0x0f83e0f8; |
---|
| 742 | + analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN1, reg); |
---|
| 743 | + reg = 0x0000f83e; |
---|
| 744 | + analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN2, reg); |
---|
| 745 | + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_80BIT; |
---|
| 746 | + analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg); |
---|
| 747 | + break; |
---|
| 748 | + case TEST_PATTERN_HBR2: |
---|
| 749 | + reg = 0xfb; |
---|
| 750 | + analogix_dp_write(dp, ANALOGIX_DP_TEST_HBR2_PATTERN, reg); |
---|
| 751 | + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_HBR2; |
---|
952 | 752 | analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg); |
---|
953 | 753 | break; |
---|
954 | 754 | case DP_NONE: |
---|
.. | .. |
---|
990 | 790 | reg = CHA_CRI(4) | CHA_CTRL; |
---|
991 | 791 | analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg); |
---|
992 | 792 | |
---|
993 | | - reg = 0x0; |
---|
994 | | - analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg); |
---|
| 793 | + if (dp->video_info.force_stream_valid) { |
---|
| 794 | + reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3); |
---|
| 795 | + reg |= VALID_CTRL | F_VALID; |
---|
| 796 | + analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg); |
---|
| 797 | + } |
---|
995 | 798 | |
---|
996 | 799 | reg = VID_HRES_TH(2) | VID_VRES_TH(0); |
---|
997 | 800 | analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_8, reg); |
---|
.. | .. |
---|
1204 | 1007 | return status; |
---|
1205 | 1008 | } |
---|
1206 | 1009 | |
---|
| 1010 | +static void analogix_dp_reuse_spd(struct analogix_dp_device *dp) |
---|
| 1011 | +{ |
---|
| 1012 | + u32 reg, val; |
---|
| 1013 | + |
---|
| 1014 | + switch (dp->plat_data->dev_type) { |
---|
| 1015 | + case RK3588_EDP: |
---|
| 1016 | + reg = ANALOGIX_DP_SPDIF_AUDIO_CTL_0; |
---|
| 1017 | + break; |
---|
| 1018 | + default: |
---|
| 1019 | + reg = ANALOGIX_DP_VIDEO_CTL_3; |
---|
| 1020 | + break; |
---|
| 1021 | + } |
---|
| 1022 | + |
---|
| 1023 | + val = analogix_dp_read(dp, reg); |
---|
| 1024 | + val |= REUSE_SPD_EN; |
---|
| 1025 | + analogix_dp_write(dp, reg, val); |
---|
| 1026 | +} |
---|
| 1027 | + |
---|
1207 | 1028 | int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, |
---|
1208 | | - struct edp_vsc_psr *vsc, bool blocking) |
---|
| 1029 | + struct dp_sdp *vsc, bool blocking) |
---|
1209 | 1030 | { |
---|
1210 | 1031 | unsigned int val; |
---|
1211 | 1032 | int ret; |
---|
.. | .. |
---|
1233 | 1054 | analogix_dp_write(dp, ANALOGIX_DP_SPD_PB3, 0x5D); |
---|
1234 | 1055 | |
---|
1235 | 1056 | /* configure DB0 / DB1 values */ |
---|
1236 | | - analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB0, vsc->DB0); |
---|
1237 | | - analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB1, vsc->DB1); |
---|
| 1057 | + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB0, vsc->db[0]); |
---|
| 1058 | + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB1, vsc->db[1]); |
---|
| 1059 | + |
---|
| 1060 | + /* configure PB0 / PB1 values */ |
---|
| 1061 | + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_PB0, |
---|
| 1062 | + vsc->db[1] ? 0x8d : 0x00); |
---|
| 1063 | + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_PB1, 0x00); |
---|
1238 | 1064 | |
---|
1239 | 1065 | /* set reuse spd inforframe */ |
---|
1240 | | - val = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_3); |
---|
1241 | | - val |= REUSE_SPD_EN; |
---|
1242 | | - analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_3, val); |
---|
| 1066 | + analogix_dp_reuse_spd(dp); |
---|
1243 | 1067 | |
---|
1244 | 1068 | /* mark info frame update */ |
---|
1245 | 1069 | val = analogix_dp_read(dp, ANALOGIX_DP_PKT_SEND_CTL); |
---|
.. | .. |
---|
1254 | 1078 | if (!blocking) |
---|
1255 | 1079 | return 0; |
---|
1256 | 1080 | |
---|
| 1081 | + /* |
---|
| 1082 | + * db[1]!=0: entering PSR, wait for fully active remote frame buffer. |
---|
| 1083 | + * db[1]==0: exiting PSR, wait for either |
---|
| 1084 | + * (a) ACTIVE_RESYNC - the sink "must display the |
---|
| 1085 | + * incoming active frames from the Source device with no visible |
---|
| 1086 | + * glitches and/or artifacts", even though timings may still be |
---|
| 1087 | + * re-synchronizing; or |
---|
| 1088 | + * (b) INACTIVE - the transition is fully complete. |
---|
| 1089 | + */ |
---|
1257 | 1090 | ret = readx_poll_timeout(analogix_dp_get_psr_status, dp, psr_status, |
---|
1258 | 1091 | psr_status >= 0 && |
---|
1259 | | - ((vsc->DB1 && psr_status == DP_PSR_SINK_ACTIVE_RFB) || |
---|
1260 | | - (!vsc->DB1 && psr_status == DP_PSR_SINK_INACTIVE)), 1500, |
---|
1261 | | - DP_TIMEOUT_PSR_LOOP_MS * 1000); |
---|
| 1092 | + ((vsc->db[1] && psr_status == DP_PSR_SINK_ACTIVE_RFB) || |
---|
| 1093 | + (!vsc->db[1] && (psr_status == DP_PSR_SINK_ACTIVE_RESYNC || |
---|
| 1094 | + psr_status == DP_PSR_SINK_INACTIVE))), |
---|
| 1095 | + 1500, DP_TIMEOUT_PSR_LOOP_MS * 1000); |
---|
1262 | 1096 | if (ret) { |
---|
1263 | 1097 | dev_warn(dp->dev, "Failed to apply PSR %d\n", ret); |
---|
1264 | 1098 | return ret; |
---|
.. | .. |
---|
1266 | 1100 | return 0; |
---|
1267 | 1101 | } |
---|
1268 | 1102 | |
---|
1269 | | -void analogix_dp_phy_power_on(struct analogix_dp_device *dp) |
---|
| 1103 | +int analogix_dp_phy_power_on(struct analogix_dp_device *dp) |
---|
1270 | 1104 | { |
---|
1271 | | - if (dp->phy_enabled) |
---|
1272 | | - return; |
---|
| 1105 | + int ret; |
---|
1273 | 1106 | |
---|
1274 | | - phy_power_on(dp->phy); |
---|
| 1107 | + ret = phy_set_mode(dp->phy, PHY_MODE_DP); |
---|
| 1108 | + if (ret) { |
---|
| 1109 | + dev_err(dp->dev, "phy_set_mode failed: %d\n", ret); |
---|
| 1110 | + return ret; |
---|
| 1111 | + } |
---|
1275 | 1112 | |
---|
1276 | | - dp->phy_enabled = true; |
---|
| 1113 | + ret = phy_power_on(dp->phy); |
---|
| 1114 | + if (ret) { |
---|
| 1115 | + dev_err(dp->dev, "phy_power_on failed: %d\n", ret); |
---|
| 1116 | + return ret; |
---|
| 1117 | + } |
---|
| 1118 | + |
---|
| 1119 | + return ret; |
---|
1277 | 1120 | } |
---|
1278 | 1121 | |
---|
1279 | 1122 | void analogix_dp_phy_power_off(struct analogix_dp_device *dp) |
---|
1280 | 1123 | { |
---|
1281 | | - if (!dp->phy_enabled) |
---|
1282 | | - return; |
---|
1283 | | - |
---|
1284 | 1124 | phy_power_off(dp->phy); |
---|
1285 | | - |
---|
1286 | | - dp->phy_enabled = false; |
---|
1287 | 1125 | } |
---|
| 1126 | + |
---|
| 1127 | +enum { |
---|
| 1128 | + AUX_STATUS_OK, |
---|
| 1129 | + AUX_STATUS_NACK_ERROR, |
---|
| 1130 | + AUX_STATUS_TIMEOUT_ERROR, |
---|
| 1131 | + AUX_STATUS_UNKNOWN_ERROR, |
---|
| 1132 | + AUX_STATUS_MUCH_DEFER_ERROR, |
---|
| 1133 | + AUX_STATUS_TX_SHORT_ERROR, |
---|
| 1134 | + AUX_STATUS_RX_SHORT_ERROR, |
---|
| 1135 | + AUX_STATUS_NACK_WITHOUT_M_ERROR, |
---|
| 1136 | + AUX_STATUS_I2C_NACK_ERROR |
---|
| 1137 | +}; |
---|
1288 | 1138 | |
---|
1289 | 1139 | ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, |
---|
1290 | 1140 | struct drm_dp_aux_msg *msg) |
---|
1291 | 1141 | { |
---|
1292 | 1142 | u32 reg; |
---|
1293 | | - u32 status_reg; |
---|
1294 | 1143 | u8 *buffer = msg->buffer; |
---|
1295 | 1144 | unsigned int i; |
---|
1296 | 1145 | int num_transferred = 0; |
---|
.. | .. |
---|
1299 | 1148 | /* Buffer size of AUX CH is 16 bytes */ |
---|
1300 | 1149 | if (WARN_ON(msg->size > 16)) |
---|
1301 | 1150 | return -E2BIG; |
---|
1302 | | - |
---|
1303 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_FUNC_EN_2); |
---|
1304 | | - if (reg & AUX_FUNC_EN_N) { |
---|
1305 | | - analogix_dp_phy_power_on(dp); |
---|
1306 | | - analogix_dp_init_aux(dp); |
---|
1307 | | - } |
---|
1308 | 1151 | |
---|
1309 | 1152 | /* Clear AUX CH data buffer */ |
---|
1310 | 1153 | reg = BUF_CLR; |
---|
.. | .. |
---|
1383 | 1226 | /* Clear interrupt source for AUX CH command reply */ |
---|
1384 | 1227 | analogix_dp_write(dp, ANALOGIX_DP_INT_STA, RPLY_RECEIV); |
---|
1385 | 1228 | |
---|
1386 | | - /* Clear interrupt source for AUX CH access error */ |
---|
1387 | | - reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA); |
---|
1388 | | - status_reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_STA); |
---|
1389 | | - if ((reg & AUX_ERR) || (status_reg & AUX_STATUS_MASK)) { |
---|
1390 | | - analogix_dp_write(dp, ANALOGIX_DP_INT_STA, AUX_ERR); |
---|
1391 | | - |
---|
1392 | | - dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n", |
---|
1393 | | - status_reg & AUX_STATUS_MASK, !!(reg & AUX_ERR)); |
---|
1394 | | - goto aux_error; |
---|
1395 | | - } |
---|
| 1229 | + reg = analogix_dp_read(dp, ANALOGIX_DP_AUX_CH_STA); |
---|
| 1230 | + if ((reg & AUX_STATUS_MASK) == AUX_STATUS_TIMEOUT_ERROR) |
---|
| 1231 | + return -ETIMEDOUT; |
---|
1396 | 1232 | |
---|
1397 | 1233 | if (msg->request & DP_AUX_I2C_READ) { |
---|
| 1234 | + size_t buf_data_count; |
---|
| 1235 | + |
---|
| 1236 | + reg = analogix_dp_read(dp, ANALOGIX_DP_BUFFER_DATA_CTL); |
---|
| 1237 | + buf_data_count = BUF_DATA_COUNT(reg); |
---|
| 1238 | + |
---|
| 1239 | + if (buf_data_count != msg->size) |
---|
| 1240 | + return -EBUSY; |
---|
| 1241 | + |
---|
1398 | 1242 | for (i = 0; i < msg->size; i++) { |
---|
1399 | 1243 | reg = analogix_dp_read(dp, ANALOGIX_DP_BUF_DATA_0 + |
---|
1400 | 1244 | 4 * i); |
---|
.. | .. |
---|
1540 | 1384 | reg |= AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N; |
---|
1541 | 1385 | analogix_dp_write(dp, ANALOGIX_DP_FUNC_EN_1, reg); |
---|
1542 | 1386 | } |
---|
| 1387 | + |
---|
| 1388 | +void analogix_dp_init(struct analogix_dp_device *dp) |
---|
| 1389 | +{ |
---|
| 1390 | + analogix_dp_init_interrupt(dp); |
---|
| 1391 | + analogix_dp_config_interrupt(dp); |
---|
| 1392 | + analogix_dp_init_hpd(dp); |
---|
| 1393 | + analogix_dp_init_aux(dp); |
---|
| 1394 | +} |
---|