radeon: first pass at bios scratch regs
authorAlex Deucher <alexdeucher@gmail.com>
Sun, 17 Aug 2008 22:09:07 +0000 (18:09 -0400)
committerAlex Deucher <alexdeucher@gmail.com>
Sun, 17 Aug 2008 22:09:07 +0000 (18:09 -0400)
- todo: updated connected status

linux-core/radeon_atombios.c
linux-core/radeon_combios.c
linux-core/radeon_connectors.c
linux-core/radeon_display.c
linux-core/radeon_encoders.c
linux-core/radeon_gem.c
linux-core/radeon_legacy_encoders.c
linux-core/radeon_mode.h
shared-core/radeon_cp.c

index eb482d9..ca287bc 100644 (file)
@@ -363,3 +363,55 @@ void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable)
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
+{
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t bios_2_scratch, bios_6_scratch;
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               bios_2_scratch = RADEON_READ(RADEON_BIOS_0_SCRATCH);
+               bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+       } else {
+               bios_2_scratch = RADEON_READ(RADEON_BIOS_0_SCRATCH);
+               bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+       }
+
+       /* let the bios control the backlight */
+       bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
+
+       /* tell the bios not to handle mode switching */
+       bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH |
+                          ATOM_S6_ACC_MODE);
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               RADEON_WRITE(R600_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(R600_BIOS_6_SCRATCH, bios_6_scratch);
+       } else {
+               RADEON_WRITE(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+       }
+
+}
+
+void
+radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t bios_6_scratch;
+
+       if (dev_priv->chip_family >= CHIP_R600)
+               bios_6_scratch = RADEON_READ(R600_BIOS_6_SCRATCH);
+       else
+               bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       if (lock)
+               bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
+       else
+               bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
+
+       if (dev_priv->chip_family >= CHIP_R600)
+               RADEON_WRITE(R600_BIOS_6_SCRATCH, bios_6_scratch);
+       else
+               RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+}
index 02f7335..200761e 100644 (file)
@@ -1301,3 +1301,44 @@ void radeon_combios_asic_init(struct drm_device *dev)
                combios_parse_mmio_table(dev, table);
 
 }
+
+void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev)
+{
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t bios_0_scratch, bios_6_scratch, bios_7_scratch;
+
+       bios_0_scratch = RADEON_READ(RADEON_BIOS_0_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+       //bios_7_scratch = RADEON_READ(RADEON_BIOS_7_SCRATCH);
+
+       /* let the bios control the backlight */
+       bios_0_scratch &= ~RADEON_DRIVER_BRIGHTNESS_EN;
+
+       /* tell the bios not to handle mode switching */
+       bios_6_scratch |= (RADEON_DISPLAY_SWITCHING_DIS |
+                                RADEON_ACC_MODE_CHANGE);
+
+       /* tell the bios a driver is loaded */
+       //bios_7_scratch |= RADEON_DRV_LOADED;
+
+       RADEON_WRITE(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+       //RADEON_WRITE(RADEON_BIOS_7_SCRATCH, bios_7_scratch);
+}
+
+void
+radeon_combios_output_lock(struct drm_encoder *encoder, bool lock)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t bios_6_scratch;
+
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       if (lock)
+               bios_6_scratch |= RADEON_DRIVER_CRITICAL;
+       else
+               bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
+
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+}
index 32f969a..7b2d7c4 100644 (file)
@@ -66,6 +66,7 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
 
 static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
 {
+       // check acpi lid status ???
        return connector_status_connected;
 }
 
@@ -240,7 +241,7 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
        }
 
        /* see if we have a default encoder  TODO */
-       
+
        /* then check use digitial */
        /* pick the first one */
        if (enc_id) {
index 39eb91e..2877cd3 100644 (file)
@@ -600,4 +600,3 @@ void radeon_modeset_cleanup(struct drm_device *dev)
 {
        drm_mode_config_cleanup(dev);
 }
-
index 04c5709..ec36e43 100644 (file)
@@ -134,7 +134,6 @@ static void atombios_display_device_control(struct drm_encoder *encoder, int ind
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-
 static void atombios_scaler_setup(struct drm_encoder *encoder, struct drm_display_mode *mode)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -213,7 +212,7 @@ void atombios_set_crtc_source(struct drm_encoder *encoder, int source)
        default:
                return;
        }
-       
+
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)param);
 
 }
