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
  ...
This commit is contained in:
Dave Airlie 2014-08-26 09:04:32 +10:00
commit d5a0f2e7be
27 changed files with 1282 additions and 399 deletions

View file

@ -3400,6 +3400,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
<sect2>
<title>Vertical Blanking and Interrupt Handling Functions Reference</title>
!Edrivers/gpu/drm/drm_irq.c
!Iinclude/drm/drmP.h drm_crtc_vblank_waitqueue
</sect2>
</sect1>

View file

@ -291,10 +291,17 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
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)
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++) {
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
struct drm_crtc *crtc = mode_set->crtc;

View file

@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
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)
{
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,
*source = INTEL_PIPE_CRC_SOURCE_PIPE;
drm_modeset_lock_all(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (!encoder->base.crtc)
continue;
@ -3957,6 +3997,7 @@ static const struct i915_debugfs_files {
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
{"i915_spr_wm_latency", &i915_spr_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)

View 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_release(dev, file);
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)

View file

@ -53,7 +53,7 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20140725"
#define DRIVER_DATE "20140808"
enum pipe {
INVALID_PIPE = -1,
@ -171,6 +171,11 @@ enum hpd_pin {
#define for_each_intel_crtc(dev, intel_crtc) \
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) \
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
if ((intel_encoder)->base.crtc == (__crtc))
@ -197,10 +202,13 @@ enum intel_dpll_id {
#define I915_NUM_PLLS 2
struct intel_dpll_hw_state {
/* i9xx, pch plls */
uint32_t dpll;
uint32_t dpll_md;
uint32_t fp0;
uint32_t fp1;
/* hsw, bdw */
uint32_t wrpll;
};
@ -634,6 +642,8 @@ struct i915_fbc {
struct drm_mm_node compressed_fb;
struct drm_mm_node *compressed_llb;
bool false_color;
struct intel_fbc_work {
struct delayed_work work;
struct drm_crtc *crtc;
@ -1227,6 +1237,12 @@ enum modeset_restore {
};
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 supports_dvi:1;
@ -2049,8 +2065,8 @@ struct drm_i915_cmd_table {
#define HAS_HW_CONTEXTS(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 USES_PPGTT(dev) intel_enable_ppgtt(dev, false)
#define USES_FULL_PPGTT(dev) intel_enable_ppgtt(dev, true)
#define USES_PPGTT(dev) (i915.enable_ppgtt)
#define USES_FULL_PPGTT(dev) (i915.enable_ppgtt == 2)
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)

View file

@ -33,17 +33,6 @@
static void bdw_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)
{
if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))

View file

@ -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,
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);
void i915_check_and_clear_faults(struct drm_device *dev);

View file

@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{
assert_spin_locked(&dev_priv->irq_lock);
if (!intel_irqs_enabled(dev_priv))
if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
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)
static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
{
struct intel_crtc *crtc;
if (!drm_handle_vblank(dev, pipe))
return false;
crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
wake_up(&crtc->vbl_wait);
return true;
}
@ -3522,18 +3517,17 @@ static void cherryview_irq_preinstall(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_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder;
u32 hotplug_irqs, hotplug, enabled_irqs = 0;
if (HAS_PCH_IBX(dev)) {
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)
enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
} else {
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)
enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
}
@ -4444,7 +4438,6 @@ static int i965_irq_postinstall(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_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder;
u32 hotplug_en;
@ -4455,7 +4448,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
hotplug_en &= ~HOTPLUG_INT_EN_MASK;
/* Note HDMI and DP share hotplug bits */
/* 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)
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
/* Programming the CRT detection parameters tends

View file

@ -497,10 +497,26 @@
#define BUNIT_REG_BISOC 0x11
#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_MASK (0x3 << DSPFREQSTAT_SHIFT)
#define DSPFREQGUAR_SHIFT 14
#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 */
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_RX0 = 10,
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,
};
@ -834,8 +855,8 @@ enum punit_power_well {
#define _VLV_TX_DW2_CH0 0x8288
#define _VLV_TX_DW2_CH1 0x8488
#define DPIO_SWING_MARGIN_SHIFT 16
#define DPIO_SWING_MARGIN_MASK (0xff << DPIO_SWING_MARGIN_SHIFT)
#define DPIO_SWING_MARGIN000_SHIFT 16
#define DPIO_SWING_MARGIN000_MASK (0xff << DPIO_SWING_MARGIN000_SHIFT)
#define DPIO_UNIQ_TRANS_SCALE_SHIFT 8
#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
@ -843,12 +864,16 @@ enum punit_power_well {
#define _VLV_TX_DW3_CH1 0x848c
/* The following bit for CHV phy */
#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_DW4_CH0 0x8290
#define _VLV_TX_DW4_CH1 0x8490
#define DPIO_SWING_DEEMPH9P5_SHIFT 24
#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_TX3_DW4_CH0 0x690
@ -1515,6 +1540,7 @@ enum punit_power_well {
/* Framebuffer compression for Ironlake */
#define ILK_DPFC_CB_BASE 0x43200
#define ILK_DPFC_CONTROL 0x43208
#define FBC_CTL_FALSE_COLOR (1<<10)
/* The bit 28-8 is reserved */
#define DPFC_RESERVED (0x1FFFFF00)
#define ILK_DPFC_RECOMP_CTL 0x4320c
@ -1671,12 +1697,9 @@ enum punit_power_well {
#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf)
#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
#define PHY_COM_LANE_RESET_DEASSERT(phy, val) \
((phy == DPIO_PHY0) ? (val | 1) : (val | 2))
#define PHY_COM_LANE_RESET_ASSERT(phy, val) \
((phy == DPIO_PHY0) ? (val & ~1) : (val & ~2))
#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
#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
@ -3472,6 +3495,8 @@ enum punit_power_well {
#define DP_LINK_TRAIN_OFF (3 << 28)
#define DP_LINK_TRAIN_MASK (3 << 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 */
#define DP_LINK_TRAIN_PAT_1_CPT (0 << 8)
@ -3728,7 +3753,6 @@ enum punit_power_well {
#define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9)
#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
#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_LEGACY_BLC_EVENT_STATUS (1UL<<6)
#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
@ -3838,73 +3862,151 @@ enum punit_power_well {
#define DSPARB_BEND_SHIFT 9 /* on 855 */
#define DSPARB_AEND_SHIFT 0
/* pnv/gen4/g4x/vlv/chv */
#define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034)
#define DSPFW_SR_SHIFT 23
#define DSPFW_SR_MASK (0x1ff<<23)
#define DSPFW_CURSORB_SHIFT 16
#define DSPFW_CURSORB_MASK (0x3f<<16)
#define DSPFW_PLANEB_SHIFT 8
#define DSPFW_PLANEB_MASK (0x7f<<8)
#define DSPFW_PLANEA_MASK (0x7f)
#define DSPFW_SR_SHIFT 23
#define DSPFW_SR_MASK (0x1ff<<23)
#define DSPFW_CURSORB_SHIFT 16
#define DSPFW_CURSORB_MASK (0x3f<<16)
#define DSPFW_PLANEB_SHIFT 8
#define DSPFW_PLANEB_MASK (0x7f<<8)
#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 DSPFW_CURSORA_MASK 0x00003f00
#define DSPFW_CURSORA_SHIFT 8
#define DSPFW_PLANEC_MASK (0x7f)
#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_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 DSPFW_HPLL_SR_EN (1<<31)
#define DSPFW_CURSOR_SR_SHIFT 24
#define DSPFW_HPLL_SR_EN (1<<31)
#define PINEVIEW_SELF_REFRESH_EN (1<<30)
#define DSPFW_CURSOR_SR_SHIFT 24
#define DSPFW_CURSOR_SR_MASK (0x3f<<24)
#define DSPFW_HPLL_CURSOR_SHIFT 16
#define DSPFW_HPLL_CURSOR_MASK (0x3f<<16)
#define DSPFW_HPLL_SR_MASK (0x1ff)
#define DSPFW4 (dev_priv->info.display_mmio_offset + 0x70070)
#define DSPFW7 (dev_priv->info.display_mmio_offset + 0x7007c)
#define DSPFW_HPLL_SR_SHIFT 0
#define DSPFW_HPLL_SR_MASK (0x1ff<<0)
/* 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*/
#define DRAIN_LATENCY_PRECISION_32 32
#define DRAIN_LATENCY_PRECISION_64 64
#define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050)
#define DDL_CURSORA_PRECISION_64 (1<<31)
#define DDL_CURSORA_PRECISION_32 (0<<31)
#define DDL_CURSORA_SHIFT 24
#define DDL_SPRITEB_PRECISION_64 (1<<23)
#define DDL_SPRITEB_PRECISION_32 (0<<23)
#define DDL_SPRITEB_SHIFT 16
#define DDL_SPRITEA_PRECISION_64 (1<<15)
#define DDL_SPRITEA_PRECISION_32 (0<<15)
#define DDL_SPRITEA_SHIFT 8
#define DDL_PLANEA_PRECISION_64 (1<<7)
#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
#define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
#define DDL_CURSOR_PRECISION_64 (1<<31)
#define DDL_CURSOR_PRECISION_32 (0<<31)
#define DDL_CURSOR_SHIFT 24
#define DDL_SPRITE_PRECISION_64(sprite) (1<<(15+8*(sprite)))
#define DDL_SPRITE_PRECISION_32(sprite) (0<<(15+8*(sprite)))
#define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite))
#define DDL_PLANE_PRECISION_64 (1<<7)
#define DDL_PLANE_PRECISION_32 (0<<7)
#define DDL_PLANE_SHIFT 0
#define DRAIN_LATENCY_MASK 0x7f
/* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64
@ -4191,6 +4293,7 @@ enum punit_power_well {
#define DVS_YUV_ORDER_UYVY (1<<16)
#define DVS_YUV_ORDER_YVYU (2<<16)
#define DVS_YUV_ORDER_VYUY (3<<16)
#define DVS_ROTATE_180 (1<<15)
#define DVS_DEST_KEY (1<<2)
#define DVS_TRICKLE_FEED_DISABLE (1<<14)
#define DVS_TILED (1<<10)
@ -4261,6 +4364,7 @@ enum punit_power_well {
#define SPRITE_YUV_ORDER_UYVY (1<<16)
#define SPRITE_YUV_ORDER_YVYU (2<<16)
#define SPRITE_YUV_ORDER_VYUY (3<<16)
#define SPRITE_ROTATE_180 (1<<15)
#define SPRITE_TRICKLE_FEED_DISABLE (1<<14)
#define SPRITE_INT_GAMMA_ENABLE (1<<13)
#define SPRITE_TILED (1<<10)
@ -4334,6 +4438,7 @@ enum punit_power_well {
#define SP_YUV_ORDER_UYVY (1<<16)
#define SP_YUV_ORDER_YVYU (2<<16)
#define SP_YUV_ORDER_VYUY (3<<16)
#define SP_ROTATE_180 (1<<15)
#define SP_TILED (1<<10)
#define _SPALINOFF (VLV_DISPLAY_BASE + 0x72184)
#define _SPASTRIDE (VLV_DISPLAY_BASE + 0x72188)
@ -5403,7 +5508,6 @@ enum punit_power_well {
#define VLV_GTLC_ALLOWWAKEERR (1 << 1)
#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
#define VLV_GTLC_SURVIVABILITY_REG 0x130098
#define FORCEWAKE_MT 0xa188 /* multi-threaded */
#define FORCEWAKE_KERNEL 0x1
#define FORCEWAKE_USER 0x2

View file

@ -976,12 +976,10 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
if (bdb->version >= 158) {
/* The VBT HDMI level shift values match the table we have. */
hdmi_level_shift = child->raw[7] & 0xF;
if (hdmi_level_shift < 0xC) {
DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
port_name(port),
hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift;
}
DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
port_name(port),
hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift;
}
}
@ -1114,8 +1112,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
struct ddi_vbt_port_info *info =
&dev_priv->vbt.ddi_port_info[port];
/* Recommended BSpec default: 800mV 0dB. */
info->hdmi_level_shift = 6;
info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN;
info->supports_dvi = (port != PORT_A && port != PORT_E);
info->supports_hdmi = info->supports_dvi;

View file

@ -802,7 +802,8 @@ struct mipi_config {
u16 rsvd4;
u8 rsvd5[5];
u8 rsvd5;
u32 target_burst_mode_freq;
u32 dsi_ddr_clk;
u32 bridge_ref_clk;

View file

@ -33,7 +33,7 @@
* automatically adapt to HDMI connections as well
*/
static const u32 hsw_ddi_translations_dp[] = {
0x00FFFFFF, 0x0006000E, /* DP parameters */
0x00FFFFFF, 0x0006000E,
0x00D75FFF, 0x0005000A,
0x00C30FFF, 0x00040006,
0x80AAAFFF, 0x000B0000,
@ -45,7 +45,7 @@ static const u32 hsw_ddi_translations_dp[] = {
};
static const u32 hsw_ddi_translations_fdi[] = {
0x00FFFFFF, 0x0007000E, /* FDI parameters */
0x00FFFFFF, 0x0007000E,
0x00D75FFF, 0x000F000A,
0x00C30FFF, 0x00060006,
0x00AAAFFF, 0x001E0000,
@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
};
static const u32 bdw_ddi_translations_edp[] = {
0x00FFFFFF, 0x00000012, /* eDP parameters */
0x00FFFFFF, 0x00000012,
0x00EBAFFF, 0x00020011,
0x00C71FFF, 0x0006000F,
0x00AAAFFF, 0x000E000A,
@ -82,11 +82,10 @@ static const u32 bdw_ddi_translations_edp[] = {
0x00BEEFFF, 0x000A000C,
0x00FFFFFF, 0x0005000F,
0x00DB6FFF, 0x000A000C,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
};
static const u32 bdw_ddi_translations_dp[] = {
0x00FFFFFF, 0x0007000E, /* DP parameters */
0x00FFFFFF, 0x0007000E,
0x00D75FFF, 0x000E000A,
0x00BEFFFF, 0x00140006,
0x80B2CFFF, 0x001B0002,
@ -95,11 +94,10 @@ static const u32 bdw_ddi_translations_dp[] = {
0x80CB2FFF, 0x001B0002,
0x00F7DFFF, 0x00180004,
0x80D75FFF, 0x001B0002,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
};
static const u32 bdw_ddi_translations_fdi[] = {
0x00FFFFFF, 0x0001000E, /* FDI parameters */
0x00FFFFFF, 0x0001000E,
0x00D75FFF, 0x0004000A,
0x00C30FFF, 0x00070006,
0x00AAAFFF, 0x000C0000,
@ -108,7 +106,20 @@ static const u32 bdw_ddi_translations_fdi[] = {
0x00C30FFF, 0x000C0000,
0x00FFFFFF, 0x00070006,
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)
@ -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;
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;
const u32 *ddi_translations_fdi;
const u32 *ddi_translations_dp;
const u32 *ddi_translations_edp;
const u32 *ddi_translations_hdmi;
const u32 *ddi_translations;
if (IS_BROADWELL(dev)) {
ddi_translations_fdi = bdw_ddi_translations_fdi;
ddi_translations_dp = bdw_ddi_translations_dp;
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)) {
ddi_translations_fdi = hsw_ddi_translations_fdi;
ddi_translations_dp = 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 {
WARN(1, "ddi translation table missing\n");
ddi_translations_edp = bdw_ddi_translations_dp;
ddi_translations_fdi = bdw_ddi_translations_fdi;
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) {
@ -193,9 +214,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
I915_WRITE(reg, ddi_translations[i]);
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: */
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;
}
}
@ -587,8 +614,8 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
return (refclk * n * 100) / (p * r);
}
void intel_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
static void hsw_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
int link_clock = 0;
@ -643,9 +670,15 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
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
intel_ddi_calculate_wrpll(int clock /* in Hz */,
unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
hsw_ddi_calculate_wrpll(int clock /* in Hz */,
unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
{
uint64_t freq2k;
unsigned p, n2, r2;
@ -708,27 +741,17 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
*r2_out = best.r2;
}
/*
* Tries to find a PLL for the CRTC. If it finds, it increases the refcount and
* stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to
* steal the selected PLL. You need to call intel_ddi_pll_enable to actually
* enable the PLL.
*/
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
static bool
hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_encoder *intel_encoder,
int clock)
{
struct drm_crtc *crtc = &intel_crtc->base;
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) {
if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
struct intel_shared_dpll *pll;
uint32_t val;
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 |
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
@ -749,6 +772,25 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
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)
{
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@ -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)
{
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 (freq == LCPLL_CLK_FREQ_54O_BDW)
return 540000;
else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
return 337500;
else
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) {
if (lcpll & LCPLL_CD_SOURCE_FCLK)
return 800000;
} else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) {
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
return 450000;
} else if (freq == LCPLL_CLK_FREQ_450) {
else if (freq == LCPLL_CLK_FREQ_450)
return 450000;
} else if (IS_HASWELL(dev)) {
if (IS_ULT(dev))
return 337500;
else
return 540000;
} else {
if (freq == LCPLL_CLK_FREQ_54O_BDW)
return 540000;
else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
return 337500;
else
return 675000;
}
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,
@ -1248,10 +1311,8 @@ static const char * const hsw_ddi_pll_names[] = {
"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;
dev_priv->num_shared_dpll = 2;
@ -1264,6 +1325,14 @@ void intel_ddi_pll_init(struct drm_device *dev)
dev_priv->shared_dplls[i].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
* 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,
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)

View file

@ -91,15 +91,16 @@ static int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj);
static void intel_dp_set_m_n(struct intel_crtc *crtc);
static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n);
struct intel_link_m_n *m_n,
struct intel_link_m_n *m2_n2);
static void ironlake_set_pipeconf(struct drm_crtc *crtc);
static void haswell_set_pipeconf(struct drm_crtc *crtc);
static void intel_set_pipe_csc(struct drm_crtc *crtc);
static void vlv_prepare_pll(struct intel_crtc *crtc);
static void chv_prepare_pll(struct intel_crtc *crtc);
static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
{
@ -1513,34 +1514,6 @@ static void intel_init_dpio(struct drm_device *dev)
}
}
static void intel_reset_dpio(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_CHERRYVIEW(dev)) {
enum dpio_phy phy;
u32 val;
for (phy = DPIO_PHY0; phy < I915_NUM_PHYS_VLV; phy++) {
/* Poll for phypwrgood signal */
if (wait_for(I915_READ(DISPLAY_PHY_STATUS) &
PHY_POWERGOOD(phy), 1))
DRM_ERROR("Display PHY %d is not power up\n", phy);
/*
* Deassert common lane reset for PHY.
*
* This should only be done on init and resume from S3
* with both PLLs disabled, or we risk losing DPIO and
* PLL synchronization.
*/
val = I915_READ(DISPLAY_PHY_CONTROL);
I915_WRITE(DISPLAY_PHY_CONTROL,
PHY_COM_LANE_RESET_DEASSERT(phy, val));
}
}
}
static void vlv_enable_pll(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
@ -1712,7 +1685,7 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
assert_pipe_disabled(dev_priv, pipe);
/* Set PLL en = 0 */
val = DPLL_SSC_REF_CLOCK_CHV;
val = DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV;
if (pipe != PIPE_A)
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
I915_WRITE(DPLL(pipe), val);
@ -1806,7 +1779,7 @@ static void intel_enable_shared_dpll(struct intel_crtc *crtc)
if (WARN_ON(pll->refcount == 0))
return;
DRM_DEBUG_KMS("enable %s (active %d, on? %d)for crtc %d\n",
DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
pll->name, pll->active, pll->on,
crtc->base.base.id);
@ -3980,7 +3953,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config.has_pch_encoder) {
intel_cpu_transcoder_set_m_n(intel_crtc,
&intel_crtc->config.fdi_m_n);
&intel_crtc->config.fdi_m_n, NULL);
}
ironlake_set_pipeconf(crtc);
@ -4093,7 +4066,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config.has_pch_encoder) {
intel_cpu_transcoder_set_m_n(intel_crtc,
&intel_crtc->config.fdi_m_n);
&intel_crtc->config.fdi_m_n, NULL);
}
haswell_set_pipeconf(crtc);
@ -4529,12 +4502,57 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
vlv_update_cdclk(dev);
}
static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 val, cmd;
WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq);
switch (cdclk) {
case 400000:
cmd = 3;
break;
case 333333:
case 320000:
cmd = 2;
break;
case 266667:
cmd = 1;
break;
case 200000:
cmd = 0;
break;
default:
WARN_ON(1);
return;
}
mutex_lock(&dev_priv->rps.hw_lock);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
val &= ~DSPFREQGUAR_MASK_CHV;
val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
50)) {
DRM_ERROR("timed out waiting for CDclk change\n");
}
mutex_unlock(&dev_priv->rps.hw_lock);
vlv_update_cdclk(dev);
}
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
int max_pixclk)
{
int vco = valleyview_get_vco(dev_priv);
int freq_320 = (vco << 1) % 320000 != 0 ? 333333 : 320000;
/* FIXME: Punit isn't quite ready yet */
if (IS_CHERRYVIEW(dev_priv->dev))
return 400000;
/*
* Really only a few cases to deal with, as only 4 CDclks are supported:
* 200MHz
@ -4597,8 +4615,13 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
int max_pixclk = intel_mode_max_pixclk(dev_priv);
int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
if (req_cdclk != dev_priv->vlv_cdclk_freq)
valleyview_set_cdclk(dev, req_cdclk);
if (req_cdclk != dev_priv->vlv_cdclk_freq) {
if (IS_CHERRYVIEW(dev))
cherryview_set_cdclk(dev, req_cdclk);
else
valleyview_set_cdclk(dev, req_cdclk);
}
modeset_update_crtc_power_domains(dev);
}
@ -4620,8 +4643,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI);
if (!is_dsi && !IS_CHERRYVIEW(dev))
vlv_prepare_pll(intel_crtc);
if (!is_dsi) {
if (IS_CHERRYVIEW(dev))
chv_prepare_pll(intel_crtc);
else
vlv_prepare_pll(intel_crtc);
}
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
@ -5265,6 +5292,10 @@ static int valleyview_get_display_clock_speed(struct drm_device *dev)
u32 val;
int divider;
/* FIXME: Punit isn't quite ready yet */
if (IS_CHERRYVIEW(dev))
return 400000;
mutex_lock(&dev_priv->dpio_lock);
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
mutex_unlock(&dev_priv->dpio_lock);
@ -5509,7 +5540,8 @@ static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
}
static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n)
struct intel_link_m_n *m_n,
struct intel_link_m_n *m2_n2)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@ -5521,6 +5553,18 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
/* M2_N2 registers to be set only for gen < 8 (M2_N2 available
* for gen < 8) and if DRRS is supported (to make sure the
* registers are not unnecessarily accessed).
*/
if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
crtc->config.has_drrs) {
I915_WRITE(PIPE_DATA_M2(transcoder),
TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
I915_WRITE(PIPE_LINK_M2(transcoder), m2_n2->link_m);
I915_WRITE(PIPE_LINK_N2(transcoder), m2_n2->link_n);
}
} else {
I915_WRITE(PIPE_DATA_M_G4X(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
I915_WRITE(PIPE_DATA_N_G4X(pipe), m_n->gmch_n);
@ -5529,12 +5573,13 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
}
}
static void intel_dp_set_m_n(struct intel_crtc *crtc)
void intel_dp_set_m_n(struct intel_crtc *crtc)
{
if (crtc->config.has_pch_encoder)
intel_pch_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
else
intel_cpu_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
intel_cpu_transcoder_set_m_n(crtc, &crtc->config.dp_m_n,
&crtc->config.dp_m2_n2);
}
static void vlv_update_pll(struct intel_crtc *crtc)
@ -5651,6 +5696,18 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
}
static void chv_update_pll(struct intel_crtc *crtc)
{
crtc->config.dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
DPLL_VCO_ENABLE;
if (crtc->pipe != PIPE_A)
crtc->config.dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
crtc->config.dpll_hw_state.dpll_md =
(crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
}
static void chv_prepare_pll(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@ -5661,15 +5718,6 @@ static void chv_update_pll(struct intel_crtc *crtc)
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
int refclk;
crtc->config.dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
DPLL_VCO_ENABLE;
if (pipe != PIPE_A)
crtc->config.dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
crtc->config.dpll_hw_state.dpll_md =
(crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
bestn = crtc->config.dpll.n;
bestm2_frac = crtc->config.dpll.m2 & 0x3fffff;
bestm1 = crtc->config.dpll.m1;
@ -6225,7 +6273,7 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
val = I915_READ(DSPSTRIDE(pipe));
crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
crtc->base.primary->fb->pitches[0] = val & 0xffffffc0;
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
plane_config->tiled);
@ -6357,7 +6405,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
static void ironlake_init_pch_refclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *encoder;
u32 val, final;
bool has_lvds = false;
@ -6367,8 +6414,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
bool can_ssc = false;
/* We need to take the global config into account */
list_for_each_entry(encoder, &mode_config->encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
switch (encoder->type) {
case INTEL_OUTPUT_LVDS:
has_panel = true;
@ -6675,11 +6721,10 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
static void lpt_init_pch_refclk(struct drm_device *dev)
{
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *encoder;
bool has_vga = false;
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
for_each_intel_encoder(dev, encoder) {
switch (encoder->type) {
case INTEL_OUTPUT_ANALOG:
has_vga = true;
@ -7135,7 +7180,8 @@ static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
enum transcoder transcoder,
struct intel_link_m_n *m_n)
struct intel_link_m_n *m_n,
struct intel_link_m_n *m2_n2)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@ -7149,6 +7195,20 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder))
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
/* Read M2_N2 registers only for gen < 8 (M2_N2 available for
* gen < 8) and if DRRS is supported (to make sure the
* registers are not unnecessarily read).
*/
if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
crtc->config.has_drrs) {
m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
m2_n2->link_n = I915_READ(PIPE_LINK_N2(transcoder));
m2_n2->gmch_m = I915_READ(PIPE_DATA_M2(transcoder))
& ~TU_SIZE_MASK;
m2_n2->gmch_n = I915_READ(PIPE_DATA_N2(transcoder));
m2_n2->tu = ((I915_READ(PIPE_DATA_M2(transcoder))
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
}
} else {
m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe));
m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe));
@ -7167,14 +7227,15 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,
intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
else
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
&pipe_config->dp_m_n);
&pipe_config->dp_m_n,
&pipe_config->dp_m2_n2);
}
static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
&pipe_config->fdi_m_n);
&pipe_config->fdi_m_n, NULL);
}
static void ironlake_get_pfit_config(struct intel_crtc *crtc,
@ -7245,7 +7306,7 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1;
val = I915_READ(DSPSTRIDE(pipe));
crtc->base.primary->fb->pitches[0] = val & 0xffffff80;
crtc->base.primary->fb->pitches[0] = val & 0xffffffc0;
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
plane_config->tiled);
@ -7605,6 +7666,22 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
return 0;
}
static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
enum port port,
struct intel_crtc_config *pipe_config)
{
pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
switch (pipe_config->ddi_pll_sel) {
case PORT_CLK_SEL_WRPLL1:
pipe_config->shared_dpll = DPLL_ID_WRPLL1;
break;
case PORT_CLK_SEL_WRPLL2:
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
break;
}
}
static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
@ -7618,16 +7695,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
switch (pipe_config->ddi_pll_sel) {
case PORT_CLK_SEL_WRPLL1:
pipe_config->shared_dpll = DPLL_ID_WRPLL1;
break;
case PORT_CLK_SEL_WRPLL2:
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
break;
}
haswell_get_ddi_pll(dev_priv, port, pipe_config);
if (pipe_config->shared_dpll >= 0) {
pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
@ -9824,8 +9892,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
to_intel_encoder(connector->base.encoder);
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
encoder->new_crtc =
to_intel_crtc(encoder->base.crtc);
}
@ -9856,8 +9923,7 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
connector->base.encoder = &connector->new_encoder->base;
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
encoder->base.crtc = &encoder->new_crtc->base;
}
@ -9984,6 +10050,15 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n,
pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n,
pipe_config->dp_m_n.tu);
DRM_DEBUG_KMS("dp: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
pipe_config->has_dp_encoder,
pipe_config->dp_m2_n2.gmch_m,
pipe_config->dp_m2_n2.gmch_n,
pipe_config->dp_m2_n2.link_m,
pipe_config->dp_m2_n2.link_n,
pipe_config->dp_m2_n2.tu);
DRM_DEBUG_KMS("requested mode:\n");
drm_mode_debug_printmodeline(&pipe_config->requested_mode);
DRM_DEBUG_KMS("adjusted mode:\n");
@ -10018,8 +10093,7 @@ static bool check_single_encoder_cloning(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct intel_encoder *source_encoder;
list_for_each_entry(source_encoder,
&dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, source_encoder) {
if (source_encoder->new_crtc != crtc)
continue;
@ -10035,8 +10109,7 @@ static bool check_encoder_cloning(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev;
struct intel_encoder *encoder;
list_for_each_entry(encoder,
&dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->new_crtc != crtc)
continue;
@ -10120,8 +10193,7 @@ encoder_retry:
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
*/
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (&encoder->new_crtc->base != crtc)
continue;
@ -10199,8 +10271,7 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
1 << connector->new_encoder->new_crtc->pipe;
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->base.crtc == &encoder->new_crtc->base)
continue;
@ -10274,8 +10345,7 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
struct intel_crtc *intel_crtc;
struct drm_connector *connector;
list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, intel_encoder) {
if (!intel_encoder->base.crtc)
continue;
@ -10364,6 +10434,22 @@ intel_pipe_config_compare(struct drm_device *dev,
return false; \
}
/* This is required for BDW+ where there is only one set of registers for
* switching between high and low RR.
* This macro can be used whenever a comparison has to be made between one
* hw state and multiple sw state variables.
*/
#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
if ((current_config->name != pipe_config->name) && \
(current_config->alt_name != pipe_config->name)) { \
DRM_ERROR("mismatch in " #name " " \
"(expected %i or %i, found %i)\n", \
current_config->name, \
current_config->alt_name, \
pipe_config->name); \
return false; \
}
#define PIPE_CONF_CHECK_FLAGS(name, mask) \
if ((current_config->name ^ pipe_config->name) & (mask)) { \
DRM_ERROR("mismatch in " #name "(" #mask ") " \
@ -10396,11 +10482,28 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(fdi_m_n.tu);
PIPE_CONF_CHECK_I(has_dp_encoder);
PIPE_CONF_CHECK_I(dp_m_n.gmch_m);
PIPE_CONF_CHECK_I(dp_m_n.gmch_n);
PIPE_CONF_CHECK_I(dp_m_n.link_m);
PIPE_CONF_CHECK_I(dp_m_n.link_n);
PIPE_CONF_CHECK_I(dp_m_n.tu);
if (INTEL_INFO(dev)->gen < 8) {
PIPE_CONF_CHECK_I(dp_m_n.gmch_m);
PIPE_CONF_CHECK_I(dp_m_n.gmch_n);
PIPE_CONF_CHECK_I(dp_m_n.link_m);
PIPE_CONF_CHECK_I(dp_m_n.link_n);
PIPE_CONF_CHECK_I(dp_m_n.tu);
if (current_config->has_drrs) {
PIPE_CONF_CHECK_I(dp_m2_n2.gmch_m);
PIPE_CONF_CHECK_I(dp_m2_n2.gmch_n);
PIPE_CONF_CHECK_I(dp_m2_n2.link_m);
PIPE_CONF_CHECK_I(dp_m2_n2.link_n);
PIPE_CONF_CHECK_I(dp_m2_n2.tu);
}
} else {
PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_m, dp_m2_n2.gmch_m);
PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_n, dp_m2_n2.gmch_n);
PIPE_CONF_CHECK_I_ALT(dp_m_n.link_m, dp_m2_n2.link_m);
PIPE_CONF_CHECK_I_ALT(dp_m_n.link_n, dp_m2_n2.link_n);
PIPE_CONF_CHECK_I_ALT(dp_m_n.tu, dp_m2_n2.tu);
}
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay);
PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal);
@ -10486,6 +10589,7 @@ intel_pipe_config_compare(struct drm_device *dev,
#undef PIPE_CONF_CHECK_X
#undef PIPE_CONF_CHECK_I
#undef PIPE_CONF_CHECK_I_ALT
#undef PIPE_CONF_CHECK_FLAGS
#undef PIPE_CONF_CHECK_CLOCK_FUZZY
#undef PIPE_CONF_QUIRK
@ -10515,8 +10619,7 @@ check_encoder_state(struct drm_device *dev)
struct intel_encoder *encoder;
struct intel_connector *connector;
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
bool enabled = false;
bool active = false;
enum pipe pipe, tracked_pipe;
@ -10595,8 +10698,7 @@ check_crtc_state(struct drm_device *dev)
WARN(crtc->active && !crtc->base.enabled,
"active crtc, but not enabled in sw tracking\n");
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->base.crtc != &crtc->base)
continue;
enabled = true;
@ -10618,8 +10720,7 @@ check_crtc_state(struct drm_device *dev)
if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
active = crtc->active;
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
enum pipe pipe;
if (encoder->base.crtc != &crtc->base)
continue;
@ -10987,7 +11088,7 @@ static void intel_set_config_restore_state(struct drm_device *dev,
}
count = 0;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, encoder) {
encoder->new_crtc =
to_intel_crtc(config->save_encoder_crtcs[count++]);
}
@ -11146,8 +11247,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
}
/* Check for any encoders that needs to be disabled. */
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
int num_connectors = 0;
list_for_each_entry(connector,
&dev->mode_config.connector_list,
@ -11180,9 +11280,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
for_each_intel_crtc(dev, crtc) {
crtc->new_enabled = false;
list_for_each_entry(encoder,
&dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->new_crtc == crtc) {
crtc->new_enabled = true;
break;
@ -11219,7 +11317,7 @@ static void disable_crtc_nofb(struct intel_crtc *crtc)
connector->new_encoder = NULL;
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->new_crtc == crtc)
encoder->new_crtc = NULL;
}
@ -11790,8 +11888,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc->cursor_base = ~0;
intel_crtc->cursor_cntl = ~0;
init_waitqueue_head(&intel_crtc->vbl_wait);
BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
@ -11853,8 +11949,7 @@ static int intel_encoder_clones(struct intel_encoder *encoder)
int index_mask = 0;
int entry = 0;
list_for_each_entry(source_encoder,
&dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, source_encoder) {
if (encoders_cloneable(encoder, source_encoder))
index_mask |= (1 << entry);
@ -12043,7 +12138,7 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_edp_psr_init(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
for_each_intel_encoder(dev, encoder) {
encoder->base.possible_crtcs = encoder->crtc_mask;
encoder->base.possible_clones =
intel_encoder_clones(encoder);
@ -12537,8 +12632,6 @@ void intel_modeset_init_hw(struct drm_device *dev)
intel_init_clock_gating(dev);
intel_reset_dpio(dev);
intel_enable_gt_powersave(dev);
}
@ -12609,7 +12702,6 @@ void intel_modeset_init(struct drm_device *dev)
}
intel_init_dpio(dev);
intel_reset_dpio(dev);
intel_shared_dpll_init(dev);
@ -12938,8 +13030,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
pipe = 0;
if (encoder->get_hw_state(encoder, &pipe)) {
@ -13003,8 +13094,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
}
/* HW state is read out, now we need to sanitize this mess. */
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
intel_sanitize_encoder(encoder);
}
@ -13371,3 +13461,25 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
}
}
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
{
struct intel_crtc *crtc;
for_each_intel_crtc(dev, crtc) {
struct intel_unpin_work *work;
unsigned long irqflags;
spin_lock_irqsave(&dev->event_lock, irqflags);
work = crtc->unpin_work;
if (work && work->event &&
work->event->base.file_priv == file) {
kfree(work->event);
work->event = NULL;
}
spin_unlock_irqrestore(&dev->event_lock, irqflags);
}
}

