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 */ 27e55d3e6cSRafał Miłecki #include "drmP.h" 28e55d3e6cSRafał Miłecki #include "radeon_drm.h" 29e55d3e6cSRafał Miłecki #include "radeon.h" 30e55d3e6cSRafał Miłecki #include "radeon_asic.h" 31e55d3e6cSRafał Miłecki #include "evergreend.h" 32e55d3e6cSRafał Miłecki #include "atom.h" 33e55d3e6cSRafał Miłecki 34e55d3e6cSRafał Miłecki /* 35e55d3e6cSRafał Miłecki * update the N and CTS parameters for a given pixel clock rate 36e55d3e6cSRafał Miłecki */ 37e55d3e6cSRafał Miłecki static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) 38e55d3e6cSRafał Miłecki { 39e55d3e6cSRafał Miłecki struct drm_device *dev = encoder->dev; 40e55d3e6cSRafał Miłecki struct radeon_device *rdev = dev->dev_private; 41e55d3e6cSRafał Miłecki struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); 42e55d3e6cSRafał Miłecki uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; 43e55d3e6cSRafał Miłecki 44e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz)); 45e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz); 46e55d3e6cSRafał Miłecki 47e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz)); 48e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz); 49e55d3e6cSRafał Miłecki 50e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz)); 51e55d3e6cSRafał Miłecki WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz); 52e55d3e6cSRafał Miłecki } 53e55d3e6cSRafał Miłecki 54e55d3e6cSRafał Miłecki /* 55e55d3e6cSRafał Miłecki * calculate the crc for a given info frame 56e55d3e6cSRafał Miłecki */ 57e55d3e6cSRafał Miłecki static void evergreen_hdmi_infoframe_checksum(uint8_t packetType, 58e55d3e6cSRafał Miłecki uint8_t versionNumber, 59e55d3e6cSRafał Miłecki uint8_t length, 60e55d3e6cSRafał Miłecki uint8_t *frame) 61e55d3e6cSRafał Miłecki { 62e55d3e6cSRafał Miłecki int i; 63e55d3e6cSRafał Miłecki frame[0] = packetType + versionNumber + length; 64e55d3e6cSRafał Miłecki for (i = 1; i <= length; i++) 65e55d3e6cSRafał Miłecki frame[0] += frame[i]; 66e55d3e6cSRafał Miłecki frame[0] = 0x100 - frame[0]; 67e55d3e6cSRafał Miłecki } 68e55d3e6cSRafał Miłecki 69e55d3e6cSRafał Miłecki /* 70e55d3e6cSRafał Miłecki * build a HDMI Video Info Frame 71e55d3e6cSRafał Miłecki */ 72e55d3e6cSRafał Miłecki static void evergreen_hdmi_videoinfoframe( 73e55d3e6cSRafał Miłecki struct drm_encoder *encoder, 74e55d3e6cSRafał Miłecki uint8_t color_format, 75e55d3e6cSRafał Miłecki int active_information_present, 76e55d3e6cSRafał Miłecki uint8_t active_format_aspect_ratio, 77e55d3e6cSRafał Miłecki uint8_t scan_information, 78e55d3e6cSRafał Miłecki uint8_t colorimetry, 79e55d3e6cSRafał Miłecki uint8_t ex_colorimetry, 80e55d3e6cSRafał Miłecki uint8_t quantization, 81e55d3e6cSRafał Miłecki int ITC, 82e55d3e6cSRafał Miłecki uint8_t picture_aspect_ratio, 83e55d3e6cSRafał Miłecki uint8_t video_format_identification, 84e55d3e6cSRafał Miłecki uint8_t pixel_repetition, 85e55d3e6cSRafał Miłecki uint8_t non_uniform_picture_scaling, 86e55d3e6cSRafał Miłecki uint8_t bar_info_data_valid, 87e55d3e6cSRafał Miłecki uint16_t top_bar, 88e55d3e6cSRafał Miłecki uint16_t bottom_bar, 89e55d3e6cSRafał Miłecki uint16_t left_bar, 90e55d3e6cSRafał Miłecki uint16_t right_bar 91e55d3e6cSRafał Miłecki ) 92e55d3e6cSRafał Miłecki { 93e55d3e6cSRafał Miłecki struct drm_device *dev = encoder->dev; 94e55d3e6cSRafał Miłecki struct radeon_device *rdev = dev->dev_private; 95e55d3e6cSRafał Miłecki uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; 96e55d3e6cSRafał Miłecki 97e55d3e6cSRafał Miłecki uint8_t frame[14]; 98e55d3e6cSRafał Miłecki 99e55d3e6cSRafał Miłecki frame[0x0] = 0; 100e55d3e6cSRafał Miłecki frame[0x1] = 101e55d3e6cSRafał Miłecki (scan_information & 0x3) | 102e55d3e6cSRafał Miłecki ((bar_info_data_valid & 0x3) << 2) | 103e55d3e6cSRafał Miłecki ((active_information_present & 0x1) << 4) | 104e55d3e6cSRafał Miłecki ((color_format & 0x3) << 5); 105e55d3e6cSRafał Miłecki frame[0x2] = 106e55d3e6cSRafał Miłecki (active_format_aspect_ratio & 0xF) | 107e55d3e6cSRafał Miłecki ((picture_aspect_ratio & 0x3) << 4) | 108e55d3e6cSRafał Miłecki ((colorimetry & 0x3) << 6); 109e55d3e6cSRafał Miłecki frame[0x3] = 110e55d3e6cSRafał Miłecki (non_uniform_picture_scaling & 0x3) | 111e55d3e6cSRafał Miłecki ((quantization & 0x3) << 2) | 112e55d3e6cSRafał Miłecki ((ex_colorimetry & 0x7) << 4) | 113e55d3e6cSRafał Miłecki ((ITC & 0x1) << 7); 114e55d3e6cSRafał Miłecki frame[0x4] = (video_format_identification & 0x7F); 115e55d3e6cSRafał Miłecki frame[0x5] = (pixel_repetition & 0xF); 116e55d3e6cSRafał Miłecki frame[0x6] = (top_bar & 0xFF); 117e55d3e6cSRafał Miłecki frame[0x7] = (top_bar >> 8); 118e55d3e6cSRafał Miłecki frame[0x8] = (bottom_bar & 0xFF); 119e55d3e6cSRafał Miłecki frame[0x9] = (bottom_bar >> 8); 120e55d3e6cSRafał Miłecki frame[0xA] = (left_bar & 0xFF); 121e55d3e6cSRafał Miłecki frame[0xB] = (left_bar >> 8); 122e55d3e6cSRafał Miłecki frame[0xC] = (right_bar & 0xFF); 123e55d3e6cSRafał Miłecki frame[0xD] = (right_bar >> 8); 124e55d3e6cSRafał Miłecki 125e55d3e6cSRafał Miłecki evergreen_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame); 126e55d3e6cSRafał Miłecki /* Our header values (type, version, length) should be alright, Intel 127e55d3e6cSRafał Miłecki * is using the same. Checksum function also seems to be OK, it works 128e55d3e6cSRafał Miłecki * fine for audio infoframe. However calculated value is always lower 129e55d3e6cSRafał Miłecki * by 2 in comparison to fglrx. It breaks displaying anything in case 130e55d3e6cSRafał Miłecki * of TVs that strictly check the checksum. Hack it manually here to 131e55d3e6cSRafał Miłecki * workaround this issue. */ 132e55d3e6cSRafał Miłecki frame[0x0] += 2; 133e55d3e6cSRafał Miłecki 134e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO0 + offset, 135e55d3e6cSRafał Miłecki frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); 136e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO1 + offset, 137e55d3e6cSRafał Miłecki frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); 138e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO2 + offset, 139e55d3e6cSRafał Miłecki frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); 140e55d3e6cSRafał Miłecki WREG32(AFMT_AVI_INFO3 + offset, 141e55d3e6cSRafał Miłecki frame[0xC] | (frame[0xD] << 8)); 142e55d3e6cSRafał Miłecki } 143e55d3e6cSRafał Miłecki 144e55d3e6cSRafał Miłecki /* 145e55d3e6cSRafał Miłecki * update the info frames with the data from the current display mode 146e55d3e6cSRafał Miłecki */ 147e55d3e6cSRafał Miłecki void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) 148e55d3e6cSRafał Miłecki { 149e55d3e6cSRafał Miłecki struct drm_device *dev = encoder->dev; 150e55d3e6cSRafał Miłecki struct radeon_device *rdev = dev->dev_private; 151e55d3e6cSRafał Miłecki uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; 152e55d3e6cSRafał Miłecki 153e55d3e6cSRafał Miłecki if (ASIC_IS_DCE5(rdev)) 154e55d3e6cSRafał Miłecki return; 155e55d3e6cSRafał Miłecki 156e55d3e6cSRafał Miłecki if (!to_radeon_encoder(encoder)->hdmi_enabled) 157e55d3e6cSRafał Miłecki return; 158e55d3e6cSRafał Miłecki 159e55d3e6cSRafał Miłecki r600_audio_set_clock(encoder, mode->clock); 160e55d3e6cSRafał Miłecki 161*1c3439f2SRafał Miłecki WREG32(HDMI_VBI_PACKET_CONTROL + offset, 162*1c3439f2SRafał Miłecki HDMI_NULL_SEND); /* send null packets when required */ 163*1c3439f2SRafał Miłecki 164e55d3e6cSRafał Miłecki WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000); 165e55d3e6cSRafał Miłecki 166*1c3439f2SRafał Miłecki WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, 167*1c3439f2SRafał Miłecki HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ 168*1c3439f2SRafał Miłecki HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ 169e55d3e6cSRafał Miłecki 170*1c3439f2SRafał Miłecki WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, 171*1c3439f2SRafał Miłecki AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ 172*1c3439f2SRafał Miłecki AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ 173e55d3e6cSRafał Miłecki 174*1c3439f2SRafał Miłecki WREG32(HDMI_ACR_PACKET_CONTROL + offset, 175*1c3439f2SRafał Miłecki HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ 176*1c3439f2SRafał Miłecki HDMI_ACR_SOURCE); /* select SW CTS value */ 177e55d3e6cSRafał Miłecki 178*1c3439f2SRafał Miłecki WREG32(HDMI_VBI_PACKET_CONTROL + offset, 179*1c3439f2SRafał Miłecki HDMI_NULL_SEND | /* send null packets when required */ 180*1c3439f2SRafał Miłecki HDMI_GC_SEND | /* send general control packets */ 181*1c3439f2SRafał Miłecki HDMI_GC_CONT); /* send general control packets every frame */ 182e55d3e6cSRafał Miłecki 183*1c3439f2SRafał Miłecki WREG32(HDMI_INFOFRAME_CONTROL0 + offset, 184*1c3439f2SRafał Miłecki HDMI_AVI_INFO_SEND | /* enable AVI info frames */ 185*1c3439f2SRafał Miłecki HDMI_AVI_INFO_CONT | /* send AVI info frames every frame/field */ 186*1c3439f2SRafał Miłecki HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ 187*1c3439f2SRafał Miłecki HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ 188*1c3439f2SRafał Miłecki 189*1c3439f2SRafał Miłecki WREG32(AFMT_INFOFRAME_CONTROL0 + offset, 190*1c3439f2SRafał Miłecki AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ 191*1c3439f2SRafał Miłecki 192*1c3439f2SRafał Miłecki WREG32(HDMI_INFOFRAME_CONTROL1 + offset, 193*1c3439f2SRafał Miłecki HDMI_AVI_INFO_LINE(2) | /* anything other than 0 */ 194*1c3439f2SRafał Miłecki HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ 195*1c3439f2SRafał Miłecki 196*1c3439f2SRafał Miłecki WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */ 197e55d3e6cSRafał Miłecki 198e55d3e6cSRafał Miłecki evergreen_hdmi_videoinfoframe(encoder, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199e55d3e6cSRafał Miłecki 0, 0, 0, 0, 0, 0); 200e55d3e6cSRafał Miłecki 201*1c3439f2SRafał Miłecki evergreen_hdmi_update_ACR(encoder, mode->clock); 202*1c3439f2SRafał Miłecki 203e55d3e6cSRafał Miłecki /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ 204e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF); 205e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); 206e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); 207e55d3e6cSRafał Miłecki WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); 208e55d3e6cSRafał Miłecki } 209