Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Jun 2012 08:44:41 +0000 (01:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Jun 2012 08:44:41 +0000 (01:44 -0700)
Pull drm fixes from Dave Airlie:
 "Radeon is most of the work, one regression, one BUG fix in the new
  prime code, some fixes to init code to make streamout not lock up the
  hardware, and just some code to enable users to test HDMI audio on
  later hw (its off by default).

  Intel adds edp edid caching for some strange Dell Vostros that black
  screen on startup if keep reading their EDID, and a fix for a DP
  regression.

  Otherwise fix for via/sis and one to stop udl binding to multiple
  non-video usb."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/i915: cache the EDID for eDP panels
  Revert "drm/i915/dp: Use auxch precharge value of 5 everywhere"
  drm/i915: eDP aux needs vdd
  drm/i915: don't enumerate HDMID if an eDP panel is already active on the port
  drm/radeon: add support for STRMOUT_BASE_UPDATE on 7xx
  drm/radeon: add some additional 6xx/7xx/EG register init
  drm/radeon: enable HDMI on DCE5 (AKA NI excluding Aruba)
  drm sis: initialize object_idr
  drm via: initialize object_idr
  drm/radeon/prime: reserve/unreserve around pin
  drm/radeon: fix regression in dynpm due to multi-ring rework
  vga_switcheroo.h: fix pci_dev warning
  drm/udl: only bind to the video devices on the hub.

21 files changed:
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_prime.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/via/via_map.c
include/linux/vga_switcheroo.h

index e0aa064..a7c727d 100644 (file)
@@ -6558,7 +6558,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                if (I915_READ(HDMIC) & PORT_DETECTED)
                        intel_hdmi_init(dev, HDMIC);
 
-               if (I915_READ(HDMID) & PORT_DETECTED)
+               if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
                        intel_hdmi_init(dev, HDMID);
 
                if (I915_READ(PCH_DP_C) & DP_DETECTED)
index 296cfc2..c044932 100644 (file)
@@ -32,6 +32,7 @@
 #include "drm.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -67,6 +68,8 @@ struct intel_dp {
        struct drm_display_mode *panel_fixed_mode;  /* for eDP */
        struct delayed_work panel_vdd_work;
        bool want_panel_vdd;
+       struct edid *edid; /* cached EDID for eDP */
+       int edid_mode_count;
 };
 
 /**
@@ -371,7 +374,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        int recv_bytes;
        uint32_t status;
        uint32_t aux_clock_divider;
-       int try, precharge = 5;
+       int try, precharge;
 
        intel_dp_check_edp(intel_dp);
        /* The clock divider is based off the hrawclk,
@@ -391,6 +394,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        else
                aux_clock_divider = intel_hrawclk(dev) / 2;
 
+       if (IS_GEN6(dev))
+               precharge = 3;
+       else
+               precharge = 5;
+
        /* Try to wait for any previous AUX channel activity */
        for (try = 0; try < 3; try++) {
                status = I915_READ(ch_ctl);
@@ -1973,6 +1981,8 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
        if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
                return;
 
+       ironlake_edp_panel_vdd_on(intel_dp);
+
        if (intel_dp_aux_native_read_retry(intel_dp, DP_SINK_OUI, buf, 3))
                DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
@@ -1980,6 +1990,8 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
        if (intel_dp_aux_native_read_retry(intel_dp, DP_BRANCH_OUI, buf, 3))
                DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
+
+       ironlake_edp_panel_vdd_off(intel_dp, false);
 }
 
 static bool
@@ -2116,10 +2128,22 @@ intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        struct edid     *edid;
+       int size;
+
+       if (is_edp(intel_dp)) {
+               if (!intel_dp->edid)
+                       return NULL;
+
+               size = (intel_dp->edid->extensions + 1) * EDID_LENGTH;
+               edid = kmalloc(size, GFP_KERNEL);
+               if (!edid)
+                       return NULL;
+
+               memcpy(edid, intel_dp->edid, size);
+               return edid;
+       }
 
-       ironlake_edp_panel_vdd_on(intel_dp);
        edid = drm_get_edid(connector, adapter);
-       ironlake_edp_panel_vdd_off(intel_dp, false);
        return edid;
 }
 
@@ -2129,9 +2153,17 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        int     ret;
 
-       ironlake_edp_panel_vdd_on(intel_dp);
+       if (is_edp(intel_dp)) {
+               drm_mode_connector_update_edid_property(connector,
+                                                       intel_dp->edid);
+               ret = drm_add_edid_modes(connector, intel_dp->edid);
+               drm_edid_to_eld(connector,
+                               intel_dp->edid);
+               connector->display_info.raw_edid = NULL;
+               return intel_dp->edid_mode_count;
+       }
+
        ret = intel_ddc_get_modes(connector, adapter);
-       ironlake_edp_panel_vdd_off(intel_dp, false);
        return ret;
 }
 
@@ -2321,6 +2353,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
        i2c_del_adapter(&intel_dp->adapter);
        drm_encoder_cleanup(encoder);
        if (is_edp(intel_dp)) {
+               kfree(intel_dp->edid);
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
                ironlake_panel_vdd_off_sync(intel_dp);
        }
@@ -2504,11 +2537,14 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
        }
 
+       intel_dp_i2c_init(intel_dp, intel_connector, name);
+
        /* Cache some DPCD data in the eDP case */
        if (is_edp(intel_dp)) {
                bool ret;
                struct edp_power_seq    cur, vbt;
                u32 pp_on, pp_off, pp_div;
+               struct edid *edid;
 
                pp_on = I915_READ(PCH_PP_ON_DELAYS);
                pp_off = I915_READ(PCH_PP_OFF_DELAYS);
@@ -2576,9 +2612,19 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        intel_dp_destroy(&intel_connector->base);
                        return;
                }
-       }
 
-       intel_dp_i2c_init(intel_dp, intel_connector, name);
+               ironlake_edp_panel_vdd_on(intel_dp);
+               edid = drm_get_edid(connector, &intel_dp->adapter);
+               if (edid) {
+                       drm_mode_connector_update_edid_property(connector,
+                                                               edid);
+                       intel_dp->edid_mode_count =
+                               drm_add_edid_modes(connector, edid);
+                       drm_edid_to_eld(connector, edid);
+                       intel_dp->edid = edid;
+               }
+               ironlake_edp_panel_vdd_off(intel_dp, false);
+       }
 
        intel_encoder->hot_plug = intel_dp_hot_plug;
 
index e7b1ec5..486ccdf 100644 (file)
@@ -1926,7 +1926,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
                r600_hdmi_enable(encoder);
-               if (ASIC_IS_DCE4(rdev))
+               if (ASIC_IS_DCE6(rdev))
+                       ; /* TODO (use pointers instead of if-s?) */
+               else if (ASIC_IS_DCE4(rdev))
                        evergreen_hdmi_setmode(encoder, adjusted_mode);
                else
                        r600_hdmi_setmode(encoder, adjusted_mode);
index 01550d0..7fb3d2e 100644 (file)
@@ -1932,6 +1932,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets);
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
+       if (rdev->family <= CHIP_SUMO2)
+               WREG32(SMX_SAR_CTL0, 0x00010000);
+
        WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) |
                                        POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) |
                                        SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1)));
index a51f880..65c5416 100644 (file)
@@ -156,9 +156,6 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset;
 
-       if (ASIC_IS_DCE5(rdev))
-               return;
-
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (!dig->afmt->enabled)
                return;
index 2773039..b50b15c 100644 (file)
 #define        SCRATCH_UMSK                                    0x8540
 #define        SCRATCH_ADDR                                    0x8544
 
+#define        SMX_SAR_CTL0                                    0xA008
 #define        SMX_DC_CTL0                                     0xA020
 #define                USE_HASH_FUNCTION                               (1 << 0)
 #define                NUMBER_OF_SETS(x)                               ((x) << 1)
index 3186522..b7bf18e 100644 (file)
@@ -1303,6 +1303,10 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = r600_audio_init(rdev);
+       if (r)
+               return r;
+
        return 0;
 }
 
@@ -1329,6 +1333,7 @@ int cayman_resume(struct radeon_device *rdev)
 
 int cayman_suspend(struct radeon_device *rdev)
 {
+       r600_audio_fini(rdev);
        /* FIXME: we should wait for ring to be empty */
        radeon_ib_pool_suspend(rdev);
        radeon_vm_manager_suspend(rdev);
index f30dc95..bff6272 100644 (file)
@@ -1839,6 +1839,7 @@ void r600_gpu_init(struct radeon_device *rdev)
        WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA |
                               NUM_CLIP_SEQ(3)));
        WREG32(PA_SC_ENHANCE, FORCE_EOV_MAX_CLK_CNT(4095));