View file

@ -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
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
@ -867,6 +853,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
pipe_config->has_pch_encoder = true;
pipe_config->has_dp_encoder = true;
pipe_config->has_drrs = false;
pipe_config->has_audio = intel_dp->has_audio;
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
@ -970,13 +957,14 @@ found:
if (intel_connector->panel.downclock_mode != NULL &&
intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
pipe_config->has_drrs = true;
intel_link_compute_m_n(bpp, lane_count,
intel_connector->panel.downclock_mode->clock,
pipe_config->port_clock,
&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);
else
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)
enum pipe pipe = intel_crtc->pipe;
u32 val;
intel_dp_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */
@ -2659,8 +2649,8 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)
/* Program swing margin */
for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK;
val |= margin_reg_value << DPIO_SWING_MARGIN_SHIFT;
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
}
@ -2971,7 +2961,10 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
}
} else {
*DP &= ~DP_LINK_TRAIN_MASK;
if (IS_CHERRYVIEW(dev))
*DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
*DP &= ~DP_LINK_TRAIN_MASK;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
case DP_TRAINING_PATTERN_DISABLE:
@ -2984,8 +2977,12 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
*DP |= DP_LINK_TRAIN_PAT_2;
break;
case DP_TRAINING_PATTERN_3:
DRM_ERROR("DP training pattern 3 not supported\n");
*DP |= DP_LINK_TRAIN_PAT_2;
if (IS_CHERRYVIEW(dev)) {
*DP |= DP_LINK_TRAIN_PAT_3_CHV;
} else {
DRM_ERROR("DP training pattern 3 not supported\n");
*DP |= DP_LINK_TRAIN_PAT_2;
}
break;
}
}
@ -3272,7 +3269,10 @@ intel_dp_link_down(struct intel_dp *intel_dp)
DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else {
DP &= ~DP_LINK_TRAIN_MASK;
if (IS_CHERRYVIEW(dev))
DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
DP &= ~DP_LINK_TRAIN_MASK;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
}
POSTING_READ(intel_dp->output_reg);
@ -4415,7 +4415,7 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
val = I915_READ(reg);
if (index > DRRS_HIGH_RR) {
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 {
val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
}
@ -4455,7 +4455,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
}
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;
}
@ -4463,7 +4463,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
(dev, fixed_mode, connector);
if (!downclock_mode) {
DRM_INFO("DRRS not supported\n");
DRM_DEBUG_KMS("DRRS not supported\n");
return NULL;
}
@ -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.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;
}

View file

@ -330,6 +330,7 @@ struct intel_crtc_config {
/* m2_n2 for eDP downclock */
struct intel_link_m_n dp_m2_n2;
bool has_drrs;
/*
* Frequence the dpll for the port should run at. Differs from the
@ -430,8 +431,6 @@ struct intel_crtc {
struct intel_pipe_wm active;
} wm;
wait_queue_head_t vbl_wait;
int scanline_offset;
struct intel_mmio_flip mmio_flip;
};
@ -455,6 +454,7 @@ struct intel_plane {
unsigned int crtc_w, crtc_h;
uint32_t src_x, src_y;
uint32_t src_w, src_h;
unsigned int rotation;
/* Since we need to change the watermarks before/after
* 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);
void hsw_disable_pc8(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc,
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);
void
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,
struct intel_crtc_config *pipe_config);
int intel_format_to_fourcc(int format);
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 */
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);
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
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);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);

View file

@ -184,7 +184,7 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
/* update the hw state for DPLL */
intel_crtc->config.dpll_hw_state.dpll = DPLL_INTEGRATED_CLOCK_VLV |
DPLL_REFA_CLK_ENABLE_VLV;
DPLL_REFA_CLK_ENABLE_VLV;
tmp = I915_READ(DSPCLK_GATE_D);
tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
@ -259,8 +259,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
temp = I915_READ(MIPI_CTRL(pipe));
temp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
I915_WRITE(MIPI_CTRL(pipe), temp |
intel_dsi->escape_clk_div <<
ESCAPE_CLOCK_DIVIDER_SHIFT);
intel_dsi->escape_clk_div <<
ESCAPE_CLOCK_DIVIDER_SHIFT);
I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP);
@ -297,7 +297,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
usleep_range(2000, 2500);
if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
== 0x00000), 30))
== 0x00000), 30))
DRM_ERROR("DSI LP not going Low\n");
val = I915_READ(MIPI_PORT_CTRL(pipe));
@ -423,9 +423,11 @@ static u16 txclkesc(u32 divider, unsigned int us)
}
/* 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,
@ -451,10 +453,12 @@ static void set_dsi_timings(struct drm_encoder *encoder,
vbp = mode->vtotal - mode->vsync_end;
/* horizontal values are in terms of high speed byte clock */
hactive = txbyteclkhs(hactive, bpp, lane_count);
hfp = txbyteclkhs(hfp, bpp, lane_count);
hsync = txbyteclkhs(hsync, bpp, lane_count);
hbp = txbyteclkhs(hbp, bpp, lane_count);
hactive = txbyteclkhs(hactive, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hfp = txbyteclkhs(hfp, bpp, lane_count, intel_dsi->burst_mode_ratio);
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_HFP_COUNT(pipe), hfp);
@ -541,12 +545,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->htotal, bpp,
intel_dsi->lane_count) + 1);
intel_dsi->lane_count,
intel_dsi->burst_mode_ratio) + 1);
} else {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->vtotal *
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_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
@ -576,7 +582,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
* XXX: write MIPI_STOP_STATE_STALL?
*/
I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
intel_dsi->hs_to_lp_count);
intel_dsi->hs_to_lp_count);
/* XXX: low power clock equivalence in terms of byte clock. the number
* of byte clocks occupied in one low power clock. based on txbyteclkhs
@ -601,10 +607,10 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
* 64 like 1366 x 768. Enable RANDOM resolution support for such
* panels by default */
I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
intel_dsi->video_frmt_cfg_bits |
intel_dsi->video_mode_format |
IP_TG_CONFIG |
RANDOM_DPI_DISPLAY_RESOLUTION);
intel_dsi->video_frmt_cfg_bits |
intel_dsi->video_mode_format |
IP_TG_CONFIG |
RANDOM_DPI_DISPLAY_RESOLUTION);
}
static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)

