]> Git Repo - J-linux.git/commitdiff
Merge remote branch 'anholt/drm-intel-next' into drm-next
authorDave Airlie <[email protected]>
Tue, 18 May 2010 23:35:51 +0000 (09:35 +1000)
committerDave Airlie <[email protected]>
Tue, 18 May 2010 23:35:51 +0000 (09:35 +1000)
* anholt/drm-intel-next: (515 commits)
  drm/i915: Fix out of tree builds
  drm/i915: move fence lru to struct drm_i915_fence_reg
  drm/i915: don't allow tiling changes on pinned buffers v2
  drm/i915: Be extra careful about A/D matching for multifunction SDVO
  drm/i915: Fix DDC bus selection for multifunction SDVO
  drm/i915: cleanup mode setting before unmapping registers
  drm/i915: Make fbc control wrapper functions
  drm/i915: Wait for the GPU whilst shrinking, if truly desperate.
  drm/i915: Use spatio-temporal dithering on PCH
  [MTD] Remove zero-length files mtdbdi.c and internal.ho
  pata_pcmcia / ide-cs: Fix bad hashes for Transcend and kingston IDs
  libata: Fix several inaccuracies in developer's guide
  slub: Fix bad boundary check in init_kmem_cache_nodes()
  raid6: fix recovery performance regression
  KEYS: call_sbin_request_key() must write lock keyrings before modifying them
  KEYS: Use RCU dereference wrappers in keyring key type code
  KEYS: find_keyring_by_name() can gain access to a freed keyring
  ALSA: hda: Fix 0 dB for Packard Bell models using Conexant CX20549 (Venice)
  ALSA: hda - Add quirk for Dell Inspiron 19T using a Conexant CX20582
  ALSA: take tu->qlock with irqs disabled
  ...

15 files changed:
1  2 
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/video/efifb.c

index 8fe66ac4e1a5f2889a12774820b497224783edc2,851a2f8ed6e650b5ff2ac376bc829220e9aad6ba..2a6b5de5ae5d07330232b8aff6b0b989300147a2
@@@ -1357,19 -1357,30 +1357,30 @@@ static void i915_setup_compression(stru
  
        dev_priv->cfb_size = size;
  
+       intel_disable_fbc(dev);
+       dev_priv->compressed_fb = compressed_fb;
        if (IS_GM45(dev)) {
-               g4x_disable_fbc(dev);
                I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
        } else {
-               i8xx_disable_fbc(dev);
                I915_WRITE(FBC_CFB_BASE, cfb_base);
                I915_WRITE(FBC_LL_BASE, ll_base);
+               dev_priv->compressed_llb = compressed_llb;
        }
  
        DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
                  ll_base, size >> 20);
  }
  
