OSDN Git Service

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Jun 2011 00:54:41 +0000 (17:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Jun 2011 00:54:41 +0000 (17:54 -0700)
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/radeon/kms: use helper functions for fence read/write
  drm/radeon/kms: set DP link config properly for DP bridges
  drm/radeon/kms/atom: AdjustPixelClock fixes for DP bridges
  drm/radeon/kms: fix handling of DP to LVDS bridges
  drm/radeon/kms: issue blank/unblank commands for ext encoders
  drm/radeon/kms: fix support for DDC on dp bridges
  drm/radeon/kms: add support for load detection on dp bridges
  drm/radeon/kms: add missing external encoder action
  drm/radeon/kms: rework atombios_get_encoder_mode()
  drm/radeon/kms: fix num crtcs for Cedar and Caicos
  Revert "drm/i915: Enable GMBUS for post-gen2 chipsets"
  drivers/gpu/drm: use printk_ratelimited instead of printk_ratelimit
  drm/radeon: workaround a hw bug on some radeon chipsets with all-0 EDIDs.
  drm: make debug levels match in edid failure code.
  drm/radeon/kms: clear wb memory by default
  drm/radeon/kms: be more pedantic about the g5 quirk (v2)
  drm/radeon/kms: signed fix for evergreen thermal
  drm: populate irq_by_busid-member for pci

15 files changed:
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/radeon/atombios.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_mode.h
include/drm/drm_crtc.h

index 0a9357c..0929219 100644 (file)
@@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)
 
 bad:
        if (raw_edid) {
-               DRM_ERROR("Raw EDID:\n");
+               printk(KERN_ERR "Raw EDID:\n");
                print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
-               printk("\n");
+               printk(KERN_ERR "\n");
        }
        return 0;
 }
@@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
        return ret == 2 ? 0 : -1;
 }
 
+static bool drm_edid_is_zero(u8 *in_edid, int length)
+{
+       int i;
+       u32 *raw_edid = (u32 *)in_edid;
+
+       for (i = 0; i < length / 4; i++)
+               if (*(raw_edid + i) != 0)
+                       return false;
+       return true;
+}
+
 static u8 *
 drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
@@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
                        goto out;
                if (drm_edid_block_valid(block))
                        break;
+               if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
+                       connector->null_edid_counter++;
+                       goto carp;
+               }
        }
        if (i == 4)
                goto carp;
index d61d185..4a058c7 100644 (file)
@@ -28,6 +28,7 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
+#include <linux/ratelimit.h>
 
 #include "drmP.h"
 #include "drm_core.h"
@@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
                return -EFAULT;
 
        m32.handle = (unsigned long)handle;
-       if (m32.handle != (unsigned long)handle && printk_ratelimit())
-               printk(KERN_ERR "compat_drm_addmap truncated handle"
-                      " %p for type %d offset %x\n",
-                      handle, m32.type, m32.offset);
+       if (m32.handle != (unsigned long)handle)
+               printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
+                                  " %p for type %d offset %x\n",
+                                  handle, m32.type, m32.offset);
 
        if (copy_to_user(argp, &m32, sizeof(m32)))
                return -EFAULT;
index e1aee4f..b6a19cb 100644 (file)
@@ -251,7 +251,7 @@ err:
 }
 
 
-int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
 {
        if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
            (p->busnum & 0xff) != dev->pdev->bus->number ||
@@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {
        .get_name = drm_pci_get_name,
        .set_busid = drm_pci_set_busid,
        .set_unique = drm_pci_set_unique,
+       .irq_by_busid = drm_pci_irq_by_busid,
        .agp_init = drm_pci_agp_init,
 };
 
index d3b903b..d98cee6 100644 (file)
@@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)
                bus->reg0 = i | GMBUS_RATE_100KHZ;
 
                /* XXX force bit banging until GMBUS is fully debugged */
-               if (IS_GEN2(dev))
-                       bus->force_bit = intel_gpio_create(dev_priv, i);
+               bus->force_bit = intel_gpio_create(dev_priv, i);
        }
 
        intel_i2c_reset(dev_priv->dev);
index 49611e2..1b50ad8 100644 (file)
@@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3
 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF   0x10
 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING       0x11
 #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION      0x12
+#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP              0x14
 
 // ucConfig
 #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK                             0x03
index 84a69e7..9541995 100644 (file)
@@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                                                DISPPLL_CONFIG_DUAL_LINK;
                                        }
                                }
+                               if (radeon_encoder_is_dp_bridge(encoder)) {
+                                       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+                                       struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
+                                       args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
+                               } else
+                                       args.v3.sInput.ucExtTransmitterID = 0;
+
                                atom_execute_table(rdev->mode_info.atom_context,
                                                   index, (uint32_t *)&args);
                                adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
