Subversion Repositories Kolibri OS

Rev

Rev 1963 | Rev 5078 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.  */
  26. #include <drm/drmP.h>
  27. #include <drm/radeon_drm.h>
  28. #include "radeon.h"
  29. #include "radeon_asic.h"
  30. #include "r600d.h"
  31. #include "atom.h"
  32.  
  33. /*
  34.  * HDMI color format
  35.  */
  36. enum r600_hdmi_color_format {
  37.         RGB = 0,
  38.         YCC_422 = 1,
  39.         YCC_444 = 2
  40. };
  41.  
  42. /*
  43.  * IEC60958 status bits
  44.  */
  45. enum r600_hdmi_iec_status_bits {
  46.         AUDIO_STATUS_DIG_ENABLE   = 0x01,
  47.         AUDIO_STATUS_V      = 0x02,
  48.         AUDIO_STATUS_VCFG        = 0x04,
  49.         AUDIO_STATUS_EMPHASIS     = 0x08,
  50.         AUDIO_STATUS_COPYRIGHT    = 0x10,
  51.         AUDIO_STATUS_NONAUDIO     = 0x20,
  52.         AUDIO_STATUS_PROFESSIONAL = 0x40,
  53.         AUDIO_STATUS_LEVEL      = 0x80
  54. };
  55.  
  56. static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
  57.     /*       32kHz        44.1kHz       48kHz    */
  58.     /* Clock      N     CTS      N     CTS      N     CTS */
  59.     {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
  60.     {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
  61.     {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
  62.     {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
  63.     {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
  64.     {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
  65.     {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
  66.     {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
  67.     { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
  68.     { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
  69.     {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
  70. };
  71.  
  72. /*
  73.  * calculate CTS value if it's not found in the table
  74.  */
  75. static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
  76. {
  77.         if (*CTS == 0)
  78.                 *CTS = clock * N / (128 * freq) * 1000;
  79.         DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
  80.                   N, *CTS, freq);
  81. }
  82.  
  83. struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
  84. {
  85.         struct radeon_hdmi_acr res;
  86.         u8 i;
  87.  
  88.         for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
  89.              r600_hdmi_predefined_acr[i].clock != 0; i++)
  90.                 ;
  91.         res = r600_hdmi_predefined_acr[i];
  92.  
  93.         /* In case some CTS are missing */
  94.         r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
  95.         r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
  96.         r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);
  97.  
  98.         return res;
  99. }
  100.  
  101. /*
  102.  * update the N and CTS parameters for a given pixel clock rate
  103.  */
  104. static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
  105. {
  106.         struct drm_device *dev = encoder->dev;
  107.         struct radeon_device *rdev = dev->dev_private;
  108.         struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
  109.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  110.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  111.         uint32_t offset = dig->afmt->offset;
  112.  
  113.         WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz));
  114.         WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz);
  115.  
  116.         WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz));
  117.         WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz);
  118.  
  119.         WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz));
  120.         WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz);
  121. }
  122.  
  123. /*
  124.  * calculate the crc for a given info frame
  125.  */
  126. static void r600_hdmi_infoframe_checksum(uint8_t packetType,
  127.                                          uint8_t versionNumber,
  128.                                          uint8_t length,
  129.                                          uint8_t *frame)
  130. {
  131.     int i;
  132.     frame[0] = packetType + versionNumber + length;
  133.     for (i = 1; i <= length; i++)
  134.         frame[0] += frame[i];
  135.     frame[0] = 0x100 - frame[0];
  136. }
  137.  
  138. /*
  139.  * build a HDMI Video Info Frame
  140.  */
  141. static void r600_hdmi_videoinfoframe(
  142.         struct drm_encoder *encoder,
  143.         enum r600_hdmi_color_format color_format,
  144.         int active_information_present,
  145.         uint8_t active_format_aspect_ratio,
  146.         uint8_t scan_information,
  147.         uint8_t colorimetry,
  148.         uint8_t ex_colorimetry,
  149.         uint8_t quantization,
  150.         int ITC,
  151.         uint8_t picture_aspect_ratio,
  152.         uint8_t video_format_identification,
  153.         uint8_t pixel_repetition,
  154.         uint8_t non_uniform_picture_scaling,
  155.         uint8_t bar_info_data_valid,
  156.         uint16_t top_bar,
  157.         uint16_t bottom_bar,
  158.         uint16_t left_bar,
  159.         uint16_t right_bar
  160. )
  161. {
  162.         struct drm_device *dev = encoder->dev;
  163.         struct radeon_device *rdev = dev->dev_private;
  164.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  165.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  166.         uint32_t offset = dig->afmt->offset;
  167.  
  168.         uint8_t frame[14];
  169.  
  170.         frame[0x0] = 0;
  171.         frame[0x1] =
  172.                 (scan_information & 0x3) |
  173.                 ((bar_info_data_valid & 0x3) << 2) |
  174.                 ((active_information_present & 0x1) << 4) |
  175.                 ((color_format & 0x3) << 5);
  176.         frame[0x2] =
  177.                 (active_format_aspect_ratio & 0xF) |
  178.                 ((picture_aspect_ratio & 0x3) << 4) |
  179.                 ((colorimetry & 0x3) << 6);
  180.         frame[0x3] =
  181.                 (non_uniform_picture_scaling & 0x3) |
  182.                 ((quantization & 0x3) << 2) |
  183.                 ((ex_colorimetry & 0x7) << 4) |
  184.                 ((ITC & 0x1) << 7);
  185.         frame[0x4] = (video_format_identification & 0x7F);
  186.         frame[0x5] = (pixel_repetition & 0xF);
  187.         frame[0x6] = (top_bar & 0xFF);
  188.         frame[0x7] = (top_bar >> 8);
  189.         frame[0x8] = (bottom_bar & 0xFF);
  190.         frame[0x9] = (bottom_bar >> 8);
  191.         frame[0xA] = (left_bar & 0xFF);
  192.         frame[0xB] = (left_bar >> 8);
  193.         frame[0xC] = (right_bar & 0xFF);
  194.         frame[0xD] = (right_bar >> 8);
  195.  
  196.         r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
  197.         /* Our header values (type, version, length) should be alright, Intel
  198.          * is using the same. Checksum function also seems to be OK, it works
  199.          * fine for audio infoframe. However calculated value is always lower
  200.          * by 2 in comparison to fglrx. It breaks displaying anything in case
  201.          * of TVs that strictly check the checksum. Hack it manually here to
  202.          * workaround this issue. */
  203.         frame[0x0] += 2;
  204.  
  205.         WREG32(HDMI0_AVI_INFO0 + offset,
  206.                 frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
  207.         WREG32(HDMI0_AVI_INFO1 + offset,
  208.                 frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
  209.         WREG32(HDMI0_AVI_INFO2 + offset,
  210.                 frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
  211.         WREG32(HDMI0_AVI_INFO3 + offset,
  212.                 frame[0xC] | (frame[0xD] << 8));
  213. }
  214.  
  215. /*
  216.  * build a Audio Info Frame
  217.  */
  218. static void r600_hdmi_audioinfoframe(
  219.         struct drm_encoder *encoder,
  220.         uint8_t channel_count,
  221.         uint8_t coding_type,
  222.         uint8_t sample_size,
  223.         uint8_t sample_frequency,
  224.         uint8_t format,
  225.         uint8_t channel_allocation,
  226.         uint8_t level_shift,
  227.         int downmix_inhibit
  228. )
  229. {
  230.         struct drm_device *dev = encoder->dev;
  231.         struct radeon_device *rdev = dev->dev_private;
  232.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  233.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  234.         uint32_t offset = dig->afmt->offset;
  235.  
  236.         uint8_t frame[11];
  237.  
  238.         frame[0x0] = 0;
  239.         frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4);
  240.         frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2);
  241.         frame[0x3] = format;
  242.         frame[0x4] = channel_allocation;
  243.         frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7);
  244.         frame[0x6] = 0;
  245.         frame[0x7] = 0;
  246.         frame[0x8] = 0;
  247.         frame[0x9] = 0;
  248.         frame[0xA] = 0;
  249.  
  250.         r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
  251.  
  252.         WREG32(HDMI0_AUDIO_INFO0 + offset,
  253.                 frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
  254.         WREG32(HDMI0_AUDIO_INFO1 + offset,
  255.                 frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
  256. }
  257.  
  258. /*
  259.  * test if audio buffer is filled enough to start playing
  260.  */
  261. static bool r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
  262. {
  263.         struct drm_device *dev = encoder->dev;
  264.         struct radeon_device *rdev = dev->dev_private;
  265.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  266.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  267.         uint32_t offset = dig->afmt->offset;
  268.  
  269.         return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0;
  270. }
  271.  
  272. /*
  273.  * have buffer status changed since last call?
  274.  */
  275. int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
  276. {
  277.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  278.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  279.         int status, result;
  280.  
  281.         if (!dig->afmt || !dig->afmt->enabled)
  282.                 return 0;
  283.  
  284.         status = r600_hdmi_is_audio_buffer_filled(encoder);
  285.         result = dig->afmt->last_buffer_filled_status != status;
  286.         dig->afmt->last_buffer_filled_status = status;
  287.  
  288.         return result;
  289. }
  290.  
  291. /*
  292.  * write the audio workaround status to the hardware
  293.  */
  294. static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
  295. {
  296.         struct drm_device *dev = encoder->dev;
  297.         struct radeon_device *rdev = dev->dev_private;
  298.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  299.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  300.         uint32_t offset = dig->afmt->offset;
  301.         bool hdmi_audio_workaround = false; /* FIXME */
  302.         u32 value;
  303.  
  304.         if (!hdmi_audio_workaround ||
  305.             r600_hdmi_is_audio_buffer_filled(encoder))
  306.                 value = 0; /* disable workaround */
  307.         else
  308.                 value = HDMI0_AUDIO_TEST_EN; /* enable workaround */
  309.         WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
  310.                  value, ~HDMI0_AUDIO_TEST_EN);
  311. }
  312.  
  313.  
  314. /*
  315.  * update the info frames with the data from the current display mode
  316.  */
  317. void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
  318. {
  319.         struct drm_device *dev = encoder->dev;
  320.         struct radeon_device *rdev = dev->dev_private;
  321.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  322.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  323.         uint32_t offset;
  324.  
  325.         /* Silent, r600_hdmi_enable will raise WARN for us */
  326.         if (!dig->afmt->enabled)
  327.                 return;
  328.         offset = dig->afmt->offset;
  329.  
  330. //      r600_audio_set_clock(encoder, mode->clock);
  331.  
  332.         WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
  333.                HDMI0_NULL_SEND); /* send null packets when required */
  334.  
  335.         WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
  336.  
  337.         if (ASIC_IS_DCE32(rdev)) {
  338.                 WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
  339.                        HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
  340.                        HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
  341.                 WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
  342.                        AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
  343.                        AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
  344.         } else {
  345.                 WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
  346.                        HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
  347.                        HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
  348.                        HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
  349.                        HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
  350.         }
  351.  
  352.         WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
  353.                HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
  354.                HDMI0_ACR_SOURCE); /* select SW CTS value */
  355.  
  356.         WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
  357.                HDMI0_NULL_SEND | /* send null packets when required */
  358.                HDMI0_GC_SEND | /* send general control packets */
  359.                HDMI0_GC_CONT); /* send general control packets every frame */
  360.  
  361.         /* TODO: HDMI0_AUDIO_INFO_UPDATE */
  362.         WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
  363.                HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
  364.                HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
  365.                HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
  366.                HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
  367.  
  368.         WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
  369.                HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
  370.                HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
  371.  
  372.         WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
  373.  
  374.         r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
  375.                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  376.  
  377.         r600_hdmi_update_ACR(encoder, mode->clock);
  378.  
  379.         /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
  380.         WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
  381.         WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
  382.         WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
  383.         WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
  384.  
  385.         r600_hdmi_audio_workaround(encoder);
  386. }
  387.  
  388. #if 0
  389. /*
  390.  * update settings with current parameters from audio engine
  391.  */
  392. void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
  393. {
  394.         struct drm_device *dev = encoder->dev;
  395.         struct radeon_device *rdev = dev->dev_private;
  396.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  397.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  398.         struct r600_audio audio = r600_audio_status(rdev);
  399.         uint32_t offset;
  400.         uint32_t iec;
  401.  
  402.         if (!dig->afmt || !dig->afmt->enabled)
  403.                 return;
  404.         offset = dig->afmt->offset;
  405.  
  406.         DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
  407.                  r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped",
  408.                   audio.channels, audio.rate, audio.bits_per_sample);
  409.         DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
  410.                   (int)audio.status_bits, (int)audio.category_code);
  411.  
  412.         iec = 0;
  413.         if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL)
  414.                 iec |= 1 << 0;
  415.         if (audio.status_bits & AUDIO_STATUS_NONAUDIO)
  416.                 iec |= 1 << 1;
  417.         if (audio.status_bits & AUDIO_STATUS_COPYRIGHT)
  418.                 iec |= 1 << 2;
  419.         if (audio.status_bits & AUDIO_STATUS_EMPHASIS)
  420.                 iec |= 1 << 3;
  421.  
  422.         iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code);
  423.  
  424.         switch (audio.rate) {
  425.         case 32000:
  426.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3);
  427.                 break;
  428.         case 44100:
  429.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0);
  430.                 break;
  431.         case 48000:
  432.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2);
  433.                 break;
  434.         case 88200:
  435.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8);
  436.                 break;
  437.         case 96000:
  438.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa);
  439.                 break;
  440.         case 176400:
  441.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc);
  442.                 break;
  443.         case 192000:
  444.                 iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe);
  445.                 break;
  446.         }
  447.  
  448.         WREG32(HDMI0_60958_0 + offset, iec);
  449.  
  450.         iec = 0;
  451.         switch (audio.bits_per_sample) {
  452.         case 16:
  453.                 iec |= HDMI0_60958_CS_WORD_LENGTH(0x2);
  454.                         break;
  455.         case 20:
  456.                 iec |= HDMI0_60958_CS_WORD_LENGTH(0x3);
  457.                         break;
  458.         case 24:
  459.                 iec |= HDMI0_60958_CS_WORD_LENGTH(0xb);
  460.                         break;
  461.                 }
  462.         if (audio.status_bits & AUDIO_STATUS_V)
  463.                 iec |= 0x5 << 16;
  464.         WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
  465.  
  466.         r600_hdmi_audioinfoframe(encoder, audio.channels - 1, 0, 0, 0, 0, 0, 0,
  467.                                  0);
  468.  
  469.         r600_hdmi_audio_workaround(encoder);
  470. }
  471. #endif
  472.  
  473. /*
  474.  * enable the HDMI engine
  475.  */
  476. void r600_hdmi_enable(struct drm_encoder *encoder)
  477. {
  478.         struct drm_device *dev = encoder->dev;
  479.         struct radeon_device *rdev = dev->dev_private;
  480.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  481.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  482.         uint32_t offset;
  483.         u32 hdmi;
  484.  
  485.         if (ASIC_IS_DCE6(rdev))
  486.                 return;
  487.  
  488.         /* Silent, r600_hdmi_enable will raise WARN for us */
  489.         if (dig->afmt->enabled)
  490.                 return;
  491.         offset = dig->afmt->offset;
  492.  
  493.         /* Older chipsets require setting HDMI and routing manually */
  494.         if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
  495.                 hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE;
  496.         switch (radeon_encoder->encoder_id) {
  497.         case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
  498.                         WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN,
  499.                                  ~AVIVO_TMDSA_CNTL_HDMI_EN);
  500.                         hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA);
  501.                 break;
  502.         case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
  503.                         WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN,
  504.                                  ~AVIVO_LVTMA_CNTL_HDMI_EN);
  505.                         hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA);
  506.                         break;
  507.                 case ENCODER_OBJECT_ID_INTERNAL_DDI:
  508.                         WREG32_P(DDIA_CNTL, DDIA_HDMI_EN, ~DDIA_HDMI_EN);
  509.                         hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA);
  510.                         break;
  511.                 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
  512.                         hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA);
  513.                 break;
  514.         default:
  515.                         dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
  516.                                 radeon_encoder->encoder_id);
  517.                 break;
  518.         }
  519.                 WREG32(HDMI0_CONTROL + offset, hdmi);
  520.         }
  521.  
  522.         if (rdev->irq.installed) {
  523.                 /* if irq is available use it */
  524. //              radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
  525.         }
  526.  
  527.         dig->afmt->enabled = true;
  528.  
  529.         DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
  530.                   offset, radeon_encoder->encoder_id);
  531. }
  532.  
  533. /*
  534.  * disable the HDMI engine
  535.  */
  536. void r600_hdmi_disable(struct drm_encoder *encoder)
  537. {
  538.         struct drm_device *dev = encoder->dev;
  539.         struct radeon_device *rdev = dev->dev_private;
  540.         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
  541.         struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
  542.         uint32_t offset;
  543.  
  544.         if (ASIC_IS_DCE6(rdev))
  545.                 return;
  546.  
  547.         /* Called for ATOM_ENCODER_MODE_HDMI only */
  548.         if (!dig || !dig->afmt) {
  549.                 WARN_ON(1);
  550.                 return;
  551.         }
  552.         if (!dig->afmt->enabled)
  553.                 return;
  554.         offset = dig->afmt->offset;
  555.  
  556.         DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
  557.                 offset, radeon_encoder->encoder_id);
  558.  
  559.         /* disable irq */
  560. //      radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
  561.  
  562.         /* Older chipsets not handled by AtomBIOS */
  563.         if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
  564.         switch (radeon_encoder->encoder_id) {
  565.         case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
  566.                         WREG32_P(AVIVO_TMDSA_CNTL, 0,
  567.                                  ~AVIVO_TMDSA_CNTL_HDMI_EN);
  568.                 break;
  569.         case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
  570.                         WREG32_P(AVIVO_LVTMA_CNTL, 0,
  571.                                  ~AVIVO_LVTMA_CNTL_HDMI_EN);
  572.                         break;
  573.                 case ENCODER_OBJECT_ID_INTERNAL_DDI:
  574.                         WREG32_P(DDIA_CNTL, 0, ~DDIA_HDMI_EN);
  575.                         break;
  576.                 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
  577.                         break;
  578.                 default:
  579.                         dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
  580.                                 radeon_encoder->encoder_id);
  581.                         break;
  582.                 }
  583.                 WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK);
  584.         }
  585.  
  586.         dig->afmt->enabled = false;
  587. }
  588.