/*
*/
/*
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
* Copyright (c) 2006-2008, 2013, Intel Corporation
* Jesse Barnes <jesse.barnes@intel.com>
*
* 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 "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "drm_sun_i2c.h"
struct gmbus_port {
const char *name;
int reg;
};
{ "ssc", GPIOB },
{ "vga", GPIOA },
{ "panel", GPIOC },
{ "dpc", GPIOD },
{ "dpb", GPIOE },
{ "dpd", GPIOF },
};
/* Intel GPIO access functions */
static inline struct intel_gmbus *
{
}
void
{
}
{
/* When using bit bashing for I2C, this bit needs to be set to 1 */
return;
if (enable)
else
}
{
/* On most chips, these bits must be preserved in software. */
return reserved;
}
{
}
{
}
{
}
{
}
{
if (state_high)
else
}
{
if (state_high)
else
}
static int
{
struct intel_gmbus,
adapter);
intel_i2c_quirk_set(dev_priv, true);
return 0;
}
static void
{
struct intel_gmbus,
adapter);
intel_i2c_quirk_set(dev_priv, false);
}
static void
{
/* -1 to map pin pair to gmbus index */
/* OSOL_i915 Begin */
if (pin == 2) {
} else {
}
/* OSOL End */
}
/*
* gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI
* mode. This results in spurious interrupt warnings if the legacy irq no. is
* shared with another device. The kernel then disables that interrupt source
* and so prevents the other device from working properly.
*/
static int
{
int ret;
gmbus4_irq_en = 0;
/* Important: The hw handles only the first bit, so set only one! Since
* need to wake up periodically and check that ourselves. */
if (ret)
return -ETIMEDOUT;
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
if (gmbus2 & gmbus2_status)
return 0;
return -ETIMEDOUT;
}
static int
{
int ret;
return wait_for(C, 10);
/* Important: The hw handles only the first bit, so set only one! */
if (!ret)
return 0;
else
return -ETIMEDOUT;
#undef C
}
static int
{
(len << GMBUS_BYTE_COUNT_SHIFT) |
while (len) {
int ret;
if (ret)
return ret;
do {
val >>= 8;
}
return 0;
}
static int
{
len -= 1;
}
while (len) {
int ret;
do {
if (ret)
return ret;
}
return 0;
}
/*
* The gmbus controller can combine a 1 or 2 byte write with a read that
* immediately follows it by using an "INDEX" cycle.
*/
static bool
{
return (i + 1 < num &&
}
static int
{
int ret;
/* GMBUS5 holds 16-bit index */
if (gmbus5)
/* Clear GMBUS5 after each index transfer */
if (gmbus5)
return ret;
}
static int
int num)
{
struct intel_gmbus,
adapter);
int i, reg_offset;
int ret = 0;
goto out;
}
for (i = 0; i < num; i++) {
i += 1; /* set i to the index of the read xfer */
} else {
}
goto timeout;
goto clear_err;
goto clear_err;
if (ret)
goto timeout;
}
/* Generate a STOP condition on the bus. Note that gmbus can't generata
* a STOP on the very first cycle. To simplify the code we
* unconditionally generate the STOP condition with an additional gmbus
* cycle. */
/* Mark the GMBUS interface as disabled after waiting for idle.
* We will re-enable it at the start of the next xfer,
* till then let it sleep.
*/
if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
}
goto out;
/*
* Wait for bus to IDLE before clearing NAK.
* If we clear the NAK while bus is still active, then it will stay
* active and the next transaction may fail.
*
* If no ACK is received during the address phase of a transaction, the
* adapter must report -ENXIO. It is not clear what to return if no ACK
* is received at other times. But we have to be careful to not return
* spurious -ENXIO because that will prevent i2c and drm edid functions
* from retrying. So return -ENXIO only when gmbus properly quiescents -
* timing out seems to happen when there _is_ a ddc chip present, but
* it's slow responding and only answers on the 2nd retry.
*/
if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
}
/* Toggle the Software Clear Interrupt bit. This has the effect
* of resetting the GMBUS controller and so clearing the
* BUS_ERROR raised by the slave's NAK.
*/
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
goto out;
DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
out:
return ret;
}
{
}
};
/**
* intel_gmbus_setup - instantiate all Intel i2c GMBuses
* @dev: DRM device
*/
{
int i;
if (HAS_PCH_NOP(dev))
return 0;
else if (HAS_PCH_SPLIT(dev))
else if (IS_VALLEYVIEW(dev))
else
dev_priv->gpio_mmio_base = 0;
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
"i915 gmbus %s",
gmbus_ports[i].name);
// bus->adapter.dev.parent = &dev->pdev->dev;
/* By default use a conservative clock rate */
/* gmbus seems to be broken on i830 */
}
return 0;
}
unsigned port)
{
/* -1 to map pin pair to gmbus index */
return (intel_gmbus_is_port_valid(port)) ?
}
{
}
{
DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
}
{
/*
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_gmbus *bus = &dev_priv->gmbus[i];
// i2c_del_adapter(&bus->adapter);
}
*/
}
/* workaround for fixing hdmi issue */
{
}