index 86157b1..7e3d96e 100644 (file)
@@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 /* get temperature in millidegrees */
 int evergreen_get_temp(struct radeon_device *rdev)
 {
-       u32 temp, toffset, actual_temp = 0;
+       u32 temp, toffset;
+       int actual_temp = 0;
 
        if (rdev->family == CHIP_JUNIPER) {
                toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>
index 9bd162f..b244962 100644 (file)
@@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = {
 int radeon_asic_init(struct radeon_device *rdev)
 {
        radeon_register_accessor_init(rdev);
+
+       /* set the number of crtcs */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               rdev->num_crtc = 1;
+       else
+               rdev->num_crtc = 2;
+
        switch (rdev->family) {
        case CHIP_R100:
        case CHIP_RV100:
@@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_JUNIPER:
        case CHIP_CYPRESS:
        case CHIP_HEMLOCK:
+               /* set num crtcs */
+               if (rdev->family == CHIP_CEDAR)
+                       rdev->num_crtc = 4;
+               else
+                       rdev->num_crtc = 6;
                rdev->asic = &evergreen_asic;
                break;
        case CHIP_PALM:
@@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_BARTS:
        case CHIP_TURKS:
        case CHIP_CAICOS:
+               /* set num crtcs */
+               if (rdev->family == CHIP_CAICOS)
+                       rdev->num_crtc = 4;
+               else
+                       rdev->num_crtc = 6;
                rdev->asic = &btc_asic;
                break;
        case CHIP_CAYMAN:
                rdev->asic = &cayman_asic;
+               /* set num crtcs */
+               rdev->num_crtc = 6;
                break;
        default:
                /* FIXME: not supported yet */
@@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev)
                rdev->asic->set_memory_clock = NULL;
        }
 
-       /* set the number of crtcs */
-       if (rdev->flags & RADEON_SINGLE_CRTC)
-               rdev->num_crtc = 1;
-       else {
-               if (ASIC_IS_DCE41(rdev))
-                       rdev->num_crtc = 2;
-               else if (ASIC_IS_DCE4(rdev))
-                       rdev->num_crtc = 6;
-               else
-                       rdev->num_crtc = 2;
-       }
-
        return 0;
 }
 
index 797c8bc..e459467 100644 (file)
@@ -1553,9 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                           (rdev->pdev->subsystem_device == 0x4a48)) {
                        /* Mac X800 */
                        rdev->mode_info.connector_table = CT_MAC_X800;
-               } else if (of_machine_is_compatible("PowerMac7,2") ||
-                          of_machine_is_compatible("PowerMac7,3")) {
-                       /* Mac G5 9600 */
+               } else if ((of_machine_is_compatible("PowerMac7,2") ||
+                           of_machine_is_compatible("PowerMac7,3")) &&
+                          (rdev->pdev->device == 0x4150) &&
+                          (rdev->pdev->subsystem_vendor == 0x1002) &&
+                          (rdev->pdev->subsystem_device == 0x4150)) {
+                       /* Mac G5 tower 9600 */
                        rdev->mode_info.connector_table = CT_MAC_G5_9600;
                } else
 #endif /* CONFIG_PPC_PMAC */
index 9c2929c..cbfca3a 100644 (file)
@@ -44,6 +44,8 @@ extern void
 radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
                             struct drm_connector *drm_connector);
 
+bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
@@ -836,6 +838,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                if (!radeon_connector->edid) {
                        DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
                                        drm_get_connector_name(connector));
+                       /* rs690 seems to have a problem with connectors not existing and always
+                        * return a block of 0's. If we see this just stop polling on this output */
+                       if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
+                               ret = connector_status_disconnected;
+                               DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
+                               radeon_connector->ddc_bus = NULL;
+                       }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
@@ -1063,10 +1072,11 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        int ret;
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
-               struct drm_encoder *encoder;
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                struct drm_display_mode *mode;
 
                if (!radeon_dig_connector->edp_on)
@@ -1078,7 +1088,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
 
                if (ret > 0) {
-                       encoder = radeon_best_single_encoder(connector);
                        if (encoder) {
                                radeon_fixup_lvds_native_mode(encoder, connector);
                                /* add scaled modes */
@@ -1102,8 +1111,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
                        /* add scaled modes */
                        radeon_add_common_modes(encoder, connector);
                }
-       } else
+       } else {
+               /* need to setup ddc on the bridge */
+               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+                       if (encoder)
+                               radeon_atom_ext_encoder_setup_ddc(encoder);
+               }
                ret = radeon_ddc_get_modes(radeon_connector);
