提交 d5a0f2e7 编写于 作者: D Dave Airlie

Merge tag 'drm-intel-next-2014-08-08' of git://anongit.freedesktop.org/drm-intel into drm-next

- Setting dp M2/N2 values plus state checker support (Vandana Kannan)
- chv power well support (Ville)
- DP training pattern 3 support for chv (Ville)
- cleanup of the hsw/bdw ddi pll code, prep work for skl (Damien)
- dsi video burst mode support (Shobhit)
- piles of other chv fixes all over (Ville et. al.)
- cleanup of the ddi translation tables setup code (Damien)
- 180 deg rotation support (Ville & Sonika Jindal)

* tag 'drm-intel-next-2014-08-08' of git://anongit.freedesktop.org/drm-intel: (59 commits)
  drm/i915: Update DRIVER_DATE to 20140808
  drm/i915: No busy-loop wait_for in the ring init code
  drm/i915: Add sprite watermark programming for VLV and CHV
  drm/i915: Round-up clock and limit drain latency
  drm/i915: Generalize drain latency computation
  drm/i915: Free pending page flip events at .preclose()
  drm/i915: clean up PPGTT checking logic
  drm/i915: Polish the chv cmnlane resrt macros
  drm/i915: Hack to tie both common lanes together on chv
  drm/i915: Add cherryview_update_wm()
  drm/i915: Update DDL only for current CRTC
  drm/i915: Parametrize VLV_DDL registers
  drm/i915: Fill out the FWx watermark register defines
  drm: Resetting rotation property
  drm/i915: Add rotation property for sprites
  drm: Add rotation_property to mode_config
  drm/i915: Make intel_plane_restore() return an error
  drm/i915: Add 180 degree sprite rotation support
  drm/i915: Introduce a for_each_intel_encoder() macro
  drm/i915: Demote the DRRS messages to debug messages
  ...
