Merge branches 'acpi-resources', 'acpi-battery', 'acpi-doc' and 'acpi-pnp'
[linux-2.6-block.git] / drivers / gpu / drm / radeon / evergreen_hdmi.c
index 1d9aebc79595d050dd52d6e28da01939b908bc16..0926739c9fa7c40d17dd09bb318cc19c4ca194c1 100644 (file)
@@ -219,13 +219,9 @@ void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset,
        WREG32(AFMT_AVI_INFO3 + offset,
                frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24));
 
-       WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset,
-               HDMI_AVI_INFO_SEND |    /* enable AVI info frames */
-               HDMI_AVI_INFO_CONT);    /* required for audio info values to be updated */
-
        WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
-               HDMI_AVI_INFO_LINE(2),  /* anything other than 0 */
-               ~HDMI_AVI_INFO_LINE_MASK);
+                HDMI_AVI_INFO_LINE(2), /* anything other than 0 */
+                ~HDMI_AVI_INFO_LINE_MASK);
 }
 
 void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
@@ -272,7 +268,7 @@ void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
 }
 
 void dce4_dp_audio_set_dto(struct radeon_device *rdev,
-       struct radeon_crtc *crtc, unsigned int clock)
+                          struct radeon_crtc *crtc, unsigned int clock)
 {
        u32 value;
 
@@ -294,7 +290,7 @@ void dce4_dp_audio_set_dto(struct radeon_device *rdev,
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
        WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
-       WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10);
+       WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
 }
 
 void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset)
@@ -350,20 +346,9 @@ void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
 
-       WREG32(HDMI_INFOFRAME_CONTROL0 + offset,
-               HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-               HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
-
        WREG32(AFMT_INFOFRAME_CONTROL0 + offset,
                AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
 
-       WREG32(HDMI_INFOFRAME_CONTROL1 + offset,
-               HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-       WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
-               HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
-               HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-
        WREG32(AFMT_60958_0 + offset,
                AFMT_60958_CS_CHANNEL_NUMBER_L(1));
 
@@ -381,9 +366,13 @@ void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset)
        WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset,
                AFMT_AUDIO_CHANNEL_ENABLE(0xff));
 
+       WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
+              HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
+              HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+
        /* allow 60958 channel status and send audio packets fields to be updated */
-       WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-               AFMT_AUDIO_SAMPLE_SEND | AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE);
+       WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + offset,
+                 AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE);
 }
 
 
@@ -408,15 +397,28 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!dig || !dig->afmt)
                return;
 
-       /* Silent, r600_hdmi_enable will raise WARN for us */
-       if (enable && dig->afmt->enabled)
-               return;
-       if (!enable && !dig->afmt->enabled)
-               return;
+       if (enable) {
+               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
-       if (!enable && dig->afmt->pin) {
-               radeon_audio_enable(rdev, dig->afmt->pin, 0);
-               dig->afmt->pin = NULL;
+               if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+                       WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
+                              HDMI_AVI_INFO_SEND | /* enable AVI info frames */
+                              HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */
+                              HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+                              HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
+                       WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                                 AFMT_AUDIO_SAMPLE_SEND);
+               } else {
+                       WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
+                              HDMI_AVI_INFO_SEND | /* enable AVI info frames */
+                              HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */
+                       WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                                  ~AFMT_AUDIO_SAMPLE_SEND);
+               }
+       } else {
+               WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                          ~AFMT_AUDIO_SAMPLE_SEND);
+               WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, 0);
        }
 
        dig->afmt->enabled = enable;
@@ -425,33 +427,32 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
                  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
 }
 
-void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
+void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       uint32_t offset;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
        if (!dig || !dig->afmt)
                return;
 
-       offset = dig->afmt->offset;
-
-       if (enable) {
+       if (enable && drm_detect_monitor_audio(radeon_connector_edid(connector))) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                struct radeon_connector_atom_dig *dig_connector;
                uint32_t val;
 
-               if (dig->afmt->enabled)
-                       return;
+               WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                         AFMT_AUDIO_SAMPLE_SEND);
 
-               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
+               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
+                      EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
 
-               if (radeon_connector->con_priv) {
+               if (!ASIC_IS_DCE6(rdev) && radeon_connector->con_priv) {
                        dig_connector = radeon_connector->con_priv;
-                       val = RREG32(EVERGREEN_DP_SEC_AUD_N + offset);
+                       val = RREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset);
                        val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf);
 
                        if (dig_connector->dp_clock == 162000)
@@ -459,21 +460,18 @@ void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
                        else
                                val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5);
 
-                       WREG32(EVERGREEN_DP_SEC_AUD_N + offset, val);
+                       WREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset, val);
                }
 
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset,
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset,
                        EVERGREEN_DP_SEC_ASP_ENABLE |           /* Audio packet transmission */
                        EVERGREEN_DP_SEC_ATP_ENABLE |           /* Audio timestamp packet transmission */
                        EVERGREEN_DP_SEC_AIP_ENABLE |           /* Audio infoframe packet transmission */
                        EVERGREEN_DP_SEC_STREAM_ENABLE);        /* Master enable for secondary stream engine */
-               radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
        } else {
-               if (!dig->afmt->enabled)
-                       return;
-
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0);
-               radeon_audio_enable(rdev, dig->afmt->pin, 0);
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
+               WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                          ~AFMT_AUDIO_SAMPLE_SEND);
        }
 
        dig->afmt->enabled = enable;