+       WREG32(VC_ENHANCE, 0);
 }
 
 
index 7479a5c..79b5591 100644 (file)
@@ -57,7 +57,7 @@ static bool radeon_dig_encoder(struct drm_encoder *encoder)
  */
 static int r600_audio_chipset_supported(struct radeon_device *rdev)
 {
-       return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE5(rdev))
+       return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE6(rdev))
                || rdev->family == CHIP_RS600
                || rdev->family == CHIP_RS690
                || rdev->family == CHIP_RS740;
index 0133f5f..ca87f7a 100644 (file)
@@ -2079,6 +2079,48 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        return -EINVAL;
                }
                break;
+       case PACKET3_STRMOUT_BASE_UPDATE:
+               if (p->family < CHIP_RV770) {
+                       DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n");
+                       return -EINVAL;
+               }
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad STRMOUT_BASE_UPDATE packet count\n");
+                       return -EINVAL;
+               }
+               if (idx_value > 3) {
+                       DRM_ERROR("bad STRMOUT_BASE_UPDATE index\n");
+                       return -EINVAL;
+               }
+               {
+                       u64 offset;
+
+                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
+                               return -EINVAL;
+                       }
+
+                       if (reloc->robj != track->vgt_strmout_bo[idx_value]) {
+                               DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo does not match\n");
+                               return -EINVAL;
+                       }
+
+                       offset = radeon_get_ib_value(p, idx+1) << 8;
+                       if (offset != track->vgt_strmout_bo_offset[idx_value]) {
+                               DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo offset does not match: 0x%llx, 0x%x\n",
+                                         offset, track->vgt_strmout_bo_offset[idx_value]);
+                               return -EINVAL;
+                       }
+
+                       if ((offset + 4) > radeon_bo_size(reloc->robj)) {
+                               DRM_ERROR("bad STRMOUT_BASE_UPDATE bo too small: 0x%llx, 0x%lx\n",
+                                         offset + 4, radeon_bo_size(reloc->robj));
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               }
+               break;
        case PACKET3_SURFACE_BASE_UPDATE:
                if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
                        DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
index 969c275..82a0a4c 100644 (file)
@@ -322,9 +322,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset;
 
-       if (ASIC_IS_DCE5(rdev))
-               return;
-
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (!dig->afmt->enabled)
                return;
@@ -483,7 +480,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
        uint32_t offset;
        u32 hdmi;
 
-       if (ASIC_IS_DCE5(rdev))
+       if (ASIC_IS_DCE6(rdev))
                return;
 
        /* Silent, r600_hdmi_enable will raise WARN for us */
@@ -543,7 +540,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset;
 
-       if (ASIC_IS_DCE5(rdev))
+       if (ASIC_IS_DCE6(rdev))
                return;
 
        /* Called for ATOM_ENCODER_MODE_HDMI only */
index a0dbf1f..025fd5b 100644 (file)
 #define                TC_L2_SIZE(x)                                   ((x)<<5)
 #define                L2_DISABLE_LATE_HIT                             (1<<9)
 
+#define        VC_ENHANCE                                      0x9714
 
 #define        VGT_CACHE_INVALIDATION                          0x88C4
 #define                CACHE_INVALIDATION(x)                           ((x)<<0)
 #define        PACKET3_SET_CTL_CONST                           0x6F
 #define                PACKET3_SET_CTL_CONST_OFFSET                    0x0003cff0
 #define                PACKET3_SET_CTL_CONST_END                       0x0003e200
+#define        PACKET3_STRMOUT_BASE_UPDATE                     0x72 /* r7xx */
 #define        PACKET3_SURFACE_BASE_UPDATE                     0x73
 
 
index 03e5f5d..2c4d53f 100644 (file)
  *   2.14.0 - add evergreen tiling informations
  *   2.15.0 - add max_pipes query
  *   2.16.0 - fix evergreen 2D tiled surface calculation
+ *   2.17.0 - add STRMOUT_BASE_UPDATE for r7xx
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       16
+#define KMS_DRIVER_MINOR       17
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 0882554..5b37e28 100644 (file)
@@ -801,9 +801,13 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
                int i;
 
                for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-                       not_processed += radeon_fence_count_emitted(rdev, i);
