radeon: pull in recent fixes from ddx
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 7 Oct 2008 18:10:39 +0000 (14:10 -0400)
committerAlex Deucher <alexdeucher@gmail.com>
Tue, 7 Oct 2008 18:10:39 +0000 (14:10 -0400)
- fixup atom digital encoder setup
- pull in add get edid (currently disabled due to
  lack of support for atom fb/scratch space)

linux-core/radeon_atombios.c
linux-core/radeon_combios.c
linux-core/radeon_encoders.c
linux-core/radeon_mode.h

index a763e76..6173227 100644 (file)
@@ -72,11 +72,66 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de
        i2c.get_data_mask = (1 <<  gpio.ucDataY_Shift);
        i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
        i2c.a_data_mask = (1 <<  gpio.ucDataA_Shift);
+       i2c.hw_line = gpio.sucI2cId.sbfAccess.bfI2C_LineMux;
+       i2c.hw_capable = gpio.sucI2cId.sbfAccess.bfHW_Capable;
        i2c.valid = true;
 
        return i2c;
 }
 
+#if 0
+// TODO fix atom FB/scratch space access
+struct edid *radeon_atom_get_edid(struct drm_connector *connector)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private;
+       struct radeon_mode_info *mode_info = &dev_priv->mode_info;
+       READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION edid_param;
+       int i2c_clock = 50;
+       int prescale;
+       unsigned char *raw_edid;
+       struct edid *edid = NULL;
+       int index = GetIndexIntoMasterTable(COMMAND, ReadEDIDFromHWAssistedI2C);
+
+       if (!radeon_connector->ddc_bus)
+               return edid;
+
+       if (!radeon_connector->ddc_bus->rec.hw_capable)
+               return edid;
+
+       if (info->atomBIOS->fbBase)
+               raw_edid = (unsigned char *)info->FB + info->atomBIOS->fbBase;
+       else if (info->atomBIOS->scratchBase)
+               raw_edid = (unsigned char *)info->atomBIOS->scratchBase;
+       else
+               return edid;
+
+       memset(raw_edid, 0, ATOM_EDID_RAW_DATASIZE);
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520)
+               prescale = (127 << 8) + (mode_info->sclk * 10) / (4 * 127 * i2c_clock);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600)
+               prescale = (((mode_info->sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
+       else
+               prescale = (mode_info->spll.reference_freq * 10) / i2c_clock;
+
+       edid_param.usPrescale = prescale;
+       edid_param.usVRAMAddress = 0;
+       edid_param.ucSlaveAddr = 0xa0;
+       edid_param.ucLineNumber = radeon_connector->ddc_bus->rec.hw_line;
+
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&edid_param);
+
+       if (raw_edid[1] == 0xff) {
+               edid = kmalloc(size_of(struct edid), GFP_KERNEL);
+               *edid = raw_edid;
+       }
+
+       return edid;
+
+}
+#endif
+
 static struct radeon_i2c_bus_rec radeon_parse_i2c_record(struct drm_device *dev, ATOM_I2C_RECORD *record)
 {
     return radeon_lookup_gpio(dev, record->sucI2cId.bfI2C_LineMux);
@@ -591,6 +646,8 @@ void radeon_atombios_get_lvds_info(struct radeon_encoder *encoder)
                encoder->voverplus = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
                encoder->vsync_width = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
                encoder->panel_pwr_delay = le16_to_cpu(lvds_info->info.usOffDelayInMs);
+               encoder->lvds_misc = lvds_info->info.ucLVDS_Misc;
+               encoder->lvds_ss_id = lvds_info->info.ucSS_Id;
        }
 }
 
index ae1ef2f..f89bf88 100644 (file)
@@ -385,6 +385,8 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
 {
        struct radeon_i2c_bus_rec i2c;
 
+       i2c.hw_line = 0;
+       i2c.hw_capable = false; // actually depends on chip
        i2c.mask_clk_mask = RADEON_GPIO_EN_1;
        i2c.mask_data_mask = RADEON_GPIO_EN_0;
        i2c.a_clk_mask = RADEON_GPIO_A_1;
index e5c95c9..87d9184 100644 (file)
@@ -228,58 +228,105 @@ void atombios_set_crtc_source(struct drm_encoder *encoder, int source)
 
 }
 
