Merge tag 'drm-intel-next-2012-03-01' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
* tag 'drm-intel-next-2012-03-01' of git://people.freedesktop.org/~danvet/drm-intel: drm/i915: Only clear the GPU domains upon a successful finish drm/i915: reenable gmbus on gen3+ again drm/i915: i2c: unconditionally set up gpio fallback drm/i915: merge gmbus and gpio i2c adpater into one drm/i915: merge struct intel_gpio into struct intel_gmbus i2c: export bit-banging algo functions drm/nouveau: do a better job at hiding the NIH i2c bit-banging algo drm/i915: add dev_priv to intel_gmbus drm/i915: Fix single msg gmbus_xfers writes drm/i915: error_buffer->ring should be signed drm/i915: Silence the error message from i915_wait_request() drm/i915: use the new hdmi_force_audio enum more drm/i915: No need to search again after retiring requests drm/i915: Only bump refcnt on objects scheduled for eviction drm/i915/bios: Downgrade the "signature missing" DRM_ERROR to debug drm/i915: Ignore LVDS on hp t5745 and hp st5747 thin client drm/i915: Fixes distorted external screen image on HP 2730p
This commit is contained in:
commit
de49442f59
@ -35,6 +35,7 @@
|
|||||||
#include "intel_ringbuffer.h"
|
#include "intel_ringbuffer.h"
|
||||||
#include <linux/io-mapping.h>
|
#include <linux/io-mapping.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-algo-bit.h>
|
||||||
#include <drm/intel-gtt.h>
|
#include <drm/intel-gtt.h>
|
||||||
#include <linux/backlight.h>
|
#include <linux/backlight.h>
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ struct drm_i915_error_state {
|
|||||||
u32 tiling:2;
|
u32 tiling:2;
|
||||||
u32 dirty:1;
|
u32 dirty:1;
|
||||||
u32 purgeable:1;
|
u32 purgeable:1;
|
||||||
u32 ring:4;
|
s32 ring:4;
|
||||||
u32 cache_level:2;
|
u32 cache_level:2;
|
||||||
} *active_bo, *pinned_bo;
|
} *active_bo, *pinned_bo;
|
||||||
u32 active_bo_count, pinned_bo_count;
|
u32 active_bo_count, pinned_bo_count;
|
||||||
@ -298,6 +299,16 @@ enum intel_pch {
|
|||||||
struct intel_fbdev;
|
struct intel_fbdev;
|
||||||
struct intel_fbc_work;
|
struct intel_fbc_work;
|
||||||
|
|
||||||
|
struct intel_gmbus {
|
||||||
|
struct i2c_adapter adapter;
|
||||||
|
bool force_bit;
|
||||||
|
bool has_gpio;
|
||||||
|
u32 reg0;
|
||||||
|
u32 gpio_reg;
|
||||||
|
struct i2c_algo_bit_data bit_algo;
|
||||||
|
struct drm_i915_private *dev_priv;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct drm_i915_private {
|
typedef struct drm_i915_private {
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
|
|
||||||
@ -315,11 +326,7 @@ typedef struct drm_i915_private {
|
|||||||
/** gt_lock is also taken in irq contexts. */
|
/** gt_lock is also taken in irq contexts. */
|
||||||
struct spinlock gt_lock;
|
struct spinlock gt_lock;
|
||||||
|
|
||||||
struct intel_gmbus {
|
struct intel_gmbus *gmbus;
|
||||||
struct i2c_adapter adapter;
|
|
||||||
struct i2c_adapter *force_bit;
|
|
||||||
u32 reg0;
|
|
||||||
} *gmbus;
|
|
||||||
|
|
||||||
/** gmbus_mutex protects against concurrent usage of the single hw gmbus
|
/** gmbus_mutex protects against concurrent usage of the single hw gmbus
|
||||||
* controller on different i2c buses. */
|
* controller on different i2c buses. */
|
||||||
|
@ -1985,11 +1985,6 @@ i915_wait_request(struct intel_ring_buffer *ring,
|
|||||||
if (atomic_read(&dev_priv->mm.wedged))
|
if (atomic_read(&dev_priv->mm.wedged))
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
|
|
||||||
if (ret && ret != -ERESTARTSYS)
|
|
||||||
DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n",
|
|
||||||
__func__, ret, seqno, ring->get_seqno(ring),
|
|
||||||
dev_priv->next_seqno);
|
|
||||||
|
|
||||||
/* Directly dispatch request retiring. While we have the work queue
|
/* Directly dispatch request retiring. While we have the work queue
|
||||||
* to handle this, the waiter on a request often wants an associated
|
* to handle this, the waiter on a request often wants an associated
|
||||||
* buffer to have made it to the inactive list, and we would need
|
* buffer to have made it to the inactive list, and we would need
|
||||||
@ -3069,10 +3064,13 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = i915_gem_object_wait_rendering(obj);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Ensure that we invalidate the GPU's caches and TLBs. */
|
/* Ensure that we invalidate the GPU's caches and TLBs. */
|
||||||
obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
|
obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
|
||||||
|
return 0;
|
||||||
return i915_gem_object_wait_rendering(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +36,6 @@ static bool
|
|||||||
mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
|
mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
|
||||||
{
|
{
|
||||||
list_add(&obj->exec_list, unwind);
|
list_add(&obj->exec_list, unwind);
|
||||||
drm_gem_object_reference(&obj->base);
|
|
||||||
return drm_mm_scan_add_block(obj->gtt_space);
|
return drm_mm_scan_add_block(obj->gtt_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,21 +48,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
|
|||||||
struct drm_i915_gem_object *obj;
|
struct drm_i915_gem_object *obj;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
i915_gem_retire_requests(dev);
|
|
||||||
|
|
||||||
/* Re-check for free space after retiring requests */
|
|
||||||
if (mappable) {
|
|
||||||
if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
|
|
||||||
min_size, alignment, 0,
|
|
||||||
dev_priv->mm.gtt_mappable_end,
|
|
||||||
0))
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
if (drm_mm_search_free(&dev_priv->mm.gtt_space,
|
|
||||||
min_size, alignment, 0))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace_i915_gem_evict(dev, min_size, alignment, mappable);
|
trace_i915_gem_evict(dev, min_size, alignment, mappable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -139,7 +123,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
|
|||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
list_del_init(&obj->exec_list);
|
list_del_init(&obj->exec_list);
|
||||||
drm_gem_object_unreference(&obj->base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We expect the caller to unpin, evict all and try again, or give up.
|
/* We expect the caller to unpin, evict all and try again, or give up.
|
||||||
@ -158,10 +141,10 @@ found:
|
|||||||
exec_list);
|
exec_list);
|
||||||
if (drm_mm_scan_remove_block(obj->gtt_space)) {
|
if (drm_mm_scan_remove_block(obj->gtt_space)) {
|
||||||
list_move(&obj->exec_list, &eviction_list);
|
list_move(&obj->exec_list, &eviction_list);
|
||||||
|
drm_gem_object_reference(&obj->base);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
list_del_init(&obj->exec_list);
|
list_del_init(&obj->exec_list);
|
||||||
drm_gem_object_unreference(&obj->base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unbinding will emit any required flushes */
|
/* Unbinding will emit any required flushes */
|
||||||
|
@ -669,7 +669,7 @@ intel_parse_bios(struct drm_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!vbt) {
|
if (!vbt) {
|
||||||
DRM_ERROR("VBT signature missing\n");
|
DRM_DEBUG_DRIVER("VBT signature missing\n");
|
||||||
pci_unmap_rom(pdev, bios);
|
pci_unmap_rom(pdev, bios);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -9049,8 +9049,6 @@ struct intel_quirk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct intel_quirk intel_quirks[] = {
|
struct intel_quirk intel_quirks[] = {
|
||||||
/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
|
|
||||||
{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
|
|
||||||
/* HP Mini needs pipe A force quirk (LP: #322104) */
|
/* HP Mini needs pipe A force quirk (LP: #322104) */
|
||||||
{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
|
{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ struct intel_dp {
|
|||||||
uint32_t DP;
|
uint32_t DP;
|
||||||
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
||||||
bool has_audio;
|
bool has_audio;
|
||||||
int force_audio;
|
enum hdmi_force_audio force_audio;
|
||||||
uint32_t color_range;
|
uint32_t color_range;
|
||||||
int dpms_mode;
|
int dpms_mode;
|
||||||
uint8_t link_bw;
|
uint8_t link_bw;
|
||||||
@ -2116,8 +2116,8 @@ intel_dp_detect(struct drm_connector *connector, bool force)
|
|||||||
if (status != connector_status_connected)
|
if (status != connector_status_connected)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (intel_dp->force_audio) {
|
if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
|
||||||
intel_dp->has_audio = intel_dp->force_audio > 0;
|
intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
|
||||||
} else {
|
} else {
|
||||||
edid = intel_dp_get_edid(connector, &intel_dp->adapter);
|
edid = intel_dp_get_edid(connector, &intel_dp->adapter);
|
||||||
if (edid) {
|
if (edid) {
|
||||||
@ -2217,10 +2217,10 @@ intel_dp_set_property(struct drm_connector *connector,
|
|||||||
|
|
||||||
intel_dp->force_audio = i;
|
intel_dp->force_audio = i;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == HDMI_AUDIO_AUTO)
|
||||||
has_audio = intel_dp_detect_audio(connector);
|
has_audio = intel_dp_detect_audio(connector);
|
||||||
else
|
else
|
||||||
has_audio = i > 0;
|
has_audio = (i == HDMI_AUDIO_ON);
|
||||||
|
|
||||||
if (has_audio == intel_dp->has_audio)
|
if (has_audio == intel_dp->has_audio)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,13 +45,6 @@ to_intel_gmbus(struct i2c_adapter *i2c)
|
|||||||
return container_of(i2c, struct intel_gmbus, adapter);
|
return container_of(i2c, struct intel_gmbus, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct intel_gpio {
|
|
||||||
struct i2c_adapter adapter;
|
|
||||||
struct i2c_algo_bit_data algo;
|
|
||||||
struct drm_i915_private *dev_priv;
|
|
||||||
u32 reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
intel_i2c_reset(struct drm_device *dev)
|
intel_i2c_reset(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@ -78,15 +71,15 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
|
|||||||
I915_WRITE(DSPCLK_GATE_D, val);
|
I915_WRITE(DSPCLK_GATE_D, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 get_reserved(struct intel_gpio *gpio)
|
static u32 get_reserved(struct intel_gmbus *bus)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
struct drm_device *dev = dev_priv->dev;
|
struct drm_device *dev = dev_priv->dev;
|
||||||
u32 reserved = 0;
|
u32 reserved = 0;
|
||||||
|
|
||||||
/* On most chips, these bits must be preserved in software. */
|
/* On most chips, these bits must be preserved in software. */
|
||||||
if (!IS_I830(dev) && !IS_845G(dev))
|
if (!IS_I830(dev) && !IS_845G(dev))
|
||||||
reserved = I915_READ_NOTRACE(gpio->reg) &
|
reserved = I915_READ_NOTRACE(bus->gpio_reg) &
|
||||||
(GPIO_DATA_PULLUP_DISABLE |
|
(GPIO_DATA_PULLUP_DISABLE |
|
||||||
GPIO_CLOCK_PULLUP_DISABLE);
|
GPIO_CLOCK_PULLUP_DISABLE);
|
||||||
|
|
||||||
@ -95,29 +88,29 @@ static u32 get_reserved(struct intel_gpio *gpio)
|
|||||||
|
|
||||||
static int get_clock(void *data)
|
static int get_clock(void *data)
|
||||||
{
|
{
|
||||||
struct intel_gpio *gpio = data;
|
struct intel_gmbus *bus = data;
|
||||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
u32 reserved = get_reserved(gpio);
|
u32 reserved = get_reserved(bus);
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK);
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved);
|
||||||
return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
|
return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_data(void *data)
|
static int get_data(void *data)
|
||||||
{
|
{
|
||||||
struct intel_gpio *gpio = data;
|
struct intel_gmbus *bus = data;
|
||||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
u32 reserved = get_reserved(gpio);
|
u32 reserved = get_reserved(bus);
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK);
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved);
|
||||||
return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
|
return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_clock(void *data, int state_high)
|
static void set_clock(void *data, int state_high)
|
||||||
{
|
{
|
||||||
struct intel_gpio *gpio = data;
|
struct intel_gmbus *bus = data;
|
||||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
u32 reserved = get_reserved(gpio);
|
u32 reserved = get_reserved(bus);
|
||||||
u32 clock_bits;
|
u32 clock_bits;
|
||||||
|
|
||||||
if (state_high)
|
if (state_high)
|
||||||
@ -126,15 +119,15 @@ static void set_clock(void *data, int state_high)
|
|||||||
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
|
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
|
||||||
GPIO_CLOCK_VAL_MASK;
|
GPIO_CLOCK_VAL_MASK;
|
||||||
|
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | clock_bits);
|
||||||
POSTING_READ(gpio->reg);
|
POSTING_READ(bus->gpio_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_data(void *data, int state_high)
|
static void set_data(void *data, int state_high)
|
||||||
{
|
{
|
||||||
struct intel_gpio *gpio = data;
|
struct intel_gmbus *bus = data;
|
||||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
u32 reserved = get_reserved(gpio);
|
u32 reserved = get_reserved(bus);
|
||||||
u32 data_bits;
|
u32 data_bits;
|
||||||
|
|
||||||
if (state_high)
|
if (state_high)
|
||||||
@ -143,13 +136,14 @@ static void set_data(void *data, int state_high)
|
|||||||
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
|
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
|
||||||
GPIO_DATA_VAL_MASK;
|
GPIO_DATA_VAL_MASK;
|
||||||
|
|
||||||
I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits);
|
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | data_bits);
|
||||||
POSTING_READ(gpio->reg);
|
POSTING_READ(bus->gpio_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct i2c_adapter *
|
static bool
|
||||||
intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
|
intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
|
||||||
{
|
{
|
||||||
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
static const int map_pin_to_reg[] = {
|
static const int map_pin_to_reg[] = {
|
||||||
0,
|
0,
|
||||||
GPIOB,
|
GPIOB,
|
||||||
@ -160,65 +154,48 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
|
|||||||
0,
|
0,
|
||||||
GPIOF,
|
GPIOF,
|
||||||
};
|
};
|
||||||
struct intel_gpio *gpio;
|
struct i2c_algo_bit_data *algo;
|
||||||
|
|
||||||
if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
|
if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
|
algo = &bus->bit_algo;
|
||||||
if (gpio == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
gpio->reg = map_pin_to_reg[pin];
|
bus->gpio_reg = map_pin_to_reg[pin];
|
||||||
if (HAS_PCH_SPLIT(dev_priv->dev))
|
if (HAS_PCH_SPLIT(dev_priv->dev))
|
||||||
gpio->reg += PCH_GPIOA - GPIOA;
|
bus->gpio_reg += PCH_GPIOA - GPIOA;
|
||||||
gpio->dev_priv = dev_priv;
|
|
||||||
|
|
||||||
snprintf(gpio->adapter.name, sizeof(gpio->adapter.name),
|
bus->adapter.algo_data = algo;
|
||||||
"i915 GPIO%c", "?BACDE?F"[pin]);
|
algo->setsda = set_data;
|
||||||
gpio->adapter.owner = THIS_MODULE;
|
algo->setscl = set_clock;
|
||||||
gpio->adapter.algo_data = &gpio->algo;
|
algo->getsda = get_data;
|
||||||
gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
|
algo->getscl = get_clock;
|
||||||
gpio->algo.setsda = set_data;
|
algo->udelay = I2C_RISEFALL_TIME;
|
||||||
gpio->algo.setscl = set_clock;
|
algo->timeout = usecs_to_jiffies(2200);
|
||||||
gpio->algo.getsda = get_data;
|
algo->data = bus;
|
||||||
gpio->algo.getscl = get_clock;
|
|
||||||
gpio->algo.udelay = I2C_RISEFALL_TIME;
|
|
||||||
gpio->algo.timeout = usecs_to_jiffies(2200);
|
|
||||||
gpio->algo.data = gpio;
|
|
||||||
|
|
||||||
if (i2c_bit_add_bus(&gpio->adapter))
|
return true;
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
return &gpio->adapter;
|
|
||||||
|
|
||||||
out_free:
|
|
||||||
kfree(gpio);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv,
|
intel_i2c_quirk_xfer(struct intel_gmbus *bus,
|
||||||
struct i2c_adapter *adapter,
|
|
||||||
struct i2c_msg *msgs,
|
struct i2c_msg *msgs,
|
||||||
int num)
|
int num)
|
||||||
{
|
{
|
||||||
struct intel_gpio *gpio = container_of(adapter,
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
struct intel_gpio,
|
|
||||||
adapter);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
intel_i2c_reset(dev_priv->dev);
|
intel_i2c_reset(dev_priv->dev);
|
||||||
|
|
||||||
intel_i2c_quirk_set(dev_priv, true);
|
intel_i2c_quirk_set(dev_priv, true);
|
||||||
set_data(gpio, 1);
|
set_data(bus, 1);
|
||||||
set_clock(gpio, 1);
|
set_clock(bus, 1);
|
||||||
udelay(I2C_RISEFALL_TIME);
|
udelay(I2C_RISEFALL_TIME);
|
||||||
|
|
||||||
ret = adapter->algo->master_xfer(adapter, msgs, num);
|
ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num);
|
||||||
|
|
||||||
set_data(gpio, 1);
|
set_data(bus, 1);
|
||||||
set_clock(gpio, 1);
|
set_clock(bus, 1);
|
||||||
intel_i2c_quirk_set(dev_priv, false);
|
intel_i2c_quirk_set(dev_priv, false);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -232,14 +209,13 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
|||||||
struct intel_gmbus *bus = container_of(adapter,
|
struct intel_gmbus *bus = container_of(adapter,
|
||||||
struct intel_gmbus,
|
struct intel_gmbus,
|
||||||
adapter);
|
adapter);
|
||||||
struct drm_i915_private *dev_priv = adapter->algo_data;
|
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||||
int i, reg_offset, ret;
|
int i, reg_offset, ret;
|
||||||
|
|
||||||
mutex_lock(&dev_priv->gmbus_mutex);
|
mutex_lock(&dev_priv->gmbus_mutex);
|
||||||
|
|
||||||
if (bus->force_bit) {
|
if (bus->force_bit) {
|
||||||
ret = intel_i2c_quirk_xfer(dev_priv,
|
ret = intel_i2c_quirk_xfer(bus, msgs, num);
|
||||||
bus->force_bit, msgs, num);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +229,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
|||||||
|
|
||||||
if (msgs[i].flags & I2C_M_RD) {
|
if (msgs[i].flags & I2C_M_RD) {
|
||||||
I915_WRITE(GMBUS1 + reg_offset,
|
I915_WRITE(GMBUS1 + reg_offset,
|
||||||
GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
|
GMBUS_CYCLE_WAIT |
|
||||||
|
(i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
|
||||||
(len << GMBUS_BYTE_COUNT_SHIFT) |
|
(len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||||
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||||
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
|
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
|
||||||
@ -282,7 +259,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
|||||||
|
|
||||||
I915_WRITE(GMBUS3 + reg_offset, val);
|
I915_WRITE(GMBUS3 + reg_offset, val);
|
||||||
I915_WRITE(GMBUS1 + reg_offset,
|
I915_WRITE(GMBUS1 + reg_offset,
|
||||||
(i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) |
|
GMBUS_CYCLE_WAIT |
|
||||||
|
(i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
|
||||||
(msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
|
(msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||||
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||||
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
|
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
|
||||||
@ -321,9 +299,12 @@ clear_err:
|
|||||||
I915_WRITE(GMBUS1 + reg_offset, 0);
|
I915_WRITE(GMBUS1 + reg_offset, 0);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Mark the GMBUS interface as disabled. We will re-enable it at the
|
/* Mark the GMBUS interface as disabled after waiting for idle.
|
||||||
* start of the next xfer, till then let it sleep.
|
* We will re-enable it at the start of the next xfer,
|
||||||
|
* till then let it sleep.
|
||||||
*/
|
*/
|
||||||
|
if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10))
|
||||||
|
DRM_INFO("GMBUS timed out waiting for idle\n");
|
||||||
I915_WRITE(GMBUS0 + reg_offset, 0);
|
I915_WRITE(GMBUS0 + reg_offset, 0);
|
||||||
ret = i;
|
ret = i;
|
||||||
goto out;
|
goto out;
|
||||||
@ -334,11 +315,12 @@ timeout:
|
|||||||
I915_WRITE(GMBUS0 + reg_offset, 0);
|
I915_WRITE(GMBUS0 + reg_offset, 0);
|
||||||
|
|
||||||
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
|
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
|
||||||
bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
|
if (!bus->has_gpio) {
|
||||||
if (!bus->force_bit)
|
ret = -EIO;
|
||||||
ret = -ENOMEM;
|
} else {
|
||||||
else
|
bus->force_bit = true;
|
||||||
ret = intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num);
|
ret = intel_i2c_quirk_xfer(bus, msgs, num);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
@ -346,14 +328,8 @@ out:
|
|||||||
|
|
||||||
static u32 gmbus_func(struct i2c_adapter *adapter)
|
static u32 gmbus_func(struct i2c_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct intel_gmbus *bus = container_of(adapter,
|
return i2c_bit_algo.functionality(adapter) &
|
||||||
struct intel_gmbus,
|
(I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||||
adapter);
|
|
||||||
|
|
||||||
if (bus->force_bit)
|
|
||||||
bus->force_bit->algo->functionality(bus->force_bit);
|
|
||||||
|
|
||||||
return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
|
||||||
/* I2C_FUNC_10BIT_ADDR | */
|
/* I2C_FUNC_10BIT_ADDR | */
|
||||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL);
|
I2C_FUNC_SMBUS_BLOCK_PROC_CALL);
|
||||||
@ -401,7 +377,7 @@ int intel_setup_gmbus(struct drm_device *dev)
|
|||||||
names[i]);
|
names[i]);
|
||||||
|
|
||||||
bus->adapter.dev.parent = &dev->pdev->dev;
|
bus->adapter.dev.parent = &dev->pdev->dev;
|
||||||
bus->adapter.algo_data = dev_priv;
|
bus->dev_priv = dev_priv;
|
||||||
|
|
||||||
bus->adapter.algo = &gmbus_algorithm;
|
bus->adapter.algo = &gmbus_algorithm;
|
||||||
ret = i2c_add_adapter(&bus->adapter);
|
ret = i2c_add_adapter(&bus->adapter);
|
||||||
@ -411,8 +387,11 @@ int intel_setup_gmbus(struct drm_device *dev)
|
|||||||
/* By default use a conservative clock rate */
|
/* By default use a conservative clock rate */
|
||||||
bus->reg0 = i | GMBUS_RATE_100KHZ;
|
bus->reg0 = i | GMBUS_RATE_100KHZ;
|
||||||
|
|
||||||
|
bus->has_gpio = intel_gpio_setup(bus, i);
|
||||||
|
|
||||||
/* XXX force bit banging until GMBUS is fully debugged */
|
/* XXX force bit banging until GMBUS is fully debugged */
|
||||||
bus->force_bit = intel_gpio_create(dev_priv, i);
|
if (bus->has_gpio && IS_GEN2(dev))
|
||||||
|
bus->force_bit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_i2c_reset(dev_priv->dev);
|
intel_i2c_reset(dev_priv->dev);
|
||||||
@ -440,19 +419,8 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
|
|||||||
{
|
{
|
||||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||||
|
|
||||||
if (force_bit) {
|
if (bus->has_gpio)
|
||||||
if (bus->force_bit == NULL) {
|
bus->force_bit = force_bit;
|
||||||
struct drm_i915_private *dev_priv = adapter->algo_data;
|
|
||||||
bus->force_bit = intel_gpio_create(dev_priv,
|
|
||||||
bus->reg0 & 0xff);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (bus->force_bit) {
|
|
||||||
i2c_del_adapter(bus->force_bit);
|
|
||||||
kfree(bus->force_bit);
|
|
||||||
bus->force_bit = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_teardown_gmbus(struct drm_device *dev)
|
void intel_teardown_gmbus(struct drm_device *dev)
|
||||||
@ -465,10 +433,6 @@ void intel_teardown_gmbus(struct drm_device *dev)
|
|||||||
|
|
||||||
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
|
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
|
||||||
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
||||||
if (bus->force_bit) {
|
|
||||||
i2c_del_adapter(bus->force_bit);
|
|
||||||
kfree(bus->force_bit);
|
|
||||||
}
|
|
||||||
i2c_del_adapter(&bus->adapter);
|
i2c_del_adapter(&bus->adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,6 +739,22 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
|||||||
DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
|
DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = intel_no_lvds_dmi_callback,
|
||||||
|
.ident = "Hewlett-Packard t5745",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "hp t5745"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.callback = intel_no_lvds_dmi_callback,
|
||||||
|
.ident = "Hewlett-Packard st5747",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "hp st5747"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{ } /* terminating entry */
|
{ } /* terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -148,7 +148,7 @@ struct intel_sdvo_connector {
|
|||||||
/* Mark the type of connector */
|
/* Mark the type of connector */
|
||||||
uint16_t output_flag;
|
uint16_t output_flag;
|
||||||
|
|
||||||
int force_audio;
|
enum hdmi_force_audio force_audio;
|
||||||
|
|
||||||
/* This contains all current supported TV format */
|
/* This contains all current supported TV format */
|
||||||
u8 tv_format_supported[TV_FORMAT_NUM];
|
u8 tv_format_supported[TV_FORMAT_NUM];
|
||||||
@ -1309,8 +1309,8 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
|
|||||||
|
|
||||||
if (status == connector_status_connected) {
|
if (status == connector_status_connected) {
|
||||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||||
if (intel_sdvo_connector->force_audio)
|
if (intel_sdvo_connector->force_audio != HDMI_AUDIO_AUTO)
|
||||||
intel_sdvo->has_hdmi_audio = intel_sdvo_connector->force_audio > 0;
|
intel_sdvo->has_hdmi_audio = (intel_sdvo_connector->force_audio == HDMI_AUDIO_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -1683,10 +1683,10 @@ intel_sdvo_set_property(struct drm_connector *connector,
|
|||||||
|
|
||||||
intel_sdvo_connector->force_audio = i;
|
intel_sdvo_connector->force_audio = i;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == HDMI_AUDIO_AUTO)
|
||||||
has_audio = intel_sdvo_detect_hdmi_audio(connector);
|
has_audio = intel_sdvo_detect_hdmi_audio(connector);
|
||||||
else
|
else
|
||||||
has_audio = i > 0;
|
has_audio = (i == HDMI_AUDIO_ON);
|
||||||
|
|
||||||
if (has_audio == intel_sdvo->has_hdmi_audio)
|
if (has_audio == intel_sdvo->has_hdmi_audio)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -277,7 +277,7 @@ i2c_bit_func(struct i2c_adapter *adap)
|
|||||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct i2c_algorithm i2c_bit_algo = {
|
const struct i2c_algorithm nouveau_i2c_bit_algo = {
|
||||||
.master_xfer = i2c_bit_xfer,
|
.master_xfer = i2c_bit_xfer,
|
||||||
.functionality = i2c_bit_func
|
.functionality = i2c_bit_func
|
||||||
};
|
};
|
||||||
@ -384,12 +384,12 @@ nouveau_i2c_init(struct drm_device *dev)
|
|||||||
case 0: /* NV04:NV50 */
|
case 0: /* NV04:NV50 */
|
||||||
port->drive = entry[0];
|
port->drive = entry[0];
|
||||||
port->sense = entry[1];
|
port->sense = entry[1];
|
||||||
port->adapter.algo = &i2c_bit_algo;
|
port->adapter.algo = &nouveau_i2c_bit_algo;
|
||||||
break;
|
break;
|
||||||
case 4: /* NV4E */
|
case 4: /* NV4E */
|
||||||
port->drive = 0x600800 + entry[1];
|
port->drive = 0x600800 + entry[1];
|
||||||
port->sense = port->drive;
|
port->sense = port->drive;
|
||||||
port->adapter.algo = &i2c_bit_algo;
|
port->adapter.algo = &nouveau_i2c_bit_algo;
|
||||||
break;
|
break;
|
||||||
case 5: /* NV50- */
|
case 5: /* NV50- */
|
||||||
port->drive = entry[0] & 0x0f;
|
port->drive = entry[0] & 0x0f;
|
||||||
@ -402,7 +402,7 @@ nouveau_i2c_init(struct drm_device *dev)
|
|||||||
port->drive = 0x00d014 + (port->drive * 0x20);
|
port->drive = 0x00d014 + (port->drive * 0x20);
|
||||||
port->sense = port->drive;
|
port->sense = port->drive;
|
||||||
}
|
}
|
||||||
port->adapter.algo = &i2c_bit_algo;
|
port->adapter.algo = &nouveau_i2c_bit_algo;
|
||||||
break;
|
break;
|
||||||
case 6: /* NV50- DP AUX */
|
case 6: /* NV50- DP AUX */
|
||||||
port->drive = entry[0];
|
port->drive = entry[0];
|
||||||
|
@ -610,10 +610,11 @@ static u32 bit_func(struct i2c_adapter *adap)
|
|||||||
|
|
||||||
/* -----exported algorithm data: ------------------------------------- */
|
/* -----exported algorithm data: ------------------------------------- */
|
||||||
|
|
||||||
static const struct i2c_algorithm i2c_bit_algo = {
|
const struct i2c_algorithm i2c_bit_algo = {
|
||||||
.master_xfer = bit_xfer,
|
.master_xfer = bit_xfer,
|
||||||
.functionality = bit_func,
|
.functionality = bit_func,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL(i2c_bit_algo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* registering functions to load algorithms at runtime
|
* registering functions to load algorithms at runtime
|
||||||
|
@ -49,5 +49,6 @@ struct i2c_algo_bit_data {
|
|||||||
|
|
||||||
int i2c_bit_add_bus(struct i2c_adapter *);
|
int i2c_bit_add_bus(struct i2c_adapter *);
|
||||||
int i2c_bit_add_numbered_bus(struct i2c_adapter *);
|
int i2c_bit_add_numbered_bus(struct i2c_adapter *);
|
||||||
|
extern const struct i2c_algorithm i2c_bit_algo;
|
||||||
|
|
||||||
#endif /* _LINUX_I2C_ALGO_BIT_H */
|
#endif /* _LINUX_I2C_ALGO_BIT_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user