summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c14
-rw-r--r--drivers/gpu/drm/drm_auth.c4
-rw-r--r--drivers/gpu/drm/drm_bufs.c140
-rw-r--r--drivers/gpu/drm/drm_context.c4
-rw-r--r--drivers/gpu/drm/drm_debugfs.c9
-rw-r--r--drivers/gpu/drm/drm_dma.c31
-rw-r--r--drivers/gpu/drm/drm_drawable.c25
-rw-r--r--drivers/gpu/drm/drm_drv.c18
-rw-r--r--drivers/gpu/drm/drm_edid.c100
-rw-r--r--drivers/gpu/drm/drm_fops.c8
-rw-r--r--drivers/gpu/drm/drm_gem.c8
-rw-r--r--drivers/gpu/drm/drm_hashtab.c6
-rw-r--r--drivers/gpu/drm/drm_ioctl.c14
-rw-r--r--drivers/gpu/drm/drm_irq.c44
-rw-r--r--drivers/gpu/drm/drm_memory.c33
-rw-r--r--drivers/gpu/drm/drm_mm.c48
-rw-r--r--drivers/gpu/drm/drm_pci.c53
-rw-r--r--drivers/gpu/drm/drm_proc.c8
-rw-r--r--drivers/gpu/drm/drm_scatter.c33
-rw-r--r--drivers/gpu/drm/drm_sman.c29
-rw-r--r--drivers/gpu/drm/drm_stub.c19
-rw-r--r--drivers/gpu/drm/drm_vm.c12
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c6
-rw-r--r--drivers/gpu/drm/i830/i830_dma.c6
-rw-r--r--drivers/gpu/drm/i915/Makefile2
-rw-r--r--drivers/gpu/drm/i915/dvo.h4
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7017.c20
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7xxx.c25
-rw-r--r--drivers/gpu/drm/i915/dvo_ivch.c21
-rw-r--r--drivers/gpu/drm/i915/dvo_sil164.c25
-rw-r--r--drivers/gpu/drm/i915/dvo_tfp410.c25
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c45
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h14
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c105
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debug.c6
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c69
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c12
-rw-r--r--drivers/gpu/drm/i915/i915_mem.c24
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h29
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c34
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c18
-rw-r--r--drivers/gpu/drm/i915/intel_display.c219
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c1153
-rw-r--r--drivers/gpu/drm/i915/intel_dp.h144
-rw-r--r--drivers/gpu/drm/i915/intel_dp_i2c.c272
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h17
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c16
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c6
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c35
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c16
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c344
-rw-r--r--drivers/gpu/drm/i915/intel_modes.c14
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c72
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c64
-rw-r--r--drivers/gpu/drm/mga/mga_dma.c14
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c12
-rw-r--r--drivers/gpu/drm/r128/r128_state.c84
-rw-r--r--drivers/gpu/drm/radeon/r100.c85
-rw-r--r--drivers/gpu/drm/radeon/r300.c478
-rw-r--r--drivers/gpu/drm/radeon/r300.h36
-rw-r--r--drivers/gpu/drm/radeon/radeon.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h15
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c26
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c33
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_mem.c24
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c30
-rw-r--r--drivers/gpu/drm/radeon/radeon_reg.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c8
-rw-r--r--drivers/gpu/drm/radeon/rv515.c58
-rw-r--r--drivers/gpu/drm/savage/savage_bci.c21
-rw-r--r--drivers/gpu/drm/savage/savage_state.c17
-rw-r--r--drivers/gpu/drm/sis/sis_drv.c6
-rw-r--r--drivers/gpu/drm/ttm/ttm_agp_backend.c3
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c11
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c1
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c1
-rw-r--r--drivers/gpu/drm/ttm/ttm_tt.c12
-rw-r--r--drivers/gpu/drm/via/via_map.c8
91 files changed, 3529 insertions, 1051 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c961fe415aef..39b393d38bb3 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -81,6 +81,7 @@ config DRM_I830
config DRM_I915
tristate "i915 driver"
+ depends on AGP_INTEL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 4e89ab08b7b8..fe23f29f7cba 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -16,6 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm-$(CONFIG_COMPAT) += drm_ioc32.o
obj-$(CONFIG_DRM) += drm.o
+obj-$(CONFIG_DRM_TTM) += ttm/
obj-$(CONFIG_DRM_TDFX) += tdfx/
obj-$(CONFIG_DRM_R128) += r128/
obj-$(CONFIG_DRM_RADEON)+= radeon/
@@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915) += i915/
obj-$(CONFIG_DRM_SIS) += sis/
obj-$(CONFIG_DRM_SAVAGE)+= savage/
obj-$(CONFIG_DRM_VIA) +=via/
-obj-$(CONFIG_DRM_TTM) += ttm/
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index 14796594e5d9..d68888fe3df9 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -203,7 +203,7 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
+ if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
@@ -211,7 +211,7 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request->type;
if (!(memory = drm_alloc_agp(dev, pages, type))) {
- drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ kfree(entry);
return -ENOMEM;
}
@@ -369,7 +369,7 @@ int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
- drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ kfree(entry);
return 0;
}
EXPORT_SYMBOL(drm_agp_free);
@@ -397,13 +397,13 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
{
struct drm_agp_head *head = NULL;
- if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
+ if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
return NULL;
memset((void *)head, 0, sizeof(*head));
head->bridge = agp_find_bridge(dev->pdev);
if (!head->bridge) {
if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
- drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+ kfree(head);
return NULL;
}
agp_copy_info(head->bridge, &head->agp_info);
@@ -412,7 +412,7 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
agp_copy_info(head->bridge, &head->agp_info);
}
if (head->agp_info.chipset == NOT_SUPPORTED) {
- drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+ kfree(head);
return NULL;
}
INIT_LIST_HEAD(&head->memory);
@@ -482,7 +482,7 @@ drm_agp_bind_pages(struct drm_device *dev,
}
for (i = 0; i < num_pages; i++)
- mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
+ mem->pages[i] = pages[i];
mem->page_count = num_pages;
mem->is_flushed = true;
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index ca7a9ef5007b..932b5aa96a67 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -79,7 +79,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
struct drm_device *dev = master->minor->dev;
DRM_DEBUG("%d\n", magic);
- entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
@@ -120,7 +120,7 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
list_del(&pt->head);
mutex_unlock(&dev->struct_mutex);
- drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ kfree(pt);
return 0;
}
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 80a257554b30..6246e3f3dad7 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -151,7 +151,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
unsigned long user_token;
int ret;
- map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
+ map = kmalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return -ENOMEM;
@@ -165,7 +165,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
* when processes fork.
*/
if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
@@ -179,7 +179,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
map->size = PAGE_ALIGN(map->size);
if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
map->mtrr = -1;
@@ -191,7 +191,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
if (map->offset + (map->size-1) < map->offset ||
map->offset < virt_to_phys(high_memory)) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
#endif
@@ -212,7 +212,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
list->map->size = map->size;
}
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
*maplist = list;
return 0;
}
@@ -227,7 +227,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
if (map->type == _DRM_REGISTERS) {
map->handle = ioremap(map->offset, map->size);
if (!map->handle) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -ENOMEM;
}
}
@@ -243,7 +243,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
list->map->size = map->size;
}
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
*maplist = list;
return 0;
}
@@ -251,7 +251,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
DRM_DEBUG("%lu %d %p\n",
map->size, drm_order(map->size), map->handle);
if (!map->handle) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -ENOMEM;
}
map->offset = (unsigned long)map->handle;
@@ -259,7 +259,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
/* Prevent a 2nd X Server from creating a 2nd lock */
if (dev->primary->master->lock.hw_lock != NULL) {
vfree(map->handle);
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EBUSY;
}
dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */
@@ -270,7 +270,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
int valid = 0;
if (!drm_core_has_AGP(dev)) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
#ifdef __alpha__
@@ -303,7 +303,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
}
}
if (!list_empty(&dev->agp->memory) && !valid) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EPERM;
}
DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
@@ -316,7 +316,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
}
case _DRM_SCATTER_GATHER:
if (!dev->sg) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
map->offset += (unsigned long)dev->sg->virtual;
@@ -328,7 +328,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
* need to point to a 64bit variable first. */
dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
if (!dmah) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -ENOMEM;
}
map->handle = dmah->vaddr;
@@ -336,15 +336,15 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
kfree(dmah);
break;
default:
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
- list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
+ list = kmalloc(sizeof(*list), GFP_KERNEL);
if (!list) {
if (map->type == _DRM_REGISTERS)
iounmap(map->handle);
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return -EINVAL;
}
memset(list, 0, sizeof(*list));
@@ -362,8 +362,8 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
if (ret) {
if (map->type == _DRM_REGISTERS)
iounmap(map->handle);
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+ kfree(map);
+ kfree(list);
mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -448,7 +448,7 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
list_del(&r_list->head);
drm_ht_remove_key(&dev->map_hash,
r_list->user_token >> PAGE_SHIFT);
- drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ kfree(r_list);
found = 1;
break;
}
@@ -491,7 +491,7 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
DRM_ERROR("tried to rmmap GEM object\n");
break;
}
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
return 0;
}
@@ -582,24 +582,16 @@ static void drm_cleanup_buf_error(struct drm_device * dev,
drm_pci_free(dev, entry->seglist[i]);
}
}
- drm_free(entry->seglist,
- entry->seg_count *
- sizeof(*entry->seglist), DRM_MEM_SEGS);
+ kfree(entry->seglist);
entry->seg_count = 0;
}
if (entry->buf_count) {
for (i = 0; i < entry->buf_count; i++) {
- if (entry->buflist[i].dev_private) {
- drm_free(entry->buflist[i].dev_private,
- entry->buflist[i].dev_priv_size,
- DRM_MEM_BUFS);
- }
+ kfree(entry->buflist[i].dev_private);
}
- drm_free(entry->buflist,
- entry->buf_count *
- sizeof(*entry->buflist), DRM_MEM_BUFS);
+ kfree(entry->buflist);
entry->buf_count = 0;
}
@@ -698,8 +690,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
return -EINVAL;
}
- entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
+ entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
if (!entry->buflist) {
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
@@ -729,7 +720,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
@@ -749,10 +740,9 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
DRM_DEBUG("byte_count: %d\n", byte_count);
- temp_buflist = drm_realloc(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ temp_buflist = krealloc(dma->buflist,
+ (dma->buf_count + entry->buf_count) *
+ sizeof(*dma->buflist), GFP_KERNEL);
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
@@ -854,8 +844,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
return -EINVAL;
}
- entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
+ entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
if (!entry->buflist) {
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
@@ -863,11 +852,9 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
}
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
- entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
- DRM_MEM_SEGS);
+ entry->seglist = kmalloc(count * sizeof(*entry->seglist), GFP_KERNEL);
if (!entry->seglist) {
- drm_free(entry->buflist,
- count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+ kfree(entry->buflist);
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
@@ -877,13 +864,11 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
/* Keep the original pagelist until we know all the allocations
* have succeeded
*/
- temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
+ sizeof(*dma->pagelist), GFP_KERNEL);
if (!temp_pagelist) {
- drm_free(entry->buflist,
- count * sizeof(*entry->buflist), DRM_MEM_BUFS);
- drm_free(entry->seglist,
- count * sizeof(*entry->seglist), DRM_MEM_SEGS);
+ kfree(entry->buflist);
+ kfree(entry->seglist);
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
@@ -907,9 +892,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
entry->buf_count = count;
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
- drm_free(temp_pagelist,
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ kfree(temp_pagelist);
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
@@ -940,18 +923,14 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc(buf->dev_priv_size,
- DRM_MEM_BUFS);
+ buf->dev_private = kmalloc(buf->dev_priv_size,
+ GFP_KERNEL);
if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
- drm_free(temp_pagelist,
- (dma->page_count +
- (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
+ kfree(temp_pagelist);
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
@@ -964,16 +943,13 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
byte_count += PAGE_SIZE << page_order;
}
- temp_buflist = drm_realloc(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ temp_buflist = krealloc(dma->buflist,
+ (dma->buf_count + entry->buf_count) *
+ sizeof(*dma->buflist), GFP_KERNEL);
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- drm_free(temp_pagelist,
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ kfree(temp_pagelist);
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
@@ -988,9 +964,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
* with the new one.
*/
if (dma->page_count) {
- drm_free(dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
+ kfree(dma->pagelist);
}
dma->pagelist = temp_pagelist;
@@ -1086,8 +1060,8 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request
return -EINVAL;
}
- entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
+ entry->buflist = kmalloc(count * sizeof(*entry->buflist),
+ GFP_KERNEL);
if (!entry->buflist) {
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
@@ -1118,7 +1092,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
@@ -1139,10 +1113,9 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request
DRM_DEBUG("byte_count: %d\n", byte_count);
- temp_buflist = drm_realloc(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ temp_buflist = krealloc(dma->buflist,
+ (dma->buf_count + entry->buf_count) *
+ sizeof(*dma->buflist), GFP_KERNEL);
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
@@ -1248,8 +1221,8 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request
return -EINVAL;
}
- entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
+ entry->buflist = kmalloc(count * sizeof(*entry->buflist),
+ GFP_KERNEL);
if (!entry->buflist) {
mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
@@ -1279,7 +1252,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request
buf->file_priv = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
@@ -1299,10 +1272,9 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request
DRM_DEBUG("byte_count: %d\n", byte_count);
- temp_buflist = drm_realloc(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ temp_buflist = krealloc(dma->buflist,
+ (dma->buf_count + entry->buf_count) *
+ sizeof(*dma->buflist), GFP_KERNEL);
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index 7d1e53c10d4b..2607753a320b 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -341,7 +341,7 @@ int drm_addctx(struct drm_device *dev, void *data,
}
}
- ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
+ ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
if (!ctx_entry) {
DRM_DEBUG("out of memory\n");
return -ENOMEM;
@@ -456,7 +456,7 @@ int drm_rmctx(struct drm_device *dev, void *data,
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx->handle) {
list_del(&pos->head);
- drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+ kfree(pos);
--dev->ctx_count;
}
}
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 6ce0e2667a85..2960b6d73456 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -100,15 +100,13 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
(dev->driver->driver_features & features) != features)
continue;
- tmp = drm_alloc(sizeof(struct drm_info_node),
- _DRM_DRIVER);
+ tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
root, tmp, &drm_debugfs_fops);
if (!ent) {
DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
name, files[i].name);
- drm_free(tmp, sizeof(struct drm_info_node),
- _DRM_DRIVER);
+ kfree(tmp);
ret = -1;
goto fail;
}
@@ -196,8 +194,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count,
if (tmp->info_ent == &files[i]) {
debugfs_remove(tmp->dent);
list_del(pos);
- drm_free(tmp, sizeof(struct drm_info_node),
- _DRM_DRIVER);
+ kfree(tmp);
}
}
}
diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c
index 7a8e2fba4678..13f1537413fb 100644
--- a/drivers/gpu/drm/drm_dma.c
+++ b/drivers/gpu/drm/drm_dma.c
@@ -47,7 +47,7 @@ int drm_dma_setup(struct drm_device *dev)
{
int i;
- dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
+ dev->dma = kmalloc(sizeof(*dev->dma), GFP_KERNEL);
if (!dev->dma)
return -ENOMEM;
@@ -88,36 +88,19 @@ void drm_dma_takedown(struct drm_device *dev)
drm_pci_free(dev, dma->bufs[i].seglist[j]);
}
}
- drm_free(dma->bufs[i].seglist,
- dma->bufs[i].seg_count
- * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
+ kfree(dma->bufs[i].seglist);
}
if (dma->bufs[i].buf_count) {
for (j = 0; j < dma->bufs[i].buf_count; j++) {
- if (dma->bufs[i].buflist[j].dev_private) {
- drm_free(dma->bufs[i].buflist[j].
- dev_private,
- dma->bufs[i].buflist[j].
- dev_priv_size, DRM_MEM_BUFS);
- }
+ kfree(dma->bufs[i].buflist[j].dev_private);
}
- drm_free(dma->bufs[i].buflist,
- dma->bufs[i].buf_count *
- sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
+ kfree(dma->bufs[i].buflist);
}
}
- if (dma->buflist) {
- drm_free(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
- }
-
- if (dma->pagelist) {
- drm_free(dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
- }
- drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+ kfree(dma->buflist);
+ kfree(dma->pagelist);
+ kfree(dev->dma);
dev->dma = NULL;
}
diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c
index 80be1cab62af..c53c9768cc11 100644
--- a/drivers/gpu/drm/drm_drawable.c
+++ b/drivers/gpu/drm/drm_drawable.c
@@ -85,9 +85,8 @@ int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
return -EINVAL;
}
- drm_free(info->rects, info->num_rects * sizeof(struct drm_clip_rect),
- DRM_MEM_BUFS);
- drm_free(info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+ kfree(info->rects);
+ kfree(info);
idr_remove(&dev->drw_idr, draw->handle);
@@ -106,12 +105,12 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file
info = idr_find(&dev->drw_idr, update->handle);
if (!info) {
- info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
DRM_ERROR("No such drawable %d\n", update->handle);
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+ kfree(info);
return -EINVAL;
}
}
@@ -121,8 +120,9 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file
if (update->num == 0)
rects = NULL;
else if (update->num != info->num_rects) {
- rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
- DRM_MEM_BUFS);
+ rects = kmalloc(update->num *
+ sizeof(struct drm_clip_rect),
+ GFP_KERNEL);
} else
rects = info->rects;
@@ -145,8 +145,7 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file
spin_lock_irqsave(&dev->drw_lock, irqflags);
if (rects != info->rects) {
- drm_free(info->rects, info->num_rects *
- sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+ kfree(info->rects);
}
info->rects = rects;
@@ -166,8 +165,7 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file
error:
if (rects != info->rects)
- drm_free(rects, update->num * sizeof(struct drm_clip_rect),
- DRM_MEM_BUFS);
+ kfree(rects);
return err;
}
@@ -186,9 +184,8 @@ static int drm_drawable_free(int idr, void *p, void *data)
struct drm_drawable_info *info = p;
if (info) {
- drm_free(info->rects, info->num_rects *
- sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+ kfree(info->rects);
+ kfree(info);
}
return 0;
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 1bf7efd8d334..b39d7bfc0c9c 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -189,7 +189,7 @@ int drm_lastclose(struct drm_device * dev)
if (entry->bound)
drm_unbind_agp(entry->memory);
drm_free_agp(entry->memory, entry->pages);
- drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ kfree(entry);
}
INIT_LIST_HEAD(&dev->agp->memory);
@@ -208,21 +208,15 @@ int drm_lastclose(struct drm_device * dev)
/* Clear vma list (only built for debugging) */
list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
list_del(&vma->head);
- drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+ kfree(vma);
}
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
for (i = 0; i < dev->queue_count; i++) {
- if (dev->queuelist[i]) {
- drm_free(dev->queuelist[i],
- sizeof(*dev->queuelist[0]),
- DRM_MEM_QUEUES);
- dev->queuelist[i] = NULL;
- }
+ kfree(dev->queuelist[i]);
+ dev->queuelist[i] = NULL;
}
- drm_free(dev->queuelist,
- dev->queue_slots * sizeof(*dev->queuelist),
- DRM_MEM_QUEUES);
+ kfree(dev->queuelist);
dev->queuelist = NULL;
}
dev->queue_count = 0;
@@ -344,8 +338,6 @@ static int __init drm_core_init(void)
goto err_p3;
}
- drm_mem_init();
-
DRM_INFO("Initialized %s %d.%d.%d %s\n",
CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
return 0;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 801a0d0e0810..80cc6d06d61b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -252,16 +252,18 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
{
struct drm_display_mode *mode;
int hsize = t->hsize * 8 + 248, vsize;
+ unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
+ >> EDID_TIMING_ASPECT_SHIFT;
mode = drm_mode_create(dev);
if (!mode)
return NULL;
- if (t->aspect_ratio == 0)
+ if (aspect_ratio == 0)
vsize = (hsize * 10) / 16;
- else if (t->aspect_ratio == 1)
+ else if (aspect_ratio == 1)
vsize = (hsize * 3) / 4;
- else if (t->aspect_ratio == 2)
+ else if (aspect_ratio == 2)
vsize = (hsize * 4) / 5;
else
vsize = (hsize * 9) / 16;
@@ -288,17 +290,24 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
{
struct drm_display_mode *mode;
struct detailed_pixel_timing *pt = &timing->data.pixel_data;
+ unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
+ unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
+ unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
+ unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
+ unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
+ unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
+ unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+ unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
/* ignore tiny modes */
- if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 ||
- ((pt->vactive_hi << 8) | pt->hactive_lo) < 64)
+ if (hactive < 64 || vactive < 64)
return NULL;
- if (pt->stereo) {
+ if (pt->misc & DRM_EDID_PT_STEREO) {
printk(KERN_WARNING "stereo mode not supported\n");
return NULL;
}
- if (!pt->separate_sync) {
+ if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
printk(KERN_WARNING "integrated sync not supported\n");
return NULL;
}
@@ -310,41 +319,36 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
mode->type = DRM_MODE_TYPE_DRIVER;
if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
- timing->pixel_clock = 1088;
-
- mode->clock = timing->pixel_clock * 10;
-
- mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
- mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
- pt->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start +
- ((pt->hsync_pulse_width_hi << 8) |
- pt->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
-
- mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
- mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
- pt->vsync_offset_lo);
- mode->vsync_end = mode->vsync_start +
- ((pt->vsync_pulse_width_hi << 4) |
- pt->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
+ timing->pixel_clock = cpu_to_le16(1088);
+
+ mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
+
+ mode->hdisplay = hactive;
+ mode->hsync_start = mode->hdisplay + hsync_offset;
+ mode->hsync_end = mode->hsync_start + hsync_pulse_width;
+ mode->htotal = mode->hdisplay + hblank;
+
+ mode->vdisplay = vactive;
+ mode->vsync_start = mode->vdisplay + vsync_offset;
+ mode->vsync_end = mode->vsync_start + vsync_pulse_width;
+ mode->vtotal = mode->vdisplay + vblank;
drm_mode_set_name(mode);
- if (pt->interlaced)
+ if (pt->misc & DRM_EDID_PT_INTERLACED)
mode->flags |= DRM_MODE_FLAG_INTERLACE;
if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
- pt->hsync_positive = 1;
- pt->vsync_positive = 1;
+ pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
}
- mode->flags |= pt->hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
- mode->flags |= pt->vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+ mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+ DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+ mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+ DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
- mode->width_mm = pt->width_mm_lo | (pt->width_mm_hi << 8);
- mode->height_mm = pt->height_mm_lo | (pt->height_mm_hi << 8);
+ mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
+ mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
mode->width_mm *= 10;
@@ -465,7 +469,7 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
struct drm_display_mode *newmode;
/* If std timings bytes are 1, 1 it's empty */
- if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
+ if (t->hsize == 1 && t->vfreq_aspect == 1)
continue;
newmode = drm_mode_std(dev, &edid->standard_timings[i]);
@@ -509,7 +513,7 @@ static int add_detailed_info(struct drm_connector *connector,
continue;
/* First detailed mode is preferred */
- if (i == 0 && edid->preferred_timing)
+ if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
newmode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, newmode);
@@ -767,22 +771,22 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
edid_fixup_preferred(connector, quirks);
- connector->display_info.serration_vsync = edid->serration_vsync;
- connector->display_info.sync_on_green = edid->sync_on_green;
- connector->display_info.composite_sync = edid->composite_sync;
- connector->display_info.separate_syncs = edid->separate_syncs;
- connector->display_info.blank_to_black = edid->blank_to_black;
- connector->display_info.video_level = edid->video_level;
- connector->display_info.digital = edid->digital;
+ connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0;
+ connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0;
+ connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0;
+ connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0;
+ connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0;
+ connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5;
+ connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0;
connector->display_info.width_mm = edid->width_cm * 10;
connector->display_info.height_mm = edid->height_cm * 10;
connector->display_info.gamma = edid->gamma;
- connector->display_info.gtf_supported = edid->default_gtf;
- connector->display_info.standard_color = edid->standard_color;
- connector->display_info.display_type = edid->display_type;
- connector->display_info.active_off_supported = edid->pm_active_off;
- connector->display_info.suspend_supported = edid->pm_suspend;
- connector->display_info.standby_supported = edid->pm_standby;
+ connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0;
+ connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0;
+ connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3;
+ connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0;
+ connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0;
+ connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0;
connector->display_info.gamma = edid->gamma;
return num_modes;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 09a3571c9908..251bc0e3b5ec 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -240,7 +240,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -328,7 +328,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
return 0;
out_free:
- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+ kfree(priv);
filp->private_data = NULL;
return ret;
}
@@ -471,7 +471,7 @@ int drm_release(struct inode *inode, struct file *filp)
drm_ctxbitmap_free(dev, pos->handle);
list_del(&pos->head);
- drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+ kfree(pos);
--dev->ctx_count;
}
}
@@ -516,7 +516,7 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->postclose)
dev->driver->postclose(dev, file_priv);
- drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
+ kfree(file_priv);
/* ========================================================
* End inline drm_release
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index ec43005100d9..8104ecaea26f 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -89,7 +89,7 @@ drm_gem_init(struct drm_device *dev)
atomic_set(&dev->gtt_count, 0);
atomic_set(&dev->gtt_memory, 0);
- mm = drm_calloc(1, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+ mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
if (!mm) {
DRM_ERROR("out of memory\n");
return -ENOMEM;
@@ -98,14 +98,14 @@ drm_gem_init(struct drm_device *dev)
dev->mm_private = mm;
if (drm_ht_create(&mm->offset_hash, 19)) {
- drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+ kfree(mm);
return -ENOMEM;
}
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
DRM_FILE_PAGE_OFFSET_SIZE)) {
drm_ht_remove(&mm->offset_hash);
- drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+ kfree(mm);
return -ENOMEM;
}
@@ -119,7 +119,7 @@ drm_gem_destroy(struct drm_device *dev)
drm_mm_takedown(&mm->offset_manager);
drm_ht_remove(&mm->offset_hash);
- drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+ kfree(mm);
dev->mm_private = NULL;
}
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index ac35145c3e20..f36b21c5b2e1 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -46,8 +46,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
ht->table = NULL;
ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
if (!ht->use_vmalloc) {
- ht->table = drm_calloc(ht->size, sizeof(*ht->table),
- DRM_MEM_HASHTAB);
+ ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
}
if (!ht->table) {
ht->use_vmalloc = 1;
@@ -200,8 +199,7 @@ void drm_ht_remove(struct drm_open_hash *ht)
if (ht->use_vmalloc)
vfree(ht->table);
else
- drm_free(ht->table, ht->size * sizeof(*ht->table),
- DRM_MEM_HASHTAB);
+ kfree(ht->table);
ht->table = NULL;
}
}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 1fad76289e66..9b9ff46c2378 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -93,7 +93,7 @@ int drm_setunique(struct drm_device *dev, void *data,
master->unique_len = u->unique_len;
master->unique_size = u->unique_len + 1;
- master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER);
+ master->unique = kmalloc(master->unique_size, GFP_KERNEL);
if (!master->unique)
return -ENOMEM;
if (copy_from_user(master->unique, u->unique, master->unique_len))
@@ -101,9 +101,8 @@ int drm_setunique(struct drm_device *dev, void *data,
master->unique[master->unique_len] = '\0';
- dev->devname =
- drm_alloc(strlen(dev->driver->pci_driver.name) +
- strlen(master->unique) + 2, DRM_MEM_DRIVER);
+ dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+ strlen(master->unique) + 2, GFP_KERNEL);
if (!dev->devname)
return -ENOMEM;
@@ -138,7 +137,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
master->unique_len = 40;
master->unique_size = master->unique_len;
- master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER);
+ master->unique = kmalloc(master->unique_size, GFP_KERNEL);
if (master->unique == NULL)
return -ENOMEM;
@@ -152,9 +151,8 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
else
master->unique_len = len;
- dev->devname =
- drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len +
- 2, DRM_MEM_DRIVER);
+ dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+ master->unique_len + 2, GFP_KERNEL);
if (dev->devname == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index fc8e5acd9d9a..b4a3dbcebe9b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -104,21 +104,13 @@ void drm_vblank_cleanup(struct drm_device *dev)
vblank_disable_fn((unsigned long)dev);
- drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
- dev->num_crtcs, DRM_MEM_DRIVER);
- drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
- dev->num_crtcs, DRM_MEM_DRIVER);
- drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
- dev->num_crtcs, DRM_MEM_DRIVER);
- drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->last_vblank_wait,
- sizeof(*dev->last_vblank_wait) * dev->num_crtcs,
- DRM_MEM_DRIVER);
- drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
- dev->num_crtcs, DRM_MEM_DRIVER);
+ kfree(dev->vbl_queue);
+ kfree(dev->_vblank_count);
+ kfree(dev->vblank_refcount);
+ kfree(dev->vblank_enabled);
+ kfree(dev->last_vblank);
+ kfree(dev->last_vblank_wait);
+ kfree(dev->vblank_inmodeset);
dev->num_crtcs = 0;
}
@@ -132,37 +124,33 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
spin_lock_init(&dev->vbl_lock);
dev->num_crtcs = num_crtcs;
- dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
- DRM_MEM_DRIVER);
+ dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
+ GFP_KERNEL);
if (!dev->vbl_queue)
goto err;
- dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
- DRM_MEM_DRIVER);
+ dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL);
if (!dev->_vblank_count)
goto err;
- dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
- DRM_MEM_DRIVER);
+ dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs,
+ GFP_KERNEL);
if (!dev->vblank_refcount)
goto err;
- dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
- DRM_MEM_DRIVER);
+ dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
if (!dev->vblank_enabled)
goto err;
- dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+ dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
if (!dev->last_vblank)
goto err;
- dev->last_vblank_wait = drm_calloc(num_crtcs, sizeof(u32),
- DRM_MEM_DRIVER);
+ dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
if (!dev->last_vblank_wait)
goto err;
- dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
- DRM_MEM_DRIVER);
+ dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
if (!dev->vblank_inmodeset)
goto err;
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index 0c707f533eab..e4865f99989c 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -36,15 +36,6 @@
#include <linux/highmem.h>
#include "drmP.h"
-#ifdef DEBUG_MEMORY
-#include "drm_memory_debug.h"
-#else
-
-/** No-op. */
-void drm_mem_init(void)
-{
-}
-
/**
* Called when "/proc/dri/%dev%/mem" is read.
*
@@ -64,28 +55,15 @@ int drm_mem_info(char *buf, char **start, off_t offset,
return 0;
}
-/** Wrapper around kmalloc() and kfree() */
-void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
-{
- void *pt;
-
- if (!(pt = kmalloc(size, GFP_KERNEL)))
- return NULL;
- if (oldpt && oldsize) {
- memcpy(pt, oldpt, oldsize);
- kfree(oldpt);
- }
- return pt;
-}
-
#if __OS_HAS_AGP
static void *agp_remap(unsigned long offset, unsigned long size,
struct drm_device * dev)
{
- unsigned long *phys_addr_map, i, num_pages =
+ unsigned long i, num_pages =
PAGE_ALIGN(size) / PAGE_SIZE;
struct drm_agp_mem *agpmem;
struct page **page_map;
+ struct page **phys_page_map;
void *addr;
size = PAGE_ALIGN(size);
@@ -112,10 +90,9 @@ static void *agp_remap(unsigned long offset, unsigned long size,
if (!page_map)
return NULL;
- phys_addr_map =
- agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE);
for (i = 0; i < num_pages; ++i)
- page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+ page_map[i] = phys_page_map[i];
addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
vfree(page_map);
@@ -157,8 +134,6 @@ static inline void *agp_remap(unsigned long offset, unsigned long size,
#endif /* agp */
-#endif /* debug_memory */
-
void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
{
if (drm_core_has_AGP(dev) &&
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index a912a0ff11cc..3e47869d6dae 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -187,9 +187,10 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
}
-
-struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node,
- unsigned long size, unsigned alignment)
+struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
+ unsigned long size,
+ unsigned alignment,
+ int atomic)
{
struct drm_mm_node *align_splitoff = NULL;
@@ -200,7 +201,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node,
if (tmp) {
align_splitoff =
- drm_mm_split_at_start(node, alignment - tmp, 0);
+ drm_mm_split_at_start(node, alignment - tmp, atomic);
if (unlikely(align_splitoff == NULL))
return NULL;
}
@@ -209,7 +210,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node,
list_del_init(&node->fl_entry);
node->free = 0;
} else {
- node = drm_mm_split_at_start(node, size, 0);
+ node = drm_mm_split_at_start(node, size, atomic);
}
if (align_splitoff)
@@ -217,42 +218,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node,
return node;
}
-
-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);
+EXPORT_SYMBOL(drm_mm_get_block_generic);
/*
* Put a block. Merge with the previous and / or next block if they are free.
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index b55d5bc6ea61..577094fb1995 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -55,17 +55,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
unsigned long addr;
size_t sz;
#endif
-#ifdef DRM_DEBUG_MEMORY
- int area = DRM_MEM_DMA;
-
- spin_lock(&drm_mem_lock);
- if ((drm_ram_used >> PAGE_SHIFT)
- > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
- spin_unlock(&drm_mem_lock);
- return 0;
- }
- spin_unlock(&drm_mem_lock);
-#endif
/* pci_alloc_consistent only guarantees alignment to the smallest
* PAGE_SIZE order which is greater than or equal to the requested size.
@@ -86,26 +75,10 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
dmah->size = size;
dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
-#ifdef DRM_DEBUG_MEMORY
- if (dmah->vaddr == NULL) {
- spin_lock(&drm_mem_lock);
- ++drm_mem_stats[area].fail_count;
- spin_unlock(&drm_mem_lock);
- kfree(dmah);
- return NULL;
- }
-
- spin_lock(&drm_mem_lock);
- ++drm_mem_stats[area].succeed_count;
- drm_mem_stats[area].bytes_allocated += size;
- drm_ram_used += size;
- spin_unlock(&drm_mem_lock);
-#else
if (dmah->vaddr == NULL) {
kfree(dmah);
return NULL;
}
-#endif
memset(dmah->vaddr, 0, size);
@@ -132,17 +105,8 @@ void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
unsigned long addr;
size_t sz;
#endif
-#ifdef DRM_DEBUG_MEMORY
- int area = DRM_MEM_DMA;
- int alloc_count;
- int free_count;
-#endif
- if (!dmah->vaddr) {
-#ifdef DRM_DEBUG_MEMORY
- DRM_MEM_ERROR(area, "Attempt to free address 0\n");
-#endif
- } else {
+ if (dmah->vaddr) {
/* XXX - Is virt_to_page() legal for consistent mem? */
/* Unreserve */
for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
@@ -152,21 +116,6 @@ void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
dmah->busaddr);
}
-
-#ifdef DRM_DEBUG_MEMORY
- spin_lock(&drm_mem_lock);
- free_count = ++drm_mem_stats[area].free_count;
- alloc_count = drm_mem_stats[area].succeed_count;
- drm_mem_stats[area].bytes_freed += size;
- drm_ram_used -= size;
- spin_unlock(&drm_mem_lock);
- if (free_count > alloc_count) {
- DRM_MEM_ERROR(area,
- "Excess frees: %d frees, %d allocs\n",
- free_count, alloc_count);
- }
-#endif
-
}
/**
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index bae5391165ac..bbd4b3d1074a 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -105,13 +105,12 @@ int drm_proc_create_files(struct drm_info_list *files, int count,
(dev->driver->driver_features & features) != features)
continue;
- tmp = drm_alloc(sizeof(struct drm_info_node), _DRM_DRIVER);
+ tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root);
if (!ent) {
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
name, files[i].name);
- drm_free(tmp, sizeof(struct drm_info_node),
- _DRM_DRIVER);
+ kfree(tmp);
ret = -1;
goto fail;
}
@@ -192,8 +191,7 @@ int drm_proc_remove_files(struct drm_info_list *files, int count,
remove_proc_entry(files[i].name,
minor->proc_root);
list_del(pos);
- drm_free(tmp, sizeof(struct drm_info_node),
- _DRM_DRIVER);
+ kfree(tmp);
}
}
}
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
index b2b0f3d41714..c7823c863d4f 100644
--- a/drivers/gpu/drm/drm_scatter.c
+++ b/drivers/gpu/drm/drm_scatter.c
@@ -58,11 +58,9 @@ void drm_sg_cleanup(struct drm_sg_mem * entry)
vfree(entry->virtual);
- drm_free(entry->busaddr,
- entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
- drm_free(entry->pagelist,
- entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
- drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ kfree(entry->busaddr);
+ kfree(entry->pagelist);
+ kfree(entry);
}
#ifdef _LP64
@@ -84,7 +82,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
if (dev->sg)
return -EINVAL;
- entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
@@ -93,34 +91,27 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
entry->pages = pages;
- entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES);
+ entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
if (!entry->pagelist) {
- drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ kfree(entry);
return -ENOMEM;
}
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
- entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
- DRM_MEM_PAGES);
+ entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
if (!entry->busaddr) {
- drm_free(entry->pagelist,
- entry->pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES);
- drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ kfree(entry->pagelist);
+ kfree(entry);
return -ENOMEM;
}
memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
if (!entry->virtual) {
- drm_free(entry->busaddr,
- entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
- drm_free(entry->pagelist,
- entry->pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES);
- drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ kfree(entry->busaddr);
+ kfree(entry->pagelist);
+ kfree(entry);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c
index 926f146390ce..463aed9403db 100644
--- a/drivers/gpu/drm/drm_sman.c
+++ b/drivers/gpu/drm/drm_sman.c
@@ -48,9 +48,7 @@ void drm_sman_takedown(struct drm_sman * sman)
{
drm_ht_remove(&sman->user_hash_tab);
drm_ht_remove(&sman->owner_hash_tab);
- if (sman->mm)
- drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
- DRM_MEM_MM);
+ kfree(sman->mm);
}
EXPORT_SYMBOL(drm_sman_takedown);
@@ -61,8 +59,9 @@ drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
{
int ret = 0;
- sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
- DRM_MEM_MM);
+ sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
+ sizeof(*sman->mm),
+ GFP_KERNEL);
if (!sman->mm) {
ret = -ENOMEM;
goto out;
@@ -78,7 +77,7 @@ drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
drm_ht_remove(&sman->owner_hash_tab);
out1:
- drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
+ kfree(sman->mm);
out:
return ret;
}
@@ -110,7 +109,7 @@ static void drm_sman_mm_destroy(void *private)
{
struct drm_mm *mm = (struct drm_mm *) private;
drm_mm_takedown(mm);
- drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+ kfree(mm);
}
static unsigned long drm_sman_mm_offset(void *private, void *ref)
@@ -130,7 +129,7 @@ drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
BUG_ON(manager >= sman->num_managers);
sman_mm = &sman->mm[manager];
- mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
+ mm = kzalloc(sizeof(*mm), GFP_KERNEL);
if (!mm) {
return -ENOMEM;
}
@@ -138,7 +137,7 @@ drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
ret = drm_mm_init(mm, start, size);
if (ret) {
- drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+ kfree(mm);
return ret;
}
@@ -176,7 +175,7 @@ static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
owner_hash);
}
- owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
+ owner_item = kzalloc(sizeof(*owner_item), GFP_KERNEL);
if (!owner_item)
goto out;
@@ -189,7 +188,7 @@ static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
return owner_item;
out1:
- drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+ kfree(owner_item);
out:
return NULL;
}
@@ -212,7 +211,7 @@ struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int man
return NULL;
}
- memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
+ memblock = kzalloc(sizeof(*memblock), GFP_KERNEL);
if (!memblock)
goto out;
@@ -237,7 +236,7 @@ struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int man
out2:
drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
out1:
- drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
+ kfree(memblock);
out:
sman_mm->free(sman_mm->private, tmp);
@@ -253,7 +252,7 @@ static void drm_sman_free(struct drm_memblock_item *item)
list_del(&item->owner_list);
drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
item->mm->free(item->mm->private, item->mm_info);
- drm_free(item, sizeof(*item), DRM_MEM_MM);
+ kfree(item);
}
int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
@@ -277,7 +276,7 @@ static void drm_sman_remove_owner(struct drm_sman *sman,
{
list_del(&owner_item->sman_list);
drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
- drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+ kfree(owner_item);
}
int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 387a8de1bc7e..155a5bbce680 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -107,7 +107,7 @@ struct drm_master *drm_master_create(struct drm_minor *minor)
{
struct drm_master *master;
- master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
+ master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master)
return NULL;
@@ -149,7 +149,7 @@ static void drm_master_destroy(struct kref *kref)
}
if (master->unique) {
- drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER);
+ kfree(master->unique);
master->unique = NULL;
master->unique_len = 0;
}
@@ -157,12 +157,12 @@ static void drm_master_destroy(struct kref *kref)
list_for_each_entry_safe(pt, next, &master->magicfree, head) {
list_del(&pt->head);
drm_ht_remove_item(&master->magiclist, &pt->hash_item);
- drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ kfree(pt);
}
drm_ht_remove(&master->magiclist);
- drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
+ kfree(master);
}
void drm_master_put(struct drm_master **master)
@@ -390,7 +390,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
DRM_DEBUG("\n");
- dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
@@ -443,7 +443,7 @@ err_g3:
err_g2:
pci_disable_device(pdev);
err_g1:
- drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ kfree(dev);
return ret;
}
EXPORT_SYMBOL(drm_get_dev);
@@ -516,7 +516,7 @@ void drm_put_dev(struct drm_device *dev)
dev->driver->unload(dev);
if (drm_core_has_AGP(dev) && dev->agp) {
- drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+ kfree(dev->agp);
dev->agp = NULL;
}
@@ -535,10 +535,9 @@ void drm_put_dev(struct drm_device *dev)
drm_put_minor(&dev->primary);
if (dev->devname) {
- drm_free(dev->devname, strlen(dev->devname) + 1,
- DRM_MEM_DRIVER);
+ kfree(dev->devname);
dev->devname = NULL;
}
- drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ kfree(dev);
}
EXPORT_SYMBOL(drm_put_dev);
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index 22f76567ac7d..7e1fbe5d4779 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -144,14 +144,14 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
* Get the page, inc the use count, and return it
*/
offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
- page = virt_to_page(__va(agpmem->memory->memory[offset]));
+ page = agpmem->memory->pages[offset];
get_page(page);
vmf->page = page;
DRM_DEBUG
("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
(unsigned long long)baddr,
- __va(agpmem->memory->memory[offset]),
+ agpmem->memory->pages[offset],
(unsigned long long)offset,
page_count(page));
return 0;
@@ -227,7 +227,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
found_maps++;
if (pt->vma == vma) {
list_del(&pt->head);
- drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+ kfree(pt);
}
}
@@ -273,7 +273,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
DRM_ERROR("tried to rmmap GEM object\n");
break;
}
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ kfree(map);
}
}
mutex_unlock(&dev->struct_mutex);
@@ -414,7 +414,7 @@ void drm_vm_open_locked(struct vm_area_struct *vma)
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_inc(&dev->vma_count);
- vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
+ vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
if (vma_entry) {
vma_entry->vma = vma;
vma_entry->pid = current->pid;
@@ -454,7 +454,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma == vma) {
list_del(&pt->head);
- drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+ kfree(pt);
break;
}
}
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index e5de8ea41544..7d1d88cdf2dc 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -227,8 +227,7 @@ static int i810_dma_cleanup(struct drm_device * dev)
/* Need to rewrite hardware status page */
I810_WRITE(0x02080, 0x1ffff000);
}
- drm_free(dev->dev_private, sizeof(drm_i810_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
@@ -439,8 +438,7 @@ static int i810_dma_init(struct drm_device *dev, void *data,
switch (init->func) {
case I810_INIT_DMA_1_4:
DRM_INFO("Using v1.4 init.\n");
- dev_priv = drm_alloc(sizeof(drm_i810_private_t),
- DRM_MEM_DRIVER);
+ dev_priv = kmalloc(sizeof(drm_i810_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
retcode = i810_dma_initialize(dev, dev_priv, init);
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
index a86ab30b4620..877bf6cb14a4 100644
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ b/drivers/gpu/drm/i830/i830_dma.c
@@ -232,8 +232,7 @@ static int i830_dma_cleanup(struct drm_device * dev)
I830_WRITE(0x02080, 0x1ffff000);
}
- drm_free(dev->dev_private, sizeof(drm_i830_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
@@ -459,8 +458,7 @@ static int i830_dma_init(struct drm_device *dev, void *data,
switch (init->func) {
case I830_INIT_DMA:
- dev_priv = drm_alloc(sizeof(drm_i830_private_t),
- DRM_MEM_DRIVER);
+ dev_priv = kmalloc(sizeof(drm_i830_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
retcode = i830_dma_initialize(dev, dev_priv, init);
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 51c5a050aa73..30d6b99fb302 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_crt.o \
intel_lvds.o \
intel_bios.o \
+ intel_dp.o \
+ intel_dp_i2c.o \
intel_hdmi.o \
intel_sdvo.o \
intel_modes.o \
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index e747ac42fe3a..288fc50627e2 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -37,7 +37,7 @@ struct intel_dvo_device {
/* GPIO register used for i2c bus to control this device */
u32 gpio;
int slave_addr;
- struct intel_i2c_chan *i2c_bus;
+ struct i2c_adapter *i2c_bus;
const struct intel_dvo_dev_ops *dev_ops;
void *dev_priv;
@@ -52,7 +52,7 @@ struct intel_dvo_dev_ops {
* Returns NULL if the device does not exist.
*/
bool (*init)(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus);
+ struct i2c_adapter *i2cbus);
/*
* Called to allow the output a chance to create properties after the
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index 03d4b4973b02..621815b531db 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
{
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
@@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
{
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
uint8_t out_buf[2];
struct i2c_msg msg = {
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
/** Probes for a CH7017 on the given bus and slave address. */
static bool ch7017_init(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus)
+ struct i2c_adapter *adapter)
{
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
struct ch7017_priv *priv;
uint8_t val;
@@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
if (priv == NULL)
return false;
- dvo->i2c_bus = i2cbus;
- dvo->i2c_bus->slave_addr = dvo->slave_addr;
+ dvo->i2c_bus = adapter;
dvo->dev_priv = priv;
if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
@@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
val != CH7018_DEVICE_ID_VALUE &&
val != CH7019_DEVICE_ID_VALUE) {
DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n",
- val, i2cbus->adapter.name,i2cbus->slave_addr);
+ val, i2cbus->adapter.name,dvo->slave_addr);
goto fail;
}
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index d2fd95dbd034..a9b896289680 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid)
static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{
struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
@@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
if (!ch7xxx->quiet) {
DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
}
@@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
uint8_t out_buf[2];
struct i2c_msg msg = {
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
if (!ch7xxx->quiet) {
DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
}
static bool ch7xxx_init(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus)
+ struct i2c_adapter *adapter)
{
/* this will detect the CH7xxx chip on the specified i2c bus */
struct ch7xxx_priv *ch7xxx;
@@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
if (ch7xxx == NULL)
return false;
- dvo->i2c_bus = i2cbus;
- dvo->i2c_bus->slave_addr = dvo->slave_addr;
+ dvo->i2c_bus = adapter;
dvo->dev_priv = ch7xxx;
ch7xxx->quiet = true;
@@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
name = ch7xxx_get_id(vendor);
if (!name) {
DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
- vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+ vendor, adapter->name, dvo->slave_addr);
goto out;
}
@@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
if (device != CH7xxx_DID) {
DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
- vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+ vendor, adapter->name, dvo->slave_addr);
goto out;
}
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index 0c8d375e8e37..aa176f9921fe 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo);
static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
{
struct ivch_priv *priv = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[1];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD,
.len = 0,
},
@@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
.buf = out_buf,
},
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD | I2C_M_NOSTART,
.len = 2,
.buf = in_buf,
@@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
if (!priv->quiet) {
DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
}
@@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
{
struct ivch_priv *priv = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[3];
struct i2c_msg msg = {
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 3,
.buf = out_buf,
@@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
if (!priv->quiet) {
DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
@@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
/** Probes the given bus and slave address for an ivch */
static bool ivch_init(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus)
+ struct i2c_adapter *adapter)
{
struct ivch_priv *priv;
uint16_t temp;
@@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo,
if (priv == NULL)
return false;
- dvo->i2c_bus = i2cbus;
- dvo->i2c_bus->slave_addr = dvo->slave_addr;
+ dvo->i2c_bus = adapter;
dvo->dev_priv = priv;
priv->quiet = true;
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index 033a4bb070b2..e1c1f7341e5c 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -76,19 +76,20 @@ struct sil164_priv {
static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{
struct sil164_priv *sil = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
@@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
if (!sil->quiet) {
DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
}
@@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
struct sil164_priv *sil= dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
uint8_t out_buf[2];
struct i2c_msg msg = {
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
if (!sil->quiet) {
DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
@@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
/* Silicon Image 164 driver for chip on i2c bus */
static bool sil164_init(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus)
+ struct i2c_adapter *adapter)
{
/* this will detect the SIL164 chip on the specified i2c bus */
struct sil164_priv *sil;
@@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
if (sil == NULL)
return false;
- dvo->i2c_bus = i2cbus;
- dvo->i2c_bus->slave_addr = dvo->slave_addr;
+ dvo->i2c_bus = adapter;
dvo->dev_priv = sil;
sil->quiet = true;
@@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
if (ch != (SIL164_VID & 0xff)) {
DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
- ch, i2cbus->adapter.name, i2cbus->slave_addr);
+ ch, adapter->name, dvo->slave_addr);
goto out;
}
@@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
if (ch != (SIL164_DID & 0xff)) {
DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
- ch, i2cbus->adapter.name, i2cbus->slave_addr);
+ ch, adapter->name, dvo->slave_addr);
goto out;
}
sil->quiet = false;
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 207fda806ebf..9ecc907384ec 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -101,19 +101,20 @@ struct tfp410_priv {
static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{
struct tfp410_priv *tfp = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
@@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
if (!tfp->quiet) {
DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
}
@@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
struct tfp410_priv *tfp = dvo->dev_priv;
- struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+ struct i2c_adapter *adapter = dvo->i2c_bus;
+ struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
uint8_t out_buf[2];
struct i2c_msg msg = {
- .addr = i2cbus->slave_addr,
+ .addr = dvo->slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
if (!tfp->quiet) {
DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
- addr, i2cbus->adapter.name, i2cbus->slave_addr);
+ addr, i2cbus->adapter.name, dvo->slave_addr);
}
return false;
@@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr)
/* Ti TFP410 driver for chip on i2c bus */
static bool tfp410_init(struct intel_dvo_device *dvo,
- struct intel_i2c_chan *i2cbus)
+ struct i2c_adapter *adapter)
{
/* this will detect the tfp410 chip on the specified i2c bus */
struct tfp410_priv *tfp;
@@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo,
if (tfp == NULL)
return false;
- dvo->i2c_bus = i2cbus;
- dvo->i2c_bus->slave_addr = dvo->slave_addr;
+ dvo->i2c_bus = adapter;
dvo->dev_priv = tfp;
tfp->quiet = true;
if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n",
- id, i2cbus->adapter.name, i2cbus->slave_addr);
+ id, adapter->name, dvo->slave_addr);
goto out;
}
if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n",
- id, i2cbus->adapter.name, i2cbus->slave_addr);
+ id, adapter->name, dvo->slave_addr);
goto out;
}
tfp->quiet = false;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1a60626f6803..f112c769d533 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -643,9 +643,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
return -EINVAL;
if (batch->num_cliprects) {
- cliprects = drm_calloc(batch->num_cliprects,
- sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ cliprects = kcalloc(batch->num_cliprects,
+ sizeof(struct drm_clip_rect),
+ GFP_KERNEL);
if (cliprects == NULL)
return -ENOMEM;
@@ -664,9 +664,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
fail_free:
- drm_free(cliprects,
- batch->num_cliprects * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kfree(cliprects);
return ret;
}
@@ -692,7 +690,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
if (cmdbuf->num_cliprects < 0)
return -EINVAL;
- batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
+ batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL);
if (batch_data == NULL)
return -ENOMEM;
@@ -701,9 +699,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
goto fail_batch_free;
if (cmdbuf->num_cliprects) {
- cliprects = drm_calloc(cmdbuf->num_cliprects,
- sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ cliprects = kcalloc(cmdbuf->num_cliprects,
+ sizeof(struct drm_clip_rect), GFP_KERNEL);
if (cliprects == NULL)
goto fail_batch_free;
@@ -726,11 +723,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
fail_clip_free:
- drm_free(cliprects,
- cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kfree(cliprects);
fail_batch_free:
- drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
+ kfree(batch_data);
return ret;
}
@@ -1067,7 +1062,7 @@ int i915_master_create(struct drm_device *dev, struct drm_master *master)
{
struct drm_i915_master_private *master_priv;
- master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+ master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (!master_priv)
return -ENOMEM;
@@ -1082,7 +1077,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
if (!master_priv)
return;
- drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+ kfree(master_priv);
master->driver_priv = NULL;
}
@@ -1111,12 +1106,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
- dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
- memset(dev_priv, 0, sizeof(drm_i915_private_t));
-
dev->dev_private = (void *)dev_priv;
dev_priv->dev = dev;
@@ -1153,13 +1146,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
"performance may suffer.\n");
}
-#ifdef CONFIG_HIGHMEM64G
- /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
- dev_priv->has_gem = 0;
-#else
/* enable GEM by default */
dev_priv->has_gem = 1;
-#endif
dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
@@ -1221,7 +1209,7 @@ out_iomapfree:
out_rmmap:
iounmap(dev_priv->regs);
free_priv:
- drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return ret;
}
@@ -1261,8 +1249,7 @@ int i915_driver_unload(struct drm_device *dev)
i915_gem_lastclose(dev);
}
- drm_free(dev->dev_private, sizeof(drm_i915_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
return 0;
}
@@ -1273,7 +1260,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
DRM_DEBUG_DRIVER(I915_DRV, "\n");
i915_file_priv = (struct drm_i915_file_private *)
- drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+ kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
if (!i915_file_priv)
return -ENOMEM;
@@ -1326,7 +1313,7 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
{
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
- drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+ kfree(i915_file_priv);
}
struct drm_ioctl_desc i915_ioctls[] = {
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 98560e1e899a..e3cb4025e323 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -67,8 +67,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
pci_save_state(dev->pdev);
- i915_save_state(dev);
-
/* If KMS is active, we do the leavevt stuff here */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
if (i915_gem_idle(dev))
@@ -77,6 +75,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
drm_irq_uninstall(dev);
}
+ i915_save_state(dev);
+
intel_opregion_free(dev, 1);
if (state.event == PM_EVENT_SUSPEND) {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8ef6bcec211b..bb4c2d387b6c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -306,6 +306,17 @@ typedef struct drm_i915_private {
u32 saveCURBPOS;
u32 saveCURBBASE;
u32 saveCURSIZE;
+ u32 saveDP_B;
+ u32 saveDP_C;
+ u32 saveDP_D;
+ u32 savePIPEA_GMCH_DATA_M;
+ u32 savePIPEB_GMCH_DATA_M;
+ u32 savePIPEA_GMCH_DATA_N;
+ u32 savePIPEB_GMCH_DATA_N;
+ u32 savePIPEA_DP_LINK_M;
+ u32 savePIPEB_DP_LINK_M;
+ u32 savePIPEA_DP_LINK_N;
+ u32 savePIPEB_DP_LINK_N;
struct {
struct drm_mm gtt_space;
@@ -646,6 +657,8 @@ void i915_gem_object_unpin(struct drm_gem_object *obj);
int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);
uint32_t i915_get_gem_seqno(struct drm_device *dev);
+int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_work_handler(struct work_struct *work);
void i915_gem_clflush_object(struct drm_gem_object *obj);
@@ -855,6 +868,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(dev)))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+#define SUPPORTS_INTEGRATED_DP(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)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c0ae6bbbd9b5..876b65cb7629 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -46,7 +46,6 @@ static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *o
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
unsigned alignment);
-static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write);
static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
static int i915_gem_evict_something(struct drm_device *dev);
static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
@@ -1007,7 +1006,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex);
#if WATCH_BUF
- DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
+ DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
obj, obj->size, read_domains, write_domain);
#endif
if (read_domains & I915_GEM_DOMAIN_GTT) {
@@ -1051,7 +1050,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
}
#if WATCH_BUF
- DRM_INFO("%s: sw_finish %d (%p %d)\n",
+ DRM_INFO("%s: sw_finish %d (%p %zd)\n",
__func__, args->handle, obj, obj->size);
#endif
obj_priv = obj->driver_private;
@@ -1158,7 +1157,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Need a new fence register? */
if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
- ret = i915_gem_object_get_fence_reg(obj, write);
+ ret = i915_gem_object_get_fence_reg(obj);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
@@ -1208,8 +1207,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
/* Set the object up for mmap'ing */
list = &obj->map_list;
- list->map = drm_calloc(1, sizeof(struct drm_map_list),
- DRM_MEM_DRIVER);
+ list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
if (!list->map)
return -ENOMEM;
@@ -1249,7 +1247,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
out_free_mm:
drm_mm_put_block(list->file_offset_node);
out_free_list:
- drm_free(list->map, sizeof(struct drm_map_list), DRM_MEM_DRIVER);
+ kfree(list->map);
return ret;
}
@@ -1271,7 +1269,7 @@ i915_gem_free_mmap_offset(struct drm_gem_object *obj)
}
if (list->map) {
- drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
+ kfree(list->map);
list->map = NULL;
}
@@ -1494,7 +1492,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
if (file_priv != NULL)
i915_file_priv = file_priv->driver_priv;
- request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
+ request = kzalloc(sizeof(*request), GFP_KERNEL);
if (request == NULL)
return 0;
@@ -1676,7 +1674,7 @@ i915_gem_retire_requests(struct drm_device *dev)
list_del(&request->list);
list_del(&request->client_list);
- drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
+ kfree(request);
} else
break;
}
@@ -2163,13 +2161,11 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
val |= I830_FENCE_REG_VALID;
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
-
}
/**
* i915_gem_object_get_fence_reg - set up a fence reg for an object
* @obj: object to map through a fence reg
- * @write: object is about to be written
*
* When mapping objects through the GTT, userspace wants to be able to write
* to them without having to worry about swizzling if the object is tiled.
@@ -2180,8 +2176,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
* It then sets up the reg based on the object's properties: address, pitch
* and tiling format.
*/
-static int
-i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
+int
+i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2331,6 +2327,42 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
}
/**
+ * i915_gem_object_put_fence_reg - waits on outstanding fenced access
+ * to the buffer to finish, and then resets the fence register.
+ * @obj: tiled object holding a fence register.
+ *
+ * Zeroes out the fence register itself and clears out the associated
+ * data structures in dev_priv and obj_priv.
+ */
+int
+i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
+ return 0;
+
+ /* On the i915, GPU access to tiled buffers is via a fence,
+ * therefore we must wait for any outstanding access to complete
+ * before clearing the fence.
+ */
+ if (!IS_I965G(dev)) {
+ int ret;
+
+ i915_gem_object_flush_gpu_write_domain(obj);
+ i915_gem_object_flush_gtt_write_domain(obj);
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret != 0)
+ return ret;
+ }
+
+ i915_gem_clear_fence_reg (obj);
+
+ return 0;
+}
+
+/**
* Finds free space in the GTT aperture and binds the object there.
*/
static int
@@ -2391,7 +2423,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
}
#if WATCH_BUF
- DRM_INFO("Binding object of size %d at 0x%08x\n",
+ DRM_INFO("Binding object of size %zd at 0x%08x\n",
obj->size, obj_priv->gtt_offset);
#endif
ret = i915_gem_object_get_pages(obj);
@@ -2800,8 +2832,7 @@ i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
/* Free the page_cpu_valid mappings which are now stale, whether
* or not we've got I915_GEM_DOMAIN_CPU.
*/
- drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
- DRM_MEM_DRIVER);
+ kfree(obj_priv->page_cpu_valid);
obj_priv->page_cpu_valid = NULL;
}
@@ -2843,8 +2874,8 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
* newly adding I915_GEM_DOMAIN_CPU
*/
if (obj_priv->page_cpu_valid == NULL) {
- obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
- DRM_MEM_DRIVER);
+ obj_priv->page_cpu_valid = kzalloc(obj->size / PAGE_SIZE,
+ GFP_KERNEL);
if (obj_priv->page_cpu_valid == NULL)
return -ENOMEM;
} else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0)
@@ -3267,8 +3298,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
}
if (args->num_cliprects != 0) {
- cliprects = drm_calloc(args->num_cliprects, sizeof(*cliprects),
- DRM_MEM_DRIVER);
+ cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
+ GFP_KERNEL);
if (cliprects == NULL)
goto pre_mutex_err;
@@ -3521,8 +3552,7 @@ err:
pre_mutex_err:
drm_free_large(object_list);
drm_free_large(exec_list);
- drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects,
- DRM_MEM_DRIVER);
+ kfree(cliprects);
return ret;
}
@@ -3550,7 +3580,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
if (!IS_I965G(dev) &&
obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
- ret = i915_gem_object_get_fence_reg(obj, true);
+ ret = i915_gem_object_get_fence_reg(obj);
if (ret != 0) {
if (ret != -EBUSY && ret != -ERESTARTSYS)
DRM_ERROR("Failure to install fence: %d\n",
@@ -3739,7 +3769,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv;
- obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
+ obj_priv = kzalloc(sizeof(*obj_priv), GFP_KERNEL);
if (obj_priv == NULL)
return -ENOMEM;
@@ -3777,9 +3807,9 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_free_mmap_offset(obj);
- drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
+ kfree(obj_priv->page_cpu_valid);
kfree(obj_priv->bit_17);
- drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
+ kfree(obj->driver_private);
}
/** Unbinds all objects that are on the given buffer list. */
@@ -4197,6 +4227,7 @@ i915_gem_lastclose(struct drm_device *dev)
void
i915_gem_load(struct drm_device *dev)
{
+ int i;
drm_i915_private_t *dev_priv = dev->dev_private;
spin_lock_init(&dev_priv->mm.active_list_lock);
@@ -4216,6 +4247,18 @@ i915_gem_load(struct drm_device *dev)
else
dev_priv->num_fence_regs = 8;
+ /* Initialize fence registers to zero */
+ if (IS_I965G(dev)) {
+ for (i = 0; i < 16; i++)
+ I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0);
+ } else {
+ for (i = 0; i < 8; i++)
+ I915_WRITE(FENCE_REG_830_0 + (i * 4), 0);
+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+ for (i = 0; i < 8; i++)
+ I915_WRITE(FENCE_REG_945_8 + (i * 4), 0);
+ }
+
i915_gem_detect_bit_6_swizzle(dev);
}
@@ -4233,7 +4276,7 @@ int i915_gem_init_phys_object(struct drm_device *dev,
if (dev_priv->mm.phys_objs[id - 1] || !size)
return 0;
- phys_obj = drm_calloc(1, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+ phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL);
if (!phys_obj)
return -ENOMEM;
@@ -4252,7 +4295,7 @@ int i915_gem_init_phys_object(struct drm_device *dev,
return 0;
kfree_obj:
- drm_free(phys_obj, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+ kfree(phys_obj);
return ret;
}
@@ -4312,6 +4355,8 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
}
drm_clflush_pages(obj_priv->pages, page_count);
drm_agp_chipset_flush(dev);
+
+ i915_gem_object_put_pages(obj);
out:
obj_priv->phys_obj->cur_obj = NULL;
obj_priv->phys_obj = NULL;
@@ -4369,6 +4414,8 @@ i915_gem_attach_phys_object(struct drm_device *dev,
kunmap_atomic(src, KM_USER0);
}
+ i915_gem_object_put_pages(obj);
+
return 0;
out:
return ret;
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
index 8d0b943e2c5a..e602614bd3f8 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len,
chunk_len = page_len - chunk;
if (chunk_len > 128)
chunk_len = 128;
- i915_gem_dump_page(obj_priv->page_list[page],
+ i915_gem_dump_page(obj_priv->pages[page],
chunk, chunk + chunk_len,
obj_priv->gtt_offset +
page * PAGE_SIZE,
@@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
uint32_t *backing_map = NULL;
int bad_count = 0;
- DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
+ DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n",
__func__, obj, obj_priv->gtt_offset, handle,
obj->size / 1024);
@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
for (page = 0; page < obj->size / PAGE_SIZE; page++) {
int i;
- backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
+ backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0);
if (backing_map == NULL) {
DRM_ERROR("failed to map backing page\n");
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index 986f1082c596..28146e405e87 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -104,7 +104,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
if (obj->name)
seq_printf(m, " (name: %d)", obj->name);
if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
- seq_printf(m, " (fence: %d\n", obj_priv->fence_reg);
+ seq_printf(m, " (fence: %d)\n", obj_priv->fence_reg);
seq_printf(m, "\n");
}
@@ -318,7 +318,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
seq_printf(m, "RingTail : %08x\n", tail);
seq_printf(m, "RingMask : %08x\n", mask);
seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
- seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
+ seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 9a05cadaa4ad..daeae62e1c28 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
+#ifdef CONFIG_PNP
if (mchbar_addr &&
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
ret = 0;
goto out_put;
}
+#endif
/* Get some space for it */
ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
@@ -408,7 +410,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
if (stride & (stride - 1))
return false;
- /* We don't handle the aperture area covered by the fence being bigger
+ /* We don't 0handle the aperture area covered by the fence being bigger
* than the object size.
*/
if (i915_get_fence_size(dev, size) != size)
@@ -417,6 +419,33 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
return true;
}
+static bool
+i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ if (obj_priv->gtt_space == NULL)
+ return true;
+
+ if (tiling_mode == I915_TILING_NONE)
+ return true;
+
+ if (!IS_I965G(dev)) {
+ if (obj_priv->gtt_offset & (obj->size - 1))
+ return false;
+ if (IS_I9XX(dev)) {
+ if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+ return false;
+ } else {
+ if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+ return false;
+ }
+ }
+
+ return true;
+}
+
/**
* Sets the tiling mode of an object, returning the required swizzling of
* bit 6 of addresses in the object.
@@ -429,6 +458,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
@@ -436,14 +466,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
obj_priv = obj->driver_private;
if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
+ mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- mutex_lock(&dev->struct_mutex);
-
if (args->tiling_mode == I915_TILING_NONE) {
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ args->stride = 0;
} else {
if (args->tiling_mode == I915_TILING_X)
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -466,32 +497,38 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
args->tiling_mode = I915_TILING_NONE;
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ args->stride = 0;
}
}
- if (args->tiling_mode != obj_priv->tiling_mode) {
- int ret;
- /* Unbind the object, as switching tiling means we're
- * switching the cache organization due to fencing, probably.
+ mutex_lock(&dev->struct_mutex);
+ if (args->tiling_mode != obj_priv->tiling_mode ||
+ args->stride != obj_priv->stride) {
+ /* We need to rebind the object if its current allocation
+ * no longer meets the alignment restrictions for its new
+ * tiling mode. Otherwise we can just leave it alone, but
+ * need to ensure that any fence register is cleared.
*/
- ret = i915_gem_object_unbind(obj);
+ if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
+ ret = i915_gem_object_unbind(obj);
+ else
+ ret = i915_gem_object_put_fence_reg(obj);
if (ret != 0) {
WARN(ret != -ERESTARTSYS,
- "failed to unbind object for tiling switch");
+ "failed to reset object for tiling switch");
args->tiling_mode = obj_priv->tiling_mode;
- mutex_unlock(&dev->struct_mutex);
- drm_gem_object_unreference(obj);
-
- return ret;
+ args->stride = obj_priv->stride;
+ goto err;
}
+
obj_priv->tiling_mode = args->tiling_mode;
+ obj_priv->stride = args->stride;
}
- obj_priv->stride = args->stride;
-
+err:
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
- return 0;
+ return ret;
}
/**
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b86b7b7130c6..228546f6eaa4 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -232,7 +232,17 @@ static void i915_hotplug_work_func(struct work_struct *work)
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
hotplug_work);
struct drm_device *dev = dev_priv->dev;
-
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector *connector;
+
+ if (mode_config->num_connector) {
+ list_for_each_entry(connector, &mode_config->connector_list, head) {
+ struct intel_output *intel_output = to_intel_output(connector);
+
+ if (intel_output->hot_plug)
+ (*intel_output->hot_plug) (intel_output);
+ }
+ }
/* Just fire off a uevent and let userspace tell us what to do */
drm_sysfs_hotplug_event(dev);
}
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c
index 96e271986d2a..83b7b81bb2b8 100644
--- a/drivers/gpu/drm/i915/i915_mem.c
+++ b/drivers/gpu/drm/i915/i915_mem.c
@@ -94,8 +94,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
- struct mem_block *newblock =
- drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ struct mem_block *newblock = kmalloc(sizeof(*newblock),
+ GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start;
@@ -111,8 +111,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
/* Maybe cut off the end of an existing block */
if (size < p->size) {
- struct mem_block *newblock =
- drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ struct mem_block *newblock = kmalloc(sizeof(*newblock),
+ GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start + size;
@@ -169,7 +169,7 @@ static void free_block(struct mem_block *p)
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+ kfree(q);
}
if (p->prev->file_priv == NULL) {
@@ -177,7 +177,7 @@ static void free_block(struct mem_block *p)
q->size += p->size;
q->next = p->next;
q->next->prev = q;
- drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
+ kfree(p);
}
}
@@ -185,14 +185,14 @@ static void free_block(struct mem_block *p)
*/
static int init_heap(struct mem_block **heap, int start, int size)
{
- struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
+ struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
if (!blocks)
return -ENOMEM;
- *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
+ *heap = kmalloc(sizeof(**heap), GFP_KERNEL);
if (!*heap) {
- drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
+ kfree(blocks);
return -ENOMEM;
}
@@ -233,7 +233,7 @@ void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+ kfree(q);
}
}
}
@@ -250,10 +250,10 @@ void i915_mem_takedown(struct mem_block **heap)
for (p = (*heap)->next; p != *heap;) {
struct mem_block *q = p;
p = p->next;
- drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+ kfree(q);
}
- drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
+ kfree(*heap);
*heap = NULL;
}
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
index dc425e74a268..e4b4e8898e39 100644
--- a/drivers/gpu/drm/i915/i915_opregion.c
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -419,7 +419,7 @@ void intel_opregion_free(struct drm_device *dev, int suspend)
return;
if (!suspend)
- acpi_video_exit();
+ acpi_video_unregister();
opregion->acpi->drdy = 0;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f6237a0b1133..88bf7521405f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -569,6 +569,19 @@
#define C0DRB3 0x10206
#define C1DRB3 0x10606
+/* Clocking configuration register */
+#define CLKCFG 0x10c00
+#define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */
+#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */
+#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */
+#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */
+#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */
+#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */
+/* this is a guess, could be 5 as well */
+#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */
+#define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */
+#define CLKCFG_FSB_MASK (7 << 0)
+
/** GM965 GM45 render standby register */
#define MCHBAR_RENDER_STANDBY 0x111B8
@@ -834,9 +847,25 @@
#define HORIZ_INTERP_MASK (3 << 6)
#define HORIZ_AUTO_SCALE (1 << 5)
#define PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define PFIT_FILTER_FUZZY (0 << 24)
+#define PFIT_SCALING_AUTO (0 << 26)
+#define PFIT_SCALING_PROGRAMMED (1 << 26)
+#define PFIT_SCALING_PILLAR (2 << 26)
+#define PFIT_SCALING_LETTER (3 << 26)
#define PFIT_PGM_RATIOS 0x61234
#define PFIT_VERT_SCALE_MASK 0xfff00000
#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+/* Pre-965 */
+#define PFIT_VERT_SCALE_SHIFT 20
+#define PFIT_VERT_SCALE_MASK 0xfff00000
+#define PFIT_HORIZ_SCALE_SHIFT 4
+#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+/* 965+ */
+#define PFIT_VERT_SCALE_SHIFT_965 16
+#define PFIT_VERT_SCALE_MASK_965 0x1fff0000
+#define PFIT_HORIZ_SCALE_SHIFT_965 0
+#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff
+
#define PFIT_AUTO_RATIOS 0x61238
/* Backlight control */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index a98e2831ed31..8d8e083d14ab 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -322,6 +322,20 @@ int i915_save_state(struct drm_device *dev)
dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+ /* Display Port state */
+ if (SUPPORTS_INTEGRATED_DP(dev)) {
+ dev_priv->saveDP_B = I915_READ(DP_B);
+ dev_priv->saveDP_C = I915_READ(DP_C);
+ dev_priv->saveDP_D = I915_READ(DP_D);
+ dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M);
+ dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M);
+ dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N);
+ dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N);
+ dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M);
+ dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M);
+ dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N);
+ dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N);
+ }
/* FIXME: save TV & SDVO state */
/* FBC state */
@@ -404,7 +418,19 @@ int i915_restore_state(struct drm_device *dev)
for (i = 0; i < 8; i++)
I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
}
-
+
+ /* Display port ratios (must be done before clock is set) */
+ if (SUPPORTS_INTEGRATED_DP(dev)) {
+ I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
+ I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
+ I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
+ I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
+ I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
+ I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
+ I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
+ I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
+ }
+
/* Pipe & plane A info */
/* Prime the clock */
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
@@ -518,6 +544,12 @@ int i915_restore_state(struct drm_device *dev)
I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+ /* Display Port state */
+ if (SUPPORTS_INTEGRATED_DP(dev)) {
+ I915_WRITE(DP_B, dev_priv->saveDP_B);
+ I915_WRITE(DP_C, dev_priv->saveDP_C);
+ I915_WRITE(DP_D, dev_priv->saveDP_D);
+ }
/* FIXME: restore TV & SDVO state */
/* FBC info */
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 754dd22fdd77..716409a57244 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -99,9 +99,11 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
{
struct bdb_lvds_options *lvds_options;
struct bdb_lvds_lfp_data *lvds_lfp_data;
+ struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
struct bdb_lvds_lfp_data_entry *entry;
struct lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode;
+ int lfp_data_size;
/* Defaults if we can't find VBT info */
dev_priv->lvds_dither = 0;
@@ -119,13 +121,20 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
if (!lvds_lfp_data)
return;
+ lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+ if (!lvds_lfp_data_ptrs)
+ return;
+
dev_priv->lvds_vbt = 1;
- entry = &lvds_lfp_data->data[lvds_options->panel_type];
+ lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+ lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+ entry = (struct bdb_lvds_lfp_data_entry *)
+ ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
+ lvds_options->panel_type));
dvo_timing = &entry->dvo_timing;
- panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
- DRM_MEM_DRIVER);
+ panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
fill_detail_timing_data(panel_fixed_mode, dvo_timing);
@@ -156,8 +165,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
if (!dvo_timing)
return;
- panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
- DRM_MEM_DRIVER);
+ panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
if (!panel_fixed_mode)
return;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 028f5b66e3d8..73e7b9cecac8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -29,6 +29,7 @@
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
+#include "intel_dp.h"
#include "drm_crtc_helper.h"
@@ -127,19 +128,6 @@ struct intel_limit {
#define I9XX_P2_LVDS_FAST 7
#define I9XX_P2_LVDS_SLOW_LIMIT 112000
-#define INTEL_LIMIT_I8XX_DVO_DAC 0
-#define INTEL_LIMIT_I8XX_LVDS 1
-#define INTEL_LIMIT_I9XX_SDVO_DAC 2
-#define INTEL_LIMIT_I9XX_LVDS 3
-#define INTEL_LIMIT_G4X_SDVO 4
-#define INTEL_LIMIT_G4X_HDMI_DAC 5
-#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6
-#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
#define G4X_DOT_SDVO_MAX 270000
@@ -218,6 +206,25 @@ struct intel_limit {
#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
+/*The parameter is for DISPLAY PORT on G4x platform*/
+#define G4X_DOT_DISPLAY_PORT_MIN 161670
+#define G4X_DOT_DISPLAY_PORT_MAX 227000
+#define G4X_N_DISPLAY_PORT_MIN 1
+#define G4X_N_DISPLAY_PORT_MAX 2
+#define G4X_M_DISPLAY_PORT_MIN 97
+#define G4X_M_DISPLAY_PORT_MAX 108
+#define G4X_M1_DISPLAY_PORT_MIN 0x10
+#define G4X_M1_DISPLAY_PORT_MAX 0x12
+#define G4X_M2_DISPLAY_PORT_MIN 0x05
+#define G4X_M2_DISPLAY_PORT_MAX 0x06
+#define G4X_P_DISPLAY_PORT_MIN 10
+#define G4X_P_DISPLAY_PORT_MAX 20
+#define G4X_P1_DISPLAY_PORT_MIN 1
+#define G4X_P1_DISPLAY_PORT_MAX 2
+#define G4X_P2_DISPLAY_PORT_SLOW 10
+#define G4X_P2_DISPLAY_PORT_FAST 10
+#define G4X_P2_DISPLAY_PORT_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).
@@ -256,8 +263,11 @@ 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 */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
+ int target, int refclk, intel_clock_t *best_clock);
+
+static const intel_limit_t intel_limits_i8xx_dvo = {
.dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
.vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
.n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
@@ -269,8 +279,9 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
.find_pll = intel_find_best_PLL,
- },
- { /* INTEL_LIMIT_I8XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i8xx_lvds = {
.dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
.vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
.n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
@@ -282,8 +293,9 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
.find_pll = intel_find_best_PLL,
- },
- { /* INTEL_LIMIT_I9XX_SDVO_DAC */
+};
+
+static const intel_limit_t intel_limits_i9xx_sdvo = {
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
.vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
.n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
@@ -295,8 +307,9 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
.find_pll = intel_find_best_PLL,
- },
- { /* INTEL_LIMIT_I9XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i9xx_lvds = {
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
.vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
.n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
@@ -311,9 +324,10 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
.find_pll = intel_find_best_PLL,
- },
+};
+
/* below parameter and function is for G4X Chipset Family*/
- { /* INTEL_LIMIT_G4X_SDVO */
+static const intel_limit_t intel_limits_g4x_sdvo = {
.dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX },
.vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
.n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX },
@@ -327,8 +341,9 @@ static const intel_limit_t intel_limits[] = {
.p2_fast = G4X_P2_SDVO_FAST
},
.find_pll = intel_g4x_find_best_PLL,
- },
- { /* INTEL_LIMIT_G4X_HDMI_DAC */
+};
+
+static const intel_limit_t intel_limits_g4x_hdmi = {
.dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX },
.vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
.n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX },
@@ -342,8 +357,9 @@ static const intel_limit_t intel_limits[] = {
.p2_fast = G4X_P2_HDMI_DAC_FAST
},
.find_pll = intel_g4x_find_best_PLL,
- },
- { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
.dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
.max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
.vco = { .min = G4X_VCO_MIN,
@@ -365,8 +381,9 @@ static const intel_limit_t intel_limits[] = {
.p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
},
.find_pll = intel_g4x_find_best_PLL,
- },
- { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
.dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
.max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
.vco = { .min = G4X_VCO_MIN,
@@ -388,8 +405,32 @@ static const intel_limit_t intel_limits[] = {
.p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
},
.find_pll = intel_g4x_find_best_PLL,
- },
- { /* INTEL_LIMIT_IGD_SDVO */
+};
+
+static const intel_limit_t intel_limits_g4x_display_port = {
+ .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
+ .max = G4X_DOT_DISPLAY_PORT_MAX },
+ .vco = { .min = G4X_VCO_MIN,
+ .max = G4X_VCO_MAX},
+ .n = { .min = G4X_N_DISPLAY_PORT_MIN,
+ .max = G4X_N_DISPLAY_PORT_MAX },
+ .m = { .min = G4X_M_DISPLAY_PORT_MIN,
+ .max = G4X_M_DISPLAY_PORT_MAX },
+ .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN,
+ .max = G4X_M1_DISPLAY_PORT_MAX },
+ .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN,
+ .max = G4X_M2_DISPLAY_PORT_MAX },
+ .p = { .min = G4X_P_DISPLAY_PORT_MIN,
+ .max = G4X_P_DISPLAY_PORT_MAX },
+ .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN,
+ .max = G4X_P1_DISPLAY_PORT_MAX},
+ .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
+ .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
+ .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
+ .find_pll = intel_find_pll_g4x_dp,
+};
+
+static const intel_limit_t intel_limits_igd_sdvo = {
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
.vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
.n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
@@ -401,8 +442,9 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
.find_pll = intel_find_best_PLL,
- },
- { /* INTEL_LIMIT_IGD_LVDS */
+};
+
+static const intel_limit_t intel_limits_igd_lvds = {
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
.vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
.n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
@@ -415,8 +457,9 @@ static const intel_limit_t intel_limits[] = {
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
.find_pll = intel_find_best_PLL,
- },
- { /* INTEL_LIMIT_IGDNG_SDVO_DAC */
+};
+
+static const intel_limit_t intel_limits_igdng_sdvo = {
.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 },
@@ -429,8 +472,9 @@ static const intel_limit_t intel_limits[] = {
.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 */
+};
+
+static const intel_limit_t intel_limits_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 },
@@ -443,16 +487,15 @@ static const intel_limit_t intel_limits[] = {
.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];
+ limit = &intel_limits_igdng_lvds;
else
- limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC];
+ limit = &intel_limits_igdng_sdvo;
return limit;
}
@@ -467,19 +510,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
LVDS_CLKB_POWER_UP)
/* LVDS with dual channel */
- limit = &intel_limits
- [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS];
+ limit = &intel_limits_g4x_dual_channel_lvds;
else
/* LVDS with dual channel */
- limit = &intel_limits
- [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS];
+ limit = &intel_limits_g4x_single_channel_lvds;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
- limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
+ limit = &intel_limits_g4x_hdmi;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
- limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
+ limit = &intel_limits_g4x_sdvo;
+ } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+ limit = &intel_limits_g4x_display_port;
} else /* The option is for other outputs */
- limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+ limit = &intel_limits_i9xx_sdvo;
return limit;
}
@@ -495,19 +538,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
limit = intel_g4x_limit(crtc);
} else if (IS_I9XX(dev) && !IS_IGD(dev)) {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
- limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+ limit = &intel_limits_i9xx_lvds;
else
- limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+ limit = &intel_limits_i9xx_sdvo;
} else if (IS_IGD(dev)) {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
- limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
+ limit = &intel_limits_igd_lvds;
else
- limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
+ limit = &intel_limits_igd_sdvo;
} else {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
- limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+ limit = &intel_limits_i8xx_lvds;
else
- limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+ limit = &intel_limits_i8xx_dvo;
}
return limit;
}
@@ -764,6 +807,35 @@ out:
return found;
}
+/* DisplayPort has only two frequencies, 162MHz and 270MHz */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+ int target, int refclk, intel_clock_t *best_clock)
+{
+ intel_clock_t clock;
+ if (target < 200000) {
+ clock.dot = 161670;
+ clock.p = 20;
+ clock.p1 = 2;
+ clock.p2 = 10;
+ clock.n = 0x01;
+ clock.m = 97;
+ clock.m1 = 0x10;
+ clock.m2 = 0x05;
+ } else {
+ clock.dot = 270000;
+ clock.p = 10;
+ clock.p1 = 1;
+ clock.p2 = 10;
+ clock.n = 0x02;
+ clock.m = 108;
+ clock.m1 = 0x12;
+ clock.m2 = 0x06;
+ }
+ memcpy(best_clock, &clock, sizeof(intel_clock_t));
+ return true;
+}
+
void
intel_wait_for_vblank(struct drm_device *dev)
{
@@ -828,19 +900,31 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
}
mutex_lock(&dev->struct_mutex);
- ret = i915_gem_object_pin(intel_fb->obj, alignment);
+ ret = i915_gem_object_pin(obj, alignment);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
- ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
+ ret = i915_gem_object_set_to_gtt_domain(obj, 1);
if (ret != 0) {
- i915_gem_object_unpin(intel_fb->obj);
+ i915_gem_object_unpin(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
+ /* Pre-i965 needs to install a fence for tiled scan-out */
+ if (!IS_I965G(dev) &&
+ obj_priv->fence_reg == I915_FENCE_REG_NONE &&
+ obj_priv->tiling_mode != I915_TILING_NONE) {
+ ret = i915_gem_object_get_fence_reg(obj);
+ if (ret != 0) {
+ i915_gem_object_unpin(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+ }
+
dspcntr = I915_READ(dspcntr_reg);
/* Mask out pixel format bits in case we change it */
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
@@ -860,7 +944,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
break;
default:
DRM_ERROR("Unknown color depth\n");
- i915_gem_object_unpin(intel_fb->obj);
+ i915_gem_object_unpin(obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -1529,7 +1613,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_clock_t clock;
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
bool ok, is_sdvo = false, is_dvo = false;
- bool is_crt = false, is_lvds = false, is_tv = false;
+ bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
const intel_limit_t *limit;
@@ -1573,6 +1657,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
case INTEL_OUTPUT_ANALOG:
is_crt = true;
break;
+ case INTEL_OUTPUT_DISPLAYPORT:
+ is_dp = true;
+ break;
}
num_outputs++;
@@ -1588,6 +1675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} else {
refclk = 48000;
}
+
/*
* Returns a set of divisors for the desired target clock with the given
@@ -1650,6 +1738,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
else if (IS_IGDNG(dev))
dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
}
+ if (is_dp)
+ dpll |= DPLL_DVO_HIGH_SPEED;
/* compute bitmask from p1 value */
if (IS_IGD(dev))
@@ -1797,6 +1887,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(lvds_reg, lvds);
I915_READ(lvds_reg);
}
+ if (is_dp)
+ intel_dp_set_m_n(crtc, mode, adjusted_mode);
I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll);
@@ -2463,6 +2555,8 @@ static void intel_setup_outputs(struct drm_device *dev)
found = intel_sdvo_init(dev, SDVOB);
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
intel_hdmi_init(dev, SDVOB);
+ if (!found && SUPPORTS_INTEGRATED_DP(dev))
+ intel_dp_init(dev, DP_B);
}
/* Before G4X SDVOC doesn't have its own detect register */
@@ -2475,7 +2569,11 @@ static void intel_setup_outputs(struct drm_device *dev)
found = intel_sdvo_init(dev, SDVOC);
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
intel_hdmi_init(dev, SDVOC);
+ if (!found && SUPPORTS_INTEGRATED_DP(dev))
+ intel_dp_init(dev, DP_C);
}
+ if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+ intel_dp_init(dev, DP_D);
} else
intel_dvo_init(dev);
@@ -2518,6 +2616,11 @@ static void intel_setup_outputs(struct drm_device *dev)
(1 << 1));
clone_mask = (1 << INTEL_OUTPUT_TVOUT);
break;
+ case INTEL_OUTPUT_DISPLAYPORT:
+ crtc_mask = ((1 << 0) |
+ (1 << 1));
+ clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
+ break;
}
encoder->possible_crtcs = crtc_mask;
encoder->possible_clones = intel_connector_clones(dev, clone_mask);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
new file mode 100644
index 000000000000..8f8d37d5663a
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -0,0 +1,1153 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "intel_dp.h"
+
+#define DP_LINK_STATUS_SIZE 6
+#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
+
+#define DP_LINK_CONFIGURATION_SIZE 9
+
+struct intel_dp_priv {
+ uint32_t output_reg;
+ uint32_t DP;
+ uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
+ uint32_t save_DP;
+ uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE];
+ bool has_audio;
+ int dpms_mode;
+ uint8_t link_bw;
+ uint8_t lane_count;
+ uint8_t dpcd[4];
+ struct intel_output *intel_output;
+ struct i2c_adapter adapter;
+ struct i2c_algo_dp_aux_data algo;
+};
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+ uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
+
+static int
+intel_dp_max_lane_count(struct intel_output *intel_output)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ int max_lane_count = 4;
+
+ if (dp_priv->dpcd[0] >= 0x11) {
+ max_lane_count = dp_priv->dpcd[2] & 0x1f;
+ switch (max_lane_count) {
+ case 1: case 2: case 4:
+ break;
+ default:
+ max_lane_count = 4;
+ }
+ }
+ return max_lane_count;
+}
+
+static int
+intel_dp_max_link_bw(struct intel_output *intel_output)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ int max_link_bw = dp_priv->dpcd[1];
+
+ switch (max_link_bw) {
+ case DP_LINK_BW_1_62:
+ case DP_LINK_BW_2_7:
+ break;
+ default:
+ max_link_bw = DP_LINK_BW_1_62;
+ break;
+ }
+ return max_link_bw;
+}
+
+static int
+intel_dp_link_clock(uint8_t link_bw)
+{
+ if (link_bw == DP_LINK_BW_2_7)
+ return 270000;
+ else
+ return 162000;
+}
+
+/* I think this is a fiction */
+static int
+intel_dp_link_required(int pixel_clock)
+{
+ return pixel_clock * 3;
+}
+
+static int
+intel_dp_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
+ int max_lanes = intel_dp_max_lane_count(intel_output);
+
+ if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes)
+ return MODE_CLOCK_HIGH;
+
+ if (mode->clock < 10000)
+ return MODE_CLOCK_LOW;
+
+ return MODE_OK;
+}
+
+static uint32_t
+pack_aux(uint8_t *src, int src_bytes)
+{
+ int i;
+ uint32_t v = 0;
+
+ if (src_bytes > 4)
+ src_bytes = 4;
+ for (i = 0; i < src_bytes; i++)
+ v |= ((uint32_t) src[i]) << ((3-i) * 8);
+ return v;
+}
+
+static void
+unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
+{
+ int i;
+ if (dst_bytes > 4)
+ dst_bytes = 4;
+ for (i = 0; i < dst_bytes; i++)
+ dst[i] = src >> ((3-i) * 8);
+}
+
+/* hrawclock is 1/4 the FSB frequency */
+static int
+intel_hrawclk(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t clkcfg;
+
+ clkcfg = I915_READ(CLKCFG);
+ switch (clkcfg & CLKCFG_FSB_MASK) {
+ case CLKCFG_FSB_400:
+ return 100;
+ case CLKCFG_FSB_533:
+ return 133;
+ case CLKCFG_FSB_667:
+ return 166;
+ case CLKCFG_FSB_800:
+ return 200;
+ case CLKCFG_FSB_1067:
+ return 266;
+ case CLKCFG_FSB_1333:
+ return 333;
+ /* these two are just a guess; one of them might be right */
+ case CLKCFG_FSB_1600:
+ case CLKCFG_FSB_1600_ALT:
+ return 400;
+ default:
+ return 133;
+ }
+}
+
+static int
+intel_dp_aux_ch(struct intel_output *intel_output,
+ uint8_t *send, int send_bytes,
+ uint8_t *recv, int recv_size)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ uint32_t output_reg = dp_priv->output_reg;
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t ch_ctl = output_reg + 0x10;
+ uint32_t ch_data = ch_ctl + 4;
+ int i;
+ int recv_bytes;
+ uint32_t ctl;
+ uint32_t status;
+ uint32_t aux_clock_divider;
+ int try;
+
+ /* The clock divider is based off the hrawclk,
+ * and would like to run at 2MHz. So, take the
+ * hrawclk value and divide by 2 and use that
+ */
+ aux_clock_divider = intel_hrawclk(dev) / 2;
+ /* Must try at least 3 times according to DP spec */
+ for (try = 0; try < 5; try++) {
+ /* Load the send data into the aux channel data registers */
+ for (i = 0; i < send_bytes; i += 4) {
+ uint32_t d = pack_aux(send + i, send_bytes - i);;
+
+ I915_WRITE(ch_data + i, d);
+ }
+
+ ctl = (DP_AUX_CH_CTL_SEND_BUSY |
+ DP_AUX_CH_CTL_TIME_OUT_400us |
+ (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+ (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+ (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+ DP_AUX_CH_CTL_DONE |
+ DP_AUX_CH_CTL_TIME_OUT_ERROR |
+ DP_AUX_CH_CTL_RECEIVE_ERROR);
+
+ /* Send the command and wait for it to complete */
+ I915_WRITE(ch_ctl, ctl);
+ (void) I915_READ(ch_ctl);
+ for (;;) {
+ udelay(100);
+ status = I915_READ(ch_ctl);
+ if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+ break;
+ }
+
+ /* Clear done status and any errors */
+ I915_WRITE(ch_ctl, (ctl |
+ DP_AUX_CH_CTL_DONE |
+ DP_AUX_CH_CTL_TIME_OUT_ERROR |
+ DP_AUX_CH_CTL_RECEIVE_ERROR));
+ (void) I915_READ(ch_ctl);
+ if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0)
+ break;
+ }
+
+ if ((status & DP_AUX_CH_CTL_DONE) == 0) {
+ printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status);
+ return -EBUSY;
+ }
+
+ /* Check for timeout or receive error.
+ * Timeouts occur when the sink is not connected
+ */
+ if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+ printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status);
+ return -EIO;
+ }
+ if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+ printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status);
+ return -ETIMEDOUT;
+ }
+
+ /* Unload any bytes sent back from the other side */
+ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+ DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+ if (recv_bytes > recv_size)
+ recv_bytes = recv_size;
+
+ for (i = 0; i < recv_bytes; i += 4) {
+ uint32_t d = I915_READ(ch_data + i);
+
+ unpack_aux(d, recv + i, recv_bytes - i);
+ }
+
+ return recv_bytes;
+}
+
+/* Write data to the aux channel in native mode */
+static int
+intel_dp_aux_native_write(struct intel_output *intel_output,
+ uint16_t address, uint8_t *send, int send_bytes)
+{
+ int ret;
+ uint8_t msg[20];
+ int msg_bytes;
+ uint8_t ack;
+
+ if (send_bytes > 16)
+ return -1;
+ msg[0] = AUX_NATIVE_WRITE << 4;
+ msg[1] = address >> 8;
+ msg[2] = address;
+ msg[3] = send_bytes - 1;
+ memcpy(&msg[4], send, send_bytes);
+ msg_bytes = send_bytes + 4;
+ for (;;) {
+ ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1);
+ if (ret < 0)
+ return ret;
+ if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+ break;
+ else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ udelay(100);
+ else
+ return -EIO;
+ }
+ return send_bytes;
+}
+
+/* Write a single byte to the aux channel in native mode */
+static int
+intel_dp_aux_native_write_1(struct intel_output *intel_output,
+ uint16_t address, uint8_t byte)
+{
+ return intel_dp_aux_native_write(intel_output, address, &byte, 1);
+}
+
+/* read bytes from a native aux channel */
+static int
+intel_dp_aux_native_read(struct intel_output *intel_output,
+ uint16_t address, uint8_t *recv, int recv_bytes)
+{
+ uint8_t msg[4];
+ int msg_bytes;
+ uint8_t reply[20];
+ int reply_bytes;
+ uint8_t ack;
+ int ret;
+
+ msg[0] = AUX_NATIVE_READ << 4;
+ msg[1] = address >> 8;
+ msg[2] = address & 0xff;
+ msg[3] = recv_bytes - 1;
+
+ msg_bytes = 4;
+ reply_bytes = recv_bytes + 1;
+
+ for (;;) {
+ ret = intel_dp_aux_ch(intel_output, msg, msg_bytes,
+ reply, reply_bytes);
+ if (ret == 0)
+ return -EPROTO;
+ if (ret < 0)
+ return ret;
+ ack = reply[0];
+ if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+ memcpy(recv, reply + 1, ret - 1);
+ return ret - 1;
+ }
+ else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ udelay(100);
+ else
+ return -EIO;
+ }
+}
+
+static int
+intel_dp_i2c_aux_ch(struct i2c_adapter *adapter,
+ uint8_t *send, int send_bytes,
+ uint8_t *recv, int recv_bytes)
+{
+ struct intel_dp_priv *dp_priv = container_of(adapter,
+ struct intel_dp_priv,
+ adapter);
+ struct intel_output *intel_output = dp_priv->intel_output;
+
+ return intel_dp_aux_ch(intel_output,
+ send, send_bytes, recv, recv_bytes);
+}
+
+static int
+intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ DRM_ERROR("i2c_init %s\n", name);
+ dp_priv->algo.running = false;
+ dp_priv->algo.address = 0;
+ dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
+
+ memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter));
+ dp_priv->adapter.owner = THIS_MODULE;
+ dp_priv->adapter.class = I2C_CLASS_DDC;
+ strncpy (dp_priv->adapter.name, name, sizeof dp_priv->adapter.name - 1);
+ dp_priv->adapter.name[sizeof dp_priv->adapter.name - 1] = '\0';
+ dp_priv->adapter.algo_data = &dp_priv->algo;
+ dp_priv->adapter.dev.parent = &intel_output->base.kdev;
+
+ return i2c_dp_aux_add_bus(&dp_priv->adapter);
+}
+
+static bool
+intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ int lane_count, clock;
+ int max_lane_count = intel_dp_max_lane_count(intel_output);
+ int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0;
+ static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+
+ for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+ for (clock = 0; clock <= max_clock; clock++) {
+ int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+
+ if (intel_dp_link_required(mode->clock) <= link_avail) {
+ dp_priv->link_bw = bws[clock];
+ dp_priv->lane_count = lane_count;
+ adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+ printk(KERN_ERR "link bw %02x lane count %d clock %d\n",
+ dp_priv->link_bw, dp_priv->lane_count,
+ adjusted_mode->clock);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+struct intel_dp_m_n {
+ uint32_t tu;
+ uint32_t gmch_m;
+ uint32_t gmch_n;
+ uint32_t link_m;
+ uint32_t link_n;
+};
+
+static void
+intel_reduce_ratio(uint32_t *num, uint32_t *den)
+{
+ while (*num > 0xffffff || *den > 0xffffff) {
+ *num >>= 1;
+ *den >>= 1;
+ }
+}
+
+static void
+intel_dp_compute_m_n(int bytes_per_pixel,
+ int nlanes,
+ int pixel_clock,
+ int link_clock,
+ struct intel_dp_m_n *m_n)
+{
+ m_n->tu = 64;
+ m_n->gmch_m = pixel_clock * bytes_per_pixel;
+ m_n->gmch_n = link_clock * nlanes;
+ intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+ m_n->link_m = pixel_clock;
+ m_n->link_n = link_clock;
+ intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector *connector;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int lane_count = 4;
+ struct intel_dp_m_n m_n;
+
+ /*
+ * Find the lane count in the intel_output private
+ */
+ list_for_each_entry(connector, &mode_config->connector_list, head) {
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ if (!connector->encoder || connector->encoder->crtc != crtc)
+ continue;
+
+ if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) {
+ lane_count = dp_priv->lane_count;
+ break;
+ }
+ }
+
+ /*
+ * Compute the GMCH and Link ratios. The '3' here is
+ * the number of bytes_per_pixel post-LUT, which we always
+ * set up for 8-bits of R/G/B, or 3 bytes total.
+ */
+ intel_dp_compute_m_n(3, lane_count,
+ mode->clock, adjusted_mode->clock, &m_n);
+
+ if (intel_crtc->pipe == 0) {
+ I915_WRITE(PIPEA_GMCH_DATA_M,
+ ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+ m_n.gmch_m);
+ I915_WRITE(PIPEA_GMCH_DATA_N,
+ m_n.gmch_n);
+ I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m);
+ I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n);
+ } else {
+ I915_WRITE(PIPEB_GMCH_DATA_M,
+ ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+ m_n.gmch_m);
+ I915_WRITE(PIPEB_GMCH_DATA_N,
+ m_n.gmch_n);
+ I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m);
+ I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n);
+ }
+}
+
+static void
+intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ struct drm_crtc *crtc = intel_output->enc.crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ dp_priv->DP = (DP_LINK_TRAIN_OFF |
+ DP_VOLTAGE_0_4 |
+ DP_PRE_EMPHASIS_0 |
+ DP_SYNC_VS_HIGH |
+ DP_SYNC_HS_HIGH);
+
+ switch (dp_priv->lane_count) {
+ case 1:
+ dp_priv->DP |= DP_PORT_WIDTH_1;
+ break;
+ case 2:
+ dp_priv->DP |= DP_PORT_WIDTH_2;
+ break;
+ case 4:
+ dp_priv->DP |= DP_PORT_WIDTH_4;
+ break;
+ }
+ if (dp_priv->has_audio)
+ dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE;
+
+ memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+ dp_priv->link_configuration[0] = dp_priv->link_bw;
+ dp_priv->link_configuration[1] = dp_priv->lane_count;
+
+ /*
+ * Check for DPCD version > 1.1,
+ * enable enahanced frame stuff in that case
+ */
+ if (dp_priv->dpcd[0] >= 0x11) {
+ dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ dp_priv->DP |= DP_ENHANCED_FRAMING;
+ }
+
+ if (intel_crtc->pipe == 1)
+ dp_priv->DP |= DP_PIPEB_SELECT;
+}
+
+
+static void
+intel_dp_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t dp_reg = I915_READ(dp_priv->output_reg);
+
+ if (mode != DRM_MODE_DPMS_ON) {
+ if (dp_reg & DP_PORT_EN)
+ intel_dp_link_down(intel_output, dp_priv->DP);
+ } else {
+ if (!(dp_reg & DP_PORT_EN))
+ intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+ }
+ dp_priv->dpms_mode = mode;
+}
+
+/*
+ * Fetch AUX CH registers 0x202 - 0x207 which contain
+ * link status information
+ */
+static bool
+intel_dp_get_link_status(struct intel_output *intel_output,
+ uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+ int ret;
+
+ ret = intel_dp_aux_native_read(intel_output,
+ DP_LANE0_1_STATUS,
+ link_status, DP_LINK_STATUS_SIZE);
+ if (ret != DP_LINK_STATUS_SIZE)
+ return false;
+ return true;
+}
+
+static uint8_t
+intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+ int r)
+{
+ return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static void
+intel_dp_save(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ dp_priv->save_DP = I915_READ(dp_priv->output_reg);
+ intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET,
+ dp_priv->save_link_configuration,
+ sizeof (dp_priv->save_link_configuration));
+}
+
+static uint8_t
+intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+ int lane)
+{
+ int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+ int s = ((lane & 1) ?
+ DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+ DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+ uint8_t l = intel_dp_link_status(link_status, i);
+
+ return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint8_t
+intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+ int lane)
+{
+ int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+ int s = ((lane & 1) ?
+ DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+ DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+ uint8_t l = intel_dp_link_status(link_status, i);
+
+ return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+
+#if 0
+static char *voltage_names[] = {
+ "0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char *pre_emph_names[] = {
+ "0dB", "3.5dB", "6dB", "9.5dB"
+};
+static char *link_train_names[] = {
+ "pattern 1", "pattern 2", "idle", "off"
+};
+#endif
+
+/*
+ * These are source-specific values; current Intel hardware supports
+ * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
+ */
+#define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800
+
+static uint8_t
+intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+{
+ switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+ case DP_TRAIN_VOLTAGE_SWING_400:
+ return DP_TRAIN_PRE_EMPHASIS_6;
+ case DP_TRAIN_VOLTAGE_SWING_600:
+ return DP_TRAIN_PRE_EMPHASIS_6;
+ case DP_TRAIN_VOLTAGE_SWING_800:
+ return DP_TRAIN_PRE_EMPHASIS_3_5;
+ case DP_TRAIN_VOLTAGE_SWING_1200:
+ default:
+ return DP_TRAIN_PRE_EMPHASIS_0;
+ }
+}
+
+static void
+intel_get_adjust_train(struct intel_output *intel_output,
+ uint8_t link_status[DP_LINK_STATUS_SIZE],
+ int lane_count,
+ uint8_t train_set[4])
+{
+ uint8_t v = 0;
+ uint8_t p = 0;
+ int lane;
+
+ for (lane = 0; lane < lane_count; lane++) {
+ uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
+ uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
+
+ if (this_v > v)
+ v = this_v;
+ if (this_p > p)
+ p = this_p;
+ }
+
+ if (v >= I830_DP_VOLTAGE_MAX)
+ v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+ if (p >= intel_dp_pre_emphasis_max(v))
+ p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+ for (lane = 0; lane < 4; lane++)
+ train_set[lane] = v | p;
+}
+
+static uint32_t
+intel_dp_signal_levels(uint8_t train_set, int lane_count)
+{
+ uint32_t signal_levels = 0;
+
+ switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
+ case DP_TRAIN_VOLTAGE_SWING_400:
+ default:
+ signal_levels |= DP_VOLTAGE_0_4;
+ break;
+ case DP_TRAIN_VOLTAGE_SWING_600:
+ signal_levels |= DP_VOLTAGE_0_6;
+ break;
+ case DP_TRAIN_VOLTAGE_SWING_800:
+ signal_levels |= DP_VOLTAGE_0_8;
+ break;
+ case DP_TRAIN_VOLTAGE_SWING_1200:
+ signal_levels |= DP_VOLTAGE_1_2;
+ break;
+ }
+ switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
+ case DP_TRAIN_PRE_EMPHASIS_0:
+ default:
+ signal_levels |= DP_PRE_EMPHASIS_0;
+ break;
+ case DP_TRAIN_PRE_EMPHASIS_3_5:
+ signal_levels |= DP_PRE_EMPHASIS_3_5;
+ break;
+ case DP_TRAIN_PRE_EMPHASIS_6:
+ signal_levels |= DP_PRE_EMPHASIS_6;
+ break;
+ case DP_TRAIN_PRE_EMPHASIS_9_5:
+ signal_levels |= DP_PRE_EMPHASIS_9_5;
+ break;
+ }
+ return signal_levels;
+}
+
+static uint8_t
+intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+ int lane)
+{
+ int i = DP_LANE0_1_STATUS + (lane >> 1);
+ int s = (lane & 1) * 4;
+ uint8_t l = intel_dp_link_status(link_status, i);
+
+ return (l >> s) & 0xf;
+}
+
+/* Check for clock recovery is done on all channels */
+static bool
+intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+ int lane;
+ uint8_t lane_status;
+
+ for (lane = 0; lane < lane_count; lane++) {
+ lane_status = intel_get_lane_status(link_status, lane);
+ if ((lane_status & DP_LANE_CR_DONE) == 0)
+ return false;
+ }
+ return true;
+}
+
+/* Check to see if channel eq is done on all channels */
+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
+ DP_LANE_CHANNEL_EQ_DONE|\
+ DP_LANE_SYMBOL_LOCKED)
+static bool
+intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+ uint8_t lane_align;
+ uint8_t lane_status;
+ int lane;
+
+ lane_align = intel_dp_link_status(link_status,
+ DP_LANE_ALIGN_STATUS_UPDATED);
+ if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+ return false;
+ for (lane = 0; lane < lane_count; lane++) {
+ lane_status = intel_get_lane_status(link_status, lane);
+ if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
+ return false;
+ }
+ return true;
+}
+
+static bool
+intel_dp_set_link_train(struct intel_output *intel_output,
+ uint32_t dp_reg_value,
+ uint8_t dp_train_pat,
+ uint8_t train_set[4],
+ bool first)
+{
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ int ret;
+
+ I915_WRITE(dp_priv->output_reg, dp_reg_value);
+ POSTING_READ(dp_priv->output_reg);
+ if (first)
+ intel_wait_for_vblank(dev);
+
+ intel_dp_aux_native_write_1(intel_output,
+ DP_TRAINING_PATTERN_SET,
+ dp_train_pat);
+
+ ret = intel_dp_aux_native_write(intel_output,
+ DP_TRAINING_LANE0_SET, train_set, 4);
+ if (ret != 4)
+ return false;
+
+ return true;
+}
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+ uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
+{
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ uint8_t train_set[4];
+ uint8_t link_status[DP_LINK_STATUS_SIZE];
+ int i;
+ uint8_t voltage;
+ bool clock_recovery = false;
+ bool channel_eq = false;
+ bool first = true;
+ int tries;
+
+ /* Write the link configuration data */
+ intel_dp_aux_native_write(intel_output, 0x100,
+ link_configuration, DP_LINK_CONFIGURATION_SIZE);
+
+ DP |= DP_PORT_EN;
+ DP &= ~DP_LINK_TRAIN_MASK;
+ memset(train_set, 0, 4);
+ voltage = 0xff;
+ tries = 0;
+ clock_recovery = false;
+ for (;;) {
+ /* Use train_set[0] to set the voltage and pre emphasis values */
+ uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+ DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+ if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1,
+ DP_TRAINING_PATTERN_1, train_set, first))
+ break;
+ first = false;
+ /* Set training pattern 1 */
+
+ udelay(100);
+ if (!intel_dp_get_link_status(intel_output, link_status))
+ break;
+
+ if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
+ clock_recovery = true;
+ break;
+ }
+
+ /* Check to see if we've tried the max voltage */
+ for (i = 0; i < dp_priv->lane_count; i++)
+ if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+ break;
+ if (i == dp_priv->lane_count)
+ break;
+
+ /* Check to see if we've tried the same voltage 5 times */
+ if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+ ++tries;
+ if (tries == 5)
+ break;
+ } else
+ tries = 0;
+ voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+ /* Compute new train_set as requested by target */
+ intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+ }
+
+ /* channel equalization */
+ tries = 0;
+ channel_eq = false;
+ for (;;) {
+ /* Use train_set[0] to set the voltage and pre emphasis values */
+ uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+ DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+ /* channel eq pattern */
+ if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2,
+ DP_TRAINING_PATTERN_2, train_set,
+ false))
+ break;
+
+ udelay(400);
+ if (!intel_dp_get_link_status(intel_output, link_status))
+ break;
+
+ if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
+ channel_eq = true;
+ break;
+ }
+
+ /* Try 5 times */
+ if (tries > 5)
+ break;
+
+ /* Compute new train_set as requested by target */
+ intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+ ++tries;
+ }
+
+ I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
+ POSTING_READ(dp_priv->output_reg);
+ intel_dp_aux_native_write_1(intel_output,
+ DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
+{
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
+ POSTING_READ(dp_priv->output_reg);
+}
+
+static void
+intel_dp_restore(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ if (dp_priv->save_DP & DP_PORT_EN)
+ intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration);
+ else
+ intel_dp_link_down(intel_output, dp_priv->save_DP);
+}
+
+/*
+ * According to DP spec
+ * 5.1.2:
+ * 1. Read DPCD
+ * 2. Configure link according to Receiver Capabilities
+ * 3. Use Link Training from 2.5.3.3 and 3.5.1.3
+ * 4. Check link status on receipt of hot-plug interrupt
+ */
+
+static void
+intel_dp_check_link_status(struct intel_output *intel_output)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+ if (!intel_output->enc.crtc)
+ return;
+
+ if (!intel_dp_get_link_status(intel_output, link_status)) {
+ intel_dp_link_down(intel_output, dp_priv->DP);
+ return;
+ }
+
+ if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
+ intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+ *
+ * \return true if DP port is connected.
+ * \return false if DP port is disconnected.
+ */
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct drm_device *dev = intel_output->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+ uint32_t temp, bit;
+ enum drm_connector_status status;
+
+ dp_priv->has_audio = false;
+
+ temp = I915_READ(PORT_HOTPLUG_EN);
+
+ I915_WRITE(PORT_HOTPLUG_EN,
+ temp |
+ DPB_HOTPLUG_INT_EN |
+ DPC_HOTPLUG_INT_EN |
+ DPD_HOTPLUG_INT_EN);
+
+ POSTING_READ(PORT_HOTPLUG_EN);
+
+ switch (dp_priv->output_reg) {
+ case DP_B:
+ bit = DPB_HOTPLUG_INT_STATUS;
+ break;
+ case DP_C:
+ bit = DPC_HOTPLUG_INT_STATUS;
+ break;
+ case DP_D:
+ bit = DPD_HOTPLUG_INT_STATUS;
+ break;
+ default:
+ return connector_status_unknown;
+ }
+
+ temp = I915_READ(PORT_HOTPLUG_STAT);
+
+ if ((temp & bit) == 0)
+ return connector_status_disconnected;
+
+ status = connector_status_disconnected;
+ if (intel_dp_aux_native_read(intel_output,
+ 0x000, dp_priv->dpcd,
+ sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+ {
+ if (dp_priv->dpcd[0] != 0)
+ status = connector_status_connected;
+ }
+ return status;
+}
+
+static int intel_dp_get_modes(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+
+ /* We should parse the EDID data and find out if it has an audio sink
+ */
+
+ return intel_ddc_get_modes(intel_output);
+}
+
+static void
+intel_dp_destroy (struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+
+ if (intel_output->i2c_bus)
+ intel_i2c_destroy(intel_output->i2c_bus);
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(intel_output);
+}
+
+static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
+ .dpms = intel_dp_dpms,
+ .mode_fixup = intel_dp_mode_fixup,
+ .prepare = intel_encoder_prepare,
+ .mode_set = intel_dp_mode_set,
+ .commit = intel_encoder_commit,
+};
+
+static const struct drm_connector_funcs intel_dp_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .save = intel_dp_save,
+ .restore = intel_dp_restore,
+ .detect = intel_dp_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = intel_dp_destroy,
+};
+
+static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
+ .get_modes = intel_dp_get_modes,
+ .mode_valid = intel_dp_mode_valid,
+ .best_encoder = intel_best_encoder,
+};
+
+static void intel_dp_enc_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs intel_dp_enc_funcs = {
+ .destroy = intel_dp_enc_destroy,
+};
+
+void
+intel_dp_hot_plug(struct intel_output *intel_output)
+{
+ struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+ if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
+ intel_dp_check_link_status(intel_output);
+}
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_connector *connector;
+ struct intel_output *intel_output;
+ struct intel_dp_priv *dp_priv;
+
+ intel_output = kcalloc(sizeof(struct intel_output) +
+ sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
+ if (!intel_output)
+ return;
+
+ dp_priv = (struct intel_dp_priv *)(intel_output + 1);
+
+ connector = &intel_output->base;
+ drm_connector_init(dev, connector, &intel_dp_connector_funcs,
+ DRM_MODE_CONNECTOR_DisplayPort);
+ drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
+
+ intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
+
+ connector->interlace_allowed = true;
+ connector->doublescan_allowed = 0;
+
+ dp_priv->intel_output = intel_output;
+ dp_priv->output_reg = output_reg;
+ dp_priv->has_audio = false;
+ dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
+ intel_output->dev_priv = dp_priv;
+
+ drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs);
+
+ drm_mode_connector_attach_encoder(&intel_output->base,
+ &intel_output->enc);
+ drm_sysfs_connector_add(connector);
+
+ /* Set up the DDC bus. */
+ intel_dp_i2c_init(intel_output,
+ (output_reg == DP_B) ? "DPDDC-B" :
+ (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D");
+ intel_output->ddc_bus = &dp_priv->adapter;
+ intel_output->hot_plug = intel_dp_hot_plug;
+
+ /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
+ * 0xd. Failure to do so will result in spurious interrupts being
+ * generated on the port when a cable is not attached.
+ */
+ if (IS_G4X(dev) && !IS_GM45(dev)) {
+ u32 temp = I915_READ(PEG_BAND_GAP_DATA);
+ I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
+ }
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
new file mode 100644
index 000000000000..2b38054d3b6d
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dp.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2008 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _INTEL_DP_H_
+#define _INTEL_DP_H_
+
+/* From the VESA DisplayPort spec */
+
+#define AUX_NATIVE_WRITE 0x8
+#define AUX_NATIVE_READ 0x9
+#define AUX_I2C_WRITE 0x0
+#define AUX_I2C_READ 0x1
+#define AUX_I2C_STATUS 0x2
+#define AUX_I2C_MOT 0x4
+
+#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
+#define AUX_NATIVE_REPLY_NACK (0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
+#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
+
+#define AUX_I2C_REPLY_ACK (0x0 << 6)
+#define AUX_I2C_REPLY_NACK (0x1 << 6)
+#define AUX_I2C_REPLY_DEFER (0x2 << 6)
+#define AUX_I2C_REPLY_MASK (0x3 << 6)
+
+/* AUX CH addresses */
+#define DP_LINK_BW_SET 0x100
+# define DP_LINK_BW_1_62 0x06
+# define DP_LINK_BW_2_7 0x0a
+
+#define DP_LANE_COUNT_SET 0x101
+# define DP_LANE_COUNT_MASK 0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET 0x102
+
+# define DP_TRAINING_PATTERN_DISABLE 0
+# define DP_TRAINING_PATTERN_1 1
+# define DP_TRAINING_PATTERN_2 2
+# define DP_TRAINING_PATTERN_MASK 0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
+
+# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
+
+#define DP_TRAINING_LANE0_SET 0x103
+#define DP_TRAINING_LANE1_SET 0x104
+#define DP_TRAINING_LANE2_SET 0x105
+#define DP_TRAINING_LANE3_SET 0x106
+
+# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
+# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
+
+#define DP_DOWNSPREAD_CTRL 0x107
+# define DP_SPREAD_AMP_0_5 (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
+# define DP_SET_ANSI_8B10B (1 << 0)
+
+#define DP_LANE0_1_STATUS 0x202
+#define DP_LANE2_3_STATUS 0x203
+
+# define DP_LANE_CR_DONE (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED (1 << 2)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
+
+#define DP_INTERLANE_ALIGN_DONE (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
+#define DP_LINK_STATUS_UPDATED (1 << 7)
+
+#define DP_SINK_STATUS 0x205
+
+#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1 0x206
+#define DP_ADJUST_REQUEST_LANE2_3 0x207
+
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
+
+struct i2c_algo_dp_aux_data {
+ bool running;
+ u16 address;
+ int (*aux_ch) (struct i2c_adapter *adapter,
+ uint8_t *send, int send_bytes,
+ uint8_t *recv, int recv_bytes);
+};
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
+
+#endif /* _INTEL_DP_H_ */
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c
new file mode 100644
index 000000000000..4e60f14b1a6d
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dp_i2c.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include "intel_dp.h"
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+
+#define MODE_I2C_START 1
+#define MODE_I2C_WRITE 2
+#define MODE_I2C_READ 4
+#define MODE_I2C_STOP 8
+
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+ uint8_t write_byte, uint8_t *read_byte)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ uint16_t address = algo_data->address;
+ uint8_t msg[5];
+ uint8_t reply[2];
+ int msg_bytes;
+ int reply_bytes;
+ int ret;
+
+ /* Set up the command byte */
+ if (mode & MODE_I2C_READ)
+ msg[0] = AUX_I2C_READ << 4;
+ else
+ msg[0] = AUX_I2C_WRITE << 4;
+
+ if (!(mode & MODE_I2C_STOP))
+ msg[0] |= AUX_I2C_MOT << 4;
+
+ msg[1] = address >> 8;
+ msg[2] = address;
+
+ switch (mode) {
+ case MODE_I2C_WRITE:
+ msg[3] = 0;
+ msg[4] = write_byte;
+ msg_bytes = 5;
+ reply_bytes = 1;
+ break;
+ case MODE_I2C_READ:
+ msg[3] = 0;
+ msg_bytes = 4;
+ reply_bytes = 2;
+ break;
+ default:
+ msg_bytes = 3;
+ reply_bytes = 1;
+ break;
+ }
+
+ for (;;) {
+ ret = (*algo_data->aux_ch)(adapter,
+ msg, msg_bytes,
+ reply, reply_bytes);
+ if (ret < 0) {
+ printk(KERN_ERR "aux_ch failed %d\n", ret);
+ return ret;
+ }
+ switch (reply[0] & AUX_I2C_REPLY_MASK) {
+ case AUX_I2C_REPLY_ACK:
+ if (mode == MODE_I2C_READ) {
+ *read_byte = reply[1];
+ }
+ return reply_bytes - 1;
+ case AUX_I2C_REPLY_NACK:
+ printk(KERN_ERR "aux_ch nack\n");
+ return -EREMOTEIO;
+ case AUX_I2C_REPLY_DEFER:
+ printk(KERN_ERR "aux_ch defer\n");
+ udelay(100);
+ break;
+ default:
+ printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]);
+ return -EREMOTEIO;
+ }
+ }
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int mode = MODE_I2C_START;
+ int ret;
+
+ if (reading)
+ mode |= MODE_I2C_READ;
+ else
+ mode |= MODE_I2C_WRITE;
+ algo_data->address = address;
+ algo_data->running = true;
+ ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+ return ret;
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int mode = MODE_I2C_STOP;
+
+ if (reading)
+ mode |= MODE_I2C_READ;
+ else
+ mode |= MODE_I2C_WRITE;
+ if (algo_data->running) {
+ (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+ algo_data->running = false;
+ }
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * the I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int ret;
+
+ if (!algo_data->running)
+ return -EIO;
+
+ ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+ return ret;
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int ret;
+
+ if (!algo_data->running)
+ return -EIO;
+
+ ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+ return ret;
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs,
+ int num)
+{
+ int ret = 0;
+ bool reading = false;
+ int m;
+ int b;
+
+ for (m = 0; m < num; m++) {
+ u16 len = msgs[m].len;
+ u8 *buf = msgs[m].buf;
+ reading = (msgs[m].flags & I2C_M_RD) != 0;
+ ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+ if (ret < 0)
+ break;
+ if (reading) {
+ for (b = 0; b < len; b++) {
+ ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+ if (ret < 0)
+ break;
+ }
+ } else {
+ for (b = 0; b < len; b++) {
+ ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+ if (ret < 0)
+ break;
+ }
+ }
+ if (ret < 0)
+ break;
+ }
+ if (ret >= 0)
+ ret = num;
+ i2c_algo_dp_aux_stop(adapter, reading);
+ printk(KERN_ERR "dp_aux_xfer return %d\n", ret);
+ return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+ .master_xfer = i2c_algo_dp_aux_xfer,
+ .functionality = i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+ (void) i2c_algo_dp_aux_address(adapter, 0, false);
+ (void) i2c_algo_dp_aux_stop(adapter, false);
+
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+ adapter->algo = &i2c_dp_aux_algo;
+ adapter->retries = 3;
+ i2c_dp_aux_reset_bus(adapter);
+ return 0;
+}
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+ int error;
+
+ error = i2c_dp_aux_prepare_bus(adapter);
+ if (error)
+ return error;
+ error = i2c_add_adapter(adapter);
+ return error;
+}
+EXPORT_SYMBOL(i2c_dp_aux_add_bus);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd4b9c5f715e..004541c935a8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -54,6 +54,7 @@
#define INTEL_OUTPUT_LVDS 4
#define INTEL_OUTPUT_TVOUT 5
#define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_DISPLAYPORT 7
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
@@ -65,7 +66,6 @@ struct intel_i2c_chan {
u32 reg; /* GPIO reg */
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo;
- u8 slave_addr;
};
struct intel_framebuffer {
@@ -79,11 +79,12 @@ struct intel_output {
struct drm_encoder enc;
int type;
- struct intel_i2c_chan *i2c_bus; /* for control functions */
- struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
+ struct i2c_adapter *i2c_bus;
+ struct i2c_adapter *ddc_bus;
bool load_detect_temp;
bool needs_tv_clock;
void *dev_priv;
+ void (*hot_plug)(struct intel_output *);
};
struct intel_crtc {
@@ -104,9 +105,9 @@ struct intel_crtc {
#define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
- const char *name);
-void intel_i2c_destroy(struct intel_i2c_chan *chan);
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+ const char *name);
+void intel_i2c_destroy(struct i2c_adapter *adapter);
int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
@@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
extern void intel_dvo_init(struct drm_device *dev);
extern void intel_tv_init(struct drm_device *dev);
extern void intel_lvds_init(struct drm_device *dev);
+extern void intel_dp_init(struct drm_device *dev, int dp_reg);
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_encoder_prepare (struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 1ee3007d6ec0..13bff20930e8 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev)
{
struct intel_output *intel_output;
struct intel_dvo_device *dvo;
- struct intel_i2c_chan *i2cbus = NULL;
+ struct i2c_adapter *i2cbus = NULL;
int ret = 0;
int i;
- int gpio_inited = 0;
int encoder_type = DRM_MODE_ENCODER_NONE;
intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output)
@@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev)
* It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA).
*/
- if (gpio_inited != gpio) {
- if (i2cbus != NULL)
- intel_i2c_destroy(i2cbus);
- if (!(i2cbus = intel_i2c_create(dev, gpio,
- gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
- continue;
- }
- gpio_inited = gpio;
+ if (i2cbus != NULL)
+ intel_i2c_destroy(i2cbus);
+ if (!(i2cbus = intel_i2c_create(dev, gpio,
+ gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
+ continue;
}
if (dvo->dev_ops!= NULL)
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 8e28e5993df5..1af7d68e3807 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -870,7 +870,11 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
*/
void intelfb_restore(void)
{
- drm_crtc_helper_set_config(&kernelfb_mode);
+ int ret;
+ if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) {
+ printk(KERN_ERR "Failed to restore crtc configuration: %d\n",
+ ret);
+ }
}
static void intelfb_restore_work_fn(struct work_struct *ignored)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 4ea2a651b92c..9e30daae37dc 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -31,6 +31,7 @@
#include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
+#include "drm_edid.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
@@ -56,8 +57,7 @@ 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_NULL_PACKETS_DURING_VSYNC;
+ SDVO_HSYNC_ACTIVE_HIGH;
if (hdmi_priv->has_hdmi_sink)
sdvox |= SDVO_AUDIO_ENABLE;
@@ -129,20 +129,26 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
return true;
}
-static void
-intel_hdmi_sink_detect(struct drm_connector *connector)
+static enum drm_connector_status
+intel_hdmi_edid_detect(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
struct edid *edid = NULL;
+ enum drm_connector_status status = connector_status_disconnected;
edid = drm_get_edid(&intel_output->base,
- &intel_output->ddc_bus->adapter);
- if (edid != NULL) {
- hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
- kfree(edid);
+ intel_output->ddc_bus);
+ hdmi_priv->has_hdmi_sink = false;
+ if (edid) {
+ if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+ status = connector_status_connected;
+ hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ }
intel_output->base.display_info.raw_edid = NULL;
+ kfree(edid);
}
+ return status;
}
static enum drm_connector_status
@@ -154,11 +160,7 @@ igdng_hdmi_detect(struct drm_connector *connector)
/* 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;
+ return intel_hdmi_edid_detect(connector);
}
static enum drm_connector_status
@@ -201,10 +203,9 @@ intel_hdmi_detect(struct drm_connector *connector)
return connector_status_unknown;
}
- if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) {
- intel_hdmi_sink_detect(connector);
- return connector_status_connected;
- } else
+ if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0)
+ return intel_hdmi_edid_detect(connector);
+ else
return connector_status_disconnected;
}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index f7061f68d050..62b8bead7652 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -124,6 +124,7 @@ static void set_data(void *data, int state_high)
* @output: driver specific output device
* @reg: GPIO reg to use
* @name: name for this bus
+ * @slave_addr: slave address (if fixed)
*
* Creates and registers a new i2c bus with the Linux i2c layer, for use
* in output probing and control (e.g. DDC or SDVO control functions).
@@ -139,8 +140,8 @@ static void set_data(void *data, int state_high)
* %GPIOH
* see PRM for details on how these different busses are used.
*/
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
- const char *name)
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+ const char *name)
{
struct intel_i2c_chan *chan;
@@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
intel_i2c_quirk_set(dev, false);
udelay(20);
- return chan;
+ return &chan->adapter;
out_free:
kfree(chan);
@@ -187,11 +188,16 @@ out_free:
*
* Unregister the adapter from the i2c layer, then free the structure.
*/
-void intel_i2c_destroy(struct intel_i2c_chan *chan)
+void intel_i2c_destroy(struct i2c_adapter *adapter)
{
- if (!chan)
+ struct intel_i2c_chan *chan;
+
+ if (!adapter)
return;
+ chan = container_of(adapter,
+ struct intel_i2c_chan,
+ adapter);
i2c_del_adapter(&chan->adapter);
kfree(chan);
}
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f073ed8432e8..9564ca44a977 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -39,6 +39,21 @@
#define I915_LVDS "i915_lvds"
+/*
+ * the following four scaling options are defined.
+ * #define DRM_MODE_SCALE_NON_GPU 0
+ * #define DRM_MODE_SCALE_FULLSCREEN 1
+ * #define DRM_MODE_SCALE_NO_SCALE 2
+ * #define DRM_MODE_SCALE_ASPECT 3
+ */
+
+/* Private structure for the integrated LVDS support */
+struct intel_lvds_priv {
+ int fitting_mode;
+ u32 pfit_control;
+ u32 pfit_pgm_ratios;
+};
+
/**
* Sets the backlight level.
*
@@ -213,10 +228,27 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
+ /*
+ * float point operation is not supported . So the PANEL_RATIO_FACTOR
+ * is defined, which can avoid the float point computation when
+ * calculating the panel ratio.
+ */
+#define PANEL_RATIO_FACTOR 8192
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct drm_encoder *tmp_encoder;
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+ u32 pfit_control = 0, pfit_pgm_ratios = 0;
+ int left_border = 0, right_border = 0, top_border = 0;
+ int bottom_border = 0;
+ bool border = 0;
+ int panel_ratio, desired_ratio, vert_scale, horiz_scale;
+ int horiz_ratio, vert_ratio;
+ u32 hsync_width, vsync_width;
+ u32 hblank_width, vblank_width;
+ u32 hsync_pos, vsync_pos;
/* Should never happen!! */
if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
@@ -232,7 +264,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
return false;
}
}
-
+ /* If we don't have a panel mode, there is nothing we can do */
+ if (dev_priv->panel_fixed_mode == NULL)
+ return true;
/*
* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode,
@@ -256,6 +290,243 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
}
+ /* Make sure pre-965s set dither correctly */
+ if (!IS_I965G(dev)) {
+ if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
+ pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+ }
+
+ /* Native modes don't need fitting */
+ if (adjusted_mode->hdisplay == mode->hdisplay &&
+ adjusted_mode->vdisplay == mode->vdisplay) {
+ pfit_pgm_ratios = 0;
+ border = 0;
+ goto out;
+ }
+
+ /* 965+ wants fuzzy fitting */
+ if (IS_I965G(dev))
+ pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
+ PFIT_FILTER_FUZZY;
+
+ hsync_width = adjusted_mode->crtc_hsync_end -
+ adjusted_mode->crtc_hsync_start;
+ vsync_width = adjusted_mode->crtc_vsync_end -
+ adjusted_mode->crtc_vsync_start;
+ hblank_width = adjusted_mode->crtc_hblank_end -
+ adjusted_mode->crtc_hblank_start;
+ vblank_width = adjusted_mode->crtc_vblank_end -
+ adjusted_mode->crtc_vblank_start;
+ /*
+ * Deal with panel fitting options. Figure out how to stretch the
+ * image based on its aspect ratio & the current panel fitting mode.
+ */
+ panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR /
+ adjusted_mode->vdisplay;
+ desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR /
+ mode->vdisplay;
+ /*
+ * Enable automatic panel scaling for non-native modes so that they fill
+ * the screen. Should be enabled before the pipe is enabled, according
+ * to register description and PRM.
+ * Change the value here to see the borders for debugging
+ */
+ I915_WRITE(BCLRPAT_A, 0);
+ I915_WRITE(BCLRPAT_B, 0);
+
+ switch (lvds_priv->fitting_mode) {
+ case DRM_MODE_SCALE_NO_SCALE:
+ /*
+ * For centered modes, we have to calculate border widths &
+ * heights and modify the values programmed into the CRTC.
+ */
+ left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2;
+ right_border = left_border;
+ if (mode->hdisplay & 1)
+ right_border++;
+ top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2;
+ bottom_border = top_border;
+ if (mode->vdisplay & 1)
+ bottom_border++;
+ /* Set active & border values */
+ adjusted_mode->crtc_hdisplay = mode->hdisplay;
+ /* Keep the boder be even */
+ if (right_border & 1)
+ right_border++;
+ /* use the border directly instead of border minuse one */
+ adjusted_mode->crtc_hblank_start = mode->hdisplay +
+ right_border;
+ /* keep the blank width constant */
+ adjusted_mode->crtc_hblank_end =
+ adjusted_mode->crtc_hblank_start + hblank_width;
+ /* get the hsync pos relative to hblank start */
+ hsync_pos = (hblank_width - hsync_width) / 2;
+ /* keep the hsync pos be even */
+ if (hsync_pos & 1)
+ hsync_pos++;
+ adjusted_mode->crtc_hsync_start =
+ adjusted_mode->crtc_hblank_start + hsync_pos;
+ /* keep the hsync width constant */
+ adjusted_mode->crtc_hsync_end =
+ adjusted_mode->crtc_hsync_start + hsync_width;
+ adjusted_mode->crtc_vdisplay = mode->vdisplay;
+ /* use the border instead of border minus one */
+ adjusted_mode->crtc_vblank_start = mode->vdisplay +
+ bottom_border;
+ /* keep the vblank width constant */
+ adjusted_mode->crtc_vblank_end =
+ adjusted_mode->crtc_vblank_start + vblank_width;
+ /* get the vsync start postion relative to vblank start */
+ vsync_pos = (vblank_width - vsync_width) / 2;
+ adjusted_mode->crtc_vsync_start =
+ adjusted_mode->crtc_vblank_start + vsync_pos;
+ /* keep the vsync width constant */
+ adjusted_mode->crtc_vsync_end =
+ adjusted_mode->crtc_vblank_start + vsync_width;
+ border = 1;
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ /* Scale but preserve the spect ratio */
+ pfit_control |= PFIT_ENABLE;
+ if (IS_I965G(dev)) {
+ /* 965+ is easy, it does everything in hw */
+ if (panel_ratio > desired_ratio)
+ pfit_control |= PFIT_SCALING_PILLAR;
+ else if (panel_ratio < desired_ratio)
+ pfit_control |= PFIT_SCALING_LETTER;
+ else
+ pfit_control |= PFIT_SCALING_AUTO;
+ } else {
+ /*
+ * For earlier chips we have to calculate the scaling
+ * ratio by hand and program it into the
+ * PFIT_PGM_RATIO register
+ */
+ u32 horiz_bits, vert_bits, bits = 12;
+ horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/
+ adjusted_mode->hdisplay;
+ vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/
+ adjusted_mode->vdisplay;
+ horiz_scale = adjusted_mode->hdisplay *
+ PANEL_RATIO_FACTOR / mode->hdisplay;
+ vert_scale = adjusted_mode->vdisplay *
+ PANEL_RATIO_FACTOR / mode->vdisplay;
+
+ /* retain aspect ratio */
+ if (panel_ratio > desired_ratio) { /* Pillar */
+ u32 scaled_width;
+ scaled_width = mode->hdisplay * vert_scale /
+ PANEL_RATIO_FACTOR;
+ horiz_ratio = vert_ratio;
+ pfit_control |= (VERT_AUTO_SCALE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ /* Pillar will have left/right borders */
+ left_border = (adjusted_mode->hdisplay -
+ scaled_width) / 2;
+ right_border = left_border;
+ if (mode->hdisplay & 1) /* odd resolutions */
+ right_border++;
+ /* keep the border be even */
+ if (right_border & 1)
+ right_border++;
+ adjusted_mode->crtc_hdisplay = scaled_width;
+ /* use border instead of border minus one */
+ adjusted_mode->crtc_hblank_start =
+ scaled_width + right_border;
+ /* keep the hblank width constant */
+ adjusted_mode->crtc_hblank_end =
+ adjusted_mode->crtc_hblank_start +
+ hblank_width;
+ /*
+ * get the hsync start pos relative to
+ * hblank start
+ */
+ hsync_pos = (hblank_width - hsync_width) / 2;
+ /* keep the hsync_pos be even */
+ if (hsync_pos & 1)
+ hsync_pos++;
+ adjusted_mode->crtc_hsync_start =
+ adjusted_mode->crtc_hblank_start +
+ hsync_pos;
+ /* keept hsync width constant */
+ adjusted_mode->crtc_hsync_end =
+ adjusted_mode->crtc_hsync_start +
+ hsync_width;
+ border = 1;
+ } else if (panel_ratio < desired_ratio) { /* letter */
+ u32 scaled_height = mode->vdisplay *
+ horiz_scale / PANEL_RATIO_FACTOR;
+ vert_ratio = horiz_ratio;
+ pfit_control |= (HORIZ_AUTO_SCALE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ /* Letterbox will have top/bottom border */
+ top_border = (adjusted_mode->vdisplay -
+ scaled_height) / 2;
+ bottom_border = top_border;
+ if (mode->vdisplay & 1)
+ bottom_border++;
+ adjusted_mode->crtc_vdisplay = scaled_height;
+ /* use border instead of border minus one */
+ adjusted_mode->crtc_vblank_start =
+ scaled_height + bottom_border;
+ /* keep the vblank width constant */
+ adjusted_mode->crtc_vblank_end =
+ adjusted_mode->crtc_vblank_start +
+ vblank_width;
+ /*
+ * get the vsync start pos relative to
+ * vblank start
+ */
+ vsync_pos = (vblank_width - vsync_width) / 2;
+ adjusted_mode->crtc_vsync_start =
+ adjusted_mode->crtc_vblank_start +
+ vsync_pos;
+ /* keep the vsync width constant */
+ adjusted_mode->crtc_vsync_end =
+ adjusted_mode->crtc_vsync_start +
+ vsync_width;
+ border = 1;
+ } else {
+ /* Aspects match, Let hw scale both directions */
+ pfit_control |= (VERT_AUTO_SCALE |
+ HORIZ_AUTO_SCALE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ }
+ horiz_bits = (1 << bits) * horiz_ratio /
+ PANEL_RATIO_FACTOR;
+ vert_bits = (1 << bits) * vert_ratio /
+ PANEL_RATIO_FACTOR;
+ pfit_pgm_ratios =
+ ((vert_bits << PFIT_VERT_SCALE_SHIFT) &
+ PFIT_VERT_SCALE_MASK) |
+ ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) &
+ PFIT_HORIZ_SCALE_MASK);
+ }
+ break;
+
+ case DRM_MODE_SCALE_FULLSCREEN:
+ /*
+ * Full scaling, even if it changes the aspect ratio.
+ * Fortunately this is all done for us in hw.
+ */
+ pfit_control |= PFIT_ENABLE;
+ if (IS_I965G(dev))
+ pfit_control |= PFIT_SCALING_AUTO;
+ else
+ pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ break;
+ default:
+ break;
+ }
+
+out:
+ lvds_priv->pfit_control = pfit_control;
+ lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
/*
* XXX: It would be nice to support lower refresh rates on the
* panels to reduce power consumption, and perhaps match the
@@ -301,8 +572,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- u32 pfit_control;
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
/*
* The LVDS pin pair will already have been turned on in the
@@ -319,22 +590,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* screen. Should be enabled before the pipe is enabled, according to
* register description and PRM.
*/
- if (mode->hdisplay != adjusted_mode->hdisplay ||
- mode->vdisplay != adjusted_mode->vdisplay)
- pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
- HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- else
- pfit_control = 0;
-
- if (!IS_I965G(dev)) {
- if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
- pfit_control |= PANEL_8TO6_DITHER_ENABLE;
- }
- else
- pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
-
- I915_WRITE(PFIT_CONTROL, pfit_control);
+ I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios);
+ I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
}
/**
@@ -406,6 +663,34 @@ static int intel_lvds_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t value)
{
+ struct drm_device *dev = connector->dev;
+ struct intel_output *intel_output =
+ to_intel_output(connector);
+
+ if (property == dev->mode_config.scaling_mode_property &&
+ connector->encoder) {
+ struct drm_crtc *crtc = connector->encoder->crtc;
+ struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+ if (value == DRM_MODE_SCALE_NON_GPU) {
+ DRM_DEBUG_KMS(I915_LVDS,
+ "non_GPU property is unsupported\n");
+ return 0;
+ }
+ if (lvds_priv->fitting_mode == value) {
+ /* the LVDS scaling property is not changed */
+ return 0;
+ }
+ lvds_priv->fitting_mode = value;
+ if (crtc && crtc->enabled) {
+ /*
+ * If the CRTC is enabled, the display will be changed
+ * according to the new panel fitting mode.
+ */
+ drm_crtc_helper_set_mode(crtc, &crtc->mode,
+ crtc->x, crtc->y, crtc->fb);
+ }
+ }
+
return 0;
}
@@ -456,7 +741,7 @@ static const struct dmi_system_id intel_no_lvds[] = {
.callback = intel_no_lvds_dmi_callback,
.ident = "Apple Mac Mini (Core series)",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
},
},
@@ -464,7 +749,7 @@ static const struct dmi_system_id intel_no_lvds[] = {
.callback = intel_no_lvds_dmi_callback,
.ident = "Apple Mac Mini (Core 2 series)",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
},
},
@@ -518,6 +803,7 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc;
+ struct intel_lvds_priv *lvds_priv;
u32 lvds;
int pipe, gpio = GPIOC;
@@ -531,7 +817,8 @@ void intel_lvds_init(struct drm_device *dev)
gpio = PCH_GPIOC;
}
- intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
+ intel_output = kzalloc(sizeof(struct intel_output) +
+ sizeof(struct intel_lvds_priv), GFP_KERNEL);
if (!intel_output) {
return;
}
@@ -553,7 +840,18 @@ void intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
+ lvds_priv = (struct intel_lvds_priv *)(intel_output + 1);
+ intel_output->dev_priv = lvds_priv;
+ /* create the scaling mode property */
+ drm_mode_create_scaling_mode_property(dev);
+ /*
+ * the initial panel fitting mode will be FULL_SCREEN.
+ */
+ drm_connector_attach_property(&intel_output->base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_FULLSCREEN);
+ lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
/*
* LVDS discovery:
* 1) check for EDID on DDC
@@ -649,5 +947,5 @@ failed:
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(intel_output);
}
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index e0910fefce87..67e2f4632a24 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output)
}
};
- intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
- ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
- intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
-
+ intel_i2c_quirk_set(intel_output->base.dev, true);
+ ret = i2c_transfer(intel_output->ddc_bus, msgs, 2);
+ intel_i2c_quirk_set(intel_output->base.dev, false);
if (ret == 2)
return true;
@@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
struct edid *edid;
int ret = 0;
- intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
- edid = drm_get_edid(&intel_output->base,
- &intel_output->ddc_bus->adapter);
- intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
+ intel_i2c_quirk_set(intel_output->base.dev, true);
+ edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus);
+ intel_i2c_quirk_set(intel_output->base.dev, false);
if (edid) {
drm_mode_connector_update_edid_property(&intel_output->base,
edid);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 9a00adb3a508..f03473779feb 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -38,8 +38,7 @@
#undef SDVO_DEBUG
#define I915_SDVO "i915_sdvo"
struct intel_sdvo_priv {
- struct intel_i2c_chan *i2c_bus;
- int slaveaddr;
+ u8 slave_addr;
/* Register for the SDVO device: SDVOB or SDVOC */
int output_device;
@@ -146,13 +145,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
struct i2c_msg msgs[] = {
{
- .addr = sdvo_priv->i2c_bus->slave_addr,
+ .addr = sdvo_priv->slave_addr >> 1,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = sdvo_priv->i2c_bus->slave_addr,
+ .addr = sdvo_priv->slave_addr >> 1,
.flags = I2C_M_RD,
.len = 1,
.buf = buf,
@@ -162,7 +161,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
out_buf[0] = addr;
out_buf[1] = 0;
- if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2)
+ if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2)
{
*ch = buf[0];
return true;
@@ -175,10 +174,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
u8 ch)
{
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u8 out_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = intel_output->i2c_bus->slave_addr,
+ .addr = sdvo_priv->slave_addr >> 1,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -188,7 +188,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
out_buf[0] = addr;
out_buf[1] = ch;
- if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1)
+ if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1)
{
return true;
}
@@ -1369,9 +1369,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
struct edid *edid = NULL;
- intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
edid = drm_get_edid(&intel_output->base,
- &intel_output->ddc_bus->adapter);
+ intel_output->ddc_bus);
if (edid != NULL) {
sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
kfree(edid);
@@ -1549,7 +1548,6 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
struct drm_i915_private *dev_priv = connector->dev->dev_private;
/*
@@ -1557,8 +1555,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
* Assume that the preferred modes are
* arranged in priority order.
*/
- /* set the bus switch and get the modes */
- intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
intel_ddc_get_modes(intel_output);
if (list_empty(&connector->probed_modes) == false)
return;
@@ -1709,7 +1705,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan)
list_for_each_entry(connector,
&dev->mode_config.connector_list, head) {
- if (to_intel_output(connector)->ddc_bus == chan) {
+ if (to_intel_output(connector)->ddc_bus == &chan->adapter) {
intel_output = to_intel_output(connector);
break;
}
@@ -1723,7 +1719,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
struct intel_output *intel_output;
struct intel_sdvo_priv *sdvo_priv;
struct i2c_algo_bit_data *algo_data;
- struct i2c_algorithm *algo;
+ const struct i2c_algorithm *algo;
algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
intel_output =
@@ -1733,7 +1729,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
return -EINVAL;
sdvo_priv = intel_output->dev_priv;
- algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo;
+ algo = intel_output->i2c_bus->algo;
intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
return algo->master_xfer(i2c_adap, msgs, num);
@@ -1785,13 +1781,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
struct drm_connector *connector;
struct intel_output *intel_output;
struct intel_sdvo_priv *sdvo_priv;
- struct intel_i2c_chan *i2cbus = NULL;
- struct intel_i2c_chan *ddcbus = NULL;
+
int connector_type;
u8 ch[0x40];
int i;
- int encoder_type, output_id;
- u8 slave_addr;
+ int encoder_type;
intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
if (!intel_output) {
@@ -1799,29 +1793,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
}
sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
+ sdvo_priv->output_device = output_device;
+
+ intel_output->dev_priv = sdvo_priv;
intel_output->type = INTEL_OUTPUT_SDVO;
/* setup the DDC bus. */
if (output_device == SDVOB)
- i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
+ intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
else
- i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
+ intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
- if (!i2cbus)
+ if (!intel_output->i2c_bus)
goto err_inteloutput;
- slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
- sdvo_priv->i2c_bus = i2cbus;
+ sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
- if (output_device == SDVOB) {
- output_id = 1;
- } else {
- output_id = 2;
- }
- 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;
+ /* Save the bit-banging i2c functionality for use by the DDC wrapper */
+ intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality;
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {
@@ -1835,17 +1824,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
/* setup the DDC bus. */
if (output_device == SDVOB)
- ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
+ intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
else
- ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+ intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
- if (ddcbus == NULL)
+ if (intel_output->ddc_bus == NULL)
goto err_i2c;
- intel_sdvo_i2c_bit_algo.functionality =
- intel_output->i2c_bus->adapter.algo->functionality;
- ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo;
- intel_output->ddc_bus = ddcbus;
+ /* Wrap with our custom algo which switches to DDC mode */
+ intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
/* In defaut case sdvo lvds is false */
sdvo_priv->is_lvds = false;
@@ -1965,9 +1952,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
return true;
err_i2c:
- if (ddcbus != NULL)
+ if (intel_output->ddc_bus != NULL)
intel_i2c_destroy(intel_output->ddc_bus);
- intel_i2c_destroy(intel_output->i2c_bus);
+ if (intel_output->i2c_bus != NULL)
+ intel_i2c_destroy(intel_output->i2c_bus);
err_inteloutput:
kfree(intel_output);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 50d7ed70b338..a43c98e3f077 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
/*
* Detect TV by polling)
*/
- if (intel_output->load_detect_temp) {
- /* TV not currently running, prod it with destructive detect */
- save_tv_dac = tv_dac;
- tv_ctl = I915_READ(TV_CTL);
- save_tv_ctl = tv_ctl;
- tv_ctl &= ~TV_ENC_ENABLE;
- 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 |
- TVDAC_C_SENSE_CTL |
- DAC_CTL_OVERRIDE |
- DAC_A_0_7_V |
- DAC_B_0_7_V |
- DAC_C_0_7_V);
- I915_WRITE(TV_CTL, tv_ctl);
- I915_WRITE(TV_DAC, tv_dac);
- intel_wait_for_vblank(dev);
- tv_dac = I915_READ(TV_DAC);
- I915_WRITE(TV_DAC, save_tv_dac);
- I915_WRITE(TV_CTL, save_tv_ctl);
- intel_wait_for_vblank(dev);
- }
+ save_tv_dac = tv_dac;
+ tv_ctl = I915_READ(TV_CTL);
+ save_tv_ctl = tv_ctl;
+ tv_ctl &= ~TV_ENC_ENABLE;
+ 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 |
+ TVDAC_C_SENSE_CTL |
+ DAC_CTL_OVERRIDE |
+ DAC_A_0_7_V |
+ DAC_B_0_7_V |
+ DAC_C_0_7_V);
+ I915_WRITE(TV_CTL, tv_ctl);
+ I915_WRITE(TV_DAC, tv_dac);
+ intel_wait_for_vblank(dev);
+ tv_dac = I915_READ(TV_DAC);
+ I915_WRITE(TV_DAC, save_tv_dac);
+ I915_WRITE(TV_CTL, save_tv_ctl);
+ intel_wait_for_vblank(dev);
/*
* A B C
* 0 1 1 Composite
@@ -1561,8 +1558,7 @@ intel_tv_destroy (struct drm_connector *connector)
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
- drm_free(intel_output, sizeof(struct intel_output) + sizeof(struct intel_tv_priv),
- DRM_MEM_DRIVER);
+ kfree(intel_output);
}
@@ -1695,8 +1691,8 @@ intel_tv_init(struct drm_device *dev)
(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
return;
- intel_output = drm_calloc(1, sizeof(struct intel_output) +
- sizeof(struct intel_tv_priv), DRM_MEM_DRIVER);
+ intel_output = kzalloc(sizeof(struct intel_output) +
+ sizeof(struct intel_tv_priv), GFP_KERNEL);
if (!intel_output) {
return;
}
@@ -1730,8 +1726,8 @@ intel_tv_init(struct drm_device *dev)
connector->doublescan_allowed = false;
/* Create TV properties then attach current values */
- tv_format_names = drm_alloc(sizeof(char *) * NUM_TV_MODES,
- DRM_MEM_DRIVER);
+ tv_format_names = kmalloc(sizeof(char *) * NUM_TV_MODES,
+ GFP_KERNEL);
if (!tv_format_names)
goto out;
for (i = 0; i < NUM_TV_MODES; i++)
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index 7a6bf9ffc5a3..6c67a02910c8 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -254,23 +254,20 @@ static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_pr
int i;
DRM_DEBUG("count=%d\n", dma->buf_count);
- dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ dev_priv->head = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL);
if (dev_priv->head == NULL)
return -ENOMEM;
- memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ entry = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL);
if (entry == NULL)
return -ENOMEM;
- memset(entry, 0, sizeof(drm_mga_freelist_t));
-
entry->next = dev_priv->head->next;
entry->prev = dev_priv->head;
SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
@@ -301,7 +298,7 @@ static void mga_freelist_cleanup(struct drm_device * dev)
entry = dev_priv->head;
while (entry) {
next = entry->next;
- drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ kfree(entry);
entry = next;
}
@@ -399,12 +396,11 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
drm_mga_private_t *dev_priv;
int ret;
- dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_mga_private_t), GFP_KERNEL);
if (!dev_priv)
return -ENOMEM;
dev->dev_private = (void *)dev_priv;
- memset(dev_priv, 0, sizeof(drm_mga_private_t));
dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
dev_priv->chipset = flags;
@@ -1150,7 +1146,7 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
*/
int mga_driver_unload(struct drm_device * dev)
{
- drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
dev->dev_private = NULL;
return 0;
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index 077c0455a6b9..c75fd3564040 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -353,12 +353,10 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
DRM_DEBUG("\n");
- dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
- memset(dev_priv, 0, sizeof(drm_r128_private_t));
-
dev_priv->is_pci = init->is_pci;
if (dev_priv->is_pci && !dev->sg) {
@@ -619,8 +617,7 @@ int r128_do_cleanup_cce(struct drm_device * dev)
("failed to cleanup PCI GART!\n");
}
- drm_free(dev->dev_private, sizeof(drm_r128_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
dev->dev_private = NULL;
}
@@ -768,18 +765,17 @@ static int r128_freelist_init(struct drm_device * dev)
drm_r128_freelist_t *entry;
int i;
- dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+ dev_priv->head = kzalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
if (dev_priv->head == NULL)
return -ENOMEM;
- memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
dev_priv->head->age = R128_BUFFER_USED;
for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+ entry = kmalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
if (!entry)
return -ENOMEM;
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index f7a5b5740764..026a48c95c8f 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -910,24 +910,24 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev,
}
buffer_size = depth->n * sizeof(u32);
- buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (buffer == NULL)
return -ENOMEM;
if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(buffer);
return -EFAULT;
}
mask_size = depth->n * sizeof(u8);
if (depth->mask) {
- mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+ mask = kmalloc(mask_size, GFP_KERNEL);
if (mask == NULL) {
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(buffer);
return -ENOMEM;
}
if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
- drm_free(mask, mask_size, DRM_MEM_BUFS);
+ kfree(buffer);
+ kfree(mask);
return -EFAULT;
}
@@ -954,7 +954,7 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev,
}
}
- drm_free(mask, mask_size, DRM_MEM_BUFS);
+ kfree(mask);
} else {
for (i = 0; i < count; i++, x++) {
BEGIN_RING(6);
@@ -978,7 +978,7 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev,
}
}
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(buffer);
return 0;
}
@@ -1000,54 +1000,54 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
xbuf_size = count * sizeof(*x);
ybuf_size = count * sizeof(*y);
- x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+ x = kmalloc(xbuf_size, GFP_KERNEL);
if (x == NULL) {
return -ENOMEM;
}
- y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+ y = kmalloc(ybuf_size, GFP_KERNEL);
if (y == NULL) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ kfree(x);
return -ENOMEM;
}
if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return -EFAULT;
}
if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return -EFAULT;
}
buffer_size = depth->n * sizeof(u32);
- buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (buffer == NULL) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return -ENOMEM;
}
if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
+ kfree(buffer);
return -EFAULT;
}
if (depth->mask) {
mask_size = depth->n * sizeof(u8);
- mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+ mask = kmalloc(mask_size, GFP_KERNEL);
if (mask == NULL) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
+ kfree(buffer);
return -ENOMEM;
}
if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
- drm_free(mask, mask_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
+ kfree(buffer);
+ kfree(mask);
return -EFAULT;
}
@@ -1074,7 +1074,7 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
}
}
- drm_free(mask, mask_size, DRM_MEM_BUFS);
+ kfree(mask);
} else {
for (i = 0; i < count; i++) {
BEGIN_RING(6);
@@ -1098,9 +1098,9 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
}
}
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
- drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
+ kfree(buffer);
return 0;
}
@@ -1167,23 +1167,23 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
xbuf_size = count * sizeof(*x);
ybuf_size = count * sizeof(*y);
- x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+ x = kmalloc(xbuf_size, GFP_KERNEL);
if (x == NULL) {
return -ENOMEM;
}
- y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+ y = kmalloc(ybuf_size, GFP_KERNEL);
if (y == NULL) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ kfree(x);
return -ENOMEM;
}
if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return -EFAULT;
}
if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return -EFAULT;
}
@@ -1210,8 +1210,8 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
ADVANCE_RING();
}
- drm_free(x, xbuf_size, DRM_MEM_BUFS);
- drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ kfree(x);
+ kfree(y);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 5225f5be7ea7..c550932a108f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -551,6 +551,9 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
/* cp setup */
WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
WREG32(RADEON_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+ RADEON_BUF_SWAP_32BIT |
+#endif
REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
REG_SET(RADEON_MAX_FETCH, max_fetch) |
@@ -644,7 +647,7 @@ int r100_cp_reset(struct radeon_device *rdev)
*/
int r100_cs_parse_packet0(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
- unsigned *auth, unsigned n,
+ const unsigned *auth, unsigned n,
radeon_packet0_check_t check)
{
unsigned reg;
@@ -654,6 +657,10 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
idx = pkt->idx + 1;
reg = pkt->reg;
+ /* Check that register fall into register range
+ * determined by the number of entry (n) in the
+ * safe register bitmap.
+ */
if (pkt->one_reg_wr) {
if ((reg >> 7) > n) {
return -EINVAL;
@@ -683,24 +690,6 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
return 0;
}
-int r100_cs_parse_packet3(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt,
- unsigned *auth, unsigned n,
- radeon_packet3_check_t check)
-{
- unsigned i, m;
-
- if ((pkt->opcode >> 5) > n) {
- return -EINVAL;
- }
- i = pkt->opcode >> 5;
- m = 1 << (pkt->opcode & 31);
- if (auth[i] & m) {
- return check(p, pkt);
- }
- return 0;
-}
-
void r100_cs_dump_packet(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
@@ -901,6 +890,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
return 0;
}
+int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ struct radeon_object *robj)
+{
+ struct radeon_cs_chunk *ib_chunk;
+ unsigned idx;
+
+ ib_chunk = &p->chunks[p->chunk_ib_idx];
+ idx = pkt->idx + 1;
+ if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
+ DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
+ "(need %u have %lu) !\n",
+ ib_chunk->kdata[idx+2] + 1,
+ radeon_object_size(robj));
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int r100_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
@@ -954,6 +962,10 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
+ if (r) {
+ return r;
+ }
break;
case 0x23:
/* FIXME: cleanup */
@@ -999,18 +1011,18 @@ int r100_cs_parse(struct radeon_cs_parser *p)
}
p->idx += pkt.count + 2;
switch (pkt.type) {
- case PACKET_TYPE0:
- r = r100_packet0_check(p, &pkt);
- break;
- case PACKET_TYPE2:
- break;
- case PACKET_TYPE3:
- r = r100_packet3_check(p, &pkt);
- break;
- default:
- DRM_ERROR("Unknown packet type %d !\n",
- pkt.type);
- return -EINVAL;
+ case PACKET_TYPE0:
+ r = r100_packet0_check(p, &pkt);
+ break;
+ case PACKET_TYPE2:
+ break;
+ case PACKET_TYPE3:
+ r = r100_packet3_check(p, &pkt);
+ break;
+ default:
+ DRM_ERROR("Unknown packet type %d !\n",
+ pkt.type);
+ return -EINVAL;
}
if (r) {
return r;
@@ -1267,12 +1279,6 @@ void r100_vram_info(struct radeon_device *rdev)
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
- if (rdev->mc.aper_size > rdev->mc.vram_size) {
- /* Why does some hw doesn't have CONFIG_MEMSIZE properly
- * setup ? */
- rdev->mc.vram_size = rdev->mc.aper_size;
- WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
- }
}
@@ -1352,6 +1358,11 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
}
}
+int r100_init(struct radeon_device *rdev)
+{
+ return 0;
+}
+
/*
* Debugfs info
*/
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index f5870a099d4f..e2ed5bc08170 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -48,14 +48,13 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc);
int r100_cs_parse_packet0(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
- unsigned *auth, unsigned n,
+ const unsigned *auth, unsigned n,
radeon_packet0_check_t check);
-int r100_cs_parse_packet3(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt,
- unsigned *auth, unsigned n,
- radeon_packet3_check_t check);
void r100_cs_dump_packet(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt);
+int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ struct radeon_object *robj);
/* This files gather functions specifics to:
* r300,r350,rv350,rv370,rv380
@@ -288,7 +287,7 @@ int r300_copy_dma(struct radeon_device *rdev,
return r;
}
/* Must wait for 2D idle & clean before DMA or hangs might happen */
- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+ radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 ));
radeon_ring_write(rdev, (1 << 16));
for (i = 0; i < num_loops; i++) {
cur_size = size;
@@ -319,7 +318,7 @@ void r300_ring_start(struct radeon_device *rdev)
/* Sub pixel 1/12 so we can have 4K rendering according to doc */
gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
- switch (rdev->num_gb_pipes) {
+ switch(rdev->num_gb_pipes) {
case 2:
gb_tile_config |= R300_PIPE_COUNT_R300;
break;
@@ -452,8 +451,8 @@ void r300_gpu_init(struct radeon_device *rdev)
case 4:
gb_tile_config |= R300_PIPE_COUNT_R420;
break;
- case 1:
default:
+ case 1:
gb_tile_config |= R300_PIPE_COUNT_RV350;
break;
}
@@ -725,18 +724,120 @@ struct r300_cs_track_cb {
unsigned offset;
};
+struct r300_cs_track_array {
+ struct radeon_object *robj;
+ unsigned esize;
+};
+
+struct r300_cs_track_texture {
+ struct radeon_object *robj;
+ unsigned pitch;
+ unsigned width;
+ unsigned height;
+ unsigned num_levels;
+ unsigned cpp;
+ unsigned tex_coord_type;
+ unsigned txdepth;
+ unsigned width_11;
+ unsigned height_11;
+ bool use_pitch;
+ bool enabled;
+ bool roundup_w;
+ bool roundup_h;
+};
+
struct r300_cs_track {
- unsigned num_cb;
- unsigned maxy;
- struct r300_cs_track_cb cb[4];
- struct r300_cs_track_cb zb;
- bool z_enabled;
+ unsigned num_cb;
+ unsigned maxy;
+ unsigned vtx_size;
+ unsigned vap_vf_cntl;
+ unsigned immd_dwords;
+ unsigned num_arrays;
+ unsigned max_indx;
+ struct r300_cs_track_array arrays[11];
+ struct r300_cs_track_cb cb[4];
+ struct r300_cs_track_cb zb;
+ struct r300_cs_track_texture textures[16];
+ bool z_enabled;
};
+static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t)
+{
+ DRM_ERROR("pitch %d\n", t->pitch);
+ DRM_ERROR("width %d\n", t->width);
+ DRM_ERROR("height %d\n", t->height);
+ DRM_ERROR("num levels %d\n", t->num_levels);
+ DRM_ERROR("depth %d\n", t->txdepth);
+ DRM_ERROR("bpp %d\n", t->cpp);
+ DRM_ERROR("coordinate type %d\n", t->tex_coord_type);
+ DRM_ERROR("width round to power of 2 %d\n", t->roundup_w);
+ DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
+}
+
+static inline int r300_cs_track_texture_check(struct radeon_device *rdev,
+ struct r300_cs_track *track)
+{
+ struct radeon_object *robj;
+ unsigned long size;
+ unsigned u, i, w, h;
+
+ for (u = 0; u < 16; u++) {
+ if (!track->textures[u].enabled)
+ continue;
+ robj = track->textures[u].robj;
+ if (robj == NULL) {
+ DRM_ERROR("No texture bound to unit %u\n", u);
+ return -EINVAL;
+ }
+ size = 0;
+ for (i = 0; i <= track->textures[u].num_levels; i++) {
+ if (track->textures[u].use_pitch) {
+ w = track->textures[u].pitch / (1 << i);
+ } else {
+ w = track->textures[u].width / (1 << i);
+ if (rdev->family >= CHIP_RV515)
+ w |= track->textures[u].width_11;
+ if (track->textures[u].roundup_w)
+ w = roundup_pow_of_two(w);
+ }
+ h = track->textures[u].height / (1 << i);
+ if (rdev->family >= CHIP_RV515)
+ h |= track->textures[u].height_11;
+ if (track->textures[u].roundup_h)
+ h = roundup_pow_of_two(h);
+ size += w * h;
+ }
+ size *= track->textures[u].cpp;
+ switch (track->textures[u].tex_coord_type) {
+ case 0:
+ break;
+ case 1:
+ size *= (1 << track->textures[u].txdepth);
+ break;
+ case 2:
+ size *= 6;
+ break;
+ default:
+ DRM_ERROR("Invalid texture coordinate type %u for unit "
+ "%u\n", track->textures[u].tex_coord_type, u);
+ return -EINVAL;
+ }
+ if (size > radeon_object_size(robj)) {
+ DRM_ERROR("Texture of unit %u needs %lu bytes but is "
+ "%lu\n", u, size, radeon_object_size(robj));
+ r300_cs_track_texture_print(&track->textures[u]);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
{
unsigned i;
unsigned long size;
+ unsigned prim_walk;
+ unsigned nverts;
for (i = 0; i < track->num_cb; i++) {
if (track->cb[i].robj == NULL) {
@@ -769,7 +870,59 @@ int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
return -EINVAL;
}
}
- return 0;
+ prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
+ nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
+ switch (prim_walk) {
+ case 1:
+ for (i = 0; i < track->num_arrays; i++) {
+ size = track->arrays[i].esize * track->max_indx * 4;
+ if (track->arrays[i].robj == NULL) {
+ DRM_ERROR("(PW %u) Vertex array %u no buffer "
+ "bound\n", prim_walk, i);
+ return -EINVAL;
+ }
+ if (size > radeon_object_size(track->arrays[i].robj)) {
+ DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
+ "have %lu dwords\n", prim_walk, i,
+ size >> 2,
+ radeon_object_size(track->arrays[i].robj) >> 2);
+ DRM_ERROR("Max indices %u\n", track->max_indx);
+ return -EINVAL;
+ }
+ }
+ break;
+ case 2:
+ for (i = 0; i < track->num_arrays; i++) {
+ size = track->arrays[i].esize * (nverts - 1) * 4;
+ if (track->arrays[i].robj == NULL) {
+ DRM_ERROR("(PW %u) Vertex array %u no buffer "
+ "bound\n", prim_walk, i);
+ return -EINVAL;
+ }
+ if (size > radeon_object_size(track->arrays[i].robj)) {
+ DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
+ "have %lu dwords\n", prim_walk, i, size >> 2,
+ radeon_object_size(track->arrays[i].robj) >> 2);
+ return -EINVAL;
+ }
+ }
+ break;
+ case 3:
+ size = track->vtx_size * nverts;
+ if (size != track->immd_dwords) {
+ DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n",
+ track->immd_dwords, size);
+ DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n",
+ nverts, track->vtx_size);
+ return -EINVAL;
+ }
+ break;
+ default:
+ DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n",
+ prim_walk);
+ return -EINVAL;
+ }
+ return r300_cs_track_texture_check(rdev, track);
}
static inline void r300_cs_track_clear(struct r300_cs_track *track)
@@ -789,9 +942,33 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track)
track->zb.pitch = 8192;
track->zb.cpp = 4;
track->zb.offset = 0;
+ track->vtx_size = 0x7F;
+ track->immd_dwords = 0xFFFFFFFFUL;
+ track->num_arrays = 11;
+ track->max_indx = 0x00FFFFFFUL;
+ for (i = 0; i < track->num_arrays; i++) {
+ track->arrays[i].robj = NULL;
+ track->arrays[i].esize = 0x7F;
+ }
+ for (i = 0; i < 16; i++) {
+ track->textures[i].pitch = 16536;
+ track->textures[i].width = 16536;
+ track->textures[i].height = 16536;
+ track->textures[i].width_11 = 1 << 11;
+ track->textures[i].height_11 = 1 << 11;
+ track->textures[i].num_levels = 12;
+ track->textures[i].txdepth = 16;
+ track->textures[i].cpp = 64;
+ track->textures[i].tex_coord_type = 1;
+ track->textures[i].robj = NULL;
+ /* CS IB emission code makes sure texture unit are disabled */
+ track->textures[i].enabled = false;
+ track->textures[i].roundup_w = true;
+ track->textures[i].roundup_h = true;
+ }
}
-static unsigned r300_auth_reg[] = {
+static const unsigned r300_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -808,7 +985,7 @@ static unsigned r300_auth_reg[] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFCFCC, 0xF00E9FFF, 0x007C0000,
+ 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -824,9 +1001,9 @@ static unsigned r300_auth_reg[] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF,
+ 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
- 0x00000000, 0x00000000, 0xFFFF0000, 0x00000000,
+ 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x0000C100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
@@ -848,8 +1025,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
- track = (struct r300_cs_track *)p->track;
- switch (reg) {
+ track = (struct r300_cs_track*)p->track;
+ switch(reg) {
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
@@ -907,6 +1084,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case R300_TX_OFFSET_0+52:
case R300_TX_OFFSET_0+56:
case R300_TX_OFFSET_0+60:
+ i = (reg - R300_TX_OFFSET_0) >> 2;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
@@ -915,11 +1093,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->textures[i].robj = reloc->robj;
break;
/* Tracked registers */
+ case 0x2084:
+ /* VAP_VF_CNTL */
+ track->vap_vf_cntl = ib_chunk->kdata[idx];
+ break;
+ case 0x20B4:
+ /* VAP_VTX_SIZE */
+ track->vtx_size = ib_chunk->kdata[idx] & 0x7F;
+ break;
+ case 0x2134:
+ /* VAP_VF_MAX_VTX_INDX */
+ track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
+ break;
case 0x43E4:
/* SC_SCISSOR1 */
-
track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1;
if (p->rdev->family < CHIP_RV515) {
track->maxy -= 1440;
@@ -994,8 +1184,166 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
/* ZB_DEPTHPITCH */
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
break;
+ case 0x4104:
+ for (i = 0; i < 16; i++) {
+ bool enabled;
+
+ enabled = !!(ib_chunk->kdata[idx] & (1 << i));
+ track->textures[i].enabled = enabled;
+ }
+ break;
+ case 0x44C0:
+ case 0x44C4:
+ case 0x44C8:
+ case 0x44CC:
+ case 0x44D0:
+ case 0x44D4:
+ case 0x44D8:
+ case 0x44DC:
+ case 0x44E0:
+ case 0x44E4:
+ case 0x44E8:
+ case 0x44EC:
+ case 0x44F0:
+ case 0x44F4:
+ case 0x44F8:
+ case 0x44FC:
+ /* TX_FORMAT1_[0-15] */
+ i = (reg - 0x44C0) >> 2;
+ tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
+ track->textures[i].tex_coord_type = tmp;
+ switch ((ib_chunk->kdata[idx] & 0x1F)) {
+ case 0:
+ case 2:
+ case 5:
+ case 18:
+ case 20:
+ case 21:
+ track->textures[i].cpp = 1;
+ break;
+ case 1:
+ case 3:
+ case 6:
+ case 7:
+ case 10:
+ case 11:
+ case 19:
+ case 22:
+ case 24:
+ track->textures[i].cpp = 2;
+ break;
+ case 4:
+ case 8:
+ case 9:
+ case 12:
+ case 13:
+ case 23:
+ case 25:
+ case 27:
+ case 30:
+ track->textures[i].cpp = 4;
+ break;
+ case 14:
+ case 26:
+ case 28:
+ track->textures[i].cpp = 8;
+ break;
+ case 29:
+ track->textures[i].cpp = 16;
+ break;
+ default:
+ DRM_ERROR("Invalid texture format %u\n",
+ (ib_chunk->kdata[idx] & 0x1F));
+ return -EINVAL;
+ break;
+ }
+ break;
+ case 0x4400:
+ case 0x4404:
+ case 0x4408:
+ case 0x440C:
+ case 0x4410:
+ case 0x4414:
+ case 0x4418:
+ case 0x441C:
+ case 0x4420:
+ case 0x4424:
+ case 0x4428:
+ case 0x442C:
+ case 0x4430:
+ case 0x4434:
+ case 0x4438:
+ case 0x443C:
+ /* TX_FILTER0_[0-15] */
+ i = (reg - 0x4400) >> 2;
+ tmp = ib_chunk->kdata[idx] & 0x7;;
+ if (tmp == 2 || tmp == 4 || tmp == 6) {
+ track->textures[i].roundup_w = false;
+ }
+ tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;;
+ if (tmp == 2 || tmp == 4 || tmp == 6) {
+ track->textures[i].roundup_h = false;
+ }
+ break;
+ case 0x4500:
+ case 0x4504:
+ case 0x4508:
+ case 0x450C:
+ case 0x4510:
+ case 0x4514:
+ case 0x4518:
+ case 0x451C:
+ case 0x4520:
+ case 0x4524:
+ case 0x4528:
+ case 0x452C:
+ case 0x4530:
+ case 0x4534:
+ case 0x4538:
+ case 0x453C:
+ /* TX_FORMAT2_[0-15] */
+ i = (reg - 0x4500) >> 2;
+ tmp = ib_chunk->kdata[idx] & 0x3FFF;
+ track->textures[i].pitch = tmp + 1;
+ if (p->rdev->family >= CHIP_RV515) {
+ tmp = ((ib_chunk->kdata[idx] >> 15) & 1) << 11;
+ track->textures[i].width_11 = tmp;
+ tmp = ((ib_chunk->kdata[idx] >> 16) & 1) << 11;
+ track->textures[i].height_11 = tmp;
+ }
+ break;
+ case 0x4480:
+ case 0x4484:
+ case 0x4488:
+ case 0x448C:
+ case 0x4490:
+ case 0x4494:
+ case 0x4498:
+ case 0x449C:
+ case 0x44A0:
+ case 0x44A4:
+ case 0x44A8:
+ case 0x44AC:
+ case 0x44B0:
+ case 0x44B4:
+ case 0x44B8:
+ case 0x44BC:
+ /* TX_FORMAT0_[0-15] */
+ i = (reg - 0x4480) >> 2;
+ tmp = ib_chunk->kdata[idx] & 0x7FF;
+ track->textures[i].width = tmp + 1;
+ tmp = (ib_chunk->kdata[idx] >> 11) & 0x7FF;
+ track->textures[i].height = tmp + 1;
+ tmp = (ib_chunk->kdata[idx] >> 26) & 0xF;
+ track->textures[i].num_levels = tmp;
+ tmp = ib_chunk->kdata[idx] & (1 << 31);
+ track->textures[i].use_pitch = !!tmp;
+ tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
+ track->textures[i].txdepth = tmp;
+ break;
default:
- printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", reg, idx);
+ printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
+ reg, idx);
return -EINVAL;
}
return 0;
@@ -1015,11 +1363,12 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
- track = (struct r300_cs_track *)p->track;
- switch (pkt->opcode) {
+ track = (struct r300_cs_track*)p->track;
+ switch(pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
- c = ib_chunk->kdata[idx++];
- for (i = 0; i < (c - 1); i += 2, idx += 3) {
+ c = ib_chunk->kdata[idx++] & 0x1F;
+ track->num_arrays = c;
+ for (i = 0; i < (c - 1); i+=2, idx+=3) {
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
@@ -1028,6 +1377,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
+ track->arrays[i + 0].esize &= 0x7F;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
@@ -1036,6 +1388,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
return r;
}
ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 1].robj = reloc->robj;
+ track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
+ track->arrays[i + 1].esize &= 0x7F;
}
if (c & 1) {
r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1046,6 +1401,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
+ track->arrays[i + 0].esize &= 0x7F;
}
break;
case PACKET3_INDX_BUFFER:
@@ -1056,14 +1414,65 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
+ if (r) {
+ return r;
+ }
break;
/* Draw packet */
- case PACKET3_3D_DRAW_VBUF:
case PACKET3_3D_DRAW_IMMD:
- case PACKET3_3D_DRAW_INDX:
- case PACKET3_3D_DRAW_VBUF_2:
+ /* Number of dwords is vtx_size * (num_vertices - 1)
+ * PRIM_WALK must be equal to 3 vertex data in embedded
+ * in cmd stream */
+ if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
+ DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
+ return -EINVAL;
+ }
+ track->vap_vf_cntl = ib_chunk->kdata[idx+1];
+ track->immd_dwords = pkt->count - 1;
+ r = r300_cs_track_check(p->rdev, track);
+ if (r) {
+ return r;
+ }
+ break;
case PACKET3_3D_DRAW_IMMD_2:
+ /* Number of dwords is vtx_size * (num_vertices - 1)
+ * PRIM_WALK must be equal to 3 vertex data in embedded
+ * in cmd stream */
+ if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
+ DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
+ return -EINVAL;
+ }
+ track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->immd_dwords = pkt->count;
+ r = r300_cs_track_check(p->rdev, track);
+ if (r) {
+ return r;
+ }
+ break;
+ case PACKET3_3D_DRAW_VBUF:
+ track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ r = r300_cs_track_check(p->rdev, track);
+ if (r) {
+ return r;
+ }
+ break;
+ case PACKET3_3D_DRAW_VBUF_2:
+ track->vap_vf_cntl = ib_chunk->kdata[idx];
+ r = r300_cs_track_check(p->rdev, track);
+ if (r) {
+ return r;
+ }
+ break;
+ case PACKET3_3D_DRAW_INDX:
+ track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ r = r300_cs_track_check(p->rdev, track);
+ if (r) {
+ return r;
+ }
+ break;
case PACKET3_3D_DRAW_INDX_2:
+ track->vap_vf_cntl = ib_chunk->kdata[idx];
r = r300_cs_track_check(p->rdev, track);
if (r) {
return r;
@@ -1095,8 +1504,8 @@ int r300_cs_parse(struct radeon_cs_parser *p)
switch (pkt.type) {
case PACKET_TYPE0:
r = r100_cs_parse_packet0(p, &pkt,
- r300_auth_reg,
- ARRAY_SIZE(r300_auth_reg),
+ p->rdev->config.r300.reg_safe_bm,
+ p->rdev->config.r300.reg_safe_bm_size,
&r300_packet0_check);
break;
case PACKET_TYPE2:
@@ -1114,3 +1523,10 @@ int r300_cs_parse(struct radeon_cs_parser *p)
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
return 0;
}
+
+int r300_init(struct radeon_device *rdev)
+{
+ rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
+ return 0;
+}
diff --git a/drivers/gpu/drm/radeon/r300.h b/drivers/gpu/drm/radeon/r300.h
new file mode 100644
index 000000000000..8486b4da9d69
--- /dev/null
+++ b/drivers/gpu/drm/radeon/r300.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * 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 shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+#ifndef R300_H
+#define R300_H
+
+struct r300_asic {
+ const unsigned *reg_safe_bm;
+ unsigned reg_safe_bm_size;
+};
+
+#endif
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c3f24cc56009..d61f2fc61df5 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -51,7 +51,7 @@
#include "radeon_mode.h"
#include "radeon_reg.h"
-
+#include "r300.h"
/*
* Modules parameters.
@@ -496,6 +496,7 @@ int r100_debugfs_cp_init(struct radeon_device *rdev);
* ASIC specific functions.
*/
struct radeon_asic {
+ int (*init)(struct radeon_device *rdev);
void (*errata)(struct radeon_device *rdev);
void (*vram_info)(struct radeon_device *rdev);
int (*gpu_reset)(struct radeon_device *rdev);
@@ -536,6 +537,10 @@ struct radeon_asic {
void (*set_clock_gating)(struct radeon_device *rdev, int enable);
};
+union radeon_asic_config {
+ struct r300_asic r300;
+};
+
/*
* IOCTL.
@@ -573,6 +578,7 @@ struct radeon_device {
struct drm_device *ddev;
struct pci_dev *pdev;
/* ASIC */
+ union radeon_asic_config config;
enum radeon_family family;
unsigned long flags;
int usec_timeout;
@@ -763,6 +769,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
/*
* ASICs macro.
*/
+#define radeon_init(rdev) (rdev)->asic->init((rdev))
#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index e57d8a784e9f..e2e567395df8 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -41,6 +41,7 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
/*
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
*/
+int r100_init(struct radeon_device *rdev);
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void r100_errata(struct radeon_device *rdev);
@@ -72,6 +73,7 @@ int r100_copy_blit(struct radeon_device *rdev,
struct radeon_fence *fence);
static struct radeon_asic r100_asic = {
+ .init = &r100_init,
.errata = &r100_errata,
.vram_info = &r100_vram_info,
.gpu_reset = &r100_gpu_reset,
@@ -104,6 +106,7 @@ static struct radeon_asic r100_asic = {
/*
* r300,r350,rv350,rv380
*/
+int r300_init(struct radeon_device *rdev);
void r300_errata(struct radeon_device *rdev);
void r300_vram_info(struct radeon_device *rdev);
int r300_gpu_reset(struct radeon_device *rdev);
@@ -126,6 +129,7 @@ int r300_copy_dma(struct radeon_device *rdev,
unsigned num_pages,
struct radeon_fence *fence);
static struct radeon_asic r300_asic = {
+ .init = &r300_init,
.errata = &r300_errata,
.vram_info = &r300_vram_info,
.gpu_reset = &r300_gpu_reset,
@@ -162,6 +166,7 @@ void r420_vram_info(struct radeon_device *rdev);
int r420_mc_init(struct radeon_device *rdev);
void r420_mc_fini(struct radeon_device *rdev);
static struct radeon_asic r420_asic = {
+ .init = &r300_init,
.errata = &r420_errata,
.vram_info = &r420_vram_info,
.gpu_reset = &r300_gpu_reset,
@@ -205,6 +210,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
static struct radeon_asic rs400_asic = {
+ .init = &r300_init,
.errata = &rs400_errata,
.vram_info = &rs400_vram_info,
.gpu_reset = &r300_gpu_reset,
@@ -249,6 +255,7 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
static struct radeon_asic rs600_asic = {
+ .init = &r300_init,
.errata = &rs600_errata,
.vram_info = &rs600_vram_info,
.gpu_reset = &r300_gpu_reset,
@@ -288,6 +295,7 @@ void rs690_mc_fini(struct radeon_device *rdev);
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
static struct radeon_asic rs690_asic = {
+ .init = &r300_init,
.errata = &rs690_errata,
.vram_info = &rs690_vram_info,
.gpu_reset = &r300_gpu_reset,
@@ -320,6 +328,7 @@ static struct radeon_asic rs690_asic = {
/*
* rv515
*/
+int rv515_init(struct radeon_device *rdev);
void rv515_errata(struct radeon_device *rdev);
void rv515_vram_info(struct radeon_device *rdev);
int rv515_gpu_reset(struct radeon_device *rdev);
@@ -331,6 +340,7 @@ void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
static struct radeon_asic rv515_asic = {
+ .init = &rv515_init,
.errata = &rv515_errata,
.vram_info = &rv515_vram_info,
.gpu_reset = &rv515_gpu_reset,
@@ -349,7 +359,7 @@ static struct radeon_asic rv515_asic = {
.irq_set = &r100_irq_set,
.irq_process = &r100_irq_process,
.fence_ring_emit = &r300_fence_ring_emit,
- .cs_parse = &r100_cs_parse,
+ .cs_parse = &r300_cs_parse,
.copy_blit = &r100_copy_blit,
.copy_dma = &r300_copy_dma,
.copy = &r100_copy_blit,
@@ -368,6 +378,7 @@ void r520_vram_info(struct radeon_device *rdev);
int r520_mc_init(struct radeon_device *rdev);
void r520_mc_fini(struct radeon_device *rdev);
static struct radeon_asic r520_asic = {
+ .init = &rv515_init,
.errata = &r520_errata,
.vram_info = &r520_vram_info,
.gpu_reset = &rv515_gpu_reset,
@@ -386,7 +397,7 @@ static struct radeon_asic r520_asic = {
.irq_set = &r100_irq_set,
.irq_process = &r100_irq_process,
.fence_ring_emit = &r300_fence_ring_emit,
- .cs_parse = &r100_cs_parse,
+ .cs_parse = &r300_cs_parse,
.copy_blit = &r100_copy_blit,
.copy_dma = &r300_copy_dma,
.copy = &r100_copy_blit,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 786632d3e378..1f5a1a490984 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -835,7 +835,6 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
struct _COMPASSIONATE_DATA *dac_info;
uint8_t frev, crev;
uint8_t bg, dac;
- int i;
struct radeon_encoder_primary_dac *p_dac = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
@@ -867,7 +866,6 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
struct _COMPASSIONATE_DATA *dac_info;
uint8_t frev, crev;
uint8_t bg, dac;
- int i;
struct radeon_encoder_tv_dac *tv_dac = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 06e8038bc4ac..afc4db280b94 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -799,6 +799,7 @@ static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
struct radeon_encoder_lvds *lvds = NULL;
uint32_t fp_vert_stretch, fp_horz_stretch;
uint32_t ppll_div_sel, ppll_val;
+ uint32_t lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL);
@@ -808,6 +809,14 @@ static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH);
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH);
+ /* These should be fail-safe defaults, fingers crossed */
+ lvds->panel_pwr_delay = 200;
+ lvds->panel_vcc_delay = 2000;
+
+ lvds->lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+ lvds->panel_digon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) & 0xf;
+ lvds->panel_blon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY2_SHIFT) & 0xf;
+
if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE)
lvds->native_mode.panel_yres =
((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >>
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 89c4c44169f7..d8356827ef17 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -2045,11 +2045,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
drm_radeon_private_t *dev_priv;
int ret = 0;
- dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
- memset(dev_priv, 0, sizeof(drm_radeon_private_t));
dev->dev_private = (void *)dev_priv;
dev_priv->flags = flags;
@@ -2103,7 +2102,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
unsigned long sareapage;
int ret;
- master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+ master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (!master_priv)
return -ENOMEM;
@@ -2137,7 +2136,7 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
if (master_priv->sarea)
drm_rmmap_locked(dev, master_priv->sarea);
- drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+ kfree(master_priv);
master->driver_priv = NULL;
}
@@ -2171,7 +2170,7 @@ int radeon_driver_unload(struct drm_device *dev)
drm_rmmap(dev, dev_priv->mmio);
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ kfree(dev_priv);
dev->dev_private = NULL;
return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 5fd2b639bf66..f97563db4e59 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -35,6 +35,23 @@
#include "atom.h"
/*
+ * Clear GPU surface registers.
+ */
+static void radeon_surface_init(struct radeon_device *rdev)
+{
+ /* FIXME: check this out */
+ if (rdev->family < CHIP_R600) {
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ WREG32(RADEON_SURFACE0_INFO +
+ i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
+ 0);
+ }
+ }
+}
+
+/*
* GPU scratch registers helpers function.
*/
static void radeon_scratch_init(struct radeon_device *rdev)
@@ -470,6 +487,10 @@ int radeon_device_init(struct radeon_device *rdev,
if (r) {
return r;
}
+ r = radeon_init(rdev);
+ if (r) {
+ return r;
+ }
/* Report DMA addressing limitation */
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
@@ -492,6 +513,8 @@ int radeon_device_init(struct radeon_device *rdev,
radeon_errata(rdev);
/* Initialize scratch registers */
radeon_scratch_init(rdev);
+ /* Initialize surface registers */
+ radeon_surface_init(rdev);
/* TODO: disable VGA need to use VGA request */
/* BIOS*/
@@ -600,9 +623,6 @@ int radeon_device_init(struct radeon_device *rdev,
if (r) {
return r;
}
- if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) {
- rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private;
- }
if (!ret) {
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
}
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 5452bb9d925e..3efcf1a526be 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -351,7 +351,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
radeon_i2c_do_lock(radeon_connector, 0);
if (edid) {
/* update digital bits here */
- if (edid->digital)
+ if (edid->input & DRM_EDID_INPUT_DIGITAL)
radeon_connector->use_digital = 1;
else
radeon_connector->use_digital = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index c815a2cbf7b3..84ba69f48784 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -313,7 +313,7 @@ static int __init radeon_init(void)
{
driver = &driver_old;
driver->num_ioctls = radeon_max_ioctl;
-#if defined(CONFIG_DRM_RADEON_KMS) && defined(CONFIG_X86)
+#if defined(CONFIG_DRM_RADEON_KMS)
/* if enabled by default */
if (radeon_modeset == -1) {
DRM_INFO("radeon default to kernel modesetting.\n");
@@ -345,7 +345,7 @@ static void __exit radeon_exit(void)
drm_exit(driver);
}
-late_initcall(radeon_init);
+module_init(radeon_init);
module_exit(radeon_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index fa86d398945e..9e8f191eb64a 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev,
{
struct fb_info *info;
struct radeon_fb_device *rfbdev;
- struct drm_framebuffer *fb;
+ struct drm_framebuffer *fb = NULL;
struct radeon_framebuffer *rfb;
struct drm_mode_fb_cmd mode_cmd;
struct drm_gem_object *gobj = NULL;
struct radeon_object *robj = NULL;
struct device *device = &rdev->pdev->dev;
int size, aligned_size, ret;
+ u64 fb_gpuaddr;
void *fbptr = NULL;
+ unsigned long tmp;
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
@@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev,
aligned_size = ALIGN(size, PAGE_SIZE);
ret = radeon_gem_object_create(rdev, aligned_size, 0,
- RADEON_GEM_DOMAIN_VRAM,
- false, ttm_bo_type_kernel,
- false, &gobj);
+ RADEON_GEM_DOMAIN_VRAM,
+ false, ttm_bo_type_kernel,
+ false, &gobj);
if (ret) {
- printk(KERN_ERR "failed to allocate framebuffer\n");
+ printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
+ surface_width, surface_height);
ret = -ENOMEM;
goto out;
}
@@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev,
ret = -ENOMEM;
goto out_unref;
}
+ ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+ if (ret) {
+ printk(KERN_ERR "failed to pin framebuffer\n");
+ ret = -ENOMEM;
+ goto out_unref;
+ }
list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
rfb = to_radeon_framebuffer(fb);
*rfb_p = rfb;
rdev->fbdev_rfb = rfb;
+ rdev->fbdev_robj = robj;
info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
if (info == NULL) {
@@ -541,13 +551,13 @@ int radeonfb_create(struct radeon_device *rdev,
info->fix.xpanstep = 1; /* doing it in hw */
info->fix.ypanstep = 1; /* doing it in hw */
info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_I830;
+ info->fix.accel = FB_ACCEL_NONE;
info->fix.type_aux = 0;
info->flags = FBINFO_DEFAULT;
info->fbops = &radeonfb_ops;
info->fix.line_length = fb->pitch;
- info->screen_base = fbptr;
- info->fix.smem_start = (unsigned long)fbptr;
+ tmp = fb_gpuaddr - rdev->mc.vram_location;
+ info->fix.smem_start = rdev->mc.aper_base + tmp;
info->fix.smem_len = size;
info->screen_base = fbptr;
info->screen_size = size;
@@ -562,8 +572,8 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.width = -1;
info->var.xres = fb_width;
info->var.yres = fb_height;
- info->fix.mmio_start = pci_resource_start(rdev->pdev, 2);
- info->fix.mmio_len = pci_resource_len(rdev->pdev, 2);
+ info->fix.mmio_start = 0;
+ info->fix.mmio_len = 0;
info->pixmap.size = 64*1024;
info->pixmap.buf_align = 8;
info->pixmap.access_align = 32;
@@ -644,7 +654,7 @@ out_unref:
if (robj) {
radeon_object_kunmap(robj);
}
- if (ret) {
+ if (fb && ret) {
list_del(&fb->filp_head);
drm_gem_object_unreference(gobj);
drm_framebuffer_cleanup(fb);
@@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
robj = rfb->obj->driver_private;
unregister_framebuffer(info);
radeon_object_kunmap(robj);
+ radeon_object_unpin(robj);
framebuffer_release(info);
}
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 71465ed2688a..dd438d32e5c0 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -162,7 +162,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_chan *i2c;
int ret;
- i2c = drm_calloc(1, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
+ i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
if (i2c == NULL)
return NULL;
@@ -189,7 +189,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
return i2c;
out_free:
- drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
+ kfree(i2c);
return NULL;
}
@@ -200,7 +200,7 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
return;
i2c_del_adapter(&i2c->adapter);
- drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
+ kfree(i2c);
}
struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 64f42b19cbfa..4612a7c146d1 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -169,7 +169,7 @@ int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
unsigned long sareapage;
int ret;
- master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+ master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (master_priv == NULL) {
return -ENOMEM;
}
@@ -199,7 +199,7 @@ void radeon_master_destroy_kms(struct drm_device *dev,
if (master_priv->sarea) {
drm_rmmap_locked(dev, master_priv->sarea);
}
- drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+ kfree(master_priv);
master->driver_priv = NULL;
}
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c
index 4af5286a36fb..ed95155c4b1d 100644
--- a/drivers/gpu/drm/radeon/radeon_mem.c
+++ b/drivers/gpu/drm/radeon/radeon_mem.c
@@ -43,8 +43,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
- struct mem_block *newblock =
- drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+ struct mem_block *newblock = kmalloc(sizeof(*newblock),
+ GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start;
@@ -60,8 +60,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
/* Maybe cut off the end of an existing block */
if (size < p->size) {
- struct mem_block *newblock =
- drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+ struct mem_block *newblock = kmalloc(sizeof(*newblock),
+ GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start + size;
@@ -118,7 +118,7 @@ static void free_block(struct mem_block *p)
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q), DRM_MEM_BUFS);
+ kfree(q);
}
if (p->prev->file_priv == NULL) {
@@ -126,7 +126,7 @@ static void free_block(struct mem_block *p)
q->size += p->size;
q->next = p->next;
q->next->prev = q;
- drm_free(p, sizeof(*q), DRM_MEM_BUFS);
+ kfree(p);
}
}
@@ -134,14 +134,14 @@ static void free_block(struct mem_block *p)
*/
static int init_heap(struct mem_block **heap, int start, int size)
{
- struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
+ struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
if (!blocks)
return -ENOMEM;
- *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
+ *heap = kmalloc(sizeof(**heap), GFP_KERNEL);
if (!*heap) {
- drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
+ kfree(blocks);
return -ENOMEM;
}
@@ -179,7 +179,7 @@ void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+ kfree(q);
}
}
}
@@ -196,10 +196,10 @@ void radeon_mem_takedown(struct mem_block **heap)
for (p = (*heap)->next; p != *heap;) {
struct mem_block *q = p;
p = p->next;
- drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+ kfree(q);
}
- drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
+ kfree(*heap);
*heap = NULL;
}
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 983e8df5e000..bac0d06c52ac 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
{
uint32_t flags;
uint32_t tmp;
- void *fbptr;
int r;
flags = radeon_object_flags_from_domain(domain);
@@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
return r;
}
- if (robj->rdev->fbdev_robj == robj) {
- mutex_lock(&robj->rdev->fbdev_info->lock);
- radeon_object_kunmap(robj);
- }
tmp = robj->tobj.mem.placement;
ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
@@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
DRM_ERROR("radeon: failed to pin object.\n");
}
radeon_object_unreserve(robj);
- if (robj->rdev->fbdev_robj == robj) {
- if (!r) {
- r = radeon_object_kmap(robj, &fbptr);
- }
- if (!r) {
- robj->rdev->fbdev_info->screen_base = fbptr;
- robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
- }
- mutex_unlock(&robj->rdev->fbdev_info->lock);
- }
return r;
}
void radeon_object_unpin(struct radeon_object *robj)
{
uint32_t flags;
- void *fbptr;
int r;
spin_lock(&robj->tobj.lock);
@@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj)
DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
return;
}
- if (robj->rdev->fbdev_robj == robj) {
- mutex_lock(&robj->rdev->fbdev_info->lock);
- radeon_object_kunmap(robj);
- }
flags = robj->tobj.mem.placement;
robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
r = ttm_buffer_object_validate(&robj->tobj,
@@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj)
DRM_ERROR("radeon: failed to unpin buffer.\n");
}
radeon_object_unreserve(robj);
- if (robj->rdev->fbdev_robj == robj) {
- if (!r) {
- r = radeon_object_kmap(robj, &fbptr);
- }
- if (!r) {
- robj->rdev->fbdev_info->screen_base = fbptr;
- robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
- }
- mutex_unlock(&robj->rdev->fbdev_info->lock);
- }
}
int radeon_object_wait(struct radeon_object *robj)
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index 6d3d90406a24..e1b618574461 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -3184,6 +3184,7 @@
# define RADEON_RB_BUFSZ_MASK (0x3f << 0)
# define RADEON_RB_BLKSZ_SHIFT 8
# define RADEON_RB_BLKSZ_MASK (0x3f << 8)
+# define RADEON_BUF_SWAP_32BIT (1 << 17)
# define RADEON_MAX_FETCH_SHIFT 18
# define RADEON_MAX_FETCH_MASK (0x3 << 18)
# define RADEON_RB_NO_UPDATE (1 << 27)
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index fa728ec6ed34..46645f3e0328 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -2866,12 +2866,12 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
*/
orig_bufsz = cmdbuf->bufsz;
if (orig_bufsz != 0) {
- kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER);
+ kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
if (kbuf == NULL)
return -ENOMEM;
if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
cmdbuf->bufsz)) {
- drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ kfree(kbuf);
return -EFAULT;
}
cmdbuf->buf = kbuf;
@@ -2884,7 +2884,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
if (orig_bufsz != 0)
- drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ kfree(kbuf);
return temp;
}
@@ -2991,7 +2991,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
}
if (orig_bufsz != 0)
- drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ kfree(kbuf);
DRM_DEBUG("DONE\n");
COMMIT_RING();
@@ -2999,7 +2999,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
err:
if (orig_bufsz != 0)
- drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ kfree(kbuf);
return -EINVAL;
}
@@ -3175,9 +3175,7 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
struct drm_radeon_driver_file_fields *radeon_priv;
DRM_DEBUG("\n");
- radeon_priv =
- (struct drm_radeon_driver_file_fields *)
- drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+ radeon_priv = kmalloc(sizeof(*radeon_priv), GFP_KERNEL);
if (!radeon_priv)
return -ENOMEM;
@@ -3196,7 +3194,7 @@ void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
struct drm_radeon_driver_file_fields *radeon_priv =
file_priv->driver_priv;
- drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+ kfree(radeon_priv);
}
struct drm_ioctl_desc radeon_ioctls[] = {
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 4c087c1510d7..1227a97f5169 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -133,6 +133,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->gpu_offset = 0;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
#if __OS_HAS_AGP
if (rdev->flags & RADEON_IS_AGP) {
if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) {
@@ -143,8 +144,9 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->io_offset = rdev->mc.agp_base;
man->io_size = rdev->mc.gtt_size;
man->io_addr = NULL;
- man->flags = TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
- TTM_MEMTYPE_FLAG_MAPPABLE;
+ if (!rdev->ddev->agp->cant_use_aperture)
+ man->flags = TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
+ TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_WC;
man->default_caching = TTM_PL_FLAG_WC;
@@ -154,8 +156,6 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->io_offset = 0;
man->io_size = 0;
man->io_addr = NULL;
- man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
- TTM_MEMTYPE_FLAG_CMA;
}
break;
case TTM_PL_VRAM:
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 7eab95db58ac..ffea37b1b3e2 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -225,6 +225,8 @@ void rv515_ring_start(struct radeon_device *rdev)
radeon_ring_write(rdev,
R300_GEOMETRY_ROUND_NEAREST |
R300_COLOR_ROUND_NEAREST);
+ radeon_ring_write(rdev, PACKET0(0x20C8, 0));
+ radeon_ring_write(rdev, 0);
radeon_ring_unlock_commit(rdev);
}
@@ -502,3 +504,59 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
return 0;
#endif
}
+
+
+/*
+ * Asic initialization
+ */
+static const unsigned r500_reg_safe_bm[159] = {
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
+ 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
+ 0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF,
+ 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+ 0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0003FC01, 0x3FFFFCF8, 0xFE800B19,
+};
+
+
+
+int rv515_init(struct radeon_device *rdev)
+{
+ rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);
+ return 0;
+}
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
index 456cd040f31a..bff6fc2524c8 100644
--- a/drivers/gpu/drm/savage/savage_bci.c
+++ b/drivers/gpu/drm/savage/savage_bci.c
@@ -298,8 +298,8 @@ static int savage_dma_init(drm_savage_private_t * dev_priv)
dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
(SAVAGE_DMA_PAGE_SIZE * 4);
- dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
- dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+ dev_priv->dma_pages = kmalloc(sizeof(drm_savage_dma_page_t) *
+ dev_priv->nr_dma_pages, GFP_KERNEL);
if (dev_priv->dma_pages == NULL)
return -ENOMEM;
@@ -539,7 +539,7 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_savage_private_t *dev_priv;
- dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+ dev_priv = kmalloc(sizeof(drm_savage_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -671,7 +671,7 @@ int savage_driver_unload(struct drm_device *dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
- drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return 0;
}
@@ -804,8 +804,8 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
dev_priv->fake_dma.offset = 0;
dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
dev_priv->fake_dma.type = _DRM_SHM;
- dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
- DRM_MEM_DRIVER);
+ dev_priv->fake_dma.handle = kmalloc(SAVAGE_FAKE_DMA_SIZE,
+ GFP_KERNEL);
if (!dev_priv->fake_dma.handle) {
DRM_ERROR("could not allocate faked DMA buffer!\n");
savage_do_cleanup_bci(dev);
@@ -903,9 +903,7 @@ static int savage_do_cleanup_bci(struct drm_device * dev)
drm_savage_private_t *dev_priv = dev->dev_private;
if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
- if (dev_priv->fake_dma.handle)
- drm_free(dev_priv->fake_dma.handle,
- SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+ kfree(dev_priv->fake_dma.handle);
} else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
dev_priv->cmd_dma->type == _DRM_AGP &&
dev_priv->dma_type == SAVAGE_DMA_AGP)
@@ -920,10 +918,7 @@ static int savage_do_cleanup_bci(struct drm_device * dev)
dev->agp_buffer_map = NULL;
}
- if (dev_priv->dma_pages)
- drm_free(dev_priv->dma_pages,
- sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
- DRM_MEM_DRIVER);
+ kfree(dev_priv->dma_pages);
return 0;
}
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c
index 5f6238fdf1fa..8a3e31599c94 100644
--- a/drivers/gpu/drm/savage/savage_state.c
+++ b/drivers/gpu/drm/savage/savage_state.c
@@ -988,20 +988,20 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
* for locking on FreeBSD.
*/
if (cmdbuf->size) {
- kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER);
+ kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL);
if (kcmd_addr == NULL)
return -ENOMEM;
if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
cmdbuf->size * 8))
{
- drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+ kfree(kcmd_addr);
return -EFAULT;
}
cmdbuf->cmd_addr = kcmd_addr;
}
if (cmdbuf->vb_size) {
- kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER);
+ kvb_addr = kmalloc(cmdbuf->vb_size, GFP_KERNEL);
if (kvb_addr == NULL) {
ret = -ENOMEM;
goto done;
@@ -1015,8 +1015,8 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
cmdbuf->vb_addr = kvb_addr;
}
if (cmdbuf->nbox) {
- kbox_addr = drm_alloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
+ GFP_KERNEL);
if (kbox_addr == NULL) {
ret = -ENOMEM;
goto done;
@@ -1154,10 +1154,9 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
done:
/* If we didn't need to allocate them, these'll be NULL */
- drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
- drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER);
- drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kfree(kcmd_addr);
+ kfree(kvb_addr);
+ kfree(kbox_addr);
return ret;
}
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 7dacc64e9b56..e725cc0b1155 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -40,7 +40,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
drm_sis_private_t *dev_priv;
int ret;
- dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -48,7 +48,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->chipset = chipset;
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
if (ret) {
- drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
+ kfree(dev_priv);
}
return ret;
@@ -59,7 +59,7 @@ static int sis_driver_unload(struct drm_device *dev)
drm_sis_private_t *dev_priv = dev->dev_private;
drm_sman_takedown(&dev_priv->sman);
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return 0;
}
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index e8f6d2229d8c..4648ed2f0143 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -63,8 +63,7 @@ static int ttm_agp_populate(struct ttm_backend *backend,
if (!page)
page = dummy_read_page;
- mem->memory[mem->page_count++] =
- phys_to_gart(page_to_phys(page));
+ mem->pages[mem->page_count++] = page;
}
agp_be->mem = mem;
return 0;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 1587aeca7bea..c1c407f7cca3 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -282,7 +282,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
if (ret)
- return ret;
+ goto out_err;
if (mem->mem_type != TTM_PL_SYSTEM) {
ret = ttm_tt_bind(bo->ttm, mem);
@@ -527,9 +527,12 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type,
ret = ttm_bo_wait(bo, false, interruptible, no_wait);
spin_unlock(&bo->lock);
- if (ret && ret != -ERESTART) {
- printk(KERN_ERR TTM_PFX "Failed to expire sync object before "
- "buffer eviction.\n");
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTART) {
+ printk(KERN_ERR TTM_PFX
+ "Failed to expire sync object before "
+ "buffer eviction.\n");
+ }
goto out;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 517c84559633..bdec583901eb 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -34,7 +34,6 @@
#include <linux/highmem.h>
#include <linux/wait.h>
#include <linux/vmalloc.h>
-#include <linux/version.h>
#include <linux/module.h>
void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 27b146c54fbc..40b75032ea47 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -32,7 +32,6 @@
#include <ttm/ttm_bo_driver.h>
#include <ttm/ttm_placement.h>
#include <linux/mm.h>
-#include <linux/version.h>
#include <linux/rbtree.h>
#include <linux/module.h>
#include <linux/uaccess.h>
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index c27ab3a877ad..75dc8bd24592 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -28,7 +28,6 @@
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
*/
-#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/highmem.h>
@@ -68,7 +67,7 @@ static void ttm_tt_cache_flush_clflush(struct page *pages[],
ttm_tt_clflush_page(*pages++);
mb();
}
-#else
+#elif !defined(__powerpc__)
static void ttm_tt_ipi_handler(void *null)
{
;
@@ -83,6 +82,15 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages)
ttm_tt_cache_flush_clflush(pages, num_pages);
return;
}
+#elif defined(__powerpc__)
+ unsigned long i;
+
+ for (i = 0; i < num_pages; ++i) {
+ if (pages[i]) {
+ unsigned long start = (unsigned long)page_address(pages[i]);
+ flush_dcache_range(start, start + PAGE_SIZE);
+ }
+ }
#else
if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0)
printk(KERN_ERR TTM_PFX
diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c
index 2c4f0b485792..6e6f91591639 100644
--- a/drivers/gpu/drm/via/via_map.c
+++ b/drivers/gpu/drm/via/via_map.c
@@ -96,7 +96,7 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
drm_via_private_t *dev_priv;
int ret = 0;
- dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -106,14 +106,14 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
if (ret) {
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return ret;
}
ret = drm_vblank_init(dev, 1);
if (ret) {
drm_sman_takedown(&dev_priv->sman);
- drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return ret;
}
@@ -126,7 +126,7 @@ int via_driver_unload(struct drm_device *dev)
drm_sman_takedown(&dev_priv->sman);
- drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return 0;
}