Commit 6b702462 authored by Linus Torvalds's avatar Linus Torvalds

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)
  ...
parents 947ec0b0 3c24475c
...@@ -46,6 +46,10 @@ ...@@ -46,6 +46,10 @@
#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #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 */ /* cover 915 and 945 variants */
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
...@@ -75,7 +79,9 @@ ...@@ -75,7 +79,9 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ 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_G45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_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; extern int agp_memory_reserved;
...@@ -1211,6 +1217,8 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) ...@@ -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_Q45_HB:
case PCI_DEVICE_ID_INTEL_G45_HB: case PCI_DEVICE_ID_INTEL_G45_HB:
case PCI_DEVICE_ID_INTEL_G41_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); *gtt_offset = *gtt_size = MB(2);
break; break;
default: default:
...@@ -2186,6 +2194,10 @@ static const struct intel_driver_description { ...@@ -2186,6 +2194,10 @@ static const struct intel_driver_description {
"G45/G43", NULL, &intel_i965_driver }, "G45/G43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
"G41", NULL, &intel_i965_driver }, "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 } { 0, 0, 0, NULL, NULL, NULL }
}; };
...@@ -2387,6 +2399,8 @@ static struct pci_device_id agp_intel_pci_table[] = { ...@@ -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_Q45_HB),
ID(PCI_DEVICE_ID_INTEL_G45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB),
ID(PCI_DEVICE_ID_INTEL_G41_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, ...@@ -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; list->user_token = list->hash.key << PAGE_SHIFT;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
list->master = dev->primary->master; if (!(map->flags & _DRM_DRIVER))
list->master = dev->primary->master;
*maplist = list; *maplist = list;
return 0; return 0;
} }
......
...@@ -589,85 +589,13 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter, ...@@ -589,85 +589,13 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
} }
EXPORT_SYMBOL(drm_do_probe_ddc_edid); 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, static int drm_ddc_read_edid(struct drm_connector *connector,
struct i2c_adapter *adapter, struct i2c_adapter *adapter,
char *buf, int len) char *buf, int len)
{ {
int ret; int ret;
ret = drm_ddc_read(adapter, buf, len); ret = drm_do_probe_ddc_edid(adapter, buf, len);
if (ret != 0) { if (ret != 0) {
dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
drm_get_connector_name(connector)); drm_get_connector_name(connector));
......
...@@ -133,7 +133,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) ...@@ -133,7 +133,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
BUG_ON((size & (PAGE_SIZE - 1)) != 0); BUG_ON((size & (PAGE_SIZE - 1)) != 0);
obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); obj = kzalloc(sizeof(*obj), GFP_KERNEL);
obj->dev = dev; obj->dev = dev;
obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); 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) ...@@ -62,6 +62,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
} }
return 0; return 0;
} }
EXPORT_SYMBOL(drm_ht_create);
void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) 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 ...@@ -156,6 +157,7 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it
} }
return 0; return 0;
} }
EXPORT_SYMBOL(drm_ht_just_insert_please);
int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
struct drm_hash_item **item) struct drm_hash_item **item)
...@@ -169,6 +171,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, ...@@ -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); *item = hlist_entry(list, struct drm_hash_item, head);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_ht_find_item);
int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) 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) ...@@ -202,3 +205,4 @@ void drm_ht_remove(struct drm_open_hash *ht)
ht->table = NULL; ht->table = NULL;
} }
} }
EXPORT_SYMBOL(drm_ht_remove);
...@@ -42,8 +42,11 @@ ...@@ -42,8 +42,11 @@
*/ */
#include "drmP.h" #include "drmP.h"
#include "drm_mm.h"
#include <linux/slab.h> #include <linux/slab.h>
#define MM_UNUSED_TARGET 4
unsigned long drm_mm_tail_space(struct drm_mm *mm) unsigned long drm_mm_tail_space(struct drm_mm *mm)
{ {
struct list_head *tail_node; struct list_head *tail_node;
...@@ -74,16 +77,62 @@ int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size) ...@@ -74,16 +77,62 @@ int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
return 0; return 0;
} }
static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
{
struct drm_mm_node *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, static int drm_mm_create_tail_node(struct drm_mm *mm,
unsigned long start, unsigned long start,
unsigned long size) unsigned long size, int atomic)
{ {
struct drm_mm_node *child; struct drm_mm_node *child;
child = (struct drm_mm_node *) child = drm_mm_kmalloc(mm, atomic);
drm_alloc(sizeof(*child), DRM_MEM_MM); if (unlikely(child == NULL))
if (!child)
return -ENOMEM; return -ENOMEM;
child->free = 1; child->free = 1;
...@@ -97,8 +146,7 @@ static int drm_mm_create_tail_node(struct drm_mm *mm, ...@@ -97,8 +146,7 @@ static int drm_mm_create_tail_node(struct drm_mm *mm,
return 0; return 0;
} }
int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic)
int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
{ {
struct list_head *tail_node; struct list_head *tail_node;
struct drm_mm_node *entry; struct drm_mm_node *entry;
...@@ -106,20 +154,21 @@ int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size) ...@@ -106,20 +154,21 @@ int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
tail_node = mm->ml_entry.prev; tail_node = mm->ml_entry.prev;
entry = list_entry(tail_node, struct drm_mm_node, ml_entry); entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
if (!entry->free) { 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; entry->size += size;
return 0; return 0;
} }
static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, 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; struct drm_mm_node *child;
child = (struct drm_mm_node *) child = drm_mm_kmalloc(parent->mm, atomic);
drm_alloc(sizeof(*child), DRM_MEM_MM); if (unlikely(child == NULL))
if (!child)
return NULL; return NULL;
INIT_LIST_HEAD(&child->fl_entry); INIT_LIST_HEAD(&child->fl_entry);
...@@ -151,8 +200,9 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, ...@@ -151,8 +200,9 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
tmp = parent->start % alignment; tmp = parent->start % alignment;
if (tmp) { if (tmp) {
align_splitoff = drm_mm_split_at_start(parent, alignment - tmp); align_splitoff =
if (!align_splitoff) drm_mm_split_at_start(parent, alignment - tmp, 0);
if (unlikely(align_splitoff == NULL))
return NULL; return NULL;
} }
...@@ -161,7 +211,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, ...@@ -161,7 +211,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
parent->free = 0; parent->free = 0;
return parent; return parent;
} else { } else {
child = drm_mm_split_at_start(parent, size); child = drm_mm_split_at_start(parent, size, 0);
} }
if (align_splitoff) if (align_splitoff)
...@@ -169,14 +219,49 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, ...@@ -169,14 +219,49 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
return child; return child;
} }
EXPORT_SYMBOL(drm_mm_get_block); 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. * Put a block. Merge with the previous and / or next block if they are free.
* Otherwise add to the free stack. * 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; struct drm_mm *mm = cur->mm;
...@@ -188,21 +273,27 @@ void drm_mm_put_block(struct drm_mm_node * cur) ...@@ -188,21 +273,27 @@ void drm_mm_put_block(struct drm_mm_node * cur)
int merged = 0; int merged = 0;
if (cur_head->prev != root_head) { 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) { if (prev_node->free) {
prev_node->size += cur->size; prev_node->size += cur->size;
merged = 1; merged = 1;
} }
} }
if (cur_head->next != root_head) { 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 (next_node->free) {
if (merged) { if (merged) {
prev_node->size += next_node->size; prev_node->size += next_node->size;
list_del(&next_node->ml_entry); list_del(&next_node->ml_entry);
list_del(&next_node->fl_entry); list_del(&next_node->fl_entry);
drm_free(next_node, sizeof(*next_node), if (mm->num_unused < MM_UNUSED_TARGET) {
DRM_MEM_MM); list_add(&next_node->fl_entry,
&mm->unused_nodes);
++mm->num_unused;
} else
kfree(next_node);
} else { } else {
next_node->size += cur->size; next_node->size += cur->size;
next_node->start = cur->start; next_node->start = cur->start;
...@@ -215,14 +306,19 @@ void drm_mm_put_block(struct drm_mm_node * cur) ...@@ -215,14 +306,19 @@ void drm_mm_put_block(struct drm_mm_node * cur)
list_add(&cur->fl_entry, &mm->fl_entry); list_add(&cur->fl_entry, &mm->fl_entry);
} else { } else {
list_del(&cur->ml_entry); 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); EXPORT_SYMBOL(drm_mm_put_block);
struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm, struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
unsigned long size, unsigned long size,
unsigned alignment, int best_match) unsigned alignment, int best_match)
{ {
struct list_head *list; struct list_head *list;
const struct list_head *free_stack = &mm->fl_entry; 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, ...@@ -247,7 +343,6 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
wasted += alignment - tmp; wasted += alignment - tmp;
} }
if (entry->size >= size + wasted) { if (entry->size >= size + wasted) {
if (!best_match) if (!best_match)
return entry; return entry;
...@@ -260,6 +355,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm, ...@@ -260,6 +355,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
return best; return best;
} }
EXPORT_SYMBOL(drm_mm_search_free);
int drm_mm_clean(struct drm_mm * mm) int drm_mm_clean(struct drm_mm * mm)
{ {
...@@ -267,14 +363,17 @@ 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); 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) int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
{ {
INIT_LIST_HEAD(&mm->ml_entry); INIT_LIST_HEAD(&mm->ml_entry);
INIT_LIST_HEAD(&mm->fl_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); EXPORT_SYMBOL(drm_mm_init);
...@@ -282,6 +381,7 @@ void drm_mm_takedown(struct drm_mm * mm) ...@@ -282,6 +381,7 @@ void drm_mm_takedown(struct drm_mm * mm)
{ {
struct list_head *bnode = mm->fl_entry.next; struct list_head *bnode = mm->fl_entry.next;
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *next;
entry = list_entry(bnode, struct drm_mm_node, fl_entry); entry = list_entry(bnode, struct drm_mm_node, fl_entry);
...@@ -293,7 +393,16 @@ void drm_mm_takedown(struct drm_mm * mm) ...@@ -293,7 +393,16 @@ void drm_mm_takedown(struct drm_mm * mm)
list_del(&entry->fl_entry); list_del(&entry->fl_entry);
list_del(&entry->ml_entry); list_del(&entry->ml_entry);
kfree(entry);
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);
drm_free(entry, sizeof(*entry), DRM_MEM_MM); BUG_ON(mm->num_unused != 0);
} }
EXPORT_SYMBOL(drm_mm_takedown); EXPORT_SYMBOL(drm_mm_takedown);
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "drm.h" #include "drm.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#define DRM_MODESET_DEBUG "drm_mode"
/** /**
* drm_mode_debug_printmodeline - debug print a mode * drm_mode_debug_printmodeline - debug print a mode
* @dev: DRM device * @dev: DRM device
...@@ -50,12 +51,13 @@ ...@@ -50,12 +51,13 @@
*/ */
void drm_mode_debug_printmodeline(struct drm_display_mode *mode) 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", DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
mode->base.id, mode->name, mode->vrefresh, mode->clock, "Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
mode->hdisplay, mode->hsync_start, mode->base.id, mode->name, mode->vrefresh, mode->clock,
mode->hsync_end, mode->htotal, mode->hdisplay, mode->hsync_start,
mode->vdisplay, mode->vsync_start, mode->hsync_end, mode->htotal,
mode->vsync_end, mode->vtotal, mode->type, mode->flags); mode->vdisplay, mode->vsync_start,
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
} }
EXPORT_SYMBOL(drm_mode_debug_printmodeline); EXPORT_SYMBOL(drm_mode_debug_printmodeline);
...@@ -401,7 +403,9 @@ void drm_mode_prune_invalid(struct drm_device *dev, ...@@ -401,7 +403,9 @@ void drm_mode_prune_invalid(struct drm_device *dev,
list_del(&mode->head); list_del(&mode->head);
if (verbose) { if (verbose) {
drm_mode_debug_printmodeline(mode); 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); drm_mode_destroy(dev, mode);
} }
......
...@@ -51,7 +51,22 @@ struct idr drm_minors_idr; ...@@ -51,7 +51,22 @@ struct idr drm_minors_idr;
struct class *drm_class; struct class *drm_class;
struct proc_dir_entry *drm_proc_root; struct proc_dir_entry *drm_proc_root;
struct dentry *drm_debugfs_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) static int drm_minor_get_id(struct drm_device *dev, int type)
{ {
int new_id; int new_id;
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#define I915_DRV "i915_drv"
/* Really want an OS-independent resettable timer. Would like to have /* 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 * 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 * 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) ...@@ -99,7 +101,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
memset(dev_priv->hw_status_page, 0, PAGE_SIZE); memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 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; return 0;
} }
...@@ -185,7 +187,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) ...@@ -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 *) master_priv->sarea_priv = (drm_i915_sarea_t *)
((u8 *)master_priv->sarea->handle + init->sarea_priv_offset); ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
} else { } 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) { if (init->ring_size != 0) {
...@@ -235,7 +238,7 @@ static int i915_dma_resume(struct drm_device * dev) ...@@ -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_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) { if (dev_priv->ring.map.handle == NULL) {
DRM_ERROR("can not ioremap virtual address for" DRM_ERROR("can not ioremap virtual address for"
...@@ -248,13 +251,14 @@ static int i915_dma_resume(struct drm_device * dev) ...@@ -248,13 +251,14 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_ERROR("Can not find hardware status page\n"); DRM_ERROR("Can not find hardware status page\n");
return -EINVAL; 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) if (dev_priv->status_gfx_addr != 0)
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
else else
I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 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; return 0;
} }
...@@ -548,10 +552,10 @@ static int i915_dispatch_flip(struct drm_device * dev) ...@@ -548,10 +552,10 @@ static int i915_dispatch_flip(struct drm_device * dev)
if (!master_priv->sarea_priv) if (!master_priv->sarea_priv)
return -EINVAL; return -EINVAL;
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
__func__, __func__,
dev_priv->current_page, dev_priv->current_page,
master_priv->sarea_priv->pf_current_page); master_priv->sarea_priv->pf_current_page);
i915_kernel_lost_context(dev); i915_kernel_lost_context(dev);
...@@ -629,8 +633,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ...@@ -629,8 +633,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", DRM_DEBUG_DRIVER(I915_DRV,
batch->start, batch->used, batch->num_cliprects); "i915 batchbuffer, start %x used %d cliprects %d\n",
batch->start, batch->used, batch->num_cliprects);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv); RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
...@@ -678,8 +683,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -678,8 +683,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
void *batch_data; void *batch_data;
int ret; int ret;
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", DRM_DEBUG_DRIVER(I915_DRV,
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); "i915 cmdbuffer, buf %p sz %d cliprects %d\n",
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv); RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
...@@ -734,7 +740,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data, ...@@ -734,7 +740,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
{ {
int ret; int ret;
DRM_DEBUG("%s\n", __func__); DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv); RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
...@@ -777,7 +783,8 @@ static int i915_getparam(struct drm_device *dev, void *data, ...@@ -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; value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
break; break;
default: default:
DRM_DEBUG("Unknown parameter %d\n", param->param); DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
param->param);
return -EINVAL; return -EINVAL;
} }
...@@ -817,7 +824,8 @@ static int i915_setparam(struct drm_device *dev, void *data, ...@@ -817,7 +824,8 @@ static int i915_setparam(struct drm_device *dev, void *data,
dev_priv->fence_reg_start = param->value; dev_priv->fence_reg_start = param->value;
break; break;
default: default:
DRM_DEBUG("unknown parameter %d\n", param->param); DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
param->param);
return -EINVAL; return -EINVAL;
} }
...@@ -865,9 +873,10 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ...@@ -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); memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n", DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
dev_priv->status_gfx_addr); dev_priv->status_gfx_addr);
DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page); DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
dev_priv->hw_status_page);
return 0; return 0;
} }
...@@ -922,7 +931,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, ...@@ -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 * Some of the preallocated space is taken by the GTT
* and popup. GTT is 1K per MB of aperture size, and popup is 4K. * 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; overhead = 4096;
else else
overhead = (*aperture_size / 1024) + 4096; overhead = (*aperture_size / 1024) + 4096;
...@@ -1153,8 +1162,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1153,8 +1162,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
#endif #endif
dev->driver->get_vblank_counter = i915_get_vblank_counter; 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; dev->driver->get_vblank_counter = gm45_get_vblank_counter;
}
i915_gem_load(dev); i915_gem_load(dev);
...@@ -1198,7 +1210,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1198,7 +1210,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
} }
/* Must be done after probing outputs */ /* 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; return 0;
...@@ -1232,7 +1246,8 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1232,7 +1246,8 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->regs != NULL) if (dev_priv->regs != NULL)
iounmap(dev_priv->regs); 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)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev); intel_modeset_cleanup(dev);
...@@ -1256,7 +1271,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) ...@@ -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; 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 *) i915_file_priv = (struct drm_i915_file_private *)
drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES); 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) ...@@ -1265,8 +1280,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
file_priv->driver_priv = i915_file_priv; file_priv->driver_priv = i915_file_priv;
i915_file_priv->mm.last_gem_seqno = 0; INIT_LIST_HEAD(&i915_file_priv->mm.request_list);
i915_file_priv->mm.last_gem_throttle_seqno = 0;
return 0; return 0;
} }
...@@ -1303,6 +1317,7 @@ void i915_driver_lastclose(struct drm_device * dev) ...@@ -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) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
i915_gem_release(dev, file_priv);
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_mem_release(dev, file_priv, dev_priv->agp_heap); i915_mem_release(dev, file_priv, dev_priv->agp_heap);
} }
......
...@@ -126,6 +126,13 @@ struct drm_i915_fence_reg { ...@@ -126,6 +126,13 @@ struct drm_i915_fence_reg {
struct drm_gem_object *obj; 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 { typedef struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
...@@ -143,6 +150,8 @@ typedef struct drm_i915_private { ...@@ -143,6 +150,8 @@ typedef struct drm_i915_private {
drm_local_map_t hws_map; drm_local_map_t hws_map;
struct drm_gem_object *hws_obj; struct drm_gem_object *hws_obj;
struct resource mch_res;
unsigned int cpp; unsigned int cpp;
int back_offset; int back_offset;
int front_offset; int front_offset;
...@@ -158,6 +167,11 @@ typedef struct drm_i915_private { ...@@ -158,6 +167,11 @@ typedef struct drm_i915_private {
/** Cached value of IMR to avoid reads in updating the bitfield */ /** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg; u32 irq_mask_reg;
u32 pipestat[2]; 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; u32 hotplug_supported_mask;
struct work_struct hotplug_work; struct work_struct hotplug_work;
...@@ -285,6 +299,13 @@ typedef struct drm_i915_private { ...@@ -285,6 +299,13 @@ typedef struct drm_i915_private {
u8 saveDACMASK; u8 saveDACMASK;
u8 saveCR[37]; u8 saveCR[37];
uint64_t saveFENCE[16]; uint64_t saveFENCE[16];
u32 saveCURACNTR;
u32 saveCURAPOS;
u32 saveCURABASE;
u32 saveCURBCNTR;
u32 saveCURBPOS;
u32 saveCURBBASE;
u32 saveCURSIZE;
struct { struct {
struct drm_mm gtt_space; struct drm_mm gtt_space;
...@@ -382,6 +403,7 @@ typedef struct drm_i915_private { ...@@ -382,6 +403,7 @@ typedef struct drm_i915_private {
/* storage for physical objects */ /* storage for physical objects */
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
} mm; } mm;
struct sdvo_device_mapping sdvo_mappings[2];
} drm_i915_private_t; } drm_i915_private_t;
/** driver private structure attached to each drm_gem_object */ /** driver private structure attached to each drm_gem_object */
...@@ -491,13 +513,16 @@ struct drm_i915_gem_request { ...@@ -491,13 +513,16 @@ struct drm_i915_gem_request {
/** Time at which this request was emitted, in jiffies. */ /** Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies; unsigned long emitted_jiffies;
/** global list entry for this request */
struct list_head list; struct list_head list;
/** file_priv list entry for this request */
struct list_head client_list;
}; };
struct drm_i915_file_private { struct drm_i915_file_private {
struct { struct {
uint32_t last_gem_seqno; struct list_head request_list;
uint32_t last_gem_throttle_seqno;
} mm; } mm;
}; };
...@@ -642,6 +667,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev, ...@@ -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); void i915_gem_free_all_phys_object(struct drm_device *dev);
int i915_gem_object_get_pages(struct drm_gem_object *obj); 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_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 */ /* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); 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); ...@@ -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 == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \ (dev)->pci_device == 0x2E12 || \
(dev)->pci_device == 0x2E22 || \ (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 || \ #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
(dev)->pci_device == 0x2A12) (dev)->pci_device == 0x2A12)
...@@ -807,20 +835,26 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -807,20 +835,26 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x29D2 || \ (dev)->pci_device == 0x29D2 || \
(IS_IGD(dev))) (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) || \ #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) || \ #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(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 /* 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. * rows, which changed the alignment requirements and fence programming.
*/ */
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(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 I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024) #define PRIMARY_RINGBUFFER_SIZE (128*1024)
......
This diff is collapsed.
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
* *
*/ */
#include <linux/acpi.h>
#include <linux/pnp.h>
#include "linux/string.h" #include "linux/string.h"
#include "linux/bitops.h" #include "linux/bitops.h"
#include "drmP.h" #include "drmP.h"
...@@ -81,6 +83,143 @@ ...@@ -81,6 +83,143 @@
* to match what the GPU expects. * 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 * Detects bit 6 swizzling of address lookup between IGD access and CPU
* access through main memory. * access through main memory.
...@@ -91,6 +230,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -91,6 +230,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable;
if (!IS_I9XX(dev)) { if (!IS_I9XX(dev)) {
/* As far as we know, the 865 doesn't have these bit 6 /* 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) ...@@ -101,6 +241,9 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
} else if (IS_MOBILE(dev)) { } else if (IS_MOBILE(dev)) {
uint32_t dcc; 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 /* On mobile 9xx chipsets, channel interleave by the CPU is
* determined by DCC. For single-channel, neither the CPU * determined by DCC. For single-channel, neither the CPU
* nor the GPU do swizzling. For dual channel interleaved, * nor the GPU do swizzling. For dual channel interleaved,
...@@ -140,6 +283,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -140,6 +283,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
} }
intel_teardown_mchbar(dev, need_disable);
} else { } else {
/* The 965, G33, and newer, have a very flexible memory /* The 965, G33, and newer, have a very flexible memory
* configuration. It will enable dual-channel mode * configuration. It will enable dual-channel mode
...@@ -170,6 +315,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -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_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y; dev_priv->mm.bit_6_swizzle_y = swizzle_y;
} }
......
...@@ -57,6 +57,47 @@ ...@@ -57,6 +57,47 @@
#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \ #define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \
DRM_I915_VBLANK_PIPE_B) 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 void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) 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) ...@@ -196,6 +237,47 @@ static void i915_hotplug_work_func(struct work_struct *work)
drm_sysfs_hotplug_event(dev); 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) irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -212,6 +294,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -212,6 +294,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
atomic_inc(&dev_priv->irq_received); atomic_inc(&dev_priv->irq_received);
if (IS_IGDNG(dev))
return igdng_irq_handler(dev);
iir = I915_READ(IIR); iir = I915_READ(IIR);
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
...@@ -349,8 +434,12 @@ void i915_user_irq_get(struct drm_device *dev) ...@@ -349,8 +434,12 @@ void i915_user_irq_get(struct drm_device *dev)
unsigned long irqflags; unsigned long irqflags;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
i915_enable_irq(dev_priv, I915_USER_INTERRUPT); 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); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
} }
...@@ -361,8 +450,12 @@ void i915_user_irq_put(struct drm_device *dev) ...@@ -361,8 +450,12 @@ void i915_user_irq_put(struct drm_device *dev)
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
if (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 (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); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
} }
...@@ -455,6 +548,9 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) ...@@ -455,6 +548,9 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
if (!(pipeconf & PIPEACONF_ENABLE)) if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL; return -EINVAL;
if (IS_IGDNG(dev))
return 0;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (IS_I965G(dev)) if (IS_I965G(dev))
i915_enable_pipestat(dev_priv, pipe, i915_enable_pipestat(dev_priv, pipe,
...@@ -474,6 +570,9 @@ void i915_disable_vblank(struct drm_device *dev, int 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
if (IS_IGDNG(dev))
return;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe, i915_disable_pipestat(dev_priv, pipe,
PIPE_VBLANK_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE |
...@@ -484,7 +583,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) ...@@ -484,7 +583,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
void i915_enable_interrupt (struct drm_device *dev) void i915_enable_interrupt (struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; 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; dev_priv->irq_enabled = 1;
} }
...@@ -545,12 +646,65 @@ int i915_vblank_swap(struct drm_device *dev, void *data, ...@@ -545,12 +646,65 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
/* drm_dma.h hooks /* 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) void i915_driver_irq_preinstall(struct drm_device * dev)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
atomic_set(&dev_priv->irq_received, 0); 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)) { if (I915_HAS_HOTPLUG(dev)) {
I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_EN, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
...@@ -562,7 +716,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev) ...@@ -562,7 +716,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
I915_WRITE(IMR, 0xffffffff); I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0); I915_WRITE(IER, 0x0);
(void) I915_READ(IER); (void) I915_READ(IER);
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
} }
int i915_driver_irq_postinstall(struct drm_device *dev) int i915_driver_irq_postinstall(struct drm_device *dev)
...@@ -570,9 +723,12 @@ 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; 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_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. */ /* Unmask the interrupts that we always want on. */
dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
...@@ -613,11 +769,24 @@ int i915_driver_irq_postinstall(struct drm_device *dev) ...@@ -613,11 +769,24 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
(void) I915_READ(IER); (void) I915_READ(IER);
opregion_enable_asle(dev); opregion_enable_asle(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
return 0; 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) void i915_driver_irq_uninstall(struct drm_device * dev)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 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) ...@@ -627,6 +796,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
dev_priv->vblank_pipe = 0; dev_priv->vblank_pipe = 0;
if (IS_IGDNG(dev)) {
igdng_irq_uninstall(dev);
return;
}
if (I915_HAS_HOTPLUG(dev)) { if (I915_HAS_HOTPLUG(dev)) {
I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_EN, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
......
This diff is collapsed.
...@@ -295,6 +295,16 @@ int i915_save_state(struct drm_device *dev) ...@@ -295,6 +295,16 @@ int i915_save_state(struct drm_device *dev)
i915_save_palette(dev, PIPE_B); i915_save_palette(dev, PIPE_B);
dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); 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 */ /* CRT state */
dev_priv->saveADPA = I915_READ(ADPA); dev_priv->saveADPA = I915_READ(ADPA);
...@@ -480,6 +490,16 @@ int i915_restore_state(struct drm_device *dev) ...@@ -480,6 +490,16 @@ int i915_restore_state(struct drm_device *dev)
I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); 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 */ /* CRT state */
I915_WRITE(ADPA, dev_priv->saveADPA); I915_WRITE(ADPA, dev_priv->saveADPA);
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_bios.h" #include "intel_bios.h"
#define SLAVE_ADDR1 0x70
#define SLAVE_ADDR2 0x72
static void * static void *
find_section(struct bdb_header *bdb, int section_id) find_section(struct bdb_header *bdb, int section_id)
...@@ -193,6 +195,88 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -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 * intel_init_bios - initialize VBIOS settings & find VBT
* @dev: DRM device * @dev: DRM device
...@@ -242,7 +326,7 @@ intel_init_bios(struct drm_device *dev) ...@@ -242,7 +326,7 @@ intel_init_bios(struct drm_device *dev)
parse_general_features(dev_priv, bdb); parse_general_features(dev_priv, bdb);
parse_lfp_panel_data(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb);
parse_sdvo_device_mapping(dev_priv, bdb);
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
return 0; return 0;
......
...@@ -135,6 +135,86 @@ struct bdb_general_features { ...@@ -135,6 +135,86 @@ struct bdb_general_features {
u8 rsvd11:6; /* finish byte */ u8 rsvd11:6; /* finish byte */
} __attribute__((packed)); } __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 { struct bdb_general_definitions {
/* DDC GPIO */ /* DDC GPIO */
u8 crt_ddc_gmbus_pin; u8 crt_ddc_gmbus_pin;
...@@ -149,14 +229,19 @@ struct bdb_general_definitions { ...@@ -149,14 +229,19 @@ struct bdb_general_definitions {
u8 boot_display[2]; u8 boot_display[2];
u8 child_dev_size; u8 child_dev_size;
/* device info */ /*
u8 tv_or_lvds_info[33]; * Device info:
u8 dev1[33]; * If TV is present, it'll be at devices[0].
u8 dev2[33]; * LVDS will be next, either devices[0] or [1], if present.
u8 dev3[33]; * On some platforms the number of device is 6. But could be as few as
u8 dev4[33]; * 4 if both TV and LVDS are missing.
/* may be another device block here on some platforms */ * 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 { struct bdb_lvds_options {
u8 panel_type; u8 panel_type;
......
...@@ -37,9 +37,14 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) ...@@ -37,9 +37,14 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
temp |= ADPA_DAC_ENABLE; temp |= ADPA_DAC_ENABLE;
...@@ -58,7 +63,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) ...@@ -58,7 +63,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
break; break;
} }
I915_WRITE(ADPA, temp); I915_WRITE(reg, temp);
} }
static int intel_crt_mode_valid(struct drm_connector *connector, static int intel_crt_mode_valid(struct drm_connector *connector,
...@@ -101,17 +106,23 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -101,17 +106,23 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int dpll_md_reg; int dpll_md_reg;
u32 adpa, dpll_md; u32 adpa, dpll_md;
u32 adpa_reg;
if (intel_crtc->pipe == 0) if (intel_crtc->pipe == 0)
dpll_md_reg = DPLL_A_MD; dpll_md_reg = DPLL_A_MD;
else else
dpll_md_reg = DPLL_B_MD; 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 * Disable separate mode multiplier used when cloning SDVO to CRT
* XXX this needs to be adjusted when we really are cloning * 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); dpll_md = I915_READ(dpll_md_reg);
I915_WRITE(dpll_md_reg, I915_WRITE(dpll_md_reg,
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
...@@ -125,13 +136,53 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -125,13 +136,53 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
if (intel_crtc->pipe == 0) { if (intel_crtc->pipe == 0) {
adpa |= ADPA_PIPE_A_SELECT; adpa |= ADPA_PIPE_A_SELECT;
I915_WRITE(BCLRPAT_A, 0); if (!IS_IGDNG(dev))
I915_WRITE(BCLRPAT_A, 0);
} else { } else {
adpa |= ADPA_PIPE_B_SELECT; 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) ...@@ -148,6 +199,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 hotplug_en; u32 hotplug_en;
int i, tries = 0; 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 * On 4 series desktop, CRT detect sequence need to be done twice
* to get a reliable result. * to get a reliable result.
...@@ -423,6 +478,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -423,6 +478,7 @@ void intel_crt_init(struct drm_device *dev)
{ {
struct drm_connector *connector; struct drm_connector *connector;
struct intel_output *intel_output; struct intel_output *intel_output;
u32 i2c_reg;
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output) if (!intel_output)
...@@ -439,7 +495,11 @@ void intel_crt_init(struct drm_device *dev) ...@@ -439,7 +495,11 @@ void intel_crt_init(struct drm_device *dev)
&intel_output->enc); &intel_output->enc);
/* Set up the DDC bus. */ /* 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) { if (!intel_output->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n"); "failed.\n");
......
This diff is collapsed.
...@@ -207,7 +207,7 @@ static int intelfb_set_par(struct fb_info *info) ...@@ -207,7 +207,7 @@ static int intelfb_set_par(struct fb_info *info)
if (var->pixclock != -1) { if (var->pixclock != -1) {
DRM_ERROR("PIXEL CLCOK SET\n"); DRM_ERROR("PIXEL CLOCK SET\n");
return -EINVAL; return -EINVAL;
} else { } else {
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -674,8 +674,12 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_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; par->crtc_ids[0] = crtc->base.id;
modeset->num_connectors = conn_count; modeset->num_connectors = conn_count;
if (modeset->mode != modeset->crtc->desired_mode) if (modeset->crtc->desired_mode) {
modeset->mode = 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; par->crtc_count = 1;
...@@ -824,8 +828,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev) ...@@ -824,8 +828,12 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
par->crtc_ids[crtc_count++] = crtc->base.id; par->crtc_ids[crtc_count++] = crtc->base.id;
modeset->num_connectors = conn_count; modeset->num_connectors = conn_count;
if (modeset->mode != modeset->crtc->desired_mode) if (modeset->crtc->desired_mode) {
modeset->mode = 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; par->crtc_count = crtc_count;
...@@ -857,9 +865,15 @@ void intelfb_restore(void) ...@@ -857,9 +865,15 @@ void intelfb_restore(void)
drm_crtc_helper_set_config(&kernelfb_mode); 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) 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 = { static struct sysrq_key_op sysrq_intelfb_restore_op = {
......
...@@ -56,7 +56,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -56,7 +56,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
sdvox = SDVO_ENCODING_HDMI | sdvox = SDVO_ENCODING_HDMI |
SDVO_BORDER_ENABLE | SDVO_BORDER_ENABLE |
SDVO_VSYNC_ACTIVE_HIGH | SDVO_VSYNC_ACTIVE_HIGH |
SDVO_HSYNC_ACTIVE_HIGH; SDVO_HSYNC_ACTIVE_HIGH |
SDVO_NULL_PACKETS_DURING_VSYNC;
if (hdmi_priv->has_hdmi_sink) if (hdmi_priv->has_hdmi_sink)
sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_AUDIO_ENABLE;
...@@ -144,6 +145,22 @@ intel_hdmi_sink_detect(struct drm_connector *connector) ...@@ -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 static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector) intel_hdmi_detect(struct drm_connector *connector)
{ {
...@@ -153,6 +170,9 @@ 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; struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
u32 temp, bit; u32 temp, bit;
if (IS_IGDNG(dev))
return igdng_hdmi_detect(connector);
temp = I915_READ(PORT_HOTPLUG_EN); temp = I915_READ(PORT_HOTPLUG_EN);
switch (hdmi_priv->sdvox_reg) { switch (hdmi_priv->sdvox_reg) {
...@@ -269,8 +289,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -269,8 +289,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) if (sdvox_reg == SDVOB)
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); 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"); 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) if (!intel_output->ddc_bus)
goto err_connector; goto err_connector;
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#define I915_LVDS "i915_lvds"
/** /**
* Sets the backlight level. * Sets the backlight level.
* *
...@@ -45,10 +47,15 @@ ...@@ -45,10 +47,15 @@
static void intel_lvds_set_backlight(struct drm_device *dev, int level) static void intel_lvds_set_backlight(struct drm_device *dev, int level)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 blc_pwm_ctl; u32 blc_pwm_ctl, reg;
if (IS_IGDNG(dev))
reg = BLC_PWM_CPU_CTL;
else
reg = BLC_PWM_CTL;
blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | I915_WRITE(reg, (blc_pwm_ctl |
(level << BACKLIGHT_DUTY_CYCLE_SHIFT))); (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
} }
...@@ -58,8 +65,14 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level) ...@@ -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) static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg;
if (IS_IGDNG(dev))
reg = BLC_PWM_PCH_CTL2;
else
reg = BLC_PWM_CTL;
return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >> return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
} }
...@@ -69,23 +82,31 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) ...@@ -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) static void intel_lvds_set_power(struct drm_device *dev, bool on)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; 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) { if (on) {
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
POWER_TARGET_ON); POWER_TARGET_ON);
do { do {
pp_status = I915_READ(PP_STATUS); pp_status = I915_READ(status_reg);
} while ((pp_status & PP_ON) == 0); } while ((pp_status & PP_ON) == 0);
intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
} else { } else {
intel_lvds_set_backlight(dev, 0); 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); ~POWER_TARGET_ON);
do { do {
pp_status = I915_READ(PP_STATUS); pp_status = I915_READ(status_reg);
} while (pp_status & PP_ON); } while (pp_status & PP_ON);
} }
} }
...@@ -106,12 +127,28 @@ static void intel_lvds_save(struct drm_connector *connector) ...@@ -106,12 +127,28 @@ static void intel_lvds_save(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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;
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_DELAYS); dev_priv->savePP_ON = I915_READ(pp_on_reg);
dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS); dev_priv->savePP_OFF = I915_READ(pp_off_reg);
dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
BACKLIGHT_DUTY_CYCLE_MASK); BACKLIGHT_DUTY_CYCLE_MASK);
...@@ -127,12 +164,28 @@ static void intel_lvds_restore(struct drm_connector *connector) ...@@ -127,12 +164,28 @@ static void intel_lvds_restore(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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;
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(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON); I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF); I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
intel_lvds_set_power(dev, true); intel_lvds_set_power(dev, true);
else else
...@@ -216,8 +269,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) ...@@ -216,8 +269,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg;
if (IS_IGDNG(dev))
reg = BLC_PWM_CPU_CTL;
else
reg = BLC_PWM_CTL;
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
BACKLIGHT_DUTY_CYCLE_MASK); BACKLIGHT_DUTY_CYCLE_MASK);
...@@ -251,6 +310,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, ...@@ -251,6 +310,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* settings. * settings.
*/ */
/* No panel fitting yet, fixme */
if (IS_IGDNG(dev))
return;
/* /*
* Enable automatic panel scaling so that non-native modes fill the * Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to * 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 = { ...@@ -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) 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; return 1;
} }
...@@ -420,8 +484,21 @@ static const struct dmi_system_id intel_no_lvds[] = { ...@@ -420,8 +484,21 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"), 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 */ { } /* terminating entry */
}; };
...@@ -442,12 +519,18 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -442,12 +519,18 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *scan; /* *modes, *bios_mode; */ struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc; struct drm_crtc *crtc;
u32 lvds; u32 lvds;
int pipe; int pipe, gpio = GPIOC;
/* Skip init on machines we know falsely report LVDS */ /* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds)) if (dmi_check_system(intel_no_lvds))
return; 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); intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output) { if (!intel_output) {
return; return;
...@@ -482,7 +565,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -482,7 +565,7 @@ void intel_lvds_init(struct drm_device *dev)
*/ */
/* Set up the DDC bus. */ /* 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) { if (!intel_output->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n"); "failed.\n");
...@@ -524,6 +607,11 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -524,6 +607,11 @@ void intel_lvds_init(struct drm_device *dev)
* on. If so, assume that whatever is currently programmed is the * on. If so, assume that whatever is currently programmed is the
* correct mode. * correct mode.
*/ */
/* IGDNG: FIXME if still fail, not try pipe mode now */
if (IS_IGDNG(dev))
goto failed;
lvds = I915_READ(LVDS); lvds = I915_READ(LVDS);
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
crtc = intel_get_crtc_from_pipe(dev, pipe); crtc = intel_get_crtc_from_pipe(dev, pipe);
...@@ -542,11 +630,22 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -542,11 +630,22 @@ void intel_lvds_init(struct drm_device *dev)
goto failed; goto failed;
out: 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); drm_sysfs_connector_add(connector);
return; return;
failed: 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) if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus); intel_i2c_destroy(intel_output->ddc_bus);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "intel_sdvo_regs.h" #include "intel_sdvo_regs.h"
#undef SDVO_DEBUG #undef SDVO_DEBUG
#define I915_SDVO "i915_sdvo"
struct intel_sdvo_priv { struct intel_sdvo_priv {
struct intel_i2c_chan *i2c_bus; struct intel_i2c_chan *i2c_bus;
int slaveaddr; int slaveaddr;
...@@ -277,20 +277,21 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, ...@@ -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; struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int i; 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++) 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++) for (; i < 8; i++)
printk(KERN_DEBUG " "); DRM_LOG_KMS(" ");
for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
if (cmd == sdvo_cmd_names[i].cmd) { 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; break;
} }
} }
if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
printk(KERN_DEBUG "(%02X)", cmd); DRM_LOG_KMS("(%02X)", cmd);
printk(KERN_DEBUG "\n"); DRM_LOG_KMS("\n");
} }
#else #else
#define intel_sdvo_debug_write(o, c, a, l) #define intel_sdvo_debug_write(o, c, a, l)
...@@ -329,16 +330,16 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output, ...@@ -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; struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int i; 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++) 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++) for (; i < 8; i++)
printk(KERN_DEBUG " "); DRM_LOG_KMS(" ");
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) 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 else
printk(KERN_DEBUG "(??? %d)", status); DRM_LOG_KMS("(??? %d)", status);
printk(KERN_DEBUG "\n"); DRM_LOG_KMS("\n");
} }
#else #else
#define intel_sdvo_debug_response(o, r, l, s) #define intel_sdvo_debug_response(o, r, l, s)
...@@ -1742,6 +1743,43 @@ static struct i2c_algorithm intel_sdvo_i2c_bit_algo = { ...@@ -1742,6 +1743,43 @@ static struct i2c_algorithm intel_sdvo_i2c_bit_algo = {
.master_xfer = intel_sdvo_master_xfer, .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) bool intel_sdvo_init(struct drm_device *dev, int output_device)
{ {
struct drm_connector *connector; struct drm_connector *connector;
...@@ -1753,6 +1791,7 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) ...@@ -1753,6 +1791,7 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
u8 ch[0x40]; u8 ch[0x40];
int i; int i;
int encoder_type, output_id; int encoder_type, output_id;
u8 slave_addr;
intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
if (!intel_output) { if (!intel_output) {
...@@ -1771,16 +1810,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) ...@@ -1771,16 +1810,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
if (!i2cbus) if (!i2cbus)
goto err_inteloutput; goto err_inteloutput;
slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
sdvo_priv->i2c_bus = i2cbus; sdvo_priv->i2c_bus = i2cbus;
if (output_device == SDVOB) { if (output_device == SDVOB) {
output_id = 1; output_id = 1;
sdvo_priv->i2c_bus->slave_addr = 0x38;
} else { } else {
output_id = 2; 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; sdvo_priv->output_device = output_device;
intel_output->i2c_bus = i2cbus; intel_output->i2c_bus = i2cbus;
intel_output->dev_priv = sdvo_priv; intel_output->dev_priv = sdvo_priv;
...@@ -1788,8 +1826,9 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) ...@@ -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 */ /* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) { for (i = 0; i < 0x40; i++) {
if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) { if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
DRM_DEBUG("No SDVO device found on SDVO%c\n", DRM_DEBUG_KMS(I915_SDVO,
output_device == SDVOB ? 'B' : 'C'); "No SDVO device found on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
goto err_i2c; goto err_i2c;
} }
} }
...@@ -1873,9 +1912,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) ...@@ -1873,9 +1912,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
sdvo_priv->controlled_output = 0; sdvo_priv->controlled_output = 0;
memcpy (bytes, &sdvo_priv->caps.output_flags, 2); memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
DRM_DEBUG("%s: Unknown SDVO output type (0x%02x%02x)\n", DRM_DEBUG_KMS(I915_SDVO,
SDVO_NAME(sdvo_priv), "%s: Unknown SDVO output type (0x%02x%02x)\n",
bytes[0], bytes[1]); SDVO_NAME(sdvo_priv),
bytes[0], bytes[1]);
encoder_type = DRM_MODE_ENCODER_NONE; encoder_type = DRM_MODE_ENCODER_NONE;
connector_type = DRM_MODE_CONNECTOR_Unknown; connector_type = DRM_MODE_CONNECTOR_Unknown;
goto err_i2c; goto err_i2c;
...@@ -1905,21 +1945,21 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) ...@@ -1905,21 +1945,21 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
&sdvo_priv->pixel_clock_max); &sdvo_priv->pixel_clock_max);
DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, " DRM_DEBUG_KMS(I915_SDVO, "%s device VID/DID: %02X:%02X.%02X, "
"clock range %dMHz - %dMHz, " "clock range %dMHz - %dMHz, "
"input 1: %c, input 2: %c, " "input 1: %c, input 2: %c, "
"output 1: %c, output 2: %c\n", "output 1: %c, output 2: %c\n",
SDVO_NAME(sdvo_priv), SDVO_NAME(sdvo_priv),
sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
sdvo_priv->caps.device_rev_id, sdvo_priv->caps.device_rev_id,
sdvo_priv->pixel_clock_min / 1000, sdvo_priv->pixel_clock_min / 1000,
sdvo_priv->pixel_clock_max / 1000, sdvo_priv->pixel_clock_max / 1000,
(sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
(sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
/* check currently supported outputs */ /* check currently supported outputs */
sdvo_priv->caps.output_flags & sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', (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'); (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
return true; return true;
......
...@@ -1392,6 +1392,9 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) ...@@ -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_MASK;
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
tv_dac &= ~TVDAC_SENSE_MASK; 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 | tv_dac |= (TVDAC_STATE_CHG_EN |
TVDAC_A_SENSE_CTL | TVDAC_A_SENSE_CTL |
TVDAC_B_SENSE_CTL | TVDAC_B_SENSE_CTL |
......
...@@ -478,26 +478,27 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) ...@@ -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)) { if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); 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++) 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_DATA, RV770_pfp_microcode[i]);
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 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++) 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_DATA, RV770_cp_microcode[i]);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); 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); 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++) 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_DATA, RV730_pfp_microcode[i]);
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 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++) 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_DATA, RV730_cp_microcode[i]);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
...@@ -1324,6 +1325,10 @@ static void r700_gfx_init(struct drm_device *dev, ...@@ -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_prim_fifo_size = 0xf9;
dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; 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; break;
case CHIP_RV710: case CHIP_RV710:
dev_priv->r600_max_pipes = 2; dev_priv->r600_max_pipes = 2;
...@@ -1345,6 +1350,31 @@ static void r700_gfx_init(struct drm_device *dev, ...@@ -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_hiz_tile_fifo_size = 0x30;
dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
break; 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: default:
break; break;
} }
...@@ -1493,6 +1523,7 @@ static void r700_gfx_init(struct drm_device *dev, ...@@ -1493,6 +1523,7 @@ static void r700_gfx_init(struct drm_device *dev,
break; break;
case CHIP_RV730: case CHIP_RV730:
case CHIP_RV710: case CHIP_RV710:
case CHIP_RV740:
default: default:
sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4); sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
break; break;
...@@ -1569,6 +1600,7 @@ static void r700_gfx_init(struct drm_device *dev, ...@@ -1569,6 +1600,7 @@ static void r700_gfx_init(struct drm_device *dev,
switch (dev_priv->flags & RADEON_FAMILY_MASK) { switch (dev_priv->flags & RADEON_FAMILY_MASK) {
case CHIP_RV770: case CHIP_RV770:
case CHIP_RV730: case CHIP_RV730:
case CHIP_RV740:
gs_prim_buffer_depth = 384; gs_prim_buffer_depth = 384;
break; break;
case CHIP_RV710: case CHIP_RV710:
......
...@@ -2109,7 +2109,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master) ...@@ -2109,7 +2109,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
/* prebuild the SAREA */ /* prebuild the SAREA */
sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE); 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); &master_priv->sarea);
if (ret) { if (ret) {
DRM_ERROR("SAREA setup failed\n"); DRM_ERROR("SAREA setup failed\n");
......
...@@ -146,6 +146,7 @@ enum radeon_family { ...@@ -146,6 +146,7 @@ enum radeon_family {
CHIP_RV770, CHIP_RV770,
CHIP_RV730, CHIP_RV730,
CHIP_RV710, CHIP_RV710,
CHIP_RV740,
CHIP_LAST, CHIP_LAST,
}; };
......
...@@ -195,10 +195,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) ...@@ -195,10 +195,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
default: default:
vsg->state = dr_via_sg_init; vsg->state = dr_via_sg_init;
} }
if (vsg->bounce_buffer) { vfree(vsg->bounce_buffer);
vfree(vsg->bounce_buffer); vsg->bounce_buffer = NULL;
vsg->bounce_buffer = NULL;
}
vsg->free_on_sequence = 0; vsg->free_on_sequence = 0;
} }
......
...@@ -638,6 +638,24 @@ int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start, ...@@ -638,6 +638,24 @@ int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
} }
EXPORT_SYMBOL(pnp_possible_config); 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] .... */ /* format is: pnp_reserve_irq=irq1[,irq2] .... */
static int __init pnp_setup_reserve_irq(char *str) static int __init pnp_setup_reserve_irq(char *str)
{ {
......
...@@ -86,7 +86,17 @@ struct drm_device; ...@@ -86,7 +86,17 @@ struct drm_device;
#include "drm_os_linux.h" #include "drm_os_linux.h"
#include "drm_hashtab.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 */ /** \name DRM template customization defaults */
/*@{*/ /*@{*/
...@@ -186,15 +196,57 @@ struct drm_device; ...@@ -186,15 +196,57 @@ struct drm_device;
* \param arg arguments * \param arg arguments
*/ */
#if DRM_DEBUG_CODE #if DRM_DEBUG_CODE
#define DRM_DEBUG(fmt, arg...) \ #define DRM_DEBUG(fmt, args...) \
do { \
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 { \ do { \
if ( drm_debug ) \ drm_ut_debug_printk(DRM_UT_DRIVER, NULL, \
printk(KERN_DEBUG \ NULL, fmt, ##args); \
"[" DRM_NAME ":%s] " fmt , \
__func__ , ##arg); \
} while (0) } while (0)
#else #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_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 #endif
#define DRM_PROC_LIMIT (PAGE_SIZE-80) #define DRM_PROC_LIMIT (PAGE_SIZE-80)
...@@ -237,15 +289,15 @@ struct drm_device; ...@@ -237,15 +289,15 @@ struct drm_device;
* \param dev DRM device. * \param dev DRM device.
* \param filp file pointer of the caller. * \param filp file pointer of the caller.
*/ */
#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \ #define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \
do { \ do { \
if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock) || \ if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \
file_priv->master->lock.file_priv != file_priv) { \ _file_priv->master->lock.file_priv != _file_priv) { \
DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\ 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),\ __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\
file_priv->master->lock.file_priv, file_priv); \ _file_priv->master->lock.file_priv, _file_priv); \
return -EINVAL; \ return -EINVAL; \
} \ } \
} while (0) } while (0)
/** /**
...@@ -502,26 +554,6 @@ struct drm_sigdata { ...@@ -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 * Kernel side of a mapping
*/ */
...@@ -1385,22 +1417,6 @@ extern char *drm_get_connector_status_name(enum drm_connector_status status); ...@@ -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 int drm_sysfs_connector_add(struct drm_connector *connector);
extern void drm_sysfs_connector_remove(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) */ /* Graphics Execution Manager library functions (drm_gem.c) */
int drm_gem_init(struct drm_device *dev); int drm_gem_init(struct drm_device *dev);
void drm_gem_destroy(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) ...@@ -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) static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
{ {
u8 *addr; if (size * nmemb <= PAGE_SIZE)
if (size <= PAGE_SIZE)
return kcalloc(nmemb, size, GFP_KERNEL); return kcalloc(nmemb, size, GFP_KERNEL);
addr = vmalloc(nmemb * size); if (size != 0 && nmemb > ULONG_MAX / size)
if (!addr)
return NULL; return NULL;
memset(addr, 0, nmemb * size); return __vmalloc(size * nmemb,
GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
return addr;
} }
static __inline void drm_free_large(void *ptr) static __inline void drm_free_large(void *ptr)
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#ifndef DRM_HASHTAB_H #ifndef DRM_HASHTAB_H
#define DRM_HASHTAB_H #define DRM_HASHTAB_H
#include <linux/list.h>
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
struct drm_hash_item { struct drm_hash_item {
......
/**************************************************************************
*
* 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 @@ ...@@ -254,6 +254,11 @@
{0x1002, 0x940A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ {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, 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, 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, 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, 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}, \ {0x1002, 0x9442, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
...@@ -268,6 +273,8 @@ ...@@ -268,6 +273,8 @@
{0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {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, 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, 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, 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, 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}, \ {0x1002, 0x947A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
...@@ -536,4 +543,6 @@ ...@@ -536,4 +543,6 @@
{0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {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, 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, 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} {0, 0, 0}
...@@ -446,6 +446,7 @@ int pnp_start_dev(struct pnp_dev *dev); ...@@ -446,6 +446,7 @@ int pnp_start_dev(struct pnp_dev *dev);
int pnp_stop_dev(struct pnp_dev *dev); int pnp_stop_dev(struct pnp_dev *dev);
int pnp_activate_dev(struct pnp_dev *dev); int pnp_activate_dev(struct pnp_dev *dev);
int pnp_disable_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 */ /* protocol helpers */
int pnp_is_active(struct pnp_dev *dev); int pnp_is_active(struct pnp_dev *dev);
...@@ -476,6 +477,7 @@ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } ...@@ -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_stop_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_activate_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_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 */ /* protocol helpers */
static inline int pnp_is_active(struct pnp_dev *dev) { return 0; } static inline int pnp_is_active(struct pnp_dev *dev) { return 0; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment