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:
commit
d5a0f2e7be
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue