drm/radeon: Update to Linux 3.17 (v2)
authorFrançois Tigeot <ftigeot@wolfpond.org>
Sat, 22 Aug 2015 16:20:38 +0000 (18:20 +0200)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Sat, 22 Aug 2015 20:37:28 +0000 (22:37 +0200)
Catch up with recent updates in i915kms driver.
While there perform some cleaning in drm and drm/ttm too.

This smallish(1.2MB) diff between Linux v3.12..v3.17 brings
few improvements for radeon cards support on DragonFly BSD.

Driver is VERY experimental even if FF 720p "Hey Mamma"
looks much more pleasing to the eyes on my Xeon box.

Me being Fortran developer(who wants to run OpenCL on BSDs too)
was literally throwing diffs at the fan to see what sticks on.
After cleaning up the mess a bit, these features seems to behave:
  kms-syscons switching on R7 240 and 5770 JUNIPER;
  current DPorts Xorg;
  Xorg-next(1.17.2) + Mesa-next(glamor for radeonsi);
  2D tiling now works out of the box on OLAND;
  glxgears/cubemap/cuberender mesa demos;
  firefox youtube videos(still some blinking on overlays);
  mpv -vo vdpau --hwdec=vdpau bsd-0088.mp4 (--vo=opengl too);
  UVD (decoding limited to 1080p frame streams);
  fragging in OpenArena maxed-out(even ttys[0-8] to quickly check mail);
  hdmi audio;
  DPM (enabled by default);
  gpu temperature monitoring through hw.sensors framework;
  automatic firmware loading.

TODO:
  update drm/ttm, any help would be really appreciated;
  ww_mutex, yep still good old "homegrown" locks;
  vma, newer shrinker api;
  dma_buf/prime;
  iic/i2c rework;
  kldunload radeonkms;
  better gart sizes support;
  newer firmware format support;
  fix failing ring sync test to ring-5(UVD);
  check how driver supports X2 and IGP cards;
  better OpenCL through Clover;
  many more.

Thanks goes to:
  ftigeot@efnet for opportunity and i915 work
  YRabbit@efnet for extensive testing of hdmi A/V on TURKS
  ivadasz@efnet for temperature sensors support
  mneumann@efnet for testing on HAWAII

  AMD for investing time and effort in opensource drivers
  NetBSD and Linux gpu developers

Special thanks to:
  everyone behind freebsd-ports-graphics/opencl (keep pushing the mngt!)

  and that Sweet special girl out there.

169 files changed:
sys/dev/drm/drm/Makefile
sys/dev/drm/drm_buffer.c
sys/dev/drm/drm_bufs.c
sys/dev/drm/drm_crtc.c
sys/dev/drm/drm_drv.c
sys/dev/drm/drm_edid.c
sys/dev/drm/drm_fb_helper.c
sys/dev/drm/drm_fops.c
sys/dev/drm/drm_ioctl.c
sys/dev/drm/drm_lock.c
sys/dev/drm/drm_vm.c
sys/dev/drm/i915/intel_crt.c
sys/dev/drm/i915/intel_display.c
sys/dev/drm/i915/intel_dp.c
sys/dev/drm/i915/intel_dsi.c
sys/dev/drm/i915/intel_dvo.c
sys/dev/drm/i915/intel_fbdev.c
sys/dev/drm/i915/intel_hdmi.c
sys/dev/drm/i915/intel_lvds.c
sys/dev/drm/i915/intel_sdvo.c
sys/dev/drm/i915/intel_tv.c
sys/dev/drm/include/drm/drmP.h
sys/dev/drm/include/drm/drm_crtc.h
sys/dev/drm/include/drm/drm_fb_helper.h
sys/dev/drm/include/drm/drm_os_linux.h
sys/dev/drm/include/drm/drm_pciids.h
sys/dev/drm/include/drm/ttm/ttm_bo_api.h
sys/dev/drm/include/drm/ttm/ttm_bo_driver.h
sys/dev/drm/include/drm/ttm/ttm_lock.h
sys/dev/drm/include/drm/ttm/ttm_placement.h
sys/dev/drm/include/linux/pci.h
sys/dev/drm/include/uapi_drm/drm.h
sys/dev/drm/include/uapi_drm/radeon_drm.h
sys/dev/drm/radeon/Makefile
sys/dev/drm/radeon/atombios.h
sys/dev/drm/radeon/atombios_crtc.c
sys/dev/drm/radeon/atombios_dp.c
sys/dev/drm/radeon/atombios_encoders.c
sys/dev/drm/radeon/atombios_i2c.c
sys/dev/drm/radeon/btc_dpm.c
sys/dev/drm/radeon/btcd.h
sys/dev/drm/radeon/cayman_reg_safe.h
sys/dev/drm/radeon/ci_dpm.c
sys/dev/drm/radeon/ci_smc.c
sys/dev/drm/radeon/cik.c
sys/dev/drm/radeon/cik_sdma.c
sys/dev/drm/radeon/cikd.h
sys/dev/drm/radeon/clearstate_cayman.h
sys/dev/drm/radeon/clearstate_ci.h
sys/dev/drm/radeon/clearstate_si.h
sys/dev/drm/radeon/cypress_dpm.c
sys/dev/drm/radeon/dce3_1_afmt.c [new file with mode: 0644]
sys/dev/drm/radeon/dce6_afmt.c
sys/dev/drm/radeon/evergreen.c
sys/dev/drm/radeon/evergreen_cs.c
sys/dev/drm/radeon/evergreen_dma.c
sys/dev/drm/radeon/evergreen_hdmi.c
sys/dev/drm/radeon/evergreen_reg.h
sys/dev/drm/radeon/evergreen_reg_safe.h
sys/dev/drm/radeon/evergreen_smc.h
sys/dev/drm/radeon/evergreend.h
sys/dev/drm/radeon/kv_dpm.c
sys/dev/drm/radeon/ni.c
sys/dev/drm/radeon/ni_dma.c
sys/dev/drm/radeon/ni_dpm.c
sys/dev/drm/radeon/nid.h
sys/dev/drm/radeon/pptable.h
sys/dev/drm/radeon/r100.c
sys/dev/drm/radeon/r200.c
sys/dev/drm/radeon/r300.c
sys/dev/drm/radeon/r300_cmdbuf.c
sys/dev/drm/radeon/r420.c
sys/dev/drm/radeon/r500_reg.h
sys/dev/drm/radeon/r520.c
sys/dev/drm/radeon/r600.c
sys/dev/drm/radeon/r600_audio.c
sys/dev/drm/radeon/r600_cp.c
sys/dev/drm/radeon/r600_cs.c
sys/dev/drm/radeon/r600_dma.c
sys/dev/drm/radeon/r600_dpm.c
sys/dev/drm/radeon/r600_dpm.h
sys/dev/drm/radeon/r600_hdmi.c
sys/dev/drm/radeon/r600_reg_safe.h
sys/dev/drm/radeon/r600d.h
sys/dev/drm/radeon/radeon.h
sys/dev/drm/radeon/radeon_agp.c
sys/dev/drm/radeon/radeon_asic.c
sys/dev/drm/radeon/radeon_asic.h
sys/dev/drm/radeon/radeon_atombios.c
sys/dev/drm/radeon/radeon_benchmark.c
sys/dev/drm/radeon/radeon_bios.c
sys/dev/drm/radeon/radeon_combios.c
sys/dev/drm/radeon/radeon_connectors.c
sys/dev/drm/radeon/radeon_cp.c
sys/dev/drm/radeon/radeon_cs.c
sys/dev/drm/radeon/radeon_device.c
sys/dev/drm/radeon/radeon_display.c
sys/dev/drm/radeon/radeon_drv.c
sys/dev/drm/radeon/radeon_drv.h
sys/dev/drm/radeon/radeon_encoders.c
sys/dev/drm/radeon/radeon_family.h
sys/dev/drm/radeon/radeon_fb.c
sys/dev/drm/radeon/radeon_fence.c
sys/dev/drm/radeon/radeon_gart.c
sys/dev/drm/radeon/radeon_gem.c
sys/dev/drm/radeon/radeon_gem.h
sys/dev/drm/radeon/radeon_i2c.c
sys/dev/drm/radeon/radeon_ib.c [new file with mode: 0644]
sys/dev/drm/radeon/radeon_irq.c
sys/dev/drm/radeon/radeon_irq_kms.c
sys/dev/drm/radeon/radeon_irq_kms.h
sys/dev/drm/radeon/radeon_kms.c
sys/dev/drm/radeon/radeon_kms.h
sys/dev/drm/radeon/radeon_legacy_crtc.c
sys/dev/drm/radeon/radeon_legacy_encoders.c
sys/dev/drm/radeon/radeon_mem.c
sys/dev/drm/radeon/radeon_mode.h
sys/dev/drm/radeon/radeon_object.c
sys/dev/drm/radeon/radeon_object.h
sys/dev/drm/radeon/radeon_pm.c
sys/dev/drm/radeon/radeon_prime.c
sys/dev/drm/radeon/radeon_ring.c
sys/dev/drm/radeon/radeon_sa.c
sys/dev/drm/radeon/radeon_semaphore.c
sys/dev/drm/radeon/radeon_state.c
sys/dev/drm/radeon/radeon_test.c
sys/dev/drm/radeon/radeon_trace.h
sys/dev/drm/radeon/radeon_ttm.c
sys/dev/drm/radeon/radeon_ucode.h
sys/dev/drm/radeon/radeon_uvd.c
sys/dev/drm/radeon/radeon_vce.c [new file with mode: 0644]
sys/dev/drm/radeon/radeon_vm.c [new file with mode: 0644]
sys/dev/drm/radeon/reg_srcs/cayman
sys/dev/drm/radeon/reg_srcs/evergreen
sys/dev/drm/radeon/reg_srcs/r600
sys/dev/drm/radeon/rs400.c
sys/dev/drm/radeon/rs600.c
sys/dev/drm/radeon/rs690.c
sys/dev/drm/radeon/rs780_dpm.c
sys/dev/drm/radeon/rv515.c
sys/dev/drm/radeon/rv6xx_dpm.c
sys/dev/drm/radeon/rv770.c
sys/dev/drm/radeon/rv770_dma.c
sys/dev/drm/radeon/rv770_dpm.c
sys/dev/drm/radeon/rv770_dpm.h
sys/dev/drm/radeon/rv770_smc.c
sys/dev/drm/radeon/rv770_smc.h
sys/dev/drm/radeon/rv770d.h
sys/dev/drm/radeon/si.c
sys/dev/drm/radeon/si_dma.c
sys/dev/drm/radeon/si_dpm.c
sys/dev/drm/radeon/si_dpm.h
sys/dev/drm/radeon/si_smc.c
sys/dev/drm/radeon/sid.h
sys/dev/drm/radeon/sislands_smc.h
sys/dev/drm/radeon/sumo_dpm.c
sys/dev/drm/radeon/sumo_smc.c
sys/dev/drm/radeon/trinity_dpm.c
sys/dev/drm/radeon/trinity_smc.c
sys/dev/drm/radeon/uvd_v1_0.c
sys/dev/drm/radeon/uvd_v2_2.c
sys/dev/drm/radeon/uvd_v3_1.c
sys/dev/drm/radeon/vce_v1_0.c [new file with mode: 0644]
sys/dev/drm/radeon/vce_v2_0.c [new file with mode: 0644]
sys/dev/drm/ttm/ttm_bo.c
sys/dev/drm/ttm/ttm_bo_manager.c
sys/dev/drm/ttm/ttm_bo_util.c
sys/dev/drm/ttm/ttm_lock.c
sys/dev/drm/ttm/ttm_page_alloc.c

index 0cde30b..3dff16b 100644 (file)
@@ -37,8 +37,8 @@ SRCS  = \
        drm_sysctl.c \
        drm_sysfs.c \
        drm_vm.c \
-       linux_compat.c \
        drm_vma_manager.c \
+       linux_compat.c \
        linux_hdmi.c \
        linux_list_sort.c \
        linux_shmem.c \
