@ -980,8 +980,8 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
pipe_name ( pipe ) ) ;
}
static bool dp_pipe_enabled ( struct drm_i915_private * dev_priv , enum pipe pipe ,
int reg , u32 port_sel , u32 val )
static bool dp_pipe_enabled ( struct drm_i915_private * dev_priv ,
enum pipe pipe , u32 port_sel , u32 val )
{
if ( ( val & DP_PORT_EN ) = = 0 )
return false ;
@ -998,11 +998,58 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe,
return true ;
}
static bool hdmi_pipe_enabled ( struct drm_i915_private * dev_priv ,
enum pipe pipe , u32 val )
{
if ( ( val & PORT_ENABLE ) = = 0 )
return false ;
if ( HAS_PCH_CPT ( dev_priv - > dev ) ) {
if ( ( val & PORT_TRANS_SEL_MASK ) ! = PORT_TRANS_SEL_CPT ( pipe ) )
return false ;
} else {
if ( ( val & TRANSCODER_MASK ) ! = TRANSCODER ( pipe ) )
return false ;
}
return true ;
}
static bool lvds_pipe_enabled ( struct drm_i915_private * dev_priv ,
enum pipe pipe , u32 val )
{
if ( ( val & LVDS_PORT_EN ) = = 0 )
return false ;
if ( HAS_PCH_CPT ( dev_priv - > dev ) ) {
if ( ( val & PORT_TRANS_SEL_MASK ) ! = PORT_TRANS_SEL_CPT ( pipe ) )
return false ;
} else {
if ( ( val & LVDS_PIPE_MASK ) ! = LVDS_PIPE ( pipe ) )
return false ;
}
return true ;
}
static bool adpa_pipe_enabled ( struct drm_i915_private * dev_priv ,
enum pipe pipe , u32 val )
{
if ( ( val & ADPA_DAC_ENABLE ) = = 0 )
return false ;
if ( HAS_PCH_CPT ( dev_priv - > dev ) ) {
if ( ( val & PORT_TRANS_SEL_MASK ) ! = PORT_TRANS_SEL_CPT ( pipe ) )
return false ;
} else {
if ( ( val & ADPA_PIPE_SELECT_MASK ) ! = ADPA_PIPE_SELECT ( pipe ) )
return false ;
}
return true ;
}
static void assert_pch_dp_disabled ( struct drm_i915_private * dev_priv ,
enum pipe pipe , int reg , u32 port_sel )
{
u32 val = I915_READ ( reg ) ;
WARN ( dp_pipe_enabled ( dev_priv , pipe , reg , port_sel , val ) ,
WARN ( dp_pipe_enabled ( dev_priv , pipe , port_sel , val ) ,
" PCH DP (0x%08x) enabled on transcoder %c, should be disabled \n " ,
reg , pipe_name ( pipe ) ) ;
}
@ -1011,7 +1058,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe , int reg )
{
u32 val = I915_READ ( reg ) ;
WARN ( HDMI_PIPE_ENABLED ( val , pipe ) ,
WARN ( hdmi_pipe_enabled ( dev_priv , val , pipe ) ,
" PCH DP (0x%08x) enabled on transcoder %c, should be disabled \n " ,
reg , pipe_name ( pipe ) ) ;
}
@ -1028,13 +1075,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
reg = PCH_ADPA ;
val = I915_READ ( reg ) ;
WARN ( ADPA_PIPE_ENABLED ( val , pipe ) ,
WARN ( adpa_pipe_enabled ( dev_priv , val , pipe ) ,
" PCH VGA enabled on transcoder %c, should be disabled \n " ,
pipe_name ( pipe ) ) ;
reg = PCH_LVDS ;
val = I915_READ ( reg ) ;
WARN ( LVDS_PIPE_ENABLED ( val , pipe ) ,
WARN ( lvds_pipe_enabled ( dev_priv , val , pipe ) ,
" PCH LVDS enabled on transcoder %c, should be disabled \n " ,
pipe_name ( pipe ) ) ;
@ -1360,7 +1407,7 @@ static void disable_pch_dp(struct drm_i915_private *dev_priv,
enum pipe pipe , int reg , u32 port_sel )
{
u32 val = I915_READ ( reg ) ;
if ( dp_pipe_enabled ( dev_priv , pipe , reg , port_sel , val ) ) {
if ( dp_pipe_enabled ( dev_priv , pipe , port_sel , val ) ) {
DRM_DEBUG_KMS ( " Disabling pch dp %x on pipe %d \n " , reg , pipe ) ;
I915_WRITE ( reg , val & ~ DP_PORT_EN ) ;
}
@ -1370,7 +1417,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
enum pipe pipe , int reg )
{
u32 val = I915_READ ( reg ) ;
if ( HDMI_PIPE_ENABLED ( val , pipe ) ) {
if ( hdmi_pipe_enabled ( dev_priv , val , pipe ) ) {
DRM_DEBUG_KMS ( " Disabling pch HDMI %x on pipe %d \n " ,
reg , pipe ) ;
I915_WRITE ( reg , val & ~ PORT_ENABLE ) ;
@ -1392,12 +1439,13 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
reg = PCH_ADPA ;
val = I915_READ ( reg ) ;
if ( ADPA_PIPE_ENABLED ( val , pipe ) )
if ( adpa_pipe_enabled ( dev_priv , val , pipe ) )
I915_WRITE ( reg , val & ~ ADPA_DAC_ENABLE ) ;
reg = PCH_LVDS ;
val = I915_READ ( reg ) ;
if ( LVDS_PIPE_ENABLED ( val , pipe ) ) {
if ( lvds_pipe_enabled ( dev_priv , val , pipe ) ) {
DRM_DEBUG_KMS ( " disable lvds on pipe %d val 0x%08x \n " , pipe , val ) ;
I915_WRITE ( reg , val & ~ LVDS_PORT_EN ) ;
POSTING_READ ( reg ) ;
udelay ( 100 ) ;
@ -5049,6 +5097,81 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
return ret ;
}
static void ironlake_update_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 drm_crtc * crtc ;
struct intel_encoder * encoder ;
struct intel_encoder * has_edp_encoder = NULL ;
u32 temp ;
bool has_lvds = false ;
/* 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 ,
base . head ) {
if ( encoder - > base . crtc ! = crtc )
continue ;
switch ( encoder - > type ) {
case INTEL_OUTPUT_LVDS :
has_lvds = true ;
case INTEL_OUTPUT_EDP :
has_edp_encoder = encoder ;
break ;
}
}
}
/* Ironlake: try to setup display ref clock before DPLL
* enabling . This is only under driver ' s control after
* PCH B stepping , previous chipset stepping should be
* ignoring this setting .
*/
temp = I915_READ ( PCH_DREF_CONTROL ) ;
/* Always enable nonspread source */
temp & = ~ DREF_NONSPREAD_SOURCE_MASK ;
temp | = DREF_NONSPREAD_SOURCE_ENABLE ;
temp & = ~ DREF_SSC_SOURCE_MASK ;
temp | = DREF_SSC_SOURCE_ENABLE ;
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
if ( has_edp_encoder ) {
if ( intel_panel_use_ssc ( dev_priv ) ) {
temp | = DREF_SSC1_ENABLE ;
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
}
temp & = ~ DREF_CPU_SOURCE_OUTPUT_MASK ;
/* Enable CPU source on CPU attached eDP */
if ( ! intel_encoder_is_pch_edp ( & has_edp_encoder - > base ) ) {
if ( intel_panel_use_ssc ( dev_priv ) )
temp | = DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD ;
else
temp | = DREF_CPU_SOURCE_OUTPUT_NONSPREAD ;
} else {
/* Enable SSC on PCH eDP if needed */
if ( intel_panel_use_ssc ( dev_priv ) ) {
DRM_ERROR ( " enabling SSC on PCH \n " ) ;
temp | = DREF_SUPERSPREAD_SOURCE_ENABLE ;
}
}
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
}
}
static int ironlake_crtc_mode_set ( struct drm_crtc * crtc ,
struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode ,
@ -5244,49 +5367,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
ironlake_compute_m_n ( intel_crtc - > bpp , lane , target_clock , link_bw ,
& m_n ) ;
/* Ironlake: try to setup display ref clock before DPLL
* enabling . This is only under driver ' s control after
* PCH B stepping , previous chipset stepping should be
* ignoring this setting .
*/
temp = I915_READ ( PCH_DREF_CONTROL ) ;
/* Always enable nonspread source */
temp & = ~ DREF_NONSPREAD_SOURCE_MASK ;
temp | = DREF_NONSPREAD_SOURCE_ENABLE ;
temp & = ~ DREF_SSC_SOURCE_MASK ;
temp | = DREF_SSC_SOURCE_ENABLE ;
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
if ( has_edp_encoder ) {
if ( intel_panel_use_ssc ( dev_priv ) ) {
temp | = DREF_SSC1_ENABLE ;
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
}
temp & = ~ DREF_CPU_SOURCE_OUTPUT_MASK ;
/* Enable CPU source on CPU attached eDP */
if ( ! intel_encoder_is_pch_edp ( & has_edp_encoder - > base ) ) {
if ( intel_panel_use_ssc ( dev_priv ) )
temp | = DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD ;
else
temp | = DREF_CPU_SOURCE_OUTPUT_NONSPREAD ;
} else {
/* Enable SSC on PCH eDP if needed */
if ( intel_panel_use_ssc ( dev_priv ) ) {
DRM_ERROR ( " enabling SSC on PCH \n " ) ;
temp | = DREF_SUPERSPREAD_SOURCE_ENABLE ;
}
}
I915_WRITE ( PCH_DREF_CONTROL , temp ) ;
POSTING_READ ( PCH_DREF_CONTROL ) ;
udelay ( 200 ) ;
}
ironlake_update_pch_refclk ( dev ) ;
fp = clock . n < < 16 | clock . m1 < < 8 | clock . m2 ;
if ( has_reduced_clock )