Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 18:01:56 +0000 (10:01 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 18:01:56 +0000 (10:01 -0800)
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (40 commits)
  vmwgfx: Snoop DMA transfers with non-covering sizes
  vmwgfx: Move the prefered mode first in the list
  vmwgfx: Unreference surface on cursor error path
  vmwgfx: Free prefered mode on error path
  vmwgfx: Use pointer return error codes
  vmwgfx: Fix hw cursor position
  vmwgfx: Infrastructure for explicit placement
  vmwgfx: Make the preferred autofit mode have a 60Hz vrefresh
  vmwgfx: Remove screen object active list
  vmwgfx: Screen object cleanups
  drm/radeon/kms: consolidate GART code, fix segfault after GPU lockup V2
  drm/radeon/kms: don't poll forever if MC GDDR link training fails
  drm/radeon/kms: fix DP setup on TRAVIS bridges
  drm/radeon/kms: set HPD polarity in hpd_init()
  drm/radeon/kms: add MSI module parameter
  drm/radeon/kms: Add MSI quirk for Dell RS690
  drm/radeon/kms: Add MSI quirk for HP RS690
  drm/radeon/kms: split MSI check into a separate function
  vmwgfx: Reinstate the update_layout ioctl
  drm/radeon/kms: always do extended edid probe
  ...

1  2 
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

@@@ -31,7 -31,6 +31,7 @@@
   */
  #include <linux/list.h>
  #include <linux/slab.h>
 +#include <linux/export.h>
  #include "drm.h"
  #include "drmP.h"
  #include "drm_crtc.h"
@@@ -163,6 -162,7 +163,7 @@@ static struct drm_conn_prop_enum_list d
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
        { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
  };
  
  static struct drm_prop_enum_list drm_encoder_enum_list[] =
        { DRM_MODE_ENCODER_TMDS, "TMDS" },
        { DRM_MODE_ENCODER_LVDS, "LVDS" },
        { DRM_MODE_ENCODER_TVDAC, "TV" },
+       { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
  };
  
  char *drm_get_encoder_name(struct drm_encoder *encoder)
@@@ -464,8 -465,10 +466,10 @@@ void drm_connector_init(struct drm_devi
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
  
-       drm_connector_attach_property(connector,
-                                     dev->mode_config.edid_property, 0);
+       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+               drm_connector_attach_property(connector,
+                                             dev->mode_config.edid_property,
+                                             0);
  
        drm_connector_attach_property(connector,
                                      dev->mode_config.dpms_property, 0);
@@@ -24,7 -24,6 +24,7 @@@
  #include <linux/firmware.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
 +#include <linux/module.h>
  #include "drmP.h"
  #include "radeon.h"
  #include "radeon_asic.h"
@@@ -262,8 -261,11 +262,11 @@@ int ni_mc_load_microcode(struct radeon_
                WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
  
                /* wait for training to complete */
-               while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
-                       udelay(10);
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
+                               break;
+                       udelay(1);
+               }
  
                if (running)
                        WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
@@@ -933,7 -935,7 +936,7 @@@ int cayman_pcie_gart_enable(struct rade
  {
        int r;
  
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
  
  void cayman_pcie_gart_disable(struct radeon_device *rdev)
  {
-       int r;
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
        WREG32(VM_L2_CNTL2, 0);
        WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
               L2_CACHE_BIGK_FRAGMENT_SIZE(6));
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
  }
  
  void cayman_pcie_gart_fini(struct radeon_device *rdev)
@@@ -1362,6 -1355,10 +1356,10 @@@ static int cayman_startup(struct radeon
                return r;
        }
  
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
        evergreen_mc_program(rdev);
        r = cayman_pcie_gart_enable(rdev);
        if (r)
@@@ -1557,6 -1554,7 +1555,7 @@@ void cayman_fini(struct radeon_device *
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        cayman_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
@@@ -41,7 -41,6 +41,7 @@@
  
  #include <linux/firmware.h>
  #include <linux/platform_device.h>
 +#include <linux/module.h>
  
  #include "r100_reg_safe.h"
  #include "rn50_reg_safe.h"
@@@ -537,6 -536,7 +537,7 @@@ void r100_hpd_init(struct radeon_devic
                default:
                        break;
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                r100_irq_set(rdev);
@@@ -577,7 -577,7 +578,7 @@@ int r100_pci_gart_init(struct radeon_de
  {
        int r;
  
-       if (rdev->gart.table.ram.ptr) {
+       if (rdev->gart.ptr) {
                WARN(1, "R100 PCI GART already initialized\n");
                return 0;
        }
@@@ -636,10 -636,12 +637,12 @@@ void r100_pci_gart_disable(struct radeo
  
  int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
  {
+       u32 *gtt = rdev->gart.ptr;
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+       gtt[i] = cpu_to_le32(lower_32_bits(addr));
        return 0;
  }
  
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/seq_file.h>
  #include <linux/firmware.h>
  #include <linux/platform_device.h>
 +#include <linux/module.h>
  #include "drmP.h"
  #include "radeon_drm.h"
  #include "radeon.h"
@@@ -763,13 -762,14 +763,14 @@@ void r600_hpd_init(struct radeon_devic
        struct drm_device *dev = rdev->ddev;
        struct drm_connector *connector;
  
-       if (ASIC_IS_DCE3(rdev)) {
-               u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
-               if (ASIC_IS_DCE32(rdev))
-                       tmp |= DC_HPDx_EN;
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               if (ASIC_IS_DCE3(rdev)) {
+                       u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
+                       if (ASIC_IS_DCE32(rdev))
+                               tmp |= DC_HPDx_EN;
  
-               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                        switch (radeon_connector->hpd.hpd) {
                        case RADEON_HPD_1:
                                WREG32(DC_HPD1_CONTROL, tmp);
                        default:
                                break;
                        }
-               }
-       } else {
-               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               } else {
                        switch (radeon_connector->hpd.hpd) {
                        case RADEON_HPD_1:
                                WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
                                break;
                        }
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                r600_irq_set(rdev);
@@@ -897,7 -895,7 +896,7 @@@ void r600_pcie_gart_tlb_flush(struct ra
        /* flush hdp cache so updates hit vram */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
            !(rdev->flags & RADEON_IS_AGP)) {
-               void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+               void __iomem *ptr = (void *)rdev->gart.ptr;
                u32 tmp;
  
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
@@@ -932,7 -930,7 +931,7 @@@ int r600_pcie_gart_init(struct radeon_d
  {
        int r;
  
-       if (rdev->gart.table.vram.robj) {
+       if (rdev->gart.robj) {
                WARN(1, "R600 PCIE GART already initialized\n");
                return 0;
        }
@@@ -949,7 -947,7 +948,7 @@@ int r600_pcie_gart_enable(struct radeon
        u32 tmp;
        int r, i;
  
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
  void r600_pcie_gart_disable(struct radeon_device *rdev)
  {
        u32 tmp;
-       int i, r;
+       int i;
  
        /* Disable all tables */
        for (i = 0; i < 7; i++)
        WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
        WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
        WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
  }
  
  void r600_pcie_gart_fini(struct radeon_device *rdev)
@@@ -1138,7 -1129,7 +1130,7 @@@ static void r600_mc_program(struct rade
                WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
                WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
        }
-       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
        tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
@@@ -1277,6 -1268,53 +1269,53 @@@ int r600_mc_init(struct radeon_device *
        return 0;
  }
  
+ int r600_vram_scratch_init(struct radeon_device *rdev)
+ {
+       int r;
+       if (rdev->vram_scratch.robj == NULL) {
+               r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
+                                    PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+                                    &rdev->vram_scratch.robj);
+               if (r) {
+                       return r;
+               }
+       }
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (unlikely(r != 0))
+               return r;
+       r = radeon_bo_pin(rdev->vram_scratch.robj,
+                         RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+               return r;
+       }
+       r = radeon_bo_kmap(rdev->vram_scratch.robj,
+                               (void **)&rdev->vram_scratch.ptr);
+       if (r)
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+       radeon_bo_unreserve(rdev->vram_scratch.robj);
+       return r;
+ }
+ void r600_vram_scratch_fini(struct radeon_device *rdev)
+ {
+       int r;
+       if (rdev->vram_scratch.robj == NULL) {
+               return;
+       }
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (likely(r == 0)) {
+               radeon_bo_kunmap(rdev->vram_scratch.robj);
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+       }
+       radeon_bo_unref(&rdev->vram_scratch.robj);
+ }
  /* We doesn't check that the GPU really needs a reset we simply do the
   * reset, it's up to the caller to determine if the GPU needs one. We
   * might add an helper function to check that.
@@@ -2332,6 -2370,14 +2371,14 @@@ void r600_fence_ring_emit(struct radeon
        if (rdev->wb.use_event) {
                u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
                        (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base);
+               /* flush read cache over gart */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+               radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+                                       PACKET3_VC_ACTION_ENA |
+                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(rdev, 0xFFFFFFFF);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, 10); /* poll interval */
                /* EVENT_WRITE_EOP - flush caches, send int */
                radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
                radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
                radeon_ring_write(rdev, fence->seq);
                radeon_ring_write(rdev, 0);
        } else {
+               /* flush read cache over gart */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+               radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+                                       PACKET3_VC_ACTION_ENA |
+                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(rdev, 0xFFFFFFFF);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, 10); /* poll interval */
                radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
                radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0));
                /* wait for 3D idle clean */
@@@ -2421,6 -2475,10 +2476,10 @@@ int r600_startup(struct radeon_device *
                }
        }
  
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
        r600_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
@@@ -2641,6 -2699,7 +2700,7 @@@ void r600_fini(struct radeon_device *rd
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        r600_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
@@@ -36,7 -36,6 +36,7 @@@
  
  #include "drm_pciids.h"
  #include <linux/console.h>
 +#include <linux/module.h>
  
  
  /*
@@@ -119,6 -118,7 +119,7 @@@ int radeon_audio = 0
  int radeon_disp_priority = 0;
  int radeon_hw_i2c = 0;
  int radeon_pcie_gen2 = 0;
+ int radeon_msi = -1;
  
  MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
  module_param_named(no_wb, radeon_no_wb, int, 0444);
@@@ -165,6 -165,9 +166,9 @@@ module_param_named(hw_i2c, radeon_hw_i2
  MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
  module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
  
+ MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
+ module_param_named(msi, radeon_msi, int, 0444);
  static int radeon_suspend(struct drm_device *dev, pm_message_t state)
  {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@@ -23,8 -23,6 +23,8 @@@
   * Authors: Dave Airlie
   *          Alex Deucher
   */
 +#include <linux/export.h>
 +
  #include "drmP.h"
  #include "radeon_drm.h"
  #include "radeon.h"
@@@ -34,7 -32,7 +34,7 @@@
   * radeon_ddc_probe
   *
   */
- bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
+ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
  {
        u8 out = 0x0;
        u8 buf[8];
                {
                        .addr = 0x50,
                        .flags = I2C_M_RD,
-                       .len = 1,
+                       .len = 8,
                        .buf = buf,
                }
        };
  
-       /* Read 8 bytes from i2c for extended probe of EDID header */
-       if (requires_extended_probe)
-               msgs[1].len = 8;
        /* on hw with routers, select right port */
        if (radeon_connector->router.ddc_valid)
                radeon_router_select_ddc_port(radeon_connector);
        if (ret != 2)
                /* Couldn't find an accessible DDC on this connector */
                return false;
-       if (requires_extended_probe) {
-               /* Probe also for valid EDID header
-                * EDID header starts with:
-                * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
-                * Only the first 6 bytes must be valid as
-                * drm_edid_block_valid() can fix the last 2 bytes */
-               if (drm_edid_header_is_valid(buf) < 6) {
-                       /* Couldn't find an accessible EDID on this
-                        * connector */
-                       return false;
-               }
+       /* Probe also for valid EDID header
+        * EDID header starts with:
+        * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+        * Only the first 6 bytes must be valid as
+        * drm_edid_block_valid() can fix the last 2 bytes */
+       if (drm_edid_header_is_valid(buf) < 6) {
+               /* Couldn't find an accessible EDID on this
+                * connector */
+               return false;
        }
        return true;
  }
@@@ -24,7 -24,6 +24,7 @@@
   * USE OR OTHER DEALINGS IN THE SOFTWARE.
   *
   **************************************************************************/
 +#include <linux/module.h>
  
  #include "drmP.h"
  #include "vmwgfx_drv.h"
  #define DRM_IOCTL_VMW_PRESENT_READBACK                                \
        DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK,    \
                 struct drm_vmw_present_readback_arg)
+ #define DRM_IOCTL_VMW_UPDATE_LAYOUT                           \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,       \
+                struct drm_vmw_update_layout_arg)
  
  /**
   * The core DRM version of this macro doesn't account for
@@@ -166,6 -168,9 +169,9 @@@ static struct drm_ioctl_desc vmw_ioctls
        VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
                      vmw_present_readback_ioctl,
                      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
+                     vmw_kms_update_layout_ioctl,
+                     DRM_MASTER | DRM_UNLOCKED),
  };
  
  static struct pci_device_id vmw_pci_id_list[] = {