diff options
author | Dave Airlie <airlied@redhat.com> | 2015-02-23 18:24:04 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-03-19 12:26:51 -0400 |
commit | 9843ead08f18270948498f37eb95d6189eed31af (patch) | |
tree | 1453a3153aa11b3e94a1c34e7b5ac7aa1af44c41 /drivers/gpu/drm | |
parent | 8f0fc088f5fff0c2e4683bc0de7fc849e7d5357a (diff) |
drm/radeon: add DisplayPort MST support (v2)
This adds initial DP 1.2 MST support to radeon, on CAYMAN
and up in theory.
This is off by default.
v2: agd5f:
- add UNIPHY3 offsets
- move atom cmd table code into atombios_encoders.c
- whitespace cleanup
- replace some magic numbers with proper defines
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_encoders.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni_reg.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 64 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_dp_mst.c | 782 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 42 |
13 files changed, 998 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index fa635f09bb0f..dea53e36a2ef 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -81,7 +81,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
81 | rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \ | 81 | rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \ |
82 | trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \ | 82 | trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \ |
83 | ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \ | 83 | ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \ |
84 | radeon_sync.o radeon_audio.o radeon_dp_auxch.o | 84 | radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o |
85 | 85 | ||
86 | radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o | 86 | radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o |
87 | 87 | ||
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 36156ea92a93..dac78ad24b31 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -610,6 +610,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
610 | } | 610 | } |
611 | } | 611 | } |
612 | 612 | ||
613 | if (radeon_encoder->is_mst_encoder) { | ||
614 | struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv; | ||
615 | struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv; | ||
616 | |||
617 | dp_clock = dig_connector->dp_clock; | ||
618 | } | ||
619 | |||
613 | /* use recommended ref_div for ss */ | 620 | /* use recommended ref_div for ss */ |
614 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 621 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
615 | if (radeon_crtc->ss_enabled) { | 622 | if (radeon_crtc->ss_enabled) { |
@@ -956,7 +963,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ | |||
956 | radeon_crtc->bpc = 8; | 963 | radeon_crtc->bpc = 8; |
957 | radeon_crtc->ss_enabled = false; | 964 | radeon_crtc->ss_enabled = false; |
958 | 965 | ||
959 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || | 966 | if (radeon_encoder->is_mst_encoder) { |
967 | radeon_dp_mst_prepare_pll(crtc, mode); | ||
968 | } else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || | ||
960 | (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) { | 969 | (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) { |
961 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 970 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
962 | struct drm_connector *connector = | 971 | struct drm_connector *connector = |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 980cbccdf1a7..f57c1ab617bc 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
@@ -671,7 +671,15 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
671 | struct drm_connector *connector; | 671 | struct drm_connector *connector; |
672 | struct radeon_connector *radeon_connector; | 672 | struct radeon_connector *radeon_connector; |
673 | struct radeon_connector_atom_dig *dig_connector; | 673 | struct radeon_connector_atom_dig *dig_connector; |
674 | struct radeon_encoder_atom_dig *dig_enc; | ||
674 | 675 | ||
676 | if (radeon_encoder_is_digital(encoder)) { | ||
677 | dig_enc = radeon_encoder->enc_priv; | ||
678 | if (dig_enc->active_mst_links) | ||
679 | return ATOM_ENCODER_MODE_DP_MST; | ||
680 | } | ||
681 | if (radeon_encoder->is_mst_encoder || radeon_encoder->offset) | ||
682 | return ATOM_ENCODER_MODE_DP_MST; | ||
675 | /* dp bridges are always DP */ | 683 | /* dp bridges are always DP */ |
676 | if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) | 684 | if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) |
677 | return ATOM_ENCODER_MODE_DP; | 685 | return ATOM_ENCODER_MODE_DP; |
@@ -1706,6 +1714,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
1706 | case DRM_MODE_DPMS_STANDBY: | 1714 | case DRM_MODE_DPMS_STANDBY: |
1707 | case DRM_MODE_DPMS_SUSPEND: | 1715 | case DRM_MODE_DPMS_SUSPEND: |
1708 | case DRM_MODE_DPMS_OFF: | 1716 | case DRM_MODE_DPMS_OFF: |
1717 | |||
1718 | /* don't power off encoders with active MST links */ | ||
1719 | if (dig->active_mst_links) | ||
1720 | return; | ||
1721 | |||
1709 | if (ASIC_IS_DCE4(rdev)) { | 1722 | if (ASIC_IS_DCE4(rdev)) { |
1710 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) | 1723 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) |
1711 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); | 1724 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); |
@@ -1974,6 +1987,53 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
1974 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | 1987 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); |
1975 | } | 1988 | } |
1976 | 1989 | ||
1990 | void | ||
1991 | atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe) | ||
1992 | { | ||
1993 | struct drm_device *dev = encoder->dev; | ||
1994 | struct radeon_device *rdev = dev->dev_private; | ||
1995 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
1996 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); | ||
1997 | uint8_t frev, crev; | ||
1998 | union crtc_source_param args; | ||
1999 | |||
2000 | memset(&args, 0, sizeof(args)); | ||
2001 | |||
2002 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | ||
2003 | return; | ||
2004 | |||
2005 | if (frev != 1 && crev != 2) | ||
2006 | DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev); | ||
2007 | |||
2008 | args.v2.ucCRTC = radeon_crtc->crtc_id; | ||
2009 | args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST; | ||
2010 | |||
2011 | switch (fe) { | ||
2012 | case 0: | ||
2013 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | ||
2014 | break; | ||
2015 | case 1: | ||
2016 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
2017 | break; | ||
2018 | case 2: | ||
2019 | args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; | ||
2020 | break; | ||
2021 | case 3: | ||
2022 | args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; | ||
2023 | break; | ||
2024 | case 4: | ||
2025 | args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; | ||
2026 | break; | ||
2027 | case 5: | ||
2028 | args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; | ||
2029 | break; | ||
2030 | case 6: | ||
2031 | args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID; | ||
2032 | break; | ||
2033 | } | ||
2034 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2035 | } | ||
2036 | |||
1977 | static void | 2037 | static void |
1978 | atombios_apply_encoder_quirks(struct drm_encoder *encoder, | 2038 | atombios_apply_encoder_quirks(struct drm_encoder *encoder, |
1979 | struct drm_display_mode *mode) | 2039 | struct drm_display_mode *mode) |
diff --git a/drivers/gpu/drm/radeon/ni_reg.h b/drivers/gpu/drm/radeon/ni_reg.h index 96c23712776e..da310a70c0f0 100644 --- a/drivers/gpu/drm/radeon/ni_reg.h +++ b/drivers/gpu/drm/radeon/ni_reg.h | |||
@@ -93,6 +93,8 @@ | |||
93 | # define NI_DP_MSE_ZERO_ENCODER (((x) & 0x1) << 8) | 93 | # define NI_DP_MSE_ZERO_ENCODER (((x) & 0x1) << 8) |
94 | 94 | ||
95 | #define NI_DP_MSE_RATE_CNTL 0x7384 | 95 | #define NI_DP_MSE_RATE_CNTL 0x7384 |
96 | # define NI_DP_MSE_RATE_Y(x) (((x) & 0x3ffffff) << 0) | ||
97 | # define NI_DP_MSE_RATE_X(x) (((x) & 0x3f) << 26) | ||
96 | 98 | ||
97 | #define NI_DP_MSE_RATE_UPDATE 0x738c | 99 | #define NI_DP_MSE_RATE_UPDATE 0x738c |
98 | 100 | ||
@@ -111,6 +113,11 @@ | |||
111 | #define NI_DIG_BE_CNTL 0x7140 | 113 | #define NI_DIG_BE_CNTL 0x7140 |
112 | # define NI_DIG_FE_SOURCE_SELECT(x) (((x) & 0x7f) << 8) | 114 | # define NI_DIG_FE_SOURCE_SELECT(x) (((x) & 0x7f) << 8) |
113 | # define NI_DIG_FE_DIG_MODE(x) (((x) & 0x7) << 16) | 115 | # define NI_DIG_FE_DIG_MODE(x) (((x) & 0x7) << 16) |
116 | # define NI_DIG_MODE_DP_SST 0 | ||
117 | # define NI_DIG_MODE_LVDS 1 | ||
118 | # define NI_DIG_MODE_TMDS_DVI 2 | ||
119 | # define NI_DIG_MODE_TMDS_HDMI 3 | ||
120 | # define NI_DIG_MODE_DP_MST 5 | ||
114 | # define NI_DIG_HPD_SELECT(x) (((x) & 0x7) << 28) | 121 | # define NI_DIG_HPD_SELECT(x) (((x) & 0x7) << 28) |
115 | 122 | ||
116 | #define NI_DIG_FE_CNTL 0x7000 | 123 | #define NI_DIG_FE_CNTL 0x7000 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 1506332d6f22..35ab65d53cc1 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -112,6 +112,7 @@ extern int radeon_use_pflipirq; | |||
112 | extern int radeon_bapm; | 112 | extern int radeon_bapm; |
113 | extern int radeon_backlight; | 113 | extern int radeon_backlight; |
114 | extern int radeon_auxch; | 114 | extern int radeon_auxch; |
115 | extern int radeon_mst; | ||
115 | 116 | ||
116 | /* | 117 | /* |
117 | * Copy from radeon_drv.h so we don't have to include both and have conflicting | 118 | * Copy from radeon_drv.h so we don't have to include both and have conflicting |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fc1b3f34cf18..8f285244c839 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -845,6 +845,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
845 | 845 | ||
846 | radeon_link_encoder_connector(dev); | 846 | radeon_link_encoder_connector(dev); |
847 | 847 | ||
848 | radeon_setup_mst_connector(dev); | ||
848 | return true; | 849 | return true; |
849 | } | 850 | } |
850 | 851 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 0a371a13da94..7ffa7d5563b9 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <drm/drm_edid.h> | 27 | #include <drm/drm_edid.h> |
28 | #include <drm/drm_crtc_helper.h> | 28 | #include <drm/drm_crtc_helper.h> |
29 | #include <drm/drm_fb_helper.h> | 29 | #include <drm/drm_fb_helper.h> |
30 | #include <drm/drm_dp_mst_helper.h> | ||
30 | #include <drm/radeon_drm.h> | 31 | #include <drm/radeon_drm.h> |
31 | #include "radeon.h" | 32 | #include "radeon.h" |
32 | #include "radeon_audio.h" | 33 | #include "radeon_audio.h" |
@@ -34,12 +35,33 @@ | |||
34 | 35 | ||
35 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
36 | 37 | ||
38 | static int radeon_dp_handle_hpd(struct drm_connector *connector) | ||
39 | { | ||
40 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
41 | int ret; | ||
42 | |||
43 | ret = radeon_dp_mst_check_status(radeon_connector); | ||
44 | if (ret == -EINVAL) | ||
45 | return 1; | ||
46 | return 0; | ||
47 | } | ||
37 | void radeon_connector_hotplug(struct drm_connector *connector) | 48 | void radeon_connector_hotplug(struct drm_connector *connector) |
38 | { | 49 | { |
39 | struct drm_device *dev = connector->dev; | 50 | struct drm_device *dev = connector->dev; |
40 | struct radeon_device *rdev = dev->dev_private; | 51 | struct radeon_device *rdev = dev->dev_private; |
41 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 52 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
42 | 53 | ||
54 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { | ||
55 | struct radeon_connector_atom_dig *dig_connector = | ||
56 | radeon_connector->con_priv; | ||
57 | |||
58 | if (radeon_connector->is_mst_connector) | ||
59 | return; | ||
60 | if (dig_connector->is_mst) { | ||
61 | radeon_dp_handle_hpd(connector); | ||
62 | return; | ||
63 | } | ||
64 | } | ||
43 | /* bail if the connector does not have hpd pin, e.g., | 65 | /* bail if the connector does not have hpd pin, e.g., |
44 | * VGA, TV, etc. | 66 | * VGA, TV, etc. |
45 | */ | 67 | */ |
@@ -1609,6 +1631,9 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
1609 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | 1631 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
1610 | int r; | 1632 | int r; |
1611 | 1633 | ||
1634 | if (radeon_dig_connector->is_mst) | ||
1635 | return connector_status_disconnected; | ||
1636 | |||
1612 | r = pm_runtime_get_sync(connector->dev->dev); | 1637 | r = pm_runtime_get_sync(connector->dev->dev); |
1613 | if (r < 0) | 1638 | if (r < 0) |
1614 | return connector_status_disconnected; | 1639 | return connector_status_disconnected; |
@@ -1667,12 +1692,21 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
1667 | radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); | 1692 | radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); |
1668 | if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { | 1693 | if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { |
1669 | ret = connector_status_connected; | 1694 | ret = connector_status_connected; |
1670 | if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) | 1695 | if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { |
1671 | radeon_dp_getdpcd(radeon_connector); | 1696 | radeon_dp_getdpcd(radeon_connector); |
1697 | r = radeon_dp_mst_probe(radeon_connector); | ||
1698 | if (r == 1) | ||
1699 | ret = connector_status_disconnected; | ||
1700 | } | ||
1672 | } else { | 1701 | } else { |
1673 | if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { | 1702 | if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { |
1674 | if (radeon_dp_getdpcd(radeon_connector)) | 1703 | if (radeon_dp_getdpcd(radeon_connector)) { |
1675 | ret = connector_status_connected; | 1704 | r = radeon_dp_mst_probe(radeon_connector); |
1705 | if (r == 1) | ||
1706 | ret = connector_status_disconnected; | ||
1707 | else | ||
1708 | ret = connector_status_connected; | ||
1709 | } | ||
1676 | } else { | 1710 | } else { |
1677 | /* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */ | 1711 | /* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */ |
1678 | if (radeon_ddc_probe(radeon_connector, false)) | 1712 | if (radeon_ddc_probe(radeon_connector, false)) |
@@ -2404,3 +2438,27 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
2404 | connector->display_info.subpixel_order = subpixel_order; | 2438 | connector->display_info.subpixel_order = subpixel_order; |
2405 | drm_connector_register(connector); | 2439 | drm_connector_register(connector); |
2406 | } | 2440 | } |
2441 | |||
2442 | void radeon_setup_mst_connector(struct drm_device *dev) | ||
2443 | { | ||
2444 | struct radeon_device *rdev = dev->dev_private; | ||
2445 | struct drm_connector *connector; | ||
2446 | struct radeon_connector *radeon_connector; | ||
2447 | |||
2448 | if (!ASIC_IS_DCE5(rdev)) | ||
2449 | return; | ||
2450 | |||
2451 | if (radeon_mst == 0) | ||
2452 | return; | ||
2453 | |||
2454 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
2455 | int ret; | ||
2456 | |||
2457 | radeon_connector = to_radeon_connector(connector); | ||
2458 | |||
2459 | if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) | ||
2460 | continue; | ||
2461 | |||
2462 | ret = radeon_dp_mst_init(radeon_connector); | ||
2463 | } | ||
2464 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bd7519fdd3f4..b7ca4c514621 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -1442,6 +1442,11 @@ int radeon_device_init(struct radeon_device *rdev, | |||
1442 | DRM_ERROR("registering gem debugfs failed (%d).\n", r); | 1442 | DRM_ERROR("registering gem debugfs failed (%d).\n", r); |
1443 | } | 1443 | } |
1444 | 1444 | ||
1445 | r = radeon_mst_debugfs_init(rdev); | ||
1446 | if (r) { | ||
1447 | DRM_ERROR("registering mst debugfs failed (%d).\n", r); | ||
1448 | } | ||
1449 | |||
1445 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { | 1450 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { |
1446 | /* Acceleration not working on AGP card try again | 1451 | /* Acceleration not working on AGP card try again |
1447 | * with fallback to PCI or PCIE GART | 1452 | * with fallback to PCI or PCIE GART |
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c new file mode 100644 index 000000000000..5952ff2bb647 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c | |||
@@ -0,0 +1,782 @@ | |||
1 | |||
2 | #include <drm/drmP.h> | ||
3 | #include <drm/drm_dp_mst_helper.h> | ||
4 | #include <drm/drm_fb_helper.h> | ||
5 | |||
6 | #include "radeon.h" | ||
7 | #include "atom.h" | ||
8 | #include "ni_reg.h" | ||
9 | |||
10 | static struct radeon_encoder *radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector); | ||
11 | |||
12 | static int radeon_atom_set_enc_offset(int id) | ||
13 | { | ||
14 | static const int offsets[] = { EVERGREEN_CRTC0_REGISTER_OFFSET, | ||
15 | EVERGREEN_CRTC1_REGISTER_OFFSET, | ||
16 | EVERGREEN_CRTC2_REGISTER_OFFSET, | ||
17 | EVERGREEN_CRTC3_REGISTER_OFFSET, | ||
18 | EVERGREEN_CRTC4_REGISTER_OFFSET, | ||
19 | EVERGREEN_CRTC5_REGISTER_OFFSET, | ||
20 | 0x13830 - 0x7030 }; | ||
21 | |||
22 | return offsets[id]; | ||
23 | } | ||
24 | |||
25 | static int radeon_dp_mst_set_be_cntl(struct radeon_encoder *primary, | ||
26 | struct radeon_encoder_mst *mst_enc, | ||
27 | enum radeon_hpd_id hpd, bool enable) | ||
28 | { | ||
29 | struct drm_device *dev = primary->base.dev; | ||
30 | struct radeon_device *rdev = dev->dev_private; | ||
31 | uint32_t reg; | ||
32 | int retries = 0; | ||
33 | uint32_t temp; | ||
34 | |||
35 | reg = RREG32(NI_DIG_BE_CNTL + primary->offset); | ||
36 | |||
37 | /* set MST mode */ | ||
38 | reg &= ~NI_DIG_FE_DIG_MODE(7); | ||
39 | reg |= NI_DIG_FE_DIG_MODE(NI_DIG_MODE_DP_MST); | ||
40 | |||
41 | if (enable) | ||
42 | reg |= NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe); | ||
43 | else | ||
44 | reg &= ~NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe); | ||
45 | |||
46 | reg |= NI_DIG_HPD_SELECT(hpd); | ||
47 | DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DIG_BE_CNTL + primary->offset, reg); | ||
48 | WREG32(NI_DIG_BE_CNTL + primary->offset, reg); | ||
49 | |||
50 | if (enable) { | ||
51 | uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe); | ||
52 | |||
53 | do { | ||
54 | temp = RREG32(NI_DIG_FE_CNTL + offset); | ||
55 | } while ((temp & NI_DIG_SYMCLK_FE_ON) && retries++ < 10000); | ||
56 | if (retries == 10000) | ||
57 | DRM_ERROR("timed out waiting for FE %d %d\n", primary->offset, mst_enc->fe); | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int radeon_dp_mst_set_stream_attrib(struct radeon_encoder *primary, | ||
63 | int stream_number, | ||
64 | int fe, | ||
65 | int slots) | ||
66 | { | ||
67 | struct drm_device *dev = primary->base.dev; | ||
68 | struct radeon_device *rdev = dev->dev_private; | ||
69 | u32 temp, val; | ||
70 | int retries = 0; | ||
71 | int satreg, satidx; | ||
72 | |||
73 | satreg = stream_number >> 1; | ||
74 | satidx = stream_number & 1; | ||
75 | |||
76 | temp = RREG32(NI_DP_MSE_SAT0 + satreg + primary->offset); | ||
77 | |||
78 | val = NI_DP_MSE_SAT_SLOT_COUNT0(slots) | NI_DP_MSE_SAT_SRC0(fe); | ||
79 | |||
80 | val <<= (16 * satidx); | ||
81 | |||
82 | temp &= ~(0xffff << (16 * satidx)); | ||
83 | |||
84 | temp |= val; | ||
85 | |||
86 | DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DP_MSE_SAT0 + satreg + primary->offset, temp); | ||
87 | WREG32(NI_DP_MSE_SAT0 + satreg + primary->offset, temp); | ||
88 | |||
89 | WREG32(NI_DP_MSE_SAT_UPDATE + primary->offset, 1); | ||
90 | |||
91 | do { | ||
92 | temp = RREG32(NI_DP_MSE_SAT_UPDATE + primary->offset); | ||
93 | } while ((temp & 0x1) && retries++ < 10000); | ||
94 | |||
95 | if (retries == 10000) | ||
96 | DRM_ERROR("timed out waitin for SAT update %d\n", primary->offset); | ||
97 | |||
98 | /* MTP 16 ? */ | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int radeon_dp_mst_update_stream_attribs(struct radeon_connector *mst_conn, | ||
103 | struct radeon_encoder *primary) | ||
104 | { | ||
105 | struct drm_device *dev = mst_conn->base.dev; | ||
106 | struct stream_attribs new_attribs[6]; | ||
107 | int i; | ||
108 | int idx = 0; | ||
109 | struct radeon_connector *radeon_connector; | ||
110 | struct drm_connector *connector; | ||
111 | |||
112 | memset(new_attribs, 0, sizeof(new_attribs)); | ||
113 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
114 | struct radeon_encoder *subenc; | ||
115 | struct radeon_encoder_mst *mst_enc; | ||
116 | |||
117 | radeon_connector = to_radeon_connector(connector); | ||
118 | if (!radeon_connector->is_mst_connector) | ||
119 | continue; | ||
120 | |||
121 | if (radeon_connector->mst_port != mst_conn) | ||
122 | continue; | ||
123 | |||
124 | subenc = radeon_connector->mst_encoder; | ||
125 | mst_enc = subenc->enc_priv; | ||
126 | |||
127 | if (!mst_enc->enc_active) | ||
128 | continue; | ||
129 | |||
130 | new_attribs[idx].fe = mst_enc->fe; | ||
131 | new_attribs[idx].slots = drm_dp_mst_get_vcpi_slots(&mst_conn->mst_mgr, mst_enc->port); | ||
132 | idx++; | ||
133 | } | ||
134 | |||
135 | for (i = 0; i < idx; i++) { | ||
136 | if (new_attribs[i].fe != mst_conn->cur_stream_attribs[i].fe || | ||
137 | new_attribs[i].slots != mst_conn->cur_stream_attribs[i].slots) { | ||
138 | radeon_dp_mst_set_stream_attrib(primary, i, new_attribs[i].fe, new_attribs[i].slots); | ||
139 | mst_conn->cur_stream_attribs[i].fe = new_attribs[i].fe; | ||
140 | mst_conn->cur_stream_attribs[i].slots = new_attribs[i].slots; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | for (i = idx; i < mst_conn->enabled_attribs; i++) { | ||
145 | radeon_dp_mst_set_stream_attrib(primary, i, 0, 0); | ||
146 | mst_conn->cur_stream_attribs[i].fe = 0; | ||
147 | mst_conn->cur_stream_attribs[i].slots = 0; | ||
148 | } | ||
149 | mst_conn->enabled_attribs = idx; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, uint32_t y) | ||
154 | { | ||
155 | struct drm_device *dev = mst->base.dev; | ||
156 | struct radeon_device *rdev = dev->dev_private; | ||
157 | struct radeon_encoder_mst *mst_enc = mst->enc_priv; | ||
158 | uint32_t val, temp; | ||
159 | uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe); | ||
160 | int retries = 0; | ||
161 | |||
162 | val = NI_DP_MSE_RATE_X(x) | NI_DP_MSE_RATE_Y(y); | ||
163 | |||
164 | WREG32(NI_DP_MSE_RATE_CNTL + offset, val); | ||
165 | |||
166 | do { | ||
167 | temp = RREG32(NI_DP_MSE_RATE_UPDATE + offset); | ||
168 | } while ((temp & 0x1) && (retries++ < 10000)); | ||
169 | |||
170 | if (retries >= 10000) | ||
171 | DRM_ERROR("timed out wait for rate cntl %d\n", mst_enc->fe); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector) | ||
176 | { | ||
177 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
178 | struct radeon_connector *master = radeon_connector->mst_port; | ||
179 | struct edid *edid; | ||
180 | int ret = 0; | ||
181 | |||
182 | edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port); | ||
183 | radeon_connector->edid = edid; | ||
184 | DRM_DEBUG_KMS("edid retrieved %p\n", edid); | ||
185 | if (radeon_connector->edid) { | ||
186 | drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); | ||
187 | ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); | ||
188 | drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid); | ||
189 | return ret; | ||
190 | } | ||
191 | drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int radeon_dp_mst_get_modes(struct drm_connector *connector) | ||
197 | { | ||
198 | return radeon_dp_mst_get_ddc_modes(connector); | ||
199 | } | ||
200 | |||
201 | static enum drm_mode_status | ||
202 | radeon_dp_mst_mode_valid(struct drm_connector *connector, | ||
203 | struct drm_display_mode *mode) | ||
204 | { | ||
205 | /* TODO - validate mode against available PBN for link */ | ||
206 | if (mode->clock < 10000) | ||
207 | return MODE_CLOCK_LOW; | ||
208 | |||
209 | if (mode->flags & DRM_MODE_FLAG_DBLCLK) | ||
210 | return MODE_H_ILLEGAL; | ||
211 | |||
212 | return MODE_OK; | ||
213 | } | ||
214 | |||
215 | struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector) | ||
216 | { | ||
217 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
218 | |||
219 | return &radeon_connector->mst_encoder->base; | ||
220 | } | ||
221 | |||
222 | static const struct drm_connector_helper_funcs radeon_dp_mst_connector_helper_funcs = { | ||
223 | .get_modes = radeon_dp_mst_get_modes, | ||
224 | .mode_valid = radeon_dp_mst_mode_valid, | ||
225 | .best_encoder = radeon_mst_best_encoder, | ||
226 | }; | ||
227 | |||
228 | static enum drm_connector_status | ||
229 | radeon_dp_mst_detect(struct drm_connector *connector, bool force) | ||
230 | { | ||
231 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
232 | struct radeon_connector *master = radeon_connector->mst_port; | ||
233 | |||
234 | return drm_dp_mst_detect_port(connector, &master->mst_mgr, radeon_connector->port); | ||
235 | } | ||
236 | |||
237 | static void | ||
238 | radeon_dp_mst_connector_destroy(struct drm_connector *connector) | ||
239 | { | ||
240 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
241 | struct radeon_encoder *radeon_encoder = radeon_connector->mst_encoder; | ||
242 | |||
243 | drm_encoder_cleanup(&radeon_encoder->base); | ||
244 | kfree(radeon_encoder); | ||
245 | drm_connector_cleanup(connector); | ||
246 | kfree(radeon_connector); | ||
247 | } | ||
248 | |||
249 | static void radeon_connector_dpms(struct drm_connector *connector, int mode) | ||
250 | { | ||
251 | DRM_DEBUG_KMS("\n"); | ||
252 | } | ||
253 | |||
254 | static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = { | ||
255 | .dpms = radeon_connector_dpms, | ||
256 | .detect = radeon_dp_mst_detect, | ||
257 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
258 | .destroy = radeon_dp_mst_connector_destroy, | ||
259 | }; | ||
260 | |||
261 | static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, | ||
262 | struct drm_dp_mst_port *port, | ||
263 | const char *pathprop) | ||
264 | { | ||
265 | struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr); | ||
266 | struct drm_device *dev = master->base.dev; | ||
267 | struct radeon_device *rdev = dev->dev_private; | ||
268 | struct radeon_connector *radeon_connector; | ||
269 | struct drm_connector *connector; | ||
270 | |||
271 | radeon_connector = kzalloc(sizeof(*radeon_connector), GFP_KERNEL); | ||
272 | if (!radeon_connector) | ||
273 | return NULL; | ||
274 | |||
275 | radeon_connector->is_mst_connector = true; | ||
276 | connector = &radeon_connector->base; | ||
277 | radeon_connector->port = port; | ||
278 | radeon_connector->mst_port = master; | ||
279 | DRM_DEBUG_KMS("\n"); | ||
280 | |||
281 | drm_connector_init(dev, connector, &radeon_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); | ||
282 | drm_connector_helper_add(connector, &radeon_dp_mst_connector_helper_funcs); | ||
283 | radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master); | ||
284 | |||
285 | drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); | ||
286 | drm_mode_connector_set_path_property(connector, pathprop); | ||
287 | drm_reinit_primary_mode_group(dev); | ||
288 | |||
289 | mutex_lock(&dev->mode_config.mutex); | ||
290 | radeon_fb_add_connector(rdev, connector); | ||
291 | mutex_unlock(&dev->mode_config.mutex); | ||
292 | |||
293 | drm_connector_register(connector); | ||
294 | return connector; | ||
295 | } | ||
296 | |||
297 | static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, | ||
298 | struct drm_connector *connector) | ||
299 | { | ||
300 | struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr); | ||
301 | struct drm_device *dev = master->base.dev; | ||
302 | struct radeon_device *rdev = dev->dev_private; | ||
303 | |||
304 | drm_connector_unregister(connector); | ||
305 | /* need to nuke the connector */ | ||
306 | mutex_lock(&dev->mode_config.mutex); | ||
307 | /* dpms off */ | ||
308 | radeon_fb_remove_connector(rdev, connector); | ||
309 | |||
310 | drm_connector_cleanup(connector); | ||
311 | mutex_unlock(&dev->mode_config.mutex); | ||
312 | drm_reinit_primary_mode_group(dev); | ||
313 | |||
314 | |||
315 | kfree(connector); | ||
316 | DRM_DEBUG_KMS("\n"); | ||
317 | } | ||
318 | |||
319 | static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) | ||
320 | { | ||
321 | struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr); | ||
322 | struct drm_device *dev = master->base.dev; | ||
323 | |||
324 | drm_kms_helper_hotplug_event(dev); | ||
325 | } | ||
326 | |||
327 | struct drm_dp_mst_topology_cbs mst_cbs = { | ||
328 | .add_connector = radeon_dp_add_mst_connector, | ||
329 | .destroy_connector = radeon_dp_destroy_mst_connector, | ||
330 | .hotplug = radeon_dp_mst_hotplug, | ||
331 | }; | ||
332 | |||
333 | struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder) | ||
334 | { | ||
335 | struct drm_device *dev = encoder->dev; | ||
336 | struct drm_connector *connector; | ||
337 | |||
338 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
339 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
340 | if (!connector->encoder) | ||
341 | continue; | ||
342 | if (!radeon_connector->is_mst_connector) | ||
343 | continue; | ||
344 | |||
345 | DRM_DEBUG_KMS("checking %p vs %p\n", connector->encoder, encoder); | ||
346 | if (connector->encoder == encoder) | ||
347 | return radeon_connector; | ||
348 | } | ||
349 | return NULL; | ||
350 | } | ||
351 | |||
352 | void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
353 | { | ||
354 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
355 | struct drm_device *dev = crtc->dev; | ||
356 | struct radeon_device *rdev = dev->dev_private; | ||
357 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder); | ||
358 | struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv; | ||
359 | struct radeon_connector *radeon_connector = radeon_mst_find_connector(&radeon_encoder->base); | ||
360 | int dp_clock; | ||
361 | struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv; | ||
362 | |||
363 | if (radeon_connector) { | ||
364 | radeon_connector->pixelclock_for_modeset = mode->clock; | ||
365 | if (radeon_connector->base.display_info.bpc) | ||
366 | radeon_crtc->bpc = radeon_connector->base.display_info.bpc; | ||
367 | else | ||
368 | radeon_crtc->bpc = 8; | ||
369 | } | ||
370 | |||
371 | DRM_DEBUG_KMS("dp_clock %p %d\n", dig_connector, dig_connector->dp_clock); | ||
372 | dp_clock = dig_connector->dp_clock; | ||
373 | radeon_crtc->ss_enabled = | ||
374 | radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss, | ||
375 | ASIC_INTERNAL_SS_ON_DP, | ||
376 | dp_clock); | ||
377 | } | ||
378 | |||
379 | static void | ||
380 | radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
381 | { | ||
382 | struct drm_device *dev = encoder->dev; | ||
383 | struct radeon_device *rdev = dev->dev_private; | ||
384 | struct radeon_encoder *radeon_encoder, *primary; | ||
385 | struct radeon_encoder_mst *mst_enc; | ||
386 | struct radeon_encoder_atom_dig *dig_enc; | ||
387 | struct radeon_connector *radeon_connector; | ||
388 | struct drm_crtc *crtc; | ||
389 | struct radeon_crtc *radeon_crtc; | ||
390 | int ret, slots; | ||
391 | |||
392 | if (!ASIC_IS_DCE5(rdev)) { | ||
393 | DRM_ERROR("got mst dpms on non-DCE5\n"); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | radeon_connector = radeon_mst_find_connector(encoder); | ||
398 | if (!radeon_connector) | ||
399 | return; | ||
400 | |||
401 | radeon_encoder = to_radeon_encoder(encoder); | ||
402 | |||
403 | mst_enc = radeon_encoder->enc_priv; | ||
404 | |||
405 | primary = mst_enc->primary; | ||
406 | |||
407 | dig_enc = primary->enc_priv; | ||
408 | |||
409 | crtc = encoder->crtc; | ||
410 | DRM_DEBUG_KMS("got connector %d\n", dig_enc->active_mst_links); | ||
411 | |||
412 | switch (mode) { | ||
413 | case DRM_MODE_DPMS_ON: | ||
414 | dig_enc->active_mst_links++; | ||
415 | |||
416 | radeon_crtc = to_radeon_crtc(crtc); | ||
417 | |||
418 | if (dig_enc->active_mst_links == 1) { | ||
419 | mst_enc->fe = dig_enc->dig_encoder; | ||
420 | mst_enc->fe_from_be = true; | ||
421 | atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe); | ||
422 | |||
423 | atombios_dig_encoder_setup(&primary->base, ATOM_ENCODER_CMD_SETUP, 0); | ||
424 | atombios_dig_transmitter_setup2(&primary->base, ATOM_TRANSMITTER_ACTION_ENABLE, | ||
425 | 0, 0, dig_enc->dig_encoder); | ||
426 | |||
427 | if (radeon_dp_needs_link_train(mst_enc->connector) || | ||
428 | dig_enc->active_mst_links == 1) { | ||
429 | radeon_dp_link_train(&primary->base, &mst_enc->connector->base); | ||
430 | } | ||
431 | |||
432 | } else { | ||
433 | mst_enc->fe = radeon_atom_pick_dig_encoder(encoder, radeon_crtc->crtc_id); | ||
434 | if (mst_enc->fe == -1) | ||
435 | DRM_ERROR("failed to get frontend for dig encoder\n"); | ||
436 | mst_enc->fe_from_be = false; | ||
437 | atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe); | ||
438 | } | ||
439 | |||
440 | DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder, | ||
441 | dig_enc->linkb, radeon_crtc->crtc_id); | ||
442 | |||
443 | ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr, | ||
444 | radeon_connector->port, | ||
445 | mst_enc->pbn, &slots); | ||
446 | ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr); | ||
447 | |||
448 | radeon_dp_mst_set_be_cntl(primary, mst_enc, | ||
449 | radeon_connector->mst_port->hpd.hpd, true); | ||
450 | |||
451 | mst_enc->enc_active = true; | ||
452 | radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary); | ||
453 | radeon_dp_mst_set_vcp_size(radeon_encoder, slots, 0); | ||
454 | |||
455 | atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0, | ||
456 | mst_enc->fe); | ||
457 | ret = drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr); | ||
458 | |||
459 | ret = drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr); | ||
460 | |||
461 | break; | ||
462 | case DRM_MODE_DPMS_STANDBY: | ||
463 | case DRM_MODE_DPMS_SUSPEND: | ||
464 | case DRM_MODE_DPMS_OFF: | ||
465 | DRM_ERROR("DPMS OFF %d\n", dig_enc->active_mst_links); | ||
466 | |||
467 | if (!mst_enc->enc_active) | ||
468 | return; | ||
469 | |||
470 | drm_dp_mst_reset_vcpi_slots(&radeon_connector->mst_port->mst_mgr, mst_enc->port); | ||
471 | ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr); | ||
472 | |||
473 | drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr); | ||
474 | /* and this can also fail */ | ||
475 | drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr); | ||
476 | |||
477 | drm_dp_mst_deallocate_vcpi(&radeon_connector->mst_port->mst_mgr, mst_enc->port); | ||
478 | |||
479 | mst_enc->enc_active = false; | ||
480 | radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary); | ||
481 | |||
482 | radeon_dp_mst_set_be_cntl(primary, mst_enc, | ||
483 | radeon_connector->mst_port->hpd.hpd, false); | ||
484 | atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0, | ||
485 | mst_enc->fe); | ||
486 | |||
487 | if (!mst_enc->fe_from_be) | ||
488 | radeon_atom_release_dig_encoder(rdev, mst_enc->fe); | ||
489 | |||
490 | mst_enc->fe_from_be = false; | ||
491 | dig_enc->active_mst_links--; | ||
492 | if (dig_enc->active_mst_links == 0) { | ||
493 | /* drop link */ | ||
494 | } | ||
495 | |||
496 | break; | ||
497 | } | ||
498 | |||
499 | } | ||
500 | |||
501 | static bool radeon_mst_mode_fixup(struct drm_encoder *encoder, | ||
502 | const struct drm_display_mode *mode, | ||
503 | struct drm_display_mode *adjusted_mode) | ||
504 | { | ||
505 | struct radeon_encoder_mst *mst_enc; | ||
506 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
507 | int bpp = 24; | ||
508 | |||
509 | mst_enc = radeon_encoder->enc_priv; | ||
510 | |||
511 | mst_enc->pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp); | ||
512 | |||
513 | mst_enc->primary->active_device = mst_enc->primary->devices & mst_enc->connector->devices; | ||
514 | DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", | ||
515 | mst_enc->primary->active_device, mst_enc->primary->devices, | ||
516 | mst_enc->connector->devices, mst_enc->primary->base.encoder_type); | ||
517 | |||
518 | |||
519 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
520 | { | ||
521 | struct radeon_connector_atom_dig *dig_connector; | ||
522 | |||
523 | dig_connector = mst_enc->connector->con_priv; | ||
524 | dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd); | ||
525 | dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base, | ||
526 | dig_connector->dpcd); | ||
527 | DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector, | ||
528 | dig_connector->dp_lane_count, dig_connector->dp_clock); | ||
529 | } | ||
530 | return true; | ||
531 | } | ||
532 | |||
533 | static void radeon_mst_encoder_prepare(struct drm_encoder *encoder) | ||
534 | { | ||
535 | struct radeon_connector *radeon_connector; | ||
536 | struct radeon_encoder *radeon_encoder, *primary; | ||
537 | struct radeon_encoder_mst *mst_enc; | ||
538 | struct radeon_encoder_atom_dig *dig_enc; | ||
539 | |||
540 | radeon_connector = radeon_mst_find_connector(encoder); | ||
541 | if (!radeon_connector) { | ||
542 | DRM_DEBUG_KMS("failed to find connector %p\n", encoder); | ||
543 | return; | ||
544 | } | ||
545 | radeon_encoder = to_radeon_encoder(encoder); | ||
546 | |||
547 | radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
548 | |||
549 | mst_enc = radeon_encoder->enc_priv; | ||
550 | |||
551 | primary = mst_enc->primary; | ||
552 | |||
553 | dig_enc = primary->enc_priv; | ||
554 | |||
555 | mst_enc->port = radeon_connector->port; | ||
556 | |||
557 | if (dig_enc->dig_encoder == -1) { | ||
558 | dig_enc->dig_encoder = radeon_atom_pick_dig_encoder(&primary->base, -1); | ||
559 | primary->offset = radeon_atom_set_enc_offset(dig_enc->dig_encoder); | ||
560 | atombios_set_mst_encoder_crtc_source(encoder, dig_enc->dig_encoder); | ||
561 | |||
562 | |||
563 | } | ||
564 | DRM_DEBUG_KMS("%d %d\n", dig_enc->dig_encoder, primary->offset); | ||
565 | } | ||
566 | |||
567 | static void | ||
568 | radeon_mst_encoder_mode_set(struct drm_encoder *encoder, | ||
569 | struct drm_display_mode *mode, | ||
570 | struct drm_display_mode *adjusted_mode) | ||
571 | { | ||
572 | DRM_DEBUG_KMS("\n"); | ||
573 | } | ||
574 | |||
575 | static void radeon_mst_encoder_commit(struct drm_encoder *encoder) | ||
576 | { | ||
577 | radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_ON); | ||
578 | DRM_DEBUG_KMS("\n"); | ||
579 | } | ||
580 | |||
581 | static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = { | ||
582 | .dpms = radeon_mst_encoder_dpms, | ||
583 | .mode_fixup = radeon_mst_mode_fixup, | ||
584 | .prepare = radeon_mst_encoder_prepare, | ||
585 | .mode_set = radeon_mst_encoder_mode_set, | ||
586 | .commit = radeon_mst_encoder_commit, | ||
587 | }; | ||
588 | |||
589 | void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder) | ||
590 | { | ||
591 | drm_encoder_cleanup(encoder); | ||
592 | kfree(encoder); | ||
593 | } | ||
594 | |||
595 | static const struct drm_encoder_funcs radeon_dp_mst_enc_funcs = { | ||
596 | .destroy = radeon_dp_mst_encoder_destroy, | ||
597 | }; | ||
598 | |||
599 | static struct radeon_encoder * | ||
600 | radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector) | ||
601 | { | ||
602 | struct drm_device *dev = connector->base.dev; | ||
603 | struct radeon_device *rdev = dev->dev_private; | ||
604 | struct radeon_encoder *radeon_encoder; | ||
605 | struct radeon_encoder_mst *mst_enc; | ||
606 | struct drm_encoder *encoder; | ||
607 | struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private; | ||
608 | struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base); | ||
609 | |||
610 | DRM_DEBUG_KMS("enc master is %p\n", enc_master); | ||
611 | radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL); | ||
612 | if (!radeon_encoder) | ||
613 | return NULL; | ||
614 | |||
615 | radeon_encoder->enc_priv = kzalloc(sizeof(*mst_enc), GFP_KERNEL); | ||
616 | if (!radeon_encoder->enc_priv) { | ||
617 | kfree(radeon_encoder); | ||
618 | return NULL; | ||
619 | } | ||
620 | encoder = &radeon_encoder->base; | ||
621 | switch (rdev->num_crtc) { | ||
622 | case 1: | ||
623 | encoder->possible_crtcs = 0x1; | ||
624 | break; | ||
625 | case 2: | ||
626 | default: | ||
627 | encoder->possible_crtcs = 0x3; | ||
628 | break; | ||
629 | case 4: | ||
630 | encoder->possible_crtcs = 0xf; | ||
631 | break; | ||
632 | case 6: | ||
633 | encoder->possible_crtcs = 0x3f; | ||
634 | break; | ||
635 | } | ||
636 | |||
637 | drm_encoder_init(dev, &radeon_encoder->base, &radeon_dp_mst_enc_funcs, | ||
638 | DRM_MODE_ENCODER_DPMST); | ||
639 | drm_encoder_helper_add(encoder, &radeon_mst_helper_funcs); | ||
640 | |||
641 | mst_enc = radeon_encoder->enc_priv; | ||
642 | mst_enc->connector = connector; | ||
643 | mst_enc->primary = to_radeon_encoder(enc_master); | ||
644 | radeon_encoder->is_mst_encoder = true; | ||
645 | return radeon_encoder; | ||
646 | } | ||
647 | |||
648 | int | ||
649 | radeon_dp_mst_init(struct radeon_connector *radeon_connector) | ||
650 | { | ||
651 | struct drm_device *dev = radeon_connector->base.dev; | ||
652 | |||
653 | if (!radeon_connector->ddc_bus->has_aux) | ||
654 | return 0; | ||
655 | |||
656 | radeon_connector->mst_mgr.cbs = &mst_cbs; | ||
657 | return drm_dp_mst_topology_mgr_init(&radeon_connector->mst_mgr, dev->dev, | ||
658 | &radeon_connector->ddc_bus->aux, 16, 6, | ||
659 | radeon_connector->base.base.id); | ||
660 | } | ||
661 | |||
662 | int | ||
663 | radeon_dp_mst_probe(struct radeon_connector *radeon_connector) | ||
664 | { | ||
665 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; | ||
666 | int ret; | ||
667 | u8 msg[1]; | ||
668 | |||
669 | if (dig_connector->dpcd[DP_DPCD_REV] < 0x12) | ||
670 | return 0; | ||
671 | |||
672 | ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_MSTM_CAP, msg, | ||
673 | 1); | ||
674 | if (ret) { | ||
675 | if (msg[0] & DP_MST_CAP) { | ||
676 | DRM_DEBUG_KMS("Sink is MST capable\n"); | ||
677 | dig_connector->is_mst = true; | ||
678 | } else { | ||
679 | DRM_DEBUG_KMS("Sink is not MST capable\n"); | ||
680 | dig_connector->is_mst = false; | ||
681 | } | ||
682 | |||
683 | } | ||
684 | drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr, | ||
685 | dig_connector->is_mst); | ||
686 | return dig_connector->is_mst; | ||
687 | } | ||
688 | |||
689 | int | ||
690 | radeon_dp_mst_check_status(struct radeon_connector *radeon_connector) | ||
691 | { | ||
692 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; | ||
693 | int retry; | ||
694 | |||
695 | if (dig_connector->is_mst) { | ||
696 | u8 esi[16] = { 0 }; | ||
697 | int dret; | ||
698 | int ret = 0; | ||
699 | bool handled; | ||
700 | |||
701 | dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, | ||
702 | DP_SINK_COUNT_ESI, esi, 8); | ||
703 | go_again: | ||
704 | if (dret == 8) { | ||
705 | DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]); | ||
706 | ret = drm_dp_mst_hpd_irq(&radeon_connector->mst_mgr, esi, &handled); | ||
707 | |||
708 | if (handled) { | ||
709 | for (retry = 0; retry < 3; retry++) { | ||
710 | int wret; | ||
711 | wret = drm_dp_dpcd_write(&radeon_connector->ddc_bus->aux, | ||
712 | DP_SINK_COUNT_ESI + 1, &esi[1], 3); | ||
713 | if (wret == 3) | ||
714 | break; | ||
715 | } | ||
716 | |||
717 | dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, | ||
718 | DP_SINK_COUNT_ESI, esi, 8); | ||
719 | if (dret == 8) { | ||
720 | DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]); | ||
721 | goto go_again; | ||
722 | } | ||
723 | } else | ||
724 | ret = 0; | ||
725 | |||
726 | return ret; | ||
727 | } else { | ||
728 | DRM_DEBUG_KMS("failed to get ESI - device may have failed %d\n", ret); | ||
729 | dig_connector->is_mst = false; | ||
730 | drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr, | ||
731 | dig_connector->is_mst); | ||
732 | /* send a hotplug event */ | ||
733 | } | ||
734 | } | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | #if defined(CONFIG_DEBUG_FS) | ||
739 | |||
740 | static int radeon_debugfs_mst_info(struct seq_file *m, void *data) | ||
741 | { | ||
742 | struct drm_info_node *node = (struct drm_info_node *)m->private; | ||
743 | struct drm_device *dev = node->minor->dev; | ||
744 | struct drm_connector *connector; | ||
745 | struct radeon_connector *radeon_connector; | ||
746 | struct radeon_connector_atom_dig *dig_connector; | ||
747 | int i; | ||
748 | |||
749 | drm_modeset_lock_all(dev); | ||
750 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
751 | if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) | ||
752 | continue; | ||
753 | |||
754 | radeon_connector = to_radeon_connector(connector); | ||
755 | dig_connector = radeon_connector->con_priv; | ||
756 | if (radeon_connector->is_mst_connector) | ||
757 | continue; | ||
758 | if (!dig_connector->is_mst) | ||
759 | continue; | ||
760 | drm_dp_mst_dump_topology(m, &radeon_connector->mst_mgr); | ||
761 | |||
762 | for (i = 0; i < radeon_connector->enabled_attribs; i++) | ||
763 | seq_printf(m, "attrib %d: %d %d\n", i, | ||
764 | radeon_connector->cur_stream_attribs[i].fe, | ||
765 | radeon_connector->cur_stream_attribs[i].slots); | ||
766 | } | ||
767 | drm_modeset_unlock_all(dev); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static struct drm_info_list radeon_debugfs_mst_list[] = { | ||
772 | {"radeon_mst_info", &radeon_debugfs_mst_info, 0, NULL}, | ||
773 | }; | ||
774 | #endif | ||
775 | |||
776 | int radeon_mst_debugfs_init(struct radeon_device *rdev) | ||
777 | { | ||
778 | #if defined(CONFIG_DEBUG_FS) | ||
779 | return radeon_debugfs_add_files(rdev, radeon_debugfs_mst_list, 1); | ||
780 | #endif | ||
781 | return 0; | ||
782 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index b088507057da..d688f6cd1ae4 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -191,6 +191,7 @@ int radeon_use_pflipirq = 2; | |||
191 | int radeon_bapm = -1; | 191 | int radeon_bapm = -1; |
192 | int radeon_backlight = -1; | 192 | int radeon_backlight = -1; |
193 | int radeon_auxch = -1; | 193 | int radeon_auxch = -1; |
194 | int radeon_mst = 0; | ||
194 | 195 | ||
195 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); | 196 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); |
196 | module_param_named(no_wb, radeon_no_wb, int, 0444); | 197 | module_param_named(no_wb, radeon_no_wb, int, 0444); |
@@ -279,6 +280,9 @@ module_param_named(backlight, radeon_backlight, int, 0444); | |||
279 | MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)"); | 280 | MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)"); |
280 | module_param_named(auxch, radeon_auxch, int, 0444); | 281 | module_param_named(auxch, radeon_auxch, int, 0444); |
281 | 282 | ||
283 | MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)"); | ||
284 | module_param_named(mst, radeon_mst, int, 0444); | ||
285 | |||
282 | static struct pci_device_id pciidlist[] = { | 286 | static struct pci_device_id pciidlist[] = { |
283 | radeon_PCI_IDS | 287 | radeon_PCI_IDS |
284 | }; | 288 | }; |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 3a297037cc17..ef99917f000d 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -247,7 +247,16 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) | |||
247 | 247 | ||
248 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 248 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
249 | radeon_connector = to_radeon_connector(connector); | 249 | radeon_connector = to_radeon_connector(connector); |
250 | if (radeon_encoder->active_device & radeon_connector->devices) | 250 | if (radeon_encoder->is_mst_encoder) { |
251 | struct radeon_encoder_mst *mst_enc; | ||
252 | |||
253 | if (!radeon_connector->is_mst_connector) | ||
254 | continue; | ||
255 | |||
256 | mst_enc = radeon_encoder->enc_priv; | ||
257 | if (mst_enc->connector == radeon_connector->mst_port) | ||
258 | return connector; | ||
259 | } else if (radeon_encoder->active_device & radeon_connector->devices) | ||
251 | return connector; | 260 | return connector; |
252 | } | 261 | } |
253 | return NULL; | 262 | return NULL; |
@@ -393,6 +402,9 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, | |||
393 | case DRM_MODE_CONNECTOR_DVID: | 402 | case DRM_MODE_CONNECTOR_DVID: |
394 | case DRM_MODE_CONNECTOR_HDMIA: | 403 | case DRM_MODE_CONNECTOR_HDMIA: |
395 | case DRM_MODE_CONNECTOR_DisplayPort: | 404 | case DRM_MODE_CONNECTOR_DisplayPort: |
405 | if (radeon_connector->is_mst_connector) | ||
406 | return false; | ||
407 | |||
396 | dig_connector = radeon_connector->con_priv; | 408 | dig_connector = radeon_connector->con_priv; |
397 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || | 409 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
398 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) | 410 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index e82ae819fc10..7162c935371c 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -89,6 +89,17 @@ static void radeon_hotplug_work_func(struct work_struct *work) | |||
89 | 89 | ||
90 | static void radeon_dp_work_func(struct work_struct *work) | 90 | static void radeon_dp_work_func(struct work_struct *work) |
91 | { | 91 | { |
92 | struct radeon_device *rdev = container_of(work, struct radeon_device, | ||
93 | dp_work); | ||
94 | struct drm_device *dev = rdev->ddev; | ||
95 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
96 | struct drm_connector *connector; | ||
97 | |||
98 | /* this should take a mutex */ | ||
99 | if (mode_config->num_connector) { | ||
100 | list_for_each_entry(connector, &mode_config->connector_list, head) | ||
101 | radeon_connector_hotplug(connector); | ||
102 | } | ||
92 | } | 103 | } |
93 | /** | 104 | /** |
94 | * radeon_driver_irq_preinstall_kms - drm irq preinstall callback | 105 | * radeon_driver_irq_preinstall_kms - drm irq preinstall callback |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index c612289d7c60..fa91a17b81b6 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <drm/drm_crtc.h> | 33 | #include <drm/drm_crtc.h> |
34 | #include <drm/drm_edid.h> | 34 | #include <drm/drm_edid.h> |
35 | #include <drm/drm_dp_helper.h> | 35 | #include <drm/drm_dp_helper.h> |
36 | #include <drm/drm_dp_mst_helper.h> | ||
36 | #include <drm/drm_fixed.h> | 37 | #include <drm/drm_fixed.h> |
37 | #include <drm/drm_crtc_helper.h> | 38 | #include <drm/drm_crtc_helper.h> |
38 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
@@ -439,12 +440,24 @@ struct radeon_encoder_atom_dig { | |||
439 | uint8_t backlight_level; | 440 | uint8_t backlight_level; |
440 | int panel_mode; | 441 | int panel_mode; |
441 | struct radeon_afmt *afmt; | 442 | struct radeon_afmt *afmt; |
443 | int active_mst_links; | ||
442 | }; | 444 | }; |
443 | 445 | ||
444 | struct radeon_encoder_atom_dac { | 446 | struct radeon_encoder_atom_dac { |
445 | enum radeon_tv_std tv_std; | 447 | enum radeon_tv_std tv_std; |
446 | }; | 448 | }; |
447 | 449 | ||
450 | struct radeon_encoder_mst { | ||
451 | int crtc; | ||
452 | struct radeon_encoder *primary; | ||
453 | struct radeon_connector *connector; | ||
454 | struct drm_dp_mst_port *port; | ||
455 | int pbn; | ||
456 | int fe; | ||
457 | bool fe_from_be; | ||
458 | bool enc_active; | ||
459 | }; | ||
460 | |||
448 | struct radeon_encoder { | 461 | struct radeon_encoder { |
449 | struct drm_encoder base; | 462 | struct drm_encoder base; |
450 | uint32_t encoder_enum; | 463 | uint32_t encoder_enum; |
@@ -464,6 +477,10 @@ struct radeon_encoder { | |||
464 | u16 caps; | 477 | u16 caps; |
465 | struct radeon_audio_funcs *audio; | 478 | struct radeon_audio_funcs *audio; |
466 | enum radeon_output_csc output_csc; | 479 | enum radeon_output_csc output_csc; |
480 | bool can_mst; | ||
481 | uint32_t offset; | ||
482 | bool is_mst_encoder; | ||
483 | /* front end for this mst encoder */ | ||
467 | }; | 484 | }; |
468 | 485 | ||
469 | struct radeon_connector_atom_dig { | 486 | struct radeon_connector_atom_dig { |
@@ -474,6 +491,7 @@ struct radeon_connector_atom_dig { | |||
474 | int dp_clock; | 491 | int dp_clock; |
475 | int dp_lane_count; | 492 | int dp_lane_count; |
476 | bool edp_on; | 493 | bool edp_on; |
494 | bool is_mst; | ||
477 | }; | 495 | }; |
478 | 496 | ||
479 | struct radeon_gpio_rec { | 497 | struct radeon_gpio_rec { |
@@ -517,6 +535,11 @@ enum radeon_connector_dither { | |||
517 | RADEON_FMT_DITHER_ENABLE = 1, | 535 | RADEON_FMT_DITHER_ENABLE = 1, |
518 | }; | 536 | }; |
519 | 537 | ||
538 | struct stream_attribs { | ||
539 | uint16_t fe; | ||
540 | uint16_t slots; | ||
541 | }; | ||
542 | |||
520 | struct radeon_connector { | 543 | struct radeon_connector { |
521 | struct drm_connector base; | 544 | struct drm_connector base; |
522 | uint32_t connector_id; | 545 | uint32_t connector_id; |
@@ -538,6 +561,14 @@ struct radeon_connector { | |||
538 | enum radeon_connector_audio audio; | 561 | enum radeon_connector_audio audio; |
539 | enum radeon_connector_dither dither; | 562 | enum radeon_connector_dither dither; |
540 | int pixelclock_for_modeset; | 563 | int pixelclock_for_modeset; |
564 | bool is_mst_connector; | ||
565 | struct radeon_connector *mst_port; | ||
566 | struct drm_dp_mst_port *port; | ||
567 | struct drm_dp_mst_topology_mgr mst_mgr; | ||
568 | |||
569 | struct radeon_encoder *mst_encoder; | ||
570 | struct stream_attribs cur_stream_attribs[6]; | ||
571 | int enabled_attribs; | ||
541 | }; | 572 | }; |
542 | 573 | ||
543 | struct radeon_framebuffer { | 574 | struct radeon_framebuffer { |
@@ -740,6 +771,8 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, | |||
740 | extern void atombios_dig_transmitter_setup2(struct drm_encoder *encoder, | 771 | extern void atombios_dig_transmitter_setup2(struct drm_encoder *encoder, |
741 | int action, uint8_t lane_num, | 772 | int action, uint8_t lane_num, |
742 | uint8_t lane_set, int fe); | 773 | uint8_t lane_set, int fe); |
774 | extern void atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, | ||
775 | int fe); | ||
743 | extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); | 776 | extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); |
744 | extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); | 777 | extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); |
745 | void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); | 778 | void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); |
@@ -960,6 +993,15 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); | |||
960 | 993 | ||
961 | int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); | 994 | int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); |
962 | 995 | ||
996 | /* mst */ | ||
997 | int radeon_dp_mst_init(struct radeon_connector *radeon_connector); | ||
998 | int radeon_dp_mst_probe(struct radeon_connector *radeon_connector); | ||
999 | int radeon_dp_mst_check_status(struct radeon_connector *radeon_connector); | ||
1000 | int radeon_mst_debugfs_init(struct radeon_device *rdev); | ||
1001 | void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode); | ||
1002 | |||
1003 | void radeon_setup_mst_connector(struct drm_device *dev); | ||
1004 | |||
963 | int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx); | 1005 | int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx); |
964 | void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx); | 1006 | void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx); |
965 | #endif | 1007 | #endif |