View file

@ -116,6 +116,8 @@ struct intel_dsi {
u16 clk_hs_to_lp_count;
u16 init_count;
u32 pclk;
u16 burst_mode_ratio;
/* all delays in ms */
u16 backlight_off_delay;

View file

@ -430,7 +430,7 @@ void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi)
u32 mask;
mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 100))
DRM_ERROR("DPI FIFOs are not empty\n");

View file

@ -271,6 +271,8 @@ static bool generic_init(struct intel_dsi_device *dsi)
u32 ths_prepare_ns, tclk_trail_ns;
u32 tclk_prepare_clkzero, ths_prepare_hszero;
u32 lp_to_hs_switch, hs_to_lp_switch;
u32 pclk, computed_ddr;
u16 burst_mode_ratio;
DRM_DEBUG_KMS("\n");
@ -284,8 +286,6 @@ static bool generic_init(struct intel_dsi_device *dsi)
else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565)
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->video_mode_format = mipi_config->video_transfer_mode;
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
@ -297,6 +297,40 @@ static bool generic_init(struct intel_dsi_device *dsi)
intel_dsi->video_frmt_cfg_bits =
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) {
case 0:
tlpx_ns = 50;

View file

@ -134,8 +134,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
#else
/* Get DSI clock from pixel clock */
static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
int pixel_format, int lane_count)
static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
{
u32 dsi_clk_khz;
u32 bpp;
@ -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
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;
}
@ -191,7 +190,7 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
for (m = 62; m <= 92; m++) {
for (p = 2; p <= 6; p++) {
/* Find the optimal m and p divisors
with minimal error +/- the required clock */
with minimal error +/- the required clock */
calc_dsi_clk = (m * ref_clk) / p;
if (calc_dsi_clk == target_dsi_clk) {
calc_m = m;
@ -228,15 +227,13 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
{
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);
int ret;
struct dsi_mnp dsi_mnp;
u32 dsi_clk;
dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
intel_dsi->lane_count);
dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
intel_dsi->lane_count);
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
if (ret) {
@ -318,8 +315,8 @@ static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
}
WARN(bpp != pipe_bpp,
"bpp match assertion failure (expected %d, current %d)\n",
bpp, pipe_bpp);
"bpp match assertion failure (expected %d, current %d)\n",
bpp, pipe_bpp);
}
u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)

View file

@ -885,7 +885,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
if (HAS_GMCH_DISPLAY(dev))
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)
continue;
@ -1260,6 +1260,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
enum pipe pipe = intel_crtc->pipe;
u32 val;
intel_hdmi_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */
@ -1429,8 +1431,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK;
val |= 102 << DPIO_SWING_MARGIN_SHIFT;
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
}

View file

@ -823,8 +823,7 @@ bool intel_is_dual_link_lvds(struct drm_device *dev)
struct intel_encoder *encoder;
struct intel_lvds_encoder *lvds_encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
for_each_intel_encoder(dev, encoder) {
if (encoder->type == INTEL_OUTPUT_LVDS) {
lvds_encoder = to_lvds_encoder(&encoder->base);

View file

@ -309,6 +309,9 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
if (dev_priv->fbc.false_color)
dpfc_ctl |= FBC_CTL_FALSE_COLOR;
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
if (IS_IVYBRIDGE(dev)) {
@ -1268,33 +1271,27 @@ static bool g4x_compute_srwm(struct drm_device *dev,
display, cursor);
}
static bool vlv_compute_drain_latency(struct drm_device *dev,
int plane,
int *plane_prec_mult,
int *plane_dl,
int *cursor_prec_mult,
int *cursor_dl)
static bool vlv_compute_drain_latency(struct drm_crtc *crtc,
int pixel_size,
int *prec_mult,
int *drain_latency)
{
struct drm_crtc *crtc;
int clock, pixel_size;
int entries;
int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
crtc = intel_get_crtc_for_plane(dev, plane);
if (!intel_crtc_active(crtc))
if (WARN(clock == 0, "Pixel clock is zero!\n"))
return false;
clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
if (WARN(pixel_size == 0, "Pixel size is zero!\n"))
return false;
entries = (clock / 1000) * pixel_size;
*plane_prec_mult = (entries > 128) ?
DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
*plane_dl = (64 * (*plane_prec_mult) * 4) / entries;
entries = DIV_ROUND_UP(clock, 1000) * pixel_size;
*prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 :
DRAIN_LATENCY_PRECISION_32;
*drain_latency = (64 * (*prec_mult) * 4) / entries;
entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */
*cursor_prec_mult = (entries > 128) ?
DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
*cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries;
if (*drain_latency > DRAIN_LATENCY_MASK)
*drain_latency = DRAIN_LATENCY_MASK;
return true;
}
@ -1307,39 +1304,48 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
* latency value.
*/
static void vlv_update_drain_latency(struct drm_device *dev)
static void vlv_update_drain_latency(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int planea_prec, planea_dl, planeb_prec, planeb_dl;
int cursora_prec, cursora_dl, cursorb_prec, cursorb_dl;
int plane_prec_mult, cursor_prec_mult; /* Precision multiplier is
either 16 or 32 */
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pixel_size;
int drain_latency;
enum pipe pipe = intel_crtc->pipe;
int plane_prec, prec_mult, plane_dl;
/* For plane A, Cursor A */
if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl,
&cursor_prec_mult, &cursora_dl)) {
cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64;
planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64;
plane_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_PLANE_PRECISION_64 |
DRAIN_LATENCY_MASK | DDL_CURSOR_PRECISION_64 |
(DRAIN_LATENCY_MASK << DDL_CURSOR_SHIFT));
I915_WRITE(VLV_DDL1, cursora_prec |
(cursora_dl << DDL_CURSORA_SHIFT) |
planea_prec | planea_dl);
if (!intel_crtc_active(crtc)) {
I915_WRITE(VLV_DDL(pipe), plane_dl);
return;
}
/* For plane B, Cursor B */
if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl,
&cursor_prec_mult, &cursorb_dl)) {
cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64;
planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64;
I915_WRITE(VLV_DDL2, cursorb_prec |
(cursorb_dl << DDL_CURSORB_SHIFT) |
planeb_prec | planeb_dl);
/* Primary plane Drain Latency */
pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
if (vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ?
DDL_PLANE_PRECISION_64 :
DDL_PLANE_PRECISION_32;
plane_dl |= plane_prec | drain_latency;
}
/* Cursor Drain Latency
* BPP is always 4 for cursor
*/
pixel_size = 4;
/* Program cursor DL only if it is enabled */
if (intel_crtc->cursor_base &&
vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ?
DDL_CURSOR_PRECISION_64 :
DDL_CURSOR_PRECISION_32;
plane_dl |= plane_prec | (drain_latency << DDL_CURSOR_SHIFT);
}
I915_WRITE(VLV_DDL(pipe), plane_dl);
}
#define single_plane_enabled(mask) is_power_of_2(mask)
@ -1355,7 +1361,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
unsigned int enabled = 0;
bool cxsr_enabled;
vlv_update_drain_latency(dev);
vlv_update_drain_latency(crtc);
if (g4x_compute_wm0(dev, PIPE_A,
&valleyview_wm_info, latency_ns,
@ -1387,7 +1393,8 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
plane_sr = cursor_sr = 0;
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, "
"B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
planea_wm, cursora_wm,
planeb_wm, cursorb_wm,
plane_sr, cursor_sr);
@ -1396,7 +1403,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
(plane_sr << DSPFW_SR_SHIFT) |
(cursorb_wm << DSPFW_CURSORB_SHIFT) |
(planeb_wm << DSPFW_PLANEB_SHIFT) |
planea_wm);
(planea_wm << DSPFW_PLANEA_SHIFT));
I915_WRITE(DSPFW2,
(I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) |
(cursora_wm << DSPFW_CURSORA_SHIFT));
@ -1408,6 +1415,116 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
intel_set_memory_cxsr(dev_priv, true);
}
static void cherryview_update_wm(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
static const int sr_latency_ns = 12000;
struct drm_i915_private *dev_priv = dev->dev_private;
int planea_wm, planeb_wm, planec_wm;
int cursora_wm, cursorb_wm, cursorc_wm;
int plane_sr, cursor_sr;
int ignore_plane_sr, ignore_cursor_sr;
unsigned int enabled = 0;
bool cxsr_enabled;
vlv_update_drain_latency(crtc);
if (g4x_compute_wm0(dev, PIPE_A,
&valleyview_wm_info, latency_ns,
&valleyview_cursor_wm_info, latency_ns,
&planea_wm, &cursora_wm))
enabled |= 1 << PIPE_A;
if (g4x_compute_wm0(dev, PIPE_B,
&valleyview_wm_info, latency_ns,
&valleyview_cursor_wm_info, latency_ns,
&planeb_wm, &cursorb_wm))
enabled |= 1 << PIPE_B;
if (g4x_compute_wm0(dev, PIPE_C,
&valleyview_wm_info, latency_ns,
&valleyview_cursor_wm_info, latency_ns,
&planec_wm, &cursorc_wm))
enabled |= 1 << PIPE_C;
if (single_plane_enabled(enabled) &&
g4x_compute_srwm(dev, ffs(enabled) - 1,
sr_latency_ns,
&valleyview_wm_info,
&valleyview_cursor_wm_info,
&plane_sr, &ignore_cursor_sr) &&
g4x_compute_srwm(dev, ffs(enabled) - 1,
2*sr_latency_ns,
&valleyview_wm_info,
&valleyview_cursor_wm_info,
&ignore_plane_sr, &cursor_sr)) {
cxsr_enabled = true;
} else {
cxsr_enabled = false;
intel_set_memory_cxsr(dev_priv, false);
plane_sr = cursor_sr = 0;
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, "
"B: plane=%d, cursor=%d, C: plane=%d, cursor=%d, "
"SR: plane=%d, cursor=%d\n",
planea_wm, cursora_wm,
planeb_wm, cursorb_wm,
planec_wm, cursorc_wm,
plane_sr, cursor_sr);
I915_WRITE(DSPFW1,
(plane_sr << DSPFW_SR_SHIFT) |
(cursorb_wm << DSPFW_CURSORB_SHIFT) |
(planeb_wm << DSPFW_PLANEB_SHIFT) |
(planea_wm << DSPFW_PLANEA_SHIFT));
I915_WRITE(DSPFW2,
(I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) |
(cursora_wm << DSPFW_CURSORA_SHIFT));
I915_WRITE(DSPFW3,
(I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) |
(cursor_sr << DSPFW_CURSOR_SR_SHIFT));
I915_WRITE(DSPFW9_CHV,
(I915_READ(DSPFW9_CHV) & ~(DSPFW_PLANEC_MASK |
DSPFW_CURSORC_MASK)) |
(planec_wm << DSPFW_PLANEC_SHIFT) |
(cursorc_wm << DSPFW_CURSORC_SHIFT));
if (cxsr_enabled)
intel_set_memory_cxsr(dev_priv, true);
}
static void valleyview_update_sprite_wm(struct drm_plane *plane,
struct drm_crtc *crtc,
uint32_t sprite_width,
uint32_t sprite_height,
int pixel_size,
bool enabled, bool scaled)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = to_intel_plane(plane)->pipe;
int sprite = to_intel_plane(plane)->plane;
int drain_latency;
int plane_prec;
int sprite_dl;
int prec_mult;
sprite_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_SPRITE_PRECISION_64(sprite) |
(DRAIN_LATENCY_MASK << DDL_SPRITE_SHIFT(sprite)));
if (enabled && vlv_compute_drain_latency(crtc, pixel_size, &prec_mult,
&drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ?
DDL_SPRITE_PRECISION_64(sprite) :
DDL_SPRITE_PRECISION_32(sprite);
sprite_dl |= plane_prec |
(drain_latency << DDL_SPRITE_SHIFT(sprite));
}
I915_WRITE(VLV_DDL(pipe), sprite_dl);
}
static void g4x_update_wm(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@ -1443,7 +1560,8 @@ static void g4x_update_wm(struct drm_crtc *crtc)
plane_sr = cursor_sr = 0;
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, "
"B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
planea_wm, cursora_wm,
planeb_wm, cursorb_wm,
plane_sr, cursor_sr);
@ -1452,7 +1570,7 @@ static void g4x_update_wm(struct drm_crtc *crtc)
(plane_sr << DSPFW_SR_SHIFT) |
(cursorb_wm << DSPFW_CURSORB_SHIFT) |
(planeb_wm << DSPFW_PLANEB_SHIFT) |
planea_wm);
(planea_wm << DSPFW_PLANEA_SHIFT));
I915_WRITE(DSPFW2,
(I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) |
(cursora_wm << DSPFW_CURSORA_SHIFT));
@ -1526,8 +1644,11 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
/* 965 has limitations... */
I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) |
(8 << 16) | (8 << 8) | (8 << 0));
I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
(8 << DSPFW_CURSORB_SHIFT) |
(8 << DSPFW_PLANEB_SHIFT) |
(8 << DSPFW_PLANEA_SHIFT));
I915_WRITE(DSPFW2, (8 << DSPFW_CURSORA_SHIFT) |
(8 << DSPFW_PLANEC_SHIFT_OLD));
/* update cursor SR watermark */
I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
@ -6252,6 +6373,153 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
vlv_set_power_well(dev_priv, power_well, false);
}
static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum dpio_phy phy;
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
/*
* Enable the CRI clock source so we can get at the
* display and the reference clock for VGA
* hotplug / manual detection.
*/
if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
phy = DPIO_PHY0;
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
DPLL_REFA_CLK_ENABLE_VLV);
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
} else {
phy = DPIO_PHY1;
I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
}
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
vlv_set_power_well(dev_priv, power_well, true);
/* Poll for phypwrgood signal */
if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
DRM_ERROR("Display PHY %d is not power up\n", phy);
I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) |
PHY_COM_LANE_RESET_DEASSERT(phy));
}
static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum dpio_phy phy;
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
phy = DPIO_PHY0;
assert_pll_disabled(dev_priv, PIPE_A);
assert_pll_disabled(dev_priv, PIPE_B);
} else {
phy = DPIO_PHY1;
assert_pll_disabled(dev_priv, PIPE_C);
}
I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) &
~PHY_COM_LANE_RESET_DEASSERT(phy));
vlv_set_power_well(dev_priv, power_well, false);
}
static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum pipe pipe = power_well->data;
bool enabled;
u32 state, ctrl;
mutex_lock(&dev_priv->rps.hw_lock);
state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe);
/*
* We only ever set the power-on and power-gate states, anything
* else is unexpected.
*/
WARN_ON(state != DP_SSS_PWR_ON(pipe) && state != DP_SSS_PWR_GATE(pipe));
enabled = state == DP_SSS_PWR_ON(pipe);
/*
* A transient state at this point would mean some unexpected party
* is poking at the power controls too.
*/
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe);
WARN_ON(ctrl << 16 != state);
mutex_unlock(&dev_priv->rps.hw_lock);
return enabled;
}
static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well,
bool enable)
{
enum pipe pipe = power_well->data;
u32 state;
u32 ctrl;
state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
mutex_lock(&dev_priv->rps.hw_lock);
#define COND \
((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == state)
if (COND)
goto out;
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
ctrl &= ~DP_SSC_MASK(pipe);
ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, ctrl);
if (wait_for(COND, 100))
DRM_ERROR("timout setting power well state %08x (%08x)\n",
state,
vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ));
#undef COND
out:
mutex_unlock(&dev_priv->rps.hw_lock);
}
static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0);
}
static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
WARN_ON_ONCE(power_well->data != PIPE_A &&
power_well->data != PIPE_B &&
power_well->data != PIPE_C);
chv_set_pipe_power_well(dev_priv, power_well, true);
}
static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
WARN_ON_ONCE(power_well->data != PIPE_A &&
power_well->data != PIPE_B &&
power_well->data != PIPE_C);
chv_set_pipe_power_well(dev_priv, power_well, false);
}
static void check_power_well_state(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
@ -6443,6 +6711,39 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_PIPE_A_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PIPE_A) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_PIPE_B_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PIPE_B) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_PIPE_C_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PIPE_C) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_D_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.sync_hw = i9xx_always_on_power_well_noop,
.enable = i9xx_always_on_power_well_noop,
@ -6450,6 +6751,20 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.is_enabled = i9xx_always_on_power_well_enabled,
};
static const struct i915_power_well_ops chv_pipe_power_well_ops = {
.sync_hw = chv_pipe_power_well_sync_hw,
.enable = chv_pipe_power_well_enable,
.disable = chv_pipe_power_well_disable,
.is_enabled = chv_pipe_power_well_enabled,
};
static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
.sync_hw = vlv_power_well_sync_hw,
.enable = chv_dpio_cmn_power_well_enable,
.disable = chv_dpio_cmn_power_well_disable,
.is_enabled = vlv_power_well_enabled,
};
static struct i915_power_well i9xx_always_on_power_well[] = {
{
.name = "always-on",
@ -6572,6 +6887,107 @@ static struct i915_power_well vlv_power_wells[] = {
},
};
static struct i915_power_well chv_power_wells[] = {
{
.name = "always-on",
.always_on = 1,
.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
.ops = &i9xx_always_on_power_well_ops,
},
#if 0
{
.name = "display",
.domains = VLV_DISPLAY_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DISP2D,
.ops = &vlv_display_power_well_ops,
},
{
.name = "pipe-a",
.domains = CHV_PIPE_A_POWER_DOMAINS,
.data = PIPE_A,
.ops = &chv_pipe_power_well_ops,
},
{
.name = "pipe-b",
.domains = CHV_PIPE_B_POWER_DOMAINS,
.data = PIPE_B,
.ops = &chv_pipe_power_well_ops,
},
{
.name = "pipe-c",
.domains = CHV_PIPE_C_POWER_DOMAINS,
.data = PIPE_C,
.ops = &chv_pipe_power_well_ops,
},
#endif
{
.name = "dpio-common-bc",
/*
* XXX: cmnreset for one PHY seems to disturb the other.
* As a workaround keep both powered on at the same
* time for now.
*/
.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
.ops = &chv_dpio_cmn_power_well_ops,
},
{
.name = "dpio-common-d",
/*
* XXX: cmnreset for one PHY seems to disturb the other.
* As a workaround keep both powered on at the same
* time for now.
*/
.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_D,
.ops = &chv_dpio_cmn_power_well_ops,
},
#if 0
{
.name = "dpio-tx-b-01",
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
},
{
.name = "dpio-tx-b-23",
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
},
{
.name = "dpio-tx-c-01",
.domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
},
{
.name = "dpio-tx-c-23",
.domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
},
{
.name = "dpio-tx-d-01",
.domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_01,
},
{
.name = "dpio-tx-d-23",
.domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS |
CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS,
.ops = &vlv_dpio_power_well_ops,
.data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_23,
},
#endif
};
static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
enum punit_power_well power_well_id)
{
@ -6608,6 +7024,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
} else if (IS_BROADWELL(dev_priv->dev)) {
set_power_wells(power_domains, bdw_power_wells);
hsw_pwr = power_domains;
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
set_power_wells(power_domains, chv_power_wells);
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
set_power_wells(power_domains, vlv_power_wells);
} else {
@ -6835,11 +7253,13 @@ void intel_init_pm(struct drm_device *dev)
else if (INTEL_INFO(dev)->gen == 8)
dev_priv->display.init_clock_gating = gen8_init_clock_gating;
} else if (IS_CHERRYVIEW(dev)) {
dev_priv->display.update_wm = valleyview_update_wm;
dev_priv->display.update_wm = cherryview_update_wm;
dev_priv->display.update_sprite_wm = valleyview_update_sprite_wm;
dev_priv->display.init_clock_gating =
cherryview_init_clock_gating;
} else if (IS_VALLEYVIEW(dev)) {
dev_priv->display.update_wm = valleyview_update_wm;
dev_priv->display.update_sprite_wm = valleyview_update_sprite_wm;
dev_priv->display.init_clock_gating =
valleyview_init_clock_gating;
} else if (IS_PINEVIEW(dev)) {

View file

@ -476,8 +476,8 @@ static bool stop_ring(struct intel_engine_cs *ring)
if (!IS_GEN2(ring->dev)) {
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
return false;
}
}

