/* asserts want to know the pipe even if the port is disabled */ if (HAS_PCH_CPT(display))
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK_CPT, val); else
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK, val);
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
adpa |= ADPA_HSYNC_ACTIVE_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
/* For CPT allow 3 pipe config, for others just use A or B */ if (HAS_PCH_LPT(display))
; /* Those bits don't exist here */ elseif (HAS_PCH_CPT(display))
adpa |= ADPA_PIPE_SEL_CPT(crtc->pipe); else
adpa |= ADPA_PIPE_SEL(crtc->pipe);
if (!HAS_PCH_SPLIT(display))
intel_de_write(display, BCLRPAT(display, crtc->pipe), 0);
switch (mode) { case DRM_MODE_DPMS_ON:
adpa |= ADPA_DAC_ENABLE; break; case DRM_MODE_DPMS_STANDBY:
adpa |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; break; case DRM_MODE_DPMS_SUSPEND:
adpa |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; break; case DRM_MODE_DPMS_OFF:
adpa |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; break;
}
status = intel_cpu_transcoder_mode_valid(display, mode); if (status != MODE_OK) return status;
if (mode->clock < 25000) return MODE_CLOCK_LOW;
if (HAS_PCH_LPT(display))
max_clock = 180000; elseif (display->platform.valleyview) /* * 270 MHz due to current DPLL limits, * DAC limit supposedly 355 MHz.
*/
max_clock = 270000; elseif (IS_DISPLAY_VER(display, 3, 4))
max_clock = 400000; else
max_clock = 350000; if (mode->clock > max_clock) return MODE_CLOCK_HIGH;
if (mode->clock > max_dotclk) return MODE_CLOCK_HIGH;
/* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ if (HAS_PCH_LPT(display) &&
ilk_get_lanes_required(mode->clock, 270000, 24) > 2) return MODE_CLOCK_HIGH;
/* HSW/BDW FDI limited to 4k */ if (mode->hdisplay > 4096) return MODE_H_ILLEGAL;
/* The first time through, trigger an explicit detection cycle */ if (crt->force_hotplug_required) { bool turn_off_dac = HAS_PCH_SPLIT(display);
u32 save_adpa;
adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; if (turn_off_dac)
adpa &= ~ADPA_DAC_ENABLE;
intel_de_write(display, crt->adpa_reg, adpa);
if (intel_de_wait_for_clear(display,
crt->adpa_reg,
ADPA_CRT_HOTPLUG_FORCE_TRIGGER,
1000))
drm_dbg_kms(display->drm, "timed out waiting for FORCE_TRIGGER");
if (turn_off_dac) {
intel_de_write(display, crt->adpa_reg, save_adpa);
intel_de_posting_read(display, crt->adpa_reg);
}
}
/* Check the status to see if both blue and green are on now */
adpa = intel_de_read(display, crt->adpa_reg); if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true; else
ret = false;
drm_dbg_kms(display->drm, "ironlake hotplug adpa=0x%x, result %d\n",
adpa, ret);
/* * Doing a force trigger causes a hpd interrupt to get sent, which can * get us stuck in a loop if we're polling: * - We enable power wells and reset the ADPA * - output_poll_exec does force probe on VGA, triggering a hpd * - HPD handler waits for poll to unlock dev->mode_config.mutex * - output_poll_exec shuts off the ADPA, unlocks * dev->mode_config.mutex * - HPD handler runs, resets ADPA and brings us back to the start * * Just disable HPD interrupts here to prevent this
*/
intel_hpd_block(&crt->base);
if (intel_de_wait_for_clear(display, crt->adpa_reg,
ADPA_CRT_HOTPLUG_FORCE_TRIGGER, 1000)) {
drm_dbg_kms(display->drm, "timed out waiting for FORCE_TRIGGER");
intel_de_write(display, crt->adpa_reg, save_adpa);
}
/* Check the status to see if both blue and green are on now */
adpa = intel_de_read(display, crt->adpa_reg); if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true; else
ret = false;
drm_dbg_kms(display->drm, "valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
intel_hpd_clear_and_unblock(&crt->base);
return ret;
}
staticbool intel_crt_detect_hotplug(struct drm_connector *connector)
{ struct intel_display *display = to_intel_display(connector->dev);
u32 stat; bool ret = false; int i, tries = 0;
if (HAS_PCH_SPLIT(display)) return ilk_crt_detect_hotplug(connector);
if (display->platform.valleyview) return valleyview_crt_detect_hotplug(connector);
/* * On 4 series desktop, CRT detect sequence need to be done twice * to get a reliable result.
*/
if (display->platform.g45)
tries = 2; else
tries = 1;
for (i = 0; i < tries ; i++) { /* turn on the FORCE_DETECT */
i915_hotplug_interrupt_update(display,
CRT_HOTPLUG_FORCE_DETECT,
CRT_HOTPLUG_FORCE_DETECT); /* wait for FORCE_DETECT to go off */ if (intel_de_wait_for_clear(display, PORT_HOTPLUG_EN(display),
CRT_HOTPLUG_FORCE_DETECT, 1000))
drm_dbg_kms(display->drm, "timed out waiting for FORCE_DETECT to go off");
}
stat = intel_de_read(display, PORT_HOTPLUG_STAT(display)); if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
ret = true;
/* clear the interrupt we just generated, if any */
intel_de_write(display, PORT_HOTPLUG_STAT(display),
CRT_HOTPLUG_INT_STATUS);
/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ staticint intel_crt_ddc_get_modes(struct drm_connector *connector, struct i2c_adapter *ddc)
{ conststruct drm_edid *drm_edid; int ret;
drm_edid = intel_crt_get_edid(connector, ddc); if (!drm_edid) return 0;
ret = intel_connector_update_modes(connector, drm_edid);
if (drm_edid) { /* * This may be a DVI-I connector with a shared DDC * link between analog and digital outputs, so we * have to check the EDID input spec of the attached device.
*/ if (drm_edid_is_digital(drm_edid)) {
drm_dbg_kms(display->drm, "CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
} else {
drm_dbg_kms(display->drm, "CRT detected via DDC:0x50 [EDID]\n");
ret = true;
}
} else {
drm_dbg_kms(display->drm, "CRT not detected via DDC:0x50 [no valid EDID found]\n");
}
/* * Wait for the border to be displayed
*/ while (intel_de_read(display, PIPEDSL(display, pipe)) >= vactive)
; while ((dsl = intel_de_read(display, PIPEDSL(display, pipe))) <= vsample)
; /* * Watch ST00 for an entire scanline
*/
detect = 0;
count = 0; do {
count++; /* Read the ST00 VGA status register */
st00 = intel_de_read8(display, _VGA_MSR_WRITE); if (st00 & (1 << 4))
detect++;
} while ((intel_de_read(display, PIPEDSL(display, pipe)) == dsl));
/* restore vblank if necessary */ if (restore_vblank)
intel_de_write(display,
TRANS_VBLANK(display, cpu_transcoder),
vblank); /* * If more than 3/4 of the scanline detected a monitor, * then it is assumed to be present. This works even on i830, * where there isn't any way to force the border color across * the screen
*/
status = detect * 4 > count * 3 ?
connector_status_connected :
connector_status_disconnected;
}
if (!intel_display_device_enabled(display)) return connector_status_disconnected;
if (!intel_display_driver_check_access(display)) return connector->status;
if (display->params.load_detect_test) {
wakeref = intel_display_power_get(display, encoder->power_domain); goto load_detect;
}
/* Skip machines without VGA that falsely report hotplug events */ if (dmi_check_system(intel_spurious_crt_detect)) return connector_status_disconnected;
if (HAS_HOTPLUG(display)) { /* We can not rely on the HPD pin always being correctly wired * up, for example many KVM do not pass it through, and so * only trust an assertion that the monitor is connected.
*/ if (intel_crt_detect_hotplug(connector)) {
drm_dbg_kms(display->drm, "CRT detected via hotplug\n");
status = connector_status_connected; goto out;
} else
drm_dbg_kms(display->drm, "CRT not detected via hotplug\n");
}
if (intel_crt_detect_ddc(connector)) {
status = connector_status_connected; goto out;
}
/* Load detection is broken on HPD capable machines. Whoever wants a * 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 (HAS_HOTPLUG(display)) {
status = connector_status_disconnected; goto out;
}
load_detect: if (!force) {
status = connector->status; goto out;
}
/* for pre-945g platforms use load detect */
state = intel_load_detect_get_pipe(connector, ctx); if (IS_ERR(state)) {
status = PTR_ERR(state);
} elseif (!state) {
status = connector_status_unknown;
} else { if (intel_crt_detect_ddc(connector))
status = connector_status_connected; elseif (DISPLAY_VER(display) < 4)
status = intel_crt_load_detect(crt,
to_intel_crtc(connector->state->crtc)->pipe); elseif (display->params.load_detect_test)
status = connector_status_disconnected; else
status = connector_status_unknown;
intel_load_detect_release_pipe(connector, state, ctx);
}
ret = intel_crt_ddc_get_modes(connector, connector->ddc); if (ret || !display->platform.g4x) goto out;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
ddc = intel_gmbus_get_adapter(display, GMBUS_PIN_DPB);
ret = intel_crt_ddc_get_modes(connector, ddc);
adpa = intel_de_read(display, adpa_reg); if ((adpa & ADPA_DAC_ENABLE) == 0) { /* * On some machines (some IVB at least) CRT can be * fused off, but there's no known fuse bit to * indicate that. On these machine the ADPA register * works normally, except the DAC enable bit won't * take. So the only way to tell is attempt to enable * it and see what happens.
*/
intel_de_write(display, adpa_reg,
adpa | ADPA_DAC_ENABLE |
ADPA_HSYNC_CNTL_DISABLE |
ADPA_VSYNC_CNTL_DISABLE); if ((intel_de_read(display, adpa_reg) & ADPA_DAC_ENABLE) == 0) return;
intel_de_write(display, adpa_reg, adpa);
}
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); if (!crt) return;
connector = intel_connector_alloc(); if (!connector) {
kfree(crt); return;
}
/* * TODO: find a proper way to discover whether we need to set the the * polarity and link reversal bits or not, instead of relying on the * BIOS.
*/ if (HAS_PCH_LPT(display)) {
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
FDI_RX_LINK_REVERSAL_OVERRIDE;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.