...@@ -3400,6 +3400,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis> ...@@ -3400,6 +3400,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
<sect2> <sect2>
<title>Vertical Blanking and Interrupt Handling Functions Reference</title> <title>Vertical Blanking and Interrupt Handling Functions Reference</title>
!Edrivers/gpu/drm/drm_irq.c !Edrivers/gpu/drm/drm_irq.c
!Iinclude/drm/drmP.h drm_crtc_vblank_waitqueue
</sect2> </sect2>
</sect1> </sect1>
......
...@@ -291,10 +291,17 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) ...@@ -291,10 +291,17 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
drm_warn_on_modeset_not_all_locked(dev); drm_warn_on_modeset_not_all_locked(dev);
list_for_each_entry(plane, &dev->mode_config.plane_list, head) list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY) if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane); drm_plane_force_disable(plane);
if (dev->mode_config.rotation_property) {
drm_object_property_set_value(&plane->base,
dev->mode_config.rotation_property,
BIT(DRM_ROTATE_0));
}
}
for (i = 0; i < fb_helper->crtc_count; i++) { for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
struct drm_crtc *crtc = mode_set->crtc; struct drm_crtc *crtc = mode_set->crtc;
......
...@@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused) ...@@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
return 0; return 0;
} }
static int i915_fbc_fc_get(void *data, u64 *val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev))
return -ENODEV;
drm_modeset_lock_all(dev);
*val = dev_priv->fbc.false_color;
drm_modeset_unlock_all(dev);
return 0;
}
static int i915_fbc_fc_set(void *data, u64 val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg;
if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev))
return -ENODEV;
drm_modeset_lock_all(dev);
reg = I915_READ(ILK_DPFC_CONTROL);
dev_priv->fbc.false_color = val;
I915_WRITE(ILK_DPFC_CONTROL, val ?
(reg | FBC_CTL_FALSE_COLOR) :
(reg & ~FBC_CTL_FALSE_COLOR));
drm_modeset_unlock_all(dev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_fc_fops,
i915_fbc_fc_get, i915_fbc_fc_set,
"%llu\n");
static int i915_ips_status(struct seq_file *m, void *unused) static int i915_ips_status(struct seq_file *m, void *unused)
{ {
struct drm_info_node *node = m->private; struct drm_info_node *node = m->private;
...@@ -2667,8 +2708,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, ...@@ -2667,8 +2708,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,
*source = INTEL_PIPE_CRC_SOURCE_PIPE; *source = INTEL_PIPE_CRC_SOURCE_PIPE;
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, for_each_intel_encoder(dev, encoder) {
base.head) {
if (!encoder->base.crtc) if (!encoder->base.crtc)
continue; continue;
...@@ -3957,6 +3997,7 @@ static const struct i915_debugfs_files { ...@@ -3957,6 +3997,7 @@ static const struct i915_debugfs_files {
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, {"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
{"i915_spr_wm_latency", &i915_spr_wm_latency_fops}, {"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
{"i915_cur_wm_latency", &i915_cur_wm_latency_fops}, {"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
{"i915_fbc_false_color", &i915_fbc_fc_fops},
}; };
void intel_display_crc_init(struct drm_device *dev) void intel_display_crc_init(struct drm_device *dev)
......
...@@ -1981,6 +1981,9 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file) ...@@ -1981,6 +1981,9 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
i915_gem_context_close(dev, file); i915_gem_context_close(dev, file);
i915_gem_release(dev, file); i915_gem_release(dev, file);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_modeset_preclose(dev, file);
} }
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#define DRIVER_NAME "i915" #define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics" #define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20140725" #define DRIVER_DATE "20140808"
enum pipe { enum pipe {
INVALID_PIPE = -1, INVALID_PIPE = -1,
...@@ -171,6 +171,11 @@ enum hpd_pin { ...@@ -171,6 +171,11 @@ enum hpd_pin {
#define for_each_intel_crtc(dev, intel_crtc) \ #define for_each_intel_crtc(dev, intel_crtc) \
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
#define for_each_intel_encoder(dev, intel_encoder) \
list_for_each_entry(intel_encoder, \
&(dev)->mode_config.encoder_list, \
base.head)
#define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
if ((intel_encoder)->base.crtc == (__crtc)) if ((intel_encoder)->base.crtc == (__crtc))
...@@ -197,10 +202,13 @@ enum intel_dpll_id { ...@@ -197,10 +202,13 @@ enum intel_dpll_id {
#define I915_NUM_PLLS 2 #define I915_NUM_PLLS 2
struct intel_dpll_hw_state { struct intel_dpll_hw_state {
/* i9xx, pch plls */
uint32_t dpll; uint32_t dpll;
uint32_t dpll_md; uint32_t dpll_md;
uint32_t fp0; uint32_t fp0;
uint32_t fp1; uint32_t fp1;
/* hsw, bdw */
uint32_t wrpll; uint32_t wrpll;
}; };
...@@ -634,6 +642,8 @@ struct i915_fbc { ...@@ -634,6 +642,8 @@ struct i915_fbc {
struct drm_mm_node compressed_fb; struct drm_mm_node compressed_fb;
struct drm_mm_node *compressed_llb; struct drm_mm_node *compressed_llb;
bool false_color;
struct intel_fbc_work { struct intel_fbc_work {
struct delayed_work work; struct delayed_work work;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -1227,6 +1237,12 @@ enum modeset_restore { ...@@ -1227,6 +1237,12 @@ enum modeset_restore {
}; };
struct ddi_vbt_port_info { struct ddi_vbt_port_info {
/*
* This is an index in the HDMI/DVI DDI buffer translation table.
* The special value HDMI_LEVEL_SHIFT_UNKNOWN means the VBT didn't
* populate this field.
*/
#define HDMI_LEVEL_SHIFT_UNKNOWN 0xff
uint8_t hdmi_level_shift; uint8_t hdmi_level_shift;
uint8_t supports_dvi:1; uint8_t supports_dvi:1;
...@@ -2049,8 +2065,8 @@ struct drm_i915_cmd_table { ...@@ -2049,8 +2065,8 @@ struct drm_i915_cmd_table {
#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev)) #define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))
#define USES_PPGTT(dev) intel_enable_ppgtt(dev, false) #define USES_PPGTT(dev) (i915.enable_ppgtt)
#define USES_FULL_PPGTT(dev) intel_enable_ppgtt(dev, true) #define USES_FULL_PPGTT(dev) (i915.enable_ppgtt == 2)
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
......
...@@ -33,17 +33,6 @@ ...@@ -33,17 +33,6 @@
static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv); static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv);
static void chv_setup_private_ppat(struct drm_i915_private *dev_priv); static void chv_setup_private_ppat(struct drm_i915_private *dev_priv);
bool intel_enable_ppgtt(struct drm_device *dev, bool full)
{
if (i915.enable_ppgtt == 0)
return false;
if (i915.enable_ppgtt == 1 && full)
return false;
return true;
}
static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
{ {
if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
......
...@@ -272,7 +272,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev); ...@@ -272,7 +272,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev);
void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start, void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
unsigned long mappable_end, unsigned long end); unsigned long mappable_end, unsigned long end);
bool intel_enable_ppgtt(struct drm_device *dev, bool full);
int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt); int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
void i915_check_and_clear_faults(struct drm_device *dev); void i915_check_and_clear_faults(struct drm_device *dev);
......
...@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) ...@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{ {
assert_spin_locked(&dev_priv->irq_lock); assert_spin_locked(&dev_priv->irq_lock);
if (!intel_irqs_enabled(dev_priv)) if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return; return;
if ((dev_priv->irq_mask & mask) != mask) { if ((dev_priv->irq_mask & mask) != mask) {
...@@ -1984,14 +1984,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) ...@@ -1984,14 +1984,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe) static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
{ {
struct intel_crtc *crtc;
if (!drm_handle_vblank(dev, pipe)) if (!drm_handle_vblank(dev, pipe))
return false; return false;
crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
wake_up(&crtc->vbl_wait);
return true; return true;
} }
...@@ -3522,18 +3517,17 @@ static void cherryview_irq_preinstall(struct drm_device *dev) ...@@ -3522,18 +3517,17 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
static void ibx_hpd_irq_setup(struct drm_device *dev) static void ibx_hpd_irq_setup(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
u32 hotplug_irqs, hotplug, enabled_irqs = 0; u32 hotplug_irqs, hotplug, enabled_irqs = 0;
if (HAS_PCH_IBX(dev)) { if (HAS_PCH_IBX(dev)) {
hotplug_irqs = SDE_HOTPLUG_MASK; hotplug_irqs = SDE_HOTPLUG_MASK;
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin]; enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
} else { } else {
hotplug_irqs = SDE_HOTPLUG_MASK_CPT; hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin]; enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
} }
...@@ -4444,7 +4438,6 @@ static int i965_irq_postinstall(struct drm_device *dev) ...@@ -4444,7 +4438,6 @@ static int i965_irq_postinstall(struct drm_device *dev)
static void i915_hpd_irq_setup(struct drm_device *dev) static void i915_hpd_irq_setup(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
u32 hotplug_en; u32 hotplug_en;
...@@ -4455,7 +4448,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev) ...@@ -4455,7 +4448,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
hotplug_en &= ~HOTPLUG_INT_EN_MASK; hotplug_en &= ~HOTPLUG_INT_EN_MASK;
/* Note HDMI and DP share hotplug bits */ /* Note HDMI and DP share hotplug bits */
/* enable bits are the same for all generations */ /* enable bits are the same for all generations */
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin]; hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
/* Programming the CRT detection parameters tends /* Programming the CRT detection parameters tends
......
...@@ -497,10 +497,26 @@ ...@@ -497,10 +497,26 @@
#define BUNIT_REG_BISOC 0x11 #define BUNIT_REG_BISOC 0x11
#define PUNIT_REG_DSPFREQ 0x36 #define PUNIT_REG_DSPFREQ 0x36
#define DSPFREQSTAT_SHIFT_CHV 24
#define DSPFREQSTAT_MASK_CHV (0x1f << DSPFREQSTAT_SHIFT_CHV)
#define DSPFREQGUAR_SHIFT_CHV 8
#define DSPFREQGUAR_MASK_CHV (0x1f << DSPFREQGUAR_SHIFT_CHV)
#define DSPFREQSTAT_SHIFT 30 #define DSPFREQSTAT_SHIFT 30
#define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT) #define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT)
#define DSPFREQGUAR_SHIFT 14 #define DSPFREQGUAR_SHIFT 14
#define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT) #define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT)
#define _DP_SSC(val, pipe) ((val) << (2 * (pipe)))
#define DP_SSC_MASK(pipe) _DP_SSC(0x3, (pipe))
#define DP_SSC_PWR_ON(pipe) _DP_SSC(0x0, (pipe))
#define DP_SSC_CLK_GATE(pipe) _DP_SSC(0x1, (pipe))
#define DP_SSC_RESET(pipe) _DP_SSC(0x2, (pipe))
#define DP_SSC_PWR_GATE(pipe) _DP_SSC(0x3, (pipe))
#define _DP_SSS(val, pipe) ((val) << (2 * (pipe) + 16))
#define DP_SSS_MASK(pipe) _DP_SSS(0x3, (pipe))
#define DP_SSS_PWR_ON(pipe) _DP_SSS(0x0, (pipe))
#define DP_SSS_CLK_GATE(pipe) _DP_SSS(0x1, (pipe))
#define DP_SSS_RESET(pipe) _DP_SSS(0x2, (pipe))
#define DP_SSS_PWR_GATE(pipe) _DP_SSS(0x3, (pipe))
/* See the PUNIT HAS v0.8 for the below bits */ /* See the PUNIT HAS v0.8 for the below bits */
enum punit_power_well { enum punit_power_well {
...@@ -514,6 +530,11 @@ enum punit_power_well { ...@@ -514,6 +530,11 @@ enum punit_power_well {
PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 = 9, PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 = 9,
PUNIT_POWER_WELL_DPIO_RX0 = 10, PUNIT_POWER_WELL_DPIO_RX0 = 10,
PUNIT_POWER_WELL_DPIO_RX1 = 11, PUNIT_POWER_WELL_DPIO_RX1 = 11,
PUNIT_POWER_WELL_DPIO_CMN_D = 12,
/* FIXME: guesswork below */
PUNIT_POWER_WELL_DPIO_TX_D_LANES_01 = 13,
PUNIT_POWER_WELL_DPIO_TX_D_LANES_23 = 14,
PUNIT_POWER_WELL_DPIO_RX2 = 15,
PUNIT_POWER_WELL_NUM, PUNIT_POWER_WELL_NUM,
}; };
...@@ -834,8 +855,8 @@ enum punit_power_well { ...@@ -834,8 +855,8 @@ enum punit_power_well {
#define _VLV_TX_DW2_CH0 0x8288 #define _VLV_TX_DW2_CH0 0x8288
#define _VLV_TX_DW2_CH1 0x8488 #define _VLV_TX_DW2_CH1 0x8488
#define DPIO_SWING_MARGIN_SHIFT 16 #define DPIO_SWING_MARGIN000_SHIFT 16
#define DPIO_SWING_MARGIN_MASK (0xff << DPIO_SWING_MARGIN_SHIFT) #define DPIO_SWING_MARGIN000_MASK (0xff << DPIO_SWING_MARGIN000_SHIFT)
#define DPIO_UNIQ_TRANS_SCALE_SHIFT 8 #define DPIO_UNIQ_TRANS_SCALE_SHIFT 8
#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1) #define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
...@@ -843,12 +864,16 @@ enum punit_power_well { ...@@ -843,12 +864,16 @@ enum punit_power_well {
#define _VLV_TX_DW3_CH1 0x848c #define _VLV_TX_DW3_CH1 0x848c
/* The following bit for CHV phy */ /* The following bit for CHV phy */
#define DPIO_TX_UNIQ_TRANS_SCALE_EN (1<<27) #define DPIO_TX_UNIQ_TRANS_SCALE_EN (1<<27)
#define DPIO_SWING_MARGIN101_SHIFT 16
#define DPIO_SWING_MARGIN101_MASK (0xff << DPIO_SWING_MARGIN101_SHIFT)
#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1) #define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1)
#define _VLV_TX_DW4_CH0 0x8290 #define _VLV_TX_DW4_CH0 0x8290
#define _VLV_TX_DW4_CH1 0x8490 #define _VLV_TX_DW4_CH1 0x8490
#define DPIO_SWING_DEEMPH9P5_SHIFT 24 #define DPIO_SWING_DEEMPH9P5_SHIFT 24
#define DPIO_SWING_DEEMPH9P5_MASK (0xff << DPIO_SWING_DEEMPH9P5_SHIFT) #define DPIO_SWING_DEEMPH9P5_MASK (0xff << DPIO_SWING_DEEMPH9P5_SHIFT)
#define DPIO_SWING_DEEMPH6P0_SHIFT 16
#define DPIO_SWING_DEEMPH6P0_MASK (0xff << DPIO_SWING_DEEMPH6P0_SHIFT)
#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1) #define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1)
#define _VLV_TX3_DW4_CH0 0x690 #define _VLV_TX3_DW4_CH0 0x690
...@@ -1515,6 +1540,7 @@ enum punit_power_well { ...@@ -1515,6 +1540,7 @@ enum punit_power_well {
/* Framebuffer compression for Ironlake */ /* Framebuffer compression for Ironlake */
#define ILK_DPFC_CB_BASE 0x43200 #define ILK_DPFC_CB_BASE 0x43200
#define ILK_DPFC_CONTROL 0x43208 #define ILK_DPFC_CONTROL 0x43208
#define FBC_CTL_FALSE_COLOR (1<<10)
/* The bit 28-8 is reserved */ /* The bit 28-8 is reserved */
#define DPFC_RESERVED (0x1FFFFF00) #define DPFC_RESERVED (0x1FFFFF00)
#define ILK_DPFC_RECOMP_CTL 0x4320c #define ILK_DPFC_RECOMP_CTL 0x4320c
...@@ -1671,12 +1697,9 @@ enum punit_power_well { ...@@ -1671,12 +1697,9 @@ enum punit_power_well {
#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240) #define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf) #define DPLL_PORTD_READY_MASK (0xf)
#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100) #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
#define PHY_COM_LANE_RESET_DEASSERT(phy, val) \ #define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
((phy == DPIO_PHY0) ? (val | 1) : (val | 2))
#define PHY_COM_LANE_RESET_ASSERT(phy, val) \
((phy == DPIO_PHY0) ? (val & ~1) : (val & ~2))
#define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104) #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
#define PHY_POWERGOOD(phy) ((phy == DPIO_PHY0) ? (1<<31) : (1<<30)) #define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
/* /*
* The i830 generation, in LVDS mode, defines P1 as the bit number set within * The i830 generation, in LVDS mode, defines P1 as the bit number set within
...@@ -3472,6 +3495,8 @@ enum punit_power_well { ...@@ -3472,6 +3495,8 @@ enum punit_power_well {
#define DP_LINK_TRAIN_OFF (3 << 28) #define DP_LINK_TRAIN_OFF (3 << 28)
#define DP_LINK_TRAIN_MASK (3 << 28) #define DP_LINK_TRAIN_MASK (3 << 28)
#define DP_LINK_TRAIN_SHIFT 28 #define DP_LINK_TRAIN_SHIFT 28
#define DP_LINK_TRAIN_PAT_3_CHV (1 << 14)
#define DP_LINK_TRAIN_MASK_CHV ((3 << 28)|(1<<14))
/* CPT Link training mode */ /* CPT Link training mode */
#define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) #define DP_LINK_TRAIN_PAT_1_CPT (0 << 8)
...@@ -3728,7 +3753,6 @@ enum punit_power_well { ...@@ -3728,7 +3753,6 @@ enum punit_power_well {
#define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9) #define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9)
#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) #define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
#define PIPE_DPST_EVENT_STATUS (1UL<<7) #define PIPE_DPST_EVENT_STATUS (1UL<<7)
#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6)
#define PIPE_A_PSR_STATUS_VLV (1UL<<6) #define PIPE_A_PSR_STATUS_VLV (1UL<<6)
#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6) #define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6)
#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) #define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
...@@ -3838,6 +3862,7 @@ enum punit_power_well { ...@@ -3838,6 +3862,7 @@ enum punit_power_well {
#define DSPARB_BEND_SHIFT 9 /* on 855 */ #define DSPARB_BEND_SHIFT 9 /* on 855 */
#define DSPARB_AEND_SHIFT 0 #define DSPARB_AEND_SHIFT 0
/* pnv/gen4/g4x/vlv/chv */
#define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034) #define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034)
#define DSPFW_SR_SHIFT 23 #define DSPFW_SR_SHIFT 23
#define DSPFW_SR_MASK (0x1ff<<23) #define DSPFW_SR_MASK (0x1ff<<23)
...@@ -3845,66 +3870,143 @@ enum punit_power_well { ...@@ -3845,66 +3870,143 @@ enum punit_power_well {
#define DSPFW_CURSORB_MASK (0x3f<<16) #define DSPFW_CURSORB_MASK (0x3f<<16)
#define DSPFW_PLANEB_SHIFT 8 #define DSPFW_PLANEB_SHIFT 8
#define DSPFW_PLANEB_MASK (0x7f<<8) #define DSPFW_PLANEB_MASK (0x7f<<8)
#define DSPFW_PLANEA_MASK (0x7f) #define DSPFW_PLANEB_MASK_VLV (0xff<<8) /* vlv/chv */
#define DSPFW_PLANEA_SHIFT 0
#define DSPFW_PLANEA_MASK (0x7f<<0)
#define DSPFW_PLANEA_MASK_VLV (0xff<<0) /* vlv/chv */
#define DSPFW2 (dev_priv->info.display_mmio_offset + 0x70038) #define DSPFW2 (dev_priv->info.display_mmio_offset + 0x70038)
#define DSPFW_CURSORA_MASK 0x00003f00 #define DSPFW_FBC_SR_EN (1<<31) /* g4x */
#define DSPFW_FBC_SR_SHIFT 28
#define DSPFW_FBC_SR_MASK (0x7<<28) /* g4x */
#define DSPFW_FBC_HPLL_SR_SHIFT 24
#define DSPFW_FBC_HPLL_SR_MASK (0xf<<24) /* g4x */
#define DSPFW_SPRITEB_SHIFT (16)
#define DSPFW_SPRITEB_MASK (0x7f<<16) /* g4x */
#define DSPFW_SPRITEB_MASK_VLV (0xff<<16) /* vlv/chv */
#define DSPFW_CURSORA_SHIFT 8 #define DSPFW_CURSORA_SHIFT 8
#define DSPFW_PLANEC_MASK (0x7f) #define DSPFW_CURSORA_MASK (0x3f<<8)
#define DSPFW_PLANEC_SHIFT_OLD 0
#define DSPFW_PLANEC_MASK_OLD (0x7f<<0) /* pre-gen4 sprite C */
#define DSPFW_SPRITEA_SHIFT 0
#define DSPFW_SPRITEA_MASK (0x7f<<0) /* g4x */
#define DSPFW_SPRITEA_MASK_VLV (0xff<<0) /* vlv/chv */
#define DSPFW3 (dev_priv->info.display_mmio_offset + 0x7003c) #define DSPFW3 (dev_priv->info.display_mmio_offset + 0x7003c)
#define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_HPLL_SR_EN (1<<31)
#define DSPFW_CURSOR_SR_SHIFT 24
#define PINEVIEW_SELF_REFRESH_EN (1<<30) #define PINEVIEW_SELF_REFRESH_EN (1<<30)
#define DSPFW_CURSOR_SR_SHIFT 24
#define DSPFW_CURSOR_SR_MASK (0x3f<<24) #define DSPFW_CURSOR_SR_MASK (0x3f<<24)
#define DSPFW_HPLL_CURSOR_SHIFT 16 #define DSPFW_HPLL_CURSOR_SHIFT 16
#define DSPFW_HPLL_CURSOR_MASK (0x3f<<16) #define DSPFW_HPLL_CURSOR_MASK (0x3f<<16)
#define DSPFW_HPLL_SR_MASK (0x1ff) #define DSPFW_HPLL_SR_SHIFT 0
#define DSPFW4 (dev_priv->info.display_mmio_offset + 0x70070) #define DSPFW_HPLL_SR_MASK (0x1ff<<0)
#define DSPFW7 (dev_priv->info.display_mmio_offset + 0x7007c)
/* vlv/chv */
#define DSPFW4 (VLV_DISPLAY_BASE + 0x70070)
#define DSPFW_SPRITEB_WM1_SHIFT 16
#define DSPFW_SPRITEB_WM1_MASK (0xff<<16)
#define DSPFW_CURSORA_WM1_SHIFT 8
#define DSPFW_CURSORA_WM1_MASK (0x3f<<8)
#define DSPFW_SPRITEA_WM1_SHIFT 0
#define DSPFW_SPRITEA_WM1_MASK (0xff<<0)
#define DSPFW5 (VLV_DISPLAY_BASE + 0x70074)
#define DSPFW_PLANEB_WM1_SHIFT 24
#define DSPFW_PLANEB_WM1_MASK (0xff<<24)
#define DSPFW_PLANEA_WM1_SHIFT 16
#define DSPFW_PLANEA_WM1_MASK (0xff<<16)
#define DSPFW_CURSORB_WM1_SHIFT 8
#define DSPFW_CURSORB_WM1_MASK (0x3f<<8)
#define DSPFW_CURSOR_SR_WM1_SHIFT 0
#define DSPFW_CURSOR_SR_WM1_MASK (0x3f<<0)
#define DSPFW6 (VLV_DISPLAY_BASE + 0x70078)
#define DSPFW_SR_WM1_SHIFT 0
#define DSPFW_SR_WM1_MASK (0x1ff<<0)
#define DSPFW7 (VLV_DISPLAY_BASE + 0x7007c)
#define DSPFW7_CHV (VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */
#define DSPFW_SPRITED_WM1_SHIFT 24
#define DSPFW_SPRITED_WM1_MASK (0xff<<24)
#define DSPFW_SPRITED_SHIFT 16
#define DSPFW_SPRITED_MASK (0xff<<16)
#define DSPFW_SPRITEC_WM1_SHIFT 8
#define DSPFW_SPRITEC_WM1_MASK (0xff<<8)
#define DSPFW_SPRITEC_SHIFT 0
#define DSPFW_SPRITEC_MASK (0xff<<0)
#define DSPFW8_CHV (VLV_DISPLAY_BASE + 0x700b8)
#define DSPFW_SPRITEF_WM1_SHIFT 24
#define DSPFW_SPRITEF_WM1_MASK (0xff<<24)
#define DSPFW_SPRITEF_SHIFT 16
#define DSPFW_SPRITEF_MASK (0xff<<16)
#define DSPFW_SPRITEE_WM1_SHIFT 8
#define DSPFW_SPRITEE_WM1_MASK (0xff<<8)
#define DSPFW_SPRITEE_SHIFT 0
#define DSPFW_SPRITEE_MASK (0xff<<0)
#define DSPFW9_CHV (VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */
#define DSPFW_PLANEC_WM1_SHIFT 24
#define DSPFW_PLANEC_WM1_MASK (0xff<<24)
#define DSPFW_PLANEC_SHIFT 16
#define DSPFW_PLANEC_MASK (0xff<<16)
#define DSPFW_CURSORC_WM1_SHIFT 8
#define DSPFW_CURSORC_WM1_MASK (0x3f<<16)
#define DSPFW_CURSORC_SHIFT 0
#define DSPFW_CURSORC_MASK (0x3f<<0)
/* vlv/chv high order bits */
#define DSPHOWM (VLV_DISPLAY_BASE + 0x70064)
#define DSPFW_SR_HI_SHIFT 24
#define DSPFW_SR_HI_MASK (1<<24)
#define DSPFW_SPRITEF_HI_SHIFT 23
#define DSPFW_SPRITEF_HI_MASK (1<<23)
#define DSPFW_SPRITEE_HI_SHIFT 22
#define DSPFW_SPRITEE_HI_MASK (1<<22)
#define DSPFW_PLANEC_HI_SHIFT 21
#define DSPFW_PLANEC_HI_MASK (1<<21)
#define DSPFW_SPRITED_HI_SHIFT 20
#define DSPFW_SPRITED_HI_MASK (1<<20)
#define DSPFW_SPRITEC_HI_SHIFT 16
#define DSPFW_SPRITEC_HI_MASK (1<<16)
#define DSPFW_PLANEB_HI_SHIFT 12
#define DSPFW_PLANEB_HI_MASK (1<<12)
#define DSPFW_SPRITEB_HI_SHIFT 8
#define DSPFW_SPRITEB_HI_MASK (1<<8)
#define DSPFW_SPRITEA_HI_SHIFT 4
#define DSPFW_SPRITEA_HI_MASK (1<<4)
#define DSPFW_PLANEA_HI_SHIFT 0
#define DSPFW_PLANEA_HI_MASK (1<<0)
#define DSPHOWM1 (VLV_DISPLAY_BASE + 0x70068)
#define DSPFW_SR_WM1_HI_SHIFT 24
#define DSPFW_SR_WM1_HI_MASK (1<<24)
#define DSPFW_SPRITEF_WM1_HI_SHIFT 23
#define DSPFW_SPRITEF_WM1_HI_MASK (1<<23)
#define DSPFW_SPRITEE_WM1_HI_SHIFT 22
#define DSPFW_SPRITEE_WM1_HI_MASK (1<<22)
#define DSPFW_PLANEC_WM1_HI_SHIFT 21
#define DSPFW_PLANEC_WM1_HI_MASK (1<<21)
#define DSPFW_SPRITED_WM1_HI_SHIFT 20
#define DSPFW_SPRITED_WM1_HI_MASK (1<<20)
#define DSPFW_SPRITEC_WM1_HI_SHIFT 16
#define DSPFW_SPRITEC_WM1_HI_MASK (1<<16)
#define DSPFW_PLANEB_WM1_HI_SHIFT 12
#define DSPFW_PLANEB_WM1_HI_MASK (1<<12)
#define DSPFW_SPRITEB_WM1_HI_SHIFT 8
#define DSPFW_SPRITEB_WM1_HI_MASK (1<<8)
#define DSPFW_SPRITEA_WM1_HI_SHIFT 4
#define DSPFW_SPRITEA_WM1_HI_MASK (1<<4)
#define DSPFW_PLANEA_WM1_HI_SHIFT 0
#define DSPFW_PLANEA_WM1_HI_MASK (1<<0)
/* drain latency register values*/ /* drain latency register values*/
#define DRAIN_LATENCY_PRECISION_32 32 #define DRAIN_LATENCY_PRECISION_32 32
#define DRAIN_LATENCY_PRECISION_64 64 #define DRAIN_LATENCY_PRECISION_64 64
#define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050) #define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
#define DDL_CURSORA_PRECISION_64 (1<<31) #define DDL_CURSOR_PRECISION_64 (1<<31)
#define DDL_CURSORA_PRECISION_32 (0<<31) #define DDL_CURSOR_PRECISION_32 (0<<31)
#define DDL_CURSORA_SHIFT 24 #define DDL_CURSOR_SHIFT 24
#define DDL_SPRITEB_PRECISION_64 (1<<23) #define DDL_SPRITE_PRECISION_64(sprite) (1<<(15+8*(sprite)))
#define DDL_SPRITEB_PRECISION_32 (0<<23) #define DDL_SPRITE_PRECISION_32(sprite) (0<<(15+8*(sprite)))
#define DDL_SPRITEB_SHIFT 16 #define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite))
#define DDL_SPRITEA_PRECISION_64 (1<<15) #define DDL_PLANE_PRECISION_64 (1<<7)
#define DDL_SPRITEA_PRECISION_32 (0<<15) #define DDL_PLANE_PRECISION_32 (0<<7)
#define DDL_SPRITEA_SHIFT 8 #define DDL_PLANE_SHIFT 0
#define DDL_PLANEA_PRECISION_64 (1<<7) #define DRAIN_LATENCY_MASK 0x7f
#define DDL_PLANEA_PRECISION_32 (0<<7)
#define DDL_PLANEA_SHIFT 0
#define VLV_DDL2 (VLV_DISPLAY_BASE + 0x70054)
#define DDL_CURSORB_PRECISION_64 (1<<31)
#define DDL_CURSORB_PRECISION_32 (0<<31)
#define DDL_CURSORB_SHIFT 24
#define DDL_SPRITED_PRECISION_64 (1<<23)
#define DDL_SPRITED_PRECISION_32 (0<<23)
#define DDL_SPRITED_SHIFT 16
#define DDL_SPRITEC_PRECISION_64 (1<<15)
#define DDL_SPRITEC_PRECISION_32 (0<<15)
#define DDL_SPRITEC_SHIFT 8
#define DDL_PLANEB_PRECISION_64 (1<<7)
#define DDL_PLANEB_PRECISION_32 (0<<7)
#define DDL_PLANEB_SHIFT 0
#define VLV_DDL3 (VLV_DISPLAY_BASE + 0x70058)
#define DDL_CURSORC_PRECISION_64 (1<<31)
#define DDL_CURSORC_PRECISION_32 (0<<31)
#define DDL_CURSORC_SHIFT 24
#define DDL_SPRITEF_PRECISION_64 (1<<23)
#define DDL_SPRITEF_PRECISION_32 (0<<23)
#define DDL_SPRITEF_SHIFT 16
#define DDL_SPRITEE_PRECISION_64 (1<<15)
#define DDL_SPRITEE_PRECISION_32 (0<<15)
#define DDL_SPRITEE_SHIFT 8
#define DDL_PLANEC_PRECISION_64 (1<<7)
#define DDL_PLANEC_PRECISION_32 (0<<7)
#define DDL_PLANEC_SHIFT 0
/* FIFO watermark sizes etc */ /* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64 #define G4X_FIFO_LINE_SIZE 64
...@@ -4191,6 +4293,7 @@ enum punit_power_well { ...@@ -4191,6 +4293,7 @@ enum punit_power_well {
#define DVS_YUV_ORDER_UYVY (1<<16) #define DVS_YUV_ORDER_UYVY (1<<16)
#define DVS_YUV_ORDER_YVYU (2<<16) #define DVS_YUV_ORDER_YVYU (2<<16)
#define DVS_YUV_ORDER_VYUY (3<<16) #define DVS_YUV_ORDER_VYUY (3<<16)
#define DVS_ROTATE_180 (1<<15)
#define DVS_DEST_KEY (1<<2) #define DVS_DEST_KEY (1<<2)
#define DVS_TRICKLE_FEED_DISABLE (1<<14) #define DVS_TRICKLE_FEED_DISABLE (1<<14)
#define DVS_TILED (1<<10) #define DVS_TILED (1<<10)
...@@ -4261,6 +4364,7 @@ enum punit_power_well { ...@@ -4261,6 +4364,7 @@ enum punit_power_well {
#define SPRITE_YUV_ORDER_UYVY (1<<16) #define SPRITE_YUV_ORDER_UYVY (1<<16)
#define SPRITE_YUV_ORDER_YVYU (2<<16) #define SPRITE_YUV_ORDER_YVYU (2<<16)
#define SPRITE_YUV_ORDER_VYUY (3<<16) #define SPRITE_YUV_ORDER_VYUY (3<<16)
#define SPRITE_ROTATE_180 (1<<15)
#define SPRITE_TRICKLE_FEED_DISABLE (1<<14) #define SPRITE_TRICKLE_FEED_DISABLE (1<<14)
#define SPRITE_INT_GAMMA_ENABLE (1<<13) #define SPRITE_INT_GAMMA_ENABLE (1<<13)
#define SPRITE_TILED (1<<10) #define SPRITE_TILED (1<<10)
...@@ -4334,6 +4438,7 @@ enum punit_power_well { ...@@ -4334,6 +4438,7 @@ enum punit_power_well {
#define SP_YUV_ORDER_UYVY (1<<16) #define SP_YUV_ORDER_UYVY (1<<16)
#define SP_YUV_ORDER_YVYU (2<<16) #define SP_YUV_ORDER_YVYU (2<<16)
#define SP_YUV_ORDER_VYUY (3<<16) #define SP_YUV_ORDER_VYUY (3<<16)
#define SP_ROTATE_180 (1<<15)
#define SP_TILED (1<<10) #define SP_TILED (1<<10)
#define _SPALINOFF (VLV_DISPLAY_BASE + 0x72184) #define _SPALINOFF (VLV_DISPLAY_BASE + 0x72184)
#define _SPASTRIDE (VLV_DISPLAY_BASE + 0x72188) #define _SPASTRIDE (VLV_DISPLAY_BASE + 0x72188)
...@@ -5403,7 +5508,6 @@ enum punit_power_well { ...@@ -5403,7 +5508,6 @@ enum punit_power_well {
#define VLV_GTLC_ALLOWWAKEERR (1 << 1) #define VLV_GTLC_ALLOWWAKEERR (1 << 1)
#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5) #define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7) #define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
#define VLV_GTLC_SURVIVABILITY_REG 0x130098
#define FORCEWAKE_MT 0xa188 /* multi-threaded */ #define FORCEWAKE_MT 0xa188 /* multi-threaded */
#define FORCEWAKE_KERNEL 0x1 #define FORCEWAKE_KERNEL 0x1
#define FORCEWAKE_USER 0x2 #define FORCEWAKE_USER 0x2
......
...@@ -976,13 +976,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, ...@@ -976,13 +976,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
if (bdb->version >= 158) { if (bdb->version >= 158) {
/* The VBT HDMI level shift values match the table we have. */ /* The VBT HDMI level shift values match the table we have. */
hdmi_level_shift = child->raw[7] & 0xF; hdmi_level_shift = child->raw[7] & 0xF;
if (hdmi_level_shift < 0xC) {
DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
port_name(port), port_name(port),
hdmi_level_shift); hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift; info->hdmi_level_shift = hdmi_level_shift;
} }
}
} }
static void parse_ddi_ports(struct drm_i915_private *dev_priv, static void parse_ddi_ports(struct drm_i915_private *dev_priv,
...@@ -1114,8 +1112,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) ...@@ -1114,8 +1112,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
struct ddi_vbt_port_info *info = struct ddi_vbt_port_info *info =
&dev_priv->vbt.ddi_port_info[port]; &dev_priv->vbt.ddi_port_info[port];
/* Recommended BSpec default: 800mV 0dB. */ info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN;
info->hdmi_level_shift = 6;
info->supports_dvi = (port != PORT_A && port != PORT_E); info->supports_dvi = (port != PORT_A && port != PORT_E);
info->supports_hdmi = info->supports_dvi; info->supports_hdmi = info->supports_dvi;
......
...@@ -802,7 +802,8 @@ struct mipi_config { ...@@ -802,7 +802,8 @@ struct mipi_config {
u16 rsvd4; u16 rsvd4;
u8 rsvd5[5]; u8 rsvd5;
u32 target_burst_mode_freq;
u32 dsi_ddr_clk; u32 dsi_ddr_clk;
u32 bridge_ref_clk; u32 bridge_ref_clk;
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
* automatically adapt to HDMI connections as well * automatically adapt to HDMI connections as well
*/ */
static const u32 hsw_ddi_translations_dp[] = { static const u32 hsw_ddi_translations_dp[] = {
0x00FFFFFF, 0x0006000E, /* DP parameters */ 0x00FFFFFF, 0x0006000E,
0x00D75FFF, 0x0005000A, 0x00D75FFF, 0x0005000A,
0x00C30FFF, 0x00040006, 0x00C30FFF, 0x00040006,
0x80AAAFFF, 0x000B0000, 0x80AAAFFF, 0x000B0000,
...@@ -45,7 +45,7 @@ static const u32 hsw_ddi_translations_dp[] = { ...@@ -45,7 +45,7 @@ static const u32 hsw_ddi_translations_dp[] = {
}; };
static const u32 hsw_ddi_translations_fdi[] = { static const u32 hsw_ddi_translations_fdi[] = {
0x00FFFFFF, 0x0007000E, /* FDI parameters */ 0x00FFFFFF, 0x0007000E,
0x00D75FFF, 0x000F000A, 0x00D75FFF, 0x000F000A,
0x00C30FFF, 0x00060006, 0x00C30FFF, 0x00060006,
0x00AAAFFF, 0x001E0000, 0x00AAAFFF, 0x001E0000,
...@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = { ...@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
}; };
static const u32 bdw_ddi_translations_edp[] = { static const u32 bdw_ddi_translations_edp[] = {
0x00FFFFFF, 0x00000012, /* eDP parameters */ 0x00FFFFFF, 0x00000012,
0x00EBAFFF, 0x00020011, 0x00EBAFFF, 0x00020011,
0x00C71FFF, 0x0006000F, 0x00C71FFF, 0x0006000F,
0x00AAAFFF, 0x000E000A, 0x00AAAFFF, 0x000E000A,
...@@ -82,11 +82,10 @@ static const u32 bdw_ddi_translations_edp[] = { ...@@ -82,11 +82,10 @@ static const u32 bdw_ddi_translations_edp[] = {
0x00BEEFFF, 0x000A000C, 0x00BEEFFF, 0x000A000C,
0x00FFFFFF, 0x0005000F, 0x00FFFFFF, 0x0005000F,
0x00DB6FFF, 0x000A000C, 0x00DB6FFF, 0x000A000C,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
}; };
static const u32 bdw_ddi_translations_dp[] = { static const u32 bdw_ddi_translations_dp[] = {
0x00FFFFFF, 0x0007000E, /* DP parameters */ 0x00FFFFFF, 0x0007000E,
0x00D75FFF, 0x000E000A, 0x00D75FFF, 0x000E000A,
0x00BEFFFF, 0x00140006, 0x00BEFFFF, 0x00140006,
0x80B2CFFF, 0x001B0002, 0x80B2CFFF, 0x001B0002,
...@@ -95,11 +94,10 @@ static const u32 bdw_ddi_translations_dp[] = { ...@@ -95,11 +94,10 @@ static const u32 bdw_ddi_translations_dp[] = {
0x80CB2FFF, 0x001B0002, 0x80CB2FFF, 0x001B0002,
0x00F7DFFF, 0x00180004, 0x00F7DFFF, 0x00180004,
0x80D75FFF, 0x001B0002, 0x80D75FFF, 0x001B0002,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
}; };
static const u32 bdw_ddi_translations_fdi[] = { static const u32 bdw_ddi_translations_fdi[] = {
0x00FFFFFF, 0x0001000E, /* FDI parameters */ 0x00FFFFFF, 0x0001000E,
0x00D75FFF, 0x0004000A, 0x00D75FFF, 0x0004000A,
0x00C30FFF, 0x00070006, 0x00C30FFF, 0x00070006,
0x00AAAFFF, 0x000C0000, 0x00AAAFFF, 0x000C0000,
...@@ -108,7 +106,20 @@ static const u32 bdw_ddi_translations_fdi[] = { ...@@ -108,7 +106,20 @@ static const u32 bdw_ddi_translations_fdi[] = {
0x00C30FFF, 0x000C0000, 0x00C30FFF, 0x000C0000,
0x00FFFFFF, 0x00070006, 0x00FFFFFF, 0x00070006,
0x00D75FFF, 0x000C0000, 0x00D75FFF, 0x000C0000,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ };
static const u32 bdw_ddi_translations_hdmi[] = {
/* Idx NT mV diff T mV diff db */
0x00FFFFFF, 0x0007000E, /* 0: 400 400 0 */
0x00D75FFF, 0x000E000A, /* 1: 400 600 3.5 */
0x00BEFFFF, 0x00140006, /* 2: 400 800 6 */
0x00FFFFFF, 0x0009000D, /* 3: 450 450 0 */
0x00FFFFFF, 0x000E000A, /* 4: 600 600 0 */
0x00D7FFFF, 0x00140006, /* 5: 600 800 2.5 */
0x80CB2FFF, 0x001B0002, /* 6: 600 1000 4.5 */
0x00FFFFFF, 0x00140006, /* 7: 800 800 0 */
0x80E79FFF, 0x001B0002, /* 8: 800 1000 2 */
0x80FFFFFF, 0x001B0002, /* 9: 1000 1000 0 */
}; };
enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
...@@ -145,26 +156,36 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -145,26 +156,36 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg; u32 reg;
int i; int i, n_hdmi_entries, hdmi_800mV_0dB;
int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
const u32 *ddi_translations_fdi; const u32 *ddi_translations_fdi;
const u32 *ddi_translations_dp; const u32 *ddi_translations_dp;
const u32 *ddi_translations_edp; const u32 *ddi_translations_edp;
const u32 *ddi_translations_hdmi;
const u32 *ddi_translations; const u32 *ddi_translations;
if (IS_BROADWELL(dev)) { if (IS_BROADWELL(dev)) {
ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_fdi = bdw_ddi_translations_fdi;
ddi_translations_dp = bdw_ddi_translations_dp; ddi_translations_dp = bdw_ddi_translations_dp;
ddi_translations_edp = bdw_ddi_translations_edp; ddi_translations_edp = bdw_ddi_translations_edp;
ddi_translations_hdmi = bdw_ddi_translations_hdmi;
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_800mV_0dB = 7;
} else if (IS_HASWELL(dev)) { } else if (IS_HASWELL(dev)) {
ddi_translations_fdi = hsw_ddi_translations_fdi; ddi_translations_fdi = hsw_ddi_translations_fdi;
ddi_translations_dp = hsw_ddi_translations_dp; ddi_translations_dp = hsw_ddi_translations_dp;
ddi_translations_edp = hsw_ddi_translations_dp; ddi_translations_edp = hsw_ddi_translations_dp;
ddi_translations_hdmi = hsw_ddi_translations_hdmi;
n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi);
hdmi_800mV_0dB = 6;
} else { } else {
WARN(1, "ddi translation table missing\n"); WARN(1, "ddi translation table missing\n");
ddi_translations_edp = bdw_ddi_translations_dp; ddi_translations_edp = bdw_ddi_translations_dp;
ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_fdi = bdw_ddi_translations_fdi;
ddi_translations_dp = bdw_ddi_translations_dp; ddi_translations_dp = bdw_ddi_translations_dp;
ddi_translations_hdmi = bdw_ddi_translations_hdmi;
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_800mV_0dB = 7;
} }
switch (port) { switch (port) {
...@@ -193,9 +214,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -193,9 +214,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
I915_WRITE(reg, ddi_translations[i]); I915_WRITE(reg, ddi_translations[i]);
reg += 4; reg += 4;
} }
/* Choose a good default if VBT is badly populated */
if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN ||
hdmi_level >= n_hdmi_entries)
hdmi_level = hdmi_800mV_0dB;
/* Entry 9 is for HDMI: */ /* Entry 9 is for HDMI: */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]); I915_WRITE(reg, ddi_translations_hdmi[hdmi_level * 2 + i]);
reg += 4; reg += 4;
} }
} }
...@@ -587,7 +614,7 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, ...@@ -587,7 +614,7 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
return (refclk * n * 100) / (p * r); return (refclk * n * 100) / (p * r);
} }
void intel_ddi_clock_get(struct intel_encoder *encoder, static void hsw_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config) struct intel_crtc_config *pipe_config)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
...@@ -643,8 +670,14 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, ...@@ -643,8 +670,14 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock;
} }
void intel_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
hsw_ddi_clock_get(encoder, pipe_config);
}
static void static void
intel_ddi_calculate_wrpll(int clock /* in Hz */, hsw_ddi_calculate_wrpll(int clock /* in Hz */,
unsigned *r2_out, unsigned *n2_out, unsigned *p_out) unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
{ {
uint64_t freq2k; uint64_t freq2k;
...@@ -708,27 +741,17 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */, ...@@ -708,27 +741,17 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
*r2_out = best.r2; *r2_out = best.r2;
} }
/* static bool
* Tries to find a PLL for the CRTC. If it finds, it increases the refcount and hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
* stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to struct intel_encoder *intel_encoder,
* steal the selected PLL. You need to call intel_ddi_pll_enable to actually int clock)
* enable the PLL.
*/
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
{ {
struct drm_crtc *crtc = &intel_crtc->base; if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
int type = intel_encoder->type;
int clock = intel_crtc->config.port_clock;
intel_put_shared_dpll(intel_crtc);
if (type == INTEL_OUTPUT_HDMI) {
struct intel_shared_dpll *pll; struct intel_shared_dpll *pll;
uint32_t val; uint32_t val;
unsigned p, n2, r2; unsigned p, n2, r2;
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
...@@ -749,6 +772,25 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) ...@@ -749,6 +772,25 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
return true; return true;
} }
/*
* Tries to find a *shared* PLL for the CRTC and store it in
* intel_crtc->ddi_pll_sel.
*
* For private DPLLs, compute_config() should do the selection for us. This
* function should be folded into compute_config() eventually.
*/
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
int clock = intel_crtc->config.port_clock;
intel_put_shared_dpll(intel_crtc);
return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock);
}
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
{ {
struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct drm_i915_private *dev_priv = crtc->dev->dev_private;
...@@ -1183,31 +1225,52 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) ...@@ -1183,31 +1225,52 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
} }
} }
int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) static int bdw_get_cdclk_freq(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = dev_priv->dev;
uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK) { if (lcpll & LCPLL_CD_SOURCE_FCLK)
return 800000; return 800000;
} else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) { else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
return 450000; return 450000;
} else if (freq == LCPLL_CLK_FREQ_450) { else if (freq == LCPLL_CLK_FREQ_450)
return 450000; return 450000;
} else if (IS_HASWELL(dev)) { else if (freq == LCPLL_CLK_FREQ_54O_BDW)
if (IS_ULT(dev))
return 337500;
else
return 540000;
} else {
if (freq == LCPLL_CLK_FREQ_54O_BDW)
return 540000; return 540000;
else if (freq == LCPLL_CLK_FREQ_337_5_BDW) else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
return 337500; return 337500;
else else
return 675000; return 675000;
} }
static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
uint32_t lcpll = I915_READ(LCPLL_CTL);
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
if (lcpll & LCPLL_CD_SOURCE_FCLK)
return 800000;
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
return 450000;
else if (freq == LCPLL_CLK_FREQ_450)
return 450000;
else if (IS_ULT(dev))
return 337500;
else
return 540000;
}
int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
if (IS_BROADWELL(dev))
return bdw_get_cdclk_freq(dev_priv);
/* Haswell */
return hsw_get_cdclk_freq(dev_priv);
} }
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
...@@ -1248,10 +1311,8 @@ static const char * const hsw_ddi_pll_names[] = { ...@@ -1248,10 +1311,8 @@ static const char * const hsw_ddi_pll_names[] = {
"WRPLL 2", "WRPLL 2",
}; };
void intel_ddi_pll_init(struct drm_device *dev) static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
int i; int i;
dev_priv->num_shared_dpll = 2; dev_priv->num_shared_dpll = 2;
...@@ -1264,6 +1325,14 @@ void intel_ddi_pll_init(struct drm_device *dev) ...@@ -1264,6 +1325,14 @@ void intel_ddi_pll_init(struct drm_device *dev)
dev_priv->shared_dplls[i].get_hw_state = dev_priv->shared_dplls[i].get_hw_state =
hsw_ddi_pll_get_hw_state; hsw_ddi_pll_get_hw_state;
} }
}
void intel_ddi_pll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
hsw_shared_dplls_init(dev_priv);
/* The LCPLL register should be turned on by the BIOS. For now let's /* The LCPLL register should be turned on by the BIOS. For now let's
* just check its state and print errors in case something is wrong. * just check its state and print errors in case something is wrong.
...@@ -1444,7 +1513,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, ...@@ -1444,7 +1513,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
} }
intel_ddi_clock_get(encoder, pipe_config); hsw_ddi_clock_get(encoder, pipe_config);
} }
static void intel_ddi_destroy(struct drm_encoder *encoder) static void intel_ddi_destroy(struct drm_encoder *encoder)
......
...@@ -828,20 +828,6 @@ intel_dp_set_clock(struct intel_encoder *encoder, ...@@ -828,20 +828,6 @@ intel_dp_set_clock(struct intel_encoder *encoder,
} }
} }
static void
intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum transcoder transcoder = crtc->config.cpu_transcoder;
I915_WRITE(PIPE_DATA_M2(transcoder),
TU_SIZE(m_n->tu) | m_n->gmch_m);
I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
}
bool bool
intel_dp_compute_config(struct intel_encoder *encoder, intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config) struct intel_crtc_config *pipe_config)
...@@ -867,6 +853,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -867,6 +853,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
pipe_config->has_pch_encoder = true; pipe_config->has_pch_encoder = true;
pipe_config->has_dp_encoder = true; pipe_config->has_dp_encoder = true;
pipe_config->has_drrs = false;
pipe_config->has_audio = intel_dp->has_audio; pipe_config->has_audio = intel_dp->has_audio;
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
...@@ -970,13 +957,14 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -970,13 +957,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (intel_connector->panel.downclock_mode != NULL && if (intel_connector->panel.downclock_mode != NULL &&
intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
pipe_config->has_drrs = true;
intel_link_compute_m_n(bpp, lane_count, intel_link_compute_m_n(bpp, lane_count,
intel_connector->panel.downclock_mode->clock, intel_connector->panel.downclock_mode->clock,
pipe_config->port_clock, pipe_config->port_clock,
&pipe_config->dp_m2_n2); &pipe_config->dp_m2_n2);
} }
if (HAS_DDI(dev)) if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
else else
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
...@@ -2293,6 +2281,8 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) ...@@ -2293,6 +2281,8 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
u32 val; u32 val;
intel_dp_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */ /* program left/right clock distribution */
...@@ -2659,8 +2649,8 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp) ...@@ -2659,8 +2649,8 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)
/* Program swing margin */ /* Program swing margin */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK; val &= ~DPIO_SWING_MARGIN000_MASK;
val |= margin_reg_value << DPIO_SWING_MARGIN_SHIFT; val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
} }
...@@ -2971,6 +2961,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2971,6 +2961,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
} }
} else { } else {
if (IS_CHERRYVIEW(dev))
*DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
*DP &= ~DP_LINK_TRAIN_MASK; *DP &= ~DP_LINK_TRAIN_MASK;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
...@@ -2984,8 +2977,12 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2984,8 +2977,12 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
*DP |= DP_LINK_TRAIN_PAT_2; *DP |= DP_LINK_TRAIN_PAT_2;
break; break;
case DP_TRAINING_PATTERN_3: case DP_TRAINING_PATTERN_3:
if (IS_CHERRYVIEW(dev)) {
*DP |= DP_LINK_TRAIN_PAT_3_CHV;
} else {
DRM_ERROR("DP training pattern 3 not supported\n"); DRM_ERROR("DP training pattern 3 not supported\n");
*DP |= DP_LINK_TRAIN_PAT_2; *DP |= DP_LINK_TRAIN_PAT_2;
}
break; break;
} }
} }
...@@ -3272,6 +3269,9 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -3272,6 +3269,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else { } else {
if (IS_CHERRYVIEW(dev))
DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
} }
...@@ -4415,7 +4415,7 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) ...@@ -4415,7 +4415,7 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
val = I915_READ(reg); val = I915_READ(reg);
if (index > DRRS_HIGH_RR) { if (index > DRRS_HIGH_RR) {
val |= PIPECONF_EDP_RR_MODE_SWITCH; val |= PIPECONF_EDP_RR_MODE_SWITCH;
intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); intel_dp_set_m_n(intel_crtc);
} else { } else {
val &= ~PIPECONF_EDP_RR_MODE_SWITCH; val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
} }
...@@ -4455,7 +4455,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4455,7 +4455,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
} }
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
DRM_INFO("VBT doesn't support DRRS\n"); DRM_DEBUG_KMS("VBT doesn't support DRRS\n");
return NULL; return NULL;
} }
...@@ -4463,7 +4463,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4463,7 +4463,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
(dev, fixed_mode, connector); (dev, fixed_mode, connector);
if (!downclock_mode) { if (!downclock_mode) {
DRM_INFO("DRRS not supported\n"); DRM_DEBUG_KMS("DRRS not supported\n");
return NULL; return NULL;
} }
...@@ -4474,7 +4474,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4474,7 +4474,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n"); DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n");
return downclock_mode; return downclock_mode;
} }
......
...@@ -330,6 +330,7 @@ struct intel_crtc_config { ...@@ -330,6 +330,7 @@ struct intel_crtc_config {
/* m2_n2 for eDP downclock */ /* m2_n2 for eDP downclock */
struct intel_link_m_n dp_m2_n2; struct intel_link_m_n dp_m2_n2;
bool has_drrs;
/* /*
* Frequence the dpll for the port should run at. Differs from the * Frequence the dpll for the port should run at. Differs from the
...@@ -430,8 +431,6 @@ struct intel_crtc { ...@@ -430,8 +431,6 @@ struct intel_crtc {
struct intel_pipe_wm active; struct intel_pipe_wm active;
} wm; } wm;
wait_queue_head_t vbl_wait;
int scanline_offset; int scanline_offset;
struct intel_mmio_flip mmio_flip; struct intel_mmio_flip mmio_flip;
}; };
...@@ -455,6 +454,7 @@ struct intel_plane { ...@@ -455,6 +454,7 @@ struct intel_plane {
unsigned int crtc_w, crtc_h; unsigned int crtc_w, crtc_h;
uint32_t src_x, src_y; uint32_t src_x, src_y;
uint32_t src_w, src_h; uint32_t src_w, src_h;
unsigned int rotation;
/* Since we need to change the watermarks before/after /* Since we need to change the watermarks before/after
* enabling/disabling the planes, we need to store the parameters here * enabling/disabling the planes, we need to store the parameters here
...@@ -882,6 +882,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv); ...@@ -882,6 +882,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv);
void hsw_disable_pc8(struct drm_i915_private *dev_priv); void hsw_disable_pc8(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc, void intel_dp_get_m_n(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config); struct intel_crtc_config *pipe_config);
void intel_dp_set_m_n(struct intel_crtc *crtc);
int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
void void
ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
...@@ -896,7 +897,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -896,7 +897,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_config *pipe_config); struct intel_crtc_config *pipe_config);
int intel_format_to_fourcc(int format); int intel_format_to_fourcc(int format);
void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc); void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
/* intel_dp.c */ /* intel_dp.c */
void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
...@@ -1091,7 +1092,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); ...@@ -1091,7 +1092,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
void intel_flush_primary_plane(struct drm_i915_private *dev_priv, void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
enum plane plane); enum plane plane);
void intel_plane_restore(struct drm_plane *plane); int intel_plane_restore(struct drm_plane *plane);
void intel_plane_disable(struct drm_plane *plane); void intel_plane_disable(struct drm_plane *plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data, int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
......
...@@ -423,9 +423,11 @@ static u16 txclkesc(u32 divider, unsigned int us) ...@@ -423,9 +423,11 @@ static u16 txclkesc(u32 divider, unsigned int us)
} }
/* return pixels in terms of txbyteclkhs */ /* return pixels in terms of txbyteclkhs */
static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count) static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
u16 burst_mode_ratio)
{ {
return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp, 8), lane_count); return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp * burst_mode_ratio,
8 * 100), lane_count);
} }
static void set_dsi_timings(struct drm_encoder *encoder, static void set_dsi_timings(struct drm_encoder *encoder,
...@@ -451,10 +453,12 @@ static void set_dsi_timings(struct drm_encoder *encoder, ...@@ -451,10 +453,12 @@ static void set_dsi_timings(struct drm_encoder *encoder,
vbp = mode->vtotal - mode->vsync_end; vbp = mode->vtotal - mode->vsync_end;
/* horizontal values are in terms of high speed byte clock */ /* horizontal values are in terms of high speed byte clock */
hactive = txbyteclkhs(hactive, bpp, lane_count); hactive = txbyteclkhs(hactive, bpp, lane_count,
hfp = txbyteclkhs(hfp, bpp, lane_count); intel_dsi->burst_mode_ratio);
hsync = txbyteclkhs(hsync, bpp, lane_count); hfp = txbyteclkhs(hfp, bpp, lane_count, intel_dsi->burst_mode_ratio);
hbp = txbyteclkhs(hbp, bpp, lane_count); hsync = txbyteclkhs(hsync, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio);
I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive);
I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); I915_WRITE(MIPI_HFP_COUNT(pipe), hfp);
...@@ -541,12 +545,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) ...@@ -541,12 +545,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
intel_dsi->video_mode_format == VIDEO_MODE_BURST) { intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->htotal, bpp, txbyteclkhs(adjusted_mode->htotal, bpp,
intel_dsi->lane_count) + 1); intel_dsi->lane_count,
intel_dsi->burst_mode_ratio) + 1);
} else { } else {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->vtotal * txbyteclkhs(adjusted_mode->vtotal *
adjusted_mode->htotal, adjusted_mode->htotal,
bpp, intel_dsi->lane_count) + 1); bpp, intel_dsi->lane_count,
intel_dsi->burst_mode_ratio) + 1);
} }
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout); I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val); I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
......
...@@ -116,6 +116,8 @@ struct intel_dsi { ...@@ -116,6 +116,8 @@ struct intel_dsi {
u16 clk_hs_to_lp_count; u16 clk_hs_to_lp_count;
u16 init_count; u16 init_count;
u32 pclk;
u16 burst_mode_ratio;
/* all delays in ms */ /* all delays in ms */
u16 backlight_off_delay; u16 backlight_off_delay;
......
...@@ -271,6 +271,8 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -271,6 +271,8 @@ static bool generic_init(struct intel_dsi_device *dsi)
u32 ths_prepare_ns, tclk_trail_ns; u32 ths_prepare_ns, tclk_trail_ns;
u32 tclk_prepare_clkzero, ths_prepare_hszero; u32 tclk_prepare_clkzero, ths_prepare_hszero;
u32 lp_to_hs_switch, hs_to_lp_switch; u32 lp_to_hs_switch, hs_to_lp_switch;
u32 pclk, computed_ddr;
u16 burst_mode_ratio;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
...@@ -284,8 +286,6 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -284,8 +286,6 @@ static bool generic_init(struct intel_dsi_device *dsi)
else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565) else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565)
bits_per_pixel = 16; bits_per_pixel = 16;
bitrate = (mode->clock * bits_per_pixel) / intel_dsi->lane_count;
intel_dsi->operation_mode = mipi_config->is_cmd_mode; intel_dsi->operation_mode = mipi_config->is_cmd_mode;
intel_dsi->video_mode_format = mipi_config->video_transfer_mode; intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel; intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
...@@ -297,6 +297,40 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -297,6 +297,40 @@ static bool generic_init(struct intel_dsi_device *dsi)
intel_dsi->video_frmt_cfg_bits = intel_dsi->video_frmt_cfg_bits =
mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0; mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
pclk = mode->clock;
/* Burst Mode Ratio
* Target ddr frequency from VBT / non burst ddr freq
* multiply by 100 to preserve remainder
*/
if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
if (mipi_config->target_burst_mode_freq) {
computed_ddr =
(pclk * bits_per_pixel) / intel_dsi->lane_count;
if (mipi_config->target_burst_mode_freq <
computed_ddr) {
DRM_ERROR("Burst mode freq is less than computed\n");
return false;
}
burst_mode_ratio = DIV_ROUND_UP(
mipi_config->target_burst_mode_freq * 100,
computed_ddr);
pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100);
} else {
DRM_ERROR("Burst mode target is not set\n");
return false;
}
} else
burst_mode_ratio = 100;
intel_dsi->burst_mode_ratio = burst_mode_ratio;
intel_dsi->pclk = pclk;
bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count;
switch (intel_dsi->escape_clk_div) { switch (intel_dsi->escape_clk_div) {
case 0: case 0:
tlpx_ns = 50; tlpx_ns = 50;
......
...@@ -134,8 +134,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode, ...@@ -134,8 +134,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
#else #else
/* Get DSI clock from pixel clock */ /* Get DSI clock from pixel clock */
static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode, static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
int pixel_format, int lane_count)
{ {
u32 dsi_clk_khz; u32 dsi_clk_khz;
u32 bpp; u32 bpp;
...@@ -156,7 +155,7 @@ static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode, ...@@ -156,7 +155,7 @@ static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
/* DSI data rate = pixel clock * bits per pixel / lane count /* DSI data rate = pixel clock * bits per pixel / lane count
pixel clock is converted from KHz to Hz */ pixel clock is converted from KHz to Hz */
dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count); dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count);
return dsi_clk_khz; return dsi_clk_khz;
} }
...@@ -228,14 +227,12 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) ...@@ -228,14 +227,12 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
static void vlv_configure_dsi_pll(struct intel_encoder *encoder) static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
int ret; int ret;
struct dsi_mnp dsi_mnp; struct dsi_mnp dsi_mnp;
u32 dsi_clk; u32 dsi_clk;
dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format, dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
intel_dsi->lane_count); intel_dsi->lane_count);
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp); ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
......
...@@ -885,7 +885,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc) ...@@ -885,7 +885,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
if (HAS_GMCH_DISPLAY(dev)) if (HAS_GMCH_DISPLAY(dev))
return false; return false;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { for_each_intel_encoder(dev, encoder) {
if (encoder->new_crtc != crtc) if (encoder->new_crtc != crtc)
continue; continue;
...@@ -1260,6 +1260,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) ...@@ -1260,6 +1260,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
u32 val; u32 val;
intel_hdmi_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */ /* program left/right clock distribution */
...@@ -1429,8 +1431,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) ...@@ -1429,8 +1431,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK; val &= ~DPIO_SWING_MARGIN000_MASK;
val |= 102 << DPIO_SWING_MARGIN_SHIFT; val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
} }
......
...@@ -823,8 +823,7 @@ bool intel_is_dual_link_lvds(struct drm_device *dev) ...@@ -823,8 +823,7 @@ bool intel_is_dual_link_lvds(struct drm_device *dev)
struct intel_encoder *encoder; struct intel_encoder *encoder;
struct intel_lvds_encoder *lvds_encoder; struct intel_lvds_encoder *lvds_encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, for_each_intel_encoder(dev, encoder) {
base.head) {
if (encoder->type == INTEL_OUTPUT_LVDS) { if (encoder->type == INTEL_OUTPUT_LVDS) {
lvds_encoder = to_lvds_encoder(&encoder->base); lvds_encoder = to_lvds_encoder(&encoder->base);
......
此差异已折叠。
...@@ -476,8 +476,8 @@ static bool stop_ring(struct intel_engine_cs *ring) ...@@ -476,8 +476,8 @@ static bool stop_ring(struct intel_engine_cs *ring)
if (!IS_GEN2(ring->dev)) { if (!IS_GEN2(ring->dev)) {
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
return false; return false;
} }
} }
......
...@@ -53,6 +53,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -53,6 +53,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
long timeout = msecs_to_jiffies_timeout(1); long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start; int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex)); WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
...@@ -81,7 +82,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -81,7 +82,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
* other CPUs can see the task state update by the time we * other CPUs can see the task state update by the time we
* read the scanline. * read the scanline.
*/ */
prepare_to_wait(&crtc->vbl_wait, &wait, TASK_UNINTERRUPTIBLE); prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
scanline = intel_get_crtc_scanline(crtc); scanline = intel_get_crtc_scanline(crtc);
if (scanline < min || scanline > max) if (scanline < min || scanline > max)
...@@ -100,7 +101,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -100,7 +101,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
local_irq_disable(); local_irq_disable();
} }
finish_wait(&crtc->vbl_wait, &wait); finish_wait(wq, &wait);
drm_vblank_put(dev, pipe); drm_vblank_put(dev, pipe);
...@@ -163,6 +164,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, ...@@ -163,6 +164,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
sprctl &= ~SP_PIXFORMAT_MASK; sprctl &= ~SP_PIXFORMAT_MASK;
sprctl &= ~SP_YUV_BYTE_ORDER_MASK; sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
sprctl &= ~SP_TILED; sprctl &= ~SP_TILED;
sprctl &= ~SP_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_YUYV: case DRM_FORMAT_YUYV:
...@@ -235,6 +237,14 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, ...@@ -235,6 +237,14 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
fb->pitches[0]); fb->pitches[0]);
linear_offset -= sprsurf_offset; linear_offset -= sprsurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SP_ROTATE_180;
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -364,6 +374,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -364,6 +374,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
sprctl &= ~SPRITE_RGB_ORDER_RGBX; sprctl &= ~SPRITE_RGB_ORDER_RGBX;
sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
sprctl &= ~SPRITE_TILED; sprctl &= ~SPRITE_TILED;
sprctl &= ~SPRITE_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
...@@ -426,6 +437,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -426,6 +437,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]); pixel_size, fb->pitches[0]);
linear_offset -= sprsurf_offset; linear_offset -= sprsurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
/* HSW and BDW does this automagically in hardware */
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] +
src_w * pixel_size;
}
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -571,6 +594,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -571,6 +594,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
dvscntr &= ~DVS_RGB_ORDER_XBGR; dvscntr &= ~DVS_RGB_ORDER_XBGR;
dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
dvscntr &= ~DVS_TILED; dvscntr &= ~DVS_TILED;
dvscntr &= ~DVS_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
...@@ -628,6 +652,14 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -628,6 +652,14 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]); pixel_size, fb->pitches[0]);
linear_offset -= dvssurf_offset; linear_offset -= dvssurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
dvscntr |= DVS_ROTATE_180;
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -895,6 +927,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -895,6 +927,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
max_scale = intel_plane->max_downscale << 16; max_scale = intel_plane->max_downscale << 16;
min_scale = intel_plane->can_scale ? 1 : (1 << 16); min_scale = intel_plane->can_scale ? 1 : (1 << 16);
drm_rect_rotate(&src, fb->width << 16, fb->height << 16,
intel_plane->rotation);
hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale); hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
BUG_ON(hscale < 0); BUG_ON(hscale < 0);
...@@ -933,6 +968,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -933,6 +968,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
drm_rect_width(&dst) * hscale - drm_rect_width(&src), drm_rect_width(&dst) * hscale - drm_rect_width(&src),
drm_rect_height(&dst) * vscale - drm_rect_height(&src)); drm_rect_height(&dst) * vscale - drm_rect_height(&src));
drm_rect_rotate_inv(&src, fb->width << 16, fb->height << 16,
intel_plane->rotation);
/* sanity check to make sure the src viewport wasn't enlarged */ /* sanity check to make sure the src viewport wasn't enlarged */
WARN_ON(src.x1 < (int) src_x || WARN_ON(src.x1 < (int) src_x ||
src.y1 < (int) src_y || src.y1 < (int) src_y ||
...@@ -1180,14 +1218,38 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, ...@@ -1180,14 +1218,38 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
return ret; return ret;
} }
void intel_plane_restore(struct drm_plane *plane) static int intel_plane_set_property(struct drm_plane *plane,
struct drm_property *prop,
uint64_t val)
{
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
uint64_t old_val;
int ret = -ENOENT;
if (prop == dev->mode_config.rotation_property) {
/* exactly one rotation angle please */
if (hweight32(val & 0xf) != 1)
return -EINVAL;
old_val = intel_plane->rotation;
intel_plane->rotation = val;
ret = intel_plane_restore(plane);
if (ret)
intel_plane->rotation = old_val;
}
return ret;
}
int intel_plane_restore(struct drm_plane *plane)
{ {
struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane *intel_plane = to_intel_plane(plane);
if (!plane->crtc || !plane->fb) if (!plane->crtc || !plane->fb)
return; return 0;
intel_update_plane(plane, plane->crtc, plane->fb, return intel_update_plane(plane, plane->crtc, plane->fb,
intel_plane->crtc_x, intel_plane->crtc_y, intel_plane->crtc_x, intel_plane->crtc_y,
intel_plane->crtc_w, intel_plane->crtc_h, intel_plane->crtc_w, intel_plane->crtc_h,
intel_plane->src_x, intel_plane->src_y, intel_plane->src_x, intel_plane->src_y,
...@@ -1206,6 +1268,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { ...@@ -1206,6 +1268,7 @@ static const struct drm_plane_funcs intel_plane_funcs = {
.update_plane = intel_update_plane, .update_plane = intel_update_plane,
.disable_plane = intel_disable_plane, .disable_plane = intel_disable_plane,
.destroy = intel_destroy_plane, .destroy = intel_destroy_plane,
.set_property = intel_plane_set_property,
}; };
static uint32_t ilk_plane_formats[] = { static uint32_t ilk_plane_formats[] = {
...@@ -1310,13 +1373,28 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ...@@ -1310,13 +1373,28 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
intel_plane->pipe = pipe; intel_plane->pipe = pipe;
intel_plane->plane = plane; intel_plane->plane = plane;
intel_plane->rotation = BIT(DRM_ROTATE_0);
possible_crtcs = (1 << pipe); possible_crtcs = (1 << pipe);
ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs, &intel_plane_funcs,
plane_formats, num_plane_formats, plane_formats, num_plane_formats,
false); false);
if (ret) if (ret) {
kfree(intel_plane); kfree(intel_plane);
goto out;
}
if (!dev->mode_config.rotation_property)
dev->mode_config.rotation_property =
drm_mode_create_rotation_property(dev,
BIT(DRM_ROTATE_0) |
BIT(DRM_ROTATE_180));
if (dev->mode_config.rotation_property)
drm_object_attach_property(&intel_plane->base.base,
dev->mode_config.rotation_property,
intel_plane->rotation);
out:
return ret; return ret;
} }
...@@ -1313,6 +1313,17 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, ...@@ -1313,6 +1313,17 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
/**
* drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
* @crtc: which CRTC's vblank waitqueue to retrieve
*
* This function returns a pointer to the vblank waitqueue for the CRTC.
* Drivers can use this to implement vblank waits using wait_event() & co.
*/
static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
{
return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;
}
/* Modesetting support */ /* Modesetting support */
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
......
...@@ -825,6 +825,7 @@ struct drm_mode_config { ...@@ -825,6 +825,7 @@ struct drm_mode_config {
struct drm_property *dpms_property; struct drm_property *dpms_property;
struct drm_property *path_property; struct drm_property *path_property;
struct drm_property *plane_type_property; struct drm_property *plane_type_property;
struct drm_property *rotation_property;
/* DVI-I properties */ /* DVI-I properties */
struct drm_property *dvi_i_subconnector_property; struct drm_property *dvi_i_subconnector_property;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册