diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/dce3_1_afmt.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_hdmi.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_audio.c | 100 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_audio.h | 3 |
5 files changed, 183 insertions, 133 deletions
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c index 0accc5ee0e39..2a963c173cc1 100644 --- a/drivers/gpu/drm/radeon/dce3_1_afmt.c +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c | |||
@@ -167,6 +167,38 @@ void dce3_2_audio_set_dto(struct radeon_device *rdev, | |||
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
171 | const struct radeon_hdmi_acr *acr) | ||
172 | { | ||
173 | struct drm_device *dev = encoder->dev; | ||
174 | struct radeon_device *rdev = dev->dev_private; | ||
175 | |||
176 | WREG32(HDMI0_ACR_PACKET_CONTROL + offset, | ||
177 | HDMI0_ACR_SOURCE | /* select SW CTS value */ | ||
178 | HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
179 | |||
180 | WREG32_P(HDMI0_ACR_32_0 + offset, | ||
181 | HDMI0_ACR_CTS_32(acr->cts_32khz), | ||
182 | ~HDMI0_ACR_CTS_32_MASK); | ||
183 | WREG32_P(HDMI0_ACR_32_1 + offset, | ||
184 | HDMI0_ACR_N_32(acr->n_32khz), | ||
185 | ~HDMI0_ACR_N_32_MASK); | ||
186 | |||
187 | WREG32_P(HDMI0_ACR_44_0 + offset, | ||
188 | HDMI0_ACR_CTS_44(acr->cts_44_1khz), | ||
189 | ~HDMI0_ACR_CTS_44_MASK); | ||
190 | WREG32_P(HDMI0_ACR_44_1 + offset, | ||
191 | HDMI0_ACR_N_44(acr->n_44_1khz), | ||
192 | ~HDMI0_ACR_N_44_MASK); | ||
193 | |||
194 | WREG32_P(HDMI0_ACR_48_0 + offset, | ||
195 | HDMI0_ACR_CTS_48(acr->cts_48khz), | ||
196 | ~HDMI0_ACR_CTS_48_MASK); | ||
197 | WREG32_P(HDMI0_ACR_48_1 + offset, | ||
198 | HDMI0_ACR_N_48(acr->n_48khz), | ||
199 | ~HDMI0_ACR_N_48_MASK); | ||
200 | } | ||
201 | |||
170 | /* | 202 | /* |
171 | * update the info frames with the data from the current display mode | 203 | * update the info frames with the data from the current display mode |
172 | */ | 204 | */ |
@@ -220,10 +252,6 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m | |||
220 | radeon_audio_write_sad_regs(encoder); | 252 | radeon_audio_write_sad_regs(encoder); |
221 | } | 253 | } |
222 | 254 | ||
223 | WREG32(HDMI0_ACR_PACKET_CONTROL + offset, | ||
224 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ | ||
225 | HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
226 | |||
227 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, | 255 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, |
228 | HDMI0_NULL_SEND | /* send null packets when required */ | 256 | HDMI0_NULL_SEND | /* send null packets when required */ |
229 | HDMI0_GC_SEND | /* send general control packets */ | 257 | HDMI0_GC_SEND | /* send general control packets */ |
@@ -255,7 +283,7 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m | |||
255 | } | 283 | } |
256 | 284 | ||
257 | radeon_update_avi_infoframe(encoder, buffer, sizeof(buffer)); | 285 | radeon_update_avi_infoframe(encoder, buffer, sizeof(buffer)); |
258 | r600_hdmi_update_ACR(encoder, mode->clock); | 286 | radeon_audio_update_acr(encoder, mode->clock); |
259 | 287 | ||
260 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ | 288 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ |
261 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); | 289 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); |
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index f2896e5ff055..05cef011c3af 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c | |||
@@ -64,26 +64,34 @@ void dce4_audio_enable(struct radeon_device *rdev, | |||
64 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); | 64 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); |
65 | } | 65 | } |
66 | 66 | ||
67 | /* | 67 | void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset, |
68 | * update the N and CTS parameters for a given pixel clock rate | 68 | const struct radeon_hdmi_acr *acr) |
69 | */ | ||
70 | static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) | ||
71 | { | 69 | { |
72 | struct drm_device *dev = encoder->dev; | 70 | struct drm_device *dev = encoder->dev; |
73 | struct radeon_device *rdev = dev->dev_private; | 71 | struct radeon_device *rdev = dev->dev_private; |
74 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); | 72 | int bpc = 8; |
75 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 73 | |
76 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 74 | if (encoder->crtc) { |
77 | uint32_t offset = dig->afmt->offset; | 75 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
76 | bpc = radeon_crtc->bpc; | ||
77 | } | ||
78 | 78 | ||
79 | WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz)); | 79 | if (bpc > 8) |
80 | WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz); | 80 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, |
81 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
82 | else | ||
83 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
84 | HDMI_ACR_SOURCE | /* select SW CTS value */ | ||
85 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
86 | |||
87 | WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr->cts_32khz)); | ||
88 | WREG32(HDMI_ACR_32_1 + offset, acr->n_32khz); | ||
81 | 89 | ||
82 | WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz)); | 90 | WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr->cts_44_1khz)); |
83 | WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz); | 91 | WREG32(HDMI_ACR_44_1 + offset, acr->n_44_1khz); |
84 | 92 | ||
85 | WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz)); | 93 | WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr->cts_48khz)); |
86 | WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz); | 94 | WREG32(HDMI_ACR_48_1 + offset, acr->n_48khz); |
87 | } | 95 | } |
88 | 96 | ||
89 | void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, | 97 | void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, |
@@ -378,15 +386,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode | |||
378 | 386 | ||
379 | /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ | 387 | /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ |
380 | 388 | ||
381 | if (bpc > 8) | 389 | radeon_audio_update_acr(encoder, mode->clock); |
382 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
383 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
384 | else | ||
385 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
386 | HDMI_ACR_SOURCE | /* select SW CTS value */ | ||
387 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
388 | |||
389 | evergreen_hdmi_update_ACR(encoder, mode->clock); | ||
390 | 390 | ||
391 | WREG32(AFMT_60958_0 + offset, | 391 | WREG32(AFMT_60958_0 + offset, |
392 | AFMT_60958_CS_CHANNEL_NUMBER_L(1)); | 392 | AFMT_60958_CS_CHANNEL_NUMBER_L(1)); |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 53ee7ad9612c..f91273912eb8 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -56,21 +56,6 @@ enum r600_hdmi_iec_status_bits { | |||
56 | AUDIO_STATUS_LEVEL = 0x80 | 56 | AUDIO_STATUS_LEVEL = 0x80 |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { | ||
60 | /* 32kHz 44.1kHz 48kHz */ | ||
61 | /* Clock N CTS N CTS N CTS */ | ||
62 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ | ||
63 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ | ||
64 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ | ||
65 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ | ||
66 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ | ||
67 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ | ||
68 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ | ||
69 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ | ||
70 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ | ||
71 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ | ||
72 | }; | ||
73 | |||
74 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) | 59 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) |
75 | { | 60 | { |
76 | struct r600_audio_pin status; | 61 | struct r600_audio_pin status; |
@@ -189,97 +174,41 @@ struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) | |||
189 | return &rdev->audio.pin[0]; | 174 | return &rdev->audio.pin[0]; |
190 | } | 175 | } |
191 | 176 | ||
192 | /* | 177 | void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset, |
193 | * calculate CTS and N values if they are not found in the table | 178 | const struct radeon_hdmi_acr *acr) |
194 | */ | ||
195 | static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) | ||
196 | { | ||
197 | int n, cts; | ||
198 | unsigned long div, mul; | ||
199 | |||
200 | /* Safe, but overly large values */ | ||
201 | n = 128 * freq; | ||
202 | cts = clock * 1000; | ||
203 | |||
204 | /* Smallest valid fraction */ | ||
205 | div = gcd(n, cts); | ||
206 | |||
207 | n /= div; | ||
208 | cts /= div; | ||
209 | |||
210 | /* | ||
211 | * The optimal N is 128*freq/1000. Calculate the closest larger | ||
212 | * value that doesn't truncate any bits. | ||
213 | */ | ||
214 | mul = ((128*freq/1000) + (n-1))/n; | ||
215 | |||
216 | n *= mul; | ||
217 | cts *= mul; | ||
218 | |||
219 | /* Check that we are in spec (not always possible) */ | ||
220 | if (n < (128*freq/1500)) | ||
221 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); | ||
222 | if (n > (128*freq/300)) | ||
223 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); | ||
224 | |||
225 | *N = n; | ||
226 | *CTS = cts; | ||
227 | |||
228 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", | ||
229 | *N, *CTS, freq); | ||
230 | } | ||
231 | |||
232 | struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) | ||
233 | { | ||
234 | struct radeon_hdmi_acr res; | ||
235 | u8 i; | ||
236 | |||
237 | /* Precalculated values for common clocks */ | ||
238 | for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { | ||
239 | if (r600_hdmi_predefined_acr[i].clock == clock) | ||
240 | return r600_hdmi_predefined_acr[i]; | ||
241 | } | ||
242 | |||
243 | /* And odd clocks get manually calculated */ | ||
244 | r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); | ||
245 | r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); | ||
246 | r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); | ||
247 | |||
248 | return res; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * update the N and CTS parameters for a given pixel clock rate | ||
253 | */ | ||
254 | void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) | ||
255 | { | 179 | { |
256 | struct drm_device *dev = encoder->dev; | 180 | struct drm_device *dev = encoder->dev; |
257 | struct radeon_device *rdev = dev->dev_private; | 181 | struct radeon_device *rdev = dev->dev_private; |
258 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); | 182 | |
259 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 183 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ |
260 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 184 | uint32_t acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : |
261 | uint32_t offset = dig->afmt->offset; | 185 | HDMI0_ACR_PACKET_CONTROL; |
186 | WREG32_P(acr_ctl + offset, | ||
187 | HDMI0_ACR_SOURCE | /* select SW CTS value */ | ||
188 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ | ||
189 | ~(HDMI0_ACR_SOURCE | | ||
190 | HDMI0_ACR_AUTO_SEND)); | ||
262 | 191 | ||
263 | WREG32_P(HDMI0_ACR_32_0 + offset, | 192 | WREG32_P(HDMI0_ACR_32_0 + offset, |
264 | HDMI0_ACR_CTS_32(acr.cts_32khz), | 193 | HDMI0_ACR_CTS_32(acr->cts_32khz), |
265 | ~HDMI0_ACR_CTS_32_MASK); | 194 | ~HDMI0_ACR_CTS_32_MASK); |
266 | WREG32_P(HDMI0_ACR_32_1 + offset, | 195 | WREG32_P(HDMI0_ACR_32_1 + offset, |
267 | HDMI0_ACR_N_32(acr.n_32khz), | 196 | HDMI0_ACR_N_32(acr->n_32khz), |
268 | ~HDMI0_ACR_N_32_MASK); | 197 | ~HDMI0_ACR_N_32_MASK); |
269 | 198 | ||
270 | WREG32_P(HDMI0_ACR_44_0 + offset, | 199 | WREG32_P(HDMI0_ACR_44_0 + offset, |
271 | HDMI0_ACR_CTS_44(acr.cts_44_1khz), | 200 | HDMI0_ACR_CTS_44(acr->cts_44_1khz), |
272 | ~HDMI0_ACR_CTS_44_MASK); | 201 | ~HDMI0_ACR_CTS_44_MASK); |
273 | WREG32_P(HDMI0_ACR_44_1 + offset, | 202 | WREG32_P(HDMI0_ACR_44_1 + offset, |
274 | HDMI0_ACR_N_44(acr.n_44_1khz), | 203 | HDMI0_ACR_N_44(acr->n_44_1khz), |
275 | ~HDMI0_ACR_N_44_MASK); | 204 | ~HDMI0_ACR_N_44_MASK); |
276 | 205 | ||
277 | WREG32_P(HDMI0_ACR_48_0 + offset, | 206 | WREG32_P(HDMI0_ACR_48_0 + offset, |
278 | HDMI0_ACR_CTS_48(acr.cts_48khz), | 207 | HDMI0_ACR_CTS_48(acr->cts_48khz), |
279 | ~HDMI0_ACR_CTS_48_MASK); | 208 | ~HDMI0_ACR_CTS_48_MASK); |
280 | WREG32_P(HDMI0_ACR_48_1 + offset, | 209 | WREG32_P(HDMI0_ACR_48_1 + offset, |
281 | HDMI0_ACR_N_48(acr.n_48khz), | 210 | HDMI0_ACR_N_48(acr->n_48khz), |
282 | ~HDMI0_ACR_N_48_MASK); | 211 | ~HDMI0_ACR_N_48_MASK); |
283 | } | 212 | } |
284 | 213 | ||
285 | /* | 214 | /* |
@@ -412,7 +341,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod | |||
412 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | 341 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
413 | struct hdmi_avi_infoframe frame; | 342 | struct hdmi_avi_infoframe frame; |
414 | uint32_t offset; | 343 | uint32_t offset; |
415 | uint32_t acr_ctl; | ||
416 | ssize_t err; | 344 | ssize_t err; |
417 | 345 | ||
418 | if (!dig || !dig->afmt) | 346 | if (!dig || !dig->afmt) |
@@ -439,15 +367,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod | |||
439 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | | 367 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | |
440 | HDMI0_60958_CS_UPDATE)); | 368 | HDMI0_60958_CS_UPDATE)); |
441 | 369 | ||
442 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ | ||
443 | acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : | ||
444 | HDMI0_ACR_PACKET_CONTROL; | ||
445 | WREG32_P(acr_ctl + offset, | ||
446 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ | ||
447 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ | ||
448 | ~(HDMI0_ACR_SOURCE | | ||
449 | HDMI0_ACR_AUTO_SEND)); | ||
450 | |||
451 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, | 370 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, |
452 | HDMI0_NULL_SEND | /* send null packets when required */ | 371 | HDMI0_NULL_SEND | /* send null packets when required */ |
453 | HDMI0_GC_SEND | /* send general control packets */ | 372 | HDMI0_GC_SEND | /* send general control packets */ |
@@ -493,7 +412,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod | |||
493 | HDMI0_GENERIC0_LINE_MASK | | 412 | HDMI0_GENERIC0_LINE_MASK | |
494 | HDMI0_GENERIC1_LINE_MASK)); | 413 | HDMI0_GENERIC1_LINE_MASK)); |
495 | 414 | ||
496 | r600_hdmi_update_ACR(encoder, mode->clock); | 415 | radeon_audio_update_acr(encoder, mode->clock); |
497 | 416 | ||
498 | WREG32_P(HDMI0_60958_0 + offset, | 417 | WREG32_P(HDMI0_60958_0 + offset, |
499 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), | 418 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), |
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index cc58ee8c7d2f..dbb3c594e9ae 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c | |||
@@ -22,6 +22,7 @@ | |||
22 | * Authors: Slava Grigorev <slava.grigorev@amd.com> | 22 | * Authors: Slava Grigorev <slava.grigorev@amd.com> |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/gcd.h> | ||
25 | #include <drm/drmP.h> | 26 | #include <drm/drmP.h> |
26 | #include <drm/drm_crtc.h> | 27 | #include <drm/drm_crtc.h> |
27 | #include "radeon.h" | 28 | #include "radeon.h" |
@@ -78,6 +79,12 @@ void r600_update_avi_infoframe(struct radeon_device *rdev, u32 offset, | |||
78 | unsigned char *buffer, size_t size); | 79 | unsigned char *buffer, size_t size); |
79 | void evergreen_update_avi_infoframe(struct radeon_device *rdev, u32 offset, | 80 | void evergreen_update_avi_infoframe(struct radeon_device *rdev, u32 offset, |
80 | unsigned char *buffer, size_t size); | 81 | unsigned char *buffer, size_t size); |
82 | void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
83 | const struct radeon_hdmi_acr *acr); | ||
84 | void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
85 | const struct radeon_hdmi_acr *acr); | ||
86 | void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
87 | const struct radeon_hdmi_acr *acr); | ||
81 | 88 | ||
82 | static const u32 pin_offsets[7] = | 89 | static const u32 pin_offsets[7] = |
83 | { | 90 | { |
@@ -132,6 +139,7 @@ static struct radeon_audio_basic_funcs dce6_funcs = { | |||
132 | static struct radeon_audio_funcs r600_hdmi_funcs = { | 139 | static struct radeon_audio_funcs r600_hdmi_funcs = { |
133 | .get_pin = r600_audio_get_pin, | 140 | .get_pin = r600_audio_get_pin, |
134 | .set_dto = r600_hdmi_audio_set_dto, | 141 | .set_dto = r600_hdmi_audio_set_dto, |
142 | .update_acr = r600_hdmi_update_acr, | ||
135 | }; | 143 | }; |
136 | 144 | ||
137 | static struct radeon_audio_funcs dce32_hdmi_funcs = { | 145 | static struct radeon_audio_funcs dce32_hdmi_funcs = { |
@@ -139,6 +147,7 @@ static struct radeon_audio_funcs dce32_hdmi_funcs = { | |||
139 | .write_sad_regs = dce3_2_afmt_write_sad_regs, | 147 | .write_sad_regs = dce3_2_afmt_write_sad_regs, |
140 | .write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation, | 148 | .write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation, |
141 | .set_dto = dce3_2_audio_set_dto, | 149 | .set_dto = dce3_2_audio_set_dto, |
150 | .update_acr = dce3_2_hdmi_update_acr, | ||
142 | }; | 151 | }; |
143 | 152 | ||
144 | static struct radeon_audio_funcs dce32_dp_funcs = { | 153 | static struct radeon_audio_funcs dce32_dp_funcs = { |
@@ -154,6 +163,7 @@ static struct radeon_audio_funcs dce4_hdmi_funcs = { | |||
154 | .write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation, | 163 | .write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation, |
155 | .write_latency_fields = dce4_afmt_write_latency_fields, | 164 | .write_latency_fields = dce4_afmt_write_latency_fields, |
156 | .set_dto = dce4_hdmi_audio_set_dto, | 165 | .set_dto = dce4_hdmi_audio_set_dto, |
166 | .update_acr = evergreen_hdmi_update_acr, | ||
157 | }; | 167 | }; |
158 | 168 | ||
159 | static struct radeon_audio_funcs dce4_dp_funcs = { | 169 | static struct radeon_audio_funcs dce4_dp_funcs = { |
@@ -171,6 +181,7 @@ static struct radeon_audio_funcs dce6_hdmi_funcs = { | |||
171 | .write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation, | 181 | .write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation, |
172 | .write_latency_fields = dce6_afmt_write_latency_fields, | 182 | .write_latency_fields = dce6_afmt_write_latency_fields, |
173 | .set_dto = dce6_hdmi_audio_set_dto, | 183 | .set_dto = dce6_hdmi_audio_set_dto, |
184 | .update_acr = evergreen_hdmi_update_acr, | ||
174 | }; | 185 | }; |
175 | 186 | ||
176 | static struct radeon_audio_funcs dce6_dp_funcs = { | 187 | static struct radeon_audio_funcs dce6_dp_funcs = { |
@@ -456,3 +467,92 @@ void radeon_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, | |||
456 | rdev->audio.funcs->update_avi_infoframe(rdev, dig->afmt->offset, | 467 | rdev->audio.funcs->update_avi_infoframe(rdev, dig->afmt->offset, |
457 | buffer, size); | 468 | buffer, size); |
458 | } | 469 | } |
470 | |||
471 | /* | ||
472 | * calculate CTS and N values if they are not found in the table | ||
473 | */ | ||
474 | static void radeon_audio_calc_cts(unsigned int clock, int *CTS, int *N, int freq) | ||
475 | { | ||
476 | int n, cts; | ||
477 | unsigned long div, mul; | ||
478 | |||
479 | /* Safe, but overly large values */ | ||
480 | n = 128 * freq; | ||
481 | cts = clock * 1000; | ||
482 | |||
483 | /* Smallest valid fraction */ | ||
484 | div = gcd(n, cts); | ||
485 | |||
486 | n /= div; | ||
487 | cts /= div; | ||
488 | |||
489 | /* | ||
490 | * The optimal N is 128*freq/1000. Calculate the closest larger | ||
491 | * value that doesn't truncate any bits. | ||
492 | */ | ||
493 | mul = ((128*freq/1000) + (n-1))/n; | ||
494 | |||
495 | n *= mul; | ||
496 | cts *= mul; | ||
497 | |||
498 | /* Check that we are in spec (not always possible) */ | ||
499 | if (n < (128*freq/1500)) | ||
500 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); | ||
501 | if (n > (128*freq/300)) | ||
502 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); | ||
503 | |||
504 | *N = n; | ||
505 | *CTS = cts; | ||
506 | |||
507 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", | ||
508 | *N, *CTS, freq); | ||
509 | } | ||
510 | |||
511 | static const struct radeon_hdmi_acr* radeon_audio_acr(unsigned int clock) | ||
512 | { | ||
513 | static struct radeon_hdmi_acr res; | ||
514 | u8 i; | ||
515 | |||
516 | static const struct radeon_hdmi_acr hdmi_predefined_acr[] = { | ||
517 | /* 32kHz 44.1kHz 48kHz */ | ||
518 | /* Clock N CTS N CTS N CTS */ | ||
519 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ | ||
520 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ | ||
521 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ | ||
522 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ | ||
523 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ | ||
524 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ | ||
525 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ | ||
526 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ | ||
527 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ | ||
528 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ | ||
529 | }; | ||
530 | |||
531 | /* Precalculated values for common clocks */ | ||
532 | for (i = 0; i < ARRAY_SIZE(hdmi_predefined_acr); i++) | ||
533 | if (hdmi_predefined_acr[i].clock == clock) | ||
534 | return &hdmi_predefined_acr[i]; | ||
535 | |||
536 | /* And odd clocks get manually calculated */ | ||
537 | radeon_audio_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); | ||
538 | radeon_audio_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); | ||
539 | radeon_audio_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); | ||
540 | |||
541 | return &res; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * update the N and CTS parameters for a given pixel clock rate | ||
546 | */ | ||
547 | void radeon_audio_update_acr(struct drm_encoder *encoder, unsigned int clock) | ||
548 | { | ||
549 | const struct radeon_hdmi_acr *acr = radeon_audio_acr(clock); | ||
550 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
551 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
552 | |||
553 | if (!dig || !dig->afmt) | ||
554 | return; | ||
555 | |||
556 | if (radeon_encoder->audio && radeon_encoder->audio->update_acr) | ||
557 | radeon_encoder->audio->update_acr(encoder, dig->afmt->offset, acr); | ||
558 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index dc85d53d1587..a4d055311ab5 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h | |||
@@ -55,6 +55,8 @@ struct radeon_audio_funcs | |||
55 | u8 *sadb, int sad_count); | 55 | u8 *sadb, int sad_count); |
56 | void (*set_dto)(struct radeon_device *rdev, | 56 | void (*set_dto)(struct radeon_device *rdev, |
57 | struct radeon_crtc *crtc, unsigned int clock); | 57 | struct radeon_crtc *crtc, unsigned int clock); |
58 | void (*update_acr)(struct drm_encoder *encoder, long offset, | ||
59 | const struct radeon_hdmi_acr *acr); | ||
58 | }; | 60 | }; |
59 | 61 | ||
60 | int radeon_audio_init(struct radeon_device *rdev); | 62 | int radeon_audio_init(struct radeon_device *rdev); |
@@ -76,5 +78,6 @@ void radeon_audio_fini(struct radeon_device *rdev); | |||
76 | void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock); | 78 | void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock); |
77 | void radeon_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, | 79 | void radeon_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, |
78 | size_t size); | 80 | size_t size); |
81 | void radeon_audio_update_acr(struct drm_encoder *encoder, unsigned int clock); | ||
79 | 82 | ||
80 | #endif | 83 | #endif |