+ static void i915_cleanup_compression(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       drm_mm_put_block(dev_priv->compressed_fb);
+       if (!IS_GM45(dev))
+               drm_mm_put_block(dev_priv->compressed_llb);
+ }
  /* true = enable decode, false = disable decoder */
  static unsigned int i915_vga_set_decode(void *cookie, bool state)
  {
@@@ -1493,7 -1504,7 +1504,7 @@@ static int i915_load_modeset_init(struc
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
  
        intel_fbdev_init(dev);
 -
 +      drm_kms_helper_poll_init(dev);
        return 0;
  
  destroy_ringbuffer:
@@@ -1759,6 -1770,8 +1770,8 @@@ int i915_driver_unload(struct drm_devic
        }
  
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               intel_modeset_cleanup(dev);
                /*
                 * free the memory space allocated for the child device
                 * config parsed from VBT
        intel_opregion_free(dev, 0);
  
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               intel_modeset_cleanup(dev);
                i915_gem_free_all_phys_object(dev);
  
                mutex_lock(&dev->struct_mutex);
                i915_gem_cleanup_ringbuffer(dev);
                mutex_unlock(&dev->struct_mutex);
+               if (I915_HAS_FBC(dev) && i915_powersave)
+                       i915_cleanup_compression(dev);
                drm_mm_takedown(&dev_priv->vram);
                i915_gem_lastclose(dev);
  
index b034ea36731ce23a4fe66586601bcb3246919f22,a7e4b1f2749789a14a819fea2ae58bb41f349908..26792af7e1a15591559c40837b1778a5d9051689
@@@ -271,7 -271,8 +271,7 @@@ static void i915_hotplug_work_func(stru
                }
        }
        /* Just fire off a uevent and let userspace tell us what to do */
 -      intelfb_hotplug(dev, false);
 -      drm_sysfs_hotplug_event(dev);
 +      drm_helper_hpd_irq_event(dev);
  }
  
  static void i915_handle_rps_change(struct drm_device *dev)
@@@ -353,7 -354,7 +353,7 @@@ irqreturn_t ironlake_irq_handler(struc
                                READ_BREADCRUMB(dev_priv);
        }
  
-       if (gt_iir & GT_USER_INTERRUPT) {
+       if (gt_iir & GT_PIPE_NOTIFY) {
                u32 seqno = i915_get_gem_seqno(dev);
                dev_priv->mm.irq_gem_seqno = seqno;
                trace_i915_gem_request_complete(dev, seqno);
@@@ -1010,7 -1011,7 +1010,7 @@@ void i915_user_irq_get(struct drm_devic
        spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
        if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
                if (HAS_PCH_SPLIT(dev))
-                       ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+                       ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
                else
                        i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
        }
@@@ -1026,7 -1027,7 +1026,7 @@@ void i915_user_irq_put(struct drm_devic
        BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
        if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
                if (HAS_PCH_SPLIT(dev))
-                       ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+                       ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
                else
                        i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
        }
@@@ -1310,7 -1311,7 +1310,7 @@@ static int ironlake_irq_postinstall(str
        /* enable kind of interrupts always enabled */
        u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
                           DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
-       u32 render_mask = GT_USER_INTERRUPT;
+       u32 render_mask = GT_PIPE_NOTIFY;
        u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
                           SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
  
index 4d739a1b13ca14b75fedf97ac06a4ef1cab63ece,e775ce67be33a3b94f8100587ec572878c36d003..8c668e3122a549a906d4156af36797a3a78e0cfb
@@@ -1048,9 -1048,8 +1048,8 @@@ void i8xx_disable_fbc(struct drm_devic
        DRM_DEBUG_KMS("disabled FBC\n");
  }
  
- static bool i8xx_fbc_enabled(struct drm_crtc *crtc)
+ static bool i8xx_fbc_enabled(struct drm_device *dev)
  {
-       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
        return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
@@@ -1107,14 -1106,43 +1106,43 @@@ void g4x_disable_fbc(struct drm_device 
        DRM_DEBUG_KMS("disabled FBC\n");
  }
  
- static bool g4x_fbc_enabled(struct drm_crtc *crtc)
+ static bool g4x_fbc_enabled(struct drm_device *dev)
  {
-       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
        return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
  }
  
+ bool intel_fbc_enabled(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (!dev_priv->display.fbc_enabled)
+               return false;
+       return dev_priv->display.fbc_enabled(dev);
+ }
+ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+ {
+       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+       if (!dev_priv->display.enable_fbc)
+               return;
+       dev_priv->display.enable_fbc(crtc, interval);
+ }
+ void intel_disable_fbc(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (!dev_priv->display.disable_fbc)
+               return;
+       dev_priv->display.disable_fbc(dev);
+ }
  /**
   * intel_update_fbc - enable/disable FBC as needed
   * @crtc: CRTC to point the compressor at
@@@ -1149,9 -1177,7 +1177,7 @@@ static void intel_update_fbc(struct drm
        if (!i915_powersave)
                return;
  
-       if (!dev_priv->display.fbc_enabled ||
-           !dev_priv->display.enable_fbc ||
-           !dev_priv->display.disable_fbc)
+       if (!I915_HAS_FBC(dev))
                return;
  
        if (!crtc->fb)
                goto out_disable;
        }
  
-       if (dev_priv->display.fbc_enabled(crtc)) {
+       if (intel_fbc_enabled(dev)) {
                /* We can re-enable it in this case, but need to update pitch */
-               if (fb->pitch > dev_priv->cfb_pitch)
-                       dev_priv->display.disable_fbc(dev);
-               if (obj_priv->fence_reg != dev_priv->cfb_fence)
-                       dev_priv->display.disable_fbc(dev);
-               if (plane != dev_priv->cfb_plane)
-                       dev_priv->display.disable_fbc(dev);
+               if ((fb->pitch > dev_priv->cfb_pitch) ||
+                   (obj_priv->fence_reg != dev_priv->cfb_fence) ||
+                   (plane != dev_priv->cfb_plane))
+                       intel_disable_fbc(dev);
        }
  
-       if (!dev_priv->display.fbc_enabled(crtc)) {
-               /* Now try to turn it back on if possible */
-               dev_priv->display.enable_fbc(crtc, 500);
-       }
+       /* Now try to turn it back on if possible */
+       if (!intel_fbc_enabled(dev))
+               intel_enable_fbc(crtc, 500);
  
        return;
  
  out_disable:
        DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
        /* Multiple disables should be harmless */
-       if (dev_priv->display.fbc_enabled(crtc))
-               dev_priv->display.disable_fbc(dev);
+       if (intel_fbc_enabled(dev))
+               intel_disable_fbc(dev);
  }
  
  static int
@@@ -3677,14 -3700,16 +3700,16 @@@ static int intel_crtc_mode_set(struct d
                /* set the dithering flag */
                if (IS_I965G(dev)) {
                        if (dev_priv->lvds_dither) {
-                               if (HAS_PCH_SPLIT(dev))
+                               if (HAS_PCH_SPLIT(dev)) {
                                        pipeconf |= PIPE_ENABLE_DITHER;
-                               else
+                                       pipeconf |= PIPE_DITHER_TYPE_ST01;
+                               } else
                                        lvds |= LVDS_ENABLE_DITHER;
                        } else {
-                               if (HAS_PCH_SPLIT(dev))
+                               if (HAS_PCH_SPLIT(dev)) {
                                        pipeconf &= ~PIPE_ENABLE_DITHER;
-                               else
+                                       pipeconf &= ~PIPE_DITHER_TYPE_MASK;
+                               } else
                                        lvds &= ~LVDS_ENABLE_DITHER;
                        }
                }
@@@ -4959,7 -4984,6 +4984,7 @@@ intel_user_framebuffer_create(struct dr
  
  static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_create = intel_user_framebuffer_create,
 +      .output_poll_changed = intel_fb_output_poll_changed,
  };
  
  static struct drm_gem_object *
@@@ -5202,8 -5226,7 +5227,7 @@@ static void intel_init_display(struct d
        else
                dev_priv->display.dpms = i9xx_crtc_dpms;
  
-       /* Only mobile has FBC, leave pointers NULL for other chips */
-       if (IS_MOBILE(dev)) {
+       if (I915_HAS_FBC(dev)) {
                if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
                        dev_priv->display.enable_fbc = g4x_enable_fbc;
                dev_priv->display.update_wm = g4x_update_wm;
        else if (IS_I965G(dev))
                dev_priv->display.update_wm = i965_update_wm;
-       else if (IS_I9XX(dev) || IS_MOBILE(dev)) {
+       else if (IS_I9XX(dev)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
+       } else if (IS_I85X(dev)) {
+               dev_priv->display.update_wm = i9xx_update_wm;
+               dev_priv->display.get_fifo_size = i85x_get_fifo_size;
        } else {
-               if (IS_I85X(dev))
-                       dev_priv->display.get_fifo_size = i85x_get_fifo_size;
-               else if (IS_845G(dev))
+               dev_priv->display.update_wm = i830_update_wm;
+               if (IS_845G(dev))
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
                else
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
-               dev_priv->display.update_wm = i830_update_wm;
        }
  }
  
@@@ -5347,7 -5371,6 +5372,7 @@@ void intel_modeset_cleanup(struct drm_d
  
        mutex_lock(&dev->struct_mutex);
  
 +      drm_kms_helper_poll_fini(dev);
        intel_fbdev_fini(dev);
  
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
index ca372abc36cd4fb0b412ca3844db66cef4986df2,5ad5a098b5bb18f8895eeadc3f32905db1bffb91..aba72c489a2f07941fc69d88516fb2a52f086363
@@@ -1504,16 -1504,17 +1504,17 @@@ intel_analog_is_connected(struct drm_de
  }
  
  enum drm_connector_status
- intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
+ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
  {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
        struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
        struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
        enum drm_connector_status status = connector_status_connected;
        struct edid *edid = NULL;
  
-       edid = drm_get_edid(connector,
-                           intel_encoder->ddc_bus);
+       edid = drm_get_edid(connector, intel_encoder->ddc_bus);
  
        /* This is only applied to SDVO cards with multiple outputs */
        if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) {
                 */
                while(temp_ddc > 1) {
                        sdvo_priv->ddc_bus = temp_ddc;
-                       edid = drm_get_edid(connector,
-                               intel_encoder->ddc_bus);
+                       edid = drm_get_edid(connector, intel_encoder->ddc_bus);
                        if (edid) {
                                /*
                                 * When we can get the EDID, maybe it is the
        /* when there is no edid and no monitor is connected with VGA
         * port, try to use the CRT ddc to read the EDID for DVI-connector
         */
-       if (edid == NULL &&
-           sdvo_priv->analog_ddc_bus &&
+       if (edid == NULL && sdvo_priv->analog_ddc_bus &&
            !intel_analog_is_connected(connector->dev))
-               edid = drm_get_edid(connector,
-                                   sdvo_priv->analog_ddc_bus);
+               edid = drm_get_edid(connector, sdvo_priv->analog_ddc_bus);
        if (edid != NULL) {
-               /* Don't report the output as connected if it's a DVI-I
-                * connector with a non-digital EDID coming out.
-                */
-               if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
-                       if (edid->input & DRM_EDID_INPUT_DIGITAL)
-                               sdvo_priv->is_hdmi =
-                                       drm_detect_hdmi_monitor(edid);
-                       else
-                               status = connector_status_disconnected;
-               }
+               bool is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
+               bool need_digital = !!(sdvo_connector->output_flag & SDVO_TMDS_MASK);
  
-               kfree(edid);
-               connector->display_info.raw_edid = NULL;
+               /* DDC bus is shared, match EDID to connector type */
+               if (is_digital && need_digital)
+                       sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
+               else if (is_digital != need_digital)
+                       status = connector_status_disconnected;
  
-       } else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+               connector->display_info.raw_edid = NULL;
+       } else
                status = connector_status_disconnected;
+       
+       kfree(edid);
  
        return status;
  }
@@@ -1601,8 -1598,8 +1598,8 @@@ static enum drm_connector_status intel_
  
        if ((sdvo_connector->output_flag & response) == 0)
                ret = connector_status_disconnected;
-       else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
-               ret = intel_sdvo_hdmi_sink_detect(connector, response);
+       else if (response & SDVO_TMDS_MASK)
+               ret = intel_sdvo_hdmi_sink_detect(connector);
        else
                ret = connector_status_connected;
  
@@@ -2054,40 -2051,17 +2051,17 @@@ static const struct drm_encoder_funcs i
   * outputs, then LVDS outputs.
   */
  static void
- intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv)
+ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
+                         struct intel_sdvo_priv *sdvo, u32 reg)
  {
-       uint16_t mask = 0;
-       unsigned int num_bits;
+       struct sdvo_device_mapping *mapping;
  
-       /* Make a mask of outputs less than or equal to our own priority in the
-        * list.
-        */
-       switch (dev_priv->controlled_output) {
-       case SDVO_OUTPUT_LVDS1:
-               mask |= SDVO_OUTPUT_LVDS1;
-       case SDVO_OUTPUT_LVDS0:
-               mask |= SDVO_OUTPUT_LVDS0;
-       case SDVO_OUTPUT_TMDS1:
-               mask |= SDVO_OUTPUT_TMDS1;
-       case SDVO_OUTPUT_TMDS0:
-               mask |= SDVO_OUTPUT_TMDS0;
-       case SDVO_OUTPUT_RGB1:
-               mask |= SDVO_OUTPUT_RGB1;
-       case SDVO_OUTPUT_RGB0:
-               mask |= SDVO_OUTPUT_RGB0;
-               break;
-       }
-       /* Count bits to find what number we are in the priority list. */
-       mask &= dev_priv->caps.output_flags;
-       num_bits = hweight16(mask);
-       if (num_bits > 3) {
-               /* if more than 3 outputs, default to DDC bus 3 for now */
-               num_bits = 3;
-       }
+       if (IS_SDVOB(reg))
+               mapping = &(dev_priv->sdvo_mappings[0]);
+       else
+               mapping = &(dev_priv->sdvo_mappings[1]);
  
-       /* Corresponds to SDVO_CONTROL_BUS_DDCx */
-       dev_priv->ddc_bus = 1 << num_bits;
+       sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
  }
  
  static bool
@@@ -2244,7 -2218,6 +2218,7 @@@ intel_sdvo_dvi_init(struct intel_encode
        }
  
        connector = &intel_connector->base;
 +      connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
        encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
        connector->connector_type = DRM_MODE_CONNECTOR_DVID;
  
@@@ -2311,7 -2284,6 +2285,7 @@@ intel_sdvo_analog_init(struct intel_enc
                  return false;
  
          connector = &intel_connector->base;
 +      connector->polled = DRM_CONNECTOR_POLL_CONNECT;
          encoder->encoder_type = DRM_MODE_ENCODER_DAC;
          connector->connector_type = DRM_MODE_CONNECTOR_VGA;
          sdvo_connector = intel_connector->dev_priv;
@@@ -2866,7 -2838,7 +2840,7 @@@ bool intel_sdvo_init(struct drm_device 
                goto err_i2c;
        }
  
-       intel_sdvo_select_ddc_bus(sdvo_priv);
+       intel_sdvo_select_ddc_bus(dev_priv, sdvo_priv, sdvo_reg);
  
        /* Set the input timing to the screen. Assume always input 0. */
        intel_sdvo_set_target_input(intel_encoder, true, false);
index 9a59ba46f078233cf564a33372e09928ca40569a,4de41b0ad5cec234a70ab94caad46e0bf8f6dd0c..cc004b05d63e7ff7153b6f2f87b75f34c7062161
@@@ -37,7 -37,6 +37,7 @@@
  #include "rs100d.h"
  #include "rv200d.h"
  #include "rv250d.h"
 +#include "atom.h"
  
  #include <linux/firmware.h>
  #include <linux/platform_device.h>
@@@ -68,264 -67,6 +68,264 @@@ MODULE_FIRMWARE(FIRMWARE_R520)
   * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
   */
  
 +void r100_pm_get_dynpm_state(struct radeon_device *rdev)
 +{
 +      int i;
 +      rdev->pm.dynpm_can_upclock = true;
 +      rdev->pm.dynpm_can_downclock = true;
 +
 +      switch (rdev->pm.dynpm_planned_action) {
 +      case DYNPM_ACTION_MINIMUM:
 +              rdev->pm.requested_power_state_index = 0;
 +              rdev->pm.dynpm_can_downclock = false;
 +              break;
 +      case DYNPM_ACTION_DOWNCLOCK:
 +              if (rdev->pm.current_power_state_index == 0) {
 +                      rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
 +                      rdev->pm.dynpm_can_downclock = false;
 +              } else {
 +                      if (rdev->pm.active_crtc_count > 1) {
 +                              for (i = 0; i < rdev->pm.num_power_states; i++) {
 +                                      if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
 +                                              continue;
 +                                      else if (i >= rdev->pm.current_power_state_index) {
 +                                              rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
 +                                              break;
 +                                      } else {
 +                                              rdev->pm.requested_power_state_index = i;
 +                                              break;
 +                                      }
 +                              }
 +                      } else
 +                              rdev->pm.requested_power_state_index =
 +                                      rdev->pm.current_power_state_index - 1;
 +              }
 +              /* don't use the power state if crtcs are active and no display flag is set */
 +              if ((rdev->pm.active_crtc_count > 0) &&
 +                  (rdev->pm.power_state[rdev->pm.requested_power_state_index].clock_info[0].flags &
 +                   RADEON_PM_MODE_NO_DISPLAY)) {
 +                      rdev->pm.requested_power_state_index++;
 +              }
 +              break;
 +      case DYNPM_ACTION_UPCLOCK:
 +              if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
 +                      rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
 +                      rdev->pm.dynpm_can_upclock = false;
 +              } else {
 +                      if (rdev->pm.active_crtc_count > 1) {
 +                              for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
 +                                      if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
 +                                              continue;
 +                                      else if (i <= rdev->pm.current_power_state_index) {
 +                                              rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
 +                                              break;
 +                                      } else {
 +                                              rdev->pm.requested_power_state_index = i;
 +                                              break;
 +                                      }
 +                              }
 +                      } else
 +                              rdev->pm.requested_power_state_index =
 +                                      rdev->pm.current_power_state_index + 1;
 +              }
 +              break;
 +      case DYNPM_ACTION_DEFAULT:
 +              rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
 +              rdev->pm.dynpm_can_upclock = false;
 +              break;
 +      case DYNPM_ACTION_NONE:
 +      default:
 +              DRM_ERROR("Requested mode for not defined action\n");
 +              return;
 +      }
 +      /* only one clock mode per power state */
 +      rdev->pm.requested_clock_mode_index = 0;
 +
 +      DRM_DEBUG("Requested: e: %d m: %d p: %d\n",
 +                rdev->pm.power_state[rdev->pm.requested_power_state_index].
 +                clock_info[rdev->pm.requested_clock_mode_index].sclk,
 +                rdev->pm.power_state[rdev->pm.requested_power_state_index].
 +                clock_info[rdev->pm.requested_clock_mode_index].mclk,
 +                rdev->pm.power_state[rdev->pm.requested_power_state_index].
 +                pcie_lanes);
 +}
 +
 +void r100_pm_init_profile(struct radeon_device *rdev)
 +{
 +      /* default */
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
 +      /* low sh */
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
 +      /* high sh */
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
 +      /* low mh */
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
 +      /* high mh */
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 +}
 +
 +void r100_pm_misc(struct radeon_device *rdev)
 +{
 +      int requested_index = rdev->pm.requested_power_state_index;
 +      struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
 +      struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
 +      u32 tmp, sclk_cntl, sclk_cntl2, sclk_more_cntl;
 +
 +      if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) {
 +              if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
 +                      tmp = RREG32(voltage->gpio.reg);
 +                      if (voltage->active_high)
 +                              tmp |= voltage->gpio.mask;
 +                      else
 +                              tmp &= ~(voltage->gpio.mask);
 +                      WREG32(voltage->gpio.reg, tmp);
 +                      if (voltage->delay)
 +                              udelay(voltage->delay);
 +              } else {
 +                      tmp = RREG32(voltage->gpio.reg);
 +                      if (voltage->active_high)
 +                              tmp &= ~voltage->gpio.mask;
 +                      else
 +                              tmp |= voltage->gpio.mask;
 +                      WREG32(voltage->gpio.reg, tmp);
 +                      if (voltage->delay)
 +                              udelay(voltage->delay);
 +              }
 +      }
 +
 +      sclk_cntl = RREG32_PLL(SCLK_CNTL);
 +      sclk_cntl2 = RREG32_PLL(SCLK_CNTL2);
 +      sclk_cntl2 &= ~REDUCED_SPEED_SCLK_SEL(3);
 +      sclk_more_cntl = RREG32_PLL(SCLK_MORE_CNTL);
 +      sclk_more_cntl &= ~VOLTAGE_DELAY_SEL(3);
 +      if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
 +              sclk_more_cntl |= REDUCED_SPEED_SCLK_EN;
 +              if (ps->misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE)
 +                      sclk_cntl2 |= REDUCED_SPEED_SCLK_MODE;
 +              else
 +                      sclk_cntl2 &= ~REDUCED_SPEED_SCLK_MODE;
 +              if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2)
 +                      sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(0);
 +              else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4)
 +                      sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(2);
 +      } else
 +              sclk_more_cntl &= ~REDUCED_SPEED_SCLK_EN;
 +
 +      if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
 +              sclk_more_cntl |= IO_CG_VOLTAGE_DROP;
 +              if (voltage->delay) {
 +                      sclk_more_cntl |= VOLTAGE_DROP_SYNC;
 +                      switch (voltage->delay) {
 +                      case 33:
 +                              sclk_more_cntl |= VOLTAGE_DELAY_SEL(0);
 +                              break;
 +                      case 66:
 +                              sclk_more_cntl |= VOLTAGE_DELAY_SEL(1);
 +                              break;
 +                      case 99:
 +                              sclk_more_cntl |= VOLTAGE_DELAY_SEL(2);
 +                              break;
 +                      case 132:
 +                              sclk_more_cntl |= VOLTAGE_DELAY_SEL(3);
 +                              break;
 +                      }
 +              } else
 +                      sclk_more_cntl &= ~VOLTAGE_DROP_SYNC;
 +      } else
 +              sclk_more_cntl &= ~IO_CG_VOLTAGE_DROP;
 +
 +      if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
 +              sclk_cntl &= ~FORCE_HDP;
 +      else
 +              sclk_cntl |= FORCE_HDP;
 +
 +      WREG32_PLL(SCLK_CNTL, sclk_cntl);
 +      WREG32_PLL(SCLK_CNTL2, sclk_cntl2);
 +      WREG32_PLL(SCLK_MORE_CNTL, sclk_more_cntl);
 +
 +      /* set pcie lanes */
 +      if ((rdev->flags & RADEON_IS_PCIE) &&
 +          !(rdev->flags & RADEON_IS_IGP) &&
 +          rdev->asic->set_pcie_lanes &&
 +          (ps->pcie_lanes !=
 +           rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
 +              radeon_set_pcie_lanes(rdev,
 +                                    ps->pcie_lanes);
 +              DRM_DEBUG("Setting: p: %d\n", ps->pcie_lanes);
 +      }
 +}
 +
 +void r100_pm_prepare(struct radeon_device *rdev)
 +{
 +      struct drm_device *ddev = rdev->ddev;
 +      struct drm_crtc *crtc;
 +      struct radeon_crtc *radeon_crtc;
 +      u32 tmp;
 +
 +      /* disable any active CRTCs */
 +      list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
 +              radeon_crtc = to_radeon_crtc(crtc);
 +              if (radeon_crtc->enabled) {
 +                      if (radeon_crtc->crtc_id) {
 +                              tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
 +                              tmp |= RADEON_CRTC2_DISP_REQ_EN_B;
 +                              WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
 +                      } else {
 +                              tmp = RREG32(RADEON_CRTC_GEN_CNTL);
 +                              tmp |= RADEON_CRTC_DISP_REQ_EN_B;
 +                              WREG32(RADEON_CRTC_GEN_CNTL, tmp);
 +                      }
 +              }
 +      }
 +}
 +
 +void r100_pm_finish(struct radeon_device *rdev)
 +{
 +      struct drm_device *ddev = rdev->ddev;
 +      struct drm_crtc *crtc;
 +      struct radeon_crtc *radeon_crtc;
 +      u32 tmp;
 +
 +      /* enable any active CRTCs */
 +      list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
 +              radeon_crtc = to_radeon_crtc(crtc);
 +              if (radeon_crtc->enabled) {
 +                      if (radeon_crtc->crtc_id) {
 +                              tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
 +                              tmp &= ~RADEON_CRTC2_DISP_REQ_EN_B;
 +                              WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
 +                      } else {
 +                              tmp = RREG32(RADEON_CRTC_GEN_CNTL);
 +                              tmp &= ~RADEON_CRTC_DISP_REQ_EN_B;
 +                              WREG32(RADEON_CRTC_GEN_CNTL, tmp);
 +                      }
 +              }
 +      }
 +}
 +
 +bool r100_gui_idle(struct radeon_device *rdev)
 +{
 +      if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)
 +              return false;
 +      else
 +              return true;
 +}
 +
  /* hpd for digital panel detect/disconnect */
  bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
  {
@@@ -513,9 -254,6 +513,9 @@@ int r100_irq_set(struct radeon_device *
        if (rdev->irq.sw_int) {
                tmp |= RADEON_SW_INT_ENABLE;
        }
 +      if (rdev->irq.gui_idle) {
 +              tmp |= RADEON_GUI_IDLE_MASK;
 +      }
        if (rdev->irq.crtc_vblank_int[0]) {
                tmp |= RADEON_CRTC_VBLANK_MASK;
        }
@@@ -550,12 -288,6 +550,12 @@@ static inline uint32_t r100_irq_ack(str
                RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT |
                RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT;
  
 +      /* the interrupt works, but the status bit is permanently asserted */
 +      if (rdev->irq.gui_idle && radeon_gui_idle(rdev)) {
 +              if (!rdev->irq.gui_idle_acked)
 +                      irq_mask |= RADEON_GUI_IDLE_STAT;
 +      }
 +
        if (irqs) {
                WREG32(RADEON_GEN_INT_STATUS, irqs);
        }
@@@ -567,9 -299,6 +567,9 @@@ int r100_irq_process(struct radeon_devi
        uint32_t status, msi_rearm;
        bool queue_hotplug = false;
  
 +      /* reset gui idle ack.  the status bit is broken */
 +      rdev->irq.gui_idle_acked = false;
 +
        status = r100_irq_ack(rdev);
        if (!status) {
                return IRQ_NONE;
                if (status & RADEON_SW_INT_TEST) {
                        radeon_fence_process(rdev);
                }
 +              /* gui idle interrupt */
 +              if (status & RADEON_GUI_IDLE_STAT) {
 +                      rdev->irq.gui_idle_acked = true;
 +                      rdev->pm.gui_idle = true;
 +                      wake_up(&rdev->irq.idle_queue);
 +              }
                /* Vertical blank interrupts */
                if (status & RADEON_CRTC_VBLANK_STAT) {
                        drm_handle_vblank(rdev->ddev, 0);
                }
                status = r100_irq_ack(rdev);
        }
 +      /* reset gui idle ack.  the status bit is broken */
 +      rdev->irq.gui_idle_acked = false;
        if (queue_hotplug)
                queue_work(rdev->wq, &rdev->hotplug_work);
        if (rdev->msi_enabled) {
@@@ -2643,53 -2364,53 +2643,53 @@@ void r100_bandwidth_update(struct radeo
        fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
        uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
        fixed20_12 memtcas_ff[8] = {
 -              fixed_init(1),
 -              fixed_init(2),
 -              fixed_init(3),
 -              fixed_init(0),
 -              fixed_init_half(1),
 -              fixed_init_half(2),
 -              fixed_init(0),
 +              dfixed_init(1),
 +              dfixed_init(2),
 +              dfixed_init(3),
 +              dfixed_init(0),
 +              dfixed_init_half(1),
 +              dfixed_init_half(2),
 +              dfixed_init(0),
        };
        fixed20_12 memtcas_rs480_ff[8] = {
 -              fixed_init(0),
 -              fixed_init(1),
 -              fixed_init(2),
 -              fixed_init(3),
 -              fixed_init(0),
 -              fixed_init_half(1),
 -              fixed_init_half(2),
 -              fixed_init_half(3),
 +              dfixed_init(0),
 +              dfixed_init(1),
 +              dfixed_init(2),
 +              dfixed_init(3),
 +              dfixed_init(0),
 +              dfixed_init_half(1),
 +              dfixed_init_half(2),
 +              dfixed_init_half(3),
        };
        fixed20_12 memtcas2_ff[8] = {
 -              fixed_init(0),
 -              fixed_init(1),
 -              fixed_init(2),
 -              fixed_init(3),
 -              fixed_init(4),
 -              fixed_init(5),
 -              fixed_init(6),
 -              fixed_init(7),
 +              dfixed_init(0),
 +              dfixed_init(1),
 +              dfixed_init(2),
 +              dfixed_init(3),
 +              dfixed_init(4),
 +              dfixed_init(5),
 +              dfixed_init(6),
 +              dfixed_init(7),
        };
        fixed20_12 memtrbs[8] = {
 -              fixed_init(1),
 -              fixed_init_half(1),
 -              fixed_init(2),
 -              fixed_init_half(2),
 -              fixed_init(3),
 -              fixed_init_half(3),
 -              fixed_init(4),
 -              fixed_init_half(4)
 +              dfixed_init(1),
 +              dfixed_init_half(1),
 +              dfixed_init(2),
 +              dfixed_init_half(2),
 +              dfixed_init(3),
 +              dfixed_init_half(3),
 +              dfixed_init(4),
 +              dfixed_init_half(4)
        };
        fixed20_12 memtrbs_r4xx[8] = {
 -              fixed_init(4),
 -              fixed_init(5),
 -              fixed_init(6),
 -              fixed_init(7),
 -              fixed_init(8),
 -              fixed_init(9),
 -              fixed_init(10),
 -              fixed_init(11)
 +              dfixed_init(4),
 +              dfixed_init(5),
 +              dfixed_init(6),
 +              dfixed_init(7),
 +              dfixed_init(8),
 +              dfixed_init(9),
 +              dfixed_init(10),
 +              dfixed_init(11)
        };
        fixed20_12 min_mem_eff;
        fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
                }
        }
  
 -      min_mem_eff.full = rfixed_const_8(0);
 +      min_mem_eff.full = dfixed_const_8(0);
        /* get modes */
        if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
                uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
        mclk_ff = rdev->pm.mclk;
  
        temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
 -      temp_ff.full = rfixed_const(temp);
 -      mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
 +      temp_ff.full = dfixed_const(temp);
 +      mem_bw.full = dfixed_mul(mclk_ff, temp_ff);
  
        pix_clk.full = 0;
        pix_clk2.full = 0;
        peak_disp_bw.full = 0;
        if (mode1) {
 -              temp_ff.full = rfixed_const(1000);
 -              pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
 -              pix_clk.full = rfixed_div(pix_clk, temp_ff);
 -              temp_ff.full = rfixed_const(pixel_bytes1);
 -              peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
 +              temp_ff.full = dfixed_const(1000);
 +              pix_clk.full = dfixed_const(mode1->clock); /* convert to fixed point */
 +              pix_clk.full = dfixed_div(pix_clk, temp_ff);
 +              temp_ff.full = dfixed_const(pixel_bytes1);
 +              peak_disp_bw.full += dfixed_mul(pix_clk, temp_ff);
        }
        if (mode2) {
 -              temp_ff.full = rfixed_const(1000);
 -              pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
 -              pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
 -              temp_ff.full = rfixed_const(pixel_bytes2);
 -              peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
 +              temp_ff.full = dfixed_const(1000);
 +              pix_clk2.full = dfixed_const(mode2->clock); /* convert to fixed point */
 +              pix_clk2.full = dfixed_div(pix_clk2, temp_ff);
 +              temp_ff.full = dfixed_const(pixel_bytes2);
 +              peak_disp_bw.full += dfixed_mul(pix_clk2, temp_ff);
        }
  
 -      mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
 +      mem_bw.full = dfixed_mul(mem_bw, min_mem_eff);
        if (peak_disp_bw.full >= mem_bw.full) {
                DRM_ERROR("You may not have enough display bandwidth for current mode\n"
                          "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
                mem_tras = ((temp >> 12) & 0xf) + 4;
        }
        /* convert to FF */
 -      trcd_ff.full = rfixed_const(mem_trcd);
 -      trp_ff.full = rfixed_const(mem_trp);
 -      tras_ff.full = rfixed_const(mem_tras);
 +      trcd_ff.full = dfixed_const(mem_trcd);
 +      trp_ff.full = dfixed_const(mem_trp);
 +      tras_ff.full = dfixed_const(mem_tras);
  
        /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
        temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
                /* extra cas latency stored in bits 23-25 0-4 clocks */
                data = (temp >> 23) & 0x7;
                if (data < 5)
 -                      tcas_ff.full += rfixed_const(data);
 +                      tcas_ff.full += dfixed_const(data);
        }
  
        if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
  
        if (rdev->flags & RADEON_IS_AGP) {
                fixed20_12 agpmode_ff;
 -              agpmode_ff.full = rfixed_const(radeon_agpmode);
 -              temp_ff.full = rfixed_const_666(16);
 -              sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
 +              agpmode_ff.full = dfixed_const(radeon_agpmode);
 +              temp_ff.full = dfixed_const_666(16);
 +              sclk_eff_ff.full -= dfixed_mul(agpmode_ff, temp_ff);
        }
        /* TODO PCIE lanes may affect this - agpmode == 16?? */
  
        if (ASIC_IS_R300(rdev)) {
 -              sclk_delay_ff.full = rfixed_const(250);
 +              sclk_delay_ff.full = dfixed_const(250);
        } else {
                if ((rdev->family == CHIP_RV100) ||
                    rdev->flags & RADEON_IS_IGP) {
                        if (rdev->mc.vram_is_ddr)
 -                              sclk_delay_ff.full = rfixed_const(41);
 +                              sclk_delay_ff.full = dfixed_const(41);
                        else
 -                              sclk_delay_ff.full = rfixed_const(33);
 +                              sclk_delay_ff.full = dfixed_const(33);
                } else {
                        if (rdev->mc.vram_width == 128)
 -                              sclk_delay_ff.full = rfixed_const(57);
 +                              sclk_delay_ff.full = dfixed_const(57);
                        else
 -                              sclk_delay_ff.full = rfixed_const(41);
 +                              sclk_delay_ff.full = dfixed_const(41);
                }
        }
  
 -      mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
 +      mc_latency_sclk.full = dfixed_div(sclk_delay_ff, sclk_eff_ff);
  
        if (rdev->mc.vram_is_ddr) {
                if (rdev->mc.vram_width == 32) {
 -                      k1.full = rfixed_const(40);
 +                      k1.full = dfixed_const(40);
                        c  = 3;
                } else {
 -                      k1.full = rfixed_const(20);
 +                      k1.full = dfixed_const(20);
                        c  = 1;
                }
        } else {
 -              k1.full = rfixed_const(40);
 +              k1.full = dfixed_const(40);
                c  = 3;
        }
  
 -      temp_ff.full = rfixed_const(2);
 -      mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
 -      temp_ff.full = rfixed_const(c);
 -      mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
 -      temp_ff.full = rfixed_const(4);
 -      mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
 -      mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
 +      temp_ff.full = dfixed_const(2);
 +      mc_latency_mclk.full = dfixed_mul(trcd_ff, temp_ff);
 +      temp_ff.full = dfixed_const(c);
 +      mc_latency_mclk.full += dfixed_mul(tcas_ff, temp_ff);
 +      temp_ff.full = dfixed_const(4);
 +      mc_latency_mclk.full += dfixed_mul(tras_ff, temp_ff);
 +      mc_latency_mclk.full += dfixed_mul(trp_ff, temp_ff);
        mc_latency_mclk.full += k1.full;
  
 -      mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
 -      mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
 +      mc_latency_mclk.full = dfixed_div(mc_latency_mclk, mclk_ff);
 +      mc_latency_mclk.full += dfixed_div(temp_ff, sclk_eff_ff);
  
        /*
          HW cursor time assuming worst case of full size colour cursor.
        */
 -      temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
 +      temp_ff.full = dfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
        temp_ff.full += trcd_ff.full;
        if (temp_ff.full < tras_ff.full)
                temp_ff.full = tras_ff.full;
 -      cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
 +      cur_latency_mclk.full = dfixed_div(temp_ff, mclk_ff);
  
 -      temp_ff.full = rfixed_const(cur_size);
 -      cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
 +      temp_ff.full = dfixed_const(cur_size);
 +      cur_latency_sclk.full = dfixed_div(temp_ff, sclk_eff_ff);
        /*
          Find the total latency for the display data.
        */
 -      disp_latency_overhead.full = rfixed_const(8);
 -      disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
 +      disp_latency_overhead.full = dfixed_const(8);
 +      disp_latency_overhead.full = dfixed_div(disp_latency_overhead, sclk_ff);
        mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
        mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
  
                /*
                  Find the drain rate of the display buffer.
                */
 -              temp_ff.full = rfixed_const((16/pixel_bytes1));
 -              disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
 +              temp_ff.full = dfixed_const((16/pixel_bytes1));
 +              disp_drain_rate.full = dfixed_div(pix_clk, temp_ff);
  
                /*
                  Find the critical point of the display buffer.
                */
 -              crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
 -              crit_point_ff.full += rfixed_const_half(0);
 +              crit_point_ff.full = dfixed_mul(disp_drain_rate, disp_latency);
 +              crit_point_ff.full += dfixed_const_half(0);
  
 -              critical_point = rfixed_trunc(crit_point_ff);
 +              critical_point = dfixed_trunc(crit_point_ff);
  
                if (rdev->disp_priority == 2) {
                        critical_point = 0;
                /*
                  Find the drain rate of the display buffer.
                */
 -              temp_ff.full = rfixed_const((16/pixel_bytes2));
 -              disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
 +              temp_ff.full = dfixed_const((16/pixel_bytes2));
 +              disp_drain_rate2.full = dfixed_div(pix_clk2, temp_ff);
  
                grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
                grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
                        critical_point2 = 0;
                else {
                        temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
 -                      temp_ff.full = rfixed_const(temp);
 -                      temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
 +                      temp_ff.full = dfixed_const(temp);
 +                      temp_ff.full = dfixed_mul(mclk_ff, temp_ff);
                        if (sclk_ff.full < temp_ff.full)
                                temp_ff.full = sclk_ff.full;
  
  
                        if (mode1) {
                                temp_ff.full = read_return_rate.full - disp_drain_rate.full;
 -                              time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
 +                              time_disp1_drop_priority.full = dfixed_div(crit_point_ff, temp_ff);
                        } else {
                                time_disp1_drop_priority.full = 0;
                        }
                        crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
 -                      crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
 -                      crit_point_ff.full += rfixed_const_half(0);
 +                      crit_point_ff.full = dfixed_mul(crit_point_ff, disp_drain_rate2);
 +                      crit_point_ff.full += dfixed_const_half(0);
  
 -                      critical_point2 = rfixed_trunc(crit_point_ff);
 +                      critical_point2 = dfixed_trunc(crit_point_ff);
  
                        if (rdev->disp_priority == 2) {
                                critical_point2 = 0;
@@@ -3283,7 -3004,7 +3283,7 @@@ int r100_cs_track_check(struct radeon_d
  
        for (i = 0; i < track->num_cb; i++) {
                if (track->cb[i].robj == NULL) {
-                       if (!(track->fastfill || track->color_channel_mask ||
+                       if (!(track->zb_cb_clear || track->color_channel_mask ||
                              track->blend_read_enable)) {
                                continue;
                        }
@@@ -3770,6 -3491,7 +3770,6 @@@ int r100_suspend(struct radeon_device *
  
  void r100_fini(struct radeon_device *rdev)
  {
 -      radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
@@@ -3825,6 -3547,8 +3825,6 @@@ int r100_init(struct radeon_device *rde
        r100_errata(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
 -      /* Initialize power management */
 -      radeon_pm_init(rdev);
        /* initialize AGP */
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
index 5c54db51de8588bb51d72060d47ecd4e4422a0de,6d9569e002f7c8c74c691b2ccee9be0368731a4e..b2f9efe2897c4362d420f61f50090fe0aedc3839
@@@ -328,13 -328,12 +328,12 @@@ void r300_gpu_init(struct radeon_devic
  {
        uint32_t gb_tile_config, tmp;
  
-       /* FIXME: rv380 one pipes ? */
        if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
-           (rdev->family == CHIP_R350)) {
+           (rdev->family == CHIP_R350 && rdev->pdev->device != 0x4148)) {
                /* r300,r350 */
                rdev->num_gb_pipes = 2;
        } else {
-               /* rv350,rv370,rv380,r300 AD */
+               /* rv350,rv370,rv380,r300 AD, r350 AH */
                rdev->num_gb_pipes = 1;
        }
        rdev->num_z_pipes = 1;
@@@ -1045,7 -1044,7 +1044,7 @@@ static int r300_packet0_check(struct ra
                break;
        case 0x4d1c:
                /* ZB_BW_CNTL */
-               track->fastfill = !!(idx_value & (1 << 2));
+               track->zb_cb_clear = !!(idx_value & (1 << 5));
                break;
        case 0x4e04:
                /* RB3D_BLENDCNTL */
@@@ -1345,6 -1344,7 +1344,6 @@@ int r300_suspend(struct radeon_device *
  
  void r300_fini(struct radeon_device *rdev)
  {
 -      radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
@@@ -1400,6 -1400,8 +1399,6 @@@ int r300_init(struct radeon_device *rde
        r300_errata(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
 -      /* Initialize power management */
 -      radeon_pm_init(rdev);
        /* initialize AGP */
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
index 87c0e3840034aec010e0f1a588a07cb8bb0dec2f,be092d243f84874e0ab49183f24f7a232f726341..4415a5ee5871df1e353c947dd31a1dd65181cd45
  #include "r420d.h"
  #include "r420_reg_safe.h"
  
 +void r420_pm_init_profile(struct radeon_device *rdev)
 +{
 +      /* default */
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
 +      /* low sh */
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
 +      /* high sh */
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
 +      /* low mh */
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
 +      /* high mh */
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 +      rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 +}
 +
  static void r420_set_reg_safe(struct radeon_device *rdev)
  {
        rdev->config.r300.reg_safe_bm = r420_reg_safe_bm;
@@@ -88,6 -59,12 +88,12 @@@ void r420_pipes_init(struct radeon_devi
        /* get max number of pipes */
        gb_pipe_select = RREG32(0x402C);
        num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
+       /* SE chips have 1 pipe */
+       if ((rdev->pdev->device == 0x5e4c) ||
+           (rdev->pdev->device == 0x5e4f))
+               num_pipes = 1;
        rdev->num_gb_pipes = num_pipes;
        tmp = 0;
        switch (num_pipes) {
@@@ -297,6 -274,7 +303,6 @@@ int r420_suspend(struct radeon_device *
  
  void r420_fini(struct radeon_device *rdev)
  {
 -      radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
@@@ -356,6 -334,8 +362,6 @@@ int r420_init(struct radeon_device *rde
  
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
 -      /* Initialize power management */
 -      radeon_pm_init(rdev);
        /* initialize AGP */
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
index 9149e4a3af0fdc7c0c55acc14705f846a262a9cf,1d05debdd60410817c6b4ee1ad1c4bd167b660e4..1c24dad0ac393bf698628c49fa8c101cccdb0c6c
@@@ -1174,7 -1174,7 +1174,7 @@@ struct radeon_encoder_atom_dig *radeon_
                lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
                        le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
                lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
 -                      le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
 +                      le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
                lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
                        le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
                lvds->panel_pwr_delay =
@@@ -1264,7 -1264,7 +1264,7 @@@ bool radeon_atom_get_tv_timings(struct 
        switch (crev) {
        case 1:
                tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
-               if (index > MAX_SUPPORTED_TV_TIMING)
+               if (index >= MAX_SUPPORTED_TV_TIMING)
                        return false;
  
                mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
                break;
        case 2:
                tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
-               if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
+               if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
                        return false;
  
                dtd_timings = &tv_info_v1_2->aModeTimings[index];
@@@ -1442,29 -1442,29 +1442,29 @@@ radeon_atombios_get_tv_dac_info(struct 
  
  static const char *thermal_controller_names[] = {
        "NONE",
 -      "LM63",
 -      "ADM1032",
 -      "ADM1030",
 -      "MUA6649",
 -      "LM64",
 -      "F75375",
 -      "ASC7512",
 +      "lm63",
 +      "adm1032",
 +      "adm1030",
 +      "max6649",
 +      "lm64",
 +      "f75375",
 +      "asc7xxx",
  };
  
  static const char *pp_lib_thermal_controller_names[] = {
        "NONE",
 -      "LM63",
 -      "ADM1032",
 -      "ADM1030",
 -      "MUA6649",
 -      "LM64",
 -      "F75375",
 +      "lm63",
 +      "adm1032",
 +      "adm1030",
 +      "max6649",
 +      "lm64",
 +      "f75375",
        "RV6xx",
        "RV770",
 -      "ADT7473",
 +      "adt7473",
        "External GPIO",
        "Evergreen",
 -      "ADT7473 with internal",
 +      "adt7473 with internal",
  
  };
  
@@@ -1489,7 -1489,7 +1489,7 @@@ void radeon_atombios_get_power_modes(st
        int state_index = 0, mode_index = 0;
        struct radeon_i2c_bus_rec i2c_bus;
  
 -      rdev->pm.default_power_state = NULL;
 +      rdev->pm.default_power_state_index = -1;
  
        if (atom_parse_data_header(mode_info->atom_context, index, NULL,
                                   &frev, &crev, &data_offset)) {
                                         power_info->info.ucOverdriveControllerAddress >> 1);
                                i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
                                rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
 +                              if (rdev->pm.i2c_bus) {
 +                                      struct i2c_board_info info = { };
 +                                      const char *name = thermal_controller_names[power_info->info.
 +                                                                                  ucOverdriveThermalController];
 +                                      info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
 +                                      strlcpy(info.type, name, sizeof(info.type));
 +                                      i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
 +                              }
                        }
                        num_modes = power_info->info.ucNumOfPowerModeEntries;
                        if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
                                num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
 +                      /* last mode is usually default, array is low to high */
                        for (i = 0; i < num_modes; i++) {
                                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
                                switch (frev) {
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
 -                                      /* skip overclock modes for now */
 -                                      if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
 -                                           rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
 -                                          (rdev->pm.power_state[state_index].clock_info[0].sclk >
 -                                           rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
 -                                              continue;
 -                                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 +                                      rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
                                        if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
 +                                      rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      rdev->pm.power_state[state_index].misc = misc;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
 -                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
 +                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      }
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
 -                                              rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
 +                                              rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      } else if (state_index == 0) {
 +                                              rdev->pm.power_state[state_index].clock_info[0].flags |=
 +                                                      RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
 -                                      /* skip overclock modes for now */
 -                                      if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
 -                                           rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
 -                                          (rdev->pm.power_state[state_index].clock_info[0].sclk >
 -                                           rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
 -                                              continue;
 -                                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 +                                      rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
 +                                      rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      rdev->pm.power_state[state_index].misc = misc;
 +                                      rdev->pm.power_state[state_index].misc2 = misc2;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
 -                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
 +                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      }
                                        if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
 +                                      if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
 -                                              rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
 +                                              rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      } else if (state_index == 0) {
 +                                              rdev->pm.power_state[state_index].clock_info[0].flags |=
 +                                                      RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
 -                                      /* skip overclock modes for now */
 -                                      if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
 -                                           rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
 -                                          (rdev->pm.power_state[state_index].clock_info[0].sclk >
 -                                           rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
 -                                              continue;
 -                                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 +                                      rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
                                                        power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
                                                }
                                        }
 +                                      rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      rdev->pm.power_state[state_index].misc = misc;
 +                                      rdev->pm.power_state[state_index].misc2 = misc2;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
 -                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
 +                                      if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
 +                                              rdev->pm.power_state[state_index].flags &=
 +                                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                                      }
                                        if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
 -                                              rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
 +                                              rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
 +                                      } else if (state_index == 0) {
 +                                              rdev->pm.power_state[state_index].clock_info[0].flags |=
 +                                                      RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
                                }
                        }
 +                      /* last mode is usually default */
 +                      if (rdev->pm.default_power_state_index == -1) {
 +                              rdev->pm.power_state[state_index - 1].type =
 +                                      POWER_STATE_TYPE_DEFAULT;
 +                              rdev->pm.default_power_state_index = state_index - 1;
 +                              rdev->pm.power_state[state_index - 1].default_clock_mode =
 +                                      &rdev->pm.power_state[state_index - 1].clock_info[0];
 +                              rdev->pm.power_state[state_index].flags &=
 +                                      ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
 +                              rdev->pm.power_state[state_index].misc = 0;
 +                              rdev->pm.power_state[state_index].misc2 = 0;
 +                      }
                } else {
                        /* add the i2c bus for thermal/fan chip */
                        /* no support for internal controller yet */
 -                      if (power_info->info_4.sThermalController.ucType > 0) {
 -                              if ((power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
 -                                  (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
 -                                  (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN)) {
 +                      ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
 +                      if (controller->ucType > 0) {
 +                              if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
 +                                  (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
 +                                  (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN)) {
                                        DRM_INFO("Internal thermal controller %s fan control\n",
 -                                               (power_info->info_4.sThermalController.ucFanParameters &
 +                                               (controller->ucFanParameters &
                                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 -                              } else if ((power_info->info_4.sThermalController.ucType ==
 +                              } else if ((controller->ucType ==
                                            ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
 -                                         (power_info->info_4.sThermalController.ucType ==
 +                                         (controller->ucType ==
                                            ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) {
                                        DRM_INFO("Special thermal controller config\n");
                                } else {
                                        DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
 -                                               pp_lib_thermal_controller_names[power_info->info_4.sThermalController.ucType],
 -                                               power_info->info_4.sThermalController.ucI2cAddress >> 1,
 -                                               (power_info->info_4.sThermalController.ucFanParameters &
 +                                               pp_lib_thermal_controller_names[controller->ucType],
 +                                               controller->ucI2cAddress >> 1,
 +                                               (controller->ucFanParameters &
                                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 -                                      i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info_4.sThermalController.ucI2cLine);
 +                                      i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
                                        rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
 +                                      if (rdev->pm.i2c_bus) {
 +                                              struct i2c_board_info info = { };
 +                                              const char *name = pp_lib_thermal_controller_names[controller->ucType];
 +                                              info.addr = controller->ucI2cAddress >> 1;
 +                                              strlcpy(info.type, name, sizeof(info.type));
 +                                              i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
 +                                      }
 +
                                }
                        }
 +                      /* first mode is usually default, followed by low to high */
                        for (i = 0; i < power_info->info_4.ucNumStates; i++) {
                                mode_index = 0;
                                power_state = (struct _ATOM_PPLIB_STATE *)
                                                /* skip invalid modes */
                                                if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
                                                        continue;
 -                                              /* skip overclock modes for now */
 -                                              if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
 -                                                  rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)
 -                                                      continue;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
                                                        VOLTAGE_SW;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
                                                if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
                                                    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
                                                        continue;
 -                                              /* skip overclock modes for now */
 -                                              if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
 -                                                   rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
 -                                                  (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
 -                                                   rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
 -                                                      continue;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
                                                        VOLTAGE_SW;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
                                                if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
                                                    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
                                                        continue;
 -                                              /* skip overclock modes for now */
 -                                              if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
 -                                                   rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
 -                                                  (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
 -                                                   rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
 -                                                      continue;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
                                                        VOLTAGE_SW;
                                                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
                                if (mode_index) {
                                        misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
                                        misc2 = le16_to_cpu(non_clock_info->usClassification);
 -                                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 +                                      rdev->pm.power_state[state_index].misc = misc;
 +                                      rdev->pm.power_state[state_index].misc2 = misc2;
 +                                      rdev->pm.power_state[state_index].pcie_lanes =
                                                ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
                                                ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
                                        switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
                                                        POWER_STATE_TYPE_PERFORMANCE;
                                                break;
                                        }
 +                                      rdev->pm.power_state[state_index].flags = 0;
 +                                      if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
 +                                              rdev->pm.power_state[state_index].flags |=
 +                                                      RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
 -                                              rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
 +                                              rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
                                        }
                                        state_index++;
                                }
                        }
 +                      /* if multiple clock modes, mark the lowest as no display */
 +                      for (i = 0; i < state_index; i++) {
 +                              if (rdev->pm.power_state[i].num_clock_modes > 1)
 +                                      rdev->pm.power_state[i].clock_info[0].flags |=
 +                                              RADEON_PM_MODE_NO_DISPLAY;
 +                      }
 +                      /* first mode is usually default */
 +                      if (rdev->pm.default_power_state_index == -1) {
 +                              rdev->pm.power_state[0].type =
 +                                      POWER_STATE_TYPE_DEFAULT;
 +                              rdev->pm.default_power_state_index = 0;
 +                              rdev->pm.power_state[0].default_clock_mode =
 +                                      &rdev->pm.power_state[0].clock_info[0];
 +                      }
                }
        } else {
 -              /* XXX figure out some good default low power mode for cards w/out power tables */
 -      }
 -
 -      if (rdev->pm.default_power_state == NULL) {
                /* add the default mode */
                rdev->pm.power_state[state_index].type =
                        POWER_STATE_TYPE_DEFAULT;
                rdev->pm.power_state[state_index].default_clock_mode =
                        &rdev->pm.power_state[state_index].clock_info[0];
                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
 -              if (rdev->asic->get_pcie_lanes)
 -                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
 -              else
 -                      rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
 -              rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
 +              rdev->pm.power_state[state_index].pcie_lanes = 16;
 +              rdev->pm.default_power_state_index = state_index;
 +              rdev->pm.power_state[state_index].flags = 0;
                state_index++;
        }
 +
        rdev->pm.num_power_states = state_index;
  
 -      rdev->pm.current_power_state = rdev->pm.default_power_state;
 -      rdev->pm.current_clock_mode =
 -              rdev->pm.default_power_state->default_clock_mode;
 +      rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 +      rdev->pm.current_clock_mode_index = 0;
  }
  
  void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
index 765854ed33c240f435d9be37f8f916ebd31a6a5d,40a24c941f20e669d1799b311c341cdd071dfc1f..0c7ccc6961a353758628d7a84ec9a843b837f7f1
@@@ -1085,7 -1085,6 +1085,7 @@@ radeon_add_atom_connector(struct drm_de
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
 +              connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                break;
        }
  
 +      if (hpd->hpd == RADEON_HPD_NONE) {
 +              if (i2c_bus->valid)
 +                      connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 +      } else
 +              connector->polled = DRM_CONNECTOR_POLL_HPD;
 +
        connector->display_info.subpixel_order = subpixel_order;
        drm_sysfs_connector_add(connector);
        return;
@@@ -1279,7 -1272,6 +1279,7 @@@ radeon_add_legacy_connector(struct drm_
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
 +              connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                        radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
                        if (!radeon_connector->ddc_bus)
                                goto failed;
+               }
+               if (connector_type == DRM_MODE_CONNECTOR_DVII) {
                        radeon_connector->dac_load_detect = true;
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.load_detect_property,
                break;
        }
  
 +      if (hpd->hpd == RADEON_HPD_NONE) {
 +              if (i2c_bus->valid)
 +                      connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 +      } else
 +              connector->polled = DRM_CONNECTOR_POLL_HPD;
        connector->display_info.subpixel_order = subpixel_order;
        drm_sysfs_connector_add(connector);
        return;
index f48f42454fbb2f29608592e1c07be457220a6989,ce5163ed1fa6f8cc4f646f4e6d0bab1c77a42085..da85cad1152b0129a270870bef7249fda2678a41
@@@ -86,12 -86,12 +86,12 @@@ static void evergreen_crtc_load_lut(str
        WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
        WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
  
-       WREG32(EVERGREEN_DC_LUT_RW_MODE, radeon_crtc->crtc_id);
-       WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007);
+       WREG32(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0);
+       WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007);
  
-       WREG32(EVERGREEN_DC_LUT_RW_INDEX, 0);
+       WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0);
        for (i = 0; i < 256; i++) {
-               WREG32(EVERGREEN_DC_LUT_30_COLOR,
+               WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset,
                       (radeon_crtc->lut_r[i] << 20) |
                       (radeon_crtc->lut_g[i] << 10) |
                       (radeon_crtc->lut_b[i] << 0));
@@@ -633,37 -633,37 +633,37 @@@ calc_fb_div(struct radeon_pll *pll
  
        vco_freq = freq * post_div;
        /* feedback_divider = vco_freq * ref_div / pll->reference_freq; */
 -      a.full = rfixed_const(pll->reference_freq);
 -      feedback_divider.full = rfixed_const(vco_freq);
 -      feedback_divider.full = rfixed_div(feedback_divider, a);
 -      a.full = rfixed_const(ref_div);
 -      feedback_divider.full = rfixed_mul(feedback_divider, a);
 +      a.full = dfixed_const(pll->reference_freq);
 +      feedback_divider.full = dfixed_const(vco_freq);
 +      feedback_divider.full = dfixed_div(feedback_divider, a);
 +      a.full = dfixed_const(ref_div);
 +      feedback_divider.full = dfixed_mul(feedback_divider, a);
  
        if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
                /* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */
 -              a.full = rfixed_const(10);
 -              feedback_divider.full = rfixed_mul(feedback_divider, a);
 -              feedback_divider.full += rfixed_const_half(0);
 -              feedback_divider.full = rfixed_floor(feedback_divider);
 -              feedback_divider.full = rfixed_div(feedback_divider, a);
 +              a.full = dfixed_const(10);
 +              feedback_divider.full = dfixed_mul(feedback_divider, a);
 +              feedback_divider.full += dfixed_const_half(0);
 +              feedback_divider.full = dfixed_floor(feedback_divider);
 +              feedback_divider.full = dfixed_div(feedback_divider, a);
  
                /* *fb_div = floor(feedback_divider); */
 -              a.full = rfixed_floor(feedback_divider);
 -              *fb_div = rfixed_trunc(a);
 +              a.full = dfixed_floor(feedback_divider);
 +              *fb_div = dfixed_trunc(a);
                /* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */
 -              a.full = rfixed_const(10);
 -              b.full = rfixed_mul(feedback_divider, a);
 +              a.full = dfixed_const(10);
 +              b.full = dfixed_mul(feedback_divider, a);
  
 -              feedback_divider.full = rfixed_floor(feedback_divider);
 -              feedback_divider.full = rfixed_mul(feedback_divider, a);
 +              feedback_divider.full = dfixed_floor(feedback_divider);
 +              feedback_divider.full = dfixed_mul(feedback_divider, a);
                feedback_divider.full = b.full - feedback_divider.full;
 -              *fb_div_frac = rfixed_trunc(feedback_divider);
 +              *fb_div_frac = dfixed_trunc(feedback_divider);
        } else {
                /* *fb_div = floor(feedback_divider + 0.5); */
 -              feedback_divider.full += rfixed_const_half(0);
 -              feedback_divider.full = rfixed_floor(feedback_divider);
 +              feedback_divider.full += dfixed_const_half(0);
 +              feedback_divider.full = dfixed_floor(feedback_divider);
  
 -              *fb_div = rfixed_trunc(feedback_divider);
 +              *fb_div = dfixed_trunc(feedback_divider);
                *fb_div_frac = 0;
        }
  
@@@ -693,10 -693,10 +693,10 @@@ calc_fb_ref_div(struct radeon_pll *pll
                pll_out_max = pll->pll_out_max;
        }
  
 -      ffreq.full = rfixed_const(freq);
 +      ffreq.full = dfixed_const(freq);
        /* max_error = ffreq * 0.0025; */
 -      a.full = rfixed_const(400);
 -      max_error.full = rfixed_div(ffreq, a);
 +      a.full = dfixed_const(400);
 +      max_error.full = dfixed_div(ffreq, a);
  
        for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
                if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) {
                                continue;
  
                        /* pll_out = vco / post_div; */
 -                      a.full = rfixed_const(post_div);
 -                      pll_out.full = rfixed_const(vco);
 -                      pll_out.full = rfixed_div(pll_out, a);
 +                      a.full = dfixed_const(post_div);
 +                      pll_out.full = dfixed_const(vco);
 +                      pll_out.full = dfixed_div(pll_out, a);
  
                        if (pll_out.full >= ffreq.full) {
                                error.full = pll_out.full - ffreq.full;
@@@ -888,15 -888,8 +888,15 @@@ radeon_user_framebuffer_create(struct d
        return &radeon_fb->base;
  }
  
 +static void radeon_output_poll_changed(struct drm_device *dev)
 +{
 +      struct radeon_device *rdev = dev->dev_private;
 +      radeon_fb_output_poll_changed(rdev);
 +}
 +
  static const struct drm_mode_config_funcs radeon_mode_funcs = {
        .fb_create = radeon_user_framebuffer_create,
 +      .output_poll_changed = radeon_output_poll_changed
  };
  
  struct drm_prop_enum_list {
@@@ -1037,12 -1030,7 +1037,12 @@@ int radeon_modeset_init(struct radeon_d
        /* initialize hpd */
        radeon_hpd_init(rdev);
  
 +      /* Initialize power management */
 +      radeon_pm_init(rdev);
 +
        radeon_fbdev_init(rdev);
 +      drm_kms_helper_poll_init(rdev->ddev);
 +
        return 0;
  }
  
@@@ -1050,10 -1038,8 +1050,10 @@@ void radeon_modeset_fini(struct radeon_
  {
        radeon_fbdev_fini(rdev);
        kfree(rdev->mode_info.bios_hardcoded_edid);
 +      radeon_pm_fini(rdev);
  
        if (rdev->mode_info.mode_config_initialized) {
 +              drm_kms_helper_poll_fini(rdev->ddev);
                radeon_hpd_fini(rdev);
                drm_mode_config_cleanup(rdev->ddev);
                rdev->mode_info.mode_config_initialized = false;
@@@ -1103,15 -1089,15 +1103,15 @@@ bool radeon_crtc_scaling_mode_fixup(str
        }
        if (radeon_crtc->rmx_type != RMX_OFF) {
                fixed20_12 a, b;
 -              a.full = rfixed_const(crtc->mode.vdisplay);
 -              b.full = rfixed_const(radeon_crtc->native_mode.hdisplay);
 -              radeon_crtc->vsc.full = rfixed_div(a, b);
 -              a.full = rfixed_const(crtc->mode.hdisplay);
 -              b.full = rfixed_const(radeon_crtc->native_mode.vdisplay);
 -              radeon_crtc->hsc.full = rfixed_div(a, b);
 +              a.full = dfixed_const(crtc->mode.vdisplay);
 +              b.full = dfixed_const(radeon_crtc->native_mode.hdisplay);
 +              radeon_crtc->vsc.full = dfixed_div(a, b);
 +              a.full = dfixed_const(crtc->mode.hdisplay);
 +              b.full = dfixed_const(radeon_crtc->native_mode.vdisplay);
 +              radeon_crtc->hsc.full = dfixed_div(a, b);
        } else {
 -              radeon_crtc->vsc.full = rfixed_const(1);
 -              radeon_crtc->hsc.full = rfixed_const(1);
 +              radeon_crtc->vsc.full = dfixed_const(1);
 +              radeon_crtc->hsc.full = dfixed_const(1);
        }
        return true;
  }
index b5dff14ea8c6e8ef71b0d8e4a8dfb063cc87417a,c5ddaf58563a22505a283c528faf06c1587d6bb8..1ebb100015b70b71f354ce8c4405b13455a02c8b
@@@ -254,6 -254,53 +254,53 @@@ radeon_get_atom_connector_priv_from_enc
        return dig_connector;
  }
  
+ void radeon_panel_mode_fixup(struct drm_encoder *encoder,
+                            struct drm_display_mode *adjusted_mode)
+ {
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+       unsigned hblank = native_mode->htotal - native_mode->hdisplay;
+       unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
+       unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
+       unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
+       unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
+       unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
+       adjusted_mode->clock = native_mode->clock;
+       adjusted_mode->flags = native_mode->flags;
+       if (ASIC_IS_AVIVO(rdev)) {
+               adjusted_mode->hdisplay = native_mode->hdisplay;
+               adjusted_mode->vdisplay = native_mode->vdisplay;
+       }
+       adjusted_mode->htotal = native_mode->hdisplay + hblank;
+       adjusted_mode->hsync_start = native_mode->hdisplay + hover;
+       adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
+       adjusted_mode->vtotal = native_mode->vdisplay + vblank;
+       adjusted_mode->vsync_start = native_mode->vdisplay + vover;
+       adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
+       drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+       if (ASIC_IS_AVIVO(rdev)) {
+               adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
+               adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
+       }
+       adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
+       adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
+       adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
+       adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
+       adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
+       adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
+ }
  static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
  
 -      /* adjust pm to upcoming mode change */
 -      radeon_pm_compute_clocks(rdev);
 -
        /* set the active encoder to connector routing */
        radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
                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)) {
-               struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
-               int mode_id = adjusted_mode->base.id;
-               *adjusted_mode = *native_mode;
-               if (!ASIC_IS_AVIVO(rdev)) {
-                       adjusted_mode->hdisplay = mode->hdisplay;
-                       adjusted_mode->vdisplay = mode->vdisplay;
-                       adjusted_mode->crtc_hdisplay = mode->hdisplay;
-                       adjusted_mode->crtc_vdisplay = mode->vdisplay;
-               }
-               adjusted_mode->base.id = mode_id;
-       }
+       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)) {
@@@ -1071,6 -1111,8 +1108,6 @@@ radeon_atom_encoder_dpms(struct drm_enc
        }
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  union crtc_source_param {
@@@ -1321,7 -1363,7 +1358,7 @@@ radeon_atom_encoder_mode_set(struct drm
  
        radeon_encoder->pixel_clock = adjusted_mode->clock;
  
-       if (ASIC_IS_AVIVO(rdev)) {
+       if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
                if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
                        atombios_yuv_setup(encoder, true);
                else
@@@ -1504,49 -1546,10 +1541,49 @@@ static void radeon_atom_encoder_commit(
  
  static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
  {
 +      struct drm_device *dev = encoder->dev;
 +      struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig;
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
  
 +      switch (radeon_encoder->encoder_id) {
 +      case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
 +      case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
 +      case ENCODER_OBJECT_ID_INTERNAL_LVDS:
 +      case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
 +              atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
 +              break;
 +      case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 +      case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 +      case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 +      case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 +              if (ASIC_IS_DCE4(rdev))
 +                      /* disable the transmitter */
 +                      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, 0, 0);
 +                      atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
 +              }
 +              break;
 +      case ENCODER_OBJECT_ID_INTERNAL_DDI:
 +              atombios_ddia_setup(encoder, ATOM_DISABLE);
 +              break;
 +      case ENCODER_OBJECT_ID_INTERNAL_DVO1:
 +      case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
 +              atombios_external_tmds_setup(encoder, ATOM_DISABLE);
 +              break;
 +      case ENCODER_OBJECT_ID_INTERNAL_DAC1:
 +      case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 +      case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 +      case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 +              atombios_dac_setup(encoder, ATOM_DISABLE);
 +              if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
 +                      atombios_tv_setup(encoder, ATOM_DISABLE);
 +              break;
 +      }
 +
        if (radeon_encoder_is_digital(encoder)) {
                if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
                        r600_hdmi_disable(encoder);
index 021572a3dd9cfd61b8afe98012c498aa7d2ad5e5,c633319f98edb47bd3f9b8ae8cabe847c909cb20..04068352ccd208a0641317a81c805c2c6dd47d29
@@@ -98,15 -98,11 +98,15 @@@ int radeon_info_ioctl(struct drm_devic
  {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_radeon_info *info;
 +      struct radeon_mode_info *minfo = &rdev->mode_info;
        uint32_t *value_ptr;
        uint32_t value;
 +      struct drm_crtc *crtc;
 +      int i, found;
  
        info = data;
        value_ptr = (uint32_t *)((unsigned long)info->value);
 +      value = *value_ptr;
        switch (info->request) {
        case RADEON_INFO_DEVICE_ID:
                value = dev->pci_device;
        case RADEON_INFO_ACCEL_WORKING:
                value = rdev->accel_working;
                break;
 +      case RADEON_INFO_CRTC_FROM_ID:
 +              for (i = 0, found = 0; i < rdev->num_crtc; i++) {
 +                      crtc = (struct drm_crtc *)minfo->crtcs[i];
 +                      if (crtc && crtc->base.id == value) {
 +                              value = i;
 +                              found = 1;
 +                              break;
 +                      }
 +              }
 +              if (!found) {
 +                      DRM_DEBUG("unknown crtc id %d\n", value);
 +                      return -EINVAL;
 +              }
 +              break;
        default:
                DRM_DEBUG("Invalid request %d\n", info->request);
                return -EINVAL;
@@@ -183,7 -165,7 +183,7 @@@ u32 radeon_get_vblank_counter_kms(struc
  {
        struct radeon_device *rdev = dev->dev_private;
  
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return -EINVAL;
        }
@@@ -195,7 -177,7 +195,7 @@@ int radeon_enable_vblank_kms(struct drm
  {
        struct radeon_device *rdev = dev->dev_private;
  
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return -EINVAL;
        }
@@@ -209,7 -191,7 +209,7 @@@ void radeon_disable_vblank_kms(struct d
  {
        struct radeon_device *rdev = dev->dev_private;
  
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return;
        }
index 341df86a253b230fc84d1b597c6c7626d271e8ce,0274abe17ad982ca8e2004e70c548fd7d55126af..5a13b3eeef1927f2cdeeb36ca3d70de8bf69f049
@@@ -116,6 -116,8 +116,6 @@@ static void radeon_legacy_lvds_dpms(str
        else
                radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
@@@ -215,22 -217,19 +215,14 @@@ static bool radeon_legacy_mode_fixup(st
                                     struct drm_display_mode *adjusted_mode)
  {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 -      struct drm_device *dev = encoder->dev;
 -      struct radeon_device *rdev = dev->dev_private;
 -
 -      /* adjust pm to upcoming mode change */
 -      radeon_pm_compute_clocks(rdev);
  
        /* set the active encoder to connector routing */
        radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
  
        /* get the native mode for LVDS */
-       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
-               struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
-               int mode_id = adjusted_mode->base.id;
-               *adjusted_mode = *native_mode;
-               adjusted_mode->hdisplay = mode->hdisplay;
-               adjusted_mode->vdisplay = mode->vdisplay;
-               adjusted_mode->crtc_hdisplay = mode->hdisplay;
-               adjusted_mode->crtc_vdisplay = mode->vdisplay;
-               adjusted_mode->base.id = mode_id;
-       }
+       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+               radeon_panel_mode_fixup(encoder, adjusted_mode);
  
        return true;
  }
@@@ -287,6 -286,8 +279,6 @@@ static void radeon_legacy_primary_dac_d
        else
                radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
@@@ -473,6 -474,8 +465,6 @@@ static void radeon_legacy_tmds_int_dpms
        else
                radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
@@@ -639,6 -642,8 +631,6 @@@ static void radeon_legacy_tmds_ext_dpms
        else
                radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
@@@ -847,6 -852,8 +839,6 @@@ static void radeon_legacy_tv_dac_dpms(s
        else
                radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
  
 -      /* adjust pm to dpms change */
 -      radeon_pm_compute_clocks(rdev);
  }
  
  static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
index 38c0b63e9bbd9aa70e9e33d4cff844171f450f78,a2bc31465e4faa950c4e7976e211a0c4a71a7e14..71e1f0e7438d0d4db3163de9a143093e47d0bb12
  #include <drm_mode.h>
  #include <drm_edid.h>
  #include <drm_dp_helper.h>
 +#include <drm_fixed.h>
  #include <linux/i2c.h>
  #include <linux/i2c-id.h>
  #include <linux/i2c-algo-bit.h>
 -#include "radeon_fixed.h"
  
  struct radeon_bo;
  struct radeon_device;
@@@ -564,6 -564,8 +564,8 @@@ extern int radeon_static_clocks_init(st
  bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                                        struct drm_display_mode *mode,
                                        struct drm_display_mode *adjusted_mode);
+ void radeon_panel_mode_fixup(struct drm_encoder *encoder,
+                            struct drm_display_mode *adjusted_mode);
  void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc);
  
  /* legacy tv */
@@@ -586,6 -588,5 +588,6 @@@ void radeon_fbdev_fini(struct radeon_de
  void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
  int radeon_fbdev_total_size(struct radeon_device *rdev);
  bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
 -void radeonfb_hotplug(struct drm_device *dev, bool polled);
 +
 +void radeon_fb_output_poll_changed(struct radeon_device *rdev);
  #endif
diff --combined drivers/video/efifb.c
index 3b986567111a4fbdc85de35ee1016d9fe645e98e,ecf405562f5ce7cff5c4a2549409162b87d680cb..4a56f46af40a35a0eeb76a307a4b0420c36699d2
@@@ -49,6 -49,7 +49,7 @@@ enum 
        M_MBP_2,        /* MacBook Pro 2nd gen */
        M_MBP_SR,       /* MacBook Pro (Santa Rosa) */
        M_MBP_4,        /* MacBook Pro, 4th gen */
+       M_MBP_5_1,    /* MacBook Pro, 5,1th gen */
        M_UNKNOWN       /* placeholder */
  };
  
@@@ -70,6 -71,7 +71,7 @@@ static struct efifb_dmi_info 
        [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
        [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
        [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
+       [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
        [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
  };
  
@@@ -106,6 -108,7 +108,7 @@@ static struct dmi_system_id __initdata 
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
        {},
  };
  
@@@ -165,7 -168,7 +168,7 @@@ static void efifb_destroy(struct fb_inf
  {
        if (info->screen_base)
                iounmap(info->screen_base);
 -      release_mem_region(info->aperture_base, info->aperture_size);
 +      release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
        framebuffer_release(info);
  }
  
@@@ -289,13 -292,8 +292,13 @@@ static int __devinit efifb_probe(struc
        info->pseudo_palette = info->par;
        info->par = NULL;
  
 -      info->aperture_base = efifb_fix.smem_start;
 -      info->aperture_size = size_remap;
 +      info->apertures = alloc_apertures(1);
 +      if (!info->apertures) {
 +              err = -ENOMEM;
 +              goto err_release_fb;
 +      }
 +      info->apertures->ranges[0].base = efifb_fix.smem_start;
 +      info->apertures->ranges[0].size = size_remap;
  
        info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
        if (!info->screen_base) {
This page took 0.174928 seconds and 4 git commands to generate.