+       }
 
        return ret;
 }
@@ -1187,14 +1202,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        enum drm_connector_status ret = connector_status_disconnected;
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 
        if (radeon_connector->edid) {
                kfree(radeon_connector->edid);
                radeon_connector->edid = NULL;
        }
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
-               struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                if (encoder) {
                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
                        struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
@@ -1214,6 +1230,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                        atombios_set_edp_panel_power(connector,
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
        } else {
+               /* need to setup ddc on the bridge */
+               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+                       if (encoder)
+                               radeon_atom_ext_encoder_setup_ddc(encoder);
+               }
                radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
                if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                        ret = connector_status_connected;
@@ -1228,6 +1249,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                        ret = connector_status_connected;
                        }
                }
+
+               if ((ret == connector_status_disconnected) &&
+                   radeon_connector->dac_load_detect) {
+                       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+                       struct drm_encoder_helper_funcs *encoder_funcs;
+                       if (encoder) {
+                               encoder_funcs = encoder->helper_private;
+                               ret = encoder_funcs->detect(encoder, connector);
+                       }
+               }
        }
 
        radeon_connector_update_scratch_regs(connector, ret);
@@ -1242,7 +1273,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
 
        /* XXX check mode bandwidth */
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 
                if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
@@ -1252,7 +1284,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
                        struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
 
-               /* AVIVO hardware supports downscaling modes larger than the panel
+                       /* AVIVO hardware supports downscaling modes larger than the panel
                         * to the panel size, but I'm not sure this is desirable.
                         */
                        if ((mode->hdisplay > native_mode->hdisplay) ||
@@ -1401,6 +1433,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                default:
                        connector->interlace_allowed = true;
                        connector->doublescan_allowed = true;
+                       radeon_connector->dac_load_detect = true;
+                       drm_connector_attach_property(&radeon_connector->base,
+                                                     rdev->mode_info.load_detect_property,
+                                                     1);
                        break;
                case DRM_MODE_CONNECTOR_DVII:
                case DRM_MODE_CONNECTOR_DVID:
@@ -1422,6 +1458,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                                connector->doublescan_allowed = true;
                        else
                                connector->doublescan_allowed = false;
+                       if (connector_type == DRM_MODE_CONNECTOR_DVII) {
+                               radeon_connector->dac_load_detect = true;
+                               drm_connector_attach_property(&radeon_connector->base,
+                                                             rdev->mode_info.load_detect_property,
+                                                             1);
+                       }
                        break;
                case DRM_MODE_CONNECTOR_LVDS:
                case DRM_MODE_CONNECTOR_eDP:
index e680501..7cfaa7e 100644 (file)
@@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev)
                return r;
        }
 
+       /* clear wb memory */
+       memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE);
        /* disable event_write fences */
        rdev->wb.use_event = false;
        /* disabled via module param */
index 03f124d..f55b64c 100644 (file)
@@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
        }
 
        if (ASIC_IS_DCE3(rdev) &&
-           (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
+           ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+            radeon_encoder_is_dp_bridge(encoder))) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                radeon_dp_set_link_config(connector, mode);
        }
@@ -660,21 +661,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        if (radeon_encoder_is_dp_bridge(encoder))
                return ATOM_ENCODER_MODE_DP;
 
+       /* DVO is always DVO */
+       if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
+               return ATOM_ENCODER_MODE_DVO;
+
        connector = radeon_get_connector_for_encoder(encoder);
-       if (!connector) {
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-                       return ATOM_ENCODER_MODE_DVI;
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               default:
-                       return ATOM_ENCODER_MODE_CRT;
-               }
-       }
+       /* if we don't have an active device yet, just use one of
+        * the connectors tied to the encoder.
+        */
+       if (!connector)
+               connector = radeon_get_connector_for_encoder_init(encoder);
        radeon_connector = to_radeon_connector(connector);
 
        switch (connector->connector_type) {
@@ -1526,26 +1522,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        }
 
        if (ext_encoder) {
-               int action;
-
                switch (mode) {
                case DRM_MODE_DPMS_ON:
                default:
-                       if (ASIC_IS_DCE41(rdev))
-                               action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
-                       else
-                               action = ATOM_ENABLE;
+                       if (ASIC_IS_DCE41(rdev)) {
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
+                       } else
+                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
-                       if (ASIC_IS_DCE41(rdev))
-                               action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
-                       else
-                               action = ATOM_DISABLE;
+                       if (ASIC_IS_DCE41(rdev)) {
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
+                       } else
+                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
                        break;
                }
-               atombios_external_encoder_setup(encoder, ext_encoder, action);
        }
 
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
@@ -2004,6 +2003,65 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
        return connector_status_disconnected;
 }
 