index febd87c..4036c71 100644 (file)
@@ -114,7 +114,7 @@ int drm_buffer_copy_from_user(struct drm_buffer *buf,
 
        for (idx = 0; idx < nr_pages; ++idx) {
 
-               if (DRM_COPY_FROM_USER(buf->data[idx],
+               if (copy_from_user(buf->data[idx],
                        (char *)user_data + idx * PAGE_SIZE,
                        min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
                        DRM_ERROR("Failed to copy user data (%p) to drm buffer"
index 882194c..a2ab8c3 100644 (file)
@@ -279,7 +279,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
        if (!(dev->flags & (FREAD|FWRITE)))
                return EACCES; /* Require read/write */
 
-       if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
+       if (!capable(CAP_SYS_ADMIN) && request->type != _DRM_AGP)
                return EACCES;
 
        DRM_LOCK(dev);
@@ -882,7 +882,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request
 {
        int order, ret;
 
-       if (!DRM_SUSER(DRM_CURPROC))
+       if (!capable(CAP_SYS_ADMIN))
                return EACCES;
 
        if (request->count < 0 || request->count > 4096)
@@ -916,7 +916,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
 {
        int order, ret;
 
-       if (!DRM_SUSER(DRM_CURPROC))
+       if (!capable(CAP_SYS_ADMIN))
                return EACCES;
 
        if (request->count < 0 || request->count > 4096)
@@ -1023,7 +1023,7 @@ int drm_infobufs(struct drm_device *dev, void *data,
                                from.low_mark = dma->bufs[i].freelist.low_mark;
                                from.high_mark = dma->bufs[i].freelist.high_mark;
 
-                               if (DRM_COPY_TO_USER(&request->list[count], &from,
+                               if (copy_to_user(&request->list[count], &from,
                                    sizeof(struct drm_buf_desc)) != 0) {
                                        retcode = EFAULT;
                                        break;
@@ -1112,7 +1112,7 @@ int drm_freebufs(struct drm_device *dev, void *data,
        
        spin_lock(&dev->dma_lock);
        for (i = 0; i < request->count; i++) {
-               if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
+               if (copy_from_user(&idx, &request->list[i], sizeof(idx))) {
                        retcode = EFAULT;
                        break;
                }
@@ -1199,23 +1199,23 @@ int drm_mapbufs(struct drm_device *dev, void *data,
        request->virtual = (void *)vaddr;
 
        for (i = 0; i < dma->buf_count; i++) {
-               if (DRM_COPY_TO_USER(&request->list[i].idx,
+               if (copy_to_user(&request->list[i].idx,
                    &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
                        retcode = EFAULT;
                        goto done;
                }
-               if (DRM_COPY_TO_USER(&request->list[i].total,
+               if (copy_to_user(&request->list[i].total,
                    &dma->buflist[i]->total, sizeof(request->list[0].total))) {
                        retcode = EFAULT;
                        goto done;
                }
-               if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
+               if (copy_to_user(&request->list[i].used, &zero,
                    sizeof(zero))) {
                        retcode = EFAULT;
                        goto done;
                }
                address = vaddr + dma->buflist[i]->offset; /* *** */
-               if (DRM_COPY_TO_USER(&request->list[i].address, &address,
+               if (copy_to_user(&request->list[i].address, &address,
                    sizeof(address))) {
                        retcode = EFAULT;
                        goto done;
index 302d79c..fb73434 100644 (file)
@@ -921,6 +921,34 @@ void drm_connector_cleanup(struct drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
 
+/**
+ * drm_connector_register - register a connector
+ * @connector: the connector to register
+ *
+ * Register userspace interfaces for a connector
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_register(struct drm_connector *connector)
+{
+       return drm_sysfs_connector_add(connector);
+}
+EXPORT_SYMBOL(drm_connector_register);
+
+/**
+ * drm_connector_unregister - unregister a connector
+ * @connector: the connector to unregister
+ *
+ * Unregister userspace interfaces for a connector
+ */
+void drm_connector_unregister(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+}
+EXPORT_SYMBOL(drm_connector_unregister);
+
+
 /**
  * drm_connector_unplug_all - unregister connector userspace interfaces
  * @dev: drm device
@@ -935,7 +963,7 @@ void drm_connector_unplug_all(struct drm_device *dev)
 
        /* taking the mode config mutex ends up in a clash with sysfs */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               drm_sysfs_connector_remove(connector);
+               drm_connector_unregister(connector);
 
 }
 EXPORT_SYMBOL(drm_connector_unplug_all);
index bbeb115..1757ebe 100644 (file)
@@ -467,7 +467,7 @@ int drm_lastclose(struct drm_device * dev)
        if (dev->lock.hw_lock) {
                dev->lock.hw_lock = NULL; /* SHM removed */
                dev->lock.file_priv = NULL;
-               DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
+               wakeup(&dev->lock.lock_queue);
        }
        DRM_UNLOCK(dev);
 
@@ -494,7 +494,7 @@ static int drm_load(struct drm_device *dev)
        dev->types[4]  = _DRM_STAT_LOCKS;
        dev->types[5]  = _DRM_STAT_UNLOCKS;
 
-       for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+       for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
                atomic_set(&dev->counts[i], 0);
 
        INIT_LIST_HEAD(&dev->vblank_event_list);
@@ -592,7 +592,7 @@ int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
        if ( len > name##_len ) len = name##_len;                       \
        name##_len = strlen( value );                                   \
        if ( len && name ) {                                            \
-               if ( DRM_COPY_TO_USER( name, value, len ) )             \
+               if ( copy_to_user( name, value, len ) )         \
                        return EFAULT;                          \
        }
 
@@ -725,7 +725,6 @@ int drm_ioctl(struct dev_ioctl_args *ap)
        unsigned int nr = DRM_IOCTL_NR(cmd);
        int retcode = 0;
        caddr_t data = ap->a_data;
-       struct thread *p = curthread;
        int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
        int is_driver_ioctl = 0;
        struct drm_file *file_priv;
@@ -772,7 +771,7 @@ int drm_ioctl(struct dev_ioctl_args *ap)
                return EINVAL;
        }
 
-       if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
+       if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
            ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
            ((ioctl->flags & DRM_MASTER) && !file_priv->master))
                return EACCES;
index de0cf7b..b0b9260 100644 (file)
@@ -3485,18 +3485,21 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
 
                        if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
                                dc_bpc = 10;
+                               info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
                                DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
                                                  connector->name);
                        }
 
                        if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
                                dc_bpc = 12;
+                               info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;
                                DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
                                                  connector->name);
                        }
 
                        if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
                                dc_bpc = 16;
+                               info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;
                                DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
                                                  connector->name);
                        }
index 9f6d4b5..3e1b9d7 100644 (file)
@@ -46,10 +46,11 @@ static LINUX_LIST_HEAD(kernel_fb_helper_list);
  * helper functions used by many drivers to implement the kernel mode setting
  * interfaces.
  *
- * Initialization is done as a three-step process with drm_fb_helper_init(),
- * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config().
- * Drivers with fancier requirements than the default behaviour can override the
- * second step with their own code.  Teardown is done with drm_fb_helper_fini().
+ * Initialization is done as a four-step process with drm_fb_helper_prepare(),
+ * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
+ * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
+ * default behaviour can override the third step with their own code.
+ * Teardown is done with drm_fb_helper_fini().
  *
  * At runtime drivers should restore the fbdev console by calling
  * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
@@ -60,6 +61,19 @@ static LINUX_LIST_HEAD(kernel_fb_helper_list);
  *
  * All other functions exported by the fb helper library can be used to
  * implement the fbdev driver interface by the driver.
+ *
+ * It is possible, though perhaps somewhat tricky, to implement race-free
+ * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
+ * helper must be called first to initialize the minimum required to make
+ * hotplug detection work. Drivers also need to make sure to properly set up
+ * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
+ * it is safe to enable interrupts and start processing hotplug events. At the
+ * same time, drivers should initialize all modeset objects such as CRTCs,
+ * encoders and connectors. To finish up the fbdev helper initialization, the
+ * drm_fb_helper_init() function is called. To probe for all attached displays
+ * and set up an initial configuration using the detected hardware, drivers
+ * should call drm_fb_helper_single_add_all_connectors() followed by
+ * drm_fb_helper_initial_config().
  */
 
 /**
@@ -535,6 +549,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
        kfree(helper->crtc_info);
 }
 
+/**
+ * drm_fb_helper_prepare - setup a drm_fb_helper structure
+ * @dev: DRM device
+ * @helper: driver-allocated fbdev helper structure to set up
+ * @funcs: pointer to structure of functions associate with this helper
+ *
+ * Sets up the bare minimum to make the framebuffer helper usable. This is
+ * useful to implement race-free initialization of the polling helpers.
+ */
+void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
+                          const struct drm_fb_helper_funcs *funcs)
+{
+       INIT_LIST_HEAD(&helper->kernel_fb_list);
+       helper->funcs = funcs;
+       helper->dev = dev;
+}
+EXPORT_SYMBOL(drm_fb_helper_prepare);
+
 /**
  * drm_fb_helper_init - initialize a drm_fb_helper structure
  * @dev: drm device
@@ -547,8 +579,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
  * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
  * to allow driver writes more control over the exact init sequence.
  *
- * Drivers must set fb_helper->funcs before calling
- * drm_fb_helper_initial_config().
+ * Drivers must call drm_fb_helper_prepare() before calling this function.
  *
  * RETURNS:
  * Zero if everything went ok, nonzero otherwise.
@@ -563,10 +594,6 @@ int drm_fb_helper_init(struct drm_device *dev,
        if (!max_conn_count)
                return -EINVAL;
 
-       fb_helper->dev = dev;
-
-       INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
-
        fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
        if (!fb_helper->crtc_info)
                return -ENOMEM;
index 9a69717..71af6e9 100644 (file)
@@ -149,7 +149,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
        priv->pid               = p->td_proc->p_pid;
 
        /* for compatibility root is always authenticated */
-       priv->authenticated     = DRM_SUSER(p);
+       priv->authenticated = capable(CAP_SYS_ADMIN);
 
        INIT_LIST_HEAD(&priv->fbs);
        INIT_LIST_HEAD(&priv->event_list);
index 2bf0a12..c2bf923 100644 (file)
@@ -57,7 +57,7 @@ int drm_getunique(struct drm_device *dev, void *data,
        struct drm_unique *u = data;
 
        if (u->unique_len >= dev->unique_len) {
-               if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
+               if (copy_to_user(u->unique, dev->unique, dev->unique_len))
                        return EFAULT;
        }
        u->unique_len = dev->unique_len;
@@ -94,7 +94,7 @@ int drm_setunique(struct drm_device *dev, void *data,
        if (busid == NULL)
                return ENOMEM;
 
-       if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
+       if (copy_from_user(busid, u->unique, u->unique_len)) {
                drm_free(busid, M_DRM);
                return EFAULT;
        }
index 05dac6f..7e5b167 100644 (file)
@@ -192,6 +192,8 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
                    context, _DRM_LOCKING_CONTEXT(old));
                return 1;
        }
-       DRM_WAKEUP_INT((void *)&lock_data->lock_queue);
+#if 0
+       wake_up_interruptible(&lock_data->lock_queue);
+#endif
        return 0;
 }
index 6b7b8c0..8c45840 100644 (file)
@@ -103,7 +103,7 @@ int drm_mmap(struct dev_mmap_args *ap)
                DRM_UNLOCK(dev);
                return -1;
        }
-       if (((map->flags & _DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) {
+       if (((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
                DRM_UNLOCK(dev);
                DRM_DEBUG("restricted map\n");
                return -1;
index 9031b86..4c37a2e 100644 (file)
@@ -868,7 +868,7 @@ void intel_crt_init(struct drm_device *dev)
 
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 
        if (!I915_HAS_HOTPLUG(dev))
                intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
index 92b038d..21f28a4 100644 (file)
@@ -12278,7 +12278,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector)
        struct drm_connector *connector = &intel_connector->base;
 
        intel_panel_destroy_backlight(connector);
-       drm_sysfs_connector_remove(connector);
+       drm_connector_unregister(connector);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
index 72fd42d..9eb95f7 100644 (file)
@@ -4416,7 +4416,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                          edp_panel_vdd_work);
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 
        if (HAS_DDI(dev))
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
@@ -4487,7 +4487,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                        edp_panel_vdd_off_sync(intel_dp);
                        drm_modeset_unlock(&dev->mode_config.connection_mutex);
                }
-               drm_sysfs_connector_remove(connector);
+               drm_connector_unregister(connector);
                drm_connector_cleanup(connector);
                return false;
        }
index bd24e7b..b975b57 100644 (file)
@@ -743,7 +743,7 @@ bool intel_dsi_init(struct drm_device *dev)
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
 
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 
        fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev);
        if (!fixed_mode) {
index df1ede6..6643f73 100644 (file)
@@ -557,7 +557,7 @@ void intel_dvo_init(struct drm_device *dev)
                        intel_dvo->panel_wants_dither = true;
                }
 
-               drm_sysfs_connector_add(connector);
+               drm_connector_register(connector);
                return;
        }
 
index 26d7bd7..3fca30f 100644 (file)
@@ -479,7 +479,7 @@ out:
        return true;
 }
 
-static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
        .initial_config = intel_fb_initial_config,
        .gamma_set = intel_crtc_fb_gamma_set,
        .gamma_get = intel_crtc_fb_gamma_get,
@@ -652,7 +652,8 @@ int intel_fbdev_init(struct drm_device *dev)
        if (ifbdev == NULL)
                return -ENOMEM;
 
-       ifbdev->helper.funcs = &intel_fb_helper_funcs;
+       drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
+
        if (!intel_fbdev_init_bios(dev, ifbdev))
                ifbdev->preferred_bpp = 32;
 
index c1288ca..2800614 100644 (file)
@@ -1489,7 +1489,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
        intel_hdmi_add_properties(intel_hdmi, connector);
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 
        /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
         * 0xd.  Failure to do so will result in spurious interrupts being
index d01222f..adcb25e 100644 (file)
@@ -1108,7 +1108,7 @@ out:
                DRM_DEBUG_KMS("lid notifier registration failed\n");
                lvds_connector->lid_notifier.notifier_call = NULL;
        }
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 #endif
 
        intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
index 229caa1..217cb49 100644 (file)
@@ -2437,7 +2437,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
        connector->base.unregister = intel_sdvo_connector_unregister;
 
        intel_connector_attach_encoder(&connector->base, &encoder->base);
-       ret = drm_sysfs_connector_add(drm_connector);
+       ret = drm_connector_register(drm_connector);
        if (ret < 0)
                goto err1;
 
@@ -2452,7 +2452,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 
 err2:
 #endif
-       drm_sysfs_connector_remove(drm_connector);
+       drm_connector_unregister(drm_connector);
 err1:
        drm_connector_cleanup(drm_connector);
 
@@ -2565,7 +2565,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
        return true;
 
 err:
-       drm_sysfs_connector_remove(connector);
+       drm_connector_unregister(connector);
        intel_sdvo_destroy(connector);
        return false;
 }
@@ -2644,7 +2644,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        return true;
 
 err:
-       drm_sysfs_connector_remove(connector);
+       drm_connector_unregister(connector);
        intel_sdvo_destroy(connector);
        return false;
 }
@@ -2717,7 +2717,7 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
        list_for_each_entry_safe(connector, tmp,
                                 &dev->mode_config.connector_list, head) {
                if (intel_attached_encoder(connector) == &intel_sdvo->base) {
-                       drm_sysfs_connector_remove(connector);
+                       drm_connector_unregister(connector);
                        intel_sdvo_destroy(connector);
                }
        }
index 0a33f47..9a15818 100644 (file)
@@ -1679,5 +1679,5 @@ intel_tv_init(struct drm_device *dev)
        drm_object_attach_property(&connector->base,
                                   dev->mode_config.tv_bottom_margin_property,
                                   intel_tv->margin[TV_MARGIN_BOTTOM]);
-       drm_sysfs_connector_add(connector);
+       drm_connector_register(connector);
 }
index 957c1f5..8fd855c 100644 (file)
@@ -93,6 +93,7 @@ MALLOC_DECLARE(M_DRM);
 
 #include <linux/atomic.h>
 #include <linux/bug.h>
+#include <linux/capability.h>
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/pci.h>
@@ -221,7 +222,6 @@ int drm_err(const char *func, const char *format, ...);
 
 SYSCTL_DECL(_hw_drm);
 
-#define DRM_ARRAY_SIZE(x) NELEM(x)
 #define DRM_MAX(a,b) ((a)>(b)?(a):(b))
 
 #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
@@ -232,10 +232,6 @@ SYSCTL_DECL(_hw_drm);
 #define DRM_DEV_UID    0
 #define DRM_DEV_GID    0
 
-#define DRM_WAKEUP(w)          wakeup((void *)w)
-#define DRM_WAKEUP_INT(w)      wakeup(w)
-#define DRM_INIT_WAITQUEUE(queue) do {(void)(queue);} while (0)
-
 #define DRM_CURPROC            curthread
 #define DRM_STRUCTPROC         struct thread
 #define DRM_CURRENTPID         (curproc != NULL ? curproc->p_pid : -1)
@@ -253,7 +249,6 @@ SYSCTL_DECL(_hw_drm);
 
 #define DRM_SYSCTL_HANDLER_ARGS        (SYSCTL_HANDLER_ARGS)
 
-#define DRM_IRQ_ARGS           void *arg
 typedef void                   irqreturn_t;
 #define IRQ_HANDLED            /* nothing */
 #define IRQ_NONE               /* nothing */
@@ -267,39 +262,9 @@ enum {
 
 #define drm_get_device_from_kdev(_kdev) (_kdev->si_drv1)
 
-/* DRM_SUSER returns true if the user is superuser */
-#define DRM_SUSER(p)           (priv_check(p, PRIV_DRIVER) == 0)
 #define DRM_AGP_FIND_DEVICE()  agp_find_device()
 #define DRM_MTRR_WC            MDF_WRITECOMBINE
 
-/* DRM_READMEMORYBARRIER() prevents reordering of reads.
- * DRM_WRITEMEMORYBARRIER() prevents reordering of writes.
- * DRM_MEMORYBARRIER() prevents reordering of reads and writes.
- */
-#define DRM_READMEMORYBARRIER()                cpu_lfence()
-#define DRM_WRITEMEMORYBARRIER()       cpu_sfence()
-#define DRM_MEMORYBARRIER()            cpu_mfence()
-
-#define DRM_VERIFYAREA_READ( uaddr, size )             \
-       (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
-
-#define DRM_COPY_TO_USER(user, kern, size) \
-       copyout(kern, user, size)
-#define DRM_COPY_FROM_USER(kern, user, size) \
-       copyin(user, kern, size)
-#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3)         \
-       copyin(arg2, arg1, arg3)
-#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)   \
-       copyout(arg2, arg1, arg3)
-#define DRM_GET_USER_UNCHECKED(val, uaddr)             \
-       ((val) = fuword32(uaddr), 0)
-
-#define        drm_can_sleep() (DRM_HZ & 1)
-
-#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {      \
-       (_map) = (_dev)->context_sareas[_ctx];          \
-} while(0)
-
 #define LOCK_TEST_WITH_RETURN(dev, file_priv)                          \
 do {                                                                   \
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||              \
@@ -882,7 +847,7 @@ struct drm_driver {
        void    (*irq_preinstall)(struct drm_device *dev);
        int     (*irq_postinstall)(struct drm_device *dev);
        void    (*irq_uninstall)(struct drm_device *dev);
-       void    (*irq_handler)(DRM_IRQ_ARGS);
+       void    (*irq_handler)(void *arg);
 
        u32     (*get_vblank_counter)(struct drm_device *dev, int crtc);
        int     (*enable_vblank)(struct drm_device *dev, int crtc);
@@ -1066,7 +1031,7 @@ struct drm_device {
 
        /** \name Usage Counters */
        /*@{ */
-       int               open_count;   /* Outstanding files open          */
+       int open_count;                 /**< Outstanding files open, protected by drm_global_mutex. */
        int               buf_use;      /* Buffers in use -- cannot alloc  */
        /*@} */
 
@@ -1769,7 +1734,8 @@ static __inline__ void drm_core_dropmap(struct drm_map *map)
 
 extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
 
-#define        drm_can_sleep() (DRM_HZ & 1)
+/* XXX bad */
+#define        drm_can_sleep() (HZ & 1)
 
 #endif /* __KERNEL__ */
 #endif /* _DRM_P_H_ */
index 66b6921..d41828a 100644 (file)
@@ -121,6 +121,9 @@ struct drm_display_info {
        enum subpixel_order subpixel_order;
        u32 color_formats;
 
+       /* Mask of supported hdmi deep color modes */
+       u8 edid_hdmi_dc_modes;
+
        u8 cea_rev;
 };
 
@@ -875,6 +878,8 @@ extern int drm_connector_init(struct drm_device *dev,
                              struct drm_connector *connector,
                              const struct drm_connector_funcs *funcs,
                              int connector_type);
+int drm_connector_register(struct drm_connector *connector);
+void drm_connector_unregister(struct drm_connector *connector);
 
 extern void drm_connector_cleanup(struct drm_connector *connector);
 /* helper to unplug all connectors from sysfs for device */
index b528c59..8112dd8 100644 (file)
@@ -85,7 +85,7 @@ struct drm_fb_helper {
        struct drm_fb_helper_crtc *crtc_info;
        int connector_count;
        struct drm_fb_helper_connector **connector_info;
-       struct drm_fb_helper_funcs *funcs;
+       const struct drm_fb_helper_funcs *funcs;
        struct task fb_mode_task;
        struct fb_info *fbdev;
        u32 pseudo_palette[17];
@@ -96,6 +96,8 @@ struct drm_fb_helper {
        bool delayed_hotplug;
 };
 
+void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
+                          const struct drm_fb_helper_funcs *funcs);
 int drm_fb_helper_init(struct drm_device *dev,
                       struct drm_fb_helper *helper, int crtc_count,
                       int max_conn);
index 55e3dda..db31c7a 100644 (file)
@@ -61,7 +61,6 @@
 #define        unlikely(x)            __builtin_expect(!!(x), 0)
 #define        likely(x)              __builtin_expect(!!(x), 1)
 
-#define DRM_HZ                 hz
 #define DRM_UDELAY(udelay)     DELAY(udelay)
 #define DRM_MDELAY(msecs)      do { int loops = (msecs);               \
                                  while (loops--) DELAY(1000);          \
index 20b2153..b555e75 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by gen-drm_pciids from:
- *   o  previous FreeBSD's drm_pciids.h
+ *   o  previous DragonFly's drm_pciids.h
  *   o  Linux' drm_pciids.h
  *   o  the PCI ID repository (http://pciids.sourceforge.net/)
  *
@@ -8,6 +8,28 @@
  */
 
 #define radeon_PCI_IDS \
+       {0x1002, 0x1304, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1305, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1306, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1307, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1309, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R6/R7 Graphics]"}, \
+       {0x1002, 0x130A, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R6 Graphics]"}, \
+       {0x1002, 0x130B, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R4 Graphics]"}, \
+       {0x1002, 0x130C, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R7 Graphics]"}, \
+       {0x1002, 0x130D, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R6 Graphics]"}, \
+       {0x1002, 0x130E, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R5 Graphics]"}, \
+       {0x1002, 0x130F, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R7 Graphics]"}, \
+       {0x1002, 0x1310, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1311, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1312, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1313, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R7 Graphics]"}, \
+       {0x1002, 0x1315, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R5 Graphics]"}, \
+       {0x1002, 0x1316, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R5 Graphics]"}, \
+       {0x1002, 0x1317, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri"}, \
+       {0x1002, 0x1318, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R5 Graphics]"}, \
+       {0x1002, 0x131B, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R4 Graphics]"}, \
+       {0x1002, 0x131C, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R7 Graphics]"}, \
+       {0x1002, 0x131D, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Kaveri [Radeon R6 Graphics]"}, \
        {0x1002, 0x3150, CHIP_RV380|RADEON_IS_MOBILITY, "ATI Radeon Mobility X600 M24"}, \
        {0x1002, 0x3151, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "M24 [FireMV 2400]"}, \
        {0x1002, 0x3152, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Radeon Mobility X300 M24"}, \
        {0x1002, 0x6601, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Mars [Radeon HD 8730M]"}, \
        {0x1002, 0x6602, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Mars"}, \
        {0x1002, 0x6603, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Mars"}, \
+       {0x1002, 0x6604, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Opal XT [Radeon R7 M265]"}, \
+       {0x1002, 0x6605, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Opal PRO [Radeon R7 M260]"}, \
        {0x1002, 0x6606, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Mars XTX [Radeon HD 8790M]"}, \
        {0x1002, 0x6607, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Mars LE [Radeon HD 8530M / R5 M240]"}, \
+       {0x1002, 0x6608, CHIP_OLAND|RADEON_NEW_MEMMAP, "Oland GL [FirePro W2100]"}, \
        {0x1002, 0x6610, CHIP_OLAND|RADEON_NEW_MEMMAP, "Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X]"}, \
        {0x1002, 0x6611, CHIP_OLAND|RADEON_NEW_MEMMAP, "Oland [Radeon HD 8570 / R7 240/340 OEM]"}, \
        {0x1002, 0x6613, CHIP_OLAND|RADEON_NEW_MEMMAP, "Oland PRO [Radeon R7 240]"}, \
        {0x1002, 0x6631, CHIP_OLAND|RADEON_NEW_MEMMAP, "Oland"}, \
        {0x1002, 0x6640, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Saturn XT [FirePro M6100]"}, \
        {0x1002, 0x6641, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Saturn PRO [Radeon HD 8930M]"}, \
+       {0x1002, 0x6646, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Bonaire XT [Radeon R9 M280X]"}, \
+       {0x1002, 0x6647, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Bonaire PRO [Radeon R9 M270X]"}, \
        {0x1002, 0x6649, CHIP_BONAIRE|RADEON_NEW_MEMMAP, "Bonaire [FirePro W5100]"}, \
        {0x1002, 0x6650, CHIP_BONAIRE|RADEON_NEW_MEMMAP, "Bonaire"}, \
        {0x1002, 0x6651, CHIP_BONAIRE|RADEON_NEW_MEMMAP, "Bonaire"}, \
        {0x1002, 0x679B, CHIP_TAHITI|RADEON_NEW_MEMMAP, "Tahiti [Radeon HD 7900 Series]"}, \
        {0x1002, 0x679E, CHIP_TAHITI|RADEON_NEW_MEMMAP, "Tahiti LE [Radeon HD 7800 Series]"}, \
        {0x1002, 0x679F, CHIP_TAHITI|RADEON_NEW_MEMMAP, "Tahiti"}, \
+       {0x1002, 0x67A0, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii XT GL [FirePro W9100]"}, \
+       {0x1002, 0x67A1, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii PRO GL [FirePro W8100]"}, \
+       {0x1002, 0x67A2, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii GL"}, \
+       {0x1002, 0x67A8, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii"}, \
+       {0x1002, 0x67A9, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii"}, \
+       {0x1002, 0x67AA, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii"}, \
+       {0x1002, 0x67B0, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii XT [Radeon R9 290X]"}, \
+       {0x1002, 0x67B1, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii PRO [Radeon R9 290]"}, \
+       {0x1002, 0x67B8, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Unknown device name"}, \
+       {0x1002, 0x67B9, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Vesuvius [Radeon R9 295X2]"}, \
+       {0x1002, 0x67BA, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Unknown device name"}, \
+       {0x1002, 0x67BE, CHIP_HAWAII|RADEON_NEW_MEMMAP, "Hawaii LE"}, \
        {0x1002, 0x6800, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Wimbledon XT [Radeon HD 7970M]"}, \
        {0x1002, 0x6801, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Wimbledon"}, \
        {0x1002, 0x6802, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Wimbledon"}, \
        {0x1002, 0x6829, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde"}, \
        {0x1002, 0x682A, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Venus PRO"}, \
        {0x1002, 0x682B, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Radeon HD 8800M Series"}, \
+       {0x1002, 0x682C, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde GL [FirePro W4100]"}, \
        {0x1002, 0x682D, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Unknown device name"}, \
        {0x1002, 0x682F, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7700M Series]"}, \
        {0x1002, 0x6830, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7800M Series]"}, \
        {0x1002, 0x983D, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Temash [Radeon HD 8250/8280G]"}, \
        {0x1002, 0x983E, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Unknown device name"}, \
        {0x1002, 0x983F, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Unknown device name"}, \
+       {0x1002, 0x9850, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R3 Graphics]"}, \
+       {0x1002, 0x9851, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R4/R5 Graphics]"}, \
+       {0x1002, 0x9852, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R2 Graphics]"}, \
+       {0x1002, 0x9853, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R2 Graphics]"}, \
+       {0x1002, 0x9854, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R3E Graphics]"}, \
+       {0x1002, 0x9855, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R6 Graphics]"}, \
+       {0x1002, 0x9856, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon R1E/R2E Graphics]"}, \
+       {0x1002, 0x9857, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins [Radeon APU XX-2200M with R2 Graphics]"}, \
+       {0x1002, 0x9858, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x9859, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985A, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985B, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985C, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985D, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985E, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
+       {0x1002, 0x985F, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Mullins"}, \
        {0x1002, 0x9900, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Unknown device name"}, \
        {0x1002, 0x9901, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7660D]"}, \
        {0x1002, 0x9903, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7640G]"}, \
index f5c48f7..a9c6d13 100644 (file)
@@ -509,13 +509,12 @@ extern int ttm_bo_init(struct ttm_bo_device *bdev,
                        void (*destroy) (struct ttm_buffer_object *));
 
 /**
- * ttm_bo_synccpu_object_init
+ * ttm_bo_create
  *
  * @bdev: Pointer to a ttm_bo_device struct.
- * @bo: Pointer to a ttm_buffer_object to be initialized.
  * @size: Requested size of buffer object.
  * @type: Requested type of buffer object.
- * @flags: Initial placement flags.
+ * @placement: Initial placement.
  * @page_alignment: Data alignment in pages.
  * @interruptible: If needing to sleep while waiting for GPU resources,
  * sleep interruptible.
index 5731262..7a05bf6 100644 (file)
@@ -184,6 +184,7 @@ struct ttm_mem_type_manager_func {
         * @man: Pointer to a memory type manager.
         * @bo: Pointer to the buffer object we're allocating space for.
         * @placement: Placement details.
+        * @flags: Additional placement flags.
         * @mem: Pointer to a struct ttm_mem_reg to be filled in.
         *
         * This function should allocate space in the memory type managed
@@ -208,6 +209,7 @@ struct ttm_mem_type_manager_func {
        int  (*get_node)(struct ttm_mem_type_manager *man,
                         struct ttm_buffer_object *bo,
                         struct ttm_placement *placement,
+                        uint32_t flags,
                         struct ttm_mem_reg *mem);
 
        /**
@@ -657,18 +659,6 @@ extern void ttm_tt_unbind(struct ttm_tt *ttm);
  */
 extern int ttm_tt_swapin(struct ttm_tt *ttm);
 
-/**
- * ttm_tt_cache_flush:
- *
- * @pages: An array of pointers to struct page:s to flush.
- * @num_pages: Number of pages to flush.
- *
- * Flush the data of the indicated pages from the cpu caches.
- * This is used when changing caching attributes of the pages from
- * cache-coherent.
- */
-extern void ttm_tt_cache_flush(struct vm_page *pages[], unsigned long num_pages);
-
 /**
  * ttm_tt_set_placement_caching:
  *
index 86de3ae..b10924a 100644 (file)
@@ -198,8 +198,6 @@ extern void ttm_write_unlock(struct ttm_lock *lock);
  */
 extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);
 
-void ttm_write_lock_downgrade(struct ttm_lock *lock);
-
 /**
  * ttm_lock_set_kill
  *
index 2be3244..f09e283 100644 (file)
@@ -66,6 +66,8 @@
  * reference the buffer.
  * TTM_PL_FLAG_NO_EVICT means that the buffer may never
  * be evicted to make room for other buffers.
+ * TTM_PL_FLAG_TOPDOWN requests to be placed from the
+ * top of the memory area, instead of the bottom.
  */
 
 #define TTM_PL_FLAG_CACHED      (1 << 16)
@@ -73,6 +75,7 @@
 #define TTM_PL_FLAG_WC          (1 << 18)
 #define TTM_PL_FLAG_SHARED      (1 << 20)
 #define TTM_PL_FLAG_NO_EVICT    (1 << 21)
+#define TTM_PL_FLAG_TOPDOWN     (1 << 22)
 
 #define TTM_PL_MASK_CACHING     (TTM_PL_FLAG_CACHED | \
                                 TTM_PL_FLAG_UNCACHED | \
index f4958b9..2ed49ef 100644 (file)
@@ -76,6 +76,14 @@ struct pci_bus {
 
 #define PCI_DMA_BIDIRECTIONAL  0
 
+/* extracted from radeon/si.c radeon/cik.c */
+#define PCI_EXP_LNKCTL PCIER_LINKCTRL /* 16 */
+#define PCI_EXP_LNKCTL2 48
+#define PCI_EXP_LNKCTL_HAWD PCIEM_LNKCTL_HAWD /* 0x0200 */
+#define PCI_EXP_DEVSTA PCIER_DEVSTS /* 10 */
+#define PCI_EXP_DEVSTA_TRPND 0x0020
+#define PCI_EXP_LNKCAP_CLKPM 0x00040000
+
 static inline int
 pci_read_config_byte(struct pci_dev *pdev, int where, u8 *val)
 {
index 5f3d32a..b3e521a 100644 (file)
@@ -635,14 +635,6 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2
 
-/**
- * DRM_CLIENT_CAP_UNIVERSAL_PLANES
- *
- * If set to 1, the DRM core will expose all planes (overlay, primary, and
- * cursor) to userspace.
- */
-#define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2
-
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
        __u64 capability;
@@ -769,7 +761,7 @@ struct drm_prime_handle {
 
 /**
  * Device specific ioctls should only be in their respective headers
- * The device specific ioctl range is from 0x40 to 0x99.
+ * The device specific ioctl range is from 0x40 to 0x9f.
  * Generic IOCTLS restart at 0xA0.
  *
  * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
index 7120fb1..47fb324 100644 (file)
@@ -510,6 +510,7 @@ typedef struct {
 #define DRM_RADEON_GEM_GET_TILING      0x29
 #define DRM_RADEON_GEM_BUSY            0x2a
 #define DRM_RADEON_GEM_VA              0x2b
+#define DRM_RADEON_GEM_OP              0x2c
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -552,6 +553,7 @@ typedef struct {
 #define DRM_IOCTL_RADEON_GEM_GET_TILING        DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
 #define DRM_IOCTL_RADEON_GEM_BUSY      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy)
 #define DRM_IOCTL_RADEON_GEM_VA                DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va)
+#define DRM_IOCTL_RADEON_GEM_OP                DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_OP, struct drm_radeon_gem_op)
 
 typedef struct drm_radeon_init {
        enum {
@@ -794,7 +796,9 @@ struct drm_radeon_gem_info {
        uint64_t        vram_visible;
 };
 
-#define RADEON_GEM_NO_BACKING_STORE 1
+#define RADEON_GEM_NO_BACKING_STORE    (1 << 0)
+#define RADEON_GEM_GTT_UC              (1 << 1)
+#define RADEON_GEM_GTT_WC              (1 << 2)
 
 struct drm_radeon_gem_create {
        uint64_t        size;
@@ -884,6 +888,16 @@ struct drm_radeon_gem_pwrite {
        uint64_t data_ptr;
 };
 
+/* Sets or returns a value associated with a buffer. */
+struct drm_radeon_gem_op {
+       uint32_t        handle; /* buffer */
+       uint32_t        op;     /* RADEON_GEM_OP_* */
+       uint64_t        value;  /* input or return value */
+};
+
+#define RADEON_GEM_OP_GET_INITIAL_DOMAIN       0
+#define RADEON_GEM_OP_SET_INITIAL_DOMAIN       1
+
 #define RADEON_VA_MAP                  1
 #define RADEON_VA_UNMAP                        2
 
@@ -919,6 +933,7 @@ struct drm_radeon_gem_va {
 #define RADEON_CS_RING_COMPUTE      1
 #define RADEON_CS_RING_DMA          2
 #define RADEON_CS_RING_UVD          3
+#define RADEON_CS_RING_VCE          4
 /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */
 /* 0 = normal, + = higher priority, - = lower priority */
 
@@ -929,6 +944,7 @@ struct drm_radeon_cs_chunk {
 };
 
 /* drm_radeon_cs_reloc.flags */
+#define RADEON_RELOC_PRIO_MASK         (0xf << 0)
 
 struct drm_radeon_cs_reloc {
        uint32_t                handle;
@@ -981,7 +997,20 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16
 /* query if CP DMA is supported on the compute ring */
 #define RADEON_INFO_SI_CP_DMA_COMPUTE  0x17
-
+/* CIK macrotile mode array */
+#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY   0x18
+/* query the number of render backends */
+#define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
+/* max engine clock - needed for OpenCL */
+#define RADEON_INFO_MAX_SCLK           0x1a
+/* version of VCE firmware */
+#define RADEON_INFO_VCE_FW_VERSION     0x1b
+/* version of VCE feedback */
+#define RADEON_INFO_VCE_FB_VERSION     0x1c
+#define RADEON_INFO_NUM_BYTES_MOVED    0x1d
+#define RADEON_INFO_VRAM_USAGE         0x1e
+#define RADEON_INFO_GTT_USAGE          0x1f
+#define RADEON_INFO_ACTIVE_CU_COUNT    0x20
 
 struct drm_radeon_info {
        uint32_t                request;
@@ -1007,4 +1036,6 @@ struct drm_radeon_info {
 #define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA      3
 #define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA      2
 
+#define CIK_TILE_MODE_DEPTH_STENCIL_1D         5
+
 #endif
index 96a7e5c..e62d596 100644 (file)
@@ -1,4 +1,8 @@
-# $FreeBSD: head/sys/modules/drm2/radeonkms/Makefile 254885 2013-08-25 19:37:15Z dumbbell $
+#
+# Makefile for the drm device(radeonkms) driver.
+#
+# Please keep SRC list structured in blocks and sorted.
+#
 
 KMOD   = radeonkms
 SRCS   =                                                               \
@@ -33,6 +37,7 @@ SRCS  +=                                                              \
        radeon_gart.c                                                   \
        radeon_gem.c                                                    \
        radeon_i2c.c                                                    \
+       radeon_ib.c                                                     \
        radeon_irq_kms.c                                                \
        radeon_kms.c                                                    \
        radeon_legacy_crtc.c                                            \
@@ -45,6 +50,7 @@ SRCS  +=                                                              \
        radeon_semaphore.c                                              \
        radeon_test.c                                                   \
        radeon_ttm.c                                                    \
+       radeon_vm.c                                                     \
        atom.c                                                          \
        atombios_crtc.c                                                 \
        atombios_dp.c                                                   \
@@ -65,6 +71,7 @@ SRCS  +=                                                              \
        r600_cs.c                                                       \
        r600_hdmi.c                                                     \
        rv770.c                                                         \
+       dce3_1_afmt.c                                                   \
        evergreen.c                                                     \
        evergreen_blit_shaders.c                                        \
        evergreen_cs.c                                                  \
@@ -114,6 +121,12 @@ SRCS       +=                                                              \
        uvd_v3_1.c                                                      \
        uvd_v4_2.c
 
+# add VCE block
+SRCS   +=                                                              \
+       radeon_vce.c                                                    \
+       vce_v1_0.c                                                      \
+       vce_v2_0.c
+
 # UMS driver
 #SRCS  +=                                                              \
        radeon_cp.c                                                     \
@@ -140,6 +153,8 @@ SRCS        +=                                                              \
        iicbus_if.h                                                     \
        pci_if.h
 
+CFLAGS+= -DCONFIG_ACPI
+
 CFLAGS+= -I${.CURDIR}/../../../dev/drm/radeon
 CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/source/include
 
index a91fa5d..47d7123 100644 (file)
@@ -1711,7 +1711,9 @@ typedef struct _PIXEL_CLOCK_PARAMETERS_V6
 #define PIXEL_CLOCK_V6_MISC_HDMI_BPP_MASK           0x0c
 #define PIXEL_CLOCK_V6_MISC_HDMI_24BPP              0x00
 #define PIXEL_CLOCK_V6_MISC_HDMI_36BPP              0x04
+#define PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6           0x08    //for V6, the correct defintion for 36bpp should be 2 for 36bpp(2:1)
 #define PIXEL_CLOCK_V6_MISC_HDMI_30BPP              0x08
+#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6           0x04    //for V6, the correct defintion for 30bpp should be 1 for 36bpp(5:4)
 #define PIXEL_CLOCK_V6_MISC_HDMI_48BPP              0x0c
 #define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC             0x10
 #define PIXEL_CLOCK_V6_MISC_GEN_DPREFCLK            0x40
@@ -2223,7 +2225,7 @@ typedef struct    _SET_VOLTAGE_PARAMETERS_V2
   USHORT   usVoltageLevel;              // real voltage level
 }SET_VOLTAGE_PARAMETERS_V2;
 
-
+// used by both SetVoltageTable v1.3 and v1.4
 typedef struct _SET_VOLTAGE_PARAMETERS_V1_3
 {
   UCHAR    ucVoltageType;               // To tell which voltage to set up, VDDC/MVDDC/MVDDQ/VDDCI
@@ -2290,15 +2292,36 @@ typedef struct  _GET_LEAKAGE_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_1
 #define        ATOM_GET_VOLTAGE_VID                0x00
 #define ATOM_GET_VOTLAGE_INIT_SEQ           0x03
 #define ATOM_GET_VOLTTAGE_PHASE_PHASE_VID   0x04
-// for SI, this state map to 0xff02 voltage state in Power Play table, which is power boost state
-#define        ATOM_GET_VOLTAGE_STATE0_LEAKAGE_VID 0x10
+#define ATOM_GET_VOLTAGE_SVID2              0x07        //Get SVI2 Regulator Info
 
+// for SI, this state map to 0xff02 voltage state in Power Play table, which is power boost state
+#define ATOM_GET_VOLTAGE_STATE0_LEAKAGE_VID 0x10
 // for SI, this state map to 0xff01 voltage state in Power Play table, which is performance state
 #define        ATOM_GET_VOLTAGE_STATE1_LEAKAGE_VID 0x11
-// undefined power state
+
 #define        ATOM_GET_VOLTAGE_STATE2_LEAKAGE_VID 0x12
 #define        ATOM_GET_VOLTAGE_STATE3_LEAKAGE_VID 0x13
 
+// New Added from CI Hawaii for GetVoltageInfoTable, input parameter structure
+typedef struct  _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2
+{
+  UCHAR    ucVoltageType;               // Input: To tell which voltage to set up, VDDC/MVDDC/MVDDQ/VDDCI
+  UCHAR    ucVoltageMode;               // Input: Indicate action: Get voltage info
+  USHORT   usVoltageLevel;              // Input: real voltage level in unit of mv or Voltage Phase (0, 1, 2, .. ) or Leakage Id
+  ULONG    ulSCLKFreq;                  // Input: when ucVoltageMode= ATOM_GET_VOLTAGE_EVV_VOLTAGE, DPM state SCLK frequency, Define in PPTable SCLK/Voltage dependence table
+}GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2;
+
+// New in GetVoltageInfo v1.2 ucVoltageMode
+#define ATOM_GET_VOLTAGE_EVV_VOLTAGE        0x09
+
+// New Added from CI Hawaii for EVV feature
+typedef struct  _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2
+{
+  USHORT   usVoltageLevel;                               // real voltage level in unit of mv
+  USHORT   usVoltageId;                                  // Voltage Id programmed in Voltage Regulator
+  ULONG    ulReseved;
+}GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2;
+
 /****************************************************************************/ 
 // Structures used by TVEncoderControlTable
 /****************************************************************************/ 
@@ -3864,6 +3887,8 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENT
 #define PP_AC_DC_SWITCH_GPIO_PINID          60
 //from SMU7.x, if ucGPIO_ID=VDDC_REGULATOR_VRHOT_GPIO_PINID in GPIO_LUTable, VRHot feature is enable
 #define VDDC_VRHOT_GPIO_PINID               61
+//if ucGPIO_ID=VDDC_PCC_GPIO_PINID in GPIO_LUTable, Peak Current Control feature is enabled
+#define VDDC_PCC_GPIO_PINID                 62
 
 typedef struct _ATOM_GPIO_PIN_LUT
 {
@@ -4169,10 +4194,10 @@ typedef struct _ATOM_COMMON_RECORD_HEADER
 #define ATOM_OBJECT_LINK_RECORD_TYPE                   18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record
 #define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE          19
 #define ATOM_ENCODER_CAP_RECORD_TYPE                   20
-
+#define ATOM_BRACKET_LAYOUT_RECORD_TYPE                21
 
 //Must be updated when new record type is added,equal to that record definition!
-#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_ENCODER_CAP_RECORD_TYPE
+#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_BRACKET_LAYOUT_RECORD_TYPE
 
 typedef struct  _ATOM_I2C_RECORD
 {
@@ -4397,6 +4422,31 @@ typedef struct _ATOM_CONNECTOR_REMOTE_CAP_RECORD
   USHORT                      usReserved;
 }ATOM_CONNECTOR_REMOTE_CAP_RECORD;
 
+typedef struct  _ATOM_CONNECTOR_LAYOUT_INFO
+{
+   USHORT usConnectorObjectId;
+   UCHAR  ucConnectorType;
+   UCHAR  ucPosition;
+}ATOM_CONNECTOR_LAYOUT_INFO;
+
+// define ATOM_CONNECTOR_LAYOUT_INFO.ucConnectorType to describe the display connector size
+#define CONNECTOR_TYPE_DVI_D                 1
+#define CONNECTOR_TYPE_DVI_I                 2
+#define CONNECTOR_TYPE_VGA                   3
+#define CONNECTOR_TYPE_HDMI                  4
+#define CONNECTOR_TYPE_DISPLAY_PORT          5
+#define CONNECTOR_TYPE_MINI_DISPLAY_PORT     6
+
+typedef struct  _ATOM_BRACKET_LAYOUT_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucLength;
+  UCHAR                       ucWidth;
+  UCHAR                       ucConnNum;
+  UCHAR                       ucReserved;
+  ATOM_CONNECTOR_LAYOUT_INFO  asConnInfo[1];
+}ATOM_BRACKET_LAYOUT_RECORD;
+
 /****************************************************************************/ 
 // ASIC voltage data table
 /****************************************************************************/ 
@@ -4524,8 +4574,9 @@ typedef struct _ATOM_VOLTAGE_OBJECT_HEADER_V3{
 #define VOLTAGE_OBJ_VR_I2C_INIT_SEQ          3        //VOLTAGE REGULATOR INIT sequece through I2C -> ATOM_I2C_VOLTAGE_OBJECT_V3
 #define VOLTAGE_OBJ_PHASE_LUT                4        //Set Vregulator Phase lookup table ->ATOM_GPIO_VOLTAGE_OBJECT_V3
 #define VOLTAGE_OBJ_SVID2                    7        //Indicate voltage control by SVID2 ->ATOM_SVID2_VOLTAGE_OBJECT_V3
-#define        VOLTAGE_OBJ_PWRBOOST_LEAKAGE_LUT     0x10     //Powerboost Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
-#define        VOLTAGE_OBJ_HIGH_STATE_LEAKAGE_LUT   0x11     //High voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
+#define VOLTAGE_OBJ_EVV                      8
+#define VOLTAGE_OBJ_PWRBOOST_LEAKAGE_LUT     0x10     //Powerboost Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
+#define VOLTAGE_OBJ_HIGH_STATE_LEAKAGE_LUT   0x11     //High voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
 #define VOLTAGE_OBJ_HIGH1_STATE_LEAKAGE_LUT  0x12     //High1 voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
 
 typedef struct  _VOLTAGE_LUT_ENTRY_V2
@@ -4552,6 +4603,10 @@ typedef struct  _ATOM_I2C_VOLTAGE_OBJECT_V3
    VOLTAGE_LUT_ENTRY asVolI2cLut[1];        // end with 0xff
 }ATOM_I2C_VOLTAGE_OBJECT_V3;
 
+// ATOM_I2C_VOLTAGE_OBJECT_V3.ucVoltageControlFlag
+#define VOLTAGE_DATA_ONE_BYTE                0
+#define VOLTAGE_DATA_TWO_BYTE                1
+
 typedef struct  _ATOM_GPIO_VOLTAGE_OBJECT_V3
 {
    ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;   // voltage mode = VOLTAGE_OBJ_GPIO_LUT or VOLTAGE_OBJ_PHASE_LUT
@@ -4584,7 +4639,8 @@ typedef struct  _ATOM_SVID2_VOLTAGE_OBJECT_V3
 // 1:0 \96 offset trim,
    USHORT   usLoadLine_PSI;
 // GPU GPIO pin Id to SVID2 regulator VRHot pin. possible value 0~31. 0 means GPIO0, 31 means GPIO31
-   UCHAR    ucReserved[2];
+   UCHAR    ucSVDGpioId;     //0~31 indicate GPIO0~31
+   UCHAR    ucSVCGpioId;     //0~31 indicate GPIO0~31
    ULONG    ulReserved;
 }ATOM_SVID2_VOLTAGE_OBJECT_V3;
 
@@ -4637,6 +4693,49 @@ typedef struct  _ATOM_ASIC_PROFILING_INFO_V2_1
   USHORT usElbVDDCI_LevelArrayOffset;    // offset of 2 dimension voltage level USHORT array
 }ATOM_ASIC_PROFILING_INFO_V2_1;
 
+typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_1
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  ULONG  ulEvvDerateTdp;
+  ULONG  ulEvvDerateTdc;
+  ULONG  ulBoardCoreTemp;
+  ULONG  ulMaxVddc;
+  ULONG  ulMinVddc;
+  ULONG  ulLoadLineSlop;
+  ULONG  ulLeakageTemp;
+  ULONG  ulLeakageVoltage;
+  ULONG  ulCACmEncodeRange;
+  ULONG  ulCACmEncodeAverage;
+  ULONG  ulCACbEncodeRange;
+  ULONG  ulCACbEncodeAverage;
+  ULONG  ulKt_bEncodeRange;
+  ULONG  ulKt_bEncodeAverage;
+  ULONG  ulKv_mEncodeRange;
+  ULONG  ulKv_mEncodeAverage;
+  ULONG  ulKv_bEncodeRange;
+  ULONG  ulKv_bEncodeAverage;
+  ULONG  ulLkgEncodeLn_MaxDivMin;
+  ULONG  ulLkgEncodeMin;
+  ULONG  ulEfuseLogisticAlpha;
+  USHORT usPowerDpm0;
+  USHORT usCurrentDpm0;
+  USHORT usPowerDpm1;
+  USHORT usCurrentDpm1;
+  USHORT usPowerDpm2;
+  USHORT usCurrentDpm2;
+  USHORT usPowerDpm3;
+  USHORT usCurrentDpm3;
+  USHORT usPowerDpm4;
+  USHORT usCurrentDpm4;
+  USHORT usPowerDpm5;
+  USHORT usCurrentDpm5;
+  USHORT usPowerDpm6;
+  USHORT usCurrentDpm6;
+  USHORT usPowerDpm7;
+  USHORT usCurrentDpm7;
+}ATOM_ASIC_PROFILING_INFO_V3_1;
+
+
 typedef struct _ATOM_POWER_SOURCE_OBJECT
 {
        UCHAR   ucPwrSrcId;                                                                                                     // Power source
@@ -5808,6 +5907,8 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3
 #define ATOM_S7_DOS_MODE_PIXEL_DEPTHb0      0x0C
 #define ATOM_S7_DOS_MODE_PIXEL_FORMATb0     0xF0
 #define ATOM_S7_DOS_8BIT_DAC_ENb1           0x01
+#define ATOM_S7_ASIC_INIT_COMPLETEb1        0x02
+#define ATOM_S7_ASIC_INIT_COMPLETE_MASK     0x00000200
 #define ATOM_S7_DOS_MODE_NUMBERw1           0x0FFFF
 
 #define ATOM_S7_DOS_8BIT_DAC_EN_SHIFT       8
@@ -6242,6 +6343,7 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
 #define _128Mx32            0x53
 #define _256Mx8             0x61
 #define _256Mx16            0x62
+#define _512Mx8             0x71
 
 #define SAMSUNG             0x1
 #define INFINEON            0x2
@@ -6987,9 +7089,10 @@ typedef struct _ATOM_DISP_OUT_INFO_V3
   UCHAR  ucMaxDispEngineNum;
   UCHAR  ucMaxActiveDispEngineNum;
   UCHAR  ucMaxPPLLNum;
-  UCHAR  ucCoreRefClkSource;                          // value of CORE_REF_CLK_SOURCE
-  UCHAR  ucReserved[3];
-       ASIC_TRANSMITTER_INFO_V2  asTransmitterInfo[1];     // for alligment only
+  UCHAR  ucCoreRefClkSource;                    // value of CORE_REF_CLK_SOURCE
+  UCHAR  ucDispCaps;
+  UCHAR  ucReserved[2];
+  ASIC_TRANSMITTER_INFO_V2  asTransmitterInfo[1];     // for alligment only
 }ATOM_DISP_OUT_INFO_V3;
 
 //ucDispCaps
index 5550c22..4f7550f 100644 (file)
@@ -209,6 +209,16 @@ static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+static const u32 vga_control_regs[6] =
+{
+       AVIVO_D1VGA_CONTROL,
+       AVIVO_D2VGA_CONTROL,
+       EVERGREEN_D3VGA_CONTROL,
+       EVERGREEN_D4VGA_CONTROL,
+       EVERGREEN_D5VGA_CONTROL,
+       EVERGREEN_D6VGA_CONTROL,
+};
+
 static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -216,13 +226,23 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
        struct radeon_device *rdev = dev->dev_private;
        int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
        BLANK_CRTC_PS_ALLOCATION args;
+       u32 vga_control = 0;
 
        memset(&args, 0, sizeof(args));
 
+       if (ASIC_IS_DCE8(rdev)) {
+               vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]);
+               WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1);
+       }
+
        args.ucCRTC = radeon_crtc->crtc_id;
        args.ucBlanking = state;
 
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+       if (ASIC_IS_DCE8(rdev)) {
+               WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control);
+       }
 }
 
 static void atombios_powergate_crtc(struct drm_crtc *crtc, int state)
@@ -250,8 +270,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
-               /* adjust pm to dpms changes BEFORE enabling crtcs */
-               radeon_pm_compute_clocks(rdev);
                atombios_enable_crtc(crtc, ATOM_ENABLE);
                if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
                        atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
@@ -269,10 +287,10 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
                radeon_crtc->enabled = false;
-               /* adjust pm to dpms changes AFTER disabling crtcs */
-               radeon_pm_compute_clocks(rdev);
                break;
        }
+       /* adjust pm to dpms */
+       radeon_pm_compute_clocks(rdev);
 }
 
 static void
@@ -423,7 +441,17 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
        union atom_enable_ss args;
 
-       if (!enable) {
+       if (enable) {
+               /* Don't mess with SS if percentage is 0 or external ss.
+                * SS is already disabled previously, and disabling it
+                * again can cause display problems if the pll is already
+                * programmed.
+                */
+               if (ss->percentage == 0)
+                       return;
+               if (ss->type & ATOM_EXTERNAL_SS_MASK)
+                       return;
+       } else {
                for (i = 0; i < rdev->num_crtc; i++) {
                        if (rdev->mode_info.crtcs[i] &&
                            rdev->mode_info.crtcs[i]->enabled &&
@@ -459,8 +487,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v3.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev))
-                       args.v3.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE4(rdev)) {
                args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -480,8 +506,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v2.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev))
-                       args.v2.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE3(rdev)) {
                args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -503,8 +527,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.lvds_ss_2.ucSpreadSpectrumRange = ss->range;
                args.lvds_ss_2.ucEnable = enable;
        } else {
-               if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
-                   (ss->type & ATOM_EXTERNAL_SS_MASK)) {
+               if (enable == ATOM_DISABLE) {
                        atombios_disable_ss(rdev, pll_id);
                        return;
                }
@@ -534,7 +557,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
        u32 adjusted_clock = mode->clock;
        int encoder_mode = atombios_get_encoder_mode(encoder);
        u32 dp_clock = mode->clock;
-       int bpc = radeon_get_monitor_bpc(connector);
+       u32 clock = mode->clock;
+       int bpc = radeon_crtc->bpc;
        bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
 
        /* reset the pll flags */
@@ -609,6 +633,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                        radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
        }
 
