linux/drivers/gpu/drm/radeon/evergreen_hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008 Advanced Micro Devices, Inc.
   3 * Copyright 2008 Red Hat Inc.
   4 * Copyright 2009 Christian König.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a
   7 * copy of this software and associated documentation files (the "Software"),
   8 * to deal in the Software without restriction, including without limitation
   9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10 * and/or sell copies of the Software, and to permit persons to whom the
  11 * Software is furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22 * OTHER DEALINGS IN THE SOFTWARE.
  23 *
  24 * Authors: Christian König
  25 *          Rafał Miłecki
  26 */
  27#include <linux/hdmi.h>
  28#include <drm/drmP.h>
  29#include <drm/radeon_drm.h>
  30#include "radeon.h"
  31#include "radeon_asic.h"
  32#include "evergreend.h"
  33#include "atom.h"
  34
  35extern void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder);
  36extern void dce6_afmt_write_sad_regs(struct drm_encoder *encoder);
  37extern void dce6_afmt_select_pin(struct drm_encoder *encoder);
  38
  39/*
  40 * update the N and CTS parameters for a given pixel clock rate
  41 */
  42static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
  43{
  44        struct drm_device *dev = encoder->dev;
  45        struct radeon_device *rdev = dev->dev_private;
  46        struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
  47        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  48        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  49        uint32_t offset = dig->afmt->offset;
  50
  51        WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz));
  52        WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz);
  53
  54        WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz));
  55        WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz);
  56
  57        WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz));
  58        WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz);
  59}
  60
  61static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
  62{
  63        struct radeon_device *rdev = encoder->dev->dev_private;
  64        struct drm_connector *connector;
  65        struct radeon_connector *radeon_connector = NULL;
  66        u32 tmp;
  67        u8 *sadb;
  68        int sad_count;
  69
  70        /* XXX: setting this register causes hangs on some asics */
  71        return;
  72
  73        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
  74                if (connector->encoder == encoder)
  75                        radeon_connector = to_radeon_connector(connector);
  76        }
  77
  78        if (!radeon_connector) {
  79                DRM_ERROR("Couldn't find encoder's connector\n");
  80                return;
  81        }
  82
  83        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
  84        if (sad_count < 0) {
  85                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
  86                return;
  87        }
  88
  89        /* program the speaker allocation */
  90        tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
  91        tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
  92        /* set HDMI mode */
  93        tmp |= HDMI_CONNECTION;
  94        if (sad_count)
  95                tmp |= SPEAKER_ALLOCATION(sadb[0]);
  96        else
  97                tmp |= SPEAKER_ALLOCATION(5); /* stereo */
  98        WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
  99
 100        kfree(sadb);
 101}
 102
 103static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
 104{
 105        struct radeon_device *rdev = encoder->dev->dev_private;
 106        struct drm_connector *connector;
 107        struct radeon_connector *radeon_connector = NULL;
 108        struct cea_sad *sads;
 109        int i, sad_count;
 110
 111        static const u16 eld_reg_to_type[][2] = {
 112                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 113                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
 114                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
 115                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
 116                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
 117                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
 118                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
 119                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
 120                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
 121                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
 122                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
 123                { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
 124        };
 125
 126        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
 127                if (connector->encoder == encoder)
 128                        radeon_connector = to_radeon_connector(connector);
 129        }
 130
 131        if (!radeon_connector) {
 132                DRM_ERROR("Couldn't find encoder's connector\n");
 133                return;
 134        }
 135
 136        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
 137        if (sad_count < 0) {
 138                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
 139                return;
 140        }
 141        BUG_ON(!sads);
 142
 143        for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 144                u32 value = 0;
 145                int j;
 146
 147                for (j = 0; j < sad_count; j++) {
 148                        struct cea_sad *sad = &sads[j];
 149
 150                        if (sad->format == eld_reg_to_type[i][1]) {
 151                                value = MAX_CHANNELS(sad->channels) |
 152                                        DESCRIPTOR_BYTE_2(sad->byte2) |
 153                                        SUPPORTED_FREQUENCIES(sad->freq);
 154                                if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
 155                                        value |= SUPPORTED_FREQUENCIES_STEREO(sad->freq);
 156                                break;
 157                        }
 158                }
 159                WREG32(eld_reg_to_type[i][0], value);
 160        }
 161
 162        kfree(sads);
 163}
 164
 165/*
 166 * build a HDMI Video Info Frame
 167 */
 168static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
 169                                                void *buffer, size_t size)
 170{
 171        struct drm_device *dev = encoder->dev;
 172        struct radeon_device *rdev = dev->dev_private;
 173        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 174        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 175        uint32_t offset = dig->afmt->offset;
 176        uint8_t *frame = buffer + 3;
 177        uint8_t *header = buffer;
 178
 179        WREG32(AFMT_AVI_INFO0 + offset,
 180                frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
 181        WREG32(AFMT_AVI_INFO1 + offset,
 182                frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
 183        WREG32(AFMT_AVI_INFO2 + offset,
 184                frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 185        WREG32(AFMT_AVI_INFO3 + offset,
 186                frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
 187}
 188
 189static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 190{
 191        struct drm_device *dev = encoder->dev;
 192        struct radeon_device *rdev = dev->dev_private;
 193        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 194        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 195        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 196        u32 base_rate = 24000;
 197        u32 max_ratio = clock / base_rate;
 198        u32 dto_phase;
 199        u32 dto_modulo = clock;
 200        u32 wallclock_ratio;
 201        u32 dto_cntl;
 202
 203        if (!dig || !dig->afmt)
 204                return;
 205
 206        if (ASIC_IS_DCE6(rdev)) {
 207                dto_phase = 24 * 1000;
 208        } else {
 209                if (max_ratio >= 8) {
 210                        dto_phase = 192 * 1000;
 211                        wallclock_ratio = 3;
 212                } else if (max_ratio >= 4) {
 213                        dto_phase = 96 * 1000;
 214                        wallclock_ratio = 2;
 215                } else if (max_ratio >= 2) {
 216                        dto_phase = 48 * 1000;
 217                        wallclock_ratio = 1;
 218                } else {
 219                        dto_phase = 24 * 1000;
 220                        wallclock_ratio = 0;
 221                }
 222                dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
 223                dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
 224                WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
 225        }
 226
 227        /* XXX two dtos; generally use dto0 for hdmi */
 228        /* Express [24MHz / target pixel clock] as an exact rational
 229         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
 230         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
 231         */
 232        WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 233        WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
 234        WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
 235}
 236
 237
 238/*
 239 * update the info frames with the data from the current display mode
 240 */
 241void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
 242{
 243        struct drm_device *dev = encoder->dev;
 244        struct radeon_device *rdev = dev->dev_private;
 245        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 246        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 247        u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
 248        struct hdmi_avi_infoframe frame;
 249        uint32_t offset;
 250        ssize_t err;
 251
 252        if (!dig || !dig->afmt)
 253                return;
 254
 255        /* Silent, r600_hdmi_enable will raise WARN for us */
 256        if (!dig->afmt->enabled)
 257                return;
 258        offset = dig->afmt->offset;
 259
 260        evergreen_audio_set_dto(encoder, mode->clock);
 261
 262        WREG32(HDMI_VBI_PACKET_CONTROL + offset,
 263               HDMI_NULL_SEND); /* send null packets when required */
 264
 265        WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000);
 266
 267        WREG32(HDMI_VBI_PACKET_CONTROL + offset,
 268               HDMI_NULL_SEND | /* send null packets when required */
 269               HDMI_GC_SEND | /* send general control packets */
 270               HDMI_GC_CONT); /* send general control packets every frame */
 271
 272        WREG32(HDMI_INFOFRAME_CONTROL0 + offset,
 273               HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
 274               HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
 275
 276        WREG32(AFMT_INFOFRAME_CONTROL0 + offset,
 277               AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
 278
 279        WREG32(HDMI_INFOFRAME_CONTROL1 + offset,
 280               HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
 281
 282        WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */
 283
 284        WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
 285               HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
 286               HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
 287
 288        WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
 289               AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
 290
 291        /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */
 292
 293        WREG32(HDMI_ACR_PACKET_CONTROL + offset,
 294               HDMI_ACR_SOURCE | /* select SW CTS value */
 295               HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
 296
 297        evergreen_hdmi_update_ACR(encoder, mode->clock);
 298
 299        WREG32(AFMT_60958_0 + offset,
 300               AFMT_60958_CS_CHANNEL_NUMBER_L(1));
 301
 302        WREG32(AFMT_60958_1 + offset,
 303               AFMT_60958_CS_CHANNEL_NUMBER_R(2));
 304
 305        WREG32(AFMT_60958_2 + offset,
 306               AFMT_60958_CS_CHANNEL_NUMBER_2(3) |
 307               AFMT_60958_CS_CHANNEL_NUMBER_3(4) |
 308               AFMT_60958_CS_CHANNEL_NUMBER_4(5) |
 309               AFMT_60958_CS_CHANNEL_NUMBER_5(6) |
 310               AFMT_60958_CS_CHANNEL_NUMBER_6(7) |
 311               AFMT_60958_CS_CHANNEL_NUMBER_7(8));
 312
 313        if (ASIC_IS_DCE6(rdev)) {
 314                dce6_afmt_write_speaker_allocation(encoder);
 315        } else {
 316                dce4_afmt_write_speaker_allocation(encoder);
 317        }
 318
 319        WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset,
 320               AFMT_AUDIO_CHANNEL_ENABLE(0xff));
 321
 322        /* fglrx sets 0x40 in 0x5f80 here */
 323
 324        if (ASIC_IS_DCE6(rdev)) {
 325                dce6_afmt_select_pin(encoder);
 326                dce6_afmt_write_sad_regs(encoder);
 327        } else {
 328                evergreen_hdmi_write_sad_regs(encoder);
 329        }
 330
 331        err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 332        if (err < 0) {
 333                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
 334                return;
 335        }
 336
 337        err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
 338        if (err < 0) {
 339                DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
 340                return;
 341        }
 342
 343        evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
 344
 345        WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset,
 346                  HDMI_AVI_INFO_SEND | /* enable AVI info frames */
 347                  HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */
 348
 349        WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
 350                 HDMI_AVI_INFO_LINE(2), /* anything other than 0 */
 351                 ~HDMI_AVI_INFO_LINE_MASK);
 352
 353        WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + offset,
 354                  AFMT_AUDIO_SAMPLE_SEND); /* send audio packets */
 355
 356        /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
 357        WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF);
 358        WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
 359        WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
 360        WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
 361}
 362
 363void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 364{
 365        struct drm_device *dev = encoder->dev;
 366        struct radeon_device *rdev = dev->dev_private;
 367        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 368        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 369
 370        if (!dig || !dig->afmt)
 371                return;
 372
 373        /* Silent, r600_hdmi_enable will raise WARN for us */
 374        if (enable && dig->afmt->enabled)
 375                return;
 376        if (!enable && !dig->afmt->enabled)
 377                return;
 378
 379        if (enable) {
 380                if (ASIC_IS_DCE6(rdev))
 381                        dig->afmt->pin = dce6_audio_get_pin(rdev);
 382                else
 383                        dig->afmt->pin = r600_audio_get_pin(rdev);
 384        } else {
 385                dig->afmt->pin = NULL;
 386        }
 387
 388        dig->afmt->enabled = enable;
 389
 390        DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 391                  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
 392}
 393