-                       if (not_processed >= 3)
-                               break;
+                       struct radeon_ring *ring = &rdev->ring[i];
+
+                       if (ring->ready) {
+                               not_processed += radeon_fence_count_emitted(rdev, i);
+                               if (not_processed >= 3)
+                                       break;
+                       }
                }
 
                if (not_processed >= 3) { /* should upclock */
index 8ddab4c..6bef46a 100644 (file)
@@ -169,11 +169,17 @@ struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
        struct radeon_bo *bo = gem_to_radeon_bo(obj);
        int ret = 0;
 
+       ret = radeon_bo_reserve(bo, false);
+       if (unlikely(ret != 0))
+               return ERR_PTR(ret);
+
        /* pin buffer into GTT */
        ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL);
-       if (ret)
+       if (ret) {
+               radeon_bo_unreserve(bo);
                return ERR_PTR(ret);
-
+       }
+       radeon_bo_unreserve(bo);
        return dma_buf_export(bo, &radeon_dmabuf_ops, obj->size, flags);
 }
 
index 4ad0281..b4f51c5 100644 (file)
@@ -616,6 +616,9 @@ static void rv770_gpu_init(struct radeon_device *rdev)
                                       ACK_FLUSH_CTL(3) |
                                       SYNC_FLUSH_CTL));
 
+       if (rdev->family != CHIP_RV770)
+               WREG32(SMX_SAR_CTL0, 0x00003f3f);
+
        db_debug3 = RREG32(DB_DEBUG3);
        db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);
        switch (rdev->family) {
@@ -792,7 +795,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
        WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA |
                                          NUM_CLIP_SEQ(3)));
-
+       WREG32(VC_ENHANCE, 0);
 }
 
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
index fdc0898..b0adfc5 100644 (file)
 #define        SCRATCH_UMSK                                    0x8540
 #define        SCRATCH_ADDR                                    0x8544
 
+#define        SMX_SAR_CTL0                                    0xA008
 #define        SMX_DC_CTL0                                     0xA020
 #define                USE_HASH_FUNCTION                               (1 << 0)
 #define                CACHE_DEPTH(x)                                  ((x) << 1)
 #define        TCP_CNTL                                        0x9610
 #define        TCP_CHAN_STEER                                  0x9614
 
+#define        VC_ENHANCE                                      0x9714
+
 #define        VGT_CACHE_INVALIDATION                          0x88C4
 #define                CACHE_INVALIDATION(x)                           ((x)<<0)
 #define                        VC_ONLY                                         0
index 30d98d1..dd14cd1 100644 (file)
@@ -47,9 +47,9 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
        if (dev_priv == NULL)
                return -ENOMEM;
 
+       idr_init(&dev_priv->object_idr);
        dev->dev_private = (void *)dev_priv;
        dev_priv->chipset = chipset;
-       idr_init(&dev->object_name_idr);
 
        return 0;
 }
index 4d02c46..6e52069 100644 (file)
 
 static struct drm_driver driver;
 
+/*
+ * There are many DisplayLink-based graphics products, all with unique PIDs.
+ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
+ * We also require a match on SubClass (0x00) and Protocol (0x00),
+ * which is compatible with all known USB 2.0 era graphics chips and firmware,
+ * but allows DisplayLink to increment those for any future incompatible chips
+ */
 static struct usb_device_id id_table[] = {
-       {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
+       {.idVendor = 0x17e9, .bInterfaceClass = 0xff,
+        .bInterfaceSubClass = 0x00,
+        .bInterfaceProtocol = 0x00,
+        .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+                       USB_DEVICE_ID_MATCH_INT_CLASS |
+                       USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+                       USB_DEVICE_ID_MATCH_INT_PROTOCOL,},
        {},
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 1f18225..c126182 100644 (file)
@@ -100,12 +100,11 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
        if (dev_priv == NULL)
                return -ENOMEM;
 
+       idr_init(&dev_priv->object_idr);
        dev->dev_private = (void *)dev_priv;
 
        dev_priv->chipset = chipset;
 
-       idr_init(&dev->object_name_idr);
-
        pci_set_master(dev->pdev);
 
        ret = drm_vblank_init(dev, 1);
index 60da41f..d844b77 100644 (file)
@@ -9,6 +9,8 @@
 
 #include <linux/fb.h>
 
+struct pci_dev;
+
 enum vga_switcheroo_state {
        VGA_SWITCHEROO_OFF,
        VGA_SWITCHEROO_ON,