+       /* adjust pll for deep color modes */
+       if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+               switch (bpc) {
+               case 8:
+               default:
+                       break;
+               case 10:
+                       clock = (clock * 5) / 4;
+                       break;
+               case 12:
+                       clock = (clock * 3) / 2;
+                       break;
+               case 16:
+                       clock = clock * 2;
+                       break;
+               }
+       }
+
        /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
         * accordingly based on the encoder/transmitter to work around
         * special hw requirements.
@@ -630,7 +672,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                        switch (crev) {
                        case 1:
                        case 2:
-                               args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+                               args.v1.usPixelClock = cpu_to_le16(clock / 10);
                                args.v1.ucTransmitterID = radeon_encoder->encoder_id;
                                args.v1.ucEncodeMode = encoder_mode;
                                if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)
@@ -642,7 +684,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
                                break;
                        case 3:
-                               args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10);
+                               args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10);
                                args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
                                args.v3.sInput.ucEncodeMode = encoder_mode;
                                args.v3.sInput.ucDispPllConfig = 0;
@@ -656,10 +698,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
                                } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-                                       if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
-                                               /* deep color support */
-                                               args.v3.sInput.usPixelClock =
-                                                       cpu_to_le16((mode->clock * bpc / 8) / 10);
                                        if (dig->coherent_mode)
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_COHERENT_MODE;
@@ -839,14 +877,21 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
                        args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
                        if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
                                args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
