1e55d3e6cSRafał Miłecki /* 2e55d3e6cSRafał Miłecki * Copyright 2008 Advanced Micro Devices, Inc. 3e55d3e6cSRafał Miłecki * Copyright 2008 Red Hat Inc. 4e55d3e6cSRafał Miłecki * Copyright 2009 Christian König. 5e55d3e6cSRafał Miłecki * 6e55d3e6cSRafał Miłecki * Permission is hereby granted, free of charge, to any person obtaining a 7e55d3e6cSRafał Miłecki * copy of this software and associated documentation files (the "Software"), 8e55d3e6cSRafał Miłecki * to deal in the Software without restriction, including without limitation 9e55d3e6cSRafał Miłecki * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10e55d3e6cSRafał Miłecki * and/or sell copies of the Software, and to permit persons to whom the 11e55d3e6cSRafał Miłecki * Software is furnished to do so, subject to the following conditions: 12e55d3e6cSRafał Miłecki * 13e55d3e6cSRafał Miłecki * The above copyright notice and this permission notice shall be included in 14e55d3e6cSRafał Miłecki * all copies or substantial portions of the Software. 15e55d3e6cSRafał Miłecki * 16e55d3e6cSRafał Miłecki * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17e55d3e6cSRafał Miłecki * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18e55d3e6cSRafał Miłecki * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19e55d3e6cSRafał Miłecki * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20e55d3e6cSRafał Miłecki * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21e55d3e6cSRafał Miłecki * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22e55d3e6cSRafał Miłecki * OTHER DEALINGS IN THE SOFTWARE. 23e55d3e6cSRafał Miłecki * 24e55d3e6cSRafał Miłecki * Authors: Christian König 25e55d3e6cSRafał Miłecki * Rafał Miłecki 26e55d3e6cSRafał Miłecki */ 27e3b2e034SThierry Reding #include <linux/hdmi.h> 28760285e7SDavid Howells #include <drm/drmP.h> 29760285e7SDavid Howells #include <drm/radeon_drm.h> 30e55d3e6cSRafał Miłecki #include "radeon.h" 31e55d3e6cSRafał Miłecki #include "radeon_asic.h" 32070a2e63SAlex Deucher #include "radeon_audio.h" 33e55d3e6cSRafał Miłecki #include "evergreend.h" 34e55d3e6cSRafał Miłecki #include "atom.h" 35e55d3e6cSRafał Miłecki 36d3d8c141SAlex Deucher /* enable the audio stream */ 378bf59820SSlava Grigorev void dce4_audio_enable(struct radeon_device *rdev, 38d3d8c141SAlex Deucher struct r600_audio_pin *pin, 39d3d8c141SAlex Deucher u8 enable_mask) 40d3d8c141SAlex Deucher { 41d3d8c141SAlex Deucher u32 tmp = RREG32(AZ_HOT_PLUG_CONTROL); 42d3d8c141SAlex Deucher 43d3d8c141SAlex Deucher if (!pin) 44d3d8c141SAlex Deucher return; 45d3d8c141SAlex Deucher 46d3d8c141SAlex Deucher if (enable_mask) { 47d3d8c141SAlex Deucher tmp |= AUDIO_ENABLED; 48d3d8c141SAlex Deucher if (enable_mask & 1) 49d3d8c141SAlex Deucher tmp |= PIN0_AUDIO_ENABLED; 50d3d8c141SAlex Deucher if (enable_mask & 2) 51d3d8c141SAlex Deucher tmp |= PIN1_AUDIO_ENABLED; 52d3d8c141SAlex Deucher if (enable_mask & 4) 53d3d8c141SAlex Deucher tmp |= PIN2_AUDIO_ENABLED; 54d3d8c141SAlex Deucher if (enable_mask & 8) 55d3d8c141SAlex Deucher tmp |= PIN3_AUDIO_ENABLED; 56d3d8c141SAlex Deucher } else { 57d3d8c141SAlex Deucher tmp &= ~(AUDIO_ENABLED | 58d3d8c141SAlex Deucher PIN0_AUDIO_ENABLED | 59d3d8c141SAlex Deucher PIN1_AUDIO_ENABLED | 60d3d8c141SAlex Deucher PIN2_AUDIO_ENABLED | 61d3d8c141SAlex Deucher PIN3_AUDIO_ENABLED); 62d3d8c141SAlex Deucher } 63d3d8c141SAlex Deucher 64d3d8c141SAlex Deucher WREG32(AZ_HOT_PLUG_CONTROL, tmp); 65d3d8c141SAlex Deucher } 66d3d8c141SAlex Deucher 6764424d6eSSlava Grigorev void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset, 6864424d6eSSlava Grigorev const struct radeon_hdmi_acr *acr) 69e55d3e6cSRafał Miłecki { 70e55d3e6cSRafał Miłecki struct drm_device *dev = encoder->dev; 71e55d3e6cSRafał Miłecki struct radeon_device *rdev = dev->dev_private; 7264424d6eSSlava Grigorev int bpc = 8; 73e55d3e6cSRafał Miłecki 7464424d6eSSlava Grigorev if (encoder->crtc) { 7564424d6eSSlava Grigorev struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 7664424d6eSSlava Grigorev bpc = radeon_crtc->bpc; 7764424d6eSSlava Grigorev } 78e55d3e6cSRafał Miłecki 7964424d6eSSlava Grigorev if (bpc > 8) 8064424d6eSSlava Grigorev WREG32(HDMI_ACR_PACKET_CONTROL + offset, 8164424d6eSSlava Grigorev HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ 8264424d6eSSlava Grigorev else 8364424d6eSSlava Grigorev WREG32(HDMI_ACR_PACKET_CONTROL + offset, 8464424d6eSSlava Grigorev HDMI_ACR_SOURCE | /* select SW CTS value */ 8564424d6eSSlava Grigorev HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ 86e55d3e6cSRafał Miłecki 8764424d6eSSlava Grigorev WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr->cts_32khz)); 8864424d6eSSlava Grigorev WREG32(HDMI_ACR_32_1 + offset, acr->n_32khz); 8964424d6eSSlava Grigorev 9064424d6eSSlava Grigorev WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr->cts_44_1khz)); 9164424d6eSSlava Grigorev WREG32(HDMI_ACR_44_1 + offset, acr->n_44_1khz); 9264424d6eSSlava Grigorev 9364424d6eSSlava Grigorev WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr->cts_48khz)); 9464424d6eSSlava Grigorev WREG32(HDMI_ACR_48_1 + offset, acr->n_48khz); 95e55d3e6cSRafał Miłecki } 96e55d3e6cSRafał Miłecki 9787654f87SSlava Grigorev void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, 9887654f87SSlava Grigorev struct drm_connector *connector, struct drm_display_mode *mode) 99712fd8a2SAlex Deucher { 100712fd8a2SAlex Deucher struct radeon_device *rdev = encoder->dev->dev_private; 101712fd8a2SAlex Deucher u32 tmp = 0; 102712fd8a2SAlex Deucher 103712fd8a2SAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 104712fd8a2SAlex Deucher if (connector->latency_present[1]) 105712fd8a2SAlex Deucher tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | 106712fd8a2SAlex Deucher AUDIO_LIPSYNC(connector->audio_latency[1]); 107712fd8a2SAlex Deucher else 108712fd8a2SAlex Deucher tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255); 109712fd8a2SAlex Deucher } else { 110712fd8a2SAlex Deucher if (connector->latency_present[0]) 111712fd8a2SAlex Deucher tmp = VIDEO_LIPSYNC(connector->video_latency[0]) | 112712fd8a2SAlex Deucher AUDIO_LIPSYNC(connector->audio_latency[0]); 113712fd8a2SAlex Deucher else 114712fd8a2SAlex Deucher tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255); 115712fd8a2SAlex Deucher } 11687654f87SSlava Grigorev WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp); 117712fd8a2SAlex Deucher } 118712fd8a2SAlex Deucher 11900a9d4bcSSlava Grigorev void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, 12000a9d4bcSSlava Grigorev u8 *sadb, int sad_count) 121ba7def4fSAlex Deucher { 122ba7def4fSAlex Deucher struct radeon_device *rdev = encoder->dev->dev_private; 123ba7def4fSAlex Deucher u32 tmp; 124ba7def4fSAlex Deucher 125ba7def4fSAlex Deucher /* program the speaker allocation */ 12600a9d4bcSSlava Grigorev tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); 127ba7def4fSAlex Deucher tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); 128ba7def4fSAlex Deucher /* set HDMI mode */ 129ba7def4fSAlex Deucher tmp |= HDMI_CONNECTION; 130ba7def4fSAlex Deucher if (sad_count) 131ba7def4fSAlex Deucher tmp |= SPEAKER_ALLOCATION(sadb[0]); 132ba7def4fSAlex Deucher else 133ba7def4fSAlex Deucher tmp |= SPEAKER_ALLOCATION(5); /* stereo */ 13400a9d4bcSSlava Grigorev WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); 13500a9d4bcSSlava Grigorev } 136ba7def4fSAlex Deucher 13700a9d4bcSSlava Grigorev void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, 13800a9d4bcSSlava Grigorev u8 *sadb, int sad_count) 13900a9d4bcSSlava Grigorev { 14000a9d4bcSSlava Grigorev struct radeon_device *rdev = encoder->dev->dev_private; 14100a9d4bcSSlava Grigorev u32 tmp; 14200a9d4bcSSlava Grigorev 14300a9d4bcSSlava Grigorev /* program the speaker allocation */ 14400a9d4bcSSlava Grigorev tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); 14500a9d4bcSSlava Grigorev tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); 14600a9d4bcSSlava Grigorev /* set DP mode */ 14700a9d4bcSSlava Grigorev tmp |= DP_CONNECTION; 14800a9d4bcSSlava Grigorev if (sad_count) 14900a9d4bcSSlava Grigorev tmp |= SPEAKER_ALLOCATION(sadb[0]); 15000a9d4bcSSlava Grigorev else 15100a9d4bcSSlava Grigorev tmp |= SPEAKER_ALLOCATION(5); /* stereo */ 15200a9d4bcSSlava Grigorev WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); 153ba7def4fSAlex Deucher } 154ba7def4fSAlex Deucher 155070a2e63SAlex Deucher void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder, 156070a2e63SAlex Deucher struct cea_sad *sads, int sad_count) 15746892caaSRafał Miłecki { 158070a2e63SAlex Deucher int i; 15946892caaSRafał Miłecki struct radeon_device *rdev = encoder->dev->dev_private; 16046892caaSRafał Miłecki static const u16 eld_reg_to_type[][2] = { 16146892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, 16246892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, 16346892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 }, 16446892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 }, 16546892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 }, 16646892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC }, 16746892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS }, 16846892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC }, 16946892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 }, 17046892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD }, 17146892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP }, 17246892caaSRafał Miłecki { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, 17346892caaSRafał Miłecki }; 17446892caaSRafał Miłecki 17546892caaSRafał Miłecki for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { 17646892caaSRafał Miłecki u32 value = 0; 1770f57bca9SAnssi Hannula u8 stereo_freqs = 0; 1780f57bca9SAnssi Hannula int max_channels = -1; 17946892caaSRafał Miłecki int j; 18046892caaSRafał Miłecki 18146892caaSRafał Miłecki for (j = 0; j < sad_count; j++) { 18246892caaSRafał Miłecki struct cea_sad *sad = &sads[j]; 18346892caaSRafał Miłecki 18446892caaSRafał Miłecki if (sad->format == eld_reg_to_type[i][1]) { 1850f57bca9SAnssi Hannula if (sad->channels > max_channels) { 18646892caaSRafał Miłecki value = MAX_CHANNELS(sad->channels) | 18746892caaSRafał Miłecki DESCRIPTOR_BYTE_2(sad->byte2) | 18846892caaSRafał Miłecki SUPPORTED_FREQUENCIES(sad->freq); 1890f57bca9SAnssi Hannula max_channels = sad->channels; 1900f57bca9SAnssi Hannula } 1910f57bca9SAnssi Hannula 19246892caaSRafał Miłecki if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) 1930f57bca9SAnssi Hannula stereo_freqs |= sad->freq; 1940f57bca9SAnssi Hannula else 19546892caaSRafał Miłecki break; 19646892caaSRafał Miłecki } 19746892caaSRafał Miłecki } 1980f57bca9SAnssi Hannula 1990f57bca9SAnssi Hannula value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); 2000f57bca9SAnssi Hannula 201070a2e63SAlex Deucher WREG32_ENDPOINT(0, eld_reg_to_type[i][0], value); 20246892caaSRafał Miłecki } 20346892caaSRafał Miłecki } 20446892caaSRafał Miłecki 205e55d3e6cSRafał Miłecki /* 20696ea7afbSSlava Grigorev * build a AVI Info Frame 207e55d3e6cSRafał Miłecki */ 208baa7d8e4SSlava Grigorev void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset, 20996ea7afbSSlava Grigorev unsigned char *buffer, size_t size) 210e55d3e6cSRafał Miłecki { 211e3b2e034SThierry Reding uint8_t *frame = buffer + 3; 212e55d3e6cSRafał Miłecki 213e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO0 + offset, 214e55d3e6cSRafał Miłecki frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); 215e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO1 + offset, 216e55d3e6cSRafał Miłecki frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); 217e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO2 + offset, 218e55d3e6cSRafał Miłecki frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); 219e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO3 + offset, 22096ea7afbSSlava Grigorev frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24)); 221baa7d8e4SSlava Grigorev 222baa7d8e4SSlava Grigorev WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset, 223baa7d8e4SSlava Grigorev HDMI_AVI_INFO_SEND | /* enable AVI info frames */ 224baa7d8e4SSlava Grigorev HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */ 225baa7d8e4SSlava Grigorev 226baa7d8e4SSlava Grigorev WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset, 227baa7d8e4SSlava Grigorev HDMI_AVI_INFO_LINE(2), /* anything other than 0 */ 228baa7d8e4SSlava Grigorev ~HDMI_AVI_INFO_LINE_MASK); 229e55d3e6cSRafał Miłecki } 230e55d3e6cSRafał Miłecki 231a85d682aSSlava Grigorev void dce4_hdmi_audio_set_dto(struct radeon_device *rdev, 232a85d682aSSlava Grigorev struct radeon_crtc *crtc, unsigned int clock) 233b1f6f47eSAlex Deucher { 234a85d682aSSlava Grigorev unsigned int max_ratio = clock / 24000; 2351518dd8eSAlex Deucher u32 dto_phase; 2361518dd8eSAlex Deucher u32 wallclock_ratio; 237a85d682aSSlava Grigorev u32 value; 238b1f6f47eSAlex Deucher 2391518dd8eSAlex Deucher if (max_ratio >= 8) { 2401518dd8eSAlex Deucher dto_phase = 192 * 1000; 2411518dd8eSAlex Deucher wallclock_ratio = 3; 2421518dd8eSAlex Deucher } else if (max_ratio >= 4) { 2431518dd8eSAlex Deucher dto_phase = 96 * 1000; 2441518dd8eSAlex Deucher wallclock_ratio = 2; 2451518dd8eSAlex Deucher } else if (max_ratio >= 2) { 2461518dd8eSAlex Deucher dto_phase = 48 * 1000; 2471518dd8eSAlex Deucher wallclock_ratio = 1; 2481518dd8eSAlex Deucher } else { 2491518dd8eSAlex Deucher dto_phase = 24 * 1000; 2501518dd8eSAlex Deucher wallclock_ratio = 0; 2511518dd8eSAlex Deucher } 2521518dd8eSAlex Deucher 253a85d682aSSlava Grigorev value = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; 254a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); 255a85d682aSSlava Grigorev value &= ~DCCG_AUDIO_DTO1_USE_512FBR_DTO; 256a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO0_CNTL, value); 257a85d682aSSlava Grigorev 258a85d682aSSlava Grigorev /* Two dtos; generally use dto0 for HDMI */ 259a85d682aSSlava Grigorev value = 0; 260a85d682aSSlava Grigorev 261a85d682aSSlava Grigorev if (crtc) 262a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); 263a85d682aSSlava Grigorev 264a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO_SOURCE, value); 265a85d682aSSlava Grigorev 266b1f6f47eSAlex Deucher /* Express [24MHz / target pixel clock] as an exact rational 267b1f6f47eSAlex Deucher * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE 268b1f6f47eSAlex Deucher * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator 269b1f6f47eSAlex Deucher */ 2701518dd8eSAlex Deucher WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); 271a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO0_MODULE, clock); 272b1f6f47eSAlex Deucher } 273b1f6f47eSAlex Deucher 274a85d682aSSlava Grigorev void dce4_dp_audio_set_dto(struct radeon_device *rdev, 275a85d682aSSlava Grigorev struct radeon_crtc *crtc, unsigned int clock) 276a85d682aSSlava Grigorev { 277a85d682aSSlava Grigorev u32 value; 278a85d682aSSlava Grigorev 279a85d682aSSlava Grigorev value = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; 280a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO1_USE_512FBR_DTO; 281a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO1_CNTL, value); 282a85d682aSSlava Grigorev 283a85d682aSSlava Grigorev /* Two dtos; generally use dto1 for DP */ 284a85d682aSSlava Grigorev value = 0; 285a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO_SEL; 286a85d682aSSlava Grigorev 287a85d682aSSlava Grigorev if (crtc) 288a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); 289a85d682aSSlava Grigorev 290a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO_SOURCE, value); 291a85d682aSSlava Grigorev 292a85d682aSSlava Grigorev /* Express [24MHz / target pixel clock] as an exact rational 293a85d682aSSlava Grigorev * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE 294a85d682aSSlava Grigorev * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator 295a85d682aSSlava Grigorev */ 296a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); 297a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10); 298a85d682aSSlava Grigorev } 299b1f6f47eSAlex Deucher 300930a9785SAlex Deucher void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset) 301930a9785SAlex Deucher { 302930a9785SAlex Deucher struct drm_device *dev = encoder->dev; 303930a9785SAlex Deucher struct radeon_device *rdev = dev->dev_private; 304930a9785SAlex Deucher 305930a9785SAlex Deucher WREG32(HDMI_VBI_PACKET_CONTROL + offset, 306930a9785SAlex Deucher HDMI_NULL_SEND | /* send null packets when required */ 307930a9785SAlex Deucher HDMI_GC_SEND | /* send general control packets */ 308930a9785SAlex Deucher HDMI_GC_CONT); /* send general control packets every frame */ 309930a9785SAlex Deucher } 310930a9785SAlex Deucher 311be273e58SSlava Grigorev void dce4_hdmi_set_color_depth(struct drm_encoder *encoder, u32 offset, int bpc) 312e55d3e6cSRafał Miłecki { 313e55d3e6cSRafał Miłecki struct drm_device *dev = encoder->dev; 314e55d3e6cSRafał Miłecki struct radeon_device *rdev = dev->dev_private; 31579766915SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 3167b555e06SAlex Deucher uint32_t val; 317e55d3e6cSRafał Miłecki 3187b555e06SAlex Deucher val = RREG32(HDMI_CONTROL + offset); 3197b555e06SAlex Deucher val &= ~HDMI_DEEP_COLOR_ENABLE; 3207b555e06SAlex Deucher val &= ~HDMI_DEEP_COLOR_DEPTH_MASK; 3217b555e06SAlex Deucher 3227b555e06SAlex Deucher switch (bpc) { 3237b555e06SAlex Deucher case 0: 3247b555e06SAlex Deucher case 6: 3257b555e06SAlex Deucher case 8: 3267b555e06SAlex Deucher case 16: 3277b555e06SAlex Deucher default: 3287b555e06SAlex Deucher DRM_DEBUG("%s: Disabling hdmi deep color for %d bpc.\n", 32972082093SJani Nikula connector->name, bpc); 3307b555e06SAlex Deucher break; 3317b555e06SAlex Deucher case 10: 3327b555e06SAlex Deucher val |= HDMI_DEEP_COLOR_ENABLE; 3337b555e06SAlex Deucher val |= HDMI_DEEP_COLOR_DEPTH(HDMI_30BIT_DEEP_COLOR); 3347b555e06SAlex Deucher DRM_DEBUG("%s: Enabling hdmi deep color 30 for 10 bpc.\n", 33572082093SJani Nikula connector->name); 3367b555e06SAlex Deucher break; 3377b555e06SAlex Deucher case 12: 3387b555e06SAlex Deucher val |= HDMI_DEEP_COLOR_ENABLE; 3397b555e06SAlex Deucher val |= HDMI_DEEP_COLOR_DEPTH(HDMI_36BIT_DEEP_COLOR); 3407b555e06SAlex Deucher DRM_DEBUG("%s: Enabling hdmi deep color 36 for 12 bpc.\n", 34172082093SJani Nikula connector->name); 3427b555e06SAlex Deucher break; 3437b555e06SAlex Deucher } 3447b555e06SAlex Deucher 3457b555e06SAlex Deucher WREG32(HDMI_CONTROL + offset, val); 346be273e58SSlava Grigorev } 347be273e58SSlava Grigorev 3481852c9a0SSlava Grigorev void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset) 3491852c9a0SSlava Grigorev { 3501852c9a0SSlava Grigorev struct drm_device *dev = encoder->dev; 3511852c9a0SSlava Grigorev struct radeon_device *rdev = dev->dev_private; 3521852c9a0SSlava Grigorev 3531852c9a0SSlava Grigorev WREG32(HDMI_INFOFRAME_CONTROL0 + offset, 3541852c9a0SSlava Grigorev HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ 3551852c9a0SSlava Grigorev HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ 3561852c9a0SSlava Grigorev 3571852c9a0SSlava Grigorev WREG32(AFMT_INFOFRAME_CONTROL0 + offset, 3581852c9a0SSlava Grigorev AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ 3591852c9a0SSlava Grigorev 3601852c9a0SSlava Grigorev WREG32(HDMI_INFOFRAME_CONTROL1 + offset, 3611852c9a0SSlava Grigorev HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ 3621852c9a0SSlava Grigorev 3631852c9a0SSlava Grigorev WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, 3641852c9a0SSlava Grigorev HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ 3651852c9a0SSlava Grigorev HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ 3661852c9a0SSlava Grigorev 3671852c9a0SSlava Grigorev WREG32(AFMT_60958_0 + offset, 3681852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_L(1)); 3691852c9a0SSlava Grigorev 3701852c9a0SSlava Grigorev WREG32(AFMT_60958_1 + offset, 3711852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_R(2)); 3721852c9a0SSlava Grigorev 3731852c9a0SSlava Grigorev WREG32(AFMT_60958_2 + offset, 3741852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_2(3) | 3751852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_3(4) | 3761852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_4(5) | 3771852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_5(6) | 3781852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_6(7) | 3791852c9a0SSlava Grigorev AFMT_60958_CS_CHANNEL_NUMBER_7(8)); 3801852c9a0SSlava Grigorev 3811852c9a0SSlava Grigorev WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset, 3821852c9a0SSlava Grigorev AFMT_AUDIO_CHANNEL_ENABLE(0xff)); 3831852c9a0SSlava Grigorev 3841852c9a0SSlava Grigorev /* allow 60958 channel status and send audio packets fields to be updated */ 3851852c9a0SSlava Grigorev WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, 3861852c9a0SSlava Grigorev AFMT_AUDIO_SAMPLE_SEND | AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE); 3871852c9a0SSlava Grigorev } 3881852c9a0SSlava Grigorev 389*3be2e7d0SSlava Grigorev 390*3be2e7d0SSlava Grigorev void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute) 391*3be2e7d0SSlava Grigorev { 392*3be2e7d0SSlava Grigorev struct drm_device *dev = encoder->dev; 393*3be2e7d0SSlava Grigorev struct radeon_device *rdev = dev->dev_private; 394*3be2e7d0SSlava Grigorev 395*3be2e7d0SSlava Grigorev if (mute) 396*3be2e7d0SSlava Grigorev WREG32_OR(HDMI_GC + offset, HDMI_GC_AVMUTE); 397*3be2e7d0SSlava Grigorev else 398*3be2e7d0SSlava Grigorev WREG32_AND(HDMI_GC + offset, ~HDMI_GC_AVMUTE); 399*3be2e7d0SSlava Grigorev } 400*3be2e7d0SSlava Grigorev 401be273e58SSlava Grigorev /* 402be273e58SSlava Grigorev * update the info frames with the data from the current display mode 403be273e58SSlava Grigorev */ 404be273e58SSlava Grigorev void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) 405be273e58SSlava Grigorev { 406be273e58SSlava Grigorev struct drm_device *dev = encoder->dev; 407be273e58SSlava Grigorev struct radeon_device *rdev = dev->dev_private; 408be273e58SSlava Grigorev struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 409be273e58SSlava Grigorev struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 410be273e58SSlava Grigorev uint32_t offset; 411be273e58SSlava Grigorev 412be273e58SSlava Grigorev if (!dig || !dig->afmt) 413be273e58SSlava Grigorev return; 414be273e58SSlava Grigorev 415be273e58SSlava Grigorev /* Silent, r600_hdmi_enable will raise WARN for us */ 416be273e58SSlava Grigorev if (!dig->afmt->enabled) 417be273e58SSlava Grigorev return; 418be273e58SSlava Grigorev offset = dig->afmt->offset; 419be273e58SSlava Grigorev 420be273e58SSlava Grigorev /* disable audio prior to setting up hw */ 421be273e58SSlava Grigorev dig->afmt->pin = radeon_audio_get_pin(encoder); 422be273e58SSlava Grigorev radeon_audio_enable(rdev, dig->afmt->pin, 0); 423be273e58SSlava Grigorev 424be273e58SSlava Grigorev radeon_audio_set_dto(encoder, mode->clock); 425be273e58SSlava Grigorev radeon_audio_set_vbi_packet(encoder); 426be273e58SSlava Grigorev radeon_hdmi_set_color_depth(encoder); 427*3be2e7d0SSlava Grigorev radeon_audio_set_mute(encoder, false); 42864424d6eSSlava Grigorev radeon_audio_update_acr(encoder, mode->clock); 42900a9d4bcSSlava Grigorev radeon_audio_write_speaker_allocation(encoder); 4301852c9a0SSlava Grigorev radeon_audio_set_audio_packet(encoder); 43188252d77SSlava Grigorev radeon_audio_select_pin(encoder); 432070a2e63SAlex Deucher radeon_audio_write_sad_regs(encoder); 43387654f87SSlava Grigorev radeon_audio_write_latency_fields(encoder, mode); 434070a2e63SAlex Deucher 435baa7d8e4SSlava Grigorev if (radeon_audio_set_avi_packet(encoder, mode) < 0) 436e3b2e034SThierry Reding return; 437d3418eacSRafał Miłecki 438e55d3e6cSRafał Miłecki /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ 439e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF); 440e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); 441e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); 442e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); 443832eafafSAlex Deucher 444832eafafSAlex Deucher /* enable audio after to setting up hw */ 4458bf59820SSlava Grigorev radeon_audio_enable(rdev, dig->afmt->pin, 0xf); 446e55d3e6cSRafał Miłecki } 447a973bea1SAlex Deucher 448a973bea1SAlex Deucher void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) 449a973bea1SAlex Deucher { 4504adb34efSAlex Deucher struct drm_device *dev = encoder->dev; 4514adb34efSAlex Deucher struct radeon_device *rdev = dev->dev_private; 452a973bea1SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 453a973bea1SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 454a973bea1SAlex Deucher 455c2b4cacfSAlex Deucher if (!dig || !dig->afmt) 456c2b4cacfSAlex Deucher return; 457c2b4cacfSAlex Deucher 458a973bea1SAlex Deucher /* Silent, r600_hdmi_enable will raise WARN for us */ 459a973bea1SAlex Deucher if (enable && dig->afmt->enabled) 460a973bea1SAlex Deucher return; 461a973bea1SAlex Deucher if (!enable && !dig->afmt->enabled) 462a973bea1SAlex Deucher return; 463a973bea1SAlex Deucher 4644adb34efSAlex Deucher if (!enable && dig->afmt->pin) { 4658bf59820SSlava Grigorev radeon_audio_enable(rdev, dig->afmt->pin, 0); 4664adb34efSAlex Deucher dig->afmt->pin = NULL; 4674adb34efSAlex Deucher } 4684adb34efSAlex Deucher 469a973bea1SAlex Deucher dig->afmt->enabled = enable; 470a973bea1SAlex Deucher 471a973bea1SAlex Deucher DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", 472a973bea1SAlex Deucher enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id); 473a973bea1SAlex Deucher } 474