Merge branch 'fix-pch-refclk' into foo
This commit is contained in:
commit
9a1f57808a
|
@ -79,11 +79,11 @@ MODULE_PARM_DESC(lvds_downclock,
|
||||||
"Use panel (LVDS/eDP) downclocking for power savings "
|
"Use panel (LVDS/eDP) downclocking for power savings "
|
||||||
"(default: false)");
|
"(default: false)");
|
||||||
|
|
||||||
unsigned int i915_panel_use_ssc __read_mostly = 1;
|
unsigned int i915_panel_use_ssc __read_mostly = -1;
|
||||||
module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
|
module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
|
||||||
MODULE_PARM_DESC(lvds_use_ssc,
|
MODULE_PARM_DESC(lvds_use_ssc,
|
||||||
"Use Spread Spectrum Clock with panels [LVDS/eDP] "
|
"Use Spread Spectrum Clock with panels [LVDS/eDP] "
|
||||||
"(default: true)");
|
"(default: auto from VBT)");
|
||||||
|
|
||||||
int i915_vbt_sdvo_panel_type __read_mostly = -1;
|
int i915_vbt_sdvo_panel_type __read_mostly = -1;
|
||||||
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
|
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
|
||||||
|
@ -471,6 +471,9 @@ static int i915_drm_thaw(struct drm_device *dev)
|
||||||
error = i915_gem_init_ringbuffer(dev);
|
error = i915_gem_init_ringbuffer(dev);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
if (HAS_PCH_SPLIT(dev))
|
||||||
|
ironlake_init_pch_refclk(dev);
|
||||||
|
|
||||||
drm_mode_config_reset(dev);
|
drm_mode_config_reset(dev);
|
||||||
drm_irq_install(dev);
|
drm_irq_install(dev);
|
||||||
|
|
||||||
|
|
|
@ -358,6 +358,7 @@ typedef struct drm_i915_private {
|
||||||
unsigned int lvds_vbt:1;
|
unsigned int lvds_vbt:1;
|
||||||
unsigned int int_crt_support:1;
|
unsigned int int_crt_support:1;
|
||||||
unsigned int lvds_use_ssc:1;
|
unsigned int lvds_use_ssc:1;
|
||||||
|
unsigned int display_clock_mode:1;
|
||||||
int lvds_ssc_freq;
|
int lvds_ssc_freq;
|
||||||
struct {
|
struct {
|
||||||
int rate;
|
int rate;
|
||||||
|
@ -1301,6 +1302,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
|
||||||
extern bool intel_fbc_enabled(struct drm_device *dev);
|
extern bool intel_fbc_enabled(struct drm_device *dev);
|
||||||
extern void intel_disable_fbc(struct drm_device *dev);
|
extern void intel_disable_fbc(struct drm_device *dev);
|
||||||
extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
|
extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
|
||||||
|
extern void ironlake_init_pch_refclk(struct drm_device *dev);
|
||||||
extern void ironlake_enable_rc6(struct drm_device *dev);
|
extern void ironlake_enable_rc6(struct drm_device *dev);
|
||||||
extern void gen6_set_rps(struct drm_device *dev, u8 val);
|
extern void gen6_set_rps(struct drm_device *dev, u8 val);
|
||||||
extern void intel_detect_pch(struct drm_device *dev);
|
extern void intel_detect_pch(struct drm_device *dev);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2006 Intel Corporation
|
* Copyright © 2006 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
||||||
dev_priv->lvds_use_ssc = general->enable_ssc;
|
dev_priv->lvds_use_ssc = general->enable_ssc;
|
||||||
dev_priv->lvds_ssc_freq =
|
dev_priv->lvds_ssc_freq =
|
||||||
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
||||||
|
dev_priv->display_clock_mode = general->display_clock_mode;
|
||||||
|
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
|
||||||
|
dev_priv->int_tv_support,
|
||||||
|
dev_priv->int_crt_support,
|
||||||
|
dev_priv->lvds_use_ssc,
|
||||||
|
dev_priv->lvds_ssc_freq,
|
||||||
|
dev_priv->display_clock_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,7 +617,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
||||||
/* Default to using SSC */
|
/* Default to using SSC */
|
||||||
dev_priv->lvds_use_ssc = 1;
|
dev_priv->lvds_use_ssc = 1;
|
||||||
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
|
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
|
||||||
DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
|
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
|
||||||
|
|
||||||
/* eDP data */
|
/* eDP data */
|
||||||
dev_priv->edp.bpp = 18;
|
dev_priv->edp.bpp = 18;
|
||||||
|
@ -639,7 +646,7 @@ intel_parse_bios(struct drm_device *dev)
|
||||||
if (dev_priv->opregion.vbt) {
|
if (dev_priv->opregion.vbt) {
|
||||||
struct vbt_header *vbt = dev_priv->opregion.vbt;
|
struct vbt_header *vbt = dev_priv->opregion.vbt;
|
||||||
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
|
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
|
||||||
DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
|
DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
|
||||||
vbt->signature);
|
vbt->signature);
|
||||||
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
|
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -120,7 +120,9 @@ struct bdb_general_features {
|
||||||
u8 ssc_freq:1;
|
u8 ssc_freq:1;
|
||||||
u8 enable_lfp_on_override:1;
|
u8 enable_lfp_on_override:1;
|
||||||
u8 disable_ssc_ddt:1;
|
u8 disable_ssc_ddt:1;
|
||||||
u8 rsvd8:3; /* finish byte */
|
u8 rsvd7:1;
|
||||||
|
u8 display_clock_mode:1;
|
||||||
|
u8 rsvd8:1; /* finish byte */
|
||||||
|
|
||||||
/* bits 3 */
|
/* bits 3 */
|
||||||
u8 disable_smooth_vision:1;
|
u8 disable_smooth_vision:1;
|
||||||
|
@ -133,7 +135,10 @@ struct bdb_general_features {
|
||||||
/* bits 5 */
|
/* bits 5 */
|
||||||
u8 int_crt_support:1;
|
u8 int_crt_support:1;
|
||||||
u8 int_tv_support:1;
|
u8 int_tv_support:1;
|
||||||
u8 rsvd11:6; /* finish byte */
|
u8 int_efp_support:1;
|
||||||
|
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
|
||||||
|
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
|
||||||
|
u8 rsvd11:3; /* finish byte */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* pre-915 */
|
/* pre-915 */
|
||||||
|
|
|
@ -4585,7 +4585,9 @@ static void intel_update_watermarks(struct drm_device *dev)
|
||||||
|
|
||||||
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
|
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
|
||||||
{
|
{
|
||||||
return dev_priv->lvds_use_ssc && i915_panel_use_ssc
|
if (i915_panel_use_ssc >= 0)
|
||||||
|
return i915_panel_use_ssc != 0;
|
||||||
|
return dev_priv->lvds_use_ssc
|
||||||
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
|
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5108,36 +5110,52 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ironlake_update_pch_refclk(struct drm_device *dev)
|
/*
|
||||||
|
* Initialize reference clocks when the driver loads
|
||||||
|
*/
|
||||||
|
void ironlake_init_pch_refclk(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||||
struct drm_crtc *crtc;
|
|
||||||
struct intel_encoder *encoder;
|
struct intel_encoder *encoder;
|
||||||
struct intel_encoder *has_edp_encoder = NULL;
|
|
||||||
u32 temp;
|
u32 temp;
|
||||||
bool has_lvds = false;
|
bool has_lvds = false;
|
||||||
|
bool has_cpu_edp = false;
|
||||||
|
bool has_pch_edp = false;
|
||||||
|
bool has_panel = false;
|
||||||
|
bool has_ck505 = false;
|
||||||
|
bool can_ssc = false;
|
||||||
|
|
||||||
/* We need to take the global config into account */
|
/* We need to take the global config into account */
|
||||||
list_for_each_entry(crtc, &mode_config->crtc_list, head) {
|
|
||||||
if (!crtc->enabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
list_for_each_entry(encoder, &mode_config->encoder_list,
|
list_for_each_entry(encoder, &mode_config->encoder_list,
|
||||||
base.head) {
|
base.head) {
|
||||||
if (encoder->base.crtc != crtc)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (encoder->type) {
|
switch (encoder->type) {
|
||||||
case INTEL_OUTPUT_LVDS:
|
case INTEL_OUTPUT_LVDS:
|
||||||
|
has_panel = true;
|
||||||
has_lvds = true;
|
has_lvds = true;
|
||||||
|
break;
|
||||||
case INTEL_OUTPUT_EDP:
|
case INTEL_OUTPUT_EDP:
|
||||||
has_edp_encoder = encoder;
|
has_panel = true;
|
||||||
|
if (intel_encoder_is_pch_edp(&encoder->base))
|
||||||
|
has_pch_edp = true;
|
||||||
|
else
|
||||||
|
has_cpu_edp = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HAS_PCH_IBX(dev)) {
|
||||||
|
has_ck505 = dev_priv->display_clock_mode;
|
||||||
|
can_ssc = has_ck505;
|
||||||
|
} else {
|
||||||
|
has_ck505 = false;
|
||||||
|
can_ssc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
|
||||||
|
has_panel, has_lvds, has_pch_edp, has_cpu_edp,
|
||||||
|
has_ck505);
|
||||||
|
|
||||||
/* Ironlake: try to setup display ref clock before DPLL
|
/* Ironlake: try to setup display ref clock before DPLL
|
||||||
* enabling. This is only under driver's control after
|
* enabling. This is only under driver's control after
|
||||||
* PCH B stepping, previous chipset stepping should be
|
* PCH B stepping, previous chipset stepping should be
|
||||||
|
@ -5146,37 +5164,62 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
|
||||||
temp = I915_READ(PCH_DREF_CONTROL);
|
temp = I915_READ(PCH_DREF_CONTROL);
|
||||||
/* Always enable nonspread source */
|
/* Always enable nonspread source */
|
||||||
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
||||||
|
|
||||||
|
if (has_ck505)
|
||||||
|
temp |= DREF_NONSPREAD_CK505_ENABLE;
|
||||||
|
else
|
||||||
temp |= DREF_NONSPREAD_SOURCE_ENABLE;
|
temp |= DREF_NONSPREAD_SOURCE_ENABLE;
|
||||||
|
|
||||||
|
if (has_panel) {
|
||||||
temp &= ~DREF_SSC_SOURCE_MASK;
|
temp &= ~DREF_SSC_SOURCE_MASK;
|
||||||
temp |= DREF_SSC_SOURCE_ENABLE;
|
temp |= DREF_SSC_SOURCE_ENABLE;
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
|
||||||
|
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
/* SSC must be turned on before enabling the CPU output */
|
||||||
udelay(200);
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
||||||
|
DRM_DEBUG_KMS("Using SSC on panel\n");
|
||||||
if (has_edp_encoder) {
|
|
||||||
if (intel_panel_use_ssc(dev_priv)) {
|
|
||||||
temp |= DREF_SSC1_ENABLE;
|
temp |= DREF_SSC1_ENABLE;
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
}
|
||||||
|
|
||||||
|
/* Get SSC going before enabling the outputs */
|
||||||
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
POSTING_READ(PCH_DREF_CONTROL);
|
||||||
udelay(200);
|
udelay(200);
|
||||||
}
|
|
||||||
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
||||||
|
|
||||||
/* Enable CPU source on CPU attached eDP */
|
/* Enable CPU source on CPU attached eDP */
|
||||||
if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
|
if (has_cpu_edp) {
|
||||||
if (intel_panel_use_ssc(dev_priv))
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
||||||
|
DRM_DEBUG_KMS("Using SSC on eDP\n");
|
||||||
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
||||||
|
} else
|
||||||
|
temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
||||||
|
|
||||||
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
|
POSTING_READ(PCH_DREF_CONTROL);
|
||||||
|
udelay(200);
|
||||||
} else {
|
} else {
|
||||||
/* Enable SSC on PCH eDP if needed */
|
DRM_DEBUG_KMS("Disabling SSC entirely\n");
|
||||||
if (intel_panel_use_ssc(dev_priv)) {
|
|
||||||
DRM_ERROR("enabling SSC on PCH\n");
|
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
||||||
temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
|
|
||||||
}
|
/* Turn off CPU output */
|
||||||
}
|
temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
||||||
|
|
||||||
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
|
POSTING_READ(PCH_DREF_CONTROL);
|
||||||
|
udelay(200);
|
||||||
|
|
||||||
|
/* Turn off the SSC source */
|
||||||
|
temp &= ~DREF_SSC_SOURCE_MASK;
|
||||||
|
temp |= DREF_SSC_SOURCE_DISABLE;
|
||||||
|
|
||||||
|
/* Turn off SSC1 */
|
||||||
|
temp &= ~ DREF_SSC1_ENABLE;
|
||||||
|
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
POSTING_READ(PCH_DREF_CONTROL);
|
||||||
udelay(200);
|
udelay(200);
|
||||||
|
@ -5242,16 +5285,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
num_connectors++;
|
num_connectors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
/*
|
||||||
refclk = dev_priv->lvds_ssc_freq * 1000;
|
* Every reference clock in a PCH system is 120MHz
|
||||||
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
*/
|
||||||
refclk / 1000);
|
refclk = 120000;
|
||||||
} else {
|
|
||||||
refclk = 96000;
|
|
||||||
if (!has_edp_encoder ||
|
|
||||||
intel_encoder_is_pch_edp(&has_edp_encoder->base))
|
|
||||||
refclk = 120000; /* 120Mhz refclk */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a set of divisors for the desired target clock with the given
|
* Returns a set of divisors for the desired target clock with the given
|
||||||
|
@ -5378,8 +5415,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
|
ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
|
||||||
&m_n);
|
&m_n);
|
||||||
|
|
||||||
ironlake_update_pch_refclk(dev);
|
|
||||||
|
|
||||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||||
if (has_reduced_clock)
|
if (has_reduced_clock)
|
||||||
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
|
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
|
||||||
|
@ -7376,6 +7411,9 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||||
|
|
||||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||||
drm_helper_disable_unused_functions(dev);
|
drm_helper_disable_unused_functions(dev);
|
||||||
|
|
||||||
|
if (HAS_PCH_SPLIT(dev))
|
||||||
|
ironlake_init_pch_refclk(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
||||||
|
|
Loading…
Reference in New Issue