-                       switch (bpc) {
-                       case 8:
-                       default:
-                               args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
-                               break;
-                       case 10:
-                               args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
-                               break;
+                       if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+                               switch (bpc) {
+                               case 8:
+                               default:
+                                       args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
+                                       break;
+                               case 10:
+                                       /* yes this is correct, the atom define is wrong */
+                                       args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
+                                       break;
+                               case 12:
+                                       /* yes this is correct, the atom define is wrong */
+                                       args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
+                                       break;
+                               }
                        }
                        args.v5.ucTransmitterID = encoder_id;
                        args.v5.ucEncoderMode = encoder_mode;
@@ -861,20 +906,22 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
                        args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
                        if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
                                args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
-                       switch (bpc) {
-                       case 8:
-                       default:
-                               args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
-                               break;
-                       case 10:
-                               args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP;
-                               break;
-                       case 12:
-                               args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP;
-                               break;
-                       case 16:
-                               args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
-                               break;
+                       if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+                               switch (bpc) {
+                               case 8:
+                               default:
+                                       args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
+                                       break;
+                               case 10:
+                                       args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
+                                       break;
+                               case 12:
+                                       args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
+                                       break;
+                               case 16:
+                                       args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
+                                       break;
+                               }
                        }
                        args.v6.ucTransmitterID = encoder_id;
                        args.v6.ucEncoderMode = encoder_mode;
@@ -915,6 +962,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
                struct radeon_connector_atom_dig *dig_connector =
                        radeon_connector->con_priv;
                int dp_clock;
+
+               /* Assign mode clock for hdmi deep color max clock limit check */
+               radeon_connector->pixelclock_for_modeset = mode->clock;
                radeon_crtc->bpc = radeon_get_monitor_bpc(connector);
 
                switch (encoder_mode) {
@@ -938,11 +988,14 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
                                                        radeon_atombios_get_ppll_ss_info(rdev,
                                                                                         &radeon_crtc->ss,
                                                                                         ATOM_DP_SS_ID1);
-                               } else
+                               } else {
                                        radeon_crtc->ss_enabled =
                                                radeon_atombios_get_ppll_ss_info(rdev,
                                                                                 &radeon_crtc->ss,
                                                                                 ATOM_DP_SS_ID1);
+                               }
+                               /* disable spread spectrum on DCE3 DP */
+                               radeon_crtc->ss_enabled = false;
                        }
                        break;
                case ATOM_ENCODER_MODE_LVDS:
@@ -993,10 +1046,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
        struct radeon_encoder *radeon_encoder =
                to_radeon_encoder(radeon_crtc->encoder);
        u32 pll_clock = mode->clock;
+       u32 clock = mode->clock;
        u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
        struct radeon_pll *pll;
        int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);
 
+       /* pass the actual clock to atombios_crtc_program_pll for DCE5,6 for HDMI */
+       if (ASIC_IS_DCE5(rdev) &&
+           (encoder_mode == ATOM_ENCODER_MODE_HDMI) &&
+           (radeon_crtc->bpc > 8))
+               clock = radeon_crtc->adjusted_clock;
+
        switch (radeon_crtc->pll_id) {
        case ATOM_PPLL1:
                pll = &rdev->clock.p1pll;
@@ -1031,7 +1091,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                                 radeon_crtc->crtc_id, &radeon_crtc->ss);
 
        atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
-                                 encoder_mode, radeon_encoder->encoder_id, mode->clock,
+                                 encoder_mode, radeon_encoder->encoder_id, clock,
                                  ref_div, fb_div, frac_fb_div, post_div,
                                  radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);
 
@@ -1039,15 +1099,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                /* calculate ss amount and step size */
                if (ASIC_IS_DCE4(rdev)) {
                        u32 step_size;
-                       u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000;
+                       u32 amount = (((fb_div * 10) + frac_fb_div) *
+                                     (u32)radeon_crtc->ss.percentage) /
+                               (100 * (u32)radeon_crtc->ss.percentage_divider);
                        radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
                        radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
                        if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
-                               step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        else
-                               step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        radeon_crtc->ss.step = step_size;
                }
@@ -1074,6 +1136,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
        u32 tmp, viewport_w, viewport_h;
        int r;
+       bool bypass_lut = false;
 
        /* no fb bound */
        if (!atomic && !crtc->primary->fb) {
@@ -1112,62 +1175,141 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(rbo);
 
-       switch (target_fb->bits_per_pixel) {
-       case 8:
+       switch (target_fb->pixel_format) {
+       case DRM_FORMAT_C8:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
                break;
-       case 15:
+       case DRM_FORMAT_XRGB4444:
+       case DRM_FORMAT_ARGB4444:
+               fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
+                            EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB4444));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+#endif
+               break;
+       case DRM_FORMAT_XRGB1555:
+       case DRM_FORMAT_ARGB1555:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+#endif
+               break;
+       case DRM_FORMAT_BGRX5551:
+       case DRM_FORMAT_BGRA5551:
+               fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
+                            EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA5551));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+#endif
                break;
-       case 16:
+       case DRM_FORMAT_RGB565:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
 #ifdef __BIG_ENDIAN
                fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
 #endif
                break;
-       case 24:
-       case 32:
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
 #ifdef __BIG_ENDIAN
                fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
 #endif
                break;
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
+               fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
+                            EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB2101010));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+#endif
+               /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
+               bypass_lut = true;
+               break;
+       case DRM_FORMAT_BGRX1010102:
+       case DRM_FORMAT_BGRA1010102:
+               fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
+                            EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA1010102));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+#endif
+               /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
+               bypass_lut = true;
+               break;
        default:
-               DRM_ERROR("Unsupported screen depth %d\n",
-                         target_fb->bits_per_pixel);
+               DRM_ERROR("Unsupported screen format %s\n",
+                         drm_get_format_name(target_fb->pixel_format));
                return -EINVAL;
        }
 
        if (tiling_flags & RADEON_TILING_MACRO) {
-               if (rdev->family >= CHIP_BONAIRE)
-                       tmp = rdev->config.cik.tile_config;
-               else if (rdev->family >= CHIP_TAHITI)
-                       tmp = rdev->config.si.tile_config;
-               else if (rdev->family >= CHIP_CAYMAN)
-                       tmp = rdev->config.cayman.tile_config;
-               else
-                       tmp = rdev->config.evergreen.tile_config;
+               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
-               switch ((tmp & 0xf0) >> 4) {
-               case 0: /* 4 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
-                       break;
-               case 1: /* 8 banks */
-               default:
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
-                       break;
-               case 2: /* 16 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
-                       break;
+               /* Set NUM_BANKS. */
+               if (rdev->family >= CHIP_TAHITI) {
+                       unsigned index, num_banks;
+
+                       if (rdev->family >= CHIP_BONAIRE) {
+                               unsigned tileb, tile_split_bytes;
+
+                               /* Calculate the macrotile mode index. */
+                               tile_split_bytes = 64 << tile_split;
+                               tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                               tileb = min(tile_split_bytes, tileb);
+
+                               for (index = 0; tileb > 64; index++)
+                                       tileb >>= 1;
+
+                               if (index >= 16) {
+                                       DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                                 target_fb->bits_per_pixel, tile_split);
+                                       return -EINVAL;
+                               }
+
+                               num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       } else {
+                               switch (target_fb->bits_per_pixel) {
+                               case 8:
+                                       index = 10;
+                                       break;
+                               case 16:
+                                       index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
+                                       break;
+                               default:
+                               case 32:
+                                       index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
+                                       break;
+                               }
+
+                               num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
+                       }
+
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
+               } else {
+                       /* NI and older. */
+                       if (rdev->family >= CHIP_CAYMAN)
+                               tmp = rdev->config.cayman.tile_config;
+                       else
+                               tmp = rdev->config.evergreen.tile_config;
+
+                       switch ((tmp & 0xf0) >> 4) {
+                       case 0: /* 4 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                               break;
+                       case 1: /* 8 banks */
+                       default:
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                               break;
+                       case 2: /* 16 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                               break;
+                       }
                }
 
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-
-               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
                fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
                fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
                fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
@@ -1180,23 +1322,18 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
        if (rdev->family >= CHIP_BONAIRE) {
-               u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
-               u32 num_rb = rdev->config.cik.max_backends_per_se;
-               if (num_pipe_configs > 8)
-                       num_pipe_configs = 8;
-               if (num_pipe_configs == 8)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
-               else if (num_pipe_configs == 4) {
-                       if (num_rb == 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
-                       else if (num_rb < 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
-               } else if (num_pipe_configs == 2)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+               /* Read the pipe config from the 2D TILED SCANOUT mode.
+                * It should be the same for the other modes too, but not all
+                * modes set the pipe config field. */
+               u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+               fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
        } else if ((rdev->family == CHIP_TAHITI) ||
                   (rdev->family == CHIP_PITCAIRN))
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
-       else if (rdev->family == CHIP_VERDE)
+       else if ((rdev->family == CHIP_VERDE) ||
+                (rdev->family == CHIP_OLAND) ||
+                (rdev->family == CHIP_HAINAN)) /* for completeness.  HAINAN has no display hw */
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
 
        switch (radeon_crtc->crtc_id) {
@@ -1233,6 +1370,18 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
        WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
+       /*
+        * The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT
+        * for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to
+        * retain the full precision throughout the pipeline.
+        */
+       WREG32_P(EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL + radeon_crtc->crtc_offset,
+                (bypass_lut ? EVERGREEN_LUT_10BIT_BYPASS_EN : 0),
+                ~EVERGREEN_LUT_10BIT_BYPASS_EN);
+
+       if (bypass_lut)
+               DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");
+
        WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
        WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
        WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);
@@ -1265,8 +1414,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
        WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
 
-       /* set pageflip to happen anywhere in vblank interval */
-       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+       /* set pageflip to happen only at start of vblank interval (front porch) */
+       WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
 
        if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
@@ -1300,6 +1449,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
        u32 tmp, viewport_w, viewport_h;
        int r;
+       bool bypass_lut = false;
 
        /* no fb bound */
        if (!atomic && !crtc->primary->fb) {
@@ -1337,18 +1487,30 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(rbo);
 
-       switch (target_fb->bits_per_pixel) {
-       case 8:
+       switch (target_fb->pixel_format) {
+       case DRM_FORMAT_C8:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
                    AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
                break;
-       case 15:
+       case DRM_FORMAT_XRGB4444:
+       case DRM_FORMAT_ARGB4444:
+               fb_format =
+                   AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
+                   AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444;
+#ifdef __BIG_ENDIAN
+               fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
+#endif
+               break;
+       case DRM_FORMAT_XRGB1555:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
                    AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
+#ifdef __BIG_ENDIAN
+               fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
+#endif
                break;
-       case 16:
+       case DRM_FORMAT_RGB565:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
                    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
@@ -1356,8 +1518,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
                fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
 #endif
                break;
-       case 24:
-       case 32:
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
                    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
@@ -1365,9 +1527,20 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
                fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
 #endif
                break;
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
+               fb_format =
+                   AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
+                   AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010;
+#ifdef __BIG_ENDIAN
+               fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
+#endif
+               /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
+               bypass_lut = true;
+               break;
        default:
-               DRM_ERROR("Unsupported screen depth %d\n",
-                         target_fb->bits_per_pixel);
+               DRM_ERROR("Unsupported screen format %s\n",
+                         drm_get_format_name(target_fb->pixel_format));
                return -EINVAL;
        }
 
@@ -1406,6 +1579,13 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        if (rdev->family >= CHIP_R600)
                WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
+       /* LUT only has 256 slots for 8 bpc fb. Bypass for > 8 bpc scanout for precision */
+       WREG32_P(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset,
+                (bypass_lut ? AVIVO_LUT_10BIT_BYPASS_EN : 0), ~AVIVO_LUT_10BIT_BYPASS_EN);
+
+       if (bypass_lut)
+               DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");
+
        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
        WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
@@ -1434,8 +1614,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
        WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
 
-       /* set pageflip to happen anywhere in vblank interval */
-       WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+       /* set pageflip to happen only at start of vblank interval (front porch) */
+       WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
 
        if (!atomic && fb && fb != crtc->primary->fb) {
                radeon_fb = to_radeon_framebuffer(fb);
@@ -1672,8 +1852,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                }
                /* otherwise, pick one of the plls */
                if ((rdev->family == CHIP_KAVERI) ||
-                   (rdev->family == CHIP_KABINI)) {
-                       /* KB/KV has PPLL1 and PPLL2 */
+                   (rdev->family == CHIP_KABINI) ||
+                   (rdev->family == CHIP_MULLINS)) {
+                       /* KB/KV/ML has PPLL1 and PPLL2 */
                        pll_in_use = radeon_get_pll_use_mask(crtc);
                        if (!(pll_in_use & (1 << ATOM_PPLL2)))
                                return ATOM_PPLL2;
@@ -1726,6 +1907,20 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                        return ATOM_PPLL1;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
+       } else if (ASIC_IS_DCE41(rdev)) {
+               /* Don't share PLLs on DCE4.1 chips */
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+                       if (rdev->clock.dp_extclk)
+                               /* skip PPLL programming if using ext clock */
+                               return ATOM_PPLL_INVALID;
+               }
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               if (!(pll_in_use & (1 << ATOM_PPLL1)))
+                       return ATOM_PPLL1;
+               if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                       return ATOM_PPLL2;
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
        } else if (ASIC_IS_DCE4(rdev)) {
                /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
                 * depending on the asic:
@@ -1823,6 +2018,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
            (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
                is_tvcv = true;
 
+       if (!radeon_crtc->adjusted_clock)
+               return -EINVAL;
+
        atombios_crtc_set_pll(crtc, adjusted_mode);
 
        if (ASIC_IS_DCE4(rdev))
@@ -1910,6 +2108,21 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
        int i;
 
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+       if (crtc->primary->fb) {
+               int r;
+               struct radeon_framebuffer *radeon_fb;
+               struct radeon_bo *rbo;
+
+               radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+               rbo = gem_to_radeon_bo(radeon_fb->obj);
+               r = radeon_bo_reserve(rbo, false);
+               if (unlikely(r))
+                       DRM_ERROR("failed to reserve rbo before unpin\n");
+               else {
+                       radeon_bo_unpin(rbo);
+                       radeon_bo_unreserve(rbo);
+               }
+       }
        /* disable the GRPH */
        if (ASIC_IS_DCE4(rdev))
                WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 0);
@@ -1940,7 +2153,9 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
                break;
        case ATOM_PPLL0:
                /* disable the ppll */
-               if ((rdev->family == CHIP_ARUBA) || (rdev->family == CHIP_BONAIRE))
+               if ((rdev->family == CHIP_ARUBA) ||
+                   (rdev->family == CHIP_BONAIRE) ||
+                   (rdev->family == CHIP_HAWAII))
                        atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
                                                  0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
                break;
index a859d34..9039996 100644 (file)
@@ -123,7 +123,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
        /* flags not zero */
        if (args.v1.ucReplyStatus == 2) {
                DRM_DEBUG_KMS("dp_aux_ch flags not zero\n");
-               return -EBUSY;
+               return -EIO;
        }
 
        /* error */
@@ -161,7 +161,7 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
        msg[3] = (msg_bytes << 4) | (send_bytes - 1);
        memcpy(&msg[4], send, send_bytes);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, NULL, 0, delay, &ack);
                if (ret == -EBUSY)
@@ -172,7 +172,7 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return send_bytes;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
@@ -195,7 +195,7 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
        msg[2] = DP_AUX_NATIVE_READ << 4;
        msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, recv, recv_bytes, delay, &ack);
                if (ret == -EBUSY)
@@ -206,7 +206,7 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return ret;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+                       usleep_range(400, 500);
                else if (ret == 0)
                        return -EPROTO;
                else
@@ -245,35 +245,31 @@ int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte)
        int ret;
        u8 ack;
 
-       /* Set up the command byte */
-       if (mode & MODE_I2C_READ)
-               msg[2] = DP_AUX_I2C_READ << 4;
-       else
-               msg[2] = DP_AUX_I2C_WRITE << 4;
-
-       if (!(mode & MODE_I2C_STOP))
-               msg[2] |= DP_AUX_I2C_MOT << 4;
-
+       /* Set up the address */
        msg[0] = address;
        msg[1] = address >> 8;
 
-       switch (mode) {
-       case MODE_I2C_WRITE:
+       /* Set up the command byte */
+       if (mode & MODE_I2C_READ) {
+               msg[2] = DP_AUX_I2C_READ << 4;
+               msg_bytes = 4;
+               msg[3] = msg_bytes << 4;
+       } else {
+               msg[2] = DP_AUX_I2C_WRITE << 4;
                msg_bytes = 5;
                msg[3] = msg_bytes << 4;
                msg[4] = write_byte;
-               break;
-       case MODE_I2C_READ:
-               msg_bytes = 4;
-               msg[3] = msg_bytes << 4;
-               break;
-       default:
-               msg_bytes = 4;
-               msg[3] = 3 << 4;
-               break;
        }
 
-       for (retry = 0; retry < 4; retry++) {
+       /* special handling for start/stop */
+       if (mode & (MODE_I2C_START | MODE_I2C_STOP))
+               msg[3] = 3 << 4;
+
+       /* Set MOT bit for all but stop */
+       if ((mode & MODE_I2C_STOP) == 0)
+               msg[2] |= DP_AUX_I2C_MOT << 4;
+
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(auxch,
                                            msg, msg_bytes, reply, reply_bytes, 0, &ack);
                if (ret == -EBUSY)
@@ -294,7 +290,7 @@ int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte)
                        return -EREMOTEIO;
                case DP_AUX_NATIVE_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_ch native defer\n");
-                       udelay(400);
+                       usleep_range(500, 600);
                        continue;
                default:
                        DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack);
@@ -311,7 +307,7 @@ int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte)
                        return -EREMOTEIO;
                case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
-                       udelay(400);
+                       usleep_range(400, 500);
                        break;
                default:
                        DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack);
@@ -385,6 +381,19 @@ static int dp_get_max_dp_pix_clock(int link_rate,
 
 /***** radeon specific DP functions *****/
 
+static int radeon_dp_get_max_link_rate(struct drm_connector *connector,
+                                      u8 dpcd[DP_DPCD_SIZE])
+{
+       int max_link_rate;
+
+       if (radeon_connector_is_dp12_capable(connector))
+               max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000);
+       else
+               max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000);
+
+       return max_link_rate;
+}
+
 /* First get the min lane# when low rate is used according to pixel clock
  * (prefer low rate), second check max lane# supported by DP panel,
  * if the max lane# < low rate lane# then use max lane# instead.
@@ -394,7 +403,7 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
                                        int pix_clock)
 {
        int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-       int max_link_rate = drm_dp_max_link_rate(dpcd);
+       int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd);
        int max_lane_num = drm_dp_max_lane_count(dpcd);
        int lane_num;
        int max_dp_pix_clock;
@@ -432,7 +441,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
                        return 540000;
        }
 
-       return drm_dp_max_link_rate(dpcd);
+       return radeon_dp_get_max_link_rate(connector, dpcd);
 }
 
 static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
@@ -602,6 +611,26 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
        return true;
 }
 
+void radeon_dp_set_rx_power_state(struct drm_connector *connector,
+                                 u8 power_state)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *dig_connector;
+
+       if (!radeon_connector->con_priv)
+               return;
+
+       dig_connector = radeon_connector->con_priv;
+
+       /* power up/down the sink */
+       if (dig_connector->dpcd[0] >= 0x11) {
+               radeon_write_dpcd_reg(radeon_connector,
+                                  DP_SET_POWER, power_state);
+               usleep_range(1000, 2000);
+       }
+}
+
+
 struct radeon_dp_link_train_info {
        struct radeon_device *rdev;
        struct drm_encoder *encoder;
@@ -672,9 +701,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
        u8 tmp;
 
        /* power up the sink */
-       if (dp_info->dpcd[0] >= 0x11)
-               radeon_write_dpcd_reg(dp_info->radeon_connector,
-                                     DP_SET_POWER, DP_SET_POWER_D0);
+       radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0);
 
        /* possibly enable downspread on the sink */
        if (dp_info->dpcd[3] & 0x1)
@@ -691,8 +718,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
 
        /* set the lane count on the sink */
        tmp = dp_info->dp_lane_count;
-       if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 &&
-           dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)
+       if (drm_dp_enhanced_frame_cap(dp_info->dpcd))
                tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
        radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp);
 
index 44a82c0..d836233 100644 (file)
@@ -181,14 +181,13 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        struct backlight_properties props;
        struct radeon_backlight_privdata *pdata;
        struct radeon_encoder_atom_dig *dig;
-       u8 backlight_level;
        char bl_name[16];
 
        /* Mac laptops with multiple GPUs use the gmux driver for backlight
         * so don't register a backlight device
         */
        if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
-           (rdev->ddev->pci_device == 0x6741))
+           (rdev->pdev->device == 0x6741))
                return;
 
        if (!radeon_encoder->enc_priv)
@@ -212,7 +211,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        props.type = BACKLIGHT_RAW;
        snprintf(bl_name, sizeof(bl_name),
                 "radeon_bl%d", dev->primary->index);
-       bd = backlight_device_register(bl_name, &drm_connector->kdev,
+       bd = backlight_device_register(bl_name, drm_connector->kdev,
                                       pdata, &radeon_atom_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -221,12 +220,17 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
 
        pdata->encoder = radeon_encoder;
 
-       backlight_level = radeon_atom_get_backlight_level_from_reg(rdev);
-
        dig = radeon_encoder->enc_priv;
        dig->bl_dev = bd;
 
        bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
+       /* Set a reasonable default here if the level is 0 otherwise
+        * fbdev will attempt to turn the backlight on after console
+        * unblanking and it will try and restore 0 which turns the backlight
+        * off again.
+        */
+       if (bd->props.brightness == 0)
+               bd->props.brightness = RADEON_MAX_BL_LEVEL;
        bd->props.power = FB_BLANK_UNBLANK;
        backlight_update_status(bd);
 
@@ -393,12 +397,10 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
            && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
                adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
 
-       /* get the native mode for LVDS */
-       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+       /* get the native mode for scaling */
+       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
                radeon_panel_mode_fixup(encoder, adjusted_mode);
-
-       /* get the native mode for TV */
-       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+       } else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
                struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
                if (tv_dac) {
                        if (tv_dac->tv_std == TV_STD_NTSC ||
@@ -408,6 +410,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
                        else
                                radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
                }
+       } else if (radeon_encoder->rmx_type != RMX_OFF) {
+               radeon_panel_mode_fixup(encoder, adjusted_mode);
        }
 
        if (ASIC_IS_DCE3(rdev) &&
@@ -530,11 +534,12 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
 
 static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
 {
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        int bpc = 8;
 
-       if (connector)
-               bpc = radeon_get_monitor_bpc(connector);
+       if (encoder->crtc) {
+               struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+               bpc = radeon_crtc->bpc;
+       }
 
        switch (bpc) {
        case 0:
@@ -777,7 +782,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                        if (radeon_connector->use_digital &&
                            (radeon_connector->audio == RADEON_AUDIO_ENABLE))
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else if (radeon_connector->use_digital)
@@ -796,7 +801,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                if (radeon_audio != 0) {
                        if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else
@@ -816,7 +821,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                } else if (radeon_audio != 0) {
                        if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else
@@ -1379,7 +1384,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        }
                        if (is_dp)
                                args.v5.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v5.ucLaneNum = 8;
                        else
                                args.v5.ucLaneNum = 4;
@@ -1698,10 +1703,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        struct radeon_connector *radeon_connector = NULL;
        struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+       bool travis_quirk = false;
 
        if (connector) {
                radeon_connector = to_radeon_connector(connector);
                radeon_dig_connector = radeon_connector->con_priv;
+               if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+                    ENCODER_OBJECT_ID_TRAVIS) &&
+                   (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
+                   !ASIC_IS_DCE5(rdev))
+                       travis_quirk = true;
        }
 
        switch (mode) {
@@ -1722,25 +1733,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                        atombios_external_encoder_setup(encoder, ext_encoder,
                                                                        EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
                        }
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                } else if (ASIC_IS_DCE4(rdev)) {
                        /* setup and enable the encoder */
                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-                       /* enable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                } else {
                        /* setup and enable the encoder and transmitter */
                        atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-                       /* some dce3.x boards have a bug in their transmitter control table.
-                        * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE
-                        * does the same thing and more.
-                        */
-                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) &&
-                           (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1748,73 +1747,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                                             ATOM_TRANSMITTER_ACTION_POWER_ON);
                                radeon_dig_connector->edp_on = true;
                        }
+               }
+               /* enable the transmitter */
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+                       /* DP_SET_POWER_D0 is set in radeon_dp_link_train */
                        radeon_dp_link_train(encoder, connector);
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               if (ext_encoder)
+                       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) || ASIC_IS_DCE5(rdev)) {
-                       /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-               } else if (ASIC_IS_DCE4(rdev)) {
+               if (ASIC_IS_DCE4(rdev)) {
+                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+               }
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
+                   connector && !travis_quirk)
+                       radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
+               if (ASIC_IS_DCE4(rdev)) {
                        /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
                } else {
                        /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
                        atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
-                       if (ASIC_IS_DCE4(rdev))
-                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       if (travis_quirk)
+                               radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                                atombios_set_edp_panel_power(connector,
                                                             ATOM_TRANSMITTER_ACTION_POWER_OFF);
                                radeon_dig_connector->edp_on = false;
                        }
                }
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-               break;
-       }
-}
-
-static void
-radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
-                            struct drm_encoder *ext_encoder,
-                            int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       default:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(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) || ASIC_IS_DCE61(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;
        }
 }
@@ -1825,7 +1807,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
 
        DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1885,9 +1866,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                return;
        }
 
-       if (ext_encoder)
-               radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
-
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 
 }
@@ -1976,8 +1954,11 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
                                        args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
                                else
                                        args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-                       } else
+                       } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
+                       } else {
                                args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+                       }
                        switch (radeon_encoder->encoder_id) {
                        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
                        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
@@ -2053,9 +2034,9 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 
        /* Funky macbooks */
-       if ((dev->pci_device == 0x71C5) &&
-           (dev->pci_subvendor == 0x106b) &&
-           (dev->pci_subdevice == 0x0080)) {
+       if ((dev->pdev->device == 0x71C5) &&
+           (dev->pdev->subsystem_vendor == 0x106b) &&
+           (dev->pdev->subsystem_device == 0x0080)) {
                if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
                        uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
 
@@ -2476,6 +2457,15 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 
        /* this is needed for the pll/ss setup to work correctly in some cases */
        atombios_set_encoder_crtc_source(encoder);
+       /* set up the FMT blocks */
+       if (ASIC_IS_DCE8(rdev))
+               dce8_program_fmt(encoder);
+       else if (ASIC_IS_DCE4(rdev))
+               dce4_program_fmt(encoder);
+       else if (ASIC_IS_DCE3(rdev))
+               dce3_program_fmt(encoder);
+       else if (ASIC_IS_AVIVO(rdev))
+               avivo_program_fmt(encoder);
 }
 
 static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
index 847c011..bccb73f 100644 (file)
@@ -49,7 +49,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
        unsigned char *base;
-       u16 out;
+       u16 out = cpu_to_le16(0);
 
        memset(&args, 0, sizeof(args));
 
@@ -60,9 +60,14 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
                        DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
                        return EINVAL;
                }
-               args.ucRegIndex = buf[0];
-               if (num > 1)
-                       memcpy(&out, &buf[1], num - 1);
+               if (buf == NULL)
+                       args.ucRegIndex = 0;
+               else
+                       args.ucRegIndex = buf[0];
+               if (num)
+                       num--;
+               if (num)
+                       memcpy(&out, &buf[1], num);
                args.lpI2CDataOut = cpu_to_le16(out);
        } else {
                if (num > ATOM_MAX_HW_I2C_READ) {
@@ -99,14 +104,14 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num)
        struct radeon_i2c_chan *i2c = device_get_softc(dev);
        struct iic_msg *p;
        int i, remaining, current_count, buffer_offset, max_bytes, ret;
-       u8 buf = 0, flags;
+       u8 flags;
 
        /* check for bus probe */
        p = &msgs[0];
        if ((num == 1) && (p->len == 0)) {
                ret = radeon_process_i2c_ch(i2c,
                                            p->slave, HW_I2C_WRITE,
-                                           &buf, 1);
+                                           NULL, 0);
                if (ret)
                        return ret;
                else
index 67d3b25..2d35b0e 100644 (file)
@@ -2512,21 +2512,6 @@ int btc_dpm_enable(struct radeon_device *rdev)
        if (eg_pi->ls_clock_gating)
                btc_ls_clock_gating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        btc_init_stutter_mode(rdev);
@@ -2578,7 +2563,11 @@ void btc_dpm_disable(struct radeon_device *rdev)
 void btc_dpm_setup_asic(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       int r;
 
+       r = ni_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        rv770_get_memory_type(rdev);
        rv740_read_clock_registers(rdev);
        btc_read_arb_registers(rdev);
@@ -2612,6 +2601,10 @@ int btc_dpm_init(struct radeon_device *rdev)
        pi->min_vddc_in_table = 0;
        pi->max_vddc_in_table = 0;
 
+       ret = r600_get_platform_caps(rdev);
+       if (ret)
+               return ret;
+
        ret = rv7xx_parse_power_table(rdev);
        if (ret)
                return ret;
@@ -2768,6 +2761,37 @@ void btc_dpm_fini(struct radeon_device *rdev)
        r600_free_extended_power_table(rdev);
 }
 
+void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
+                                                    struct seq_file *m)
+{
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       struct radeon_ps *rps = &eg_pi->current_rps;
+       struct rv7xx_ps *ps = rv770_get_ps(rps);
+       struct rv7xx_pl *pl;
+       u32 current_index =
+               (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+               CURRENT_PROFILE_INDEX_SHIFT;
+
+       if (current_index > 2) {
+               seq_printf(m, "invalid dpm profile %d\n", current_index);
+       } else {
+               if (current_index == 0)
+                       pl = &ps->low;
+               else if (current_index == 1)
+                       pl = &ps->medium;
+               else /* current_index == 2 */
+                       pl = &ps->high;
+               seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
+               if (rdev->family >= CHIP_CEDAR) {
+                       seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
+                                  current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
+               } else {
+                       seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u\n",
+                                  current_index, pl->sclk, pl->mclk, pl->vddc);
+               }
+       }
+}
+
 u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
index 29e32de..9c65be2 100644 (file)
 #       define DYN_SPREAD_SPECTRUM_EN                   (1 << 23)
 #       define AC_DC_SW                                 (1 << 24)
 
+#define TARGET_AND_CURRENT_PROFILE_INDEX                  0x66c
+#       define CURRENT_PROFILE_INDEX_MASK                 (0xf << 4)
+#       define CURRENT_PROFILE_INDEX_SHIFT                4
+
 #define        CG_BIF_REQ_AND_RSP                              0x7f4
 #define                CG_CLIENT_REQ(x)                        ((x) << 0)
 #define                CG_CLIENT_REQ_MASK                      (0xff << 0)
