diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-07-31 16:51:33 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-08-30 16:30:45 -0400 |
commit | b530602fd4625f763344e455902981b22f85f609 (patch) | |
tree | fb1c932b2bf74b76fbbdc198d527a698088500c2 | |
parent | a4d39e68949f5b4f7b426be63782b421018f741a (diff) |
drm/radeon: add audio support for DCE6/8 GPUs (v12)
Similar to DCE4/5, but supports multiple audio pins
which can be assigned per afmt block.
v2: rework the driver to handle more than one audio
pin.
v3: try different dto reg
v4: properly program dto
v5 (ck): change dto programming order
v6: program speaker allocation block
v7: rebase
v8: rebase on Rafał's changes
v9: integrated Rafał's comments, update to latest
drm_edid_to_speaker_allocation API
v10: add missing line break in error message
v11: add back audio enabled messages
v12: fix copy paste typo in r600_audio_enable
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Rafał Miłecki <zajec5@gmail.com>
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_encoders.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/dce6_afmt.c | 251 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_hdmi.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_audio.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 59 |
15 files changed, 455 insertions, 62 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index da2a8e9e9308..306364a1ecda 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
80 | r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \ | 80 | r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.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 | 83 | ci_dpm.o dce6_afmt.o |
84 | 84 | ||
85 | # add async DMA block | 85 | # add async DMA block |
86 | radeon-y += \ | 86 | radeon-y += \ |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 092275d53d4a..dfac7965ea28 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
@@ -682,8 +682,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
682 | int | 682 | int |
683 | atombios_get_encoder_mode(struct drm_encoder *encoder) | 683 | atombios_get_encoder_mode(struct drm_encoder *encoder) |
684 | { | 684 | { |
685 | struct drm_device *dev = encoder->dev; | ||
686 | struct radeon_device *rdev = dev->dev_private; | ||
687 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 685 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
688 | struct drm_connector *connector; | 686 | struct drm_connector *connector; |
689 | struct radeon_connector *radeon_connector; | 687 | struct radeon_connector *radeon_connector; |
@@ -710,8 +708,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
710 | case DRM_MODE_CONNECTOR_DVII: | 708 | case DRM_MODE_CONNECTOR_DVII: |
711 | case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ | 709 | case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ |
712 | if (drm_detect_hdmi_monitor(radeon_connector->edid) && | 710 | if (drm_detect_hdmi_monitor(radeon_connector->edid) && |
713 | radeon_audio && | 711 | radeon_audio) |
714 | !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ | ||
715 | return ATOM_ENCODER_MODE_HDMI; | 712 | return ATOM_ENCODER_MODE_HDMI; |
716 | else if (radeon_connector->use_digital) | 713 | else if (radeon_connector->use_digital) |
717 | return ATOM_ENCODER_MODE_DVI; | 714 | return ATOM_ENCODER_MODE_DVI; |
@@ -722,8 +719,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
722 | case DRM_MODE_CONNECTOR_HDMIA: | 719 | case DRM_MODE_CONNECTOR_HDMIA: |
723 | default: | 720 | default: |
724 | if (drm_detect_hdmi_monitor(radeon_connector->edid) && | 721 | if (drm_detect_hdmi_monitor(radeon_connector->edid) && |
725 | radeon_audio && | 722 | radeon_audio) |
726 | !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ | ||
727 | return ATOM_ENCODER_MODE_HDMI; | 723 | return ATOM_ENCODER_MODE_HDMI; |
728 | else | 724 | else |
729 | return ATOM_ENCODER_MODE_DVI; | 725 | return ATOM_ENCODER_MODE_DVI; |
@@ -737,8 +733,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
737 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) | 733 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) |
738 | return ATOM_ENCODER_MODE_DP; | 734 | return ATOM_ENCODER_MODE_DP; |
739 | else if (drm_detect_hdmi_monitor(radeon_connector->edid) && | 735 | else if (drm_detect_hdmi_monitor(radeon_connector->edid) && |
740 | radeon_audio && | 736 | radeon_audio) |
741 | !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ | ||
742 | return ATOM_ENCODER_MODE_HDMI; | 737 | return ATOM_ENCODER_MODE_HDMI; |
743 | else | 738 | else |
744 | return ATOM_ENCODER_MODE_DVI; | 739 | return ATOM_ENCODER_MODE_DVI; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 692e31b95d34..2b6049d55233 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -7004,6 +7004,10 @@ static int cik_startup(struct radeon_device *rdev) | |||
7004 | return r; | 7004 | return r; |
7005 | } | 7005 | } |
7006 | 7006 | ||
7007 | r = dce6_audio_init(rdev); | ||
7008 | if (r) | ||
7009 | return r; | ||
7010 | |||
7007 | return 0; | 7011 | return 0; |
7008 | } | 7012 | } |
7009 | 7013 | ||
@@ -7049,6 +7053,7 @@ int cik_resume(struct radeon_device *rdev) | |||
7049 | */ | 7053 | */ |
7050 | int cik_suspend(struct radeon_device *rdev) | 7054 | int cik_suspend(struct radeon_device *rdev) |
7051 | { | 7055 | { |
7056 | dce6_audio_fini(rdev); | ||
7052 | radeon_vm_manager_fini(rdev); | 7057 | radeon_vm_manager_fini(rdev); |
7053 | cik_cp_enable(rdev, false); | 7058 | cik_cp_enable(rdev, false); |
7054 | cik_sdma_enable(rdev, false); | 7059 | cik_sdma_enable(rdev, false); |
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c new file mode 100644 index 000000000000..0d9a6a21088c --- /dev/null +++ b/drivers/gpu/drm/radeon/dce6_afmt.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | */ | ||
23 | #include <linux/hdmi.h> | ||
24 | #include <drm/drmP.h> | ||
25 | #include "radeon.h" | ||
26 | #include "sid.h" | ||
27 | |||
28 | static u32 dce6_endpoint_rreg(struct radeon_device *rdev, | ||
29 | u32 block_offset, u32 reg) | ||
30 | { | ||
31 | u32 r; | ||
32 | |||
33 | WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | ||
34 | r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset); | ||
35 | return r; | ||
36 | } | ||
37 | |||
38 | static void dce6_endpoint_wreg(struct radeon_device *rdev, | ||
39 | u32 block_offset, u32 reg, u32 v) | ||
40 | { | ||
41 | if (ASIC_IS_DCE8(rdev)) | ||
42 | WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | ||
43 | else | ||
44 | WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, | ||
45 | AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg)); | ||
46 | WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v); | ||
47 | } | ||
48 | |||
49 | #define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg)) | ||
50 | #define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v)) | ||
51 | |||
52 | |||
53 | static void dce6_afmt_get_connected_pins(struct radeon_device *rdev) | ||
54 | { | ||
55 | int i; | ||
56 | u32 offset, tmp; | ||
57 | |||
58 | for (i = 0; i < rdev->audio.num_pins; i++) { | ||
59 | offset = rdev->audio.pin[i].offset; | ||
60 | tmp = RREG32_ENDPOINT(offset, | ||
61 | AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); | ||
62 | if (((tmp & PORT_CONNECTIVITY_MASK) >> PORT_CONNECTIVITY_SHIFT) == 1) | ||
63 | rdev->audio.pin[i].connected = false; | ||
64 | else | ||
65 | rdev->audio.pin[i].connected = true; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev) | ||
70 | { | ||
71 | int i; | ||
72 | |||
73 | dce6_afmt_get_connected_pins(rdev); | ||
74 | |||
75 | for (i = 0; i < rdev->audio.num_pins; i++) { | ||
76 | if (rdev->audio.pin[i].connected) | ||
77 | return &rdev->audio.pin[i]; | ||
78 | } | ||
79 | DRM_ERROR("No connected audio pins found!\n"); | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | void dce6_afmt_select_pin(struct drm_encoder *encoder) | ||
84 | { | ||
85 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
86 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
87 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
88 | u32 offset = dig->afmt->offset; | ||
89 | u32 id = dig->afmt->pin->id; | ||
90 | |||
91 | if (!dig->afmt->pin) | ||
92 | return; | ||
93 | |||
94 | WREG32(AFMT_AUDIO_SRC_CONTROL + offset, AFMT_AUDIO_SRC_SELECT(id)); | ||
95 | } | ||
96 | |||
97 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) | ||
98 | { | ||
99 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
100 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
101 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
102 | u32 offset, tmp; | ||
103 | struct drm_connector *connector; | ||
104 | struct radeon_connector *radeon_connector = NULL; | ||
105 | struct cea_sad *sads; | ||
106 | int i, sad_count, sadb_count; | ||
107 | u8 *sadb; | ||
108 | |||
109 | static const u16 eld_reg_to_type[][2] = { | ||
110 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, | ||
111 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, | ||
112 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 }, | ||
113 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 }, | ||
114 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 }, | ||
115 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC }, | ||
116 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS }, | ||
117 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC }, | ||
118 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 }, | ||
119 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD }, | ||
120 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP }, | ||
121 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, | ||
122 | }; | ||
123 | |||
124 | if (!dig->afmt->pin) | ||
125 | return; | ||
126 | |||
127 | offset = dig->afmt->pin->offset; | ||
128 | |||
129 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
130 | if (connector->encoder == encoder) | ||
131 | radeon_connector = to_radeon_connector(connector); | ||
132 | } | ||
133 | |||
134 | if (!radeon_connector) { | ||
135 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); | ||
140 | if (sad_count < 0) { | ||
141 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | ||
142 | return; | ||
143 | } | ||
144 | BUG_ON(!sads); | ||
145 | |||
146 | sadb_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); | ||
147 | if (sadb_count < 0) { | ||
148 | DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | /* program the speaker allocation */ | ||
153 | tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | ||
154 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); | ||
155 | /* set HDMI mode */ | ||
156 | tmp |= HDMI_CONNECTION; | ||
157 | if (sadb_count) | ||
158 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | ||
159 | else | ||
160 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | ||
161 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | ||
162 | |||
163 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { | ||
164 | u32 value = 0; | ||
165 | int j; | ||
166 | |||
167 | for (j = 0; j < sad_count; j++) { | ||
168 | struct cea_sad *sad = &sads[j]; | ||
169 | |||
170 | if (sad->format == eld_reg_to_type[i][1]) { | ||
171 | value = MAX_CHANNELS(sad->channels) | | ||
172 | DESCRIPTOR_BYTE_2(sad->byte2) | | ||
173 | SUPPORTED_FREQUENCIES(sad->freq); | ||
174 | if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) | ||
175 | value |= SUPPORTED_FREQUENCIES_STEREO(sad->freq); | ||
176 | break; | ||
177 | } | ||
178 | } | ||
179 | WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); | ||
180 | } | ||
181 | |||
182 | kfree(sads); | ||
183 | kfree(sadb); | ||
184 | } | ||
185 | |||
186 | static int dce6_audio_chipset_supported(struct radeon_device *rdev) | ||
187 | { | ||
188 | return !ASIC_IS_NODCE(rdev); | ||
189 | } | ||
190 | |||
191 | static void dce6_audio_enable(struct radeon_device *rdev, | ||
192 | struct r600_audio_pin *pin, | ||
193 | bool enable) | ||
194 | { | ||
195 | WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL, | ||
196 | AUDIO_ENABLED); | ||
197 | DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); | ||
198 | } | ||
199 | |||
200 | static const u32 pin_offsets[7] = | ||
201 | { | ||
202 | (0x5e00 - 0x5e00), | ||
203 | (0x5e18 - 0x5e00), | ||
204 | (0x5e30 - 0x5e00), | ||
205 | (0x5e48 - 0x5e00), | ||
206 | (0x5e60 - 0x5e00), | ||
207 | (0x5e78 - 0x5e00), | ||
208 | (0x5e90 - 0x5e00), | ||
209 | }; | ||
210 | |||
211 | int dce6_audio_init(struct radeon_device *rdev) | ||
212 | { | ||
213 | int i; | ||
214 | |||
215 | if (!radeon_audio || !dce6_audio_chipset_supported(rdev)) | ||
216 | return 0; | ||
217 | |||
218 | rdev->audio.enabled = true; | ||
219 | |||
220 | if (ASIC_IS_DCE8(rdev)) | ||
221 | rdev->audio.num_pins = 7; | ||
222 | else | ||
223 | rdev->audio.num_pins = 6; | ||
224 | |||
225 | for (i = 0; i < rdev->audio.num_pins; i++) { | ||
226 | rdev->audio.pin[i].channels = -1; | ||
227 | rdev->audio.pin[i].rate = -1; | ||
228 | rdev->audio.pin[i].bits_per_sample = -1; | ||
229 | rdev->audio.pin[i].status_bits = 0; | ||
230 | rdev->audio.pin[i].category_code = 0; | ||
231 | rdev->audio.pin[i].connected = false; | ||
232 | rdev->audio.pin[i].offset = pin_offsets[i]; | ||
233 | rdev->audio.pin[i].id = i; | ||
234 | dce6_audio_enable(rdev, &rdev->audio.pin[i], true); | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | void dce6_audio_fini(struct radeon_device *rdev) | ||
241 | { | ||
242 | int i; | ||
243 | |||
244 | if (!rdev->audio.enabled) | ||
245 | return; | ||
246 | |||
247 | for (i = 0; i < rdev->audio.num_pins; i++) | ||
248 | dce6_audio_enable(rdev, &rdev->audio.pin[i], false); | ||
249 | |||
250 | rdev->audio.enabled = false; | ||
251 | } | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index b0e280058b9b..c5acdf0a301a 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c | |||
@@ -32,6 +32,9 @@ | |||
32 | #include "evergreend.h" | 32 | #include "evergreend.h" |
33 | #include "atom.h" | 33 | #include "atom.h" |
34 | 34 | ||
35 | extern void dce6_afmt_write_sad_regs(struct drm_encoder *encoder); | ||
36 | extern void dce6_afmt_select_pin(struct drm_encoder *encoder); | ||
37 | |||
35 | /* | 38 | /* |
36 | * update the N and CTS parameters for a given pixel clock rate | 39 | * update the N and CTS parameters for a given pixel clock rate |
37 | */ | 40 | */ |
@@ -157,22 +160,26 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
157 | if (!dig || !dig->afmt) | 160 | if (!dig || !dig->afmt) |
158 | return; | 161 | return; |
159 | 162 | ||
160 | if (max_ratio >= 8) { | 163 | if (ASIC_IS_DCE6(rdev)) { |
161 | dto_phase = 192 * 1000; | ||
162 | wallclock_ratio = 3; | ||
163 | } else if (max_ratio >= 4) { | ||
164 | dto_phase = 96 * 1000; | ||
165 | wallclock_ratio = 2; | ||
166 | } else if (max_ratio >= 2) { | ||
167 | dto_phase = 48 * 1000; | ||
168 | wallclock_ratio = 1; | ||
169 | } else { | ||
170 | dto_phase = 24 * 1000; | 164 | dto_phase = 24 * 1000; |
171 | wallclock_ratio = 0; | 165 | } else { |
166 | if (max_ratio >= 8) { | ||
167 | dto_phase = 192 * 1000; | ||
168 | wallclock_ratio = 3; | ||
169 | } else if (max_ratio >= 4) { | ||
170 | dto_phase = 96 * 1000; | ||
171 | wallclock_ratio = 2; | ||
172 | } else if (max_ratio >= 2) { | ||
173 | dto_phase = 48 * 1000; | ||
174 | wallclock_ratio = 1; | ||
175 | } else { | ||
176 | dto_phase = 24 * 1000; | ||
177 | wallclock_ratio = 0; | ||
178 | } | ||
179 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
180 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
181 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
172 | } | 182 | } |
173 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
174 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
175 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
176 | 183 | ||
177 | /* XXX two dtos; generally use dto0 for hdmi */ | 184 | /* XXX two dtos; generally use dto0 for hdmi */ |
178 | /* Express [24MHz / target pixel clock] as an exact rational | 185 | /* Express [24MHz / target pixel clock] as an exact rational |
@@ -266,7 +273,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode | |||
266 | AFMT_AUDIO_CHANNEL_ENABLE(0xff)); | 273 | AFMT_AUDIO_CHANNEL_ENABLE(0xff)); |
267 | 274 | ||
268 | /* fglrx sets 0x40 in 0x5f80 here */ | 275 | /* fglrx sets 0x40 in 0x5f80 here */ |
269 | evergreen_hdmi_write_sad_regs(encoder); | 276 | |
277 | if (ASIC_IS_DCE6(rdev)) { | ||
278 | dce6_afmt_select_pin(encoder); | ||
279 | dce6_afmt_write_sad_regs(encoder); | ||
280 | } else { | ||
281 | evergreen_hdmi_write_sad_regs(encoder); | ||
282 | } | ||
270 | 283 | ||
271 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | 284 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
272 | if (err < 0) { | 285 | if (err < 0) { |
@@ -302,6 +315,8 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode | |||
302 | 315 | ||
303 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) | 316 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) |
304 | { | 317 | { |
318 | struct drm_device *dev = encoder->dev; | ||
319 | struct radeon_device *rdev = dev->dev_private; | ||
305 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 320 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
306 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 321 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
307 | 322 | ||
@@ -314,6 +329,15 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) | |||
314 | if (!enable && !dig->afmt->enabled) | 329 | if (!enable && !dig->afmt->enabled) |
315 | return; | 330 | return; |
316 | 331 | ||
332 | if (enable) { | ||
333 | if (ASIC_IS_DCE6(rdev)) | ||
334 | dig->afmt->pin = dce6_audio_get_pin(rdev); | ||
335 | else | ||
336 | dig->afmt->pin = r600_audio_get_pin(rdev); | ||
337 | } else { | ||
338 | dig->afmt->pin = NULL; | ||
339 | } | ||
340 | |||
317 | dig->afmt->enabled = enable; | 341 | dig->afmt->enabled = enable; |
318 | 342 | ||
319 | DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", | 343 | DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 2db8ce0023ac..69499fff06b0 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -2027,9 +2027,15 @@ static int cayman_startup(struct radeon_device *rdev) | |||
2027 | return r; | 2027 | return r; |
2028 | } | 2028 | } |
2029 | 2029 | ||
2030 | r = r600_audio_init(rdev); | 2030 | if (ASIC_IS_DCE6(rdev)) { |
2031 | if (r) | 2031 | r = dce6_audio_init(rdev); |
2032 | return r; | 2032 | if (r) |
2033 | return r; | ||
2034 | } else { | ||
2035 | r = r600_audio_init(rdev); | ||
2036 | if (r) | ||
2037 | return r; | ||
2038 | } | ||
2033 | 2039 | ||
2034 | return 0; | 2040 | return 0; |
2035 | } | 2041 | } |
@@ -2060,7 +2066,10 @@ int cayman_resume(struct radeon_device *rdev) | |||
2060 | 2066 | ||
2061 | int cayman_suspend(struct radeon_device *rdev) | 2067 | int cayman_suspend(struct radeon_device *rdev) |
2062 | { | 2068 | { |
2063 | r600_audio_fini(rdev); | 2069 | if (ASIC_IS_DCE6(rdev)) |
2070 | dce6_audio_fini(rdev); | ||
2071 | else | ||
2072 | r600_audio_fini(rdev); | ||
2064 | radeon_vm_manager_fini(rdev); | 2073 | radeon_vm_manager_fini(rdev); |
2065 | cayman_cp_enable(rdev, false); | 2074 | cayman_cp_enable(rdev, false); |
2066 | cayman_dma_stop(rdev); | 2075 | cayman_dma_stop(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index c92eb86a8e55..47fc2b886979 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
@@ -57,12 +57,12 @@ static bool radeon_dig_encoder(struct drm_encoder *encoder) | |||
57 | */ | 57 | */ |
58 | static int r600_audio_chipset_supported(struct radeon_device *rdev) | 58 | static int r600_audio_chipset_supported(struct radeon_device *rdev) |
59 | { | 59 | { |
60 | return ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE6(rdev); | 60 | return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); |
61 | } | 61 | } |
62 | 62 | ||
63 | struct r600_audio r600_audio_status(struct radeon_device *rdev) | 63 | struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) |
64 | { | 64 | { |
65 | struct r600_audio status; | 65 | struct r600_audio_pin status; |
66 | uint32_t value; | 66 | uint32_t value; |
67 | 67 | ||
68 | value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); | 68 | value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
@@ -120,16 +120,16 @@ void r600_audio_update_hdmi(struct work_struct *work) | |||
120 | struct radeon_device *rdev = container_of(work, struct radeon_device, | 120 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
121 | audio_work); | 121 | audio_work); |
122 | struct drm_device *dev = rdev->ddev; | 122 | struct drm_device *dev = rdev->ddev; |
123 | struct r600_audio audio_status = r600_audio_status(rdev); | 123 | struct r600_audio_pin audio_status = r600_audio_status(rdev); |
124 | struct drm_encoder *encoder; | 124 | struct drm_encoder *encoder; |
125 | bool changed = false; | 125 | bool changed = false; |
126 | 126 | ||
127 | if (rdev->audio_status.channels != audio_status.channels || | 127 | if (rdev->audio.pin[0].channels != audio_status.channels || |
128 | rdev->audio_status.rate != audio_status.rate || | 128 | rdev->audio.pin[0].rate != audio_status.rate || |
129 | rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || | 129 | rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample || |
130 | rdev->audio_status.status_bits != audio_status.status_bits || | 130 | rdev->audio.pin[0].status_bits != audio_status.status_bits || |
131 | rdev->audio_status.category_code != audio_status.category_code) { | 131 | rdev->audio.pin[0].category_code != audio_status.category_code) { |
132 | rdev->audio_status = audio_status; | 132 | rdev->audio.pin[0] = audio_status; |
133 | changed = true; | 133 | changed = true; |
134 | } | 134 | } |
135 | 135 | ||
@@ -141,13 +141,13 @@ void r600_audio_update_hdmi(struct work_struct *work) | |||
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | /* | 144 | /* enable the audio stream */ |
145 | * turn on/off audio engine | 145 | static void r600_audio_enable(struct radeon_device *rdev, |
146 | */ | 146 | struct r600_audio_pin *pin, |
147 | static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) | 147 | bool enable) |
148 | { | 148 | { |
149 | u32 value = 0; | 149 | u32 value = 0; |
150 | DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); | 150 | |
151 | if (ASIC_IS_DCE4(rdev)) { | 151 | if (ASIC_IS_DCE4(rdev)) { |
152 | if (enable) { | 152 | if (enable) { |
153 | value |= 0x81000000; /* Required to enable audio */ | 153 | value |= 0x81000000; /* Required to enable audio */ |
@@ -158,7 +158,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) | |||
158 | WREG32_P(R600_AUDIO_ENABLE, | 158 | WREG32_P(R600_AUDIO_ENABLE, |
159 | enable ? 0x81000000 : 0x0, ~0x81000000); | 159 | enable ? 0x81000000 : 0x0, ~0x81000000); |
160 | } | 160 | } |
161 | rdev->audio_enabled = enable; | 161 | DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); |
162 | } | 162 | } |
163 | 163 | ||
164 | /* | 164 | /* |
@@ -169,13 +169,17 @@ int r600_audio_init(struct radeon_device *rdev) | |||
169 | if (!radeon_audio || !r600_audio_chipset_supported(rdev)) | 169 | if (!radeon_audio || !r600_audio_chipset_supported(rdev)) |
170 | return 0; | 170 | return 0; |
171 | 171 | ||
172 | r600_audio_engine_enable(rdev, true); | 172 | rdev->audio.enabled = true; |
173 | |||
174 | rdev->audio.num_pins = 1; | ||
175 | rdev->audio.pin[0].channels = -1; | ||
176 | rdev->audio.pin[0].rate = -1; | ||
177 | rdev->audio.pin[0].bits_per_sample = -1; | ||
178 | rdev->audio.pin[0].status_bits = 0; | ||
179 | rdev->audio.pin[0].category_code = 0; | ||
180 | rdev->audio.pin[0].id = 0; | ||
173 | 181 | ||
174 | rdev->audio_status.channels = -1; | 182 | r600_audio_enable(rdev, &rdev->audio.pin[0], true); |
175 | rdev->audio_status.rate = -1; | ||
176 | rdev->audio_status.bits_per_sample = -1; | ||
177 | rdev->audio_status.status_bits = 0; | ||
178 | rdev->audio_status.category_code = 0; | ||
179 | 183 | ||
180 | return 0; | 184 | return 0; |
181 | } | 185 | } |
@@ -186,8 +190,16 @@ int r600_audio_init(struct radeon_device *rdev) | |||
186 | */ | 190 | */ |
187 | void r600_audio_fini(struct radeon_device *rdev) | 191 | void r600_audio_fini(struct radeon_device *rdev) |
188 | { | 192 | { |
189 | if (!rdev->audio_enabled) | 193 | if (!rdev->audio.enabled) |
190 | return; | 194 | return; |
191 | 195 | ||
192 | r600_audio_engine_enable(rdev, false); | 196 | r600_audio_enable(rdev, &rdev->audio.pin[0], false); |
197 | |||
198 | rdev->audio.enabled = false; | ||
199 | } | ||
200 | |||
201 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) | ||
202 | { | ||
203 | /* only one pin on 6xx-NI */ | ||
204 | return &rdev->audio.pin[0]; | ||
193 | } | 205 | } |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index f264df5470f7..e1dec1339461 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -382,7 +382,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) | |||
382 | struct radeon_device *rdev = dev->dev_private; | 382 | struct radeon_device *rdev = dev->dev_private; |
383 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 383 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
384 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 384 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
385 | struct r600_audio audio = r600_audio_status(rdev); | 385 | struct r600_audio_pin audio = r600_audio_status(rdev); |
386 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; | 386 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
387 | struct hdmi_audio_infoframe frame; | 387 | struct hdmi_audio_infoframe frame; |
388 | uint32_t offset; | 388 | uint32_t offset; |
@@ -491,6 +491,11 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) | |||
491 | if (!enable && !dig->afmt->enabled) | 491 | if (!enable && !dig->afmt->enabled) |
492 | return; | 492 | return; |
493 | 493 | ||
494 | if (enable) | ||
495 | dig->afmt->pin = r600_audio_get_pin(rdev); | ||
496 | else | ||
497 | dig->afmt->pin = NULL; | ||
498 | |||
494 | /* Older chipsets require setting HDMI and routing manually */ | 499 | /* Older chipsets require setting HDMI and routing manually */ |
495 | if (!ASIC_IS_DCE3(rdev)) { | 500 | if (!ASIC_IS_DCE3(rdev)) { |
496 | if (enable) | 501 | if (enable) |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 791cc8de6395..82fef854b686 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -696,7 +696,7 @@ union radeon_irq_stat_regs { | |||
696 | 696 | ||
697 | #define RADEON_MAX_HPD_PINS 6 | 697 | #define RADEON_MAX_HPD_PINS 6 |
698 | #define RADEON_MAX_CRTCS 6 | 698 | #define RADEON_MAX_CRTCS 6 |
699 | #define RADEON_MAX_AFMT_BLOCKS 6 | 699 | #define RADEON_MAX_AFMT_BLOCKS 7 |
700 | 700 | ||
701 | struct radeon_irq { | 701 | struct radeon_irq { |
702 | bool installed; | 702 | bool installed; |
@@ -1537,12 +1537,21 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev, | |||
1537 | int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev, | 1537 | int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev, |
1538 | unsigned cg_upll_func_cntl); | 1538 | unsigned cg_upll_func_cntl); |
1539 | 1539 | ||
1540 | struct r600_audio { | 1540 | struct r600_audio_pin { |
1541 | int channels; | 1541 | int channels; |
1542 | int rate; | 1542 | int rate; |
1543 | int bits_per_sample; | 1543 | int bits_per_sample; |
1544 | u8 status_bits; | 1544 | u8 status_bits; |
1545 | u8 category_code; | 1545 | u8 category_code; |
1546 | u32 offset; | ||
1547 | bool connected; | ||
1548 | u32 id; | ||
1549 | }; | ||
1550 | |||
1551 | struct r600_audio { | ||
1552 | bool enabled; | ||
1553 | struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS]; | ||
1554 | int num_pins; | ||
1546 | }; | 1555 | }; |
1547 | 1556 | ||
1548 | /* | 1557 | /* |
@@ -2128,9 +2137,8 @@ struct radeon_device { | |||
2128 | struct work_struct reset_work; | 2137 | struct work_struct reset_work; |
2129 | int num_crtc; /* number of crtcs */ | 2138 | int num_crtc; /* number of crtcs */ |
2130 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ | 2139 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ |
2131 | bool audio_enabled; | ||
2132 | bool has_uvd; | 2140 | bool has_uvd; |
2133 | struct r600_audio audio_status; /* audio stuff */ | 2141 | struct r600_audio audio; /* audio stuff */ |
2134 | struct notifier_block acpi_nb; | 2142 | struct notifier_block acpi_nb; |
2135 | /* only one userspace can use Hyperz features or CMASK at a time */ | 2143 | /* only one userspace can use Hyperz features or CMASK at a time */ |
2136 | struct drm_file *hyperz_filp; | 2144 | struct drm_file *hyperz_filp; |
@@ -2594,6 +2602,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
2594 | 2602 | ||
2595 | /* audio */ | 2603 | /* audio */ |
2596 | void r600_audio_update_hdmi(struct work_struct *work); | 2604 | void r600_audio_update_hdmi(struct work_struct *work); |
2605 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev); | ||
2606 | struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev); | ||
2597 | 2607 | ||
2598 | /* | 2608 | /* |
2599 | * R600 vram scratch functions | 2609 | * R600 vram scratch functions |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index da755bf37421..69f3122779c3 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -1739,6 +1739,8 @@ static struct radeon_asic trinity_asic = { | |||
1739 | .wait_for_vblank = &dce4_wait_for_vblank, | 1739 | .wait_for_vblank = &dce4_wait_for_vblank, |
1740 | .set_backlight_level = &atombios_set_backlight_level, | 1740 | .set_backlight_level = &atombios_set_backlight_level, |
1741 | .get_backlight_level = &atombios_get_backlight_level, | 1741 | .get_backlight_level = &atombios_get_backlight_level, |
1742 | .hdmi_enable = &evergreen_hdmi_enable, | ||
1743 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
1742 | }, | 1744 | }, |
1743 | .copy = { | 1745 | .copy = { |
1744 | .blit = &r600_copy_cpdma, | 1746 | .blit = &r600_copy_cpdma, |
@@ -1867,6 +1869,8 @@ static struct radeon_asic si_asic = { | |||
1867 | .wait_for_vblank = &dce4_wait_for_vblank, | 1869 | .wait_for_vblank = &dce4_wait_for_vblank, |
1868 | .set_backlight_level = &atombios_set_backlight_level, | 1870 | .set_backlight_level = &atombios_set_backlight_level, |
1869 | .get_backlight_level = &atombios_get_backlight_level, | 1871 | .get_backlight_level = &atombios_get_backlight_level, |
1872 | .hdmi_enable = &evergreen_hdmi_enable, | ||
1873 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
1870 | }, | 1874 | }, |
1871 | .copy = { | 1875 | .copy = { |
1872 | .blit = NULL, | 1876 | .blit = NULL, |
@@ -2009,6 +2013,8 @@ static struct radeon_asic ci_asic = { | |||
2009 | .bandwidth_update = &dce8_bandwidth_update, | 2013 | .bandwidth_update = &dce8_bandwidth_update, |
2010 | .get_vblank_counter = &evergreen_get_vblank_counter, | 2014 | .get_vblank_counter = &evergreen_get_vblank_counter, |
2011 | .wait_for_vblank = &dce4_wait_for_vblank, | 2015 | .wait_for_vblank = &dce4_wait_for_vblank, |
2016 | .hdmi_enable = &evergreen_hdmi_enable, | ||
2017 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
2012 | }, | 2018 | }, |
2013 | .copy = { | 2019 | .copy = { |
2014 | .blit = NULL, | 2020 | .blit = NULL, |
@@ -2107,6 +2113,8 @@ static struct radeon_asic kv_asic = { | |||
2107 | .bandwidth_update = &dce8_bandwidth_update, | 2113 | .bandwidth_update = &dce8_bandwidth_update, |
2108 | .get_vblank_counter = &evergreen_get_vblank_counter, | 2114 | .get_vblank_counter = &evergreen_get_vblank_counter, |
2109 | .wait_for_vblank = &dce4_wait_for_vblank, | 2115 | .wait_for_vblank = &dce4_wait_for_vblank, |
2116 | .hdmi_enable = &evergreen_hdmi_enable, | ||
2117 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
2110 | }, | 2118 | }, |
2111 | .copy = { | 2119 | .copy = { |
2112 | .blit = NULL, | 2120 | .blit = NULL, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e69f00a7f153..818bbe6b884b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -379,7 +379,7 @@ void r600_disable_interrupts(struct radeon_device *rdev); | |||
379 | void r600_rlc_stop(struct radeon_device *rdev); | 379 | void r600_rlc_stop(struct radeon_device *rdev); |
380 | /* r600 audio */ | 380 | /* r600 audio */ |
381 | int r600_audio_init(struct radeon_device *rdev); | 381 | int r600_audio_init(struct radeon_device *rdev); |
382 | struct r600_audio r600_audio_status(struct radeon_device *rdev); | 382 | struct r600_audio_pin r600_audio_status(struct radeon_device *rdev); |
383 | void r600_audio_fini(struct radeon_device *rdev); | 383 | void r600_audio_fini(struct radeon_device *rdev); |
384 | int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | 384 | int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); |
385 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | 385 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); |
@@ -628,6 +628,8 @@ int trinity_dpm_force_performance_level(struct radeon_device *rdev, | |||
628 | 628 | ||
629 | /* DCE6 - SI */ | 629 | /* DCE6 - SI */ |
630 | void dce6_bandwidth_update(struct radeon_device *rdev); | 630 | void dce6_bandwidth_update(struct radeon_device *rdev); |
631 | int dce6_audio_init(struct radeon_device *rdev); | ||
632 | void dce6_audio_fini(struct radeon_device *rdev); | ||
631 | 633 | ||
632 | /* | 634 | /* |
633 | * si | 635 | * si |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 31d9fbe85c72..af9cd6a57efc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -1254,8 +1254,8 @@ static void radeon_afmt_init(struct radeon_device *rdev) | |||
1254 | for (i = 0; i < RADEON_MAX_AFMT_BLOCKS; i++) | 1254 | for (i = 0; i < RADEON_MAX_AFMT_BLOCKS; i++) |
1255 | rdev->mode_info.afmt[i] = NULL; | 1255 | rdev->mode_info.afmt[i] = NULL; |
1256 | 1256 | ||
1257 | if (ASIC_IS_DCE6(rdev)) { | 1257 | if (ASIC_IS_NODCE(rdev)) { |
1258 | /* todo */ | 1258 | /* nothing to do */ |
1259 | } else if (ASIC_IS_DCE4(rdev)) { | 1259 | } else if (ASIC_IS_DCE4(rdev)) { |
1260 | static uint32_t eg_offsets[] = { | 1260 | static uint32_t eg_offsets[] = { |
1261 | EVERGREEN_CRTC0_REGISTER_OFFSET, | 1261 | EVERGREEN_CRTC0_REGISTER_OFFSET, |
@@ -1264,12 +1264,19 @@ static void radeon_afmt_init(struct radeon_device *rdev) | |||
1264 | EVERGREEN_CRTC3_REGISTER_OFFSET, | 1264 | EVERGREEN_CRTC3_REGISTER_OFFSET, |
1265 | EVERGREEN_CRTC4_REGISTER_OFFSET, | 1265 | EVERGREEN_CRTC4_REGISTER_OFFSET, |
1266 | EVERGREEN_CRTC5_REGISTER_OFFSET, | 1266 | EVERGREEN_CRTC5_REGISTER_OFFSET, |
1267 | 0x13830 - 0x7030, | ||
1267 | }; | 1268 | }; |
1268 | int num_afmt; | 1269 | int num_afmt; |
1269 | 1270 | ||
1271 | /* DCE8 has 7 audio blocks tied to DIG encoders */ | ||
1272 | /* DCE6 has 6 audio blocks tied to DIG encoders */ | ||
1270 | /* DCE4/5 has 6 audio blocks tied to DIG encoders */ | 1273 | /* DCE4/5 has 6 audio blocks tied to DIG encoders */ |
1271 | /* DCE4.1 has 2 audio blocks tied to DIG encoders */ | 1274 | /* DCE4.1 has 2 audio blocks tied to DIG encoders */ |
1272 | if (ASIC_IS_DCE5(rdev)) | 1275 | if (ASIC_IS_DCE8(rdev)) |
1276 | num_afmt = 7; | ||
1277 | else if (ASIC_IS_DCE6(rdev)) | ||
1278 | num_afmt = 6; | ||
1279 | else if (ASIC_IS_DCE5(rdev)) | ||
1273 | num_afmt = 6; | 1280 | num_afmt = 6; |
1274 | else if (ASIC_IS_DCE41(rdev)) | 1281 | else if (ASIC_IS_DCE41(rdev)) |
1275 | num_afmt = 2; | 1282 | num_afmt = 2; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 8296632a4235..d908d8d68f6b 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -225,6 +225,7 @@ struct radeon_afmt { | |||
225 | int offset; | 225 | int offset; |
226 | bool last_buffer_filled_status; | 226 | bool last_buffer_filled_status; |
227 | int id; | 227 | int id; |
228 | struct r600_audio_pin *pin; | ||
228 | }; | 229 | }; |
229 | 230 | ||
230 | struct radeon_mode_info { | 231 | struct radeon_mode_info { |
@@ -233,7 +234,7 @@ struct radeon_mode_info { | |||
233 | enum radeon_connector_table connector_table; | 234 | enum radeon_connector_table connector_table; |
234 | bool mode_config_initialized; | 235 | bool mode_config_initialized; |
235 | struct radeon_crtc *crtcs[6]; | 236 | struct radeon_crtc *crtcs[6]; |
236 | struct radeon_afmt *afmt[6]; | 237 | struct radeon_afmt *afmt[7]; |
237 | /* DVI-I properties */ | 238 | /* DVI-I properties */ |
238 | struct drm_property *coherent_mode_property; | 239 | struct drm_property *coherent_mode_property; |
239 | /* DAC enable load detect */ | 240 | /* DAC enable load detect */ |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f5307e6bb92b..fb2058c9670d 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -6264,6 +6264,10 @@ static int si_startup(struct radeon_device *rdev) | |||
6264 | return r; | 6264 | return r; |
6265 | } | 6265 | } |
6266 | 6266 | ||
6267 | r = dce6_audio_init(rdev); | ||
6268 | if (r) | ||
6269 | return r; | ||
6270 | |||
6267 | return 0; | 6271 | return 0; |
6268 | } | 6272 | } |
6269 | 6273 | ||
@@ -6295,6 +6299,7 @@ int si_resume(struct radeon_device *rdev) | |||
6295 | 6299 | ||
6296 | int si_suspend(struct radeon_device *rdev) | 6300 | int si_suspend(struct radeon_device *rdev) |
6297 | { | 6301 | { |
6302 | dce6_audio_fini(rdev); | ||
6298 | radeon_vm_manager_fini(rdev); | 6303 | radeon_vm_manager_fini(rdev); |
6299 | si_cp_enable(rdev, false); | 6304 | si_cp_enable(rdev, false); |
6300 | cayman_dma_stop(rdev); | 6305 | cayman_dma_stop(rdev); |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 2c8da27a929f..968cf699c29e 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
@@ -635,6 +635,54 @@ | |||
635 | 635 | ||
636 | #define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 | 636 | #define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 |
637 | 637 | ||
638 | /* DCE6 ELD audio interface */ | ||
639 | #define AZ_F0_CODEC_ENDPOINT_INDEX 0x5E00 | ||
640 | # define AZ_ENDPOINT_REG_INDEX(x) (((x) & 0xff) << 0) | ||
641 | # define AZ_ENDPOINT_REG_WRITE_EN (1 << 8) | ||
642 | #define AZ_F0_CODEC_ENDPOINT_DATA 0x5E04 | ||
643 | |||
644 | #define AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER 0x25 | ||
645 | #define SPEAKER_ALLOCATION(x) (((x) & 0x7f) << 0) | ||
646 | #define SPEAKER_ALLOCATION_MASK (0x7f << 0) | ||
647 | #define SPEAKER_ALLOCATION_SHIFT 0 | ||
648 | #define HDMI_CONNECTION (1 << 16) | ||
649 | #define DP_CONNECTION (1 << 17) | ||
650 | |||
651 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 0x28 /* LPCM */ | ||
652 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1 0x29 /* AC3 */ | ||
653 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2 0x2A /* MPEG1 */ | ||
654 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3 0x2B /* MP3 */ | ||
655 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4 0x2C /* MPEG2 */ | ||
656 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5 0x2D /* AAC */ | ||
657 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6 0x2E /* DTS */ | ||
658 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7 0x2F /* ATRAC */ | ||
659 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8 0x30 /* one bit audio - leave at 0 (default) */ | ||
660 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9 0x31 /* Dolby Digital */ | ||
661 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10 0x32 /* DTS-HD */ | ||
662 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11 0x33 /* MAT-MLP */ | ||
663 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12 0x34 /* DTS */ | ||
664 | #define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13 0x35 /* WMA Pro */ | ||
665 | # define MAX_CHANNELS(x) (((x) & 0x7) << 0) | ||
666 | /* max channels minus one. 7 = 8 channels */ | ||
667 | # define SUPPORTED_FREQUENCIES(x) (((x) & 0xff) << 8) | ||
668 | # define DESCRIPTOR_BYTE_2(x) (((x) & 0xff) << 16) | ||
669 | # define SUPPORTED_FREQUENCIES_STEREO(x) (((x) & 0xff) << 24) /* LPCM only */ | ||
670 | /* SUPPORTED_FREQUENCIES, SUPPORTED_FREQUENCIES_STEREO | ||
671 | * bit0 = 32 kHz | ||
672 | * bit1 = 44.1 kHz | ||
673 | * bit2 = 48 kHz | ||
674 | * bit3 = 88.2 kHz | ||
675 | * bit4 = 96 kHz | ||
676 | * bit5 = 176.4 kHz | ||
677 | * bit6 = 192 kHz | ||
678 | */ | ||
679 | #define AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL 0x54 | ||
680 | # define AUDIO_ENABLED (1 << 31) | ||
681 | |||
682 | #define AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x56 | ||
683 | #define PORT_CONNECTIVITY_MASK (3 << 30) | ||
684 | #define PORT_CONNECTIVITY_SHIFT 30 | ||
685 | |||
638 | #define DC_LB_MEMORY_SPLIT 0x6b0c | 686 | #define DC_LB_MEMORY_SPLIT 0x6b0c |
639 | #define DC_LB_MEMORY_CONFIG(x) ((x) << 20) | 687 | #define DC_LB_MEMORY_CONFIG(x) ((x) << 20) |
640 | 688 | ||
@@ -755,6 +803,17 @@ | |||
755 | /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ | 803 | /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ |
756 | #define CRTC_STATUS_FRAME_COUNT 0x6e98 | 804 | #define CRTC_STATUS_FRAME_COUNT 0x6e98 |
757 | 805 | ||
806 | #define AFMT_AUDIO_SRC_CONTROL 0x713c | ||
807 | #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) | ||
808 | /* AFMT_AUDIO_SRC_SELECT | ||
809 | * 0 = stream0 | ||
810 | * 1 = stream1 | ||
811 | * 2 = stream2 | ||
812 | * 3 = stream3 | ||
813 | * 4 = stream4 | ||
814 | * 5 = stream5 | ||
815 | */ | ||
816 | |||
758 | #define GRBM_CNTL 0x8000 | 817 | #define GRBM_CNTL 0x8000 |
759 | #define GRBM_READ_TIMEOUT(x) ((x) << 0) | 818 | #define GRBM_READ_TIMEOUT(x) ((x) << 0) |
760 | 819 | ||