Rev 3764 | Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3764 | Rev 5078 | ||
---|---|---|---|
Line 55... | Line 55... | ||
55 | }; |
55 | }; |
Line 56... | Line 56... | ||
56 | 56 | ||
57 | static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { |
57 | static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { |
58 | /* 32kHz 44.1kHz 48kHz */ |
58 | /* 32kHz 44.1kHz 48kHz */ |
59 | /* Clock N CTS N CTS N CTS */ |
59 | /* Clock N CTS N CTS N CTS */ |
60 | { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ |
60 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ |
61 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ |
61 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ |
62 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ |
62 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ |
63 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ |
63 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ |
64 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ |
64 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ |
65 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ |
65 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ |
66 | { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ |
66 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ |
67 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ |
67 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ |
68 | { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ |
68 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ |
69 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ |
- | |
70 | { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ |
69 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ |
Line -... | Line 70... | ||
- | 70 | }; |
|
71 | }; |
71 | |
72 | 72 | ||
73 | /* |
73 | /* |
74 | * calculate CTS value if it's not found in the table |
74 | * calculate CTS and N values if they are not found in the table |
75 | */ |
75 | */ |
- | 76 | static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) |
|
- | 77 | { |
|
- | 78 | int n, cts; |
|
- | 79 | unsigned long div, mul; |
|
- | 80 | ||
- | 81 | /* Safe, but overly large values */ |
|
- | 82 | n = 128 * freq; |
|
- | 83 | cts = clock * 1000; |
|
76 | static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) |
84 | |
- | 85 | /* Smallest valid fraction */ |
|
- | 86 | div = gcd(n, cts); |
|
- | 87 | ||
- | 88 | n /= div; |
|
- | 89 | cts /= div; |
|
- | 90 | ||
- | 91 | /* |
|
- | 92 | * The optimal N is 128*freq/1000. Calculate the closest larger |
|
- | 93 | * value that doesn't truncate any bits. |
|
- | 94 | */ |
|
- | 95 | mul = ((128*freq/1000) + (n-1))/n; |
|
- | 96 | ||
- | 97 | n *= mul; |
|
- | 98 | cts *= mul; |
|
77 | { |
99 | |
- | 100 | /* Check that we are in spec (not always possible) */ |
|
- | 101 | if (n < (128*freq/1500)) |
|
- | 102 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); |
|
- | 103 | if (n > (128*freq/300)) |
|
- | 104 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); |
|
- | 105 | ||
- | 106 | *N = n; |
|
78 | if (*CTS == 0) |
107 | *CTS = cts; |
79 | *CTS = clock * N / (128 * freq) * 1000; |
108 | |
80 | DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", |
109 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", |
Line 81... | Line 110... | ||
81 | N, *CTS, freq); |
110 | *N, *CTS, freq); |
82 | } |
111 | } |
83 | 112 | ||
84 | struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) |
113 | struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) |
Line -... | Line 114... | ||
- | 114 | { |
|
85 | { |
115 | struct radeon_hdmi_acr res; |
86 | struct radeon_hdmi_acr res; |
116 | u8 i; |
87 | u8 i; |
- | |
88 | 117 | ||
- | 118 | /* Precalculated values for common clocks */ |
|
89 | for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && |
119 | for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { |
90 | r600_hdmi_predefined_acr[i].clock != 0; i++) |
120 | if (r600_hdmi_predefined_acr[i].clock == clock) |
91 | ; |
121 | return r600_hdmi_predefined_acr[i]; |
92 | res = r600_hdmi_predefined_acr[i]; |
122 | } |
93 | 123 | ||
Line 94... | Line 124... | ||
94 | /* In case some CTS are missing */ |
124 | /* And odd clocks get manually calculated */ |
95 | r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); |
125 | r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); |
Line 96... | Line 126... | ||
96 | r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); |
126 | r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); |
97 | r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); |
127 | r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); |
98 | 128 | ||
99 | return res; |
129 | return res; |
100 | } |
130 | } |
101 | 131 | ||
102 | /* |
132 | /* |
103 | * update the N and CTS parameters for a given pixel clock rate |
133 | * update the N and CTS parameters for a given pixel clock rate |
104 | */ |
134 | */ |
105 | static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) |
135 | void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) |
106 | { |
136 | { |
Line -... | Line 137... | ||
- | 137 | struct drm_device *dev = encoder->dev; |
|
107 | struct drm_device *dev = encoder->dev; |
138 | struct radeon_device *rdev = dev->dev_private; |
- | 139 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); |
|
108 | struct radeon_device *rdev = dev->dev_private; |
140 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
- | 141 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
|
- | 142 | uint32_t offset = dig->afmt->offset; |
|
109 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); |
143 | |
- | 144 | WREG32_P(HDMI0_ACR_32_0 + offset, |
|
110 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
145 | HDMI0_ACR_CTS_32(acr.cts_32khz), |
- | 146 | ~HDMI0_ACR_CTS_32_MASK); |
|
111 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
147 | WREG32_P(HDMI0_ACR_32_1 + offset, |
- | 148 | HDMI0_ACR_N_32(acr.n_32khz), |
|
- | 149 | ~HDMI0_ACR_N_32_MASK); |
|
112 | uint32_t offset = dig->afmt->offset; |
150 | |
- | 151 | WREG32_P(HDMI0_ACR_44_0 + offset, |
|
113 | 152 | HDMI0_ACR_CTS_44(acr.cts_44_1khz), |
|
- | 153 | ~HDMI0_ACR_CTS_44_MASK); |
|
114 | WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz)); |
154 | WREG32_P(HDMI0_ACR_44_1 + offset, |
- | 155 | HDMI0_ACR_N_44(acr.n_44_1khz), |
|
- | 156 | ~HDMI0_ACR_N_44_MASK); |
|
115 | WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz); |
157 | |
Line 116... | Line 158... | ||
116 | 158 | WREG32_P(HDMI0_ACR_48_0 + offset, |
|
117 | WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz)); |
159 | HDMI0_ACR_CTS_48(acr.cts_48khz), |
118 | WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz); |
160 | ~HDMI0_ACR_CTS_48_MASK); |
119 | 161 | WREG32_P(HDMI0_ACR_48_1 + offset, |
|
120 | WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz)); |
162 | HDMI0_ACR_N_48(acr.n_48khz), |
121 | WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz); |
163 | ~HDMI0_ACR_N_48_MASK); |
122 | } |
164 | } |
123 | 165 | ||
124 | /* |
166 | /* |
125 | * build a HDMI Video Info Frame |
167 | * build a HDMI Video Info Frame |
126 | */ |
168 | */ |
127 | static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, |
169 | void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, |
128 | void *buffer, size_t size) |
- | |
129 | { |
- | |
130 | struct drm_device *dev = encoder->dev; |
- | |
131 | struct radeon_device *rdev = dev->dev_private; |
- | |
132 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
- | |
133 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
- | |
134 | uint32_t offset = dig->afmt->offset; |
170 | size_t size) |
135 | uint8_t *frame = buffer + 3; |
- | |
Line 136... | Line 171... | ||
136 | 171 | { |
|
137 | /* Our header values (type, version, length) should be alright, Intel |
172 | struct drm_device *dev = encoder->dev; |
138 | * is using the same. Checksum function also seems to be OK, it works |
173 | struct radeon_device *rdev = dev->dev_private; |
139 | * fine for audio infoframe. However calculated value is always lower |
174 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
140 | * by 2 in comparison to fglrx. It breaks displaying anything in case |
175 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
141 | * of TVs that strictly check the checksum. Hack it manually here to |
176 | uint32_t offset = dig->afmt->offset; |
142 | * workaround this issue. */ |
177 | uint8_t *frame = buffer + 3; |
143 | frame[0x0] += 2; |
178 | uint8_t *header = buffer; |
144 | 179 | ||
Line 145... | Line 180... | ||
145 | WREG32(HDMI0_AVI_INFO0 + offset, |
180 | WREG32(HDMI0_AVI_INFO0 + offset, |
146 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); |
181 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); |
147 | WREG32(HDMI0_AVI_INFO1 + offset, |
182 | WREG32(HDMI0_AVI_INFO1 + offset, |
Line 205... | Line 240... | ||
205 | } |
240 | } |
Line 206... | Line 241... | ||
206 | 241 | ||
207 | /* |
242 | /* |
208 | * write the audio workaround status to the hardware |
243 | * write the audio workaround status to the hardware |
209 | */ |
244 | */ |
210 | static void r600_hdmi_audio_workaround(struct drm_encoder *encoder) |
245 | void r600_hdmi_audio_workaround(struct drm_encoder *encoder) |
211 | { |
246 | { |
212 | struct drm_device *dev = encoder->dev; |
247 | struct drm_device *dev = encoder->dev; |
213 | struct radeon_device *rdev = dev->dev_private; |
248 | struct radeon_device *rdev = dev->dev_private; |
214 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
249 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
Line 231... | Line 266... | ||
231 | struct drm_device *dev = encoder->dev; |
266 | struct drm_device *dev = encoder->dev; |
232 | struct radeon_device *rdev = dev->dev_private; |
267 | struct radeon_device *rdev = dev->dev_private; |
233 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
268 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
234 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
269 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
235 | u32 base_rate = 24000; |
270 | u32 base_rate = 24000; |
- | 271 | u32 max_ratio = clock / base_rate; |
|
- | 272 | u32 dto_phase; |
|
- | 273 | u32 dto_modulo = clock; |
|
- | 274 | u32 wallclock_ratio; |
|
- | 275 | u32 dto_cntl; |
|
Line 236... | Line 276... | ||
236 | 276 | ||
237 | if (!dig || !dig->afmt) |
277 | if (!dig || !dig->afmt) |
Line -... | Line 278... | ||
- | 278 | return; |
|
- | 279 | ||
- | 280 | if (max_ratio >= 8) { |
|
- | 281 | dto_phase = 192 * 1000; |
|
- | 282 | wallclock_ratio = 3; |
|
- | 283 | } else if (max_ratio >= 4) { |
|
- | 284 | dto_phase = 96 * 1000; |
|
- | 285 | wallclock_ratio = 2; |
|
- | 286 | } else if (max_ratio >= 2) { |
|
- | 287 | dto_phase = 48 * 1000; |
|
- | 288 | wallclock_ratio = 1; |
|
- | 289 | } else { |
|
- | 290 | dto_phase = 24 * 1000; |
|
- | 291 | wallclock_ratio = 0; |
|
238 | return; |
292 | } |
239 | 293 | ||
240 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. |
294 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. |
241 | * doesn't matter which one you use. Just use the first one. |
295 | * doesn't matter which one you use. Just use the first one. |
242 | */ |
296 | */ |
243 | /* XXX two dtos; generally use dto0 for hdmi */ |
297 | /* XXX two dtos; generally use dto0 for hdmi */ |
244 | /* Express [24MHz / target pixel clock] as an exact rational |
298 | /* Express [24MHz / target pixel clock] as an exact rational |
245 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
299 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
246 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
300 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
- | 301 | */ |
|
- | 302 | if (ASIC_IS_DCE32(rdev)) { |
|
- | 303 | if (dig->dig_encoder == 0) { |
|
- | 304 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
|
- | 305 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); |
|
- | 306 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); |
|
- | 307 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); |
|
- | 308 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); |
|
- | 309 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
|
- | 310 | } else { |
|
- | 311 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
|
- | 312 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); |
|
- | 313 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); |
|
- | 314 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); |
|
- | 315 | WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); |
|
- | 316 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
|
247 | */ |
317 | } |
248 | if (ASIC_IS_DCE3(rdev)) { |
318 | } else { |
249 | /* according to the reg specs, this should DCE3.2 only, but in |
319 | /* according to the reg specs, this should DCE3.2 only, but in |
- | 320 | * practice it seems to cover DCE2.0/3.0/3.1 as well. |
|
250 | * practice it seems to cover DCE3.0 as well. |
321 | */ |
251 | */ |
322 | if (dig->dig_encoder == 0) { |
252 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); |
323 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); |
253 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
324 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
254 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
- | |
255 | } else { |
325 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
256 | /* according to the reg specs, this should be DCE2.0 and DCE3.0 */ |
326 | } else { |
- | 327 | WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100); |
|
- | 328 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); |
|
257 | WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) | |
329 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
258 | AUDIO_DTO_MODULE(clock / 10)); |
330 | } |
Line 259... | Line 331... | ||
259 | } |
331 | } |
260 | } |
332 | } |
Line 269... | Line 341... | ||
269 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
341 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
270 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
342 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
271 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
343 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
272 | struct hdmi_avi_infoframe frame; |
344 | struct hdmi_avi_infoframe frame; |
273 | uint32_t offset; |
345 | uint32_t offset; |
- | 346 | uint32_t acr_ctl; |
|
274 | ssize_t err; |
347 | ssize_t err; |
Line -... | Line 348... | ||
- | 348 | ||
- | 349 | if (!dig || !dig->afmt) |
|
- | 350 | return; |
|
275 | 351 | ||
276 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
352 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
277 | if (!dig->afmt->enabled) |
353 | if (!dig->afmt->enabled) |
278 | return; |
354 | return; |
Line -... | Line 355... | ||
- | 355 | offset = dig->afmt->offset; |
|
- | 356 | ||
279 | offset = dig->afmt->offset; |
357 | /* disable audio prior to setting up hw */ |
Line 280... | Line 358... | ||
280 | 358 | dig->afmt->pin = r600_audio_get_pin(rdev); |
|
281 | // r600_audio_set_clock(encoder, mode->clock); |
- | |
Line 282... | Line -... | ||
282 | - | ||
283 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, |
- | |
284 | HDMI0_NULL_SEND); /* send null packets when required */ |
- | |
285 | 359 | r600_audio_enable(rdev, dig->afmt->pin, false); |
|
286 | WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); |
- | |
287 | - | ||
288 | if (ASIC_IS_DCE32(rdev)) { |
- | |
289 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, |
- | |
290 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ |
- | |
291 | HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ |
- | |
292 | WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, |
- | |
293 | AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ |
360 | |
294 | AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ |
361 | r600_audio_set_dto(encoder, mode->clock); |
295 | } else { |
362 | |
296 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, |
363 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, |
- | 364 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ |
|
- | 365 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ |
|
- | 366 | HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ |
|
- | 367 | HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */ |
|
297 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ |
368 | ~(HDMI0_AUDIO_SAMPLE_SEND | |
- | 369 | HDMI0_AUDIO_DELAY_EN_MASK | |
|
- | 370 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | |
|
- | 371 | HDMI0_60958_CS_UPDATE)); |
|
- | 372 | ||
- | 373 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ |
|
- | 374 | acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : |
|
- | 375 | HDMI0_ACR_PACKET_CONTROL; |
|
- | 376 | WREG32_P(acr_ctl + offset, |
|
Line 298... | Line -... | ||
298 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ |
- | |
299 | HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ |
- | |
300 | HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ |
- | |
301 | } |
- | |
302 | 377 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ |
|
303 | WREG32(HDMI0_ACR_PACKET_CONTROL + offset, |
378 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ |
304 | HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ |
379 | ~(HDMI0_ACR_SOURCE | |
305 | HDMI0_ACR_SOURCE); /* select SW CTS value */ |
380 | HDMI0_ACR_AUTO_SEND)); |
Line 306... | Line -... | ||
306 | - | ||
307 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, |
381 | |
308 | HDMI0_NULL_SEND | /* send null packets when required */ |
382 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, |
309 | HDMI0_GC_SEND | /* send general control packets */ |
383 | HDMI0_NULL_SEND | /* send null packets when required */ |
310 | HDMI0_GC_CONT); /* send general control packets every frame */ |
384 | HDMI0_GC_SEND | /* send general control packets */ |
311 | 385 | HDMI0_GC_CONT); /* send general control packets every frame */ |
|
Line 312... | Line 386... | ||
312 | /* TODO: HDMI0_AUDIO_INFO_UPDATE */ |
386 | |
313 | WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, |
387 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
314 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ |
388 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ |
- | 389 | HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ |
|
- | 390 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
|
Line -... | Line 391... | ||
- | 391 | HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ |
|
315 | HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ |
392 | |
Line 316... | Line 393... | ||
316 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
393 | WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, |
317 | HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ |
394 | HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ |
318 | 395 | HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ |
|
319 | WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, |
396 | ~(HDMI0_AVI_INFO_LINE_MASK | |
Line 333... | Line 410... | ||
333 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); |
410 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); |
334 | return; |
411 | return; |
335 | } |
412 | } |
Line 336... | Line 413... | ||
336 | 413 | ||
- | 414 | r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); |
|
- | 415 | ||
- | 416 | /* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */ |
|
- | 417 | ||
- | 418 | WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, |
|
- | 419 | ~(HDMI0_GENERIC0_SEND | |
|
- | 420 | HDMI0_GENERIC0_CONT | |
|
- | 421 | HDMI0_GENERIC0_UPDATE | |
|
- | 422 | HDMI0_GENERIC1_SEND | |
|
- | 423 | HDMI0_GENERIC1_CONT | |
|
- | 424 | HDMI0_GENERIC0_LINE_MASK | |
|
- | 425 | HDMI0_GENERIC1_LINE_MASK)); |
|
337 | r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); |
426 | |
Line -... | Line 427... | ||
- | 427 | r600_hdmi_update_ACR(encoder, mode->clock); |
|
- | 428 | ||
- | 429 | WREG32_P(HDMI0_60958_0 + offset, |
|
- | 430 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), |
|
- | 431 | ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | |
|
- | 432 | HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); |
|
- | 433 | ||
- | 434 | WREG32_P(HDMI0_60958_1 + offset, |
|
- | 435 | HDMI0_60958_CS_CHANNEL_NUMBER_R(2), |
|
338 | r600_hdmi_update_ACR(encoder, mode->clock); |
436 | ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); |
339 | 437 | ||
340 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ |
438 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ |
341 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); |
439 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); |
342 | WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); |
440 | WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); |
Line -... | Line 441... | ||
- | 441 | WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); |
|
343 | WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); |
442 | WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); |
344 | WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); |
443 | |
Line -... | Line 444... | ||
- | 444 | /* enable audio after to setting up hw */ |
|
- | 445 | r600_audio_enable(rdev, dig->afmt->pin, true); |
|
345 | 446 | } |
|
- | 447 | ||
346 | r600_hdmi_audio_workaround(encoder); |
448 | /** |
347 | } |
449 | * r600_hdmi_update_audio_settings - Update audio infoframe |
348 | 450 | * |
|
349 | #if 0 |
451 | * @encoder: drm encoder |
350 | /* |
452 | * |
351 | * update settings with current parameters from audio engine |
453 | * Gets info about current audio stream and updates audio infoframe. |
352 | */ |
454 | */ |
353 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) |
455 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) |
354 | { |
456 | { |
355 | struct drm_device *dev = encoder->dev; |
457 | struct drm_device *dev = encoder->dev; |
356 | struct radeon_device *rdev = dev->dev_private; |
458 | struct radeon_device *rdev = dev->dev_private; |
357 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
459 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
358 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
460 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
359 | struct r600_audio audio = r600_audio_status(rdev); |
461 | struct r600_audio_pin audio = r600_audio_status(rdev); |
360 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
462 | uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
Line 361... | Line 463... | ||
361 | struct hdmi_audio_infoframe frame; |
463 | struct hdmi_audio_infoframe frame; |
362 | uint32_t offset; |
464 | uint32_t offset; |
363 | uint32_t iec; |
465 | uint32_t value; |
Line 371... | Line 473... | ||
371 | r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped", |
473 | r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped", |
372 | audio.channels, audio.rate, audio.bits_per_sample); |
474 | audio.channels, audio.rate, audio.bits_per_sample); |
373 | DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n", |
475 | DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n", |
374 | (int)audio.status_bits, (int)audio.category_code); |
476 | (int)audio.status_bits, (int)audio.category_code); |
Line 375... | Line -... | ||
375 | - | ||
376 | iec = 0; |
- | |
377 | if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL) |
- | |
378 | iec |= 1 << 0; |
- | |
379 | if (audio.status_bits & AUDIO_STATUS_NONAUDIO) |
- | |
380 | iec |= 1 << 1; |
- | |
381 | if (audio.status_bits & AUDIO_STATUS_COPYRIGHT) |
- | |
382 | iec |= 1 << 2; |
- | |
383 | if (audio.status_bits & AUDIO_STATUS_EMPHASIS) |
- | |
384 | iec |= 1 << 3; |
- | |
385 | - | ||
386 | iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code); |
- | |
387 | - | ||
388 | switch (audio.rate) { |
- | |
389 | case 32000: |
- | |
390 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3); |
- | |
391 | break; |
- | |
392 | case 44100: |
- | |
393 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0); |
- | |
394 | break; |
- | |
395 | case 48000: |
- | |
396 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2); |
- | |
397 | break; |
- | |
398 | case 88200: |
- | |
399 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8); |
- | |
400 | break; |
- | |
401 | case 96000: |
- | |
402 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa); |
- | |
403 | break; |
- | |
404 | case 176400: |
- | |
405 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc); |
- | |
406 | break; |
- | |
407 | case 192000: |
- | |
408 | iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe); |
- | |
409 | break; |
- | |
410 | } |
- | |
411 | - | ||
412 | WREG32(HDMI0_60958_0 + offset, iec); |
- | |
413 | - | ||
414 | iec = 0; |
- | |
415 | switch (audio.bits_per_sample) { |
- | |
416 | case 16: |
- | |
417 | iec |= HDMI0_60958_CS_WORD_LENGTH(0x2); |
- | |
418 | break; |
- | |
419 | case 20: |
- | |
420 | iec |= HDMI0_60958_CS_WORD_LENGTH(0x3); |
- | |
421 | break; |
- | |
422 | case 24: |
- | |
423 | iec |= HDMI0_60958_CS_WORD_LENGTH(0xb); |
- | |
424 | break; |
- | |
425 | } |
- | |
426 | if (audio.status_bits & AUDIO_STATUS_V) |
- | |
427 | iec |= 0x5 << 16; |
- | |
428 | WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f); |
- | |
429 | 477 | ||
430 | err = hdmi_audio_infoframe_init(&frame); |
478 | err = hdmi_audio_infoframe_init(&frame); |
431 | if (err < 0) { |
479 | if (err < 0) { |
432 | DRM_ERROR("failed to setup audio infoframe\n"); |
480 | DRM_ERROR("failed to setup audio infoframe\n"); |
433 | return; |
481 | return; |
Line 439... | Line 487... | ||
439 | if (err < 0) { |
487 | if (err < 0) { |
440 | DRM_ERROR("failed to pack audio infoframe\n"); |
488 | DRM_ERROR("failed to pack audio infoframe\n"); |
441 | return; |
489 | return; |
442 | } |
490 | } |
Line -... | Line 491... | ||
- | 491 | ||
- | 492 | value = RREG32(HDMI0_AUDIO_PACKET_CONTROL + offset); |
|
- | 493 | if (value & HDMI0_AUDIO_TEST_EN) |
|
- | 494 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, |
|
- | 495 | value & ~HDMI0_AUDIO_TEST_EN); |
|
- | 496 | ||
- | 497 | WREG32_OR(HDMI0_CONTROL + offset, |
|
- | 498 | HDMI0_ERROR_ACK); |
|
- | 499 | ||
- | 500 | WREG32_AND(HDMI0_INFOFRAME_CONTROL0 + offset, |
|
- | 501 | ~HDMI0_AUDIO_INFO_SOURCE); |
|
443 | 502 | ||
- | 503 | r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer)); |
|
- | 504 | ||
- | 505 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
|
444 | r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer)); |
506 | HDMI0_AUDIO_INFO_CONT | |
445 | r600_hdmi_audio_workaround(encoder); |
507 | HDMI0_AUDIO_INFO_UPDATE); |
446 | } |
- | |
Line 447... | Line 508... | ||
447 | #endif |
508 | } |
448 | 509 | ||
449 | /* |
510 | /* |
450 | * enable the HDMI engine |
511 | * enable the HDMI engine |
Line 455... | Line 516... | ||
455 | struct radeon_device *rdev = dev->dev_private; |
516 | struct radeon_device *rdev = dev->dev_private; |
456 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
517 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
457 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
518 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
458 | u32 hdmi = HDMI0_ERROR_ACK; |
519 | u32 hdmi = HDMI0_ERROR_ACK; |
Line -... | Line 520... | ||
- | 520 | ||
- | 521 | if (!dig || !dig->afmt) |
|
- | 522 | return; |
|
459 | 523 | ||
460 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
524 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
461 | if (enable && dig->afmt->enabled) |
525 | if (enable && dig->afmt->enabled) |
462 | return; |
526 | return; |
463 | if (!enable && !dig->afmt->enabled) |
527 | if (!enable && !dig->afmt->enabled) |