28,6 → 28,7 |
#include <linux/i2c.h> |
#include <linux/slab.h> |
#include <drm/drmP.h> |
#include <drm/drm_atomic_helper.h> |
#include <drm/drm_crtc.h> |
#include <drm/drm_crtc_helper.h> |
#include <drm/drm_edid.h> |
110,12 → 111,12 |
} |
|
static void intel_crt_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct drm_device *dev = encoder->base.dev; |
int dotclock; |
|
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); |
pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
|
dotclock = pipe_config->port_clock; |
|
122,33 → 123,21 |
if (HAS_PCH_SPLIT(dev)) |
ironlake_check_encoder_dotclock(pipe_config, dotclock); |
|
pipe_config->adjusted_mode.crtc_clock = dotclock; |
pipe_config->base.adjusted_mode.crtc_clock = dotclock; |
} |
|
static void hsw_crt_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
intel_ddi_get_config(encoder, pipe_config); |
|
pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | |
pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | |
DRM_MODE_FLAG_NHSYNC | |
DRM_MODE_FLAG_PVSYNC | |
DRM_MODE_FLAG_NVSYNC); |
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); |
pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
} |
|
static void hsw_crt_pre_enable(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n"); |
I915_WRITE(SPLL_CTL, |
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC); |
POSTING_READ(SPLL_CTL); |
udelay(20); |
} |
|
/* Note: The caller is required to filter out dpms modes not supported by the |
* platform. */ |
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) |
157,7 → 146,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crt *crt = intel_encoder_to_crt(encoder); |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
u32 adpa; |
|
if (INTEL_INFO(dev)->gen >= 5) |
206,18 → 195,13 |
intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF); |
} |
|
static void pch_disable_crt(struct intel_encoder *encoder) |
{ |
} |
|
static void hsw_crt_post_disable(struct intel_encoder *encoder) |
static void pch_post_disable_crt(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t val; |
|
DRM_DEBUG_KMS("Disabling SPLL\n"); |
val = I915_READ(SPLL_CTL); |
WARN_ON(!(val & SPLL_PLL_ENABLE)); |
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); |
POSTING_READ(SPLL_CTL); |
intel_disable_crt(encoder); |
} |
|
static void intel_enable_crt(struct intel_encoder *encoder) |
227,53 → 211,6 |
intel_crt_set_dpms(encoder, crt->connector->base.dpms); |
} |
|
/* Special dpms function to support cloning between dvo/sdvo/crt. */ |
static void intel_crt_dpms(struct drm_connector *connector, int mode) |
{ |
struct drm_device *dev = connector->dev; |
struct intel_encoder *encoder = intel_attached_encoder(connector); |
struct drm_crtc *crtc; |
int old_dpms; |
|
/* PCH platforms and VLV only support on/off. */ |
if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) |
mode = DRM_MODE_DPMS_OFF; |
|
if (mode == connector->dpms) |
return; |
|
old_dpms = connector->dpms; |
connector->dpms = mode; |
|
/* Only need to change hw state when actually enabled */ |
crtc = encoder->base.crtc; |
if (!crtc) { |
encoder->connectors_active = false; |
return; |
} |
|
/* We need the pipe to run for anything but OFF. */ |
if (mode == DRM_MODE_DPMS_OFF) |
encoder->connectors_active = false; |
else |
encoder->connectors_active = true; |
|
/* We call connector dpms manually below in case pipe dpms doesn't |
* change due to cloning. */ |
if (mode < old_dpms) { |
/* From off to on, enable the pipe first. */ |
intel_crtc_update_dpms(crtc); |
|
intel_crt_set_dpms(encoder, mode); |
} else { |
intel_crt_set_dpms(encoder, mode); |
|
intel_crtc_update_dpms(crtc); |
} |
|
intel_modeset_check_state(connector->dev); |
} |
|
static enum drm_mode_status |
intel_crt_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
303,7 → 240,7 |
} |
|
static bool intel_crt_compute_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct drm_device *dev = encoder->base.dev; |
|
318,6 → 255,10 |
if (HAS_DDI(dev)) { |
pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
pipe_config->port_clock = 135000 * 2; |
|
pipe_config->dpll_hw_state.wrpll = 0; |
pipe_config->dpll_hw_state.spll = |
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; |
} |
|
return true; |
414,7 → 355,7 |
{ |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 hotplug_en, orig, stat; |
u32 stat; |
bool ret = false; |
int i, tries = 0; |
|
433,12 → 374,12 |
tries = 2; |
else |
tries = 1; |
hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); |
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; |
|
for (i = 0; i < tries ; i++) { |
/* turn on the FORCE_DETECT */ |
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
i915_hotplug_interrupt_update(dev_priv, |
CRT_HOTPLUG_FORCE_DETECT, |
CRT_HOTPLUG_FORCE_DETECT); |
/* wait for FORCE_DETECT to go off */ |
if (wait_for((I915_READ(PORT_HOTPLUG_EN) & |
CRT_HOTPLUG_FORCE_DETECT) == 0, |
453,8 → 394,7 |
/* clear the interrupt we just generated, if any */ |
I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); |
|
/* and put the bits back */ |
I915_WRITE(PORT_HOTPLUG_EN, orig); |
i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0); |
|
return ret; |
} |
689,7 → 629,7 |
* broken monitor (without edid) to work behind a broken kvm (that fails |
* to have the right resistors for HP detection) needs to fix this up. |
* For now just bail out. */ |
if (I915_HAS_HOTPLUG(dev)) { |
if (I915_HAS_HOTPLUG(dev) && !i915.load_detect_test) { |
status = connector_status_disconnected; |
goto out; |
} |
705,9 → 645,11 |
if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { |
if (intel_crt_detect_ddc(connector)) |
status = connector_status_connected; |
else if (INTEL_INFO(dev)->gen < 4) |
status = intel_crt_load_detect(crt); |
else |
status = intel_crt_load_detect(crt); |
intel_release_load_detect_pipe(connector, &tmp); |
status = connector_status_unknown; |
intel_release_load_detect_pipe(connector, &tmp, &ctx); |
} else |
status = connector_status_unknown; |
|
744,7 → 686,7 |
goto out; |
|
/* Try to probe digital port for output in DVI-I -> VGA mode. */ |
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); |
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB); |
ret = intel_crt_ddc_get_modes(connector, i2c); |
|
out: |
787,11 → 729,14 |
|
static const struct drm_connector_funcs intel_crt_connector_funcs = { |
.reset = intel_crt_reset, |
.dpms = intel_crt_dpms, |
.dpms = drm_atomic_helper_connector_dpms, |
.detect = intel_crt_detect, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.destroy = intel_crt_destroy, |
.set_property = intel_crt_set_property, |
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
.atomic_get_property = intel_connector_atomic_get_property, |
}; |
|
static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
845,7 → 790,7 |
if (!crt) |
return; |
|
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
intel_connector = intel_connector_alloc(); |
if (!intel_connector) { |
kfree(crt); |
return; |
882,7 → 827,12 |
crt->adpa_reg = ADPA; |
|
crt->base.compute_config = intel_crt_compute_config; |
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) { |
crt->base.disable = pch_disable_crt; |
crt->base.post_disable = pch_post_disable_crt; |
} else { |
crt->base.disable = intel_disable_crt; |
} |
crt->base.enable = intel_enable_crt; |
if (I915_HAS_HOTPLUG(dev)) |
crt->base.hpd_pin = HPD_CRT; |
889,8 → 839,6 |
if (HAS_DDI(dev)) { |
crt->base.get_config = hsw_crt_get_config; |
crt->base.get_hw_state = intel_ddi_get_hw_state; |
crt->base.pre_enable = hsw_crt_pre_enable; |
crt->base.post_disable = hsw_crt_post_disable; |
} else { |
crt->base.get_config = intel_crt_get_config; |
crt->base.get_hw_state = intel_crt_get_hw_state; |
919,7 → 867,7 |
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | |
FDI_RX_LINK_REVERSAL_OVERRIDE; |
|
dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config; |
dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config; |
} |
|
intel_crt_reset(connector); |