-static void radeon_dfp_disable_dither(struct drm_encoder *encoder, int device)
+static void atombios_output_digital_mode_set(struct drm_encoder *encoder,
+                                            int device,
+                                            struct drm_display_mode *mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_radeon_private *dev_priv = dev->dev_private;
-
-       if (!radeon_is_avivo(dev_priv))
-               return;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_radeon_private *dev_priv = encoder->dev->dev_private;
+       uint8_t frev, crev;
+       int index;
+       LVDS_ENCODER_CONTROL_PS_ALLOCATION args;
+       LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 args2;
+       uint32_t *param = NULL;
 
        switch (device) {
        case ATOM_DEVICE_DFP1_INDEX:
-               RADEON_WRITE(AVIVO_TMDSA_BIT_DEPTH_CONTROL, 0); /* TMDSA */
+               index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
                break;
-       case ATOM_DEVICE_DFP2_INDEX:
-               if ((dev_priv->chip_family == CHIP_RS600) ||
-                   (dev_priv->chip_family == CHIP_RS690) ||
-                   (dev_priv->chip_family == CHIP_RS740))
-                       RADEON_WRITE(AVIVO_DDIA_BIT_DEPTH_CONTROL, 0); /* DDIA */
-               else
-                       RADEON_WRITE(AVIVO_DVOA_BIT_DEPTH_CONTROL, 0); /* DVO */
+       case ATOM_DEVICE_LCD1_INDEX:
+               index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
                break;
-               /*case ATOM_DEVICE_LCD1_INDEX:*/ /* LVDS panels need dither enabled */
        case ATOM_DEVICE_DFP3_INDEX:
-               RADEON_WRITE(AVIVO_LVTMA_BIT_DEPTH_CONTROL, 0); /* LVTMA */
+               index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
                break;
        default:
+               return;
+       }
+
+       atom_parse_cmd_header(dev_priv->mode_info.atom_context, index, &frev, &crev);
+
+       switch (frev) {
+       case 0:
+       case 1:
+               switch (crev) {
+               case 0:
+               case 1:
+                       memset(&args, 0, sizeof(args));
+                       args.ucAction = PANEL_ENCODER_ACTION_ENABLE;
+                       // TODO HDMI
+                       //if (radeon_encoder->type == OUTPUT_HDMI)
+                               //disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+                       args.usPixelClock = cpu_to_le16(mode->clock / 10);
+                       if (device == ATOM_DEVICE_LCD1_INDEX) {
+                               if (radeon_encoder->lvds_misc & (1 << 0))
+                                       args.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               if (radeon_encoder->lvds_misc & (1 << 1))
+                                       args.ucMisc |= (1 << 1);
+                       } else {
+                               if (mode->clock > 165000)
+                                       args.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               // TODO 6-bit DAC
+                               args.ucMisc |= (1 << 1);
+                       }
+                       param = (uint32_t *)&args;
+                       break;
+               case 2:
+               case 3:
+                       memset(&args2, 0, sizeof(args2));
+                       args2.ucAction = PANEL_ENCODER_ACTION_ENABLE;
+                       if (crev == 3) {
+                               // TODO coherent mode
+                               //if (encoder->coherent_mode)
+                                       //args2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+                       }
+                       // TODO HDMI
+                       //if (radeon_encoder->type == OUTPUT_HDMI)
+                               //args2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+                       if (device == ATOM_DEVICE_LCD1_INDEX) {
+                               if (radeon_encoder->lvds_misc & (1 << 0))
+                                       args2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               if (radeon_encoder->lvds_misc & (1 << 5)) {
+                                       args2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+                                       if (radeon_encoder->lvds_misc & (1 << 1))
+                                               args2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+                               }
+                               if (radeon_encoder->lvds_misc & (1 << 6)) {
+                                       args2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+                                       if (radeon_encoder->lvds_misc & (1 << 1))
+                                               args2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+                               }
+                       } else {
+                               if (mode->clock > 165000)
+                                       args2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                       }
+                       param = (uint32_t *)&args2;
+                       break;
+               }
                break;
        }
-}
 
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)param);
+}
 
 static void radeon_lvtma_mode_set(struct drm_encoder *encoder,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_radeon_private *dev_priv = dev->dev_private;
-       LVDS_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
 
-       memset(&args, 0, sizeof(args));
        atombios_scaler_setup(encoder, mode);
        atombios_set_crtc_source(encoder, ATOM_DEVICE_LCD1_INDEX);
-
-       args.ucAction = 1;
-       if (adjusted_mode->clock > 165000)
-               args.ucMisc = 1;
-       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);
+       atombios_output_digital_mode_set(encoder, ATOM_DEVICE_LCD1_INDEX, adjusted_mode);
 }
 
 
@@ -287,7 +334,6 @@ 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;
        int index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
        uint32_t bios_2_scratch, bios_3_scratch;
        int crtc_id = 0;