@@ -264,7 +263,7 @@ static void radeon_lvtma_mode_set(struct drm_encoder *encoder,
        else
                args.ucMisc = 0;
        args.usPixelClock = cpu_to_le16(adjusted_mode->clock / 10);
-       
+
        printk("executing set LVDS encoder\n");
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -273,18 +272,44 @@ static void radeon_lvtma_mode_set(struct drm_encoder *encoder,
 static void radeon_lvtma_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        int index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+       uint32_t bios_2_scratch, bios_3_scratch;
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               bios_2_scratch = RADEON_READ(R600_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(R600_BIOS_3_SCRATCH);
+       } else {
+               bios_2_scratch = RADEON_READ(RADEON_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(RADEON_BIOS_3_SCRATCH);
+       }
+
+       bios_2_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
+       bios_3_scratch |= (radeon_crtc->crtc_id << 17);
 
        switch(mode) {
        case DRM_MODE_DPMS_ON:
                atombios_display_device_control(encoder, index, ATOM_ENABLE);
+               bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
+               bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                atombios_display_device_control(encoder, index, ATOM_DISABLE);
+               bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
+               bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
                break;
        }
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               RADEON_WRITE(R600_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(R600_BIOS_3_SCRATCH, bios_3_scratch);
+       } else {
+               RADEON_WRITE(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
+       }
 }
 
 static bool radeon_lvtma_mode_fixup(struct drm_encoder *encoder,
@@ -297,18 +322,20 @@ static bool radeon_lvtma_mode_fixup(struct drm_encoder *encoder,
 
        if (radeon_encoder->rmx_type != RMX_OFF)
                radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
-       
+
        return true;
 }
 
 static void radeon_lvtma_prepare(struct drm_encoder *encoder)
 {
+       radeon_atom_output_lock(encoder, true);
        radeon_lvtma_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_lvtma_commit(struct drm_encoder *encoder)
 {
        radeon_lvtma_dpms(encoder, DRM_MODE_DPMS_ON);
+       radeon_atom_output_lock(encoder, false);
 }
 
 static const struct drm_encoder_helper_funcs radeon_atom_lvtma_helper_funcs = {
@@ -366,25 +393,91 @@ static void radeon_atom_dac_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        int atom_type = -1;
        int index;
+       uint32_t bios_2_scratch, bios_3_scratch;
 
        atom_type = atom_dac_find_atom_type(radeon_encoder, NULL);
        if (atom_type == -1)
                return;
-       
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               bios_2_scratch = RADEON_READ(R600_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(R600_BIOS_3_SCRATCH);
+       } else {
+               bios_2_scratch = RADEON_READ(RADEON_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(RADEON_BIOS_3_SCRATCH);
+       }
+
        switch(atom_type) {
        case ATOM_DEVICE_CRT1_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
+               bios_2_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 16);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
+                       break;
+               }
                break;
        case ATOM_DEVICE_CRT2_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
+               bios_2_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 20);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
+                       break;
+               }
                break;
        case ATOM_DEVICE_TV1_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+               bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 18);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
+                       break;
+               }
                break;
        case ATOM_DEVICE_CV_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+               bios_2_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 24);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_CV_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
+                       break;
+               }
                break;
        default:
                return;
@@ -394,12 +487,20 @@ static void radeon_atom_dac_dpms(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_ON:
                atombios_display_device_control(encoder, index, ATOM_ENABLE);
                break;
-       case DRM_MODE_DPMS_STANDBY:     
+       case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                atombios_display_device_control(encoder, index, ATOM_DISABLE);
                break;
        }
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               RADEON_WRITE(R600_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(R600_BIOS_3_SCRATCH, bios_3_scratch);
+       } else {
+               RADEON_WRITE(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
+       }
 }
 
 static bool radeon_atom_dac_mode_fixup(struct drm_encoder *encoder,
@@ -411,12 +512,14 @@ static bool radeon_atom_dac_mode_fixup(struct drm_encoder *encoder,
 
 static void radeon_atom_dac_prepare(struct drm_encoder *encoder)
 {
+       radeon_atom_output_lock(encoder, true);
        radeon_atom_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_atom_dac_commit(struct drm_encoder *encoder)
 {
        radeon_atom_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+       radeon_atom_output_lock(encoder, false);
 }
 
 static int atombios_dac_setup(struct drm_encoder *encoder,
@@ -447,7 +550,7 @@ static int atombios_dac_setup(struct drm_encoder *encoder,
                args.ucDacStandard = id ? ATOM_DAC2_NTSC : ATOM_DAC1_NTSC;
        /* TODO PAL */
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
-       
+
        return 0;
 }
 
@@ -471,7 +574,7 @@ static int atombios_tv1_setup(struct drm_encoder *encoder,
        }
 
        args.sTVEncoder.usPixelClock = cpu_to_le16(mode->clock / 10);
-       
+
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
        return 0;
 }
@@ -496,7 +599,7 @@ static void radeon_atom_dac_mode_set(struct drm_encoder *encoder,
        if ((atom_type == ATOM_DEVICE_TV1_INDEX) ||
            (atom_type == ATOM_DEVICE_CV_INDEX))
                atombios_tv1_setup(encoder, adjusted_mode, atom_type);
-       
+
 }
 
 static bool atom_dac_load_detect(struct drm_encoder *encoder, int atom_devices)
@@ -525,11 +628,11 @@ static bool atom_dac_load_detect(struct drm_encoder *encoder, int atom_devices)
                        args.sDacload.ucMisc = 1;
        } else
                return false;
-       
+
        DRM_DEBUG("writing %x %x\n", args.sDacload.usDeviceID, args.sDacload.ucDacType);
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
        return true;
-}       
+}
 
 static enum drm_connector_status radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
