Subversion Repositories Kolibri OS

Rev

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