+static enum drm_connector_status
+radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+       u32 bios_0_scratch;
+
+       if (!ASIC_IS_DCE4(rdev))
+               return connector_status_unknown;
+
+       if (!ext_encoder)
+               return connector_status_unknown;
+
+       if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
+               return connector_status_unknown;
+
+       /* load detect on the dp bridge */
+       atombios_external_encoder_setup(encoder, ext_encoder,
+                                       EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
+
+       bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+
+       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+                       return connector_status_connected; /* CTV */
+               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+                       return connector_status_connected; /* STV */
+       }
+       return connector_status_disconnected;
+}
+
+void
+radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
+{
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+
+       if (ext_encoder)
+               /* ddc_setup on the dp bridge */
+               atombios_external_encoder_setup(encoder, ext_encoder,
+                                               EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
+
+}
+
 static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -2167,7 +2225,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
        .mode_set = radeon_atom_encoder_mode_set,
        .commit = radeon_atom_encoder_commit,
        .disable = radeon_atom_encoder_disable,
-       /* no detect for TMDS/LVDS yet */
+       .detect = radeon_atom_dig_detect,
 };
 
 static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
index 1f82294..021d2b6 100644 (file)
 #include "radeon.h"
 #include "radeon_trace.h"
 
+static void radeon_fence_write(struct radeon_device *rdev, u32 seq)
+{
+       if (rdev->wb.enabled) {
+               u32 scratch_index;
+               if (rdev->wb.use_event)
+                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               else
+                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
+       } else
+               WREG32(rdev->fence_drv.scratch_reg, seq);
+}
+
+static u32 radeon_fence_read(struct radeon_device *rdev)
+{
+       u32 seq;
+
+       if (rdev->wb.enabled) {
+               u32 scratch_index;
+               if (rdev->wb.use_event)
+                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               else
+                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
+       } else
+               seq = RREG32(rdev->fence_drv.scratch_reg);
+       return seq;
+}
+
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 {
        unsigned long irq_flags;
@@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
                return 0;
        }
        fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
-       if (!rdev->cp.ready) {
+       if (!rdev->cp.ready)
                /* FIXME: cp is not running assume everythings is done right
                 * away
                 */
-               WREG32(rdev->fence_drv.scratch_reg, fence->seq);
-       else
+               radeon_fence_write(rdev, fence->seq);
+       else
                radeon_fence_ring_emit(rdev, fence);
 
        trace_radeon_fence_emit(rdev->ddev, fence->seq);
@@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev)
        bool wake = false;
        unsigned long cjiffies;
 
-       if (rdev->wb.enabled) {
-               u32 scratch_index;
-               if (rdev->wb.use_event)
-                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-               else
-                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-               seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
-       } else
-               seq = RREG32(rdev->fence_drv.scratch_reg);
+       seq = radeon_fence_read(rdev);
        if (seq != rdev->fence_drv.last_seq) {
                rdev->fence_drv.last_seq = seq;
                rdev->fence_drv.last_jiffies = jiffies;
@@ -251,7 +272,7 @@ retry:
                        r = radeon_gpu_reset(rdev);
                        if (r)
                                return r;
-                       WREG32(rdev->fence_drv.scratch_reg, fence->seq);
+                       radeon_fence_write(rdev, fence->seq);
                        rdev->gpu_lockup = false;
                }
                timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
@@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
                write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
                return r;
        }
-       WREG32(rdev->fence_drv.scratch_reg, 0);
+       radeon_fence_write(rdev, 0);
        atomic_set(&rdev->fence_drv.seq, 0);
        INIT_LIST_HEAD(&rdev->fence_drv.created);
        INIT_LIST_HEAD(&rdev->fence_drv.emited);
@@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
        struct radeon_fence *fence;
 
        seq_printf(m, "Last signaled fence 0x%08X\n",
-                  RREG32(rdev->fence_drv.scratch_reg));
+                  radeon_fence_read(rdev));
        if (!list_empty(&rdev->fence_drv.emited)) {
                   fence = list_entry(rdev->fence_drv.emited.prev,
                                      struct radeon_fence, list);
index 977a341..6df4e3c 100644 (file)
@@ -483,6 +483,8 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev);
 extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
                                           int action, uint8_t lane_num,
                                           uint8_t lane_set);
+extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
+extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                                u8 write_byte, u8 *read_byte);
 
index 9573e0c..33d12f8 100644 (file)
@@ -520,6 +520,8 @@ struct drm_connector {
        uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
        uint32_t force_encoder_id;
        struct drm_encoder *encoder; /* currently active encoder */
+
+       int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
 };
 
 /**