@@ -551,7 +654,7 @@ static enum drm_connector_status radeon_atom_dac_detect(struct drm_encoder *enco
        }
 
 
-       if (dev_priv->chip_family >= CHIP_R600) 
+       if (dev_priv->chip_family >= CHIP_R600)
                bios_0_scratch = RADEON_READ(R600_BIOS_0_SCRATCH);
        else
                bios_0_scratch = RADEON_READ(RADEON_BIOS_0_SCRATCH);
@@ -607,7 +710,7 @@ static void atombios_tmds1_setup(struct drm_encoder *encoder,
 
        args.usPixelClock = cpu_to_le16(mode->clock / 10);
 
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 static void atombios_tmds2_setup(struct drm_encoder *encoder,
@@ -628,7 +731,7 @@ static void atombios_tmds2_setup(struct drm_encoder *encoder,
 
        args.usPixelClock = cpu_to_le16(mode->clock / 10);
 
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 
@@ -652,7 +755,7 @@ static void atombios_ext_tmds_setup(struct drm_encoder *encoder,
        // TODO 6-bit DAC
 //     args.usPixelClock = cpu_to_le16(mode->clock / 10);
 
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 static void atombios_dig1_setup(struct drm_encoder *encoder,
@@ -680,7 +783,7 @@ static void atombios_dig1_setup(struct drm_encoder *encoder,
        }
 
        // TODO Encoder MODE
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 static void atombios_ddia_setup(struct drm_encoder *encoder,
@@ -699,7 +802,7 @@ static void atombios_ddia_setup(struct drm_encoder *encoder,
        else
                args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = 0;
 
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args); 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios_index, int dac_type, int with_tv)
@@ -760,8 +863,10 @@ static void radeon_atom_tmds_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        int atom_type = -1;
        int index = -1;
+       uint32_t bios_2_scratch, bios_3_scratch;
 
        if (radeon_encoder->atom_device & ATOM_DEVICE_DFP1_SUPPORT)
                atom_type = ATOM_DEVICE_DFP1_INDEX;
@@ -773,15 +878,65 @@ static void radeon_atom_tmds_dpms(struct drm_encoder *encoder, int mode)
        if (atom_type == -1)
                return;
 
+       if (dev_priv->chip_family >= CHIP_R600) {
+               bios_2_scratch = RADEON_READ(R600_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(R600_BIOS_3_SCRATCH);
+       } else {
+               bios_2_scratch = RADEON_READ(RADEON_BIOS_2_SCRATCH);
+               bios_3_scratch = RADEON_READ(RADEON_BIOS_3_SCRATCH);
+       }
+
        switch(atom_type) {
        case ATOM_DEVICE_DFP1_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
+               bios_2_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 19);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
+                       break;
+               }
                break;
        case ATOM_DEVICE_DFP2_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               bios_2_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 23);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
+                       break;
+               }
                break;
        case ATOM_DEVICE_DFP3_INDEX:
                index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
+               bios_2_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
+               bios_3_scratch |= (radeon_crtc->crtc_id << 25);
+               switch(mode) {
+               case DRM_MODE_DPMS_ON:
+                       bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
+                       bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
+                       break;
+               case DRM_MODE_DPMS_STANDBY:
+               case DRM_MODE_DPMS_SUSPEND:
+               case DRM_MODE_DPMS_OFF:
+                       bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
+                       bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
+                       break;
+               }
                break;
        }
 
@@ -798,6 +953,14 @@ static void radeon_atom_tmds_dpms(struct drm_encoder *encoder, int mode)
                atombios_display_device_control(encoder, index, ATOM_DISABLE);
                break;
        }
+
+       if (dev_priv->chip_family >= CHIP_R600) {
+               RADEON_WRITE(R600_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(R600_BIOS_3_SCRATCH, bios_3_scratch);
+       } else {
+               RADEON_WRITE(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+               RADEON_WRITE(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
+       }
 }
 
 static bool radeon_atom_tmds_mode_fixup(struct drm_encoder *encoder,
@@ -845,12 +1008,14 @@ static void radeon_atom_tmds_mode_set(struct drm_encoder *encoder,
 
 static void radeon_atom_tmds_prepare(struct drm_encoder *encoder)
 {
+       radeon_atom_output_lock(encoder, true);
        radeon_atom_tmds_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_atom_tmds_commit(struct drm_encoder *encoder)
 {
        radeon_atom_tmds_dpms(encoder, DRM_MODE_DPMS_ON);
+       radeon_atom_output_lock(encoder, false);
 }
 
 static const struct drm_encoder_helper_funcs radeon_atom_tmds_helper_funcs = {
@@ -894,4 +1059,3 @@ struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bio
        radeon_encoder->atom_device &= analog_enc_mask;
        return encoder;
 }
-
index 6a7529c..d572008 100644 (file)
@@ -225,7 +225,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
        args->addr_ptr = (uint64_t) addr;
 
        return 0;
-       
+
 }
 
 int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
index 48cdd18..6452154 100644 (file)
@@ -197,10 +197,19 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
+       uint32_t bios_5_scratch, bios_6_scratch;
 
        DRM_DEBUG("\n");
 
+       // FIXME atom/legacy cards like r4xx
+       bios_5_scratch = RADEON_READ(RADEON_BIOS_5_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
+       bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_LCD1_CRTC_SHIFT);
+
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                disp_pwr_man = RADEON_READ(RADEON_DISP_PWR_MAN);
@@ -228,6 +237,11 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
                /* enable backlight */
                lvds_gen_cntl |= RADEON_LVDS_BLON;
                RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+
+               /* update bios scratch regs */
+               bios_5_scratch |= RADEON_LCD1_ON;
+               bios_6_scratch |= RADEON_LCD_DPMS_ON;
+
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
@@ -239,18 +253,27 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
                 lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
                 RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
                RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl);
+
+               bios_5_scratch &= ~RADEON_LCD1_ON;
+               bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
                break;
        }
+       RADEON_WRITE(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
 
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
        radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
 {
        radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, false);
 }
 
 static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
@@ -372,9 +395,20 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
 {
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        uint32_t crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL);
        uint32_t dac_cntl = RADEON_READ(RADEON_DAC_CNTL);
        uint32_t dac_macro_cntl = RADEON_READ(RADEON_DAC_MACRO_CNTL);
+       uint32_t bios_5_scratch, bios_6_scratch;
+
+       DRM_DEBUG("\n");
+
+       // FIXME atom/legacy cards like r4xx
+       bios_5_scratch = RADEON_READ(RADEON_BIOS_5_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
+       bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT1_CRTC_SHIFT);
 
        DRM_DEBUG("\n");
 
@@ -385,6 +419,8 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
                                    RADEON_DAC_PDWN_G |
                                    RADEON_DAC_PDWN_B);
+               bios_5_scratch |= RADEON_CRT1_ON;
+               bios_6_scratch |= RADEON_CRT_DPMS_ON;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
@@ -394,6 +430,8 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                dac_macro_cntl |= (RADEON_DAC_PDWN_R |
                                   RADEON_DAC_PDWN_G |
                                   RADEON_DAC_PDWN_B);
+               bios_5_scratch &= ~RADEON_CRT1_ON;
+               bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
                break;
        }
 
@@ -401,16 +439,22 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
        RADEON_WRITE(RADEON_DAC_CNTL, dac_cntl);
        RADEON_WRITE(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
 
+       RADEON_WRITE(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
 
 static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
 {
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
        radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
 {
        radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, false);
 }
 
 static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
@@ -527,32 +571,52 @@ static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        uint32_t fp_gen_cntl = RADEON_READ(RADEON_FP_GEN_CNTL);
+       uint32_t bios_5_scratch, bios_6_scratch;
 
        DRM_DEBUG("\n");
 
+       // FIXME atom/legacy cards like r4xx
+       bios_5_scratch = RADEON_READ(RADEON_BIOS_5_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
+       bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP1_CRTC_SHIFT);
+
        switch(mode) {
        case DRM_MODE_DPMS_ON:
                 fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+               bios_5_scratch |= RADEON_DFP1_ON;
+               bios_6_scratch |= RADEON_DFP_DPMS_ON;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+               bios_5_scratch &= ~RADEON_DFP1_ON;
+               bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
                break;
        }
 
        RADEON_WRITE(RADEON_FP_GEN_CNTL, fp_gen_cntl);
+
+       RADEON_WRITE(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
 
 static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
 {
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
        radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
 {
        radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
 }
 
 static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
@@ -691,34 +755,54 @@ static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        uint32_t fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL);
+       uint32_t bios_5_scratch, bios_6_scratch;
 
        DRM_DEBUG("\n");
 
+       // FIXME atom/legacy cards like r4xx
+       bios_5_scratch = RADEON_READ(RADEON_BIOS_5_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
+       bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP2_CRTC_SHIFT);
+
        switch(mode) {
        case DRM_MODE_DPMS_ON:
                fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
                fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+               bios_5_scratch |= RADEON_DFP2_ON;
+               bios_6_scratch |= RADEON_DFP_DPMS_ON;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
                fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+               bios_5_scratch &= ~RADEON_DFP2_ON;
+               bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
                break;
        }
 
        RADEON_WRITE(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+
+       RADEON_WRITE(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
 
 static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
 {
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
        radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
 {
        radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, false);
 }
 
 static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
@@ -827,11 +911,23 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
        //uint32_t tv_master_cntl = 0;
+       uint32_t bios_5_scratch, bios_6_scratch;
 
        DRM_DEBUG("\n");
 
+       // FIXME atom/legacy cards like r4xx
+       bios_5_scratch = RADEON_READ(RADEON_BIOS_5_SCRATCH);
+       bios_6_scratch = RADEON_READ(RADEON_BIOS_6_SCRATCH);
+
+       bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
+       bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT2_CRTC_SHIFT);
+       // FIXME TV
+       //bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
+       //bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_TV1_CRTC_SHIFT);
+
        if (dev_priv->chip_family == CHIP_R200)
                fp2_gen_cntl = RADEON_READ(RADEON_FP2_GEN_CNTL);
        else {
@@ -860,6 +956,10 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
                                                 RADEON_TV_DAC_BDACPD |
                                                 RADEON_TV_DAC_BGSLEEP);
                }
+               //bios_5_scratch |= RADEON_TV1_ON;
+               //bios_6_scratch |= RADEON_TV_DPMS_ON;
+               bios_5_scratch |= RADEON_CRT2_ON;
+               bios_6_scratch |= RADEON_CRT_DPMS_ON;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
@@ -881,6 +981,10 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
                                                RADEON_TV_DAC_BDACPD |
                                                RADEON_TV_DAC_BGSLEEP);
                }
+               //bios_5_scratch &= ~RADEON_TV1_ON;
+               //bios_6_scratch &= ~RADEON_TV_DPMS_ON;
+               bios_5_scratch &= ~RADEON_CRT2_ON;
+               bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
                break;
        }
 
@@ -892,16 +996,22 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
                RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl);
        }
 
