diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_audio.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600_audio.c | 215 |
1 files changed, 83 insertions, 132 deletions
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index ba66f3093d46..7c4fa77f018f 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
@@ -29,7 +29,28 @@ | |||
29 | #include "radeon_asic.h" | 29 | #include "radeon_asic.h" |
30 | #include "atom.h" | 30 | #include "atom.h" |
31 | 31 | ||
32 | #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ | 32 | /* |
33 | * check if enc_priv stores radeon_encoder_atom_dig | ||
34 | */ | ||
35 | static bool radeon_dig_encoder(struct drm_encoder *encoder) | ||
36 | { | ||
37 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
38 | switch (radeon_encoder->encoder_id) { | ||
39 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
40 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
41 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
42 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
43 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
44 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
45 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
46 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
47 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
48 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
49 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
50 | return true; | ||
51 | } | ||
52 | return false; | ||
53 | } | ||
33 | 54 | ||
34 | /* | 55 | /* |
35 | * check if the chipset is supported | 56 | * check if the chipset is supported |
@@ -42,118 +63,85 @@ static int r600_audio_chipset_supported(struct radeon_device *rdev) | |||
42 | || rdev->family == CHIP_RS740; | 63 | || rdev->family == CHIP_RS740; |
43 | } | 64 | } |
44 | 65 | ||
45 | /* | 66 | struct r600_audio r600_audio_status(struct radeon_device *rdev) |
46 | * current number of channels | ||
47 | */ | ||
48 | int r600_audio_channels(struct radeon_device *rdev) | ||
49 | { | 67 | { |
50 | return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; | 68 | struct r600_audio status; |
51 | } | 69 | uint32_t value; |
52 | 70 | ||
53 | /* | 71 | value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
54 | * current bits per sample | ||
55 | */ | ||
56 | int r600_audio_bits_per_sample(struct radeon_device *rdev) | ||
57 | { | ||
58 | uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; | ||
59 | switch (value) { | ||
60 | case 0x0: return 8; | ||
61 | case 0x1: return 16; | ||
62 | case 0x2: return 20; | ||
63 | case 0x3: return 24; | ||
64 | case 0x4: return 32; | ||
65 | } | ||
66 | 72 | ||
67 | dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n", | 73 | /* number of channels */ |
68 | (int)value); | 74 | status.channels = (value & 0x7) + 1; |
69 | 75 | ||
70 | return 16; | 76 | /* bits per sample */ |
71 | } | 77 | switch ((value & 0xF0) >> 4) { |
72 | 78 | case 0x0: | |
73 | /* | 79 | status.bits_per_sample = 8; |
74 | * current sampling rate in HZ | 80 | break; |
75 | */ | 81 | case 0x1: |
76 | int r600_audio_rate(struct radeon_device *rdev) | 82 | status.bits_per_sample = 16; |
77 | { | 83 | break; |
78 | uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); | 84 | case 0x2: |
79 | uint32_t result; | 85 | status.bits_per_sample = 20; |
86 | break; | ||
87 | case 0x3: | ||
88 | status.bits_per_sample = 24; | ||
89 | break; | ||
90 | case 0x4: | ||
91 | status.bits_per_sample = 32; | ||
92 | break; | ||
93 | default: | ||
94 | dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", | ||
95 | (int)value); | ||
96 | status.bits_per_sample = 16; | ||
97 | } | ||
80 | 98 | ||
99 | /* current sampling rate in HZ */ | ||
81 | if (value & 0x4000) | 100 | if (value & 0x4000) |
82 | result = 44100; | 101 | status.rate = 44100; |
83 | else | 102 | else |
84 | result = 48000; | 103 | status.rate = 48000; |
104 | status.rate *= ((value >> 11) & 0x7) + 1; | ||
105 | status.rate /= ((value >> 8) & 0x7) + 1; | ||
85 | 106 | ||
86 | result *= ((value >> 11) & 0x7) + 1; | 107 | value = RREG32(R600_AUDIO_STATUS_BITS); |
87 | result /= ((value >> 8) & 0x7) + 1; | ||
88 | 108 | ||
89 | return result; | 109 | /* iec 60958 status bits */ |
90 | } | 110 | status.status_bits = value & 0xff; |
91 | 111 | ||
92 | /* | 112 | /* iec 60958 category code */ |
93 | * iec 60958 status bits | 113 | status.category_code = (value >> 8) & 0xff; |
94 | */ | ||
95 | uint8_t r600_audio_status_bits(struct radeon_device *rdev) | ||
96 | { | ||
97 | return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; | ||
98 | } | ||
99 | 114 | ||
100 | /* | 115 | return status; |
101 | * iec 60958 category code | ||
102 | */ | ||
103 | uint8_t r600_audio_category_code(struct radeon_device *rdev) | ||
104 | { | ||
105 | return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * schedule next audio update event | ||
110 | */ | ||
111 | void r600_audio_schedule_polling(struct radeon_device *rdev) | ||
112 | { | ||
113 | mod_timer(&rdev->audio_timer, | ||
114 | jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); | ||
115 | } | 116 | } |
116 | 117 | ||
117 | /* | 118 | /* |
118 | * update all hdmi interfaces with current audio parameters | 119 | * update all hdmi interfaces with current audio parameters |
119 | */ | 120 | */ |
120 | static void r600_audio_update_hdmi(unsigned long param) | 121 | void r600_audio_update_hdmi(struct work_struct *work) |
121 | { | 122 | { |
122 | struct radeon_device *rdev = (struct radeon_device *)param; | 123 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
124 | audio_work); | ||
123 | struct drm_device *dev = rdev->ddev; | 125 | struct drm_device *dev = rdev->ddev; |
124 | 126 | struct r600_audio audio_status = r600_audio_status(rdev); | |
125 | int channels = r600_audio_channels(rdev); | ||
126 | int rate = r600_audio_rate(rdev); | ||
127 | int bps = r600_audio_bits_per_sample(rdev); | ||
128 | uint8_t status_bits = r600_audio_status_bits(rdev); | ||
129 | uint8_t category_code = r600_audio_category_code(rdev); | ||
130 | |||
131 | struct drm_encoder *encoder; | 127 | struct drm_encoder *encoder; |
132 | int changes = 0, still_going = 0; | 128 | bool changed = false; |
133 | 129 | ||
134 | changes |= channels != rdev->audio_channels; | 130 | if (rdev->audio_status.channels != audio_status.channels || |
135 | changes |= rate != rdev->audio_rate; | 131 | rdev->audio_status.rate != audio_status.rate || |
136 | changes |= bps != rdev->audio_bits_per_sample; | 132 | rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || |
137 | changes |= status_bits != rdev->audio_status_bits; | 133 | rdev->audio_status.status_bits != audio_status.status_bits || |
138 | changes |= category_code != rdev->audio_category_code; | 134 | rdev->audio_status.category_code != audio_status.category_code) { |
139 | 135 | rdev->audio_status = audio_status; | |
140 | if (changes) { | 136 | changed = true; |
141 | rdev->audio_channels = channels; | ||
142 | rdev->audio_rate = rate; | ||
143 | rdev->audio_bits_per_sample = bps; | ||
144 | rdev->audio_status_bits = status_bits; | ||
145 | rdev->audio_category_code = category_code; | ||
146 | } | 137 | } |
147 | 138 | ||
148 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 139 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
149 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 140 | if (!radeon_dig_encoder(encoder)) |
150 | still_going |= radeon_encoder->audio_polling_active; | 141 | continue; |
151 | if (changes || r600_hdmi_buffer_status_changed(encoder)) | 142 | if (changed || r600_hdmi_buffer_status_changed(encoder)) |
152 | r600_hdmi_update_audio_settings(encoder); | 143 | r600_hdmi_update_audio_settings(encoder); |
153 | } | 144 | } |
154 | |||
155 | if (still_going) | ||
156 | r600_audio_schedule_polling(rdev); | ||
157 | } | 145 | } |
158 | 146 | ||
159 | /* | 147 | /* |
@@ -177,7 +165,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) | |||
177 | } | 165 | } |
178 | 166 | ||
179 | /* | 167 | /* |
180 | * initialize the audio vars and register the update timer | 168 | * initialize the audio vars |
181 | */ | 169 | */ |
182 | int r600_audio_init(struct radeon_device *rdev) | 170 | int r600_audio_init(struct radeon_device *rdev) |
183 | { | 171 | { |
@@ -186,51 +174,16 @@ int r600_audio_init(struct radeon_device *rdev) | |||
186 | 174 | ||
187 | r600_audio_engine_enable(rdev, true); | 175 | r600_audio_engine_enable(rdev, true); |
188 | 176 | ||
189 | rdev->audio_channels = -1; | 177 | rdev->audio_status.channels = -1; |
190 | rdev->audio_rate = -1; | 178 | rdev->audio_status.rate = -1; |
191 | rdev->audio_bits_per_sample = -1; | 179 | rdev->audio_status.bits_per_sample = -1; |
192 | rdev->audio_status_bits = 0; | 180 | rdev->audio_status.status_bits = 0; |
193 | rdev->audio_category_code = 0; | 181 | rdev->audio_status.category_code = 0; |
194 | |||
195 | setup_timer( | ||
196 | &rdev->audio_timer, | ||
197 | r600_audio_update_hdmi, | ||
198 | (unsigned long)rdev); | ||
199 | 182 | ||
200 | return 0; | 183 | return 0; |
201 | } | 184 | } |
202 | 185 | ||
203 | /* | 186 | /* |
204 | * enable the polling timer, to check for status changes | ||
205 | */ | ||
206 | void r600_audio_enable_polling(struct drm_encoder *encoder) | ||
207 | { | ||
208 | struct drm_device *dev = encoder->dev; | ||
209 | struct radeon_device *rdev = dev->dev_private; | ||
210 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
211 | |||
212 | DRM_DEBUG("r600_audio_enable_polling: %d\n", | ||
213 | radeon_encoder->audio_polling_active); | ||
214 | if (radeon_encoder->audio_polling_active) | ||
215 | return; | ||
216 | |||
217 | radeon_encoder->audio_polling_active = 1; | ||
218 | if (rdev->audio_enabled) | ||
219 | mod_timer(&rdev->audio_timer, jiffies + 1); | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * disable the polling timer, so we get no more status updates | ||
224 | */ | ||
225 | void r600_audio_disable_polling(struct drm_encoder *encoder) | ||
226 | { | ||
227 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
228 | DRM_DEBUG("r600_audio_disable_polling: %d\n", | ||
229 | radeon_encoder->audio_polling_active); | ||
230 | radeon_encoder->audio_polling_active = 0; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * atach the audio codec to the clock source of the encoder | 187 | * atach the audio codec to the clock source of the encoder |
235 | */ | 188 | */ |
236 | void r600_audio_set_clock(struct drm_encoder *encoder, int clock) | 189 | void r600_audio_set_clock(struct drm_encoder *encoder, int clock) |
@@ -297,7 +250,5 @@ void r600_audio_fini(struct radeon_device *rdev) | |||
297 | if (!rdev->audio_enabled) | 250 | if (!rdev->audio_enabled) |
298 | return; | 251 | return; |
299 | 252 | ||
300 | del_timer(&rdev->audio_timer); | ||
301 | |||
302 | r600_audio_engine_enable(rdev, false); | 253 | r600_audio_engine_enable(rdev, false); |
303 | } | 254 | } |