@@ -593,7 +639,6 @@ static int atombios_tv1_setup(struct drm_encoder *encoder,
 {
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        TV_ENCODER_CONTROL_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
 
@@ -617,7 +662,6 @@ static void radeon_atom_dac_mode_set(struct drm_encoder *encoder,
                                     struct drm_display_mode *adjusted_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);
        int atom_type = -1;
 
@@ -724,69 +768,22 @@ static const struct drm_encoder_funcs radeon_atom_dac_enc_funcs = {
        . destroy = radeon_enc_destroy,
 };
 
-
-static void atombios_tmds1_setup(struct drm_encoder *encoder,
-                                struct drm_display_mode *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);
-       TMDS1_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
-
-       memset(&args, 0, sizeof(args));
-       args.ucAction = 1;
-       if (mode->clock > 165000)
-               args.ucMisc = 1;
-       else
-               args.ucMisc = 0;
-
-       args.usPixelClock = cpu_to_le16(mode->clock / 10);
-
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-static void atombios_tmds2_setup(struct drm_encoder *encoder,
-                                struct drm_display_mode *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);
-       TMDS2_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
-
-       memset(&args, 0, sizeof(args));
-       args.ucAction = 1;
-       if (mode->clock > 165000)
-               args.ucMisc = 1;
-       else
-               args.ucMisc = 0;
-
-       args.usPixelClock = cpu_to_le16(mode->clock / 10);
-
-       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-
 void atombios_ext_tmds_setup(struct drm_encoder *encoder,
                             struct drm_display_mode *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);
        ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
 
        memset(&args, 0, sizeof(args));
-       args.sXTmdsEncoder.ucEnable = 1;
+       args.sXTmdsEncoder.ucEnable = PANEL_ENCODER_ACTION_ENABLE;
 
        if (mode->clock > 165000)
-               args.sXTmdsEncoder.ucMisc = 1;
-       else
-               args.sXTmdsEncoder.ucMisc = 0;
+               args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
 
        // TODO 6-bit DAC
-//     args.usPixelClock = cpu_to_le16(mode->clock / 10);
+       args.sXTmdsEncoder.ucMisc |= (1 << 1);
 
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -799,7 +796,8 @@ static void atombios_dig1_setup(struct drm_encoder *encoder,
        DIG_ENCODER_CONTROL_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
 
-       args.ucAction = 1;
+       memset(&args, 0, sizeof(args));
+       args.ucAction = ATOM_ENABLE;
        args.usPixelClock = mode->clock / 10;
        args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
 
@@ -827,13 +825,12 @@ static void atombios_ddia_setup(struct drm_encoder *encoder,
        DVO_ENCODER_CONTROL_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
 
-       args.sDVOEncoder.ucAction = ATOM_ENABLE;
-       args.sDVOEncoder.usPixelClock = mode->clock / 10;
+       memset(&args, 0, sizeof(args));
+       args.sDVOEncoder.ucAction = PANEL_ENCODER_ACTION_ENABLE;
+       args.sDVOEncoder.usPixelClock = cpu_to_le16(mode->clock / 10);
 
        if (mode->clock > 165000)
                args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
-       else
-               args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = 0;
 
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -846,8 +843,10 @@ struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios
        struct drm_encoder *encoder;
        int type = with_tv ? DRM_MODE_ENCODER_TVDAC : DRM_MODE_ENCODER_DAC;
        int found = 0;
-       int digital_enc_mask = ~(ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | ATOM_DEVICE_DFP3_SUPPORT |
-                               ATOM_DEVICE_LCD1_SUPPORT);
+       int digital_enc_mask = ~(ATOM_DEVICE_DFP1_SUPPORT |
+                                ATOM_DEVICE_DFP2_SUPPORT |
+                                ATOM_DEVICE_DFP3_SUPPORT |
+                                ATOM_DEVICE_LCD1_SUPPORT);
        /* we may already have added this encoder */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
@@ -1036,7 +1035,7 @@ static void radeon_atom_tmds_mode_set(struct drm_encoder *encoder,
        atombios_set_crtc_source(encoder, atom_type);
 
        if (atom_type == ATOM_DEVICE_DFP1_INDEX)
-               atombios_tmds1_setup(encoder, adjusted_mode);
+               atombios_output_digital_mode_set(encoder, ATOM_DEVICE_DFP1_INDEX, adjusted_mode);
        if (atom_type == ATOM_DEVICE_DFP2_INDEX) {
                if ((dev_priv->chip_family == CHIP_RS600) ||
                    (dev_priv->chip_family == CHIP_RS690) ||
@@ -1046,10 +1045,7 @@ static void radeon_atom_tmds_mode_set(struct drm_encoder *encoder,
                        atombios_ext_tmds_setup(encoder, adjusted_mode);
        }
        if (atom_type == ATOM_DEVICE_DFP3_INDEX)
-               atombios_tmds2_setup(encoder, adjusted_mode);
-       radeon_dfp_disable_dither(encoder, atom_type);
-
-
+               atombios_output_digital_mode_set(encoder, ATOM_DEVICE_DFP3_INDEX, adjusted_mode);
 }
 
 static void radeon_atom_tmds_prepare(struct drm_encoder *encoder)
@@ -1085,7 +1081,7 @@ struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bio
        struct drm_encoder *encoder;
        int analog_enc_mask = ~(ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT);
 
-               radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+       radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
        if (!radeon_encoder) {
                return NULL;
        }
index fef2738..64608e3 100644 (file)
@@ -116,6 +116,8 @@ struct radeon_i2c_bus_rec {
        uint32_t get_data_mask;
        uint32_t a_clk_mask;
        uint32_t a_data_mask;
+       int hw_line;
+       bool hw_capable;
 };
 
 struct radeon_bios_connector {
@@ -227,6 +229,10 @@ struct radeon_encoder {
        bool use_bios_dividers;
        uint32_t lvds_gen_cntl;
 
+       /* atom lvds */
+       int lvds_misc;
+       int lvds_ss_id;
+
        /* legacy primary dac */
        uint32_t ps2_pdac_adj;