/*
*/
/*
* Copyright (c) 2006-2007, 2013, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*/
#include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
#include "drm_edid.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "drm_sun_i2c.h" /* OSOL_i915 */
/* Here's the desired hotplug mode */
struct intel_crt {
/* DPMS state is stored in the connector, which we need in the
bool force_hotplug_required;
};
{
}
{
}
{
if (!(tmp & ADPA_DAC_ENABLE))
return false;
if (HAS_PCH_CPT(dev))
else
return true;
}
struct intel_crtc_config *pipe_config)
{
if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
else
if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
else
}
/* Note: The caller is required to filter out dpms modes not supported by the
* platform. */
{
temp &= ~ADPA_DAC_ENABLE;
switch(mode) {
case DRM_MODE_DPMS_ON:
temp |= ADPA_DAC_ENABLE;
break;
case DRM_MODE_DPMS_STANDBY:
break;
case DRM_MODE_DPMS_SUSPEND:
break;
case DRM_MODE_DPMS_OFF:
break;
}
}
{
}
{
}
{
int old_dpms;
return;
/* Only need to change hw state when actually enabled */
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. */
/* From off to on, enable the pipe first. */
} else {
}
}
struct drm_display_mode *mode)
{
int max_clock = 0;
return MODE_NO_DBLESCAN;
return MODE_CLOCK_LOW;
max_clock = 350000;
else
max_clock = 400000;
return MODE_CLOCK_HIGH;
/* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */
if (HAS_PCH_LPT(dev) &&
return MODE_CLOCK_HIGH;
return MODE_OK;
}
struct intel_crtc_config *pipe_config)
{
if (HAS_PCH_SPLIT(dev))
pipe_config->has_pch_encoder = true;
/* LPT FDI RX only supports 8bpc. */
if (HAS_PCH_LPT(dev))
return true;
}
/* LINTED */
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (HAS_PCH_SPLIT(dev))
else
adpa = 0;
/* For CPT allow 3 pipe config, for others just use A or B */
/* LINTED */
if (HAS_PCH_LPT(dev))
; /* Those bits don't exist here */
else if (HAS_PCH_CPT(dev))
else if (intel_crtc->pipe == 0)
else
if (!HAS_PCH_SPLIT(dev))
}
{
bool ret;
/* The first time through, trigger an explicit detection cycle */
if (crt->force_hotplug_required) {
crt->force_hotplug_required = 0;
if (turn_off_dac)
adpa &= ~ADPA_DAC_ENABLE;
1000))
DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
if (turn_off_dac) {
}
}
/* Check the status to see if both blue and green are on now */
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true;
else
ret = false;
return ret;
}
{
bool ret;
1000)) {
DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
}
/* Check the status to see if both blue and green are on now */
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true;
else
ret = false;
/* FIXME: debug force function and remove */
ret = true;
return ret;
}
/**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
*
*
* \return true if CRT is connected.
* \return false if CRT is disconnected.
*/
{
bool ret = false;
int i, tries = 0;
if (HAS_PCH_SPLIT(dev))
if (IS_VALLEYVIEW(dev))
return valleyview_crt_detect_hotplug(connector);
/*
* On 4 series desktop, CRT detect sequence need to be done twice
* to get a reliable result.
*/
tries = 2;
else
tries = 1;
for (i = 0; i < tries ; i++) {
/* turn on the FORCE_DETECT */
/* wait for FORCE_DETECT to go off */
CRT_HOTPLUG_FORCE_DETECT) == 0,
1000))
DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off");
}
ret = true;
/* clear the interrupt we just generated, if any */
/* and put the bits back */
return ret;
}
struct i2c_adapter *i2c)
{
DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
intel_gmbus_force_bit(i2c, true);
intel_gmbus_force_bit(i2c, false);
}
return edid;
}
/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
struct i2c_adapter *adapter)
{
int ret;
if (!edid)
return 0;
return ret;
}
{
if (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 (!is_digital) {
DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
return true;
}
DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
} else {
DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
}
return false;
}
static enum drm_connector_status
{
DRM_DEBUG_KMS("starting load-detect on CRT\n");
/* Set the border color to purple. */
/* Wait for next Vblank to substitue
* border color for Color info */
} else {
bool restore_vblank = false;
/*
* If there isn't any border, add some.
* Yes, this will flicker
*/
(vblank_start - 1) |
restore_vblank = true;
}
/* sample in the vertical border, selecting the larger one */
else
/*
* Wait for the border to be displayed
*/
;
;
/*
* Watch ST00 for an entire scanline
*/
detect = 0;
count = 0;
do {
count++;
/* Read the ST00 VGA status register */
detect++;
/* restore vblank if necessary */
if (restore_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
*/
}
/* Restore previous settings */
return status;
}
static enum drm_connector_status
{
if (I915_HAS_HOTPLUG(dev)) {
/* 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_DEBUG_KMS("CRT detected via hotplug\n");
return connector_status_connected;
} else
DRM_DEBUG_KMS("CRT not detected via hotplug\n");
}
return connector_status_connected;
/* 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 (I915_HAS_HOTPLUG(dev))
return connector_status_disconnected;
if (!force)
/* for pre-945g platforms use load detect */
else
} else
return status;
}
{
/* OSOL_i915: drm_sysfs_connector_remove(connector); */
}
{
int ret;
return ret;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
}
/* LINTED */
/* LINTED */
struct drm_property *property,
/* LINTED */
{
return 0;
}
{
if (HAS_PCH_SPLIT(dev)) {
}
}
/*
* Routines for controlling stuff on the analog port
*/
};
.reset = intel_crt_reset,
.dpms = intel_crt_dpms,
};
};
};
{
/* Skip machines without VGA that falsely report hotplug events */
if (!crt)
return;
if (!intel_connector) {
return;
}
else
connector->interlace_allowed = 0;
else
connector->doublescan_allowed = 0;
if (HAS_PCH_SPLIT(dev))
else if (IS_VALLEYVIEW(dev))
else
if (I915_HAS_HOTPLUG(dev))
else
/* OSOL_i915: drm_sysfs_connector_add(connector); */
if (!I915_HAS_HOTPLUG(dev))
/*
* Configure the automatic hotplug detection stuff
*/
crt->force_hotplug_required = 0;
/*
* 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(dev)) {
}
}