index 41c676e..aa9682b 100644 (file)
@@ -324,7 +324,7 @@ static const unsigned cayman_reg_safe_bm[2047] = {
        0x00000E00, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0xFFFFFCF8, 0xFE07FF00,
        0x3CF1F003, 0xE39E7BCF, 0xFFFFFFFF, 0xFFFFFFFF,
-       0xE7020000, 0xDDD898DD, 0x279FA3FD, 0x011FFFF0,
+       0xE7020000, 0xDDD898DD, 0x079FA3FD, 0x011FFFE0,
        0xBFFF0000, 0xEFC3DF87, 0x7BF0F7E1, 0x1EFC3DF8,
        0xDFBF0F7E, 0xFFFFF7EF, 0xFFFFFFFF, 0x00000000,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
index 6123a09..900dcbc 100644 (file)
  *
  */
 
+#include <linux/firmware.h>
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_ucode.h"
 #include "cikd.h"
 #include "r600_dpm.h"
 #include "ci_dpm.h"
 #define VOLTAGE_VID_OFFSET_SCALE1    625
 #define VOLTAGE_VID_OFFSET_SCALE2    100
 
+static const struct ci_pt_defaults defaults_hawaii_xt =
+{
+       1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000,
+       { 0x84,  0x0,   0x0,   0x7F,  0x0,   0x0,   0x5A,  0x60,  0x51,  0x8E,  0x79,  0x6B,  0x5F,  0x90,  0x79  },
+       { 0x1EA, 0x1EA, 0x1EA, 0x224, 0x224, 0x224, 0x24F, 0x24F, 0x24F, 0x28E, 0x28E, 0x28E, 0x2BC, 0x2BC, 0x2BC }
+};
+
+static const struct ci_pt_defaults defaults_hawaii_pro =
+{
+       1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062,
+       { 0x93,  0x0,   0x0,   0x97,  0x0,   0x0,   0x6B,  0x60,  0x51,  0x95,  0x79,  0x6B,  0x5F,  0x90,  0x79  },
+       { 0x1EA, 0x1EA, 0x1EA, 0x224, 0x224, 0x224, 0x24F, 0x24F, 0x24F, 0x28E, 0x28E, 0x28E, 0x2BC, 0x2BC, 0x2BC }
+};
+
 static const struct ci_pt_defaults defaults_bonaire_xt =
 {
        1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
@@ -173,22 +189,39 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev)
 {
        struct ci_power_info *pi = ci_get_pi(rdev);
 
-       switch (rdev->ddev->pci_device) {
-        case 0x6650:
-        case 0x6658:
-        case 0x665C:
-        default:
+       switch (rdev->pdev->device) {
+       case 0x6649:
+       case 0x6650:
+       case 0x6651:
+       case 0x6658:
+       case 0x665C:
+       case 0x665D:
+       default:
                pi->powertune_defaults = &defaults_bonaire_xt;
                break;
-        case 0x6651:
-        case 0x665D:
-               pi->powertune_defaults = &defaults_bonaire_pro;
-               break;
-        case 0x6640:
+       case 0x6640:
+       case 0x6641:
+       case 0x6646:
+       case 0x6647:
                pi->powertune_defaults = &defaults_saturn_xt;
                break;
-        case 0x6641:
-               pi->powertune_defaults = &defaults_saturn_pro;
+       case 0x67B8:
+       case 0x67B0:
+               pi->powertune_defaults = &defaults_hawaii_xt;
+               break;
+       case 0x67BA:
+       case 0x67B1:
+               pi->powertune_defaults = &defaults_hawaii_pro;
+               break;
+       case 0x67A0:
+       case 0x67A1:
+       case 0x67A2:
+       case 0x67A8:
+       case 0x67A9:
+       case 0x67AA:
+       case 0x67B9:
+       case 0x67BE:
+               pi->powertune_defaults = &defaults_bonaire_xt;
                break;
        }
 
@@ -704,6 +737,14 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
        u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
+       if (rps->vce_active) {
+               rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
+               rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
+       } else {
+               rps->evclk = 0;
+               rps->ecclk = 0;
+       }
+
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
            ci_dpm_vblank_too_short(rdev))
                disable_mclk_switching = true;
@@ -762,6 +803,13 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
                sclk = ps->performance_levels[0].sclk;
        }
 
+       if (rps->vce_active) {
+               if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
+                       sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
+               if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
+                       mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
+       }
+
        ps->performance_levels[0].sclk = sclk;
        ps->performance_levels[0].mclk = mclk;
 
@@ -807,6 +855,9 @@ static int ci_set_thermal_temperature_range(struct radeon_device *rdev,
        WREG32_SMC(CG_THERMAL_CTRL, tmp);
 #endif
 
+       rdev->pm.dpm.thermal.min_temp = low_temp;
+       rdev->pm.dpm.thermal.max_temp = high_temp;
+
        return 0;
 }
 
@@ -878,7 +929,18 @@ static void ci_get_leakage_voltages(struct radeon_device *rdev)
        pi->vddc_leakage.count = 0;
        pi->vddci_leakage.count = 0;
 
-       if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
+       if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
+               for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
+                       virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+                       if (radeon_atom_get_voltage_evv(rdev, virtual_voltage_id, &vddc) != 0)
+                               continue;
+                       if (vddc != 0 && vddc != virtual_voltage_id) {
+                               pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc;
+                               pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id;
+                               pi->vddc_leakage.count++;
+                       }
+               }
+       } else if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
                for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
                        virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
                        if (radeon_atom_get_leakage_vddc_based_on_leakage_params(rdev, &vddc, &vddci,
@@ -1117,7 +1179,7 @@ static int ci_stop_dpm(struct radeon_device *rdev)
        tmp &= ~GLOBAL_PWRMGT_EN;
        WREG32_SMC(GENERAL_PWRMGT, tmp);
 
-       tmp = RREG32(SCLK_PWRMGT_CNTL);
+       tmp = RREG32_SMC(SCLK_PWRMGT_CNTL);
        tmp &= ~DYNAMIC_PM_EN;
        WREG32_SMC(SCLK_PWRMGT_CNTL, tmp);
 
@@ -3426,7 +3488,6 @@ static int ci_enable_uvd_dpm(struct radeon_device *rdev, bool enable)
                0 : -EINVAL;
 }
 
-#if 0
 static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
 {
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3459,6 +3520,7 @@ static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
                0 : -EINVAL;
 }
 
+#if 0
 static int ci_enable_samu_dpm(struct radeon_device *rdev, bool enable)
 {
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3545,7 +3607,6 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate)
        return ci_enable_uvd_dpm(rdev, !gate);
 }
 
-#if 0
 static u8 ci_get_vce_boot_level(struct radeon_device *rdev)
 {
        u8 i;
@@ -3566,15 +3627,15 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,
                             struct radeon_ps *radeon_current_state)
 {
        struct ci_power_info *pi = ci_get_pi(rdev);
-       bool new_vce_clock_non_zero = (radeon_new_state->evclk != 0);
-       bool old_vce_clock_non_zero = (radeon_current_state->evclk != 0);
        int ret = 0;
        u32 tmp;
 
-       if (new_vce_clock_non_zero != old_vce_clock_non_zero) {
-               if (new_vce_clock_non_zero) {
-                       pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
+       if (radeon_current_state->evclk != radeon_new_state->evclk) {
+               if (radeon_new_state->evclk) {
+                       /* turn the clocks on when encoding */
+                       cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false);
 
+                       pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
                        tmp = RREG32_SMC(DPM_TABLE_475);
                        tmp &= ~VceBootLevel_MASK;
                        tmp |= VceBootLevel(pi->smc_state_table.VceBootLevel);
@@ -3582,12 +3643,16 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,
 
                        ret = ci_enable_vce_dpm(rdev, true);
                } else {
+                       /* turn the clocks off when not encoding */
+                       cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true);
+
                        ret = ci_enable_vce_dpm(rdev, false);
                }
        }
        return ret;
 }
 
+#if 0
 static int ci_update_samu_dpm(struct radeon_device *rdev, bool gate)
 {
        return ci_enable_samu_dpm(rdev, gate);
@@ -4461,7 +4526,7 @@ static void ci_get_memory_type(struct radeon_device *rdev)
 }
 
 static void ci_update_current_ps(struct radeon_device *rdev,
-                         struct radeon_ps *rps)
+                                struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4472,7 +4537,7 @@ static void ci_update_current_ps(struct radeon_device *rdev,
 }
 
 static void ci_update_requested_ps(struct radeon_device *rdev,
-                           struct radeon_ps *rps)
+                                  struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4506,6 +4571,11 @@ void ci_dpm_post_set_power_state(struct radeon_device *rdev)
 
 void ci_dpm_setup_asic(struct radeon_device *rdev)
 {
+       int r;
+
+       r = ci_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        ci_read_clock_registers(rdev);
        ci_get_memory_type(rdev);
        ci_enable_acpi_power_management(rdev);
@@ -4518,13 +4588,6 @@ int ci_dpm_enable(struct radeon_device *rdev)
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        if (ci_is_smc_running(rdev))
                return -EINVAL;
        if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
@@ -4622,6 +4685,18 @@ int ci_dpm_enable(struct radeon_device *rdev)
                DRM_ERROR("ci_enable_power_containment failed\n");
                return ret;
        }
+
+       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       ci_update_current_ps(rdev, boot_ps);
+
+       return 0;
+}
+
+int ci_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
 #if 0
@@ -4642,19 +4717,8 @@ int ci_dpm_enable(struct radeon_device *rdev)
 #endif
        }
 
-       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
        ci_dpm_powergate_uvd(rdev, true);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
-       ci_update_current_ps(rdev, boot_ps);
-
        return 0;
 }
 
@@ -4663,12 +4727,6 @@ void ci_dpm_disable(struct radeon_device *rdev)
        struct ci_power_info *pi = ci_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_dpm_powergate_uvd(rdev, false);
 
        if (!ci_is_smc_running(rdev))
@@ -4699,13 +4757,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = &pi->current_rps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_find_dpm_states_clocks_in_dpm_table(rdev, new_ps);
        if (pi->pcie_performance_request)
                ci_request_link_speed_change_before_state_change(rdev, new_ps, old_ps);
@@ -4724,13 +4775,13 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
                DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n");
                return ret;
        }
-#if 0
+
        ret = ci_update_vce_dpm(rdev, new_ps, old_ps);
        if (ret) {
                DRM_ERROR("ci_update_vce_dpm failed\n");
                return ret;
        }
-#endif
+
        ret = ci_update_sclk_t(rdev);
        if (ret) {
                DRM_ERROR("ci_update_sclk_t failed\n");
@@ -4761,13 +4812,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        if (pi->pcie_performance_request)
                ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
@@ -4938,9 +4982,6 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        if (!rdev->pm.dpm.ps)
                return -ENOMEM;
        power_state_offset = (u8 *)state_array->states;
-       rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
-       rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
-       rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
        for (i = 0; i < state_array->ucNumEntries; i++) {
                u8 *idx;
                power_state = (union pplib_power_state *)power_state_offset;
@@ -4977,11 +5018,26 @@ static int ci_parse_power_table(struct radeon_device *rdev)
                power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
        }
        rdev->pm.dpm.num_ps = state_array->ucNumEntries;
+
+       /* fill in the vce power states */
+       for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
+               u32 sclk, mclk;
+               clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
+               clock_info = (union pplib_clock_info *)
+                       &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
+               sclk = le16_to_cpu(clock_info->ci.usEngineClockLow);
+               sclk |= clock_info->ci.ucEngineClockHigh << 16;
+               mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow);
+               mclk |= clock_info->ci.ucMemoryClockHigh << 16;
+               rdev->pm.dpm.vce_states[i].sclk = sclk;
+               rdev->pm.dpm.vce_states[i].mclk = mclk;
+       }
+
        return 0;
 }
 
 static int ci_get_vbios_boot_values(struct radeon_device *rdev,
-                            struct ci_vbios_boot_state *boot_state)
+                                   struct ci_vbios_boot_state *boot_state)
 {
        struct radeon_mode_info *mode_info = &rdev->mode_info;
        int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
@@ -5056,17 +5112,25 @@ int ci_dpm_init(struct radeon_device *rdev)
                ci_dpm_fini(rdev);
                return ret;
        }
-       ret = ci_parse_power_table(rdev);
+
+       ret = r600_get_platform_caps(rdev);
        if (ret) {
                ci_dpm_fini(rdev);
                return ret;
        }
+
        ret = r600_parse_extended_power_table(rdev);
        if (ret) {
                ci_dpm_fini(rdev);
                return ret;
        }
 
+       ret = ci_parse_power_table(rdev);
+       if (ret) {
+               ci_dpm_fini(rdev);
+               return ret;
+       }
+
         pi->dll_default_on = false;
         pi->sram_end = SMC_RAM_END;
 
@@ -5085,6 +5149,12 @@ int ci_dpm_init(struct radeon_device *rdev)
        pi->mclk_dpm_key_disabled = 0;
        pi->pcie_dpm_key_disabled = 0;
 
+       /* mclk dpm is unstable on some R7 260X cards with the old mc ucode */
+       if ((rdev->pdev->device == 0x6658) &&
+           (rdev->mc_fw->datasize == (BONAIRE_MC_UCODE_SIZE * 4))) {
+               pi->mclk_dpm_key_disabled = 1;
+       }
+
        pi->caps_sclk_ds = true;
 
        pi->mclk_strobe_mode_threshold = 40000;
@@ -5099,6 +5169,7 @@ int ci_dpm_init(struct radeon_device *rdev)
        pi->caps_sclk_throttle_low_notification = false;
 
        pi->caps_uvd_dpm = true;
+       pi->caps_vce_dpm = true;
 
         ci_get_leakage_voltages(rdev);
         ci_patch_dependency_tables_with_leakage(rdev);
@@ -5129,9 +5200,15 @@ int ci_dpm_init(struct radeon_device *rdev)
        rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
        rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
 
-       pi->thermal_temp_setting.temperature_low = 99500;
-       pi->thermal_temp_setting.temperature_high = 100000;
-       pi->thermal_temp_setting.temperature_shutdown = 104000;
+       if (rdev->family == CHIP_HAWAII) {
+               pi->thermal_temp_setting.temperature_low = 94500;
+               pi->thermal_temp_setting.temperature_high = 95000;
+               pi->thermal_temp_setting.temperature_shutdown = 104000;
+       } else {
+               pi->thermal_temp_setting.temperature_low = 99500;
+               pi->thermal_temp_setting.temperature_high = 100000;
+               pi->thermal_temp_setting.temperature_shutdown = 104000;
+       }
 
        pi->uvd_enabled = false;
 
index 1c18c7d..67911ed 100644 (file)
@@ -27,8 +27,8 @@
 #include "radeon.h"
 #include "cikd.h"
 #include "ppsmc.h"
-#include "ci_dpm.h"
 #include "radeon_ucode.h"
+#include "ci_dpm.h"
 
 static int ci_set_smc_sram_address(struct radeon_device *rdev,
                                   u32 smc_address, u32 limit)
@@ -51,7 +51,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
        u32 data, original_data;
        u32 addr;
        u32 extra_shift;
-       int ret;
+       int ret = 0;
 
        if (smc_start_address & 3)
                return -EINVAL;
@@ -60,13 +60,14 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
        addr = smc_start_address;
 
+       spin_lock(&rdev->smc_idx_lock);
        while (byte_count >= 4) {
                /* SMC address space is BE */
                data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
 
@@ -81,7 +82,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                original_data = RREG32(SMC_IND_DATA_0);
 
@@ -98,11 +99,15 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
        }
-       return 0;
+
+done:
+       spin_unlock(&rdev->smc_idx_lock);
+
+       return ret;
 }
 
 void ci_start_smc(struct radeon_device *rdev)
@@ -211,6 +216,10 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                ucode_start_address = BONAIRE_SMC_UCODE_START;
                ucode_size = BONAIRE_SMC_UCODE_SIZE;
                break;
+       case CHIP_HAWAII:
+               ucode_start_address = HAWAII_SMC_UCODE_START;
+               ucode_size = HAWAII_SMC_UCODE_SIZE;
+               break;
        default:
                DRM_ERROR("unknown asic in smc ucode loader\n");
                BUG();
@@ -220,6 +229,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                return -EINVAL;
 
        src = (const u8 *)rdev->smc_fw->data;
+       spin_lock(&rdev->smc_idx_lock);
        WREG32(SMC_IND_INDEX_0, ucode_start_address);
        WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
        while (ucode_size >= 4) {
@@ -232,6 +242,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                ucode_size -= 4;
        }
        WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
+       spin_unlock(&rdev->smc_idx_lock);
 
        return 0;
 }
