mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (50 commits) drm: include kernel list header file in hashtab header drm: Export hash table functionality. drm: Split out the mm declarations in a separate header. Add atomic operations. drm/radeon: add support for RV790. drm/radeon: add rv740 drm support. drm_calloc_large: check right size, check integer overflow, use GFP_ZERO drm: Eliminate magic I2C frobbing when reading EDID drm/i915: duplicate desired mode for use by fbcon. drm/via: vfree() no need checking before calling it drm: Replace DRM_DEBUG with DRM_DEBUG_DRIVER in i915 driver drm: Replace DRM_DEBUG with DRM_DEBUG_MODE in drm_mode drm/i915: Replace DRM_DEBUG with DRM_DEBUG_KMS in intel_sdvo drm/i915: replace DRM_DEBUG with DRM_DEBUG_KMS in intel_lvds drm: add separate drm debugging levels radeon: remove _DRM_DRIVER from the preadded sarea map drm: don't associate _DRM_DRIVER maps with a master drm: simplify kcalloc() call to kzalloc(). intelfb: fix spelling of "CLOCK" drm: fix LOCK_TEST_WITH_RETURN macro drm/i915: Hook connector to encoder during load detection (fixes tv/vga detect) ...
This commit is contained in:
commit
6b702462cb
@ -46,6 +46,10 @@
|
||||
#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
|
||||
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
|
||||
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
|
||||
#define PCI_DEVICE_ID_INTEL_IGDNG_D_HB 0x0040
|
||||
#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042
|
||||
#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044
|
||||
#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046
|
||||
|
||||
/* cover 915 and 945 variants */
|
||||
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
|
||||
@ -75,7 +79,9 @@
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB)
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB)
|
||||
|
||||
extern int agp_memory_reserved;
|
||||
|
||||
@ -1211,6 +1217,8 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
||||
case PCI_DEVICE_ID_INTEL_Q45_HB:
|
||||
case PCI_DEVICE_ID_INTEL_G45_HB:
|
||||
case PCI_DEVICE_ID_INTEL_G41_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
|
||||
*gtt_offset = *gtt_size = MB(2);
|
||||
break;
|
||||
default:
|
||||
@ -2186,6 +2194,10 @@ static const struct intel_driver_description {
|
||||
"G45/G43", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
|
||||
"G41", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0,
|
||||
"IGDNG/D", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
|
||||
"IGDNG/M", NULL, &intel_i965_driver },
|
||||
{ 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -2387,6 +2399,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
||||
ID(PCI_DEVICE_ID_INTEL_Q45_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_G45_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_G41_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -371,7 +371,8 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
||||
list->user_token = list->hash.key << PAGE_SHIFT;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
list->master = dev->primary->master;
|
||||
if (!(map->flags & _DRM_DRIVER))
|
||||
list->master = dev->primary->master;
|
||||
*maplist = list;
|
||||
return 0;
|
||||
}
|
||||
|
@ -589,85 +589,13 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_do_probe_ddc_edid);
|
||||
|
||||
/**
|
||||
* Get EDID information.
|
||||
*
|
||||
* \param adapter : i2c device adaptor.
|
||||
* \param buf : EDID data buffer to be filled
|
||||
* \param len : EDID data buffer length
|
||||
* \return 0 on success or -1 on failure.
|
||||
*
|
||||
* Initialize DDC, then fetch EDID information
|
||||
* by calling drm_do_probe_ddc_edid function.
|
||||
*/
|
||||
static int drm_ddc_read(struct i2c_adapter *adapter,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
struct i2c_algo_bit_data *algo_data = adapter->algo_data;
|
||||
int i, j;
|
||||
int ret = -1;
|
||||
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
|
||||
for (i = 0; i < 1; i++) {
|
||||
/* For some old monitors we need the
|
||||
* following process to initialize/stop DDC
|
||||
*/
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
msleep(13);
|
||||
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
for (j = 0; j < 5; j++) {
|
||||
msleep(10);
|
||||
if (algo_data->getscl(algo_data->data))
|
||||
break;
|
||||
}
|
||||
if (j == 5)
|
||||
continue;
|
||||
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
msleep(15);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
msleep(15);
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
msleep(15);
|
||||
|
||||
/* Do the real work */
|
||||
ret = drm_do_probe_ddc_edid(adapter, buf, len);
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
msleep(15);
|
||||
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
for (j = 0; j < 10; j++) {
|
||||
msleep(10);
|
||||
if (algo_data->getscl(algo_data->data))
|
||||
break;
|
||||
}
|
||||
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
msleep(15);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
/* Release the DDC lines when done or the Apple Cinema HD display
|
||||
* will switch off
|
||||
*/
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int drm_ddc_read_edid(struct drm_connector *connector,
|
||||
struct i2c_adapter *adapter,
|
||||
char *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_ddc_read(adapter, buf, len);
|
||||
ret = drm_do_probe_ddc_edid(adapter, buf, len);
|
||||
if (ret != 0) {
|
||||
dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
|
||||
drm_get_connector_name(connector));
|
||||
|
@ -133,7 +133,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
|
||||
|
||||
BUG_ON((size & (PAGE_SIZE - 1)) != 0);
|
||||
|
||||
obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
|
||||
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
|
||||
|
||||
obj->dev = dev;
|
||||
obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
|
||||
|
@ -62,6 +62,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ht_create);
|
||||
|
||||
void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
|
||||
{
|
||||
@ -156,6 +157,7 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ht_just_insert_please);
|
||||
|
||||
int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
|
||||
struct drm_hash_item **item)
|
||||
@ -169,6 +171,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
|
||||
*item = hlist_entry(list, struct drm_hash_item, head);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ht_find_item);
|
||||
|
||||
int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
|
||||
{
|
||||
@ -202,3 +205,4 @@ void drm_ht_remove(struct drm_open_hash *ht)
|
||||
ht->table = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ht_remove);
|
||||
|
@ -42,8 +42,11 @@
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_mm.h"
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define MM_UNUSED_TARGET 4
|
||||
|
||||
unsigned long drm_mm_tail_space(struct drm_mm *mm)
|
||||
{
|
||||
struct list_head *tail_node;
|
||||
@ -74,16 +77,62 @@ int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int drm_mm_create_tail_node(struct drm_mm *mm,
|
||||
unsigned long start,
|
||||
unsigned long size)
|
||||
static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
|
||||
{
|
||||
struct drm_mm_node *child;
|
||||
|
||||
child = (struct drm_mm_node *)
|
||||
drm_alloc(sizeof(*child), DRM_MEM_MM);
|
||||
if (!child)
|
||||
if (atomic)
|
||||
child = kmalloc(sizeof(*child), GFP_ATOMIC);
|
||||
else
|
||||
child = kmalloc(sizeof(*child), GFP_KERNEL);
|
||||
|
||||
if (unlikely(child == NULL)) {
|
||||
spin_lock(&mm->unused_lock);
|
||||
if (list_empty(&mm->unused_nodes))
|
||||
child = NULL;
|
||||
else {
|
||||
child =
|
||||
list_entry(mm->unused_nodes.next,
|
||||
struct drm_mm_node, fl_entry);
|
||||
list_del(&child->fl_entry);
|
||||
--mm->num_unused;
|
||||
}
|
||||
spin_unlock(&mm->unused_lock);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
int drm_mm_pre_get(struct drm_mm *mm)
|
||||
{
|
||||
struct drm_mm_node *node;
|
||||
|
||||
spin_lock(&mm->unused_lock);
|
||||
while (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
spin_unlock(&mm->unused_lock);
|
||||
node = kmalloc(sizeof(*node), GFP_KERNEL);
|
||||
spin_lock(&mm->unused_lock);
|
||||
|
||||
if (unlikely(node == NULL)) {
|
||||
int ret = (mm->num_unused < 2) ? -ENOMEM : 0;
|
||||
spin_unlock(&mm->unused_lock);
|
||||
return ret;
|
||||
}
|
||||
++mm->num_unused;
|
||||
list_add_tail(&node->fl_entry, &mm->unused_nodes);
|
||||
}
|
||||
spin_unlock(&mm->unused_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_pre_get);
|
||||
|
||||
static int drm_mm_create_tail_node(struct drm_mm *mm,
|
||||
unsigned long start,
|
||||
unsigned long size, int atomic)
|
||||
{
|
||||
struct drm_mm_node *child;
|
||||
|
||||
child = drm_mm_kmalloc(mm, atomic);
|
||||
if (unlikely(child == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
child->free = 1;
|
||||
@ -97,8 +146,7 @@ static int drm_mm_create_tail_node(struct drm_mm *mm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
|
||||
int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic)
|
||||
{
|
||||
struct list_head *tail_node;
|
||||
struct drm_mm_node *entry;
|
||||
@ -106,20 +154,21 @@ int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
|
||||
tail_node = mm->ml_entry.prev;
|
||||
entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
|
||||
if (!entry->free) {
|
||||
return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
|
||||
return drm_mm_create_tail_node(mm, entry->start + entry->size,
|
||||
size, atomic);
|
||||
}
|
||||
entry->size += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
|
||||
unsigned long size)
|
||||
unsigned long size,
|
||||
int atomic)
|
||||
{
|
||||
struct drm_mm_node *child;
|
||||
|
||||
child = (struct drm_mm_node *)
|
||||
drm_alloc(sizeof(*child), DRM_MEM_MM);
|
||||
if (!child)
|
||||
child = drm_mm_kmalloc(parent->mm, atomic);
|
||||
if (unlikely(child == NULL))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&child->fl_entry);
|
||||
@ -151,8 +200,9 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
|
||||
tmp = parent->start % alignment;
|
||||
|
||||
if (tmp) {
|
||||
align_splitoff = drm_mm_split_at_start(parent, alignment - tmp);
|
||||
if (!align_splitoff)
|
||||
align_splitoff =
|
||||
drm_mm_split_at_start(parent, alignment - tmp, 0);
|
||||
if (unlikely(align_splitoff == NULL))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -161,7 +211,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
|
||||
parent->free = 0;
|
||||
return parent;
|
||||
} else {
|
||||
child = drm_mm_split_at_start(parent, size);
|
||||
child = drm_mm_split_at_start(parent, size, 0);
|
||||
}
|
||||
|
||||
if (align_splitoff)
|
||||
@ -169,14 +219,49 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_mm_get_block);
|
||||
|
||||
struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
|
||||
unsigned long size,
|
||||
unsigned alignment)
|
||||
{
|
||||
|
||||
struct drm_mm_node *align_splitoff = NULL;
|
||||
struct drm_mm_node *child;
|
||||
unsigned tmp = 0;
|
||||
|
||||
if (alignment)
|
||||
tmp = parent->start % alignment;
|
||||
|
||||
if (tmp) {
|
||||
align_splitoff =
|
||||
drm_mm_split_at_start(parent, alignment - tmp, 1);
|
||||
if (unlikely(align_splitoff == NULL))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (parent->size == size) {
|
||||
list_del_init(&parent->fl_entry);
|
||||
parent->free = 0;
|
||||
return parent;
|
||||
} else {
|
||||
child = drm_mm_split_at_start(parent, size, 1);
|
||||
}
|
||||
|
||||
if (align_splitoff)
|
||||
drm_mm_put_block(align_splitoff);
|
||||
|
||||
return child;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_get_block_atomic);
|
||||
|
||||
/*
|
||||
* Put a block. Merge with the previous and / or next block if they are free.
|
||||
* Otherwise add to the free stack.
|
||||
*/
|
||||
|
||||
void drm_mm_put_block(struct drm_mm_node * cur)
|
||||
void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
{
|
||||
|
||||
struct drm_mm *mm = cur->mm;
|
||||
@ -188,21 +273,27 @@ void drm_mm_put_block(struct drm_mm_node * cur)
|
||||
int merged = 0;
|
||||
|
||||
if (cur_head->prev != root_head) {
|
||||
prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
|
||||
prev_node =
|
||||
list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
|
||||
if (prev_node->free) {
|
||||
prev_node->size += cur->size;
|
||||
merged = 1;
|
||||
}
|
||||
}
|
||||
if (cur_head->next != root_head) {
|
||||
next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
|
||||
next_node =
|
||||
list_entry(cur_head->next, struct drm_mm_node, ml_entry);
|
||||
if (next_node->free) {
|
||||
if (merged) {
|
||||
prev_node->size += next_node->size;
|
||||
list_del(&next_node->ml_entry);
|
||||
list_del(&next_node->fl_entry);
|
||||
drm_free(next_node, sizeof(*next_node),
|
||||
DRM_MEM_MM);
|
||||
if (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
list_add(&next_node->fl_entry,
|
||||
&mm->unused_nodes);
|
||||
++mm->num_unused;
|
||||
} else
|
||||
kfree(next_node);
|
||||
} else {
|
||||
next_node->size += cur->size;
|
||||
next_node->start = cur->start;
|
||||
@ -215,14 +306,19 @@ void drm_mm_put_block(struct drm_mm_node * cur)
|
||||
list_add(&cur->fl_entry, &mm->fl_entry);
|
||||
} else {
|
||||
list_del(&cur->ml_entry);
|
||||
drm_free(cur, sizeof(*cur), DRM_MEM_MM);
|
||||
if (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
list_add(&cur->fl_entry, &mm->unused_nodes);
|
||||
++mm->num_unused;
|
||||
} else
|
||||
kfree(cur);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_mm_put_block);
|
||||
|
||||
struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
|
||||
unsigned long size,
|
||||
unsigned alignment, int best_match)
|
||||
struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
|
||||
unsigned long size,
|
||||
unsigned alignment, int best_match)
|
||||
{
|
||||
struct list_head *list;
|
||||
const struct list_head *free_stack = &mm->fl_entry;
|
||||
@ -247,7 +343,6 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
|
||||
wasted += alignment - tmp;
|
||||
}
|
||||
|
||||
|
||||
if (entry->size >= size + wasted) {
|
||||
if (!best_match)
|
||||
return entry;
|
||||
@ -260,6 +355,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
|
||||
|
||||
return best;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_search_free);
|
||||
|
||||
int drm_mm_clean(struct drm_mm * mm)
|
||||
{
|
||||
@ -267,14 +363,17 @@ int drm_mm_clean(struct drm_mm * mm)
|
||||
|
||||
return (head->next->next == head);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_search_free);
|
||||
EXPORT_SYMBOL(drm_mm_clean);
|
||||
|
||||
int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
|
||||
{
|
||||
INIT_LIST_HEAD(&mm->ml_entry);
|
||||
INIT_LIST_HEAD(&mm->fl_entry);
|
||||
INIT_LIST_HEAD(&mm->unused_nodes);
|
||||
mm->num_unused = 0;
|
||||
spin_lock_init(&mm->unused_lock);
|
||||
|
||||
return drm_mm_create_tail_node(mm, start, size);
|
||||
return drm_mm_create_tail_node(mm, start, size, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_init);
|
||||
|
||||
@ -282,6 +381,7 @@ void drm_mm_takedown(struct drm_mm * mm)
|
||||
{
|
||||
struct list_head *bnode = mm->fl_entry.next;
|
||||
struct drm_mm_node *entry;
|
||||
struct drm_mm_node *next;
|
||||
|
||||
entry = list_entry(bnode, struct drm_mm_node, fl_entry);
|
||||
|
||||
@ -293,7 +393,16 @@ void drm_mm_takedown(struct drm_mm * mm)
|
||||
|
||||
list_del(&entry->fl_entry);
|
||||
list_del(&entry->ml_entry);
|
||||
kfree(entry);
|
||||
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_MM);
|
||||
spin_lock(&mm->unused_lock);
|
||||
list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) {
|
||||
list_del(&entry->fl_entry);
|
||||
kfree(entry);
|
||||
--mm->num_unused;
|
||||
}
|
||||
spin_unlock(&mm->unused_lock);
|
||||
|
||||
BUG_ON(mm->num_unused != 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_takedown);
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
|
||||
#define DRM_MODESET_DEBUG "drm_mode"
|
||||
/**
|
||||
* drm_mode_debug_printmodeline - debug print a mode
|
||||
* @dev: DRM device
|
||||
@ -50,12 +51,13 @@
|
||||
*/
|
||||
void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
|
||||
mode->base.id, mode->name, mode->vrefresh, mode->clock,
|
||||
mode->hdisplay, mode->hsync_start,
|
||||
mode->hsync_end, mode->htotal,
|
||||
mode->vdisplay, mode->vsync_start,
|
||||
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
|
||||
DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
|
||||
"Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
|
||||
mode->base.id, mode->name, mode->vrefresh, mode->clock,
|
||||
mode->hdisplay, mode->hsync_start,
|
||||
mode->hsync_end, mode->htotal,
|
||||
mode->vdisplay, mode->vsync_start,
|
||||
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_debug_printmodeline);
|
||||
|
||||
@ -401,7 +403,9 @@ void drm_mode_prune_invalid(struct drm_device *dev,
|
||||
list_del(&mode->head);
|
||||
if (verbose) {
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status);
|
||||
DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
|
||||
"Not using %s mode %d\n",
|
||||
mode->name, mode->status);
|
||||
}
|
||||
drm_mode_destroy(dev, mode);
|
||||
}
|
||||
|
@ -51,7 +51,22 @@ struct idr drm_minors_idr;
|
||||
struct class *drm_class;
|
||||
struct proc_dir_entry *drm_proc_root;
|
||||
struct dentry *drm_debugfs_root;
|
||||
void drm_ut_debug_printk(unsigned int request_level,
|
||||
const char *prefix,
|
||||
const char *function_name,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (drm_debug & request_level) {
|
||||
if (function_name)
|
||||
printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
|
||||
va_start(args, format);
|
||||
vprintk(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ut_debug_printk);
|
||||
static int drm_minor_get_id(struct drm_device *dev, int type)
|
||||
{
|
||||
int new_id;
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define I915_DRV "i915_drv"
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
* the head pointer changes, so that EBUSY only happens if the ring
|
||||
@ -99,7 +101,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
|
||||
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -185,7 +187,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
||||
master_priv->sarea_priv = (drm_i915_sarea_t *)
|
||||
((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
|
||||
} else {
|
||||
DRM_DEBUG("sarea not found assuming DRI2 userspace\n");
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"sarea not found assuming DRI2 userspace\n");
|
||||
}
|
||||
|
||||
if (init->ring_size != 0) {
|
||||
@ -235,7 +238,7 @@ static int i915_dma_resume(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __func__);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
@ -248,13 +251,14 @@ static int i915_dma_resume(struct drm_device * dev)
|
||||
DRM_ERROR("Can not find hardware status page\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "hw status page @ %p\n",
|
||||
dev_priv->hw_status_page);
|
||||
|
||||
if (dev_priv->status_gfx_addr != 0)
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
else
|
||||
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -548,10 +552,10 @@ static int i915_dispatch_flip(struct drm_device * dev)
|
||||
if (!master_priv->sarea_priv)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__func__,
|
||||
dev_priv->current_page,
|
||||
master_priv->sarea_priv->pf_current_page);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
|
||||
__func__,
|
||||
dev_priv->current_page,
|
||||
master_priv->sarea_priv->pf_current_page);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
@ -629,8 +633,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch->start, batch->used, batch->num_cliprects);
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch->start, batch->used, batch->num_cliprects);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
@ -678,8 +683,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
||||
void *batch_data;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
@ -734,7 +740,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("%s\n", __func__);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
@ -777,7 +783,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
|
||||
param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -817,7 +824,8 @@ static int i915_setparam(struct drm_device *dev, void *data,
|
||||
dev_priv->fence_reg_start = param->value;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("unknown parameter %d\n", param->param);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
|
||||
param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -865,9 +873,10 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
||||
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
|
||||
dev_priv->status_gfx_addr);
|
||||
DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
|
||||
dev_priv->status_gfx_addr);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
|
||||
dev_priv->hw_status_page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -922,7 +931,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
|
||||
* Some of the preallocated space is taken by the GTT
|
||||
* and popup. GTT is 1K per MB of aperture size, and popup is 4K.
|
||||
*/
|
||||
if (IS_G4X(dev) || IS_IGD(dev))
|
||||
if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev))
|
||||
overhead = 4096;
|
||||
else
|
||||
overhead = (*aperture_size / 1024) + 4096;
|
||||
@ -1153,8 +1162,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
#endif
|
||||
|
||||
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
||||
if (IS_GM45(dev))
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
if (IS_G4X(dev) || IS_IGDNG(dev)) {
|
||||
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
|
||||
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
|
||||
}
|
||||
|
||||
i915_gem_load(dev);
|
||||
|
||||
@ -1198,7 +1210,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
}
|
||||
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_init(dev, 0);
|
||||
/* FIXME: verify on IGDNG */
|
||||
if (!IS_IGDNG(dev))
|
||||
intel_opregion_init(dev, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1232,7 +1246,8 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
if (dev_priv->regs != NULL)
|
||||
iounmap(dev_priv->regs);
|
||||
|
||||
intel_opregion_free(dev, 0);
|
||||
if (!IS_IGDNG(dev))
|
||||
intel_opregion_free(dev, 0);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
intel_modeset_cleanup(dev);
|
||||
@ -1256,7 +1271,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_i915_file_private *i915_file_priv;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "\n");
|
||||
i915_file_priv = (struct drm_i915_file_private *)
|
||||
drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
|
||||
|
||||
@ -1265,8 +1280,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
|
||||
|
||||
file_priv->driver_priv = i915_file_priv;
|
||||
|
||||
i915_file_priv->mm.last_gem_seqno = 0;
|
||||
i915_file_priv->mm.last_gem_throttle_seqno = 0;
|
||||
INIT_LIST_HEAD(&i915_file_priv->mm.request_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1303,6 +1317,7 @@ void i915_driver_lastclose(struct drm_device * dev)
|
||||
void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_gem_release(dev, file_priv);
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_mem_release(dev, file_priv, dev_priv->agp_heap);
|
||||
}
|
||||
|
@ -126,6 +126,13 @@ struct drm_i915_fence_reg {
|
||||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
struct sdvo_device_mapping {
|
||||
u8 dvo_port;
|
||||
u8 slave_addr;
|
||||
u8 dvo_wiring;
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
|
||||
@ -143,6 +150,8 @@ typedef struct drm_i915_private {
|
||||
drm_local_map_t hws_map;
|
||||
struct drm_gem_object *hws_obj;
|
||||
|
||||
struct resource mch_res;
|
||||
|
||||
unsigned int cpp;
|
||||
int back_offset;
|
||||
int front_offset;
|
||||
@ -158,6 +167,11 @@ typedef struct drm_i915_private {
|
||||
/** Cached value of IMR to avoid reads in updating the bitfield */
|
||||
u32 irq_mask_reg;
|
||||
u32 pipestat[2];
|
||||
/** splitted irq regs for graphics and display engine on IGDNG,
|
||||
irq_mask_reg is still used for display irq. */
|
||||
u32 gt_irq_mask_reg;
|
||||
u32 gt_irq_enable_reg;
|
||||
u32 de_irq_enable_reg;
|
||||
|
||||
u32 hotplug_supported_mask;
|
||||
struct work_struct hotplug_work;
|
||||
@ -285,6 +299,13 @@ typedef struct drm_i915_private {
|
||||
u8 saveDACMASK;
|
||||
u8 saveCR[37];
|
||||
uint64_t saveFENCE[16];
|
||||
u32 saveCURACNTR;
|
||||
u32 saveCURAPOS;
|
||||
u32 saveCURABASE;
|
||||
u32 saveCURBCNTR;
|
||||
u32 saveCURBPOS;
|
||||
u32 saveCURBBASE;
|
||||
u32 saveCURSIZE;
|
||||
|
||||
struct {
|
||||
struct drm_mm gtt_space;
|
||||
@ -382,6 +403,7 @@ typedef struct drm_i915_private {
|
||||
/* storage for physical objects */
|
||||
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
|
||||
} mm;
|
||||
struct sdvo_device_mapping sdvo_mappings[2];
|
||||
} drm_i915_private_t;
|
||||
|
||||
/** driver private structure attached to each drm_gem_object */
|
||||
@ -491,13 +513,16 @@ struct drm_i915_gem_request {
|
||||
/** Time at which this request was emitted, in jiffies. */
|
||||
unsigned long emitted_jiffies;
|
||||
|
||||
/** global list entry for this request */
|
||||
struct list_head list;
|
||||
|
||||
/** file_priv list entry for this request */
|
||||
struct list_head client_list;
|
||||
};
|
||||
|
||||
struct drm_i915_file_private {
|
||||
struct {
|
||||
uint32_t last_gem_seqno;
|
||||
uint32_t last_gem_throttle_seqno;
|
||||
struct list_head request_list;
|
||||
} mm;
|
||||
};
|
||||
|
||||
@ -642,6 +667,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
|
||||
void i915_gem_free_all_phys_object(struct drm_device *dev);
|
||||
int i915_gem_object_get_pages(struct drm_gem_object *obj);
|
||||
void i915_gem_object_put_pages(struct drm_gem_object *obj);
|
||||
void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
|
||||
|
||||
/* i915_gem_tiling.c */
|
||||
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
|
||||
@ -785,7 +811,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
(dev)->pci_device == 0x2E02 || \
|
||||
(dev)->pci_device == 0x2E12 || \
|
||||
(dev)->pci_device == 0x2E22 || \
|
||||
(dev)->pci_device == 0x2E32)
|
||||
(dev)->pci_device == 0x2E32 || \
|
||||
(dev)->pci_device == 0x0042 || \
|
||||
(dev)->pci_device == 0x0046)
|
||||
|
||||
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
|
||||
(dev)->pci_device == 0x2A12)
|
||||
@ -807,20 +835,26 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
(dev)->pci_device == 0x29D2 || \
|
||||
(IS_IGD(dev)))
|
||||
|
||||
#define IS_IGDNG_D(dev) ((dev)->pci_device == 0x0042)
|
||||
#define IS_IGDNG_M(dev) ((dev)->pci_device == 0x0046)
|
||||
#define IS_IGDNG(dev) (IS_IGDNG_D(dev) || IS_IGDNG_M(dev))
|
||||
|
||||
#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
|
||||
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
|
||||
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
|
||||
IS_IGDNG(dev))
|
||||
|
||||
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
|
||||
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
|
||||
IS_IGD(dev))
|
||||
IS_IGD(dev) || IS_IGDNG_M(dev))
|
||||
|
||||
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
|
||||
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
|
||||
IS_IGDNG(dev))
|
||||
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
||||
* rows, which changed the alignment requirements and fence programming.
|
||||
*/
|
||||
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
|
||||
IS_I915GM(dev)))
|
||||
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev))
|
||||
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
|
||||
#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
|
||||
|
||||
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
||||
|
@ -989,10 +989,10 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
||||
return -ENODEV;
|
||||
|
||||
/* Only handle setting domains to types used by the CPU. */
|
||||
if (write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
|
||||
if (write_domain & I915_GEM_GPU_DOMAINS)
|
||||
return -EINVAL;
|
||||
|
||||
if (read_domains & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
|
||||
if (read_domains & I915_GEM_GPU_DOMAINS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Having something in the write domain implies it's in the read
|
||||
@ -1481,14 +1481,19 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
|
||||
* Returned sequence numbers are nonzero on success.
|
||||
*/
|
||||
static uint32_t
|
||||
i915_add_request(struct drm_device *dev, uint32_t flush_domains)
|
||||
i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
|
||||
uint32_t flush_domains)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_file_private *i915_file_priv = NULL;
|
||||
struct drm_i915_gem_request *request;
|
||||
uint32_t seqno;
|
||||
int was_empty;
|
||||
RING_LOCALS;
|
||||
|
||||
if (file_priv != NULL)
|
||||
i915_file_priv = file_priv->driver_priv;
|
||||
|
||||
request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
|
||||
if (request == NULL)
|
||||
return 0;
|
||||
@ -1515,6 +1520,12 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
|
||||
request->emitted_jiffies = jiffies;
|
||||
was_empty = list_empty(&dev_priv->mm.request_list);
|
||||
list_add_tail(&request->list, &dev_priv->mm.request_list);
|
||||
if (i915_file_priv) {
|
||||
list_add_tail(&request->client_list,
|
||||
&i915_file_priv->mm.request_list);
|
||||
} else {
|
||||
INIT_LIST_HEAD(&request->client_list);
|
||||
}
|
||||
|
||||
/* Associate any objects on the flushing list matching the write
|
||||
* domain we're flushing with our flush.
|
||||
@ -1664,6 +1675,7 @@ i915_gem_retire_requests(struct drm_device *dev)
|
||||
i915_gem_retire_request(dev, request);
|
||||
|
||||
list_del(&request->list);
|
||||
list_del(&request->client_list);
|
||||
drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
|
||||
} else
|
||||
break;
|
||||
@ -1702,7 +1714,10 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
|
||||
BUG_ON(seqno == 0);
|
||||
|
||||
if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
|
||||
ier = I915_READ(IER);
|
||||
if (IS_IGDNG(dev))
|
||||
ier = I915_READ(DEIER) | I915_READ(GTIER);
|
||||
else
|
||||
ier = I915_READ(IER);
|
||||
if (!ier) {
|
||||
DRM_ERROR("something (likely vbetool) disabled "
|
||||
"interrupts, re-enabling\n");
|
||||
@ -1754,8 +1769,7 @@ i915_gem_flush(struct drm_device *dev,
|
||||
if (flush_domains & I915_GEM_DOMAIN_CPU)
|
||||
drm_agp_chipset_flush(dev);
|
||||
|
||||
if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
|
||||
I915_GEM_DOMAIN_GTT)) {
|
||||
if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
|
||||
/*
|
||||
* read/write caches:
|
||||
*
|
||||
@ -1977,7 +1991,7 @@ i915_gem_evict_something(struct drm_device *dev)
|
||||
i915_gem_flush(dev,
|
||||
obj->write_domain,
|
||||
obj->write_domain);
|
||||
i915_add_request(dev, obj->write_domain);
|
||||
i915_add_request(dev, NULL, obj->write_domain);
|
||||
|
||||
obj = NULL;
|
||||
continue;
|
||||
@ -1991,7 +2005,7 @@ i915_gem_evict_something(struct drm_device *dev)
|
||||
/* If we didn't do any of the above, there's nothing to be done
|
||||
* and we just can't fit it in.
|
||||
*/
|
||||
return -ENOMEM;
|
||||
return -ENOSPC;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -2006,7 +2020,7 @@ i915_gem_evict_everything(struct drm_device *dev)
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
if (ret == -ENOMEM)
|
||||
if (ret == -ENOSPC)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
@ -2215,7 +2229,7 @@ try_again:
|
||||
loff_t offset;
|
||||
|
||||
if (avail == 0)
|
||||
return -ENOMEM;
|
||||
return -ENOSPC;
|
||||
|
||||
for (i = dev_priv->fence_reg_start;
|
||||
i < dev_priv->num_fence_regs; i++) {
|
||||
@ -2248,7 +2262,7 @@ try_again:
|
||||
i915_gem_flush(dev,
|
||||
I915_GEM_GPU_DOMAINS,
|
||||
I915_GEM_GPU_DOMAINS);
|
||||
seqno = i915_add_request(dev,
|
||||
seqno = i915_add_request(dev, NULL,
|
||||
I915_GEM_GPU_DOMAINS);
|
||||
if (seqno == 0)
|
||||
return -ENOMEM;
|
||||
@ -2364,7 +2378,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
if (lists_empty) {
|
||||
DRM_ERROR("GTT full, but LRU list empty\n");
|
||||
return -ENOMEM;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
ret = i915_gem_evict_something(dev);
|
||||
@ -2409,8 +2423,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
||||
* wasn't in the GTT, there shouldn't be any way it could have been in
|
||||
* a GPU cache
|
||||
*/
|
||||
BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
|
||||
BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
|
||||
BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
|
||||
BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2452,7 +2466,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
||||
|
||||
/* Queue the GPU write cache flushing we need. */
|
||||
i915_gem_flush(dev, 0, obj->write_domain);
|
||||
seqno = i915_add_request(dev, obj->write_domain);
|
||||
seqno = i915_add_request(dev, NULL, obj->write_domain);
|
||||
obj->write_domain = 0;
|
||||
i915_gem_object_move_to_active(obj, seqno);
|
||||
}
|
||||
@ -3035,20 +3049,12 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int nbox = exec->num_cliprects;
|
||||
int i = 0, count;
|
||||
uint32_t exec_start, exec_len;
|
||||
uint32_t exec_start, exec_len;
|
||||
RING_LOCALS;
|
||||
|
||||
exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
|
||||
exec_len = (uint32_t) exec->batch_len;
|
||||
|
||||
if ((exec_start | exec_len) & 0x7) {
|
||||
DRM_ERROR("alignment\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!exec_start)
|
||||
return -EINVAL;
|
||||
|
||||
count = nbox ? nbox : 1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
@ -3089,6 +3095,10 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
|
||||
/* Throttle our rendering by waiting until the ring has completed our requests
|
||||
* emitted over 20 msec ago.
|
||||
*
|
||||
* Note that if we were to use the current jiffies each time around the loop,
|
||||
* we wouldn't escape the function with any frames outstanding if the time to
|
||||
* render a frame was over 20ms.
|
||||
*
|
||||
* This should get us reasonable parallelism between CPU and GPU but also
|
||||
* relatively low latency when blocking on a particular request to finish.
|
||||
*/
|
||||
@ -3097,15 +3107,25 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
|
||||
int ret = 0;
|
||||
uint32_t seqno;
|
||||
unsigned long recent_enough = jiffies - msecs_to_jiffies(20);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
seqno = i915_file_priv->mm.last_gem_throttle_seqno;
|
||||
i915_file_priv->mm.last_gem_throttle_seqno =
|
||||
i915_file_priv->mm.last_gem_seqno;
|
||||
if (seqno)
|
||||
ret = i915_wait_request(dev, seqno);
|
||||
while (!list_empty(&i915_file_priv->mm.request_list)) {
|
||||
struct drm_i915_gem_request *request;
|
||||
|
||||
request = list_first_entry(&i915_file_priv->mm.request_list,
|
||||
struct drm_i915_gem_request,
|
||||
client_list);
|
||||
|
||||
if (time_after_eq(request->emitted_jiffies, recent_enough))
|
||||
break;
|
||||
|
||||
ret = i915_wait_request(dev, request->seqno);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3182,12 +3202,29 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
|
||||
uint64_t exec_offset)
|
||||
{
|
||||
uint32_t exec_start, exec_len;
|
||||
|
||||
exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
|
||||
exec_len = (uint32_t) exec->batch_len;
|
||||
|
||||
if ((exec_start | exec_len) & 0x7)
|
||||
return -EINVAL;
|
||||
|
||||
if (!exec_start)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
|
||||
struct drm_i915_gem_execbuffer *args = data;
|
||||
struct drm_i915_gem_exec_object *exec_list = NULL;
|
||||
struct drm_gem_object **object_list = NULL;
|
||||
@ -3312,7 +3349,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
break;
|
||||
|
||||
/* error other than GTT full, or we've already tried again */
|
||||
if (ret != -ENOMEM || pin_tries >= 1) {
|
||||
if (ret != -ENOSPC || pin_tries >= 1) {
|
||||
if (ret != -ERESTARTSYS)
|
||||
DRM_ERROR("Failed to pin buffers %d\n", ret);
|
||||
goto err;
|
||||
@ -3331,8 +3368,20 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
/* Set the pending read domains for the batch buffer to COMMAND */
|
||||
batch_obj = object_list[args->buffer_count-1];
|
||||
batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
|
||||
batch_obj->pending_write_domain = 0;
|
||||
if (batch_obj->pending_write_domain) {
|
||||
DRM_ERROR("Attempting to use self-modifying batch buffer\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
|
||||
|
||||
/* Sanity check the batch buffer, prior to moving objects */
|
||||
exec_offset = exec_list[args->buffer_count - 1].offset;
|
||||
ret = i915_gem_check_execbuffer (args, exec_offset);
|
||||
if (ret != 0) {
|
||||
DRM_ERROR("execbuf with invalid offset/length\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
i915_verify_inactive(dev, __FILE__, __LINE__);
|
||||
|
||||
@ -3363,7 +3412,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
dev->invalidate_domains,
|
||||
dev->flush_domains);
|
||||
if (dev->flush_domains)
|
||||
(void)i915_add_request(dev, dev->flush_domains);
|
||||
(void)i915_add_request(dev, file_priv,
|
||||
dev->flush_domains);
|
||||
}
|
||||
|
||||
for (i = 0; i < args->buffer_count; i++) {
|
||||
@ -3381,8 +3431,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
}
|
||||
#endif
|
||||
|
||||
exec_offset = exec_list[args->buffer_count - 1].offset;
|
||||
|
||||
#if WATCH_EXEC
|
||||
i915_gem_dump_object(batch_obj,
|
||||
args->batch_len,
|
||||
@ -3412,9 +3460,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
* *some* interrupts representing completion of buffers that we can
|
||||
* wait on when trying to clear up gtt space).
|
||||
*/
|
||||
seqno = i915_add_request(dev, flush_domains);
|
||||
seqno = i915_add_request(dev, file_priv, flush_domains);
|
||||
BUG_ON(seqno == 0);
|
||||
i915_file_priv->mm.last_gem_seqno = seqno;
|
||||
for (i = 0; i < args->buffer_count; i++) {
|
||||
struct drm_gem_object *obj = object_list[i];
|
||||
|
||||
@ -3520,8 +3567,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
|
||||
atomic_inc(&dev->pin_count);
|
||||
atomic_add(obj->size, &dev->pin_memory);
|
||||
if (!obj_priv->active &&
|
||||
(obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
|
||||
I915_GEM_DOMAIN_GTT)) == 0 &&
|
||||
(obj->write_domain & I915_GEM_GPU_DOMAINS) == 0 &&
|
||||
!list_empty(&obj_priv->list))
|
||||
list_del_init(&obj_priv->list);
|
||||
}
|
||||
@ -3548,8 +3594,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj)
|
||||
*/
|
||||
if (obj_priv->pin_count == 0) {
|
||||
if (!obj_priv->active &&
|
||||
(obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
|
||||
I915_GEM_DOMAIN_GTT)) == 0)
|
||||
(obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
|
||||
list_move_tail(&obj_priv->list,
|
||||
&dev_priv->mm.inactive_list);
|
||||
atomic_dec(&dev->pin_count);
|
||||
@ -3653,15 +3698,14 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL) {
|
||||
DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
|
||||
args->handle);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
/* Update the active list for the hardware's current position.
|
||||
* Otherwise this only updates on a delayed timer or when irqs are
|
||||
* actually unmasked, and our working set ends up being larger than
|
||||
@ -3800,9 +3844,8 @@ i915_gem_idle(struct drm_device *dev)
|
||||
|
||||
/* Flush the GPU along with all non-CPU write domains
|
||||
*/
|
||||
i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
|
||||
~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
|
||||
seqno = i915_add_request(dev, ~I915_GEM_DOMAIN_CPU);
|
||||
i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
||||
seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
||||
|
||||
if (seqno == 0) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@ -4352,3 +4395,17 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||
drm_agp_chipset_flush(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
|
||||
|
||||
/* Clean up our request list when the client is going away, so that
|
||||
* later retire_requests won't dereference our soon-to-be-gone
|
||||
* file_priv.
|
||||
*/
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
while (!list_empty(&i915_file_priv->mm.request_list))
|
||||
list_del_init(i915_file_priv->mm.request_list.next);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pnp.h>
|
||||
#include "linux/string.h"
|
||||
#include "linux/bitops.h"
|
||||
#include "drmP.h"
|
||||
@ -81,6 +83,143 @@
|
||||
* to match what the GPU expects.
|
||||
*/
|
||||
|
||||
#define MCHBAR_I915 0x44
|
||||
#define MCHBAR_I965 0x48
|
||||
#define MCHBAR_SIZE (4*4096)
|
||||
|
||||
#define DEVEN_REG 0x54
|
||||
#define DEVEN_MCHBAR_EN (1 << 28)
|
||||
|
||||
/* Allocate space for the MCH regs if needed, return nonzero on error */
|
||||
static int
|
||||
intel_alloc_mchbar_resource(struct drm_device *dev)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp_lo, temp_hi = 0;
|
||||
u64 mchbar_addr;
|
||||
int ret = 0;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(bridge_dev, reg, &temp_lo);
|
||||
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
||||
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
||||
if (mchbar_addr &&
|
||||
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
||||
ret = 0;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
/* Get some space for it */
|
||||
ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
|
||||
MCHBAR_SIZE, MCHBAR_SIZE,
|
||||
PCIBIOS_MIN_MEM,
|
||||
0, pcibios_align_resource,
|
||||
bridge_dev);
|
||||
if (ret) {
|
||||
DRM_DEBUG("failed bus alloc: %d\n", ret);
|
||||
dev_priv->mch_res.start = 0;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_write_config_dword(bridge_dev, reg + 4,
|
||||
upper_32_bits(dev_priv->mch_res.start));
|
||||
|
||||
pci_write_config_dword(bridge_dev, reg,
|
||||
lower_32_bits(dev_priv->mch_res.start));
|
||||
out_put:
|
||||
pci_dev_put(bridge_dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup MCHBAR if possible, return true if we should disable it again */
|
||||
static bool
|
||||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool need_disable = false, enabled;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
|
||||
enabled = !!(temp & DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
enabled = temp & 1;
|
||||
}
|
||||
|
||||
/* If it's already enabled, don't have to do anything */
|
||||
if (enabled)
|
||||
goto out_put;
|
||||
|
||||
if (intel_alloc_mchbar_resource(dev))
|
||||
goto out_put;
|
||||
|
||||
need_disable = true;
|
||||
|
||||
/* Space is allocated or reserved, so enable it. */
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_write_config_dword(bridge_dev, DEVEN_REG,
|
||||
temp | DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
|
||||
}
|
||||
out_put:
|
||||
pci_dev_put(bridge_dev);
|
||||
out:
|
||||
return need_disable;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_teardown_mchbar(struct drm_device *dev, bool disable)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct pci_dev *bridge_dev;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (disable) {
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
|
||||
temp &= ~DEVEN_MCHBAR_EN;
|
||||
pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
temp &= ~1;
|
||||
pci_write_config_dword(bridge_dev, mchbar_reg, temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_priv->mch_res.start)
|
||||
release_resource(&dev_priv->mch_res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects bit 6 swizzling of address lookup between IGD access and CPU
|
||||
* access through main memory.
|
||||
@ -91,6 +230,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
bool need_disable;
|
||||
|
||||
if (!IS_I9XX(dev)) {
|
||||
/* As far as we know, the 865 doesn't have these bit 6
|
||||
@ -101,6 +241,9 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
} else if (IS_MOBILE(dev)) {
|
||||
uint32_t dcc;
|
||||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
need_disable = intel_setup_mchbar(dev);
|
||||
|
||||
/* On mobile 9xx chipsets, channel interleave by the CPU is
|
||||
* determined by DCC. For single-channel, neither the CPU
|
||||
* nor the GPU do swizzling. For dual channel interleaved,
|
||||
@ -140,6 +283,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
intel_teardown_mchbar(dev, need_disable);
|
||||
} else {
|
||||
/* The 965, G33, and newer, have a very flexible memory
|
||||
* configuration. It will enable dual-channel mode
|
||||
@ -170,6 +315,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: check with memory config on IGDNG */
|
||||
if (IS_IGDNG(dev)) {
|
||||
DRM_ERROR("disable tiling on IGDNG...\n");
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
|
||||
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
||||
}
|
||||
|
@ -57,6 +57,47 @@
|
||||
#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \
|
||||
DRM_I915_VBLANK_PIPE_B)
|
||||
|
||||
void
|
||||
igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
|
||||
dev_priv->gt_irq_mask_reg &= ~mask;
|
||||
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
|
||||
(void) I915_READ(GTIMR);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
|
||||
dev_priv->gt_irq_mask_reg |= mask;
|
||||
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
|
||||
(void) I915_READ(GTIMR);
|
||||
}
|
||||
}
|
||||
|
||||
/* For display hotplug interrupt */
|
||||
void
|
||||
igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
if ((dev_priv->irq_mask_reg & mask) != 0) {
|
||||
dev_priv->irq_mask_reg &= ~mask;
|
||||
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
|
||||
(void) I915_READ(DEIMR);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
if ((dev_priv->irq_mask_reg & mask) != mask) {
|
||||
dev_priv->irq_mask_reg |= mask;
|
||||
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
|
||||
(void) I915_READ(DEIMR);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
@ -196,6 +237,47 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
drm_sysfs_hotplug_event(dev);
|
||||
}
|
||||
|
||||
irqreturn_t igdng_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int ret = IRQ_NONE;
|
||||
u32 de_iir, gt_iir;
|
||||
u32 new_de_iir, new_gt_iir;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
|
||||
de_iir = I915_READ(DEIIR);
|
||||
gt_iir = I915_READ(GTIIR);
|
||||
|
||||
for (;;) {
|
||||
if (de_iir == 0 && gt_iir == 0)
|
||||
break;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
I915_WRITE(DEIIR, de_iir);
|
||||
new_de_iir = I915_READ(DEIIR);
|
||||
I915_WRITE(GTIIR, gt_iir);
|
||||
new_gt_iir = I915_READ(GTIIR);
|
||||
|
||||
if (dev->primary->master) {
|
||||
master_priv = dev->primary->master->driver_priv;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
}
|
||||
|
||||
if (gt_iir & GT_USER_INTERRUPT) {
|
||||
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
|
||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||
}
|
||||
|
||||
de_iir = new_de_iir;
|
||||
gt_iir = new_gt_iir;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
@ -212,6 +294,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
|
||||
atomic_inc(&dev_priv->irq_received);
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return igdng_irq_handler(dev);
|
||||
|
||||
iir = I915_READ(IIR);
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
@ -349,8 +434,12 @@ void i915_user_irq_get(struct drm_device *dev)
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
|
||||
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
|
||||
if (IS_IGDNG(dev))
|
||||
igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
||||
else
|
||||
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||
}
|
||||
|
||||
@ -361,8 +450,12 @@ void i915_user_irq_put(struct drm_device *dev)
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
|
||||
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
|
||||
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
|
||||
if (IS_IGDNG(dev))
|
||||
igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
||||
else
|
||||
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||
}
|
||||
|
||||
@ -455,6 +548,9 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
|
||||
if (!(pipeconf & PIPEACONF_ENABLE))
|
||||
return -EINVAL;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (IS_I965G(dev))
|
||||
i915_enable_pipestat(dev_priv, pipe,
|
||||
@ -474,6 +570,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
i915_disable_pipestat(dev_priv, pipe,
|
||||
PIPE_VBLANK_INTERRUPT_ENABLE |
|
||||
@ -484,7 +583,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
|
||||
void i915_enable_interrupt (struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
opregion_enable_asle(dev);
|
||||
|
||||
if (!IS_IGDNG(dev))
|
||||
opregion_enable_asle(dev);
|
||||
dev_priv->irq_enabled = 1;
|
||||
}
|
||||
|
||||
@ -545,12 +646,65 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
static void igdng_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
I915_WRITE(HWSTAM, 0xeffe);
|
||||
|
||||
/* XXX hotplug from PCH */
|
||||
|
||||
I915_WRITE(DEIMR, 0xffffffff);
|
||||
I915_WRITE(DEIER, 0x0);
|
||||
(void) I915_READ(DEIER);
|
||||
|
||||
/* and GT */
|
||||
I915_WRITE(GTIMR, 0xffffffff);
|
||||
I915_WRITE(GTIER, 0x0);
|
||||
(void) I915_READ(GTIER);
|
||||
}
|
||||
|
||||
static int igdng_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
/* enable kind of interrupts always enabled */
|
||||
u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
|
||||
u32 render_mask = GT_USER_INTERRUPT;
|
||||
|
||||
dev_priv->irq_mask_reg = ~display_mask;
|
||||
dev_priv->de_irq_enable_reg = display_mask;
|
||||
|
||||
/* should always can generate irq */
|
||||
I915_WRITE(DEIIR, I915_READ(DEIIR));
|
||||
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
|
||||
I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
|
||||
(void) I915_READ(DEIER);
|
||||
|
||||
/* user interrupt should be enabled, but masked initial */
|
||||
dev_priv->gt_irq_mask_reg = 0xffffffff;
|
||||
dev_priv->gt_irq_enable_reg = render_mask;
|
||||
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
|
||||
I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
|
||||
(void) I915_READ(GTIER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_irq_preinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
atomic_set(&dev_priv->irq_received, 0);
|
||||
|
||||
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
igdng_irq_preinstall(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
@ -562,7 +716,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
||||
I915_WRITE(IMR, 0xffffffff);
|
||||
I915_WRITE(IER, 0x0);
|
||||
(void) I915_READ(IER);
|
||||
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
|
||||
}
|
||||
|
||||
int i915_driver_irq_postinstall(struct drm_device *dev)
|
||||
@ -570,9 +723,12 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
|
||||
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
||||
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
|
||||
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
if (IS_IGDNG(dev))
|
||||
return igdng_irq_postinstall(dev);
|
||||
|
||||
/* Unmask the interrupts that we always want on. */
|
||||
dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
|
||||
@ -613,11 +769,24 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
||||
(void) I915_READ(IER);
|
||||
|
||||
opregion_enable_asle(dev);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void igdng_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
I915_WRITE(HWSTAM, 0xffffffff);
|
||||
|
||||
I915_WRITE(DEIMR, 0xffffffff);
|
||||
I915_WRITE(DEIER, 0x0);
|
||||
I915_WRITE(DEIIR, I915_READ(DEIIR));
|
||||
|
||||
I915_WRITE(GTIMR, 0xffffffff);
|
||||
I915_WRITE(GTIER, 0x0);
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
}
|
||||
|
||||
void i915_driver_irq_uninstall(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
@ -627,6 +796,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
||||
dev_priv->vblank_pipe = 0;
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
igdng_irq_uninstall(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
@ -450,6 +450,13 @@
|
||||
#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
|
||||
#define PLL_REF_INPUT_MASK (3 << 13)
|
||||
#define PLL_LOAD_PULSE_PHASE_SHIFT 9
|
||||
/* IGDNG */
|
||||
# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9
|
||||
# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9)
|
||||
# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9)
|
||||
# define DPLL_FPA1_P1_POST_DIV_SHIFT 0
|
||||
# define DPLL_FPA1_P1_POST_DIV_MASK 0xff
|
||||
|
||||
/*
|
||||
* Parallel to Serial Load Pulse phase selection.
|
||||
* Selects the phase for the 10X DPLL clock for the PCIe
|
||||
@ -631,8 +638,11 @@
|
||||
/* Hotplug control (945+ only) */
|
||||
#define PORT_HOTPLUG_EN 0x61110
|
||||
#define HDMIB_HOTPLUG_INT_EN (1 << 29)
|
||||
#define DPB_HOTPLUG_INT_EN (1 << 29)
|
||||
#define HDMIC_HOTPLUG_INT_EN (1 << 28)
|
||||
#define DPC_HOTPLUG_INT_EN (1 << 28)
|
||||
#define HDMID_HOTPLUG_INT_EN (1 << 27)
|
||||
#define DPD_HOTPLUG_INT_EN (1 << 27)
|
||||
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
|
||||
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
|
||||
#define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
@ -665,8 +675,11 @@
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
|
||||
#define DPB_HOTPLUG_INT_STATUS (1 << 29)
|
||||
#define HDMIC_HOTPLUG_INT_STATUS (1 << 28)
|
||||
#define DPC_HOTPLUG_INT_STATUS (1 << 28)
|
||||
#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
|
||||
#define DPD_HOTPLUG_INT_STATUS (1 << 27)
|
||||
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
|
||||
#define TV_HOTPLUG_INT_STATUS (1 << 10)
|
||||
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
|
||||
@ -951,15 +964,15 @@
|
||||
# define DAC_A_1_3_V (0 << 4)
|
||||
# define DAC_A_1_1_V (1 << 4)
|
||||
# define DAC_A_0_7_V (2 << 4)
|
||||
# define DAC_A_OFF (3 << 4)
|
||||
# define DAC_A_MASK (3 << 4)
|
||||
# define DAC_B_1_3_V (0 << 2)
|
||||
# define DAC_B_1_1_V (1 << 2)
|
||||
# define DAC_B_0_7_V (2 << 2)
|
||||
# define DAC_B_OFF (3 << 2)
|
||||
# define DAC_B_MASK (3 << 2)
|
||||
# define DAC_C_1_3_V (0 << 0)
|
||||
# define DAC_C_1_1_V (1 << 0)
|
||||
# define DAC_C_0_7_V (2 << 0)
|
||||
# define DAC_C_OFF (3 << 0)
|
||||
# define DAC_C_MASK (3 << 0)
|
||||
|
||||
/**
|
||||
* CSC coefficients are stored in a floating point format with 9 bits of
|
||||
@ -1328,6 +1341,163 @@
|
||||
#define TV_V_CHROMA_0 0x68400
|
||||
#define TV_V_CHROMA_42 0x684a8
|
||||
|
||||
/* Display Port */
|
||||
#define DP_B 0x64100
|
||||
#define DP_C 0x64200
|
||||
#define DP_D 0x64300
|
||||
|
||||
#define DP_PORT_EN (1 << 31)
|
||||
#define DP_PIPEB_SELECT (1 << 30)
|
||||
|
||||
/* Link training mode - select a suitable mode for each stage */
|
||||
#define DP_LINK_TRAIN_PAT_1 (0 << 28)
|
||||
#define DP_LINK_TRAIN_PAT_2 (1 << 28)
|
||||
#define DP_LINK_TRAIN_PAT_IDLE (2 << 28)
|
||||
#define DP_LINK_TRAIN_OFF (3 << 28)
|
||||
#define DP_LINK_TRAIN_MASK (3 << 28)
|
||||
#define DP_LINK_TRAIN_SHIFT 28
|
||||
|
||||
/* Signal voltages. These are mostly controlled by the other end */
|
||||
#define DP_VOLTAGE_0_4 (0 << 25)
|
||||
#define DP_VOLTAGE_0_6 (1 << 25)
|
||||
#define DP_VOLTAGE_0_8 (2 << 25)
|
||||
#define DP_VOLTAGE_1_2 (3 << 25)
|
||||
#define DP_VOLTAGE_MASK (7 << 25)
|
||||
#define DP_VOLTAGE_SHIFT 25
|
||||
|
||||
/* Signal pre-emphasis levels, like voltages, the other end tells us what
|
||||
* they want
|
||||
*/
|
||||
#define DP_PRE_EMPHASIS_0 (0 << 22)
|
||||
#define DP_PRE_EMPHASIS_3_5 (1 << 22)
|
||||
#define DP_PRE_EMPHASIS_6 (2 << 22)
|
||||
#define DP_PRE_EMPHASIS_9_5 (3 << 22)
|
||||
#define DP_PRE_EMPHASIS_MASK (7 << 22)
|
||||
#define DP_PRE_EMPHASIS_SHIFT 22
|
||||
|
||||
/* How many wires to use. I guess 3 was too hard */
|
||||
#define DP_PORT_WIDTH_1 (0 << 19)
|
||||
#define DP_PORT_WIDTH_2 (1 << 19)
|
||||
#define DP_PORT_WIDTH_4 (3 << 19)
|
||||
#define DP_PORT_WIDTH_MASK (7 << 19)
|
||||
|
||||
/* Mystic DPCD version 1.1 special mode */
|
||||
#define DP_ENHANCED_FRAMING (1 << 18)
|
||||
|
||||
/** locked once port is enabled */
|
||||
#define DP_PORT_REVERSAL (1 << 15)
|
||||
|
||||
/** sends the clock on lane 15 of the PEG for debug */
|
||||
#define DP_CLOCK_OUTPUT_ENABLE (1 << 13)
|
||||
|
||||
#define DP_SCRAMBLING_DISABLE (1 << 12)
|
||||
|
||||
/** limit RGB values to avoid confusing TVs */
|
||||
#define DP_COLOR_RANGE_16_235 (1 << 8)
|
||||
|
||||
/** Turn on the audio link */
|
||||
#define DP_AUDIO_OUTPUT_ENABLE (1 << 6)
|
||||
|
||||
/** vs and hs sync polarity */
|
||||
#define DP_SYNC_VS_HIGH (1 << 4)
|
||||
#define DP_SYNC_HS_HIGH (1 << 3)
|
||||
|
||||
/** A fantasy */
|
||||
#define DP_DETECTED (1 << 2)
|
||||
|
||||
/** The aux channel provides a way to talk to the
|
||||
* signal sink for DDC etc. Max packet size supported
|
||||
* is 20 bytes in each direction, hence the 5 fixed
|
||||
* data registers
|
||||
*/
|
||||
#define DPB_AUX_CH_CTL 0x64110
|
||||
#define DPB_AUX_CH_DATA1 0x64114
|
||||
#define DPB_AUX_CH_DATA2 0x64118
|
||||
#define DPB_AUX_CH_DATA3 0x6411c
|
||||
#define DPB_AUX_CH_DATA4 0x64120
|
||||
#define DPB_AUX_CH_DATA5 0x64124
|
||||
|
||||
#define DPC_AUX_CH_CTL 0x64210
|
||||
#define DPC_AUX_CH_DATA1 0x64214
|
||||
#define DPC_AUX_CH_DATA2 0x64218
|
||||
#define DPC_AUX_CH_DATA3 0x6421c
|
||||
#define DPC_AUX_CH_DATA4 0x64220
|
||||
#define DPC_AUX_CH_DATA5 0x64224
|
||||
|
||||
#define DPD_AUX_CH_CTL 0x64310
|
||||
#define DPD_AUX_CH_DATA1 0x64314
|
||||
#define DPD_AUX_CH_DATA2 0x64318
|
||||
#define DPD_AUX_CH_DATA3 0x6431c
|
||||
#define DPD_AUX_CH_DATA4 0x64320
|
||||
#define DPD_AUX_CH_DATA5 0x64324
|
||||
|
||||
#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31)
|
||||
#define DP_AUX_CH_CTL_DONE (1 << 30)
|
||||
#define DP_AUX_CH_CTL_INTERRUPT (1 << 29)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_1600us (3 << 26)
|
||||
#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26)
|
||||
#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25)
|
||||
#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20)
|
||||
#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20
|
||||
#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16)
|
||||
#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16
|
||||
#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15)
|
||||
#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14)
|
||||
#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13)
|
||||
#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12)
|
||||
#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11)
|
||||
#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff)
|
||||
#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0
|
||||
|
||||
/*
|
||||
* Computing GMCH M and N values for the Display Port link
|
||||
*
|
||||
* GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
|
||||
*
|
||||
* ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
|
||||
*
|
||||
* The GMCH value is used internally
|
||||
*
|
||||
* bytes_per_pixel is the number of bytes coming out of the plane,
|
||||
* which is after the LUTs, so we want the bytes for our color format.
|
||||
* For our current usage, this is always 3, one byte for R, G and B.
|
||||
*/
|
||||
#define PIPEA_GMCH_DATA_M 0x70050
|
||||
#define PIPEB_GMCH_DATA_M 0x71050
|
||||
|
||||
/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
|
||||
#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25)
|
||||
#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25
|
||||
|
||||
#define PIPE_GMCH_DATA_M_MASK (0xffffff)
|
||||
|
||||
#define PIPEA_GMCH_DATA_N 0x70054
|
||||
#define PIPEB_GMCH_DATA_N 0x71054
|
||||
#define PIPE_GMCH_DATA_N_MASK (0xffffff)
|
||||
|
||||
/*
|
||||
* Computing Link M and N values for the Display Port link
|
||||
*
|
||||
* Link M / N = pixel_clock / ls_clk
|
||||
*
|
||||
* (the DP spec calls pixel_clock the 'strm_clk')
|
||||
*
|
||||
* The Link value is transmitted in the Main Stream
|
||||
* Attributes and VB-ID.
|
||||
*/
|
||||
|
||||
#define PIPEA_DP_LINK_M 0x70060
|
||||
#define PIPEB_DP_LINK_M 0x71060
|
||||
#define PIPEA_DP_LINK_M_MASK (0xffffff)
|
||||
|
||||
#define PIPEA_DP_LINK_N 0x70064
|
||||
#define PIPEB_DP_LINK_N 0x71064
|
||||
#define PIPEA_DP_LINK_N_MASK (0xffffff)
|
||||
|
||||
/* Display & cursor control */
|
||||
|
||||
/* Pipe A */
|
||||
@ -1517,4 +1687,444 @@
|
||||
# define VGA_2X_MODE (1 << 30)
|
||||
# define VGA_PIPE_B_SELECT (1 << 29)
|
||||
|
||||
/* IGDNG */
|
||||
|
||||
#define CPU_VGACNTRL 0x41000
|
||||
|
||||
#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
|
||||
#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
|
||||
#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2)
|
||||
#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2)
|
||||
#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2)
|
||||
#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2)
|
||||
#define DIGITAL_PORTA_NO_DETECT (0 << 0)
|
||||
#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1)
|
||||
#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0)
|
||||
|
||||
/* refresh rate hardware control */
|
||||
#define RR_HW_CTL 0x45300
|
||||
#define RR_HW_LOW_POWER_FRAMES_MASK 0xff
|
||||
#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
|
||||
|
||||
#define FDI_PLL_BIOS_0 0x46000
|
||||
#define FDI_PLL_BIOS_1 0x46004
|
||||
#define FDI_PLL_BIOS_2 0x46008
|
||||
#define DISPLAY_PORT_PLL_BIOS_0 0x4600c
|
||||
#define DISPLAY_PORT_PLL_BIOS_1 0x46010
|
||||
#define DISPLAY_PORT_PLL_BIOS_2 0x46014
|
||||
|
||||
#define FDI_PLL_FREQ_CTL 0x46030
|
||||
#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
|
||||
#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
|
||||
#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff
|
||||
|
||||
|
||||
#define PIPEA_DATA_M1 0x60030
|
||||
#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
|
||||
#define TU_SIZE_MASK 0x7e000000
|
||||
#define PIPEA_DATA_M1_OFFSET 0
|
||||
#define PIPEA_DATA_N1 0x60034
|
||||
#define PIPEA_DATA_N1_OFFSET 0
|
||||
|
||||
#define PIPEA_DATA_M2 0x60038
|
||||
#define PIPEA_DATA_M2_OFFSET 0
|
||||
#define PIPEA_DATA_N2 0x6003c
|
||||
#define PIPEA_DATA_N2_OFFSET 0
|
||||
|
||||
#define PIPEA_LINK_M1 0x60040
|
||||
#define PIPEA_LINK_M1_OFFSET 0
|
||||
#define PIPEA_LINK_N1 0x60044
|
||||
#define PIPEA_LINK_N1_OFFSET 0
|
||||
|
||||
#define PIPEA_LINK_M2 0x60048
|
||||
#define PIPEA_LINK_M2_OFFSET 0
|
||||
#define PIPEA_LINK_N2 0x6004c
|
||||
#define PIPEA_LINK_N2_OFFSET 0
|
||||
|
||||
/* PIPEB timing regs are same start from 0x61000 */
|
||||
|
||||
#define PIPEB_DATA_M1 0x61030
|
||||
#define PIPEB_DATA_M1_OFFSET 0
|
||||
#define PIPEB_DATA_N1 0x61034
|
||||
#define PIPEB_DATA_N1_OFFSET 0
|
||||
|
||||
#define PIPEB_DATA_M2 0x61038
|
||||
#define PIPEB_DATA_M2_OFFSET 0
|
||||
#define PIPEB_DATA_N2 0x6103c
|
||||
#define PIPEB_DATA_N2_OFFSET 0
|
||||
|
||||
#define PIPEB_LINK_M1 0x61040
|
||||
#define PIPEB_LINK_M1_OFFSET 0
|
||||
#define PIPEB_LINK_N1 0x61044
|
||||
#define PIPEB_LINK_N1_OFFSET 0
|
||||
|
||||
#define PIPEB_LINK_M2 0x61048
|
||||
#define PIPEB_LINK_M2_OFFSET 0
|
||||
#define PIPEB_LINK_N2 0x6104c
|
||||
#define PIPEB_LINK_N2_OFFSET 0
|
||||
|
||||
/* CPU panel fitter */
|
||||
#define PFA_CTL_1 0x68080
|
||||
#define PFB_CTL_1 0x68880
|
||||
#define PF_ENABLE (1<<31)
|
||||
|
||||
/* legacy palette */
|
||||
#define LGC_PALETTE_A 0x4a000
|
||||
#define LGC_PALETTE_B 0x4a800
|
||||
|
||||
/* interrupts */
|
||||
#define DE_MASTER_IRQ_CONTROL (1 << 31)
|
||||
#define DE_SPRITEB_FLIP_DONE (1 << 29)
|
||||
#define DE_SPRITEA_FLIP_DONE (1 << 28)
|
||||
#define DE_PLANEB_FLIP_DONE (1 << 27)
|
||||
#define DE_PLANEA_FLIP_DONE (1 << 26)
|
||||
#define DE_PCU_EVENT (1 << 25)
|
||||
#define DE_GTT_FAULT (1 << 24)
|
||||
#define DE_POISON (1 << 23)
|
||||
#define DE_PERFORM_COUNTER (1 << 22)
|
||||
#define DE_PCH_EVENT (1 << 21)
|
||||
#define DE_AUX_CHANNEL_A (1 << 20)
|
||||
#define DE_DP_A_HOTPLUG (1 << 19)
|
||||
#define DE_GSE (1 << 18)
|
||||
#define DE_PIPEB_VBLANK (1 << 15)
|
||||
#define DE_PIPEB_EVEN_FIELD (1 << 14)
|
||||
#define DE_PIPEB_ODD_FIELD (1 << 13)
|
||||
#define DE_PIPEB_LINE_COMPARE (1 << 12)
|
||||
#define DE_PIPEB_VSYNC (1 << 11)
|
||||
#define DE_PIPEB_FIFO_UNDERRUN (1 << 8)
|
||||
#define DE_PIPEA_VBLANK (1 << 7)
|
||||
#define DE_PIPEA_EVEN_FIELD (1 << 6)
|
||||
#define DE_PIPEA_ODD_FIELD (1 << 5)
|
||||
#define DE_PIPEA_LINE_COMPARE (1 << 4)
|
||||
#define DE_PIPEA_VSYNC (1 << 3)
|
||||
#define DE_PIPEA_FIFO_UNDERRUN (1 << 0)
|
||||
|
||||
#define DEISR 0x44000
|
||||
#define DEIMR 0x44004
|
||||
#define DEIIR 0x44008
|
||||
#define DEIER 0x4400c
|
||||
|
||||
/* GT interrupt */
|
||||
#define GT_SYNC_STATUS (1 << 2)
|
||||
#define GT_USER_INTERRUPT (1 << 0)
|
||||
|
||||
#define GTISR 0x44010
|
||||
#define GTIMR 0x44014
|
||||
#define GTIIR 0x44018
|
||||
#define GTIER 0x4401c
|
||||
|
||||
/* PCH */
|
||||
|
||||
/* south display engine interrupt */
|
||||
#define SDE_CRT_HOTPLUG (1 << 11)
|
||||
#define SDE_PORTD_HOTPLUG (1 << 10)
|
||||
#define SDE_PORTC_HOTPLUG (1 << 9)
|
||||
#define SDE_PORTB_HOTPLUG (1 << 8)
|
||||
#define SDE_SDVOB_HOTPLUG (1 << 6)
|
||||
|
||||
#define SDEISR 0xc4000
|
||||
#define SDEIMR 0xc4004
|
||||
#define SDEIIR 0xc4008
|
||||
#define SDEIER 0xc400c
|
||||
|
||||
/* digital port hotplug */
|
||||
#define PCH_PORT_HOTPLUG 0xc4030
|
||||
#define PORTD_HOTPLUG_ENABLE (1 << 20)
|
||||
#define PORTD_PULSE_DURATION_2ms (0)
|
||||
#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
|
||||
#define PORTD_PULSE_DURATION_6ms (2 << 18)
|
||||
#define PORTD_PULSE_DURATION_100ms (3 << 18)
|
||||
#define PORTD_HOTPLUG_NO_DETECT (0)
|
||||
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
|
||||
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
|
||||
#define PORTC_HOTPLUG_ENABLE (1 << 12)
|
||||
#define PORTC_PULSE_DURATION_2ms (0)
|
||||
#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
|
||||
#define PORTC_PULSE_DURATION_6ms (2 << 10)
|
||||
#define PORTC_PULSE_DURATION_100ms (3 << 10)
|
||||
#define PORTC_HOTPLUG_NO_DETECT (0)
|
||||
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
|
||||
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
|
||||
#define PORTB_HOTPLUG_ENABLE (1 << 4)
|
||||
#define PORTB_PULSE_DURATION_2ms (0)
|
||||
#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
|
||||
#define PORTB_PULSE_DURATION_6ms (2 << 2)
|
||||
#define PORTB_PULSE_DURATION_100ms (3 << 2)
|
||||
#define PORTB_HOTPLUG_NO_DETECT (0)
|
||||
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
|
||||
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
|
||||
|
||||
#define PCH_GPIOA 0xc5010
|
||||
#define PCH_GPIOB 0xc5014
|
||||
#define PCH_GPIOC 0xc5018
|
||||
#define PCH_GPIOD 0xc501c
|
||||
#define PCH_GPIOE 0xc5020
|
||||
#define PCH_GPIOF 0xc5024
|
||||
|
||||
#define PCH_DPLL_A 0xc6014
|
||||
#define PCH_DPLL_B 0xc6018
|
||||
|
||||
#define PCH_FPA0 0xc6040
|
||||
#define PCH_FPA1 0xc6044
|
||||
#define PCH_FPB0 0xc6048
|
||||
#define PCH_FPB1 0xc604c
|
||||
|
||||
#define PCH_DPLL_TEST 0xc606c
|
||||
|
||||
#define PCH_DREF_CONTROL 0xC6200
|
||||
#define DREF_CONTROL_MASK 0x7fc3
|
||||
#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13)
|
||||
#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13)
|
||||
#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3<<13)
|
||||
#define DREF_CPU_SOURCE_OUTPUT_MASK (3<<13)
|
||||
#define DREF_SSC_SOURCE_DISABLE (0<<11)
|
||||
#define DREF_SSC_SOURCE_ENABLE (2<<11)
|
||||
#define DREF_SSC_SOURCE_MASK (2<<11)
|
||||
#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
|
||||
#define DREF_NONSPREAD_CK505_ENABLE (1<<9)
|
||||
#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
|
||||
#define DREF_NONSPREAD_SOURCE_MASK (2<<9)
|
||||
#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
|
||||
#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
|
||||
#define DREF_SSC4_DOWNSPREAD (0<<6)
|
||||
#define DREF_SSC4_CENTERSPREAD (1<<6)
|
||||
#define DREF_SSC1_DISABLE (0<<1)
|
||||
#define DREF_SSC1_ENABLE (1<<1)
|
||||
#define DREF_SSC4_DISABLE (0)
|
||||
#define DREF_SSC4_ENABLE (1)
|
||||
|
||||
#define PCH_RAWCLK_FREQ 0xc6204
|
||||
#define FDL_TP1_TIMER_SHIFT 12
|
||||
#define FDL_TP1_TIMER_MASK (3<<12)
|
||||
#define FDL_TP2_TIMER_SHIFT 10
|
||||
#define FDL_TP2_TIMER_MASK (3<<10)
|
||||
#define RAWCLK_FREQ_MASK 0x3ff
|
||||
|
||||
#define PCH_DPLL_TMR_CFG 0xc6208
|
||||
|
||||
#define PCH_SSC4_PARMS 0xc6210
|
||||
#define PCH_SSC4_AUX_PARMS 0xc6214
|
||||
|
||||
/* transcoder */
|
||||
|
||||
#define TRANS_HTOTAL_A 0xe0000
|
||||
#define TRANS_HTOTAL_SHIFT 16
|
||||
#define TRANS_HACTIVE_SHIFT 0
|
||||
#define TRANS_HBLANK_A 0xe0004
|
||||
#define TRANS_HBLANK_END_SHIFT 16
|
||||
#define TRANS_HBLANK_START_SHIFT 0
|
||||
#define TRANS_HSYNC_A 0xe0008
|
||||
#define TRANS_HSYNC_END_SHIFT 16
|
||||
#define TRANS_HSYNC_START_SHIFT 0
|
||||
#define TRANS_VTOTAL_A 0xe000c
|
||||
#define TRANS_VTOTAL_SHIFT 16
|
||||
#define TRANS_VACTIVE_SHIFT 0
|
||||
#define TRANS_VBLANK_A 0xe0010
|
||||
#define TRANS_VBLANK_END_SHIFT 16
|
||||
#define TRANS_VBLANK_START_SHIFT 0
|
||||
#define TRANS_VSYNC_A 0xe0014
|
||||
#define TRANS_VSYNC_END_SHIFT 16
|
||||
#define TRANS_VSYNC_START_SHIFT 0
|
||||
|
||||
#define TRANSA_DATA_M1 0xe0030
|
||||
#define TRANSA_DATA_N1 0xe0034
|
||||
#define TRANSA_DATA_M2 0xe0038
|
||||
#define TRANSA_DATA_N2 0xe003c
|
||||
#define TRANSA_DP_LINK_M1 0xe0040
|
||||
#define TRANSA_DP_LINK_N1 0xe0044
|
||||
#define TRANSA_DP_LINK_M2 0xe0048
|
||||
#define TRANSA_DP_LINK_N2 0xe004c
|
||||
|
||||
#define TRANS_HTOTAL_B 0xe1000
|
||||
#define TRANS_HBLANK_B 0xe1004
|
||||
#define TRANS_HSYNC_B 0xe1008
|
||||
#define TRANS_VTOTAL_B 0xe100c
|
||||
#define TRANS_VBLANK_B 0xe1010
|
||||
#define TRANS_VSYNC_B 0xe1014
|
||||
|
||||
#define TRANSB_DATA_M1 0xe1030
|
||||
#define TRANSB_DATA_N1 0xe1034
|
||||
#define TRANSB_DATA_M2 0xe1038
|
||||
#define TRANSB_DATA_N2 0xe103c
|
||||
#define TRANSB_DP_LINK_M1 0xe1040
|
||||
#define TRANSB_DP_LINK_N1 0xe1044
|
||||
#define TRANSB_DP_LINK_M2 0xe1048
|
||||
#define TRANSB_DP_LINK_N2 0xe104c
|
||||
|
||||
#define TRANSACONF 0xf0008
|
||||
#define TRANSBCONF 0xf1008
|
||||
#define TRANS_DISABLE (0<<31)
|
||||
#define TRANS_ENABLE (1<<31)
|
||||
#define TRANS_STATE_MASK (1<<30)
|
||||
#define TRANS_STATE_DISABLE (0<<30)
|
||||
#define TRANS_STATE_ENABLE (1<<30)
|
||||
#define TRANS_FSYNC_DELAY_HB1 (0<<27)
|
||||
#define TRANS_FSYNC_DELAY_HB2 (1<<27)
|
||||
#define TRANS_FSYNC_DELAY_HB3 (2<<27)
|
||||
#define TRANS_FSYNC_DELAY_HB4 (3<<27)
|
||||
#define TRANS_DP_AUDIO_ONLY (1<<26)
|
||||
#define TRANS_DP_VIDEO_AUDIO (0<<26)
|
||||
#define TRANS_PROGRESSIVE (0<<21)
|
||||
#define TRANS_8BPC (0<<5)
|
||||
#define TRANS_10BPC (1<<5)
|
||||
#define TRANS_6BPC (2<<5)
|
||||
#define TRANS_12BPC (3<<5)
|
||||
|
||||
#define FDI_RXA_CHICKEN 0xc200c
|
||||
#define FDI_RXB_CHICKEN 0xc2010
|
||||
#define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1)
|
||||
|
||||
/* CPU: FDI_TX */
|
||||
#define FDI_TXA_CTL 0x60100
|
||||
#define FDI_TXB_CTL 0x61100
|
||||
#define FDI_TX_DISABLE (0<<31)
|
||||
#define FDI_TX_ENABLE (1<<31)
|
||||
#define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
|
||||
#define FDI_LINK_TRAIN_PATTERN_2 (1<<28)
|
||||
#define FDI_LINK_TRAIN_PATTERN_IDLE (2<<28)
|
||||
#define FDI_LINK_TRAIN_NONE (3<<28)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0<<25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1<<25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2<<25)
|
||||
#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3<<25)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2<<22)
|
||||
#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3<<22)
|
||||
#define FDI_DP_PORT_WIDTH_X1 (0<<19)
|
||||
#define FDI_DP_PORT_WIDTH_X2 (1<<19)
|
||||
#define FDI_DP_PORT_WIDTH_X3 (2<<19)
|
||||
#define FDI_DP_PORT_WIDTH_X4 (3<<19)
|
||||
#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
|
||||
/* IGDNG: hardwired to 1 */
|
||||
#define FDI_TX_PLL_ENABLE (1<<14)
|
||||
/* both Tx and Rx */
|
||||
#define FDI_SCRAMBLING_ENABLE (0<<7)
|
||||
#define FDI_SCRAMBLING_DISABLE (1<<7)
|
||||
|
||||
/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
|
||||
#define FDI_RXA_CTL 0xf000c
|
||||
#define FDI_RXB_CTL 0xf100c
|
||||
#define FDI_RX_ENABLE (1<<31)
|
||||
#define FDI_RX_DISABLE (0<<31)
|
||||
/* train, dp width same as FDI_TX */
|
||||
#define FDI_DP_PORT_WIDTH_X8 (7<<19)
|
||||
#define FDI_8BPC (0<<16)
|
||||
#define FDI_10BPC (1<<16)
|
||||
#define FDI_6BPC (2<<16)
|
||||
#define FDI_12BPC (3<<16)
|
||||
#define FDI_LINK_REVERSE_OVERWRITE (1<<15)
|
||||
#define FDI_DMI_LINK_REVERSE_MASK (1<<14)
|
||||
#define FDI_RX_PLL_ENABLE (1<<13)
|
||||
#define FDI_FS_ERR_CORRECT_ENABLE (1<<11)
|
||||
#define FDI_FE_ERR_CORRECT_ENABLE (1<<10)
|
||||
#define FDI_FS_ERR_REPORT_ENABLE (1<<9)
|
||||
#define FDI_FE_ERR_REPORT_ENABLE (1<<8)
|
||||
#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
|
||||
#define FDI_SEL_RAWCLK (0<<4)
|
||||
#define FDI_SEL_PCDCLK (1<<4)
|
||||
|
||||
#define FDI_RXA_MISC 0xf0010
|
||||
#define FDI_RXB_MISC 0xf1010
|
||||
#define FDI_RXA_TUSIZE1 0xf0030
|
||||
#define FDI_RXA_TUSIZE2 0xf0038
|
||||
#define FDI_RXB_TUSIZE1 0xf1030
|
||||
#define FDI_RXB_TUSIZE2 0xf1038
|
||||
|
||||
/* FDI_RX interrupt register format */
|
||||
#define FDI_RX_INTER_LANE_ALIGN (1<<10)
|
||||
#define FDI_RX_SYMBOL_LOCK (1<<9) /* train 2 */
|
||||
#define FDI_RX_BIT_LOCK (1<<8) /* train 1 */
|
||||
#define FDI_RX_TRAIN_PATTERN_2_FAIL (1<<7)
|
||||
#define FDI_RX_FS_CODE_ERR (1<<6)
|
||||
#define FDI_RX_FE_CODE_ERR (1<<5)
|
||||
#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1<<4)
|
||||
#define FDI_RX_HDCP_LINK_FAIL (1<<3)
|
||||
#define FDI_RX_PIXEL_FIFO_OVERFLOW (1<<2)
|
||||
#define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1)
|
||||
#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0)
|
||||
|
||||
#define FDI_RXA_IIR 0xf0014
|
||||
#define FDI_RXA_IMR 0xf0018
|
||||
#define FDI_RXB_IIR 0xf1014
|
||||
#define FDI_RXB_IMR 0xf1018
|
||||
|
||||
#define FDI_PLL_CTL_1 0xfe000
|
||||
#define FDI_PLL_CTL_2 0xfe004
|
||||
|
||||
/* CRT */
|
||||
#define PCH_ADPA 0xe1100
|
||||
#define ADPA_TRANS_SELECT_MASK (1<<30)
|
||||
#define ADPA_TRANS_A_SELECT 0
|
||||
#define ADPA_TRANS_B_SELECT (1<<30)
|
||||
#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */
|
||||
#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0<<24)
|
||||
#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3<<24)
|
||||
#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
|
||||
#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2<<24)
|
||||
#define ADPA_CRT_HOTPLUG_ENABLE (1<<23)
|
||||
#define ADPA_CRT_HOTPLUG_PERIOD_64 (0<<22)
|
||||
#define ADPA_CRT_HOTPLUG_PERIOD_128 (1<<22)
|
||||
#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0<<21)
|
||||
#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1<<21)
|
||||
#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0<<20)
|
||||
#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1<<20)
|
||||
#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0<<18)
|
||||
#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1<<18)
|
||||
#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2<<18)
|
||||
#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3<<18)
|
||||
#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0<<17)
|
||||
#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17)
|
||||
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
|
||||
|
||||
/* or SDVOB */
|
||||
#define HDMIB 0xe1140
|
||||
#define PORT_ENABLE (1 << 31)
|
||||
#define TRANSCODER_A (0)
|
||||
#define TRANSCODER_B (1 << 30)
|
||||
#define COLOR_FORMAT_8bpc (0)
|
||||
#define COLOR_FORMAT_12bpc (3 << 26)
|
||||
#define SDVOB_HOTPLUG_ENABLE (1 << 23)
|
||||
#define SDVO_ENCODING (0)
|
||||
#define TMDS_ENCODING (2 << 10)
|
||||
#define NULL_PACKET_VSYNC_ENABLE (1 << 9)
|
||||
#define SDVOB_BORDER_ENABLE (1 << 7)
|
||||
#define AUDIO_ENABLE (1 << 6)
|
||||
#define VSYNC_ACTIVE_HIGH (1 << 4)
|
||||
#define HSYNC_ACTIVE_HIGH (1 << 3)
|
||||
#define PORT_DETECTED (1 << 2)
|
||||
|
||||
#define HDMIC 0xe1150
|
||||
#define HDMID 0xe1160
|
||||
|
||||
#define PCH_LVDS 0xe1180
|
||||
#define LVDS_DETECTED (1 << 1)
|
||||
|
||||
#define BLC_PWM_CPU_CTL2 0x48250
|
||||
#define PWM_ENABLE (1 << 31)
|
||||
#define PWM_PIPE_A (0 << 29)
|
||||
#define PWM_PIPE_B (1 << 29)
|
||||
#define BLC_PWM_CPU_CTL 0x48254
|
||||
|
||||
#define BLC_PWM_PCH_CTL1 0xc8250
|
||||
#define PWM_PCH_ENABLE (1 << 31)
|
||||
#define PWM_POLARITY_ACTIVE_LOW (1 << 29)
|
||||
#define PWM_POLARITY_ACTIVE_HIGH (0 << 29)
|
||||
#define PWM_POLARITY_ACTIVE_LOW2 (1 << 28)
|
||||
#define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28)
|
||||
|
||||
#define BLC_PWM_PCH_CTL2 0xc8254
|
||||
|
||||
#define PCH_PP_STATUS 0xc7200
|
||||
#define PCH_PP_CONTROL 0xc7204
|
||||
#define EDP_FORCE_VDD (1 << 3)
|
||||
#define EDP_BLC_ENABLE (1 << 2)
|
||||
#define PANEL_POWER_RESET (1 << 1)
|
||||
#define PANEL_POWER_OFF (0 << 0)
|
||||
#define PANEL_POWER_ON (1 << 0)
|
||||
#define PCH_PP_ON_DELAYS 0xc7208
|
||||
#define EDP_PANEL (1 << 30)
|
||||
#define PCH_PP_OFF_DELAYS 0xc720c
|
||||
#define PCH_PP_DIVISOR 0xc7210
|
||||
|
||||
#endif /* _I915_REG_H_ */
|
||||
|
@ -295,6 +295,16 @@ int i915_save_state(struct drm_device *dev)
|
||||
i915_save_palette(dev, PIPE_B);
|
||||
dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
|
||||
|
||||
/* Cursor state */
|
||||
dev_priv->saveCURACNTR = I915_READ(CURACNTR);
|
||||
dev_priv->saveCURAPOS = I915_READ(CURAPOS);
|
||||
dev_priv->saveCURABASE = I915_READ(CURABASE);
|
||||
dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
|
||||
dev_priv->saveCURBPOS = I915_READ(CURBPOS);
|
||||
dev_priv->saveCURBBASE = I915_READ(CURBBASE);
|
||||
if (!IS_I9XX(dev))
|
||||
dev_priv->saveCURSIZE = I915_READ(CURSIZE);
|
||||
|
||||
/* CRT state */
|
||||
dev_priv->saveADPA = I915_READ(ADPA);
|
||||
|
||||
@ -480,6 +490,16 @@ int i915_restore_state(struct drm_device *dev)
|
||||
I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
|
||||
I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
|
||||
|
||||
/* Cursor state */
|
||||
I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
|
||||
I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
|
||||
I915_WRITE(CURABASE, dev_priv->saveCURABASE);
|
||||
I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
|
||||
I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
|
||||
I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
|
||||
if (!IS_I9XX(dev))
|
||||
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
|
||||
|
||||
/* CRT state */
|
||||
I915_WRITE(ADPA, dev_priv->saveADPA);
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "i915_drv.h"
|
||||
#include "intel_bios.h"
|
||||
|
||||
#define SLAVE_ADDR1 0x70
|
||||
#define SLAVE_ADDR2 0x72
|
||||
|
||||
static void *
|
||||
find_section(struct bdb_header *bdb, int section_id)
|
||||
@ -193,6 +195,88 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
||||
struct bdb_header *bdb)
|
||||
{
|
||||
struct sdvo_device_mapping *p_mapping;
|
||||
struct bdb_general_definitions *p_defs;
|
||||
struct child_device_config *p_child;
|
||||
int i, child_device_num, count;
|
||||
u16 block_size, *block_ptr;
|
||||
|
||||
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||
if (!p_defs) {
|
||||
DRM_DEBUG("No general definition block is found\n");
|
||||
return;
|
||||
}
|
||||
/* judge whether the size of child device meets the requirements.
|
||||
* If the child device size obtained from general definition block
|
||||
* is different with sizeof(struct child_device_config), skip the
|
||||
* parsing of sdvo device info
|
||||
*/
|
||||
if (p_defs->child_dev_size != sizeof(*p_child)) {
|
||||
/* different child dev size . Ignore it */
|
||||
DRM_DEBUG("different child size is found. Invalid.\n");
|
||||
return;
|
||||
}
|
||||
/* get the block size of general definitions */
|
||||
block_ptr = (u16 *)((char *)p_defs - 2);
|
||||
block_size = *block_ptr;
|
||||
/* get the number of child device */
|
||||
child_device_num = (block_size - sizeof(*p_defs)) /
|
||||
sizeof(*p_child);
|
||||
count = 0;
|
||||
for (i = 0; i < child_device_num; i++) {
|
||||
p_child = &(p_defs->devices[i]);
|
||||
if (!p_child->device_type) {
|
||||
/* skip the device block if device type is invalid */
|
||||
continue;
|
||||
}
|
||||
if (p_child->slave_addr != SLAVE_ADDR1 &&
|
||||
p_child->slave_addr != SLAVE_ADDR2) {
|
||||
/*
|
||||
* If the slave address is neither 0x70 nor 0x72,
|
||||
* it is not a SDVO device. Skip it.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (p_child->dvo_port != DEVICE_PORT_DVOB &&
|
||||
p_child->dvo_port != DEVICE_PORT_DVOC) {
|
||||
/* skip the incorrect SDVO port */
|
||||
DRM_DEBUG("Incorrect SDVO port. Skip it \n");
|
||||
continue;
|
||||
}
|
||||
DRM_DEBUG("the SDVO device with slave addr %2x is found on "
|
||||
"%s port\n",
|
||||
p_child->slave_addr,
|
||||
(p_child->dvo_port == DEVICE_PORT_DVOB) ?
|
||||
"SDVOB" : "SDVOC");
|
||||
p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
|
||||
if (!p_mapping->initialized) {
|
||||
p_mapping->dvo_port = p_child->dvo_port;
|
||||
p_mapping->slave_addr = p_child->slave_addr;
|
||||
p_mapping->dvo_wiring = p_child->dvo_wiring;
|
||||
p_mapping->initialized = 1;
|
||||
} else {
|
||||
DRM_DEBUG("Maybe one SDVO port is shared by "
|
||||
"two SDVO device.\n");
|
||||
}
|
||||
if (p_child->slave2_addr) {
|
||||
/* Maybe this is a SDVO device with multiple inputs */
|
||||
/* And the mapping info is not added */
|
||||
DRM_DEBUG("there exists the slave2_addr. Maybe this "
|
||||
"is a SDVO device with multiple inputs.\n");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
/* No SDVO device info is found */
|
||||
DRM_DEBUG("No SDVO device info is found in VBT\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* intel_init_bios - initialize VBIOS settings & find VBT
|
||||
* @dev: DRM device
|
||||
@ -242,7 +326,7 @@ intel_init_bios(struct drm_device *dev)
|
||||
parse_general_features(dev_priv, bdb);
|
||||
parse_lfp_panel_data(dev_priv, bdb);
|
||||
parse_sdvo_panel_data(dev_priv, bdb);
|
||||
|
||||
parse_sdvo_device_mapping(dev_priv, bdb);
|
||||
pci_unmap_rom(pdev, bios);
|
||||
|
||||
return 0;
|
||||
|
@ -135,6 +135,86 @@ struct bdb_general_features {
|
||||
u8 rsvd11:6; /* finish byte */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* pre-915 */
|
||||
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
|
||||
#define GPIO_PIN_ADD_I2C 0x05 /* "ADDCARD I2C GPIO pins" */
|
||||
#define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */
|
||||
#define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */
|
||||
|
||||
/* Pre 915 */
|
||||
#define DEVICE_TYPE_NONE 0x00
|
||||
#define DEVICE_TYPE_CRT 0x01
|
||||
#define DEVICE_TYPE_TV 0x09
|
||||
#define DEVICE_TYPE_EFP 0x12
|
||||
#define DEVICE_TYPE_LFP 0x22
|
||||
/* On 915+ */
|
||||
#define DEVICE_TYPE_CRT_DPMS 0x6001
|
||||
#define DEVICE_TYPE_CRT_DPMS_HOTPLUG 0x4001
|
||||
#define DEVICE_TYPE_TV_COMPOSITE 0x0209
|
||||
#define DEVICE_TYPE_TV_MACROVISION 0x0289
|
||||
#define DEVICE_TYPE_TV_RF_COMPOSITE 0x020c
|
||||
#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE 0x0609
|
||||
#define DEVICE_TYPE_TV_SCART 0x0209
|
||||
#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
|
||||
#define DEVICE_TYPE_EFP_HOTPLUG_PWR 0x6012
|
||||
#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052
|
||||
#define DEVICE_TYPE_EFP_DVI_I 0x6053
|
||||
#define DEVICE_TYPE_EFP_DVI_D_DUAL 0x6152
|
||||
#define DEVICE_TYPE_EFP_DVI_D_HDCP 0x60d2
|
||||
#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR 0x6062
|
||||
#define DEVICE_TYPE_OPENLDI_DUALPIX 0x6162
|
||||
#define DEVICE_TYPE_LFP_PANELLINK 0x5012
|
||||
#define DEVICE_TYPE_LFP_CMOS_PWR 0x5042
|
||||
#define DEVICE_TYPE_LFP_LVDS_PWR 0x5062
|
||||
#define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162
|
||||
#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
|
||||
|
||||
#define DEVICE_CFG_NONE 0x00
|
||||
#define DEVICE_CFG_12BIT_DVOB 0x01
|
||||
#define DEVICE_CFG_12BIT_DVOC 0x02
|
||||
#define DEVICE_CFG_24BIT_DVOBC 0x09
|
||||
#define DEVICE_CFG_24BIT_DVOCB 0x0a
|
||||
#define DEVICE_CFG_DUAL_DVOB 0x11
|
||||
#define DEVICE_CFG_DUAL_DVOC 0x12
|
||||
#define DEVICE_CFG_DUAL_DVOBC 0x13
|
||||
#define DEVICE_CFG_DUAL_LINK_DVOBC 0x19
|
||||
#define DEVICE_CFG_DUAL_LINK_DVOCB 0x1a
|
||||
|
||||
#define DEVICE_WIRE_NONE 0x00
|
||||
#define DEVICE_WIRE_DVOB 0x01
|
||||
#define DEVICE_WIRE_DVOC 0x02
|
||||
#define DEVICE_WIRE_DVOBC 0x03
|
||||
#define DEVICE_WIRE_DVOBB 0x05
|
||||
#define DEVICE_WIRE_DVOCC 0x06
|
||||
#define DEVICE_WIRE_DVOB_MASTER 0x0d
|
||||
#define DEVICE_WIRE_DVOC_MASTER 0x0e
|
||||
|
||||
#define DEVICE_PORT_DVOA 0x00 /* none on 845+ */
|
||||
#define DEVICE_PORT_DVOB 0x01
|
||||
#define DEVICE_PORT_DVOC 0x02
|
||||
|
||||
struct child_device_config {
|
||||
u16 handle;
|
||||
u16 device_type;
|
||||
u8 device_id[10]; /* See DEVICE_TYPE_* above */
|
||||
u16 addin_offset;
|
||||
u8 dvo_port; /* See Device_PORT_* above */
|
||||
u8 i2c_pin;
|
||||
u8 slave_addr;
|
||||
u8 ddc_pin;
|
||||
u16 edid_ptr;
|
||||
u8 dvo_cfg; /* See DEVICE_CFG_* above */
|
||||
u8 dvo2_port;
|
||||
u8 i2c2_pin;
|
||||
u8 slave2_addr;
|
||||
u8 ddc2_pin;
|
||||
u8 capabilities;
|
||||
u8 dvo_wiring;/* See DEVICE_WIRE_* above */
|
||||
u8 dvo2_wiring;
|
||||
u16 extended_type;
|
||||
u8 dvo_function;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct bdb_general_definitions {
|
||||
/* DDC GPIO */
|
||||
u8 crt_ddc_gmbus_pin;
|
||||
@ -149,14 +229,19 @@ struct bdb_general_definitions {
|
||||
u8 boot_display[2];
|
||||
u8 child_dev_size;
|
||||
|
||||
/* device info */
|
||||
u8 tv_or_lvds_info[33];
|
||||
u8 dev1[33];
|
||||
u8 dev2[33];
|
||||
u8 dev3[33];
|
||||
u8 dev4[33];
|
||||
/* may be another device block here on some platforms */
|
||||
};
|
||||
/*
|
||||
* Device info:
|
||||
* If TV is present, it'll be at devices[0].
|
||||
* LVDS will be next, either devices[0] or [1], if present.
|
||||
* On some platforms the number of device is 6. But could be as few as
|
||||
* 4 if both TV and LVDS are missing.
|
||||
* And the device num is related with the size of general definition
|
||||
* block. It is obtained by using the following formula:
|
||||
* number = (block_size - sizeof(bdb_general_definitions))/
|
||||
* sizeof(child_device_config);
|
||||
*/
|
||||
struct child_device_config devices[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct bdb_lvds_options {
|
||||
u8 panel_type;
|
||||
|
@ -37,9 +37,14 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 temp;
|
||||
u32 temp, reg;
|
||||
|
||||
temp = I915_READ(ADPA);
|
||||
if (IS_IGDNG(dev))
|
||||
reg = PCH_ADPA;
|
||||
else
|
||||
reg = ADPA;
|
||||
|
||||
temp = I915_READ(reg);
|
||||
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
||||
temp |= ADPA_DAC_ENABLE;
|
||||
|
||||
@ -58,7 +63,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE(ADPA, temp);
|
||||
I915_WRITE(reg, temp);
|
||||
}
|
||||
|
||||
static int intel_crt_mode_valid(struct drm_connector *connector,
|
||||
@ -101,17 +106,23 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int dpll_md_reg;
|
||||
u32 adpa, dpll_md;
|
||||
u32 adpa_reg;
|
||||
|
||||
if (intel_crtc->pipe == 0)
|
||||
dpll_md_reg = DPLL_A_MD;
|
||||
else
|
||||
dpll_md_reg = DPLL_B_MD;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
adpa_reg = PCH_ADPA;
|
||||
else
|
||||
adpa_reg = ADPA;
|
||||
|
||||
/*
|
||||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (IS_I965G(dev)) {
|
||||
if (IS_I965G(dev) && !IS_IGDNG(dev)) {
|
||||
dpll_md = I915_READ(dpll_md_reg);
|
||||
I915_WRITE(dpll_md_reg,
|
||||
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
@ -125,13 +136,53 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
||||
|
||||
if (intel_crtc->pipe == 0) {
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
I915_WRITE(BCLRPAT_A, 0);
|
||||
if (!IS_IGDNG(dev))
|
||||
I915_WRITE(BCLRPAT_A, 0);
|
||||
} else {
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
I915_WRITE(BCLRPAT_B, 0);
|
||||
if (!IS_IGDNG(dev))
|
||||
I915_WRITE(BCLRPAT_B, 0);
|
||||
}
|
||||
|
||||
I915_WRITE(ADPA, adpa);
|
||||
I915_WRITE(adpa_reg, adpa);
|
||||
}
|
||||
|
||||
static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 adpa, temp;
|
||||
bool ret;
|
||||
|
||||
temp = adpa = I915_READ(PCH_ADPA);
|
||||
|
||||
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
|
||||
|
||||
adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
|
||||
ADPA_CRT_HOTPLUG_WARMUP_10MS |
|
||||
ADPA_CRT_HOTPLUG_SAMPLE_4S |
|
||||
ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
|
||||
ADPA_CRT_HOTPLUG_VOLREF_325MV |
|
||||
ADPA_CRT_HOTPLUG_ENABLE |
|
||||
ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
|
||||
|
||||
DRM_DEBUG("pch crt adpa 0x%x", adpa);
|
||||
I915_WRITE(PCH_ADPA, adpa);
|
||||
|
||||
/* This might not be needed as not specified in spec...*/
|
||||
udelay(1000);
|
||||
|
||||
/* Check the status to see if both blue and green are on now */
|
||||
adpa = I915_READ(PCH_ADPA);
|
||||
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) ==
|
||||
ADPA_CRT_HOTPLUG_MONITOR_COLOR)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
|
||||
/* restore origin register */
|
||||
I915_WRITE(PCH_ADPA, temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,6 +199,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 hotplug_en;
|
||||
int i, tries = 0;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return intel_igdng_crt_detect_hotplug(connector);
|
||||
|
||||
/*
|
||||
* On 4 series desktop, CRT detect sequence need to be done twice
|
||||
* to get a reliable result.
|
||||
@ -423,6 +478,7 @@ void intel_crt_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct intel_output *intel_output;
|
||||
u32 i2c_reg;
|
||||
|
||||
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output)
|
||||
@ -439,7 +495,11 @@ void intel_crt_init(struct drm_device *dev)
|
||||
&intel_output->enc);
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
|
||||
if (IS_IGDNG(dev))
|
||||
i2c_reg = PCH_GPIOA;
|
||||
else
|
||||
i2c_reg = GPIOA;
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
|
@ -137,6 +137,8 @@ struct intel_limit {
|
||||
#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7
|
||||
#define INTEL_LIMIT_IGD_SDVO_DAC 8
|
||||
#define INTEL_LIMIT_IGD_LVDS 9
|
||||
#define INTEL_LIMIT_IGDNG_SDVO_DAC 10
|
||||
#define INTEL_LIMIT_IGDNG_LVDS 11
|
||||
|
||||
/*The parameter is for SDVO on G4x platform*/
|
||||
#define G4X_DOT_SDVO_MIN 25000
|
||||
@ -216,12 +218,43 @@ struct intel_limit {
|
||||
#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
|
||||
#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
|
||||
|
||||
/* IGDNG */
|
||||
/* as we calculate clock using (register_value + 2) for
|
||||
N/M1/M2, so here the range value for them is (actual_value-2).
|
||||
*/
|
||||
#define IGDNG_DOT_MIN 25000
|
||||
#define IGDNG_DOT_MAX 350000
|
||||
#define IGDNG_VCO_MIN 1760000
|
||||
#define IGDNG_VCO_MAX 3510000
|
||||
#define IGDNG_N_MIN 1
|
||||
#define IGDNG_N_MAX 5
|
||||
#define IGDNG_M_MIN 79
|
||||
#define IGDNG_M_MAX 118
|
||||
#define IGDNG_M1_MIN 12
|
||||
#define IGDNG_M1_MAX 23
|
||||
#define IGDNG_M2_MIN 5
|
||||
#define IGDNG_M2_MAX 9
|
||||
#define IGDNG_P_SDVO_DAC_MIN 5
|
||||
#define IGDNG_P_SDVO_DAC_MAX 80
|
||||
#define IGDNG_P_LVDS_MIN 28
|
||||
#define IGDNG_P_LVDS_MAX 112
|
||||
#define IGDNG_P1_MIN 1
|
||||
#define IGDNG_P1_MAX 8
|
||||
#define IGDNG_P2_SDVO_DAC_SLOW 10
|
||||
#define IGDNG_P2_SDVO_DAC_FAST 5
|
||||
#define IGDNG_P2_LVDS_SLOW 14 /* single channel */
|
||||
#define IGDNG_P2_LVDS_FAST 7 /* double channel */
|
||||
#define IGDNG_P2_DOT_LIMIT 225000 /* 225Mhz */
|
||||
|
||||
static bool
|
||||
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
|
||||
static const intel_limit_t intel_limits[] = {
|
||||
{ /* INTEL_LIMIT_I8XX_DVO_DAC */
|
||||
@ -383,9 +416,47 @@ static const intel_limit_t intel_limits[] = {
|
||||
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
},
|
||||
|
||||
{ /* INTEL_LIMIT_IGDNG_SDVO_DAC */
|
||||
.dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX },
|
||||
.vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX },
|
||||
.n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX },
|
||||
.m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX },
|
||||
.m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX },
|
||||
.m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX },
|
||||
.p = { .min = IGDNG_P_SDVO_DAC_MIN, .max = IGDNG_P_SDVO_DAC_MAX },
|
||||
.p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX },
|
||||
.p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT,
|
||||
.p2_slow = IGDNG_P2_SDVO_DAC_SLOW,
|
||||
.p2_fast = IGDNG_P2_SDVO_DAC_FAST },
|
||||
.find_pll = intel_igdng_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_IGDNG_LVDS */
|
||||
.dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX },
|
||||
.vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX },
|
||||
.n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX },
|
||||
.m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX },
|
||||
.m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX },
|
||||
.m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX },
|
||||
.p = { .min = IGDNG_P_LVDS_MIN, .max = IGDNG_P_LVDS_MAX },
|
||||
.p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX },
|
||||
.p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT,
|
||||
.p2_slow = IGDNG_P2_LVDS_SLOW,
|
||||
.p2_fast = IGDNG_P2_LVDS_FAST },
|
||||
.find_pll = intel_igdng_find_best_PLL,
|
||||
},
|
||||
};
|
||||
|
||||
static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc)
|
||||
{
|
||||
const intel_limit_t *limit;
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
||||
limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS];
|
||||
else
|
||||
limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC];
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -418,7 +489,9 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
||||
struct drm_device *dev = crtc->dev;
|
||||
const intel_limit_t *limit;
|
||||
|
||||
if (IS_G4X(dev)) {
|
||||
if (IS_IGDNG(dev))
|
||||
limit = intel_igdng_limit(crtc);
|
||||
else if (IS_G4X(dev)) {
|
||||
limit = intel_g4x_limit(crtc);
|
||||
} else if (IS_I9XX(dev) && !IS_IGD(dev)) {
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
||||
@ -630,7 +703,64 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
intel_clock_t clock;
|
||||
int max_n;
|
||||
bool found;
|
||||
int err_most = 47;
|
||||
found = false;
|
||||
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
||||
if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
|
||||
LVDS_CLKB_POWER_UP)
|
||||
clock.p2 = limit->p2.p2_fast;
|
||||
else
|
||||
clock.p2 = limit->p2.p2_slow;
|
||||
} else {
|
||||
if (target < limit->p2.dot_limit)
|
||||
clock.p2 = limit->p2.p2_slow;
|
||||
else
|
||||
clock.p2 = limit->p2.p2_fast;
|
||||
}
|
||||
|
||||
memset(best_clock, 0, sizeof(*best_clock));
|
||||
max_n = limit->n.max;
|
||||
/* based on hardware requriment prefer smaller n to precision */
|
||||
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
||||
/* based on hardware requirment prefere larger m1,m2, p1 */
|
||||
for (clock.m1 = limit->m1.max;
|
||||
clock.m1 >= limit->m1.min; clock.m1--) {
|
||||
for (clock.m2 = limit->m2.max;
|
||||
clock.m2 >= limit->m2.min; clock.m2--) {
|
||||
for (clock.p1 = limit->p1.max;
|
||||
clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
if (!intel_PLL_is_valid(crtc, &clock))
|
||||
continue;
|
||||
this_err = abs((10000 - (target*10000/clock.dot)));
|
||||
if (this_err < err_most) {
|
||||
*best_clock = clock;
|
||||
err_most = this_err;
|
||||
max_n = clock.n;
|
||||
found = true;
|
||||
/* found on first matching */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return found;
|
||||
}
|
||||
|
||||
@ -785,18 +915,292 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the power management mode of the pipe and plane.
|
||||
*
|
||||
* This code should probably grow support for turning the cursor off and back
|
||||
* on appropriately at the same time as we're turning the pipe off/on.
|
||||
*/
|
||||
static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->pipe;
|
||||
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
|
||||
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
||||
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
||||
int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
|
||||
int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
|
||||
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
|
||||
int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
|
||||
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
|
||||
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
|
||||
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
|
||||
int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
|
||||
int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
|
||||
int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
|
||||
int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
|
||||
int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
|
||||
int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
|
||||
int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
|
||||
int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
|
||||
int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
|
||||
u32 temp;
|
||||
int tries = 5, j;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off
|
||||
* and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
|
||||
*/
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
DRM_DEBUG("crtc %d dpms on\n", pipe);
|
||||
/* enable PCH DPLL */
|
||||
temp = I915_READ(pch_dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) == 0) {
|
||||
I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
I915_READ(pch_dpll_reg);
|
||||
}
|
||||
|
||||
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
|
||||
FDI_SEL_PCDCLK |
|
||||
FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
|
||||
I915_READ(fdi_rx_reg);
|
||||
udelay(200);
|
||||
|
||||
/* Enable CPU FDI TX PLL, always on for IGDNG */
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
||||
I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
|
||||
I915_READ(fdi_tx_reg);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
/* Enable CPU pipe */
|
||||
temp = I915_READ(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) == 0) {
|
||||
I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
|
||||
I915_READ(pipeconf_reg);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
/* configure and enable CPU plane */
|
||||
temp = I915_READ(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
|
||||
I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
||||
}
|
||||
|
||||
/* enable CPU FDI TX and PCH FDI RX */
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
temp |= FDI_TX_ENABLE;
|
||||
temp |= FDI_DP_PORT_WIDTH_X4; /* default */
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
||||
I915_WRITE(fdi_tx_reg, temp);
|
||||
I915_READ(fdi_tx_reg);
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
||||
I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
||||
I915_READ(fdi_rx_reg);
|
||||
|
||||
udelay(150);
|
||||
|
||||
/* Train FDI. */
|
||||
/* umask FDI RX Interrupt symbol_lock and bit_lock bit
|
||||
for train result */
|
||||
temp = I915_READ(fdi_rx_imr_reg);
|
||||
temp &= ~FDI_RX_SYMBOL_LOCK;
|
||||
temp &= ~FDI_RX_BIT_LOCK;
|
||||
I915_WRITE(fdi_rx_imr_reg, temp);
|
||||
I915_READ(fdi_rx_imr_reg);
|
||||
udelay(150);
|
||||
|
||||
temp = I915_READ(fdi_rx_iir_reg);
|
||||
DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
||||
|
||||
if ((temp & FDI_RX_BIT_LOCK) == 0) {
|
||||
for (j = 0; j < tries; j++) {
|
||||
temp = I915_READ(fdi_rx_iir_reg);
|
||||
DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
||||
if (temp & FDI_RX_BIT_LOCK)
|
||||
break;
|
||||
udelay(200);
|
||||
}
|
||||
if (j != tries)
|
||||
I915_WRITE(fdi_rx_iir_reg,
|
||||
temp | FDI_RX_BIT_LOCK);
|
||||
else
|
||||
DRM_DEBUG("train 1 fail\n");
|
||||
} else {
|
||||
I915_WRITE(fdi_rx_iir_reg,
|
||||
temp | FDI_RX_BIT_LOCK);
|
||||
DRM_DEBUG("train 1 ok 2!\n");
|
||||
}
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
||||
I915_WRITE(fdi_tx_reg, temp);
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
||||
I915_WRITE(fdi_rx_reg, temp);
|
||||
|
||||
udelay(150);
|
||||
|
||||
temp = I915_READ(fdi_rx_iir_reg);
|
||||
DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
||||
|
||||
if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
|
||||
for (j = 0; j < tries; j++) {
|
||||
temp = I915_READ(fdi_rx_iir_reg);
|
||||
DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
||||
if (temp & FDI_RX_SYMBOL_LOCK)
|
||||
break;
|
||||
udelay(200);
|
||||
}
|
||||
if (j != tries) {
|
||||
I915_WRITE(fdi_rx_iir_reg,
|
||||
temp | FDI_RX_SYMBOL_LOCK);
|
||||
DRM_DEBUG("train 2 ok 1!\n");
|
||||
} else
|
||||
DRM_DEBUG("train 2 fail\n");
|
||||
} else {
|
||||
I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK);
|
||||
DRM_DEBUG("train 2 ok 2!\n");
|
||||
}
|
||||
DRM_DEBUG("train done\n");
|
||||
|
||||
/* set transcoder timing */
|
||||
I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
|
||||
I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
|
||||
I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
|
||||
|
||||
I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
|
||||
I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
|
||||
I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
|
||||
|
||||
/* enable PCH transcoder */
|
||||
temp = I915_READ(transconf_reg);
|
||||
I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
|
||||
I915_READ(transconf_reg);
|
||||
|
||||
while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
|
||||
;
|
||||
|
||||
/* enable normal */
|
||||
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
|
||||
FDI_TX_ENHANCE_FRAME_ENABLE);
|
||||
I915_READ(fdi_tx_reg);
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
|
||||
FDI_RX_ENHANCE_FRAME_ENABLE);
|
||||
I915_READ(fdi_rx_reg);
|
||||
|
||||
/* wait one idle pattern time */
|
||||
udelay(100);
|
||||
|
||||
intel_crtc_load_lut(crtc);
|
||||
|
||||
break;
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
DRM_DEBUG("crtc %d dpms off\n", pipe);
|
||||
|
||||
/* Disable the VGA plane that we never use */
|
||||
I915_WRITE(CPU_VGACNTRL, VGA_DISP_DISABLE);
|
||||
|
||||
/* Disable display plane */
|
||||
temp = I915_READ(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
|
||||
I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
||||
I915_READ(dspbase_reg);
|
||||
}
|
||||
|
||||
/* disable cpu pipe, disable after all planes disabled */
|
||||
temp = I915_READ(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) != 0) {
|
||||
I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
I915_READ(pipeconf_reg);
|
||||
/* wait for cpu pipe off, pipe state */
|
||||
while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0)
|
||||
;
|
||||
} else
|
||||
DRM_DEBUG("crtc %d is disabled\n", pipe);
|
||||
|
||||
/* IGDNG-A : disable cpu panel fitter ? */
|
||||
temp = I915_READ(pf_ctl_reg);
|
||||
if ((temp & PF_ENABLE) != 0) {
|
||||
I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
|
||||
I915_READ(pf_ctl_reg);
|
||||
}
|
||||
|
||||
/* disable CPU FDI tx and PCH FDI rx */
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
|
||||
I915_READ(fdi_tx_reg);
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
|
||||
I915_READ(fdi_rx_reg);
|
||||
|
||||
/* still set train pattern 1 */
|
||||
temp = I915_READ(fdi_tx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
||||
I915_WRITE(fdi_tx_reg, temp);
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
temp &= ~FDI_LINK_TRAIN_NONE;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
||||
I915_WRITE(fdi_rx_reg, temp);
|
||||
|
||||
/* disable PCH transcoder */
|
||||
temp = I915_READ(transconf_reg);
|
||||
if ((temp & TRANS_ENABLE) != 0) {
|
||||
I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
|
||||
I915_READ(transconf_reg);
|
||||
/* wait for PCH transcoder off, transcoder state */
|
||||
while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PCH DPLL */
|
||||
temp = I915_READ(pch_dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) != 0) {
|
||||
I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
||||
I915_READ(pch_dpll_reg);
|
||||
}
|
||||
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
if ((temp & FDI_RX_PLL_ENABLE) != 0) {
|
||||
temp &= ~FDI_SEL_PCDCLK;
|
||||
temp &= ~FDI_RX_PLL_ENABLE;
|
||||
I915_WRITE(fdi_rx_reg, temp);
|
||||
I915_READ(fdi_rx_reg);
|
||||
}
|
||||
|
||||
/* Wait for the clocks to turn off. */
|
||||
udelay(150);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
@ -805,7 +1209,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off
|
||||
* and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
|
||||
@ -890,6 +1293,26 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
udelay(150);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the power management mode of the pipe and plane.
|
||||
*
|
||||
* This code should probably grow support for turning the cursor off and back
|
||||
* on appropriately at the same time as we're turning the pipe off/on.
|
||||
*/
|
||||
static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
bool enabled;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
igdng_crtc_dpms(crtc, mode);
|
||||
else
|
||||
i9xx_crtc_dpms(crtc, mode);
|
||||
|
||||
if (!dev->primary->master)
|
||||
return;
|
||||
@ -947,6 +1370,12 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
if (IS_IGDNG(dev)) {
|
||||
/* FDI link clock is fixed at 2.7G */
|
||||
if (mode->clock * 3 > 27000 * 4)
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1030,6 +1459,48 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct fdi_m_n {
|
||||
u32 tu;
|
||||
u32 gmch_m;
|
||||
u32 gmch_n;
|
||||
u32 link_m;
|
||||
u32 link_n;
|
||||
};
|
||||
|
||||
static void
|
||||
fdi_reduce_ratio(u32 *num, u32 *den)
|
||||
{
|
||||
while (*num > 0xffffff || *den > 0xffffff) {
|
||||
*num >>= 1;
|
||||
*den >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define DATA_N 0x800000
|
||||
#define LINK_N 0x80000
|
||||
|
||||
static void
|
||||
igdng_compute_m_n(int bytes_per_pixel, int nlanes,
|
||||
int pixel_clock, int link_clock,
|
||||
struct fdi_m_n *m_n)
|
||||
{
|
||||
u64 temp;
|
||||
|
||||
m_n->tu = 64; /* default size */
|
||||
|
||||
temp = (u64) DATA_N * pixel_clock;
|
||||
temp = div_u64(temp, link_clock);
|
||||
m_n->gmch_m = (temp * bytes_per_pixel) / nlanes;
|
||||
m_n->gmch_n = DATA_N;
|
||||
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
||||
|
||||
temp = (u64) LINK_N * pixel_clock;
|
||||
m_n->link_m = div_u64(temp, link_clock);
|
||||
m_n->link_n = LINK_N;
|
||||
fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
|
||||
}
|
||||
|
||||
|
||||
static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
@ -1063,6 +1534,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_connector *connector;
|
||||
const intel_limit_t *limit;
|
||||
int ret;
|
||||
struct fdi_m_n m_n = {0};
|
||||
int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
|
||||
int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
|
||||
int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
|
||||
int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
|
||||
int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
|
||||
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
|
||||
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
||||
int lvds_reg = LVDS;
|
||||
u32 temp;
|
||||
int sdvo_pixel_multiply;
|
||||
|
||||
drm_vblank_pre_modeset(dev, pipe);
|
||||
|
||||
@ -1101,6 +1583,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
|
||||
} else if (IS_I9XX(dev)) {
|
||||
refclk = 96000;
|
||||
if (IS_IGDNG(dev))
|
||||
refclk = 120000; /* 120Mhz refclk */
|
||||
} else {
|
||||
refclk = 48000;
|
||||
}
|
||||
@ -1114,6 +1598,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
|
||||
if (!ok) {
|
||||
DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
||||
drm_vblank_post_modeset(dev, pipe);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1137,12 +1622,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
|
||||
/* FDI link */
|
||||
if (IS_IGDNG(dev))
|
||||
igdng_compute_m_n(3, 4, /* lane num 4 */
|
||||
adjusted_mode->clock,
|
||||
270000, /* lane clock */
|
||||
&m_n);
|
||||
|
||||
if (IS_IGD(dev))
|
||||
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
|
||||
else
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
if (!IS_IGDNG(dev))
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
if (is_lvds)
|
||||
dpll |= DPLLB_MODE_LVDS;
|
||||
@ -1150,17 +1644,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
dpll |= DPLLB_MODE_DAC_SERIAL;
|
||||
if (is_sdvo) {
|
||||
dpll |= DPLL_DVO_HIGH_SPEED;
|
||||
if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
if (IS_I945G(dev) || IS_I945GM(dev))
|
||||
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
|
||||
}
|
||||
else if (IS_IGDNG(dev))
|
||||
dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
|
||||
}
|
||||
|
||||
/* compute bitmask from p1 value */
|
||||
if (IS_IGD(dev))
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
|
||||
else
|
||||
else {
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
||||
/* also FPA1 */
|
||||
if (IS_IGDNG(dev))
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
||||
}
|
||||
switch (clock.p2) {
|
||||
case 5:
|
||||
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
|
||||
@ -1175,7 +1674,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
||||
break;
|
||||
}
|
||||
if (IS_I965G(dev))
|
||||
if (IS_I965G(dev) && !IS_IGDNG(dev))
|
||||
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
|
||||
} else {
|
||||
if (is_lvds) {
|
||||
@ -1207,10 +1706,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
/* Set up the display plane register */
|
||||
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
||||
|
||||
if (pipe == 0)
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_A;
|
||||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
/* IGDNG's plane is forced to pipe, bit 24 is to
|
||||
enable color space conversion */
|
||||
if (!IS_IGDNG(dev)) {
|
||||
if (pipe == 0)
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_A;
|
||||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
}
|
||||
|
||||
if (pipe == 0 && !IS_I965G(dev)) {
|
||||
/* Enable pixel doubling when the dot clock is > 90% of the (display)
|
||||
@ -1231,12 +1734,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
|
||||
|
||||
/* Disable the panel fitter if it was on our pipe */
|
||||
if (intel_panel_fitter_pipe(dev) == pipe)
|
||||
if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe)
|
||||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
|
||||
DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
|
||||
/* assign to IGDNG registers */
|
||||
if (IS_IGDNG(dev)) {
|
||||
fp_reg = pch_fp_reg;
|
||||
dpll_reg = pch_dpll_reg;
|
||||
}
|
||||
|
||||
if (dpll & DPLL_VCO_ENABLE) {
|
||||
I915_WRITE(fp_reg, fp);
|
||||
@ -1245,13 +1753,33 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
udelay(150);
|
||||
}
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
/* enable PCH clock reference source */
|
||||
/* XXX need to change the setting for other outputs */
|
||||
u32 temp;
|
||||
temp = I915_READ(PCH_DREF_CONTROL);
|
||||
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
||||
temp |= DREF_NONSPREAD_CK505_ENABLE;
|
||||
temp &= ~DREF_SSC_SOURCE_MASK;
|
||||
temp |= DREF_SSC_SOURCE_ENABLE;
|
||||
temp &= ~DREF_SSC1_ENABLE;
|
||||
/* if no eDP, disable source output to CPU */
|
||||
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
||||
temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||
}
|
||||
|
||||
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
||||
* This is an exception to the general rule that mode_set doesn't turn
|
||||
* things on.
|
||||
*/
|
||||
if (is_lvds) {
|
||||
u32 lvds = I915_READ(LVDS);
|
||||
u32 lvds;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
lvds_reg = PCH_LVDS;
|
||||
|
||||
lvds = I915_READ(lvds_reg);
|
||||
lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
|
||||
/* Set the B0-B3 data pairs corresponding to whether we're going to
|
||||
* set the DPLLs for dual-channel mode or not.
|
||||
@ -1266,8 +1794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
* panels behave in the two modes.
|
||||
*/
|
||||
|
||||
I915_WRITE(LVDS, lvds);
|
||||
I915_READ(LVDS);
|
||||
I915_WRITE(lvds_reg, lvds);
|
||||
I915_READ(lvds_reg);
|
||||
}
|
||||
|
||||
I915_WRITE(fp_reg, fp);
|
||||
@ -1276,8 +1804,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
/* Wait for the clocks to stabilize. */
|
||||
udelay(150);
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
if (IS_I965G(dev) && !IS_IGDNG(dev)) {
|
||||
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
|
||||
((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
|
||||
} else {
|
||||
@ -1303,9 +1831,25 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
/* pipesrc and dspsize control the size that is scaled from, which should
|
||||
* always be the user's requested size.
|
||||
*/
|
||||
I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
|
||||
I915_WRITE(dsppos_reg, 0);
|
||||
if (!IS_IGDNG(dev)) {
|
||||
I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
|
||||
(mode->hdisplay - 1));
|
||||
I915_WRITE(dsppos_reg, 0);
|
||||
}
|
||||
I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
|
||||
I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
|
||||
I915_WRITE(link_m1_reg, m_n.link_m);
|
||||
I915_WRITE(link_n1_reg, m_n.link_n);
|
||||
|
||||
/* enable FDI RX PLL too */
|
||||
temp = I915_READ(fdi_rx_reg);
|
||||
I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
I915_WRITE(pipeconf_reg, pipeconf);
|
||||
I915_READ(pipeconf_reg);
|
||||
|
||||
@ -1315,12 +1859,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
|
||||
/* Flush the plane changes */
|
||||
ret = intel_pipe_set_base(crtc, x, y, old_fb);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
drm_vblank_post_modeset(dev, pipe);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Loads the palette/gamma unit for the CRTC with the prepared values */
|
||||
@ -1336,6 +1877,11 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
||||
if (!crtc->enabled)
|
||||
return;
|
||||
|
||||
/* use legacy palette for IGDNG */
|
||||
if (IS_IGDNG(dev))
|
||||
palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
|
||||
LGC_PALETTE_B;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
I915_WRITE(palreg + 4 * i,
|
||||
(intel_crtc->lut_r[i] << 16) |
|
||||
@ -1464,16 +2010,16 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
uint32_t adder;
|
||||
|
||||
if (x < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
temp |= x << CURSOR_X_SHIFT;
|
||||
temp |= y << CURSOR_Y_SHIFT;
|
||||
|
||||
adder = intel_crtc->cursor_addr;
|
||||
I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
|
||||
@ -1590,6 +2136,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
|
||||
}
|
||||
|
||||
encoder->crtc = crtc;
|
||||
intel_output->base.encoder = encoder;
|
||||
intel_output->load_detect_temp = true;
|
||||
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
@ -1625,6 +2172,7 @@ void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_
|
||||
|
||||
if (intel_output->load_detect_temp) {
|
||||
encoder->crtc = NULL;
|
||||
intel_output->base.encoder = NULL;
|
||||
intel_output->load_detect_temp = false;
|
||||
crtc->enabled = drm_helper_crtc_in_use(crtc);
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
@ -1762,6 +2310,8 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
if (intel_crtc->mode_set.mode)
|
||||
drm_mode_destroy(crtc->dev, intel_crtc->mode_set.mode);
|
||||
drm_crtc_cleanup(crtc);
|
||||
kfree(intel_crtc);
|
||||
}
|
||||
@ -1888,7 +2438,24 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
intel_lvds_init(dev);
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
if (IS_IGDNG(dev)) {
|
||||
int found;
|
||||
|
||||
if (I915_READ(HDMIB) & PORT_DETECTED) {
|
||||
/* check SDVOB */
|
||||
/* found = intel_sdvo_init(dev, HDMIB); */
|
||||
found = 0;
|
||||
if (!found)
|
||||
intel_hdmi_init(dev, HDMIB);
|
||||
}
|
||||
|
||||
if (I915_READ(HDMIC) & PORT_DETECTED)
|
||||
intel_hdmi_init(dev, HDMIC);
|
||||
|
||||
if (I915_READ(HDMID) & PORT_DETECTED)
|
||||
intel_hdmi_init(dev, HDMID);
|
||||
|
||||
} else if (IS_I9XX(dev)) {
|
||||
int found;
|
||||
u32 reg;
|
||||
|
||||
@ -1912,7 +2479,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
} else
|
||||
intel_dvo_init(dev);
|
||||
|
||||
if (IS_I9XX(dev) && IS_MOBILE(dev))
|
||||
if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev))
|
||||
intel_tv_init(dev);
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
|
@ -207,7 +207,7 @@ static int intelfb_set_par(struct fb_info *info)
|
||||
|
||||
if (var->pixclock != -1) {
|
||||
|
||||
DRM_ERROR("PIXEL CLCOK SET\n");
|
||||
DRM_ERROR("PIXEL CLOCK SET\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct drm_crtc *crtc;
|
||||
@ -674,8 +674,12 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *
|
||||
par->crtc_ids[0] = crtc->base.id;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->mode != modeset->crtc->desired_mode)
|
||||
modeset->mode = modeset->crtc->desired_mode;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = drm_mode_duplicate(dev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
|
||||
par->crtc_count = 1;
|
||||
|
||||
@ -824,8 +828,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
|
||||
par->crtc_ids[crtc_count++] = crtc->base.id;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->mode != modeset->crtc->desired_mode)
|
||||
modeset->mode = modeset->crtc->desired_mode;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = drm_mode_duplicate(dev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
}
|
||||
par->crtc_count = crtc_count;
|
||||
|
||||
@ -857,9 +865,15 @@ void intelfb_restore(void)
|
||||
drm_crtc_helper_set_config(&kernelfb_mode);
|
||||
}
|
||||
|
||||
static void intelfb_restore_work_fn(struct work_struct *ignored)
|
||||
{
|
||||
intelfb_restore();
|
||||
}
|
||||
static DECLARE_WORK(intelfb_restore_work, intelfb_restore_work_fn);
|
||||
|
||||
static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
|
||||
{
|
||||
intelfb_restore();
|
||||
schedule_work(&intelfb_restore_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_intelfb_restore_op = {
|
||||
|
@ -56,7 +56,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
sdvox = SDVO_ENCODING_HDMI |
|
||||
SDVO_BORDER_ENABLE |
|
||||
SDVO_VSYNC_ACTIVE_HIGH |
|
||||
SDVO_HSYNC_ACTIVE_HIGH;
|
||||
SDVO_HSYNC_ACTIVE_HIGH |
|
||||
SDVO_NULL_PACKETS_DURING_VSYNC;
|
||||
|
||||
if (hdmi_priv->has_hdmi_sink)
|
||||
sdvox |= SDVO_AUDIO_ENABLE;
|
||||
@ -144,6 +145,22 @@ intel_hdmi_sink_detect(struct drm_connector *connector)
|
||||
}
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
igdng_hdmi_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
||||
|
||||
/* FIXME hotplug detect */
|
||||
|
||||
hdmi_priv->has_hdmi_sink = false;
|
||||
intel_hdmi_sink_detect(connector);
|
||||
if (hdmi_priv->has_hdmi_sink)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_hdmi_detect(struct drm_connector *connector)
|
||||
{
|
||||
@ -153,6 +170,9 @@ intel_hdmi_detect(struct drm_connector *connector)
|
||||
struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
||||
u32 temp, bit;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return igdng_hdmi_detect(connector);
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
|
||||
switch (hdmi_priv->sdvox_reg) {
|
||||
@ -269,8 +289,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
||||
/* Set up the DDC bus. */
|
||||
if (sdvox_reg == SDVOB)
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
|
||||
else
|
||||
else if (sdvox_reg == SDVOC)
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
|
||||
else if (sdvox_reg == HDMIB)
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
|
||||
"HDMIB");
|
||||
else if (sdvox_reg == HDMIC)
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
|
||||
"HDMIC");
|
||||
else if (sdvox_reg == HDMID)
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
|
||||
"HDMID");
|
||||
|
||||
if (!intel_output->ddc_bus)
|
||||
goto err_connector;
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define I915_LVDS "i915_lvds"
|
||||
|
||||
/**
|
||||
* Sets the backlight level.
|
||||
*
|
||||
@ -45,10 +47,15 @@
|
||||
static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 blc_pwm_ctl;
|
||||
u32 blc_pwm_ctl, reg;
|
||||
|
||||
blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
|
||||
if (IS_IGDNG(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
||||
blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(reg, (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
|
||||
}
|
||||
|
||||
@ -58,8 +65,14 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
|
||||
return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
if (IS_IGDNG(dev))
|
||||
reg = BLC_PWM_PCH_CTL2;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
||||
return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
}
|
||||
|
||||
@ -69,23 +82,31 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_status;
|
||||
u32 pp_status, ctl_reg, status_reg;
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
ctl_reg = PCH_PP_CONTROL;
|
||||
status_reg = PCH_PP_STATUS;
|
||||
} else {
|
||||
ctl_reg = PP_CONTROL;
|
||||
status_reg = PP_STATUS;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
|
||||
POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = I915_READ(PP_STATUS);
|
||||
pp_status = I915_READ(status_reg);
|
||||
} while ((pp_status & PP_ON) == 0);
|
||||
|
||||
intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
|
||||
} else {
|
||||
intel_lvds_set_backlight(dev, 0);
|
||||
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) &
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
|
||||
~POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = I915_READ(PP_STATUS);
|
||||
pp_status = I915_READ(status_reg);
|
||||
} while (pp_status & PP_ON);
|
||||
}
|
||||
}
|
||||
@ -106,12 +127,28 @@ static void intel_lvds_save(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
||||
u32 pwm_ctl_reg;
|
||||
|
||||
dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS);
|
||||
dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS);
|
||||
dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
|
||||
dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
|
||||
if (IS_IGDNG(dev)) {
|
||||
pp_on_reg = PCH_PP_ON_DELAYS;
|
||||
pp_off_reg = PCH_PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PCH_PP_CONTROL;
|
||||
pp_div_reg = PCH_PP_DIVISOR;
|
||||
pwm_ctl_reg = BLC_PWM_CPU_CTL;
|
||||
} else {
|
||||
pp_on_reg = PP_ON_DELAYS;
|
||||
pp_off_reg = PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PP_CONTROL;
|
||||
pp_div_reg = PP_DIVISOR;
|
||||
pwm_ctl_reg = BLC_PWM_CTL;
|
||||
}
|
||||
|
||||
dev_priv->savePP_ON = I915_READ(pp_on_reg);
|
||||
dev_priv->savePP_OFF = I915_READ(pp_off_reg);
|
||||
dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
|
||||
dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
|
||||
@ -127,12 +164,28 @@ static void intel_lvds_restore(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
||||
u32 pwm_ctl_reg;
|
||||
|
||||
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
|
||||
I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON);
|
||||
I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF);
|
||||
I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
|
||||
I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
|
||||
if (IS_IGDNG(dev)) {
|
||||
pp_on_reg = PCH_PP_ON_DELAYS;
|
||||
pp_off_reg = PCH_PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PCH_PP_CONTROL;
|
||||
pp_div_reg = PCH_PP_DIVISOR;
|
||||
pwm_ctl_reg = BLC_PWM_CPU_CTL;
|
||||
} else {
|
||||
pp_on_reg = PP_ON_DELAYS;
|
||||
pp_off_reg = PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PP_CONTROL;
|
||||
pp_div_reg = PP_DIVISOR;
|
||||
pwm_ctl_reg = BLC_PWM_CTL;
|
||||
}
|
||||
|
||||
I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
|
||||
I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
|
||||
I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
|
||||
I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
|
||||
I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
|
||||
if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
|
||||
intel_lvds_set_power(dev, true);
|
||||
else
|
||||
@ -216,8 +269,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
|
||||
if (IS_IGDNG(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
|
||||
@ -251,6 +310,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
||||
* settings.
|
||||
*/
|
||||
|
||||
/* No panel fitting yet, fixme */
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Enable automatic panel scaling so that non-native modes fill the
|
||||
* screen. Should be enabled before the pipe is enabled, according to
|
||||
@ -382,7 +445,8 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
|
||||
|
||||
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
DRM_DEBUG("Skipping LVDS initialization for %s\n", id->ident);
|
||||
DRM_DEBUG_KMS(I915_LVDS,
|
||||
"Skipping LVDS initialization for %s\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -420,8 +484,21 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
|
||||
},
|
||||
},
|
||||
|
||||
/* FIXME: add a check for the Aopen Mini PC */
|
||||
{
|
||||
.callback = intel_no_lvds_dmi_callback,
|
||||
.ident = "AOpen Mini PC",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = intel_no_lvds_dmi_callback,
|
||||
.ident = "Aopen i945GTt-VFA",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
|
||||
},
|
||||
},
|
||||
|
||||
{ } /* terminating entry */
|
||||
};
|
||||
@ -442,12 +519,18 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
||||
struct drm_crtc *crtc;
|
||||
u32 lvds;
|
||||
int pipe;
|
||||
int pipe, gpio = GPIOC;
|
||||
|
||||
/* Skip init on machines we know falsely report LVDS */
|
||||
if (dmi_check_system(intel_no_lvds))
|
||||
return;
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
|
||||
return;
|
||||
gpio = PCH_GPIOC;
|
||||
}
|
||||
|
||||
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
return;
|
||||
@ -482,7 +565,7 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
*/
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
@ -524,6 +607,11 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
* on. If so, assume that whatever is currently programmed is the
|
||||
* correct mode.
|
||||
*/
|
||||
|
||||
/* IGDNG: FIXME if still fail, not try pipe mode now */
|
||||
if (IS_IGDNG(dev))
|
||||
goto failed;
|
||||
|
||||
lvds = I915_READ(LVDS);
|
||||
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
|
||||
crtc = intel_get_crtc_from_pipe(dev, pipe);
|
||||
@ -542,11 +630,22 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
goto failed;
|
||||
|
||||
out:
|
||||
if (IS_IGDNG(dev)) {
|
||||
u32 pwm;
|
||||
/* make sure PWM is enabled */
|
||||
pwm = I915_READ(BLC_PWM_CPU_CTL2);
|
||||
pwm |= (PWM_ENABLE | PWM_PIPE_B);
|
||||
I915_WRITE(BLC_PWM_CPU_CTL2, pwm);
|
||||
|
||||
pwm = I915_READ(BLC_PWM_PCH_CTL1);
|
||||
pwm |= PWM_PCH_ENABLE;
|
||||
I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
|
||||
}
|
||||
drm_sysfs_connector_add(connector);
|
||||
return;
|
||||
|
||||
failed:
|
||||
DRM_DEBUG("No LVDS modes found, disabling.\n");
|
||||
DRM_DEBUG_KMS(I915_LVDS, "No LVDS modes found, disabling.\n");
|
||||
if (intel_output->ddc_bus)
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
drm_connector_cleanup(connector);
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "intel_sdvo_regs.h"
|
||||
|
||||
#undef SDVO_DEBUG
|
||||
|
||||
#define I915_SDVO "i915_sdvo"
|
||||
struct intel_sdvo_priv {
|
||||
struct intel_i2c_chan *i2c_bus;
|
||||
int slaveaddr;
|
||||
@ -277,20 +277,21 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s: W: %02X ",
|
||||
SDVO_NAME(sdvo_priv), cmd);
|
||||
for (i = 0; i < args_len; i++)
|
||||
printk(KERN_DEBUG "%02X ", ((u8 *)args)[i]);
|
||||
DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
|
||||
for (; i < 8; i++)
|
||||
printk(KERN_DEBUG " ");
|
||||
DRM_LOG_KMS(" ");
|
||||
for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
|
||||
if (cmd == sdvo_cmd_names[i].cmd) {
|
||||
printk(KERN_DEBUG "(%s)", sdvo_cmd_names[i].name);
|
||||
DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
|
||||
printk(KERN_DEBUG "(%02X)", cmd);
|
||||
printk(KERN_DEBUG "\n");
|
||||
DRM_LOG_KMS("(%02X)", cmd);
|
||||
DRM_LOG_KMS("\n");
|
||||
}
|
||||
#else
|
||||
#define intel_sdvo_debug_write(o, c, a, l)
|
||||
@ -329,16 +330,16 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "%s: R: ", SDVO_NAME(sdvo_priv));
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s: R: ", SDVO_NAME(sdvo_priv));
|
||||
for (i = 0; i < response_len; i++)
|
||||
printk(KERN_DEBUG "%02X ", ((u8 *)response)[i]);
|
||||
DRM_LOG_KMS("%02X ", ((u8 *)response)[i]);
|
||||
for (; i < 8; i++)
|
||||
printk(KERN_DEBUG " ");
|
||||
DRM_LOG_KMS(" ");
|
||||
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
|
||||
printk(KERN_DEBUG "(%s)", cmd_status_names[status]);
|
||||
DRM_LOG_KMS("(%s)", cmd_status_names[status]);
|
||||
else
|
||||
printk(KERN_DEBUG "(??? %d)", status);
|
||||
printk(KERN_DEBUG "\n");
|
||||
DRM_LOG_KMS("(??? %d)", status);
|
||||
DRM_LOG_KMS("\n");
|
||||
}
|
||||
#else
|
||||
#define intel_sdvo_debug_response(o, r, l, s)
|
||||
@ -1742,6 +1743,43 @@ static struct i2c_algorithm intel_sdvo_i2c_bit_algo = {
|
||||
.master_xfer = intel_sdvo_master_xfer,
|
||||
};
|
||||
|
||||
static u8
|
||||
intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct sdvo_device_mapping *my_mapping, *other_mapping;
|
||||
|
||||
if (output_device == SDVOB) {
|
||||
my_mapping = &dev_priv->sdvo_mappings[0];
|
||||
other_mapping = &dev_priv->sdvo_mappings[1];
|
||||
} else {
|
||||
my_mapping = &dev_priv->sdvo_mappings[1];
|
||||
other_mapping = &dev_priv->sdvo_mappings[0];
|
||||
}
|
||||
|
||||
/* If the BIOS described our SDVO device, take advantage of it. */
|
||||
if (my_mapping->slave_addr)
|
||||
return my_mapping->slave_addr;
|
||||
|
||||
/* If the BIOS only described a different SDVO device, use the
|
||||
* address that it isn't using.
|
||||
*/
|
||||
if (other_mapping->slave_addr) {
|
||||
if (other_mapping->slave_addr == 0x70)
|
||||
return 0x72;
|
||||
else
|
||||
return 0x70;
|
||||
}
|
||||
|
||||
/* No SDVO device info is found for another DVO port,
|
||||
* so use mapping assumption we had before BIOS parsing.
|
||||
*/
|
||||
if (output_device == SDVOB)
|
||||
return 0x70;
|
||||
else
|
||||
return 0x72;
|
||||
}
|
||||
|
||||
bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
@ -1753,6 +1791,7 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
u8 ch[0x40];
|
||||
int i;
|
||||
int encoder_type, output_id;
|
||||
u8 slave_addr;
|
||||
|
||||
intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
@ -1771,16 +1810,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
if (!i2cbus)
|
||||
goto err_inteloutput;
|
||||
|
||||
slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
|
||||
sdvo_priv->i2c_bus = i2cbus;
|
||||
|
||||
if (output_device == SDVOB) {
|
||||
output_id = 1;
|
||||
sdvo_priv->i2c_bus->slave_addr = 0x38;
|
||||
} else {
|
||||
output_id = 2;
|
||||
sdvo_priv->i2c_bus->slave_addr = 0x39;
|
||||
}
|
||||
|
||||
sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1;
|
||||
sdvo_priv->output_device = output_device;
|
||||
intel_output->i2c_bus = i2cbus;
|
||||
intel_output->dev_priv = sdvo_priv;
|
||||
@ -1788,8 +1826,9 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
/* Read the regs to test if we can talk to the device */
|
||||
for (i = 0; i < 0x40; i++) {
|
||||
if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
|
||||
DRM_DEBUG("No SDVO device found on SDVO%c\n",
|
||||
output_device == SDVOB ? 'B' : 'C');
|
||||
DRM_DEBUG_KMS(I915_SDVO,
|
||||
"No SDVO device found on SDVO%c\n",
|
||||
output_device == SDVOB ? 'B' : 'C');
|
||||
goto err_i2c;
|
||||
}
|
||||
}
|
||||
@ -1873,9 +1912,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
|
||||
sdvo_priv->controlled_output = 0;
|
||||
memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
|
||||
DRM_DEBUG("%s: Unknown SDVO output type (0x%02x%02x)\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
bytes[0], bytes[1]);
|
||||
DRM_DEBUG_KMS(I915_SDVO,
|
||||
"%s: Unknown SDVO output type (0x%02x%02x)\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
bytes[0], bytes[1]);
|
||||
encoder_type = DRM_MODE_ENCODER_NONE;
|
||||
connector_type = DRM_MODE_CONNECTOR_Unknown;
|
||||
goto err_i2c;
|
||||
@ -1905,21 +1945,21 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
&sdvo_priv->pixel_clock_max);
|
||||
|
||||
|
||||
DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
|
||||
"clock range %dMHz - %dMHz, "
|
||||
"input 1: %c, input 2: %c, "
|
||||
"output 1: %c, output 2: %c\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
|
||||
sdvo_priv->caps.device_rev_id,
|
||||
sdvo_priv->pixel_clock_min / 1000,
|
||||
sdvo_priv->pixel_clock_max / 1000,
|
||||
(sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
|
||||
(sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
|
||||
/* check currently supported outputs */
|
||||
sdvo_priv->caps.output_flags &
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s device VID/DID: %02X:%02X.%02X, "
|
||||
"clock range %dMHz - %dMHz, "
|
||||
"input 1: %c, input 2: %c, "
|
||||
"output 1: %c, output 2: %c\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
|
||||
sdvo_priv->caps.device_rev_id,
|
||||
sdvo_priv->pixel_clock_min / 1000,
|
||||
sdvo_priv->pixel_clock_max / 1000,
|
||||
(sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
|
||||
(sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
|
||||
/* check currently supported outputs */
|
||||
sdvo_priv->caps.output_flags &
|
||||
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
|
||||
sdvo_priv->caps.output_flags &
|
||||
sdvo_priv->caps.output_flags &
|
||||
(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
|
||||
|
||||
return true;
|
||||
|
@ -1392,6 +1392,9 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
|
||||
tv_ctl &= ~TV_TEST_MODE_MASK;
|
||||
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
|
||||
tv_dac &= ~TVDAC_SENSE_MASK;
|
||||
tv_dac &= ~DAC_A_MASK;
|
||||
tv_dac &= ~DAC_B_MASK;
|
||||
tv_dac &= ~DAC_C_MASK;
|
||||
tv_dac |= (TVDAC_STATE_CHG_EN |
|
||||
TVDAC_A_SENSE_CTL |
|
||||
TVDAC_B_SENSE_CTL |
|
||||
|
@ -478,26 +478,27 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV770 PFP Microcode\n");
|
||||
DRM_INFO("Loading RV770/RV790 PFP Microcode\n");
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
DRM_INFO("Loading RV770 CP Microcode\n");
|
||||
DRM_INFO("Loading RV770/RV790 CP Microcode\n");
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730)) {
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)) {
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV730 PFP Microcode\n");
|
||||
DRM_INFO("Loading RV730/RV740 PFP Microcode\n");
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
DRM_INFO("Loading RV730 CP Microcode\n");
|
||||
DRM_INFO("Loading RV730/RV740 CP Microcode\n");
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
@ -1324,6 +1325,10 @@ static void r700_gfx_init(struct drm_device *dev,
|
||||
dev_priv->r700_sc_prim_fifo_size = 0xf9;
|
||||
dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
|
||||
dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
|
||||
if (dev_priv->r600_sx_max_export_pos_size > 16) {
|
||||
dev_priv->r600_sx_max_export_pos_size -= 16;
|
||||
dev_priv->r600_sx_max_export_smx_size += 16;
|
||||
}
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
dev_priv->r600_max_pipes = 2;
|
||||
@ -1345,6 +1350,31 @@ static void r700_gfx_init(struct drm_device *dev,
|
||||
dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
|
||||
dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
|
||||
break;
|
||||
case CHIP_RV740:
|
||||
dev_priv->r600_max_pipes = 4;
|
||||
dev_priv->r600_max_tile_pipes = 4;
|
||||
dev_priv->r600_max_simds = 8;
|
||||
dev_priv->r600_max_backends = 4;
|
||||
dev_priv->r600_max_gprs = 256;
|
||||
dev_priv->r600_max_threads = 248;
|
||||
dev_priv->r600_max_stack_entries = 512;
|
||||
dev_priv->r600_max_hw_contexts = 8;
|
||||
dev_priv->r600_max_gs_threads = 16 * 2;
|
||||
dev_priv->r600_sx_max_export_size = 256;
|
||||
dev_priv->r600_sx_max_export_pos_size = 32;
|
||||
dev_priv->r600_sx_max_export_smx_size = 224;
|
||||
dev_priv->r600_sq_num_cf_insts = 2;
|
||||
|
||||
dev_priv->r700_sx_num_of_sets = 7;
|
||||
dev_priv->r700_sc_prim_fifo_size = 0x100;
|
||||
dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
|
||||
dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
|
||||
|
||||
if (dev_priv->r600_sx_max_export_pos_size > 16) {
|
||||
dev_priv->r600_sx_max_export_pos_size -= 16;
|
||||
dev_priv->r600_sx_max_export_smx_size += 16;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1493,6 +1523,7 @@ static void r700_gfx_init(struct drm_device *dev,
|
||||
break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
default:
|
||||
sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
|
||||
break;
|
||||
@ -1569,6 +1600,7 @@ static void r700_gfx_init(struct drm_device *dev,
|
||||
switch (dev_priv->flags & RADEON_FAMILY_MASK) {
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV740:
|
||||
gs_prim_buffer_depth = 384;
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
|
@ -2109,7 +2109,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
|
||||
|
||||
/* prebuild the SAREA */
|
||||
sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
|
||||
ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
|
||||
ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
|
||||
&master_priv->sarea);
|
||||
if (ret) {
|
||||
DRM_ERROR("SAREA setup failed\n");
|
||||
|
@ -146,6 +146,7 @@ enum radeon_family {
|
||||
CHIP_RV770,
|
||||
CHIP_RV730,
|
||||
CHIP_RV710,
|
||||
CHIP_RV740,
|
||||
CHIP_LAST,
|
||||
};
|
||||
|
||||
|
@ -195,10 +195,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
|
||||
default:
|
||||
vsg->state = dr_via_sg_init;
|
||||
}
|
||||
if (vsg->bounce_buffer) {
|
||||
vfree(vsg->bounce_buffer);
|
||||
vsg->bounce_buffer = NULL;
|
||||
}
|
||||
vfree(vsg->bounce_buffer);
|
||||
vsg->bounce_buffer = NULL;
|
||||
vsg->free_on_sequence = 0;
|
||||
}
|
||||
|
||||
|
@ -638,6 +638,24 @@ int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
|
||||
}
|
||||
EXPORT_SYMBOL(pnp_possible_config);
|
||||
|
||||
int pnp_range_reserved(resource_size_t start, resource_size_t end)
|
||||
{
|
||||
struct pnp_dev *dev;
|
||||
struct pnp_resource *pnp_res;
|
||||
resource_size_t *dev_start, *dev_end;
|
||||
|
||||
pnp_for_each_dev(dev) {
|
||||
list_for_each_entry(pnp_res, &dev->resources, list) {
|
||||
dev_start = &pnp_res->res.start;
|
||||
dev_end = &pnp_res->res.end;
|
||||
if (ranged_conflict(&start, &end, dev_start, dev_end))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pnp_range_reserved);
|
||||
|
||||
/* format is: pnp_reserve_irq=irq1[,irq2] .... */
|
||||
static int __init pnp_setup_reserve_irq(char *str)
|
||||
{
|
||||
|
@ -86,7 +86,17 @@ struct drm_device;
|
||||
|
||||
#include "drm_os_linux.h"
|
||||
#include "drm_hashtab.h"
|
||||
#include "drm_mm.h"
|
||||
|
||||
#define DRM_UT_CORE 0x01
|
||||
#define DRM_UT_DRIVER 0x02
|
||||
#define DRM_UT_KMS 0x04
|
||||
#define DRM_UT_MODE 0x08
|
||||
|
||||
extern void drm_ut_debug_printk(unsigned int request_level,
|
||||
const char *prefix,
|
||||
const char *function_name,
|
||||
const char *format, ...);
|
||||
/***********************************************************************/
|
||||
/** \name DRM template customization defaults */
|
||||
/*@{*/
|
||||
@ -186,15 +196,57 @@ struct drm_device;
|
||||
* \param arg arguments
|
||||
*/
|
||||
#if DRM_DEBUG_CODE
|
||||
#define DRM_DEBUG(fmt, arg...) \
|
||||
#define DRM_DEBUG(fmt, args...) \
|
||||
do { \
|
||||
if ( drm_debug ) \
|
||||
printk(KERN_DEBUG \
|
||||
"[" DRM_NAME ":%s] " fmt , \
|
||||
__func__ , ##arg); \
|
||||
drm_ut_debug_printk(DRM_UT_CORE, DRM_NAME, \
|
||||
__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define DRM_DEBUG_DRIVER(prefix, fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_DRIVER, prefix, \
|
||||
__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_KMS(prefix, fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_KMS, prefix, \
|
||||
__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_MODE(prefix, fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_MODE, prefix, \
|
||||
__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_LOG(fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_CORE, NULL, \
|
||||
NULL, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_LOG_KMS(fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_KMS, NULL, \
|
||||
NULL, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_LOG_MODE(fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_MODE, NULL, \
|
||||
NULL, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_LOG_DRIVER(fmt, args...) \
|
||||
do { \
|
||||
drm_ut_debug_printk(DRM_UT_DRIVER, NULL, \
|
||||
NULL, fmt, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DRM_DEBUG_DRIVER(prefix, fmt, args...) do { } while (0)
|
||||
#define DRM_DEBUG_KMS(prefix, fmt, args...) do { } while (0)
|
||||
#define DRM_DEBUG_MODE(prefix, fmt, args...) do { } while (0)
|
||||
#define DRM_DEBUG(fmt, arg...) do { } while (0)
|
||||
#define DRM_LOG(fmt, arg...) do { } while (0)
|
||||
#define DRM_LOG_KMS(fmt, args...) do { } while (0)
|
||||
#define DRM_LOG_MODE(fmt, arg...) do { } while (0)
|
||||
#define DRM_LOG_DRIVER(fmt, arg...) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define DRM_PROC_LIMIT (PAGE_SIZE-80)
|
||||
@ -237,15 +289,15 @@ struct drm_device;
|
||||
* \param dev DRM device.
|
||||
* \param filp file pointer of the caller.
|
||||
*/
|
||||
#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \
|
||||
do { \
|
||||
if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock) || \
|
||||
file_priv->master->lock.file_priv != file_priv) { \
|
||||
#define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \
|
||||
do { \
|
||||
if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \
|
||||
_file_priv->master->lock.file_priv != _file_priv) { \
|
||||
DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
|
||||
__func__, _DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock),\
|
||||
file_priv->master->lock.file_priv, file_priv); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
__func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\
|
||||
_file_priv->master->lock.file_priv, _file_priv); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
@ -502,26 +554,6 @@ struct drm_sigdata {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Generic memory manager structs
|
||||
*/
|
||||
|
||||
struct drm_mm_node {
|
||||
struct list_head fl_entry;
|
||||
struct list_head ml_entry;
|
||||
int free;
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
struct drm_mm *mm;
|
||||
void *private;
|
||||
};
|
||||
|
||||
struct drm_mm {
|
||||
struct list_head fl_entry;
|
||||
struct list_head ml_entry;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Kernel side of a mapping
|
||||
*/
|
||||
@ -1385,22 +1417,6 @@ extern char *drm_get_connector_status_name(enum drm_connector_status status);
|
||||
extern int drm_sysfs_connector_add(struct drm_connector *connector);
|
||||
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
|
||||
|
||||
/*
|
||||
* Basic memory manager support (drm_mm.c)
|
||||
*/
|
||||
extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
|
||||
unsigned long size,
|
||||
unsigned alignment);
|
||||
extern void drm_mm_put_block(struct drm_mm_node * cur);
|
||||
extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
|
||||
unsigned alignment, int best_match);
|
||||
extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
|
||||
extern void drm_mm_takedown(struct drm_mm *mm);
|
||||
extern int drm_mm_clean(struct drm_mm *mm);
|
||||
extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
|
||||
extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
|
||||
extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
|
||||
|
||||
/* Graphics Execution Manager library functions (drm_gem.c) */
|
||||
int drm_gem_init(struct drm_device *dev);
|
||||
void drm_gem_destroy(struct drm_device *dev);
|
||||
@ -1522,18 +1538,14 @@ static __inline__ void *drm_calloc(size_t nmemb, size_t size, int area)
|
||||
|
||||
static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
|
||||
{
|
||||
u8 *addr;
|
||||
|
||||
if (size <= PAGE_SIZE)
|
||||
if (size * nmemb <= PAGE_SIZE)
|
||||
return kcalloc(nmemb, size, GFP_KERNEL);
|
||||
|
||||
addr = vmalloc(nmemb * size);
|
||||
if (!addr)
|
||||
if (size != 0 && nmemb > ULONG_MAX / size)
|
||||
return NULL;
|
||||
|
||||
memset(addr, 0, nmemb * size);
|
||||
|
||||
return addr;
|
||||
return __vmalloc(size * nmemb,
|
||||
GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
|
||||
}
|
||||
|
||||
static __inline void drm_free_large(void *ptr)
|
||||
|
@ -35,6 +35,8 @@
|
||||
#ifndef DRM_HASHTAB_H
|
||||
#define DRM_HASHTAB_H
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
|
||||
|
||||
struct drm_hash_item {
|
||||
|
90
include/drm/drm_mm.h
Normal file
90
include/drm/drm_mm.h
Normal file
@ -0,0 +1,90 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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:
|
||||
* Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#ifndef _DRM_MM_H_
|
||||
#define _DRM_MM_H_
|
||||
|
||||
/*
|
||||
* Generic range manager structs
|
||||
*/
|
||||
#include <linux/list.h>
|
||||
|
||||
struct drm_mm_node {
|
||||
struct list_head fl_entry;
|
||||
struct list_head ml_entry;
|
||||
int free;
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
struct drm_mm *mm;
|
||||
void *private;
|
||||
};
|
||||
|
||||
struct drm_mm {
|
||||
struct list_head fl_entry;
|
||||
struct list_head ml_entry;
|
||||
struct list_head unused_nodes;
|
||||
int num_unused;
|
||||
spinlock_t unused_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* Basic range manager support (drm_mm.c)
|
||||
*/
|
||||
|
||||
extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
|
||||
unsigned long size,
|
||||
unsigned alignment);
|
||||
extern struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
|
||||
unsigned long size,
|
||||
unsigned alignment);
|
||||
extern void drm_mm_put_block(struct drm_mm_node *cur);
|
||||
extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
|
||||
unsigned long size,
|
||||
unsigned alignment,
|
||||
int best_match);
|
||||
extern int drm_mm_init(struct drm_mm *mm, unsigned long start,
|
||||
unsigned long size);
|
||||
extern void drm_mm_takedown(struct drm_mm *mm);
|
||||
extern int drm_mm_clean(struct drm_mm *mm);
|
||||
extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
|
||||
extern int drm_mm_remove_space_from_tail(struct drm_mm *mm,
|
||||
unsigned long size);
|
||||
extern int drm_mm_add_space_to_tail(struct drm_mm *mm,
|
||||
unsigned long size, int atomic);
|
||||
extern int drm_mm_pre_get(struct drm_mm *mm);
|
||||
|
||||
static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
|
||||
{
|
||||
return block->mm;
|
||||
}
|
||||
|
||||
#endif
|
@ -254,6 +254,11 @@
|
||||
{0x1002, 0x940A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x940B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x940F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x94A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x94A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x94B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x94B3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x94B5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x9441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x9442, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
|
||||
@ -268,6 +273,8 @@
|
||||
{0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x946B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x947A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
@ -536,4 +543,6 @@
|
||||
{0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0, 0, 0}
|
||||
|
@ -446,6 +446,7 @@ int pnp_start_dev(struct pnp_dev *dev);
|
||||
int pnp_stop_dev(struct pnp_dev *dev);
|
||||
int pnp_activate_dev(struct pnp_dev *dev);
|
||||
int pnp_disable_dev(struct pnp_dev *dev);
|
||||
int pnp_range_reserved(resource_size_t start, resource_size_t end);
|
||||
|
||||
/* protocol helpers */
|
||||
int pnp_is_active(struct pnp_dev *dev);
|
||||
@ -476,6 +477,7 @@ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; }
|
||||
static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; }
|
||||
static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
|
||||
static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
|
||||
static inline int pnp_range_reserved(resource_size_t start, resource_size_t end) { return 0;}
|
||||
|
||||
/* protocol helpers */
|
||||
static inline int pnp_is_active(struct pnp_dev *dev) { return 0; }
|
||||
|
Loading…
Reference in New Issue
Block a user