View file

@ -53,6 +53,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
enum pipe pipe = crtc->pipe;
long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
DEFINE_WAIT(wait);
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
* other CPUs can see the task state update by the time we
* 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);
if (scanline < min || scanline > max)
@ -100,7 +101,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
local_irq_disable();
}
finish_wait(&crtc->vbl_wait, &wait);
finish_wait(wq, &wait);
drm_vblank_put(dev, pipe);
@ -163,6 +164,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
sprctl &= ~SP_PIXFORMAT_MASK;
sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
sprctl &= ~SP_TILED;
sprctl &= ~SP_ROTATE_180;
switch (fb->pixel_format) {
case DRM_FORMAT_YUYV:
@ -235,6 +237,14 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
fb->pitches[0]);
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);
intel_update_primary_plane(intel_crtc);
@ -364,6 +374,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
sprctl &= ~SPRITE_RGB_ORDER_RGBX;
sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
sprctl &= ~SPRITE_TILED;
sprctl &= ~SPRITE_ROTATE_180;
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
@ -426,6 +437,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]);
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);
intel_update_primary_plane(intel_crtc);
@ -571,6 +594,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
dvscntr &= ~DVS_RGB_ORDER_XBGR;
dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
dvscntr &= ~DVS_TILED;
dvscntr &= ~DVS_ROTATE_180;
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
@ -628,6 +652,14 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]);
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);
intel_update_primary_plane(intel_crtc);
@ -895,6 +927,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
max_scale = intel_plane->max_downscale << 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);
BUG_ON(hscale < 0);
@ -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_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 */
WARN_ON(src.x1 < (int) src_x ||
src.y1 < (int) src_y ||
@ -1180,18 +1218,42 @@ out_unlock:
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);
if (!plane->crtc || !plane->fb)
return;
return 0;
intel_update_plane(plane, plane->crtc, plane->fb,
intel_plane->crtc_x, intel_plane->crtc_y,
intel_plane->crtc_w, intel_plane->crtc_h,
intel_plane->src_x, intel_plane->src_y,
intel_plane->src_w, intel_plane->src_h);
return intel_update_plane(plane, plane->crtc, plane->fb,
intel_plane->crtc_x, intel_plane->crtc_y,
intel_plane->crtc_w, intel_plane->crtc_h,
intel_plane->src_x, intel_plane->src_y,
intel_plane->src_w, intel_plane->src_h);
}
void intel_plane_disable(struct drm_plane *plane)
@ -1206,6 +1268,7 @@ static const struct drm_plane_funcs intel_plane_funcs = {
.update_plane = intel_update_plane,
.disable_plane = intel_disable_plane,
.destroy = intel_destroy_plane,
.set_property = intel_plane_set_property,
};
static uint32_t ilk_plane_formats[] = {
@ -1310,13 +1373,28 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
intel_plane->pipe = pipe;
intel_plane->plane = plane;
intel_plane->rotation = BIT(DRM_ROTATE_0);
possible_crtcs = (1 << pipe);
ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs,
plane_formats, num_plane_formats,
false);
if (ret)
if (ret) {
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;
}

View file

@ -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,
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 */
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);

View file

@ -825,6 +825,7 @@ struct drm_mode_config {
struct drm_property *dpms_property;
struct drm_property *path_property;
struct drm_property *plane_type_property;
struct drm_property *rotation_property;
/* DVI-I properties */
struct drm_property *dvi_i_subconnector_property;