@@ -241,12 +252,13 @@ int ci_read_smc_sram_dword(struct radeon_device *rdev,
 {
        int ret;
 
+       spin_lock(&rdev->smc_idx_lock);
        ret = ci_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               *value = RREG32(SMC_IND_DATA_0);
+       spin_unlock(&rdev->smc_idx_lock);
 
-       *value = RREG32(SMC_IND_DATA_0);
-       return 0;
+       return ret;
 }
 
 int ci_write_smc_sram_dword(struct radeon_device *rdev,
@@ -254,10 +266,11 @@ int ci_write_smc_sram_dword(struct radeon_device *rdev,
 {
        int ret;
 
+       spin_lock(&rdev->smc_idx_lock);
        ret = ci_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               WREG32(SMC_IND_DATA_0, value);
+       spin_unlock(&rdev->smc_idx_lock);
 
-       WREG32(SMC_IND_DATA_0, value);
-       return 0;
+       return ret;
 }
index 5f78989..a875442 100644 (file)
 #include "radeon_ucode.h"
 #include "clearstate_ci.h"
 
-#define PCI_EXP_LNKCTL PCIER_LINKCTRL /* 16 */
-#define PCI_EXP_LNKCTL2 48
-#define PCI_EXP_LNKCTL_HAWD PCIEM_LNKCTL_HAWD /* 0x0200 */
-#define PCI_EXP_DEVSTA PCIER_DEVSTS /* 10 */
-#define PCI_EXP_DEVSTA_TRPND 0x0020
-#define PCI_EXP_LNKCAP_CLKPM 0x00040000
-
 MODULE_FIRMWARE("radeon/BONAIRE_pfp.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_me.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_ce.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_mec.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_mc.bin");
+MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin");
 MODULE_FIRMWARE("radeon/BONAIRE_smc.bin");
+MODULE_FIRMWARE("radeon/HAWAII_pfp.bin");
+MODULE_FIRMWARE("radeon/HAWAII_me.bin");
+MODULE_FIRMWARE("radeon/HAWAII_ce.bin");
+MODULE_FIRMWARE("radeon/HAWAII_mec.bin");
+MODULE_FIRMWARE("radeon/HAWAII_mc.bin");
+MODULE_FIRMWARE("radeon/HAWAII_mc2.bin");
+MODULE_FIRMWARE("radeon/HAWAII_rlc.bin");
+MODULE_FIRMWARE("radeon/HAWAII_sdma.bin");
+MODULE_FIRMWARE("radeon/HAWAII_smc.bin");
 MODULE_FIRMWARE("radeon/KAVERI_pfp.bin");
 MODULE_FIRMWARE("radeon/KAVERI_me.bin");
 MODULE_FIRMWARE("radeon/KAVERI_ce.bin");
@@ -59,7 +62,14 @@ MODULE_FIRMWARE("radeon/KABINI_ce.bin");
 MODULE_FIRMWARE("radeon/KABINI_mec.bin");
 MODULE_FIRMWARE("radeon/KABINI_rlc.bin");
 MODULE_FIRMWARE("radeon/KABINI_sdma.bin");
-
+MODULE_FIRMWARE("radeon/MULLINS_pfp.bin");
+MODULE_FIRMWARE("radeon/MULLINS_me.bin");
+MODULE_FIRMWARE("radeon/MULLINS_ce.bin");
+MODULE_FIRMWARE("radeon/MULLINS_mec.bin");
+MODULE_FIRMWARE("radeon/MULLINS_rlc.bin");
+MODULE_FIRMWARE("radeon/MULLINS_sdma.bin");
+
+static u32 cik_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
 static void cik_rlc_stop(struct radeon_device *rdev);
 static void cik_pcie_gen3_enable(struct radeon_device *rdev);
 static void cik_program_aspm(struct radeon_device *rdev);
@@ -114,18 +124,22 @@ u32 cik_pciep_rreg(struct radeon_device *rdev, u32 reg)
 {
        u32 r;
 
+       spin_lock(&rdev->pciep_idx_lock);
        WREG32(PCIE_INDEX, reg);
        (void)RREG32(PCIE_INDEX);
        r = RREG32(PCIE_DATA);
+       spin_unlock(&rdev->pciep_idx_lock);
        return r;
 }
 
 void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       spin_lock(&rdev->pciep_idx_lock);
        WREG32(PCIE_INDEX, reg);
        (void)RREG32(PCIE_INDEX);
        WREG32(PCIE_DATA, v);
        (void)RREG32(PCIE_DATA);
+       spin_unlock(&rdev->pciep_idx_lock);
 }
 
 static const u32 spectre_rlc_save_restore_register_list[] =
@@ -1073,7 +1087,7 @@ static const u32 spectre_golden_registers[] =
        0x8a14, 0xf000003f, 0x00000007,
        0x8b24, 0xffffffff, 0x00ffffff,
        0x28350, 0x3f3f3fff, 0x00000082,
-       0x28355, 0x0000003f, 0x00000000,
+       0x28354, 0x0000003f, 0x00000000,
        0x3e78, 0x00000001, 0x00000002,
        0x913c, 0xffff03df, 0x00000004,
        0xc768, 0x00000008, 0x00000008,
@@ -1283,6 +1297,208 @@ static const u32 kalindi_mgcg_cgcg_init[] =
        0xd80c, 0xff000ff0, 0x00000100
 };
 
+static const u32 hawaii_golden_spm_registers[] =
+{
+       0x30800, 0xe0ffffff, 0xe0000000
+};
+
+static const u32 hawaii_golden_common_registers[] =
+{
+       0x30800, 0xffffffff, 0xe0000000,
+       0x28350, 0xffffffff, 0x3a00161a,
+       0x28354, 0xffffffff, 0x0000002e,
+       0x9a10, 0xffffffff, 0x00018208,
+       0x98f8, 0xffffffff, 0x12011003
+};
+
+static const u32 hawaii_golden_registers[] =
+{
+       0x3354, 0x00000333, 0x00000333,
+       0x9a10, 0x00010000, 0x00058208,
+       0x9830, 0xffffffff, 0x00000000,
+       0x9834, 0xf00fffff, 0x00000400,
+       0x9838, 0x0002021c, 0x00020200,
+       0xc78, 0x00000080, 0x00000000,
+       0x5bb0, 0x000000f0, 0x00000070,
+       0x5bc0, 0xf0311fff, 0x80300000,
+       0x350c, 0x00810000, 0x408af000,
+       0x7030, 0x31000111, 0x00000011,
+       0x2f48, 0x73773777, 0x12010001,
+       0x2120, 0x0000007f, 0x0000001b,
+       0x21dc, 0x00007fb6, 0x00002191,
+       0x3628, 0x0000003f, 0x0000000a,
+       0x362c, 0x0000003f, 0x0000000a,
+       0x2ae4, 0x00073ffe, 0x000022a2,
+       0x240c, 0x000007ff, 0x00000000,
+       0x8bf0, 0x00002001, 0x00000001,
+       0x8b24, 0xffffffff, 0x00ffffff,
+       0x30a04, 0x0000ff0f, 0x00000000,
+       0x28a4c, 0x07ffffff, 0x06000000,
+       0x3e78, 0x00000001, 0x00000002,
+       0xc768, 0x00000008, 0x00000008,
+       0xc770, 0x00000f00, 0x00000800,
+       0xc774, 0x00000f00, 0x00000800,
+       0xc798, 0x00ffffff, 0x00ff7fbf,
+       0xc79c, 0x00ffffff, 0x00ff7faf,
+       0x8c00, 0x000000ff, 0x00000800,
+       0xe40, 0x00001fff, 0x00001fff,
+       0x9060, 0x0000007f, 0x00000020,
+       0x9508, 0x00010000, 0x00010000,
+       0xae00, 0x00100000, 0x000ff07c,
+       0xac14, 0x000003ff, 0x0000000f,
+       0xac10, 0xffffffff, 0x7564fdec,
+       0xac0c, 0xffffffff, 0x3120b9a8,
+       0xac08, 0x20000000, 0x0f9c0000
+};
+
+static const u32 hawaii_mgcg_cgcg_init[] =
+{
+       0xc420, 0xffffffff, 0xfffffffd,
+       0x30800, 0xffffffff, 0xe0000000,
+       0x3c2a0, 0xffffffff, 0x00000100,
+       0x3c208, 0xffffffff, 0x00000100,
+       0x3c2c0, 0xffffffff, 0x00000100,
+       0x3c2c8, 0xffffffff, 0x00000100,
+       0x3c2c4, 0xffffffff, 0x00000100,
+       0x55e4, 0xffffffff, 0x00200100,
+       0x3c280, 0xffffffff, 0x00000100,
+       0x3c214, 0xffffffff, 0x06000100,
+       0x3c220, 0xffffffff, 0x00000100,
+       0x3c218, 0xffffffff, 0x06000100,
+       0x3c204, 0xffffffff, 0x00000100,
+       0x3c2e0, 0xffffffff, 0x00000100,
+       0x3c224, 0xffffffff, 0x00000100,
+       0x3c200, 0xffffffff, 0x00000100,
+       0x3c230, 0xffffffff, 0x00000100,
+       0x3c234, 0xffffffff, 0x00000100,
+       0x3c250, 0xffffffff, 0x00000100,
+       0x3c254, 0xffffffff, 0x00000100,
+       0x3c258, 0xffffffff, 0x00000100,
+       0x3c25c, 0xffffffff, 0x00000100,
+       0x3c260, 0xffffffff, 0x00000100,
+       0x3c27c, 0xffffffff, 0x00000100,
+       0x3c278, 0xffffffff, 0x00000100,
+       0x3c210, 0xffffffff, 0x06000100,
+       0x3c290, 0xffffffff, 0x00000100,
+       0x3c274, 0xffffffff, 0x00000100,
+       0x3c2b4, 0xffffffff, 0x00000100,
+       0x3c2b0, 0xffffffff, 0x00000100,
+       0x3c270, 0xffffffff, 0x00000100,
+       0x30800, 0xffffffff, 0xe0000000,
+       0x3c020, 0xffffffff, 0x00010000,
+       0x3c024, 0xffffffff, 0x00030002,
+       0x3c028, 0xffffffff, 0x00040007,
+       0x3c02c, 0xffffffff, 0x00060005,
+       0x3c030, 0xffffffff, 0x00090008,
+       0x3c034, 0xffffffff, 0x00010000,
+       0x3c038, 0xffffffff, 0x00030002,
+       0x3c03c, 0xffffffff, 0x00040007,
+       0x3c040, 0xffffffff, 0x00060005,
+       0x3c044, 0xffffffff, 0x00090008,
+       0x3c048, 0xffffffff, 0x00010000,
+       0x3c04c, 0xffffffff, 0x00030002,
+       0x3c050, 0xffffffff, 0x00040007,
+       0x3c054, 0xffffffff, 0x00060005,
+       0x3c058, 0xffffffff, 0x00090008,
+       0x3c05c, 0xffffffff, 0x00010000,
+       0x3c060, 0xffffffff, 0x00030002,
+       0x3c064, 0xffffffff, 0x00040007,
+       0x3c068, 0xffffffff, 0x00060005,
+       0x3c06c, 0xffffffff, 0x00090008,
+       0x3c070, 0xffffffff, 0x00010000,
+       0x3c074, 0xffffffff, 0x00030002,
+       0x3c078, 0xffffffff, 0x00040007,
+       0x3c07c, 0xffffffff, 0x00060005,
+       0x3c080, 0xffffffff, 0x00090008,
+       0x3c084, 0xffffffff, 0x00010000,
+       0x3c088, 0xffffffff, 0x00030002,
+       0x3c08c, 0xffffffff, 0x00040007,
+       0x3c090, 0xffffffff, 0x00060005,
+       0x3c094, 0xffffffff, 0x00090008,
+       0x3c098, 0xffffffff, 0x00010000,
+       0x3c09c, 0xffffffff, 0x00030002,
+       0x3c0a0, 0xffffffff, 0x00040007,
+       0x3c0a4, 0xffffffff, 0x00060005,
+       0x3c0a8, 0xffffffff, 0x00090008,
+       0x3c0ac, 0xffffffff, 0x00010000,
+       0x3c0b0, 0xffffffff, 0x00030002,
+       0x3c0b4, 0xffffffff, 0x00040007,
+       0x3c0b8, 0xffffffff, 0x00060005,
+       0x3c0bc, 0xffffffff, 0x00090008,
+       0x3c0c0, 0xffffffff, 0x00010000,
+       0x3c0c4, 0xffffffff, 0x00030002,
+       0x3c0c8, 0xffffffff, 0x00040007,
+       0x3c0cc, 0xffffffff, 0x00060005,
+       0x3c0d0, 0xffffffff, 0x00090008,
+       0x3c0d4, 0xffffffff, 0x00010000,
+       0x3c0d8, 0xffffffff, 0x00030002,
+       0x3c0dc, 0xffffffff, 0x00040007,
+       0x3c0e0, 0xffffffff, 0x00060005,
+       0x3c0e4, 0xffffffff, 0x00090008,
+       0x3c0e8, 0xffffffff, 0x00010000,
+       0x3c0ec, 0xffffffff, 0x00030002,
+       0x3c0f0, 0xffffffff, 0x00040007,
+       0x3c0f4, 0xffffffff, 0x00060005,
+       0x3c0f8, 0xffffffff, 0x00090008,
+       0xc318, 0xffffffff, 0x00020200,
+       0x3350, 0xffffffff, 0x00000200,
+       0x15c0, 0xffffffff, 0x00000400,
+       0x55e8, 0xffffffff, 0x00000000,
+       0x2f50, 0xffffffff, 0x00000902,
+       0x3c000, 0xffffffff, 0x96940200,
+       0x8708, 0xffffffff, 0x00900100,
+       0xc424, 0xffffffff, 0x0020003f,
+       0x38, 0xffffffff, 0x0140001c,
+       0x3c, 0x000f0000, 0x000f0000,
+       0x220, 0xffffffff, 0xc060000c,
+       0x224, 0xc0000fff, 0x00000100,
+       0xf90, 0xffffffff, 0x00000100,
+       0xf98, 0x00000101, 0x00000000,
+       0x20a8, 0xffffffff, 0x00000104,
+       0x55e4, 0xff000fff, 0x00000100,
+       0x30cc, 0xc0000fff, 0x00000104,
+       0xc1e4, 0x00000001, 0x00000001,
+       0xd00c, 0xff000ff0, 0x00000100,
+       0xd80c, 0xff000ff0, 0x00000100
+};
+
+static const u32 godavari_golden_registers[] =
+{
+       0x55e4, 0xff607fff, 0xfc000100,
+       0x6ed8, 0x00010101, 0x00010000,
+       0x9830, 0xffffffff, 0x00000000,
+       0x98302, 0xf00fffff, 0x00000400,
+       0x6130, 0xffffffff, 0x00010000,
+       0x5bb0, 0x000000f0, 0x00000070,
+       0x5bc0, 0xf0311fff, 0x80300000,
+       0x98f8, 0x73773777, 0x12010001,
+       0x98fc, 0xffffffff, 0x00000010,
+       0x8030, 0x00001f0f, 0x0000100a,
+       0x2f48, 0x73773777, 0x12010001,
+       0x2408, 0x000fffff, 0x000c007f,
+       0x8a14, 0xf000003f, 0x00000007,
+       0x8b24, 0xffffffff, 0x00ff0fff,
+       0x30a04, 0x0000ff0f, 0x00000000,
+       0x28a4c, 0x07ffffff, 0x06000000,
+       0x4d8, 0x00000fff, 0x00000100,
+       0xd014, 0x00010000, 0x00810001,
+       0xd814, 0x00010000, 0x00810001,
+       0x3e78, 0x00000001, 0x00000002,
+       0xc768, 0x00000008, 0x00000008,
+       0xc770, 0x00000f00, 0x00000800,
+       0xc774, 0x00000f00, 0x00000800,
+       0xc798, 0x00ffffff, 0x00ff7fbf,
+       0xc79c, 0x00ffffff, 0x00ff7faf,
+       0x8c00, 0x000000ff, 0x00000001,
+       0x214f8, 0x01ff01ff, 0x00000002,
+       0x21498, 0x007ff800, 0x00200000,
+       0x2015c, 0xffffffff, 0x00000f40,
+       0x88c4, 0x001f3ae3, 0x00000082,
+       0x88d4, 0x0000001f, 0x00000010,
+       0x30934, 0xffffffff, 0x00000000
+};
+
+
 static void cik_init_golden_registers(struct radeon_device *rdev)
 {
        switch (rdev->family) {
@@ -1314,6 +1530,20 @@ static void cik_init_golden_registers(struct radeon_device *rdev)
                                                 kalindi_golden_spm_registers,
                                                 (const u32)ARRAY_SIZE(kalindi_golden_spm_registers));
                break;
+       case CHIP_MULLINS:
+               radeon_program_register_sequence(rdev,
+                                                kalindi_mgcg_cgcg_init,
+                                                (const u32)ARRAY_SIZE(kalindi_mgcg_cgcg_init));
+               radeon_program_register_sequence(rdev,
+                                                godavari_golden_registers,
+                                                (const u32)ARRAY_SIZE(godavari_golden_registers));
+               radeon_program_register_sequence(rdev,
+                                                kalindi_golden_common_registers,
+                                                (const u32)ARRAY_SIZE(kalindi_golden_common_registers));
+               radeon_program_register_sequence(rdev,
+                                                kalindi_golden_spm_registers,
+                                                (const u32)ARRAY_SIZE(kalindi_golden_spm_registers));
+               break;
        case CHIP_KAVERI:
                radeon_program_register_sequence(rdev,
                                                 spectre_mgcg_cgcg_init,
@@ -1328,6 +1558,20 @@ static void cik_init_golden_registers(struct radeon_device *rdev)
                                                 spectre_golden_spm_registers,
                                                 (const u32)ARRAY_SIZE(spectre_golden_spm_registers));
                break;
+       case CHIP_HAWAII:
+               radeon_program_register_sequence(rdev,
+                                                hawaii_mgcg_cgcg_init,
+                                                (const u32)ARRAY_SIZE(hawaii_mgcg_cgcg_init));
+               radeon_program_register_sequence(rdev,
+                                                hawaii_golden_registers,
+                                                (const u32)ARRAY_SIZE(hawaii_golden_registers));
+               radeon_program_register_sequence(rdev,
+                                                hawaii_golden_common_registers,
+                                                (const u32)ARRAY_SIZE(hawaii_golden_common_registers));
+               radeon_program_register_sequence(rdev,
+                                                hawaii_golden_spm_registers,
+                                                (const u32)ARRAY_SIZE(hawaii_golden_spm_registers));
+               break;
        default:
                break;
        }
@@ -1359,17 +1603,17 @@ u32 cik_get_xclk(struct radeon_device *rdev)
  * cik_mm_rdoorbell - read a doorbell dword
  *
  * @rdev: radeon_device pointer
- * @offset: byte offset into the aperture
+ * @index: doorbell index
  *
  * Returns the value in the doorbell aperture at the
- * requested offset (CIK).
+ * requested doorbell index (CIK).
  */
-u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset)
+u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index)
 {
-       if (offset < rdev->doorbell.size) {
-               return readl(((uint8_t __iomem *)rdev->doorbell.ptr) + offset);
+       if (index < rdev->doorbell.num_doorbells) {
+               return readl(rdev->doorbell.ptr + index);
        } else {
-               DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", offset);
+               DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index);
                return 0;
        }
 }
@@ -1378,18 +1622,18 @@ u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset)
  * cik_mm_wdoorbell - write a doorbell dword
  *
  * @rdev: radeon_device pointer
- * @offset: byte offset into the aperture
+ * @index: doorbell index
  * @v: value to write
  *
  * Writes @v to the doorbell aperture at the
- * requested offset (CIK).
+ * requested doorbell index (CIK).
  */
-void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v)
+void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v)
 {
-       if (offset < rdev->doorbell.size) {
-               writel(v, ((uint8_t __iomem *)rdev->doorbell.ptr) + offset);
+       if (index < rdev->doorbell.num_doorbells) {
+               writel(v, rdev->doorbell.ptr + index);
        } else {
-               DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", offset);
+               DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index);
        }
 }
 
@@ -1435,6 +1679,35 @@ static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] =
        {0x0000009f, 0x00b48000}
 };
 
+#define HAWAII_IO_MC_REGS_SIZE 22
+
+static const u32 hawaii_io_mc_regs[HAWAII_IO_MC_REGS_SIZE][2] =
+{
+       {0x0000007d, 0x40000000},
+       {0x0000007e, 0x40180304},
+       {0x0000007f, 0x0000ff00},
+       {0x00000081, 0x00000000},
+       {0x00000083, 0x00000800},
+       {0x00000086, 0x00000000},
+       {0x00000087, 0x00000100},
+       {0x00000088, 0x00020100},
+       {0x00000089, 0x00000000},
+       {0x0000008b, 0x00040000},
+       {0x0000008c, 0x00000100},
+       {0x0000008e, 0xff010000},
+       {0x00000090, 0xffffefff},
+       {0x00000091, 0xfff3efff},
+       {0x00000092, 0xfff3efbf},
+       {0x00000093, 0xf7ffffff},
+       {0x00000094, 0xffffff7f},
+       {0x00000095, 0x00000fff},
+       {0x00000096, 0x00116fff},
+       {0x00000097, 0x60010000},
+       {0x00000098, 0x10010000},
+       {0x0000009f, 0x00c79000}
+};
+
+
 /**
  * cik_srbm_select - select specific register instances
  *
@@ -1467,23 +1740,29 @@ static void cik_srbm_select(struct radeon_device *rdev,
  * Load the GDDR MC ucode into the hw (CIK).
  * Returns 0 on success, error on failure.
  */
-static int ci_mc_load_microcode(struct radeon_device *rdev)
+int ci_mc_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
        u32 running, blackout = 0;
        u32 *io_mc_regs;
-       int i, ucode_size, regs_size;
+       int i, regs_size, ucode_size;
 
        if (!rdev->mc_fw)
                return -EINVAL;
 
+       ucode_size = rdev->mc_fw->datasize / 4;
+
        switch (rdev->family) {
        case CHIP_BONAIRE:
-       default:
                io_mc_regs = (u32 *)&bonaire_io_mc_regs;
-               ucode_size = CIK_MC_UCODE_SIZE;
                regs_size = BONAIRE_IO_MC_REGS_SIZE;
                break;
+       case CHIP_HAWAII:
+               io_mc_regs = (u32 *)&hawaii_io_mc_regs;
+               regs_size = HAWAII_IO_MC_REGS_SIZE;
+               break;
+       default:
+               return -EINVAL;
        }
 
        running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1545,8 +1824,8 @@ static int cik_init_microcode(struct radeon_device *rdev)
 {
        const char *chip_name;
        size_t pfp_req_size, me_req_size, ce_req_size,
-               mec_req_size, rlc_req_size, mc_req_size,
-               sdma_req_size, smc_req_size;
+               mec_req_size, rlc_req_size, mc_req_size = 0,
+               sdma_req_size, smc_req_size = 0, mc2_req_size = 0;
        char fw_name[30];
        int err;
 
@@ -1560,10 +1839,23 @@ static int cik_init_microcode(struct radeon_device *rdev)
                ce_req_size = CIK_CE_UCODE_SIZE * 4;
                mec_req_size = CIK_MEC_UCODE_SIZE * 4;
                rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4;
-               mc_req_size = CIK_MC_UCODE_SIZE * 4;
+               mc_req_size = BONAIRE_MC_UCODE_SIZE * 4;
+               mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4;
                sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
                smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4);
                break;
+       case CHIP_HAWAII:
+               chip_name = "HAWAII";
+               pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
+               me_req_size = CIK_ME_UCODE_SIZE * 4;
+               ce_req_size = CIK_CE_UCODE_SIZE * 4;
+               mec_req_size = CIK_MEC_UCODE_SIZE * 4;
+               rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4;
+               mc_req_size = HAWAII_MC_UCODE_SIZE * 4;
+               mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4;
+               sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+               smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4);
+               break;
        case CHIP_KAVERI:
                chip_name = "KAVERI";
                pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
@@ -1582,6 +1874,15 @@ static int cik_init_microcode(struct radeon_device *rdev)
                rlc_req_size = KB_RLC_UCODE_SIZE * 4;
                sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
                break;
+       case CHIP_MULLINS:
+               chip_name = "MULLINS";
+               pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
+               me_req_size = CIK_ME_UCODE_SIZE * 4;
+               ce_req_size = CIK_CE_UCODE_SIZE * 4;
+               mec_req_size = CIK_MEC_UCODE_SIZE * 4;
+               rlc_req_size = ML_RLC_UCODE_SIZE * 4;
+               sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+               break;
        default: BUG();
        }
 
@@ -1656,16 +1957,22 @@ static int cik_init_microcode(struct radeon_device *rdev)
 
        /* No SMC, MC ucode on APUs */
        if (!(rdev->flags & RADEON_IS_IGP)) {
-               ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name);
+               ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc2", chip_name);
                err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
-               if (err)
-                       goto out;
-               if (rdev->mc_fw->datasize != mc_req_size) {
+               if (err) {
+                       ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name);
+                       err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+                       if (err)
+                               goto out;
+               }
+               if ((rdev->mc_fw->datasize != mc_req_size) &&
+                   (rdev->mc_fw->datasize != mc2_req_size)){
                        printk(KERN_ERR
                               "cik_mc: Bogus length %zu in firmware \"%s\"\n",
                               rdev->mc_fw->datasize, fw_name);
                        err = -EINVAL;
                }
+               DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->datasize);
 
                ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_smc", chip_name);
                err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
@@ -1748,125 +2055,129 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
 
        num_pipe_configs = rdev->config.cik.max_tile_pipes;
        if (num_pipe_configs > 8)
-               num_pipe_configs = 8; /* ??? */
+               num_pipe_configs = 16;
 