+       RADEON_WRITE(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+       RADEON_WRITE(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
 }
 
 static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
 {
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, true);
        radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
 {
        radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+       // fix me: atom/legacy r4xx
+       radeon_combios_output_lock(encoder, false);
 }
 
 static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
index 7278c42..d7c60fa 100644 (file)
@@ -293,6 +293,10 @@ extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder);
 extern bool radeon_combios_get_tv_info(struct radeon_encoder *encoder);
 extern bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
 extern bool radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder);
+extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
+extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
+extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
+extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev);
 extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                     u16 blue, int regno);
 struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev,
@@ -311,6 +315,7 @@ void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_stat
 
 void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable);
 void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable);
+void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable);
 void radeon_get_clock_info(struct drm_device *dev);
 extern bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device *dev);
 
index e30696f..6b71360 100644 (file)
@@ -2409,8 +2409,12 @@ int radeon_modeset_preinit(struct drm_device *dev)
 
        if (dev_priv->is_atom_bios) {
                dev_priv->mode_info.atom_context = atom_parse(&card, dev_priv->bios);
-       }
+               radeon_atom_initialize_bios_scratch_regs(dev);
+       } else
+               radeon_combios_initialize_bios_scratch_regs(dev);
+
        radeon_get_clock_info(dev);
+
        return 0;
 }