aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/Makefile2
-rw-r--r--drivers/gpu/drm/radeon/r600_audio.c184
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c154
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h1
4 files changed, 155 insertions, 186 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 7d7aed5357f0..d01b87991422 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
72 radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ 72 radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
73 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ 73 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
74 r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \ 74 r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
75 radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \ 75 radeon_pm.o atombios_dp.o r600_hdmi.o dce3_1_afmt.o \
76 evergreen.o evergreen_cs.o evergreen_blit_shaders.o \ 76 evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
77 evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ 77 evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ 78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
deleted file mode 100644
index 4c7163c1b656..000000000000
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2 * Copyright 2008 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Christian König.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Christian König
25 */
26#include <drm/drmP.h>
27#include "radeon.h"
28#include "radeon_reg.h"
29#include "radeon_asic.h"
30#include "atom.h"
31
32/*
33 * check if the chipset is supported
34 */
35static int r600_audio_chipset_supported(struct radeon_device *rdev)
36{
37 return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
38}
39
40struct r600_audio_pin r600_audio_status(struct radeon_device *rdev)
41{
42 struct r600_audio_pin status;
43 uint32_t value;
44
45 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
46
47 /* number of channels */
48 status.channels = (value & 0x7) + 1;
49
50 /* bits per sample */
51 switch ((value & 0xF0) >> 4) {
52 case 0x0:
53 status.bits_per_sample = 8;
54 break;
55 case 0x1:
56 status.bits_per_sample = 16;
57 break;
58 case 0x2:
59 status.bits_per_sample = 20;
60 break;
61 case 0x3:
62 status.bits_per_sample = 24;
63 break;
64 case 0x4:
65 status.bits_per_sample = 32;
66 break;
67 default:
68 dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n",
69 (int)value);
70 status.bits_per_sample = 16;
71 }
72
73 /* current sampling rate in HZ */
74 if (value & 0x4000)
75 status.rate = 44100;
76 else
77 status.rate = 48000;
78 status.rate *= ((value >> 11) & 0x7) + 1;
79 status.rate /= ((value >> 8) & 0x7) + 1;
80
81 value = RREG32(R600_AUDIO_STATUS_BITS);
82
83 /* iec 60958 status bits */
84 status.status_bits = value & 0xff;
85
86 /* iec 60958 category code */
87 status.category_code = (value >> 8) & 0xff;
88
89 return status;
90}
91
92/*
93 * update all hdmi interfaces with current audio parameters
94 */
95void r600_audio_update_hdmi(struct work_struct *work)
96{
97 struct radeon_device *rdev = container_of(work, struct radeon_device,
98 audio_work);
99 struct drm_device *dev = rdev->ddev;
100 struct r600_audio_pin audio_status = r600_audio_status(rdev);
101 struct drm_encoder *encoder;
102 bool changed = false;
103
104 if (rdev->audio.pin[0].channels != audio_status.channels ||
105 rdev->audio.pin[0].rate != audio_status.rate ||
106 rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample ||
107 rdev->audio.pin[0].status_bits != audio_status.status_bits ||
108 rdev->audio.pin[0].category_code != audio_status.category_code) {
109 rdev->audio.pin[0] = audio_status;
110 changed = true;
111 }
112
113 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
114 if (!radeon_encoder_is_digital(encoder))
115 continue;
116 if (changed || r600_hdmi_buffer_status_changed(encoder))
117 r600_hdmi_update_audio_settings(encoder);
118 }
119}
120
121/* enable the audio stream */
122void r600_audio_enable(struct radeon_device *rdev,
123 struct r600_audio_pin *pin,
124 bool enable)
125{
126 u32 value = 0;
127
128 if (!pin)
129 return;
130
131 if (ASIC_IS_DCE4(rdev)) {
132 if (enable) {
133 value |= 0x81000000; /* Required to enable audio */
134 value |= 0x0e1000f0; /* fglrx sets that too */
135 }
136 WREG32(EVERGREEN_AUDIO_ENABLE, value);
137 } else {
138 WREG32_P(R600_AUDIO_ENABLE,
139 enable ? 0x81000000 : 0x0, ~0x81000000);
140 }
141}
142
143/*
144 * initialize the audio vars
145 */
146int r600_audio_init(struct radeon_device *rdev)
147{
148 if (!radeon_audio || !r600_audio_chipset_supported(rdev))
149 return 0;
150
151 rdev->audio.enabled = true;
152
153 rdev->audio.num_pins = 1;
154 rdev->audio.pin[0].channels = -1;
155 rdev->audio.pin[0].rate = -1;
156 rdev->audio.pin[0].bits_per_sample = -1;
157 rdev->audio.pin[0].status_bits = 0;
158 rdev->audio.pin[0].category_code = 0;
159 rdev->audio.pin[0].id = 0;
160 /* disable audio. it will be set up later */
161 r600_audio_enable(rdev, &rdev->audio.pin[0], false);
162
163 return 0;
164}
165
166/*
167 * release the audio timer
168 * TODO: How to do this correctly on SMP systems?
169 */
170void r600_audio_fini(struct radeon_device *rdev)
171{
172 if (!rdev->audio.enabled)
173 return;
174
175 r600_audio_enable(rdev, &rdev->audio.pin[0], false);
176
177 rdev->audio.enabled = false;
178}
179
180struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev)
181{
182 /* only one pin on 6xx-NI */
183 return &rdev->audio.pin[0];
184}
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 26ef8ced6f89..29e5f49334be 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -72,6 +72,160 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
72 72
73 73
74/* 74/*
75 * check if the chipset is supported
76 */
77static int r600_audio_chipset_supported(struct radeon_device *rdev)
78{
79 return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
80}
81
82static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev)
83{
84 struct r600_audio_pin status;
85 uint32_t value;
86
87 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
88
89 /* number of channels */
90 status.channels = (value & 0x7) + 1;
91
92 /* bits per sample */
93 switch ((value & 0xF0) >> 4) {
94 case 0x0:
95 status.bits_per_sample = 8;
96 break;
97 case 0x1:
98 status.bits_per_sample = 16;
99 break;
100 case 0x2:
101 status.bits_per_sample = 20;
102 break;
103 case 0x3:
104 status.bits_per_sample = 24;
105 break;
106 case 0x4:
107 status.bits_per_sample = 32;
108 break;
109 default:
110 dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n",
111 (int)value);
112 status.bits_per_sample = 16;
113 }
114
115 /* current sampling rate in HZ */
116 if (value & 0x4000)
117 status.rate = 44100;
118 else
119 status.rate = 48000;
120 status.rate *= ((value >> 11) & 0x7) + 1;
121 status.rate /= ((value >> 8) & 0x7) + 1;
122
123 value = RREG32(R600_AUDIO_STATUS_BITS);
124
125 /* iec 60958 status bits */
126 status.status_bits = value & 0xff;
127
128 /* iec 60958 category code */
129 status.category_code = (value >> 8) & 0xff;
130
131 return status;
132}
133
134/*
135 * update all hdmi interfaces with current audio parameters
136 */
137void r600_audio_update_hdmi(struct work_struct *work)
138{
139 struct radeon_device *rdev = container_of(work, struct radeon_device,
140 audio_work);
141 struct drm_device *dev = rdev->ddev;
142 struct r600_audio_pin audio_status = r600_audio_status(rdev);
143 struct drm_encoder *encoder;
144 bool changed = false;
145
146 if (rdev->audio.pin[0].channels != audio_status.channels ||
147 rdev->audio.pin[0].rate != audio_status.rate ||
148 rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample ||
149 rdev->audio.pin[0].status_bits != audio_status.status_bits ||
150 rdev->audio.pin[0].category_code != audio_status.category_code) {
151 rdev->audio.pin[0] = audio_status;
152 changed = true;
153 }
154
155 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
156 if (!radeon_encoder_is_digital(encoder))
157 continue;
158 if (changed || r600_hdmi_buffer_status_changed(encoder))
159 r600_hdmi_update_audio_settings(encoder);
160 }
161}
162
163/* enable the audio stream */
164void r600_audio_enable(struct radeon_device *rdev,
165 struct r600_audio_pin *pin,
166 bool enable)
167{
168 u32 value = 0;
169
170 if (!pin)
171 return;
172
173 if (ASIC_IS_DCE4(rdev)) {
174 if (enable) {
175 value |= 0x81000000; /* Required to enable audio */
176 value |= 0x0e1000f0; /* fglrx sets that too */
177 }
178 WREG32(EVERGREEN_AUDIO_ENABLE, value);
179 } else {
180 WREG32_P(R600_AUDIO_ENABLE,
181 enable ? 0x81000000 : 0x0, ~0x81000000);
182 }
183}
184
185/*
186 * initialize the audio vars
187 */
188int r600_audio_init(struct radeon_device *rdev)
189{
190 if (!radeon_audio || !r600_audio_chipset_supported(rdev))
191 return 0;
192
193 rdev->audio.enabled = true;
194
195 rdev->audio.num_pins = 1;
196 rdev->audio.pin[0].channels = -1;
197 rdev->audio.pin[0].rate = -1;
198 rdev->audio.pin[0].bits_per_sample = -1;
199 rdev->audio.pin[0].status_bits = 0;
200 rdev->audio.pin[0].category_code = 0;
201 rdev->audio.pin[0].id = 0;
202 /* disable audio. it will be set up later */
203 r600_audio_enable(rdev, &rdev->audio.pin[0], false);
204
205 return 0;
206}
207
208/*
209 * release the audio timer
210 * TODO: How to do this correctly on SMP systems?
211 */
212void r600_audio_fini(struct radeon_device *rdev)
213{
214 if (!rdev->audio.enabled)
215 return;
216
217 r600_audio_enable(rdev, &rdev->audio.pin[0], false);
218
219 rdev->audio.enabled = false;
220}
221
222struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev)
223{
224 /* only one pin on 6xx-NI */
225 return &rdev->audio.pin[0];
226}
227
228/*
75 * calculate CTS and N values if they are not found in the table 229 * calculate CTS and N values if they are not found in the table
76 */ 230 */
77static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) 231static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index ca01bb8ea217..c41363f4fc1a 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -392,7 +392,6 @@ void r600_disable_interrupts(struct radeon_device *rdev);
392void r600_rlc_stop(struct radeon_device *rdev); 392void r600_rlc_stop(struct radeon_device *rdev);
393/* r600 audio */ 393/* r600 audio */
394int r600_audio_init(struct radeon_device *rdev); 394int r600_audio_init(struct radeon_device *rdev);
395struct r600_audio_pin r600_audio_status(struct radeon_device *rdev);
396void r600_audio_fini(struct radeon_device *rdev); 395void r600_audio_fini(struct radeon_device *rdev);
397void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock); 396void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
398void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, 397void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,