1b530602fSAlex Deucher /* 2b530602fSAlex Deucher * Copyright 2013 Advanced Micro Devices, Inc. 3b530602fSAlex Deucher * 4b530602fSAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 5b530602fSAlex Deucher * copy of this software and associated documentation files (the "Software"), 6b530602fSAlex Deucher * to deal in the Software without restriction, including without limitation 7b530602fSAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b530602fSAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the 9b530602fSAlex Deucher * Software is furnished to do so, subject to the following conditions: 10b530602fSAlex Deucher * 11b530602fSAlex Deucher * The above copyright notice and this permission notice shall be included in 12b530602fSAlex Deucher * all copies or substantial portions of the Software. 13b530602fSAlex Deucher * 14b530602fSAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15b530602fSAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16b530602fSAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17b530602fSAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18b530602fSAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19b530602fSAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20b530602fSAlex Deucher * OTHER DEALINGS IN THE SOFTWARE. 21b530602fSAlex Deucher * 22b530602fSAlex Deucher */ 23b530602fSAlex Deucher #include <linux/hdmi.h> 24b530602fSAlex Deucher #include <drm/drmP.h> 25b530602fSAlex Deucher #include "radeon.h" 261a626b68SSlava Grigorev #include "radeon_audio.h" 27b530602fSAlex Deucher #include "sid.h" 28b530602fSAlex Deucher 292afa3265SSlava Grigorev #define DCE8_DCCG_AUDIO_DTO1_PHASE 0x05b8 302afa3265SSlava Grigorev #define DCE8_DCCG_AUDIO_DTO1_MODULE 0x05bc 312afa3265SSlava Grigorev 321a626b68SSlava Grigorev u32 dce6_endpoint_rreg(struct radeon_device *rdev, 33b530602fSAlex Deucher u32 block_offset, u32 reg) 34b530602fSAlex Deucher { 350a5b7b0bSAlex Deucher unsigned long flags; 36b530602fSAlex Deucher u32 r; 37b530602fSAlex Deucher 380a5b7b0bSAlex Deucher spin_lock_irqsave(&rdev->end_idx_lock, flags); 39b530602fSAlex Deucher WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); 40b530602fSAlex Deucher r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset); 410a5b7b0bSAlex Deucher spin_unlock_irqrestore(&rdev->end_idx_lock, flags); 420a5b7b0bSAlex Deucher 43b530602fSAlex Deucher return r; 44b530602fSAlex Deucher } 45b530602fSAlex Deucher 461a626b68SSlava Grigorev void dce6_endpoint_wreg(struct radeon_device *rdev, 47b530602fSAlex Deucher u32 block_offset, u32 reg, u32 v) 48b530602fSAlex Deucher { 490a5b7b0bSAlex Deucher unsigned long flags; 500a5b7b0bSAlex Deucher 510a5b7b0bSAlex Deucher spin_lock_irqsave(&rdev->end_idx_lock, flags); 52b530602fSAlex Deucher if (ASIC_IS_DCE8(rdev)) 53b530602fSAlex Deucher WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); 54b530602fSAlex Deucher else 55b530602fSAlex Deucher WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, 56b530602fSAlex Deucher AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg)); 57b530602fSAlex Deucher WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v); 580a5b7b0bSAlex Deucher spin_unlock_irqrestore(&rdev->end_idx_lock, flags); 59b530602fSAlex Deucher } 60b530602fSAlex Deucher 61b530602fSAlex Deucher static void dce6_afmt_get_connected_pins(struct radeon_device *rdev) 62b530602fSAlex Deucher { 63b530602fSAlex Deucher int i; 64b530602fSAlex Deucher u32 offset, tmp; 65b530602fSAlex Deucher 66b530602fSAlex Deucher for (i = 0; i < rdev->audio.num_pins; i++) { 67b530602fSAlex Deucher offset = rdev->audio.pin[i].offset; 68b530602fSAlex Deucher tmp = RREG32_ENDPOINT(offset, 69b530602fSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); 70b530602fSAlex Deucher if (((tmp & PORT_CONNECTIVITY_MASK) >> PORT_CONNECTIVITY_SHIFT) == 1) 71b530602fSAlex Deucher rdev->audio.pin[i].connected = false; 72b530602fSAlex Deucher else 73b530602fSAlex Deucher rdev->audio.pin[i].connected = true; 74b530602fSAlex Deucher } 75b530602fSAlex Deucher } 76b530602fSAlex Deucher 77b530602fSAlex Deucher struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev) 78b530602fSAlex Deucher { 79d0465208SAlex Deucher struct drm_encoder *encoder; 80d0465208SAlex Deucher struct radeon_encoder *radeon_encoder; 81d0465208SAlex Deucher struct radeon_encoder_atom_dig *dig; 82d0465208SAlex Deucher struct r600_audio_pin *pin = NULL; 83d0465208SAlex Deucher int i, pin_count; 84b530602fSAlex Deucher 85b530602fSAlex Deucher dce6_afmt_get_connected_pins(rdev); 86b530602fSAlex Deucher 87b530602fSAlex Deucher for (i = 0; i < rdev->audio.num_pins; i++) { 88d0465208SAlex Deucher if (rdev->audio.pin[i].connected) { 89d0465208SAlex Deucher pin = &rdev->audio.pin[i]; 90d0465208SAlex Deucher pin_count = 0; 91d0465208SAlex Deucher 92d0465208SAlex Deucher list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) { 93d0465208SAlex Deucher if (radeon_encoder_is_digital(encoder)) { 94d0465208SAlex Deucher radeon_encoder = to_radeon_encoder(encoder); 95d0465208SAlex Deucher dig = radeon_encoder->enc_priv; 96d0465208SAlex Deucher if (dig->pin == pin) 97d0465208SAlex Deucher pin_count++; 98b530602fSAlex Deucher } 99d0465208SAlex Deucher } 100d0465208SAlex Deucher 101d0465208SAlex Deucher if (pin_count == 0) 102d0465208SAlex Deucher return pin; 103d0465208SAlex Deucher } 104d0465208SAlex Deucher } 105d0465208SAlex Deucher if (!pin) 106b530602fSAlex Deucher DRM_ERROR("No connected audio pins found!\n"); 107d0465208SAlex Deucher return pin; 108b530602fSAlex Deucher } 109b530602fSAlex Deucher 110b530602fSAlex Deucher void dce6_afmt_select_pin(struct drm_encoder *encoder) 111b530602fSAlex Deucher { 112b530602fSAlex Deucher struct radeon_device *rdev = encoder->dev->dev_private; 113b530602fSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 114b530602fSAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 115b530602fSAlex Deucher 116d0ea397eSAlex Deucher if (!dig || !dig->afmt || !dig->pin) 117b530602fSAlex Deucher return; 118b530602fSAlex Deucher 119d0ea397eSAlex Deucher WREG32(AFMT_AUDIO_SRC_CONTROL + dig->afmt->offset, 120d0ea397eSAlex Deucher AFMT_AUDIO_SRC_SELECT(dig->pin->id)); 121b530602fSAlex Deucher } 122b530602fSAlex Deucher 123b1880258SAlex Deucher void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, 124d0ea397eSAlex Deucher struct drm_connector *connector, 125d0ea397eSAlex Deucher struct drm_display_mode *mode) 126b1880258SAlex Deucher { 127b1880258SAlex Deucher struct radeon_device *rdev = encoder->dev->dev_private; 128b1880258SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 129b1880258SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 130d0ea397eSAlex Deucher u32 tmp = 0; 131b1880258SAlex Deucher 132d0ea397eSAlex Deucher if (!dig || !dig->afmt || !dig->pin) 133b1880258SAlex Deucher return; 134b1880258SAlex Deucher 135b1880258SAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 136b1880258SAlex Deucher if (connector->latency_present[1]) 137b1880258SAlex Deucher tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | 138b1880258SAlex Deucher AUDIO_LIPSYNC(connector->audio_latency[1]); 139b1880258SAlex Deucher else 140c748990bSStefan Brüns tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0); 141b1880258SAlex Deucher } else { 142b1880258SAlex Deucher if (connector->latency_present[0]) 143b1880258SAlex Deucher tmp = VIDEO_LIPSYNC(connector->video_latency[0]) | 144b1880258SAlex Deucher AUDIO_LIPSYNC(connector->audio_latency[0]); 145b1880258SAlex Deucher else 146c748990bSStefan Brüns tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0); 147b1880258SAlex Deucher } 148d0ea397eSAlex Deucher WREG32_ENDPOINT(dig->pin->offset, 149d0ea397eSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); 150b1880258SAlex Deucher } 151b1880258SAlex Deucher 15200a9d4bcSSlava Grigorev void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, 15300a9d4bcSSlava Grigorev u8 *sadb, int sad_count) 1546159b65aSRafał Miłecki { 1556159b65aSRafał Miłecki struct radeon_device *rdev = encoder->dev->dev_private; 1566159b65aSRafał Miłecki struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1576159b65aSRafał Miłecki struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 158d0ea397eSAlex Deucher u32 tmp; 1596159b65aSRafał Miłecki 160d0ea397eSAlex Deucher if (!dig || !dig->afmt || !dig->pin) 1616159b65aSRafał Miłecki return; 1626159b65aSRafał Miłecki 1636159b65aSRafał Miłecki /* program the speaker allocation */ 164d0ea397eSAlex Deucher tmp = RREG32_ENDPOINT(dig->pin->offset, 165d0ea397eSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); 1666159b65aSRafał Miłecki tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); 1676159b65aSRafał Miłecki /* set HDMI mode */ 1686159b65aSRafał Miłecki tmp |= HDMI_CONNECTION; 1696159b65aSRafał Miłecki if (sad_count) 1706159b65aSRafał Miłecki tmp |= SPEAKER_ALLOCATION(sadb[0]); 1716159b65aSRafał Miłecki else 1726159b65aSRafał Miłecki tmp |= SPEAKER_ALLOCATION(5); /* stereo */ 173d0ea397eSAlex Deucher WREG32_ENDPOINT(dig->pin->offset, 174d0ea397eSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); 17500a9d4bcSSlava Grigorev } 1766159b65aSRafał Miłecki 17700a9d4bcSSlava Grigorev void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, 17800a9d4bcSSlava Grigorev u8 *sadb, int sad_count) 17900a9d4bcSSlava Grigorev { 18000a9d4bcSSlava Grigorev struct radeon_device *rdev = encoder->dev->dev_private; 18100a9d4bcSSlava Grigorev struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 18200a9d4bcSSlava Grigorev struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 183d0ea397eSAlex Deucher u32 tmp; 18400a9d4bcSSlava Grigorev 185d0ea397eSAlex Deucher if (!dig || !dig->afmt || !dig->pin) 18600a9d4bcSSlava Grigorev return; 18700a9d4bcSSlava Grigorev 18800a9d4bcSSlava Grigorev /* program the speaker allocation */ 189d0ea397eSAlex Deucher tmp = RREG32_ENDPOINT(dig->pin->offset, 190d0ea397eSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); 19100a9d4bcSSlava Grigorev tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); 19200a9d4bcSSlava Grigorev /* set DP mode */ 19300a9d4bcSSlava Grigorev tmp |= DP_CONNECTION; 19400a9d4bcSSlava Grigorev if (sad_count) 19500a9d4bcSSlava Grigorev tmp |= SPEAKER_ALLOCATION(sadb[0]); 19600a9d4bcSSlava Grigorev else 19700a9d4bcSSlava Grigorev tmp |= SPEAKER_ALLOCATION(5); /* stereo */ 198d0ea397eSAlex Deucher WREG32_ENDPOINT(dig->pin->offset, 199d0ea397eSAlex Deucher AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); 2006159b65aSRafał Miłecki } 2016159b65aSRafał Miłecki 202070a2e63SAlex Deucher void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, 203070a2e63SAlex Deucher struct cea_sad *sads, int sad_count) 204b530602fSAlex Deucher { 205070a2e63SAlex Deucher int i; 206b530602fSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 207b530602fSAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 208070a2e63SAlex Deucher struct radeon_device *rdev = encoder->dev->dev_private; 209b530602fSAlex Deucher static const u16 eld_reg_to_type[][2] = { 210b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, 211b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, 212b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 }, 213b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 }, 214b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 }, 215b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC }, 216b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS }, 217b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC }, 218b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 }, 219b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD }, 220b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP }, 221b530602fSAlex Deucher { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, 222b530602fSAlex Deucher }; 223b530602fSAlex Deucher 224d0ea397eSAlex Deucher if (!dig || !dig->afmt || !dig->pin) 225b530602fSAlex Deucher return; 226b530602fSAlex Deucher 227b530602fSAlex Deucher for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { 228b530602fSAlex Deucher u32 value = 0; 2290f57bca9SAnssi Hannula u8 stereo_freqs = 0; 2300f57bca9SAnssi Hannula int max_channels = -1; 231b530602fSAlex Deucher int j; 232b530602fSAlex Deucher 233b530602fSAlex Deucher for (j = 0; j < sad_count; j++) { 234b530602fSAlex Deucher struct cea_sad *sad = &sads[j]; 235b530602fSAlex Deucher 236b530602fSAlex Deucher if (sad->format == eld_reg_to_type[i][1]) { 2370f57bca9SAnssi Hannula if (sad->channels > max_channels) { 238b530602fSAlex Deucher value = MAX_CHANNELS(sad->channels) | 239b530602fSAlex Deucher DESCRIPTOR_BYTE_2(sad->byte2) | 240b530602fSAlex Deucher SUPPORTED_FREQUENCIES(sad->freq); 2410f57bca9SAnssi Hannula max_channels = sad->channels; 2420f57bca9SAnssi Hannula } 2430f57bca9SAnssi Hannula 244b530602fSAlex Deucher if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) 2450f57bca9SAnssi Hannula stereo_freqs |= sad->freq; 2460f57bca9SAnssi Hannula else 247b530602fSAlex Deucher break; 248b530602fSAlex Deucher } 249b530602fSAlex Deucher } 2500f57bca9SAnssi Hannula 2510f57bca9SAnssi Hannula value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); 2520f57bca9SAnssi Hannula 253d0ea397eSAlex Deucher WREG32_ENDPOINT(dig->pin->offset, eld_reg_to_type[i][0], value); 254b530602fSAlex Deucher } 255b530602fSAlex Deucher } 256b530602fSAlex Deucher 257832eafafSAlex Deucher void dce6_audio_enable(struct radeon_device *rdev, 258b530602fSAlex Deucher struct r600_audio_pin *pin, 259d3d8c141SAlex Deucher u8 enable_mask) 260b530602fSAlex Deucher { 261832eafafSAlex Deucher if (!pin) 262832eafafSAlex Deucher return; 263832eafafSAlex Deucher 264f68fdbe4SAlex Deucher WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, 265d3d8c141SAlex Deucher enable_mask ? AUDIO_ENABLED : 0); 266b530602fSAlex Deucher } 267a85d682aSSlava Grigorev 268a85d682aSSlava Grigorev void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, 269a85d682aSSlava Grigorev struct radeon_crtc *crtc, unsigned int clock) 270a85d682aSSlava Grigorev { 271a85d682aSSlava Grigorev /* Two dtos; generally use dto0 for HDMI */ 272a85d682aSSlava Grigorev u32 value = 0; 273a85d682aSSlava Grigorev 274a85d682aSSlava Grigorev if (crtc) 275a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); 276a85d682aSSlava Grigorev 277a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO_SOURCE, value); 278a85d682aSSlava Grigorev 279a85d682aSSlava Grigorev /* Express [24MHz / target pixel clock] as an exact rational 280a85d682aSSlava Grigorev * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE 281a85d682aSSlava Grigorev * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator 282a85d682aSSlava Grigorev */ 283a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO0_PHASE, 24000); 284a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO0_MODULE, clock); 285a85d682aSSlava Grigorev } 286a85d682aSSlava Grigorev 287a85d682aSSlava Grigorev void dce6_dp_audio_set_dto(struct radeon_device *rdev, 288a85d682aSSlava Grigorev struct radeon_crtc *crtc, unsigned int clock) 289a85d682aSSlava Grigorev { 290a85d682aSSlava Grigorev /* Two dtos; generally use dto1 for DP */ 291a85d682aSSlava Grigorev u32 value = 0; 292a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO_SEL; 293a85d682aSSlava Grigorev 294a85d682aSSlava Grigorev if (crtc) 295a85d682aSSlava Grigorev value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); 296a85d682aSSlava Grigorev 297a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO_SOURCE, value); 298a85d682aSSlava Grigorev 299a85d682aSSlava Grigorev /* Express [24MHz / target pixel clock] as an exact rational 300a85d682aSSlava Grigorev * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE 301a85d682aSSlava Grigorev * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator 302a85d682aSSlava Grigorev */ 3032afa3265SSlava Grigorev if (ASIC_IS_DCE8(rdev)) { 3042afa3265SSlava Grigorev WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000); 3052afa3265SSlava Grigorev WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock); 3062afa3265SSlava Grigorev } else { 307a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); 308a85d682aSSlava Grigorev WREG32(DCCG_AUDIO_DTO1_MODULE, clock); 309a85d682aSSlava Grigorev } 3102afa3265SSlava Grigorev } 311