]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2009 01:09:18 +0000 (18:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2009 01:09:18 +0000 (18:09 -0700)
* '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)
  ...

34 files changed:
drivers/char/agp/intel-agp.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_hashtab.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/via/via_dmablit.c
drivers/pnp/resource.c
include/drm/drmP.h
include/drm/drm_hashtab.h
include/drm/drm_mm.h [new file with mode: 0644]
include/drm/drm_pciids.h
include/linux/pnp.h

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