-       if (num_pipe_configs == 8) {
+       if (num_pipe_configs == 16) {
                for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
                        switch (reg_offset) {
                        case 0:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B));
                                break;
                        case 1:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B));
                                break;
                        case 2:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
                                break;
                        case 3:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B));
                                break;
                        case 4:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(split_equal_to_row_size));
                                break;
                        case 5:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                break;
                        case 6:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
                                break;
                        case 7:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 TILE_SPLIT(split_equal_to_row_size));
                                break;
                        case 8:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16));
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
                                break;
                        case 9:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                break;
                        case 10:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 11:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_8x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 12:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 13:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                break;
                        case 14:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 16:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_8x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 17:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 27:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                break;
                        case 28:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 29:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_8x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        case 30:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
                                                 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
                                break;
                        default:
@@ -1881,7 +2192,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                        case 0:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 1:
@@ -1893,13 +2204,13 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                        case 2:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 3:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 4:
@@ -1922,39 +2233,39 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 8:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 9:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 10:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
                                                 NUM_BANKS(ADDR_SURF_16_BANK));
                                break;
                        case 11:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_8_BANK));
                                break;
                        case 12:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
                                                 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-                                                NUM_BANKS(ADDR_SURF_8_BANK));
+                                                NUM_BANKS(ADDR_SURF_4_BANK));
                                break;
                        case 13:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
                                                 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
                                                 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-                                                NUM_BANKS(ADDR_SURF_4_BANK));
+                                                NUM_BANKS(ADDR_SURF_2_BANK));
                                break;
                        case 14:
                                gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
@@ -1966,31 +2277,255 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                gb_tile_moden = 0;
                                break;
                        }
+                       rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
                        WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
-       } else if (num_pipe_configs == 4) {
-               if (num_rbs == 4) {
-                       for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-                               switch (reg_offset) {
-                               case 0:
-                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B));
-                                       break;
-                               case 1:
-                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B));
-                                       break;
-                               case 2:
-                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
-                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
-                                       break;
-                               case 3:
+       } else if (num_pipe_configs == 8) {
+               for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+                       switch (reg_offset) {
+                       case 0:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B));
+                               break;
+                       case 1:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B));
+                               break;
+                       case 2:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
+                               break;
+                       case 3:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B));
+                               break;
+                       case 4:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(split_equal_to_row_size));
+                               break;
+                       case 5:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 6:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
+                               break;
+                       case 7:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                TILE_SPLIT(split_equal_to_row_size));
+                               break;
+                       case 8:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16));
+                               break;
+                       case 9:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
+                               break;
+                       case 10:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 11:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 12:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 13:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
+                               break;
+                       case 14:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 16:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 17:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 27:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
+                               break;
+                       case 28:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 29:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 30:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+                                                SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       default:
+                               gb_tile_moden = 0;
+                               break;
+                       }
+                       rdev->config.cik.tile_mode_array[reg_offset] = gb_tile_moden;
+                       WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
+               }
+               for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
+                       switch (reg_offset) {
+                       case 0:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 1:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 2:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 3:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 4:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 5:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_4_BANK));
+                               break;
+                       case 6:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_2_BANK));
+                               break;
+                       case 8:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 9:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 10:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 11:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                                NUM_BANKS(ADDR_SURF_16_BANK));
+                               break;
+                       case 12:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 13:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_4_BANK));
+                               break;
+                       case 14:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                                BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                                MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                                NUM_BANKS(ADDR_SURF_2_BANK));
+                               break;
+                       default:
+                               gb_tile_moden = 0;
+                               break;
+                       }
+                       rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
+                       WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
+               }
+       } else if (num_pipe_configs == 4) {
+               if (num_rbs == 4) {
+                       for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+                               switch (reg_offset) {
+                               case 0:
+                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B));
+                                       break;
+                               case 1:
+                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B));
+                                       break;
+                               case 2:
+                                       gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                                        MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                                        TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B));
+                                       break;
+                               case 3:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING) |
                                                         PIPE_CONFIG(ADDR_SURF_P4_16x16) |
@@ -2004,6 +2539,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 5:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                        break;
                                case 6:
@@ -2024,6 +2560,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 9:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                        break;
                                case 10:
@@ -2046,6 +2583,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 13:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                        break;
                                case 14:
@@ -2068,6 +2606,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 27:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                        break;
                                case 28:
@@ -2130,6 +2669,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 5:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                        break;
                                case 6:
@@ -2150,6 +2690,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 9:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
                                        break;
                                case 10:
@@ -2172,6 +2713,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 13:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                        break;
                                case 14:
@@ -2194,6 +2736,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                        break;
                                case 27:
                                        gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                        PIPE_CONFIG(ADDR_SURF_P4_8x16) |
                                                         MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
                                        break;
                                case 28:
@@ -2312,6 +2855,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                gb_tile_moden = 0;
                                break;
                        }
+                       rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
                        WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
        } else if (num_pipe_configs == 2) {
@@ -2349,6 +2893,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 5:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P2) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
                                break;
                        case 6:
@@ -2364,11 +2909,13 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                                 TILE_SPLIT(split_equal_to_row_size));
                                break;
                        case 8:
-                               gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED);
+                               gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+                                               PIPE_CONFIG(ADDR_SURF_P2);
                                break;
                        case 9:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P2));
                                break;
                        case 10:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
@@ -2390,6 +2937,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 13:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                                PIPE_CONFIG(ADDR_SURF_P2) |
                                                 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
                                break;
                        case 14:
@@ -2412,7 +2960,8 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                break;
                        case 27:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
+                                                MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                                PIPE_CONFIG(ADDR_SURF_P2));
                                break;
                        case 28:
                                gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
@@ -2529,6 +3078,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
                                gb_tile_moden = 0;
                                break;
                        }
+                       rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
                        WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
        } else
@@ -2582,7 +3132,7 @@ static u32 cik_create_bitmask(u32 bit_width)
 }
 
 /**
- * cik_select_se_sh - select which SE, SH to address
+ * cik_get_rb_disabled - computes the mask of disabled RBs
  *
  * @rdev: radeon_device pointer
  * @max_rb_num: max RBs (render backends) for the asic
@@ -2593,7 +3143,7 @@ static u32 cik_create_bitmask(u32 bit_width)
  * Returns the disabled RB bitmask.
  */
 static u32 cik_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -2607,7 +3157,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
@@ -2624,7 +3174,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
  */
 static void cik_setup_rb(struct radeon_device *rdev,
                         u32 se_num, u32 sh_per_se,
-                        u32 max_rb_num)
+                        u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -2634,24 +3184,35 @@ static void cik_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        cik_select_se_sh(rdev, i, j);
-                       data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
-                       disabled_rbs |= data << ((i * sh_per_se + j) * CIK_RB_BITMAP_WIDTH_PER_SH);
+                       data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
+                       if (rdev->family == CHIP_HAWAII)
+                               disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH);
+                       else
+                               disabled_rbs |= data << ((i * sh_per_se + j) * CIK_RB_BITMAP_WIDTH_PER_SH);
                }
        }
        cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.cik.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                cik_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
                for (j = 0; j < sh_per_se; j++) {
                        switch (enabled_rbs & 3) {
+                       case 0:
+                               if (j == 0)
+                                       data |= PKR_MAP(RASTER_CONFIG_RB_MAP_3);
+                               else
+                                       data |= PKR_MAP(RASTER_CONFIG_RB_MAP_0);
+                               break;
                        case 1:
                                data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2);
                                break;
@@ -2704,31 +3265,49 @@ static void cik_gpu_init(struct radeon_device *rdev)
                rdev->config.cik.sc_earlyz_tile_fifo_size = 0x130;
                gb_addr_config = BONAIRE_GB_ADDR_CONFIG_GOLDEN;
                break;
+       case CHIP_HAWAII:
+               rdev->config.cik.max_shader_engines = 4;
+               rdev->config.cik.max_tile_pipes = 16;
+               rdev->config.cik.max_cu_per_sh = 11;
+               rdev->config.cik.max_sh_per_se = 1;
+               rdev->config.cik.max_backends_per_se = 4;
+               rdev->config.cik.max_texture_channel_caches = 16;
+               rdev->config.cik.max_gprs = 256;
+               rdev->config.cik.max_gs_threads = 32;
+               rdev->config.cik.max_hw_contexts = 8;
+
+               rdev->config.cik.sc_prim_fifo_size_frontend = 0x20;
+               rdev->config.cik.sc_prim_fifo_size_backend = 0x100;
+               rdev->config.cik.sc_hiz_tile_fifo_size = 0x30;
+               rdev->config.cik.sc_earlyz_tile_fifo_size = 0x130;
+               gb_addr_config = HAWAII_GB_ADDR_CONFIG_GOLDEN;
+               break;
        case CHIP_KAVERI:
                rdev->config.cik.max_shader_engines = 1;
                rdev->config.cik.max_tile_pipes = 4;
-               if ((rdev->ddev->pci_device == 0x1304) ||
-                   (rdev->ddev->pci_device == 0x1305) ||
-                   (rdev->ddev->pci_device == 0x130C) ||
-                   (rdev->ddev->pci_device == 0x130F) ||
-                   (rdev->ddev->pci_device == 0x1310) ||
-                   (rdev->ddev->pci_device == 0x1311) ||
-                   (rdev->ddev->pci_device == 0x131C)) {
+               if ((rdev->pdev->device == 0x1304) ||
+                   (rdev->pdev->device == 0x1305) ||
+                   (rdev->pdev->device == 0x130C) ||
+                   (rdev->pdev->device == 0x130F) ||
+                   (rdev->pdev->device == 0x1310) ||
+                   (rdev->pdev->device == 0x1311) ||
+                   (rdev->pdev->device == 0x131C)) {
                        rdev->config.cik.max_cu_per_sh = 8;
                        rdev->config.cik.max_backends_per_se = 2;
-               } else if ((rdev->ddev->pci_device == 0x1309) ||
-                          (rdev->ddev->pci_device == 0x130A) ||
-                          (rdev->ddev->pci_device == 0x130D) ||
-                          (rdev->ddev->pci_device == 0x1313) ||
-                          (rdev->ddev->pci_device == 0x131D)) {
+               } else if ((rdev->pdev->device == 0x1309) ||
+                          (rdev->pdev->device == 0x130A) ||
+                          (rdev->pdev->device == 0x130D) ||
+                          (rdev->pdev->device == 0x1313) ||
+                          (rdev->pdev->device == 0x131D)) {
                        rdev->config.cik.max_cu_per_sh = 6;
                        rdev->config.cik.max_backends_per_se = 2;
-               } else if ((rdev->ddev->pci_device == 0x1306) ||
-                          (rdev->ddev->pci_device == 0x1307) ||
-                          (rdev->ddev->pci_device == 0x130B) ||
-                          (rdev->ddev->pci_device == 0x130E) ||
-                          (rdev->ddev->pci_device == 0x1315) ||
-                          (rdev->ddev->pci_device == 0x131B)) {
+               } else if ((rdev->pdev->device == 0x1306) ||
+                          (rdev->pdev->device == 0x1307) ||
+                          (rdev->pdev->device == 0x130B) ||
+                          (rdev->pdev->device == 0x130E) ||
+                          (rdev->pdev->device == 0x1315) ||
+                          (rdev->pdev->device == 0x1318) ||
+                          (rdev->pdev->device == 0x131B)) {
                        rdev->config.cik.max_cu_per_sh = 4;
                        rdev->config.cik.max_backends_per_se = 1;
                } else {
@@ -2748,6 +3327,7 @@ static void cik_gpu_init(struct radeon_device *rdev)
                gb_addr_config = BONAIRE_GB_ADDR_CONFIG_GOLDEN;
                break;
        case CHIP_KABINI:
+       case CHIP_MULLINS:
        default:
                rdev->config.cik.max_shader_engines = 1;
                rdev->config.cik.max_tile_pipes = 2;
@@ -2855,6 +3435,14 @@ static void cik_gpu_init(struct radeon_device *rdev)
                     rdev->config.cik.max_sh_per_se,
                     rdev->config.cik.max_backends_per_se);
 
+       rdev->config.cik.active_cus = 0;
+       for (i = 0; i < rdev->config.cik.max_shader_engines; i++) {
+               for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) {
+                       rdev->config.cik.active_cus +=
+                               hweight32(cik_get_cu_active_bitmap(rdev, i, j));
+               }
+       }
+
        /* set HW defaults for 3D engine */
        WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
 
@@ -2975,7 +3563,7 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
        radeon_ring_write(ring, PACKET3(PACKET3_SET_UCONFIG_REG, 1));
        radeon_ring_write(ring, ((scratch - PACKET3_SET_UCONFIG_REG_START) >> 2));
        radeon_ring_write(ring, 0xDEADBEEF);
-       radeon_ring_unlock_commit(rdev, ring);
+       radeon_ring_unlock_commit(rdev, ring, false);
 
        for (i = 0; i < rdev->usec_timeout; i++) {
                tmp = RREG32(scratch);
@@ -2994,6 +3582,51 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
        return r;
 }
 
+/**
+ * cik_hdp_flush_cp_ring_emit - emit an hdp flush on the cp
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emits an hdp flush on the cp.
+ */
+static void cik_hdp_flush_cp_ring_emit(struct radeon_device *rdev,
+                                      int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 ref_and_mask;
+
+       switch (ring->idx) {
+       case CAYMAN_RING_TYPE_CP1_INDEX:
+       case CAYMAN_RING_TYPE_CP2_INDEX:
+       default:
+               switch (ring->me) {
+               case 0:
+                       ref_and_mask = CP2 << ring->pipe;
+                       break;
+               case 1:
+                       ref_and_mask = CP6 << ring->pipe;
+                       break;
+               default:
+                       return;
+               }
+               break;
+       case RADEON_RING_TYPE_GFX_INDEX:
+               ref_and_mask = CP0;
+               break;
+       }
+
+       radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+       radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(1) | /* write, wait, write */
+                                WAIT_REG_MEM_FUNCTION(3) |  /* == */
+                                WAIT_REG_MEM_ENGINE(1)));   /* pfp */
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ >> 2);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE >> 2);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, 0x20); /* poll interval */
+}
+
 /**
  * cik_fence_gfx_ring_emit - emit a fence on the gfx ring
  *
@@ -3019,16 +3652,6 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | DATA_SEL(1) | INT_SEL(2));
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
-       /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
 }
 
 /**
@@ -3057,19 +3680,20 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, upper_32_bits(addr));
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
-       /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
 }
 
-void cik_semaphore_ring_emit(struct radeon_device *rdev,
+/**
+ * cik_semaphore_ring_emit - emit a semaphore on the CP ring
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring buffer object
+ * @semaphore: radeon semaphore object
+ * @emit_wait: Is this a sempahore wait?
+ *
+ * Emits a semaphore signal/wait packet to the CP ring and prevents the PFP
+ * from running ahead of semaphore waits.
+ */
+bool cik_semaphore_ring_emit(struct radeon_device *rdev,
                             struct radeon_ring *ring,
                             struct radeon_semaphore *semaphore,
                             bool emit_wait)
@@ -3078,8 +3702,91 @@ void cik_semaphore_ring_emit(struct radeon_device *rdev,
        unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL;
 
        radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1));
-       radeon_ring_write(ring, addr & 0xffffffff);
+       radeon_ring_write(ring, lower_32_bits(addr));
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel);
+
+       if (emit_wait && ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
+               /* Prevent the PFP from running ahead of the semaphore wait */
+               radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+               radeon_ring_write(ring, 0x0);
+       }
+
+       return true;
+}
+
+/**
+ * cik_copy_cpdma - copy pages using the CP DMA engine
+ *
+ * @rdev: radeon_device pointer
+ * @src_offset: src GPU address
+ * @dst_offset: dst GPU address
+ * @num_gpu_pages: number of GPU pages to xfer
+ * @fence: radeon fence object
+ *
+ * Copy GPU paging using the CP DMA engine (CIK+).
+ * Used by the radeon ttm implementation to move pages if
+ * registered as the asic copy callback.
+ */
+int cik_copy_cpdma(struct radeon_device *rdev,
+                  uint64_t src_offset, uint64_t dst_offset,
+                  unsigned num_gpu_pages,
+                  struct radeon_fence **fence)
+{
+       struct radeon_semaphore *sem = NULL;
+       int ring_index = rdev->asic->copy.blit_ring_index;
+       struct radeon_ring *ring = &rdev->ring[ring_index];
+       u32 size_in_bytes, cur_size_in_bytes, control;
+       int i, num_loops;
+       int r = 0;
+
+       r = radeon_semaphore_create(rdev, &sem);
+       if (r) {
+               DRM_ERROR("radeon: moving bo (%d).\n", r);
+               return r;
+       }
+
+       size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
+       num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff);
+       r = radeon_ring_lock(rdev, ring, num_loops * 7 + 18);
+       if (r) {
+               DRM_ERROR("radeon: moving bo (%d).\n", r);
+               radeon_semaphore_free(rdev, &sem, NULL);
+               return r;
+       }
+
+       radeon_semaphore_sync_to(sem, *fence);
+       radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+       for (i = 0; i < num_loops; i++) {
+               cur_size_in_bytes = size_in_bytes;
+               if (cur_size_in_bytes > 0x1fffff)
+                       cur_size_in_bytes = 0x1fffff;
+               size_in_bytes -= cur_size_in_bytes;
+               control = 0;
+               if (size_in_bytes == 0)
+                       control |= PACKET3_DMA_DATA_CP_SYNC;
+               radeon_ring_write(ring, PACKET3(PACKET3_DMA_DATA, 5));
+               radeon_ring_write(ring, control);
+               radeon_ring_write(ring, lower_32_bits(src_offset));
+               radeon_ring_write(ring, upper_32_bits(src_offset));
+               radeon_ring_write(ring, lower_32_bits(dst_offset));
+               radeon_ring_write(ring, upper_32_bits(dst_offset));
+               radeon_ring_write(ring, cur_size_in_bytes);
+               src_offset += cur_size_in_bytes;
+               dst_offset += cur_size_in_bytes;
+       }
+
+       r = radeon_fence_emit(rdev, fence, ring->idx);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
+               return r;
+       }
+
+       radeon_ring_unlock_commit(rdev, ring, false);
+       radeon_semaphore_free(rdev, &sem, *fence);
+
+       return r;
 }
 
 /*
@@ -3121,7 +3828,7 @@ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
                        radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
                        radeon_ring_write(ring, WRITE_DATA_DST_SEL(1));
                        radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
-                       radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
+                       radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr));
                        radeon_ring_write(ring, next_rptr);
                }
 
@@ -3175,7 +3882,7 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        ib.ptr[1] = ((scratch - PACKET3_SET_UCONFIG_REG_START) >> 2);
        ib.ptr[2] = 0xDEADBEEF;
        ib.length_dw = 3;
-       r = radeon_ib_schedule(rdev, &ib, NULL);
+       r = radeon_ib_schedule(rdev, &ib, NULL, false);
        if (r) {
                radeon_scratch_free(rdev, scratch);
                radeon_ib_free(rdev, &ib);
@@ -3243,6 +3950,8 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable)
        if (enable)
                WREG32(CP_ME_CNTL, 0);
        else {
+               if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+                       radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
                WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
                rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
        }
@@ -3351,7 +4060,7 @@ static int cik_cp_gfx_start(struct radeon_device *rdev)
        radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
        radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */
 
-       radeon_ring_unlock_commit(rdev, ring);
+       radeon_ring_unlock_commit(rdev, ring, false);
 
        return 0;
 }
@@ -3388,7 +4097,8 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
        int r;
 
        WREG32(CP_SEM_WAIT_TIMER, 0x0);
-       WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
+       if (rdev->family != CHIP_HAWAII)
+               WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
 
        /* Set the write pointer delay */
        WREG32(CP_RB_WPTR_DELAY, 0);
@@ -3430,8 +4140,6 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
        WREG32(CP_RB0_BASE, rb_addr);
        WREG32(CP_RB0_BASE_HI, upper_32_bits(rb_addr));
 
-       ring->rptr = RREG32(CP_RB0_RPTR);
-
        /* start the ring */
        cik_cp_gfx_start(rdev);
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
@@ -3440,18 +4148,50 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
                rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
                return r;
        }
+
+       if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+               radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+
        return 0;
 }
 
-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring)
+u32 cik_gfx_get_rptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
 {
        u32 rptr;
 
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(CP_RB0_RPTR);
+
+       return rptr;
+}
+
+u32 cik_gfx_get_wptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(CP_RB0_WPTR);
+
+       return wptr;
+}
 
+void cik_gfx_set_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       WREG32(CP_RB0_WPTR, ring->wptr);
+       (void)RREG32(CP_RB0_WPTR);
+}
+
+u32 cik_compute_get_rptr(struct radeon_device *rdev,
+                        struct radeon