diff options
136 files changed, 2607 insertions, 1728 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 7ff1d0d208a7..2d68054f9795 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -50,7 +50,7 @@ obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_MWAVE) += mwave/ -obj-$(CONFIG_AGP) += agp/ +obj-y += agp/ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index d8b1b576556c..c528f96ee204 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -68,6 +68,7 @@ config AGP_AMD64 config AGP_INTEL tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" depends on AGP && X86 + select INTEL_GTT help This option gives you AGP support for the GLX component of X on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875, @@ -155,3 +156,7 @@ config AGP_SGI_TIOCA This option gives you AGP GART support for the SGI TIO chipset for IA64 processors. +config INTEL_GTT + tristate + depends on X86 && PCI + diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index 8eb56e273e75..604489bcdbf9 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_PARISC) += parisc-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_INTEL) += intel-agp.o -obj-$(CONFIG_AGP_INTEL) += intel-gtt.o +obj-$(CONFIG_INTEL_GTT) += intel-gtt.o obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o obj-$(CONFIG_AGP_SIS) += sis-agp.o diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a426ee1f57a6..9ef0a48a5b28 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -14,9 +14,6 @@ #include "intel-agp.h" #include <drm/intel-gtt.h> -int intel_agp_enabled; -EXPORT_SYMBOL(intel_agp_enabled); - static int intel_fetch_size(void) { int i; @@ -814,8 +811,6 @@ static int agp_intel_probe(struct pci_dev *pdev, found_gmch: pci_set_drvdata(pdev, bridge); err = agp_add_bridge(bridge); - if (!err) - intel_agp_enabled = 1; return err; } diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index b8e2014cb9cb..078968d8d07d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -94,6 +94,7 @@ static struct _intel_private { #define IS_IRONLAKE intel_private.driver->is_ironlake #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, struct sg_table *st) @@ -168,6 +169,7 @@ static void i8xx_destroy_pages(struct page *page) __free_pages(page, 2); atomic_dec(&agp_bridge->current_memory_agp); } +#endif #define I810_GTT_ORDER 4 static int i810_setup(void) @@ -209,6 +211,7 @@ static void i810_cleanup(void) free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER); } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -289,6 +292,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr) } kfree(curr); } +#endif static int intel_gtt_setup_scratch_page(void) { @@ -647,7 +651,9 @@ static int intel_gtt_init(void) return -ENOMEM; } +#if IS_ENABLED(CONFIG_AGP_INTEL) global_cache_flush(); /* FIXME: ? */ +#endif intel_private.stolen_size = intel_gtt_stolen_size(); @@ -671,6 +677,7 @@ static int intel_gtt_init(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_fetch_size(void) { int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); @@ -689,6 +696,7 @@ static int intel_fake_agp_fetch_size(void) return 0; } +#endif static void i830_cleanup(void) { @@ -801,6 +809,7 @@ static int i830_setup(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) { agp_bridge->gatt_table_real = NULL; @@ -825,6 +834,7 @@ static int intel_fake_agp_configure(void) return 0; } +#endif static bool i830_check_flags(unsigned int flags) { @@ -863,6 +873,7 @@ void intel_gtt_insert_sg_entries(struct sg_table *st, } EXPORT_SYMBOL(intel_gtt_insert_sg_entries); +#if IS_ENABLED(CONFIG_AGP_INTEL) static void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, struct page **pages, @@ -928,6 +939,7 @@ out_err: mem->is_flushed = true; return ret; } +#endif void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) { @@ -941,6 +953,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) } EXPORT_SYMBOL(intel_gtt_clear_range); +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_remove_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -982,6 +995,7 @@ static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, /* always return NULL for other allocation types for now */ return NULL; } +#endif static int intel_alloc_chipset_flush_resource(void) { @@ -1138,6 +1152,7 @@ static int i9xx_setup(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static const struct agp_bridge_driver intel_fake_agp_driver = { .owner = THIS_MODULE, .size_type = FIXED_APER_SIZE, @@ -1159,6 +1174,7 @@ static const struct agp_bridge_driver intel_fake_agp_driver = { .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, }; +#endif static const struct intel_gtt_driver i81x_gtt_driver = { .gen = 1, @@ -1376,11 +1392,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, intel_private.refcount++; +#if IS_ENABLED(CONFIG_AGP_INTEL) if (bridge) { bridge->driver = &intel_fake_agp_driver; bridge->dev_private_data = &intel_private; bridge->dev = bridge_pdev; } +#endif intel_private.bridge_dev = pci_dev_get(bridge_pdev); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 4f2b28354915..069f64533ac3 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -128,6 +128,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) return -ENOMEM; } + platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; /* Get the implementation specific driver data. */ @@ -376,7 +377,7 @@ static int armada_drm_probe(struct platform_device *pdev) static int armada_drm_remove(struct platform_device *pdev) { - drm_platform_exit(&armada_drm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index b6aded73838b..117d3eca5e37 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -222,7 +222,7 @@ void cirrus_fbdev_fini(struct cirrus_device *cdev); void cirrus_driver_irq_preinstall(struct drm_device *dev); int cirrus_driver_irq_postinstall(struct drm_device *dev); void cirrus_driver_irq_uninstall(struct drm_device *dev); -irqreturn_t cirrus_driver_irq_handler(DRM_IRQ_ARGS); +irqreturn_t cirrus_driver_irq_handler(int irq, void *arg); /* cirrus_kms.c */ int cirrus_driver_load(struct drm_device *dev, unsigned long flags); diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c index e301d653d97e..dde205cef384 100644 --- a/drivers/gpu/drm/drm_agpsupport.c +++ b/drivers/gpu/drm/drm_agpsupport.c @@ -53,7 +53,7 @@ */ int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info) { - DRM_AGP_KERN *kern; + struct agp_kern_info *kern; if (!dev->agp || !dev->agp->acquired) return -EINVAL; @@ -198,17 +198,15 @@ int drm_agp_enable_ioctl(struct drm_device *dev, void *data, int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) { struct drm_agp_mem *entry; - DRM_AGP_MEM *memory; + struct agp_memory *memory; unsigned long pages; u32 type; if (!dev->agp || !dev->agp->acquired) return -EINVAL; - if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL))) + if (!(entry = kzalloc(sizeof(*entry), GFP_KERNEL))) return -ENOMEM; - memset(entry, 0, sizeof(*entry)); - pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; type = (u32) request->type; if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) { @@ -393,14 +391,16 @@ int drm_agp_free_ioctl(struct drm_device *dev, void *data, * Gets the drm_agp_t structure which is made available by the agpgart module * via the inter_module_* functions. Creates and initializes a drm_agp_head * structure. + * + * Note that final cleanup of the kmalloced structure is directly done in + * drm_pci_agp_destroy. */ struct drm_agp_head *drm_agp_init(struct drm_device *dev) { struct drm_agp_head *head = NULL; - if (!(head = kmalloc(sizeof(*head), GFP_KERNEL))) + if (!(head = kzalloc(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))) { @@ -439,7 +439,7 @@ void drm_agp_clear(struct drm_device *dev) { struct drm_agp_mem *entry, *tempe; - if (!drm_core_has_AGP(dev) || !dev->agp) + if (!dev->agp) return; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; @@ -460,35 +460,20 @@ void drm_agp_clear(struct drm_device *dev) } /** - * drm_agp_destroy - Destroy AGP head - * @dev: DRM device - * - * Destroy resources that were previously allocated via drm_agp_initp. Caller - * must ensure to clean up all AGP resources before calling this. See - * drm_agp_clear(). - * - * Call this to destroy AGP heads allocated via drm_agp_init(). - */ -void drm_agp_destroy(struct drm_agp_head *agp) -{ - kfree(agp); -} - -/** * Binds a collection of pages into AGP memory at the given offset, returning * the AGP memory structure containing them. * * No reference is held on the pages during this time -- it is up to the * caller to handle that. */ -DRM_AGP_MEM * +struct agp_memory * drm_agp_bind_pages(struct drm_device *dev, struct page **pages, unsigned long num_pages, uint32_t gtt_offset, u32 type) { - DRM_AGP_MEM *mem; + struct agp_memory *mem; int ret, i; DRM_DEBUG("\n"); diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c index 39a718340319..0406110f83ed 100644 --- a/drivers/gpu/drm/drm_buffer.c +++ b/drivers/gpu/drm/drm_buffer.c @@ -114,7 +114,7 @@ int drm_buffer_copy_from_user(struct drm_buffer *buf, for (idx = 0; idx < nr_pages; ++idx) { - if (DRM_COPY_FROM_USER(buf->data[idx], + if (copy_from_user(buf->data[idx], user_data + idx * PAGE_SIZE, min(PAGE_SIZE, size - idx * PAGE_SIZE))) { DRM_ERROR("Failed to copy user data (%p) to drm buffer" diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 471e051d295e..edec31fe3fed 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -261,7 +261,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, struct drm_agp_mem *entry; int valid = 0; - if (!drm_core_has_AGP(dev)) { + if (!dev->agp) { kfree(map); return -EINVAL; } @@ -303,9 +303,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, break; } - case _DRM_GEM: - DRM_ERROR("tried to addmap GEM object\n"); - break; case _DRM_SCATTER_GATHER: if (!dev->sg) { kfree(map); @@ -483,9 +480,6 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map) dmah.size = map->size; __drm_pci_free(dev, &dmah); break; - case _DRM_GEM: - DRM_ERROR("tried to rmmap GEM object\n"); - break; } kfree(map); @@ -1396,7 +1390,7 @@ int drm_mapbufs(struct drm_device *dev, void *data, spin_unlock(&dev->count_lock); if (request->count >= dma->buf_count) { - if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) + if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG))) { struct drm_local_map *map = dev->agp_buffer_map; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d6cf77c472e7..266a01d7f635 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2767,10 +2767,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, } if (fb->funcs->dirty) { - drm_modeset_lock_all(dev); ret = fb->funcs->dirty(fb, file_priv, flags, r->color, clips, num_clips); - drm_modeset_unlock_all(dev); } else { ret = -ENOSYS; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index d9137e49c4e8..345be03c23db 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -315,9 +315,6 @@ long drm_ioctl(struct file *filp, if (drm_device_is_unplugged(dev)) return -ENODEV; - atomic_inc(&dev->ioctl_count); - ++file_priv->ioctl_count; - if ((nr >= DRM_CORE_IOCTL_COUNT) && ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) goto err_i1; @@ -410,7 +407,6 @@ long drm_ioctl(struct file *filp, if (kdata != stack_kdata) kfree(kdata); - atomic_dec(&dev->ioctl_count); if (retcode) DRM_DEBUG("ret = %d\n", retcode); return retcode; diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 9081172ef057..1b4c7a5442c5 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -141,7 +141,7 @@ static int edid_size(const u8 *edid, int data_size) return (edid[0x7e] + 1) * EDID_LENGTH; } -static u8 *edid_load(struct drm_connector *connector, const char *name, +static void *edid_load(struct drm_connector *connector, const char *name, const char *connector_name) { const struct firmware *fw = NULL; @@ -263,7 +263,7 @@ int drm_load_edid_firmware(struct drm_connector *connector) if (*last == '\n') *last = '\0'; - edid = (struct edid *) edid_load(connector, edidname, connector_name); + edid = edid_load(connector, edidname, connector_name); if (IS_ERR_OR_NULL(edid)) return 0; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0a19401aff80..98a03639b413 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) struct drm_crtc *crtc; int bound = 0, crtcs_bound = 0; + /* Sometimes user space wants everything disabled, so don't steal the + * display if there's a master. */ + if (dev->primary->master) + return false; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb) crtcs_bound++; @@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) if (bound < crtcs_bound) return false; + return true; } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index c5b929c3f77a..7f2af9aca038 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -232,7 +232,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_put_pid; } - priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->always_authenticated = capable(CAP_SYS_ADMIN); priv->authenticated = priv->always_authenticated; @@ -392,9 +391,6 @@ static void drm_legacy_dev_reinit(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - atomic_set(&dev->ioctl_count, 0); - atomic_set(&dev->vma_count, 0); - dev->sigdata.lock = NULL; dev->context_flag = 0; @@ -578,12 +574,7 @@ int drm_release(struct inode *inode, struct file *filp) */ if (!--dev->open_count) { - if (atomic_read(&dev->ioctl_count)) { - DRM_ERROR("Device busy: %d\n", - atomic_read(&dev->ioctl_count)); - retcode = -EBUSY; - } else - retcode = drm_lastclose(dev); + retcode = drm_lastclose(dev); if (drm_device_is_unplugged(dev)) drm_put_dev(dev); } diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 4761adedad2a..3ff39bb0402d 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -175,11 +175,6 @@ drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) mutex_unlock(&filp->prime.lock); } -static void drm_gem_object_ref_bug(struct kref *list_kref) -{ - BUG(); -} - /** * Called after the last handle to the object has been closed * @@ -195,13 +190,6 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj) if (obj->name) { idr_remove(&dev->object_name_idr, obj->name); obj->name = 0; - /* - * The object name held a reference to this object, drop - * that now. - * - * This cannot be the last reference, since the handle holds one too. - */ - kref_put(&obj->refcount, drm_gem_object_ref_bug); } } @@ -602,9 +590,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, goto err; obj->name = ret; - - /* Allocate a reference for the name table. */ - drm_gem_object_reference(obj); } args->name = (uint64_t) obj->name; diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 7d5a152eeb02..7473035dd28b 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -186,14 +186,14 @@ int drm_clients_info(struct seq_file *m, void *data) struct drm_file *priv; mutex_lock(&dev->struct_mutex); - seq_printf(m, "a dev pid uid magic ioctls\n\n"); + seq_printf(m, "a dev pid uid magic\n\n"); list_for_each_entry(priv, &dev->filelist, lhead) { - seq_printf(m, "%c %3d %5d %5d %10u %10lu\n", + seq_printf(m, "%c %3d %5d %5d %10u\n", priv->authenticated ? 'y' : 'n', priv->minor->index, pid_vnr(priv->pid), from_kuid_munged(seq_user_ns(m), priv->uid), - priv->magic, priv->ioctl_count); + priv->magic); } mutex_unlock(&dev->struct_mutex); return 0; @@ -234,14 +234,18 @@ int drm_vma_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_vma_entry *pt; struct vm_area_struct *vma; + unsigned long vma_count = 0; #if defined(__i386__) unsigned int pgprot; #endif mutex_lock(&dev->struct_mutex); - seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n", - atomic_read(&dev->vma_count), - high_memory, (void *)(unsigned long)virt_to_phys(high_memory)); + list_for_each_entry(pt, &dev->vmalist, head) + vma_count++; + + seq_printf(m, "vma use count: %lu, high_memory = %pK, 0x%pK\n", + vma_count, high_memory, + (void *)(unsigned long)virt_to_phys(high_memory)); list_for_each_entry(pt, &dev->vmalist, head) { vma = pt->vma; diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 64c34d5876ff..e7de2da57234 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -368,7 +368,7 @@ int drm_irq_uninstall(struct drm_device *dev) if (dev->num_crtcs) { spin_lock_irqsave(&dev->vbl_lock, irqflags); for (i = 0; i < dev->num_crtcs; i++) { - DRM_WAKEUP(&dev->vblank[i].queue); + wake_up(&dev->vblank[i].queue); dev->vblank[i].enabled = false; dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); @@ -960,7 +960,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc) if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && (drm_vblank_offdelay > 0)) mod_timer(&dev->vblank_disable_timer, - jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); + jiffies + ((drm_vblank_offdelay * HZ)/1000)); } EXPORT_SYMBOL(drm_vblank_put); @@ -980,7 +980,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); vblank_disable_and_save(dev, crtc); - DRM_WAKEUP(&dev->vblank[crtc].queue); + wake_up(&dev->vblank[crtc].queue); /* Send any queued vblank events, lest the natives grow disquiet */ seq = drm_vblank_count_and_time(dev, crtc, &now); @@ -1244,7 +1244,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); dev->vblank[crtc].last_wait = vblwait->request.sequence; - DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ, (((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) || !dev->irq_enabled)); @@ -1363,7 +1363,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) crtc, (int) diff_ns); } - DRM_WAKEUP(&dev->vblank[crtc].queue); + wake_up(&dev->vblank[crtc].queue); drm_handle_vblank_events(dev, crtc); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 64e44fad8ae8..00c67c0f2381 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -82,19 +82,19 @@ static void *agp_remap(unsigned long offset, unsigned long size, } /** Wrapper around agp_free_memory() */ -void drm_free_agp(DRM_AGP_MEM * handle, int pages) +void drm_free_agp(struct agp_memory * handle, int pages) { agp_free_memory(handle); } /** Wrapper around agp_bind_memory() */ -int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) +int drm_bind_agp(struct agp_memory * handle, unsigned int start) { return agp_bind_memory(handle, start); } /** Wrapper around agp_unbind_memory() */ -int drm_unbind_agp(DRM_AGP_MEM * handle) +int drm_unbind_agp(struct agp_memory * handle) { return agp_unbind_memory(handle); } @@ -110,8 +110,7 @@ static inline void *agp_remap(unsigned long offset, unsigned long size, void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev) { - if (drm_core_has_AGP(dev) && - dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) + if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) map->handle = agp_remap(map->offset, map->size, dev); else map->handle = ioremap(map->offset, map->size); @@ -120,8 +119,7 @@ EXPORT_SYMBOL(drm_core_ioremap); void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev) { - if (drm_core_has_AGP(dev) && - dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) + if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) map->handle = agp_remap(map->offset, map->size, dev); else map->handle = ioremap_wc(map->offset, map->size); @@ -133,8 +131,7 @@ void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev) if (!map->handle || !map->size) return; - if (drm_core_has_AGP(dev) && - dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) + if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) vunmap(map->handle); else iounmap(map->handle); diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 02679793c9e2..5736aaa7e86c 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -262,16 +262,11 @@ static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) return 0; } -static int drm_pci_agp_init(struct drm_device *dev) +static void drm_pci_agp_init(struct drm_device *dev) { - if (drm_core_has_AGP(dev)) { + if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { if (drm_pci_device_is_agp(dev)) dev->agp = drm_agp_init(dev); - if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) - && (dev->agp == NULL)) { - DRM_ERROR("Cannot initialize the agpgart module.\n"); - return -EINVAL; - } if (dev->agp) { dev->agp->agp_mtrr = arch_phys_wc_add( dev->agp->agp_info.aper_base, @@ -279,15 +274,14 @@ static int drm_pci_agp_init(struct drm_device *dev) 1024 * 1024); } } - return 0; } -static void drm_pci_agp_destroy(struct drm_device *dev) +void drm_pci_agp_destroy(struct drm_device *dev) { - if (drm_core_has_AGP(dev) && dev->agp) { + if (dev->agp) { arch_phys_wc_del(dev->agp->agp_mtrr); drm_agp_clear(dev); - drm_agp_destroy(dev->agp); + kfree(dev->agp); dev->agp = NULL; } } @@ -299,8 +293,6 @@ static struct drm_bus drm_pci_bus = { .set_busid = drm_pci_set_busid, .set_unique = drm_pci_set_unique, .irq_by_busid = drm_pci_irq_by_busid, - .agp_init = drm_pci_agp_init, - .agp_destroy = drm_pci_agp_destroy, }; /** @@ -338,17 +330,25 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if (drm_core_check_feature(dev, DRIVER_MODESET)) pci_set_drvdata(pdev, dev); + drm_pci_agp_init(dev); + ret = drm_dev_register(dev, ent->driver_data); if (ret) - goto err_pci; + goto err_agp; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, pci_name(pdev), dev->primary->index); + /* No locking needed since shadow-attach is single-threaded since it may + * only be called from the per-driver module init hook. */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list); + return 0; -err_pci: +err_agp: + drm_pci_agp_destroy(dev); pci_disable_device(pdev); err_free: drm_dev_free(dev); @@ -375,7 +375,6 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) DRM_DEBUG("\n"); - INIT_LIST_HEAD(&driver->device_list); driver->kdriver.pci = pdriver; driver->bus = &drm_pci_bus; @@ -383,6 +382,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) return pci_register_driver(pdriver); /* If not using KMS, fall back to stealth mode manual scanning. */ + INIT_LIST_HEAD(&driver->legacy_dev_list); for (i = 0; pdriver->id_table[i].vendor != 0; i++) { pid = &pdriver->id_table[i]; @@ -452,6 +452,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) return -1; } +void drm_pci_agp_destroy(struct drm_device *dev) {} #endif EXPORT_SYMBOL(drm_pci_init); @@ -465,8 +466,11 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) if (driver->driver_features & DRIVER_MODESET) { pci_unregister_driver(pdriver); } else { - list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) + list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list, + legacy_dev_list) { drm_put_dev(dev); + list_del(&dev->legacy_dev_list); + } } DRM_INFO("Module unloaded\n"); } diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index fc24fee8ec83..21fc82006b78 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -147,18 +147,6 @@ int drm_platform_init(struct drm_driver *driver, struct platform_device *platfor driver->kdriver.platform_device = platform_device; driver->bus = &drm_platform_bus; - INIT_LIST_HEAD(&driver->device_list); return drm_get_platform_dev(platform_device, driver); } EXPORT_SYMBOL(drm_platform_init); - -void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device) -{ - struct drm_device *dev, *tmp; - DRM_DEBUG("\n"); - - list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) - drm_put_dev(dev); - DRM_INFO("Module unloaded\n"); -} -EXPORT_SYMBOL(drm_platform_exit); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index f53d5246979c..a4a5c6ac110a 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -99,13 +99,19 @@ void drm_ut_debug_printk(unsigned int request_level, const char *function_name, const char *format, ...) { + struct va_format vaf; va_list args; if (drm_debug & request_level) { - if (function_name) - printk(KERN_DEBUG "[%s:%s], ", prefix, function_name); va_start(args, format); - vprintk(format, args); + vaf.fmt = format; + vaf.va = &args; + + if (function_name) + printk(KERN_DEBUG "[%s:%s], %pV", prefix, + function_name, &vaf); + else + printk(KERN_DEBUG "%pV", &vaf); va_end(args); } } @@ -521,16 +527,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) mutex_lock(&drm_global_mutex); - if (dev->driver->bus->agp_init) { - ret = dev->driver->bus->agp_init(dev); - if (ret) - goto out_unlock; - } - if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); if (ret) - goto err_agp; + goto out_unlock; } if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { @@ -557,8 +557,6 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) goto err_unload; } - list_add_tail(&dev->driver_item, &dev->driver->device_list); - ret = 0; goto out_unlock; @@ -571,9 +569,6 @@ err_render_node: drm_put_minor(dev->render); err_control_node: drm_put_minor(dev->control); -err_agp: - if (dev->driver->bus->agp_destroy) - dev->driver->bus->agp_destroy(dev); out_unlock: mutex_unlock(&drm_global_mutex); return ret; @@ -597,8 +592,8 @@ void drm_dev_unregister(struct drm_device *dev) if (dev->driver->unload) dev->driver->unload(dev); - if (dev->driver->bus->agp_destroy) - dev->driver->bus->agp_destroy(dev); + if (dev->agp) + drm_pci_agp_destroy(dev); drm_vblank_cleanup(dev); @@ -608,7 +603,5 @@ void drm_dev_unregister(struct drm_device *dev) drm_unplug_minor(dev->control); drm_unplug_minor(dev->render); drm_unplug_minor(dev->primary); - - list_del(&dev->driver_item); } EXPORT_SYMBOL(drm_dev_unregister); diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index b179b70e7853..21ae8d96880b 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -63,7 +63,6 @@ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) int res; DRM_DEBUG("\n"); - INIT_LIST_HEAD(&driver->device_list); driver->kdriver.usb = udriver; driver->bus = &drm_usb_bus; diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 93e95d7efd57..24e045c4f531 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -101,7 +101,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) /* * Find the right map */ - if (!drm_core_has_AGP(dev)) + if (!dev->agp) goto vm_fault_error; if (!dev->agp || !dev->agp->cant_use_aperture) @@ -220,7 +220,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); map = vma->vm_private_data; @@ -266,9 +265,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) dmah.size = map->size; __drm_pci_free(dev, &dmah); break; - case _DRM_GEM: - DRM_ERROR("tried to rmmap GEM object\n"); - break; } kfree(map); } @@ -408,7 +404,6 @@ void drm_vm_open_locked(struct drm_device *dev, DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); - atomic_inc(&dev->vma_count); vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL); if (vma_entry) { @@ -436,7 +431,6 @@ void drm_vm_close_locked(struct drm_device *dev, DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { if (pt->vma == vma) { @@ -595,7 +589,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) switch (map->type) { #if !defined(__arm__) case _DRM_AGP: - if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) { + if (dev->agp && dev->agp->cant_use_aperture) { /* * On some platforms we can't talk to bus dma address from the CPU, so for * memory of type DRM_AGP, we'll deal with sorting out the real physical diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 22b8f5eced80..7e074a4d2848 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -119,6 +119,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) drm_vblank_offdelay = VBLANK_OFF_DELAY; + platform_set_drvdata(dev->platformdev, dev); + return 0; err_drm_device: @@ -305,7 +307,7 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) static int exynos_drm_platform_remove(struct platform_device *pdev) { - drm_platform_exit(&exynos_drm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a61878bf5dcd..267aca91b70d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -954,7 +954,7 @@ static int fimd_probe(struct platform_device *pdev) } ctx->driver_data = drm_fimd_get_driver_data(pdev); - DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue); + init_waitqueue_head(&ctx->wait_vsync_queue); atomic_set(&ctx->wait_vsync_event, 0); subdrv = &ctx->subdrv; diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 63bc5f92fbb3..2dfa48c76f54 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -868,7 +868,7 @@ static void mixer_wait_for_vblank(void *ctx) */ if (!wait_event_timeout(mixer_ctx->wait_vsync_queue, !atomic_read(&mixer_ctx->wait_vsync_event), - DRM_HZ/20)) + HZ/20)) DRM_DEBUG_KMS("vblank wait timed out.\n"); } @@ -1019,7 +1019,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) /* set wait vsync event to zero and wake up queue. */ if (atomic_read(&ctx->wait_vsync_event)) { atomic_set(&ctx->wait_vsync_event, 0); - DRM_WAKEUP(&ctx->wait_vsync_queue); + wake_up(&ctx->wait_vsync_queue); } } @@ -1209,7 +1209,7 @@ static int mixer_probe(struct platform_device *pdev) drm_hdmi_ctx->ctx = (void *)ctx; ctx->vp_enabled = drv->is_vp_enabled; ctx->mxr_ver = drv->version; - DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue); + init_waitqueue_head(&ctx->wait_vsync_queue); atomic_set(&ctx->wait_vsync_event, 0); platform_set_drvdata(pdev, drm_hdmi_ctx); diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c index d5ef1a5793c8..de6f62a6ceb7 100644 --- a/drivers/gpu/drm/gma500/accel_2d.c +++ b/drivers/gpu/drm/gma500/accel_2d.c @@ -326,7 +326,7 @@ int psbfb_sync(struct fb_info *info) struct psb_framebuffer *psbfb = &fbdev->pfb; struct drm_device *dev = psbfb->base.dev; struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long _end = jiffies + DRM_HZ; + unsigned long _end = jiffies + HZ; int busy = 0; unsigned long flags; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index f88a1815d87c..6a7c2481d4ab 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -483,7 +483,7 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder, if (send_bytes > 16) return -1; - msg[0] = AUX_NATIVE_WRITE << 4; + msg[0] = DP_AUX_NATIVE_WRITE << 4; msg[1] = address >> 8; msg[2] = address & 0xff; msg[3] = send_bytes - 1; @@ -493,9 +493,10 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder, ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) break; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(100); else return -EIO; @@ -523,7 +524,7 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder, uint8_t ack; int ret; - msg[0] = AUX_NATIVE_READ << 4; + msg[0] = DP_AUX_NATIVE_READ << 4; msg[1] = address >> 8; msg[2] = address & 0xff; msg[3] = recv_bytes - 1; @@ -538,12 +539,12 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder, return -EPROTO; if (ret < 0) return ret; - ack = reply[0]; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { + ack = reply[0] >> 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) { memcpy(recv, reply + 1, ret - 1); return ret - 1; } - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(100); else return -EIO; @@ -569,12 +570,12 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, /* Set up the command byte */ if (mode & MODE_I2C_READ) - msg[0] = AUX_I2C_READ << 4; + msg[0] = DP_AUX_I2C_READ << 4; else - msg[0] = AUX_I2C_WRITE << 4; + msg[0] = DP_AUX_I2C_WRITE << 4; if (!(mode & MODE_I2C_STOP)) - msg[0] |= AUX_I2C_MOT << 4; + msg[0] |= DP_AUX_I2C_MOT << 4; msg[1] = address >> 8; msg[2] = address; @@ -606,16 +607,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, return ret; } - switch (reply[0] & AUX_NATIVE_REPLY_MASK) { - case AUX_NATIVE_REPLY_ACK: + switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) { + case DP_AUX_NATIVE_REPLY_ACK: /* I2C-over-AUX Reply field is only valid * when paired with AUX ACK. */ break; - case AUX_NATIVE_REPLY_NACK: + case DP_AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); return -EREMOTEIO; - case AUX_NATIVE_REPLY_DEFER: + case DP_AUX_NATIVE_REPLY_DEFER: udelay(100); continue; default: @@ -624,16 +625,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, return -EREMOTEIO; } - switch (reply[0] & AUX_I2C_REPLY_MASK) { - case AUX_I2C_REPLY_ACK: + switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) { + case DP_AUX_I2C_REPLY_ACK: if (mode == MODE_I2C_READ) { *read_byte = reply[1]; } return reply_bytes - 1; - case AUX_I2C_REPLY_NACK: + case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); return -EREMOTEIO; - case AUX_I2C_REPLY_DEFER: + case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(100); break; diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index b59e6588c343..5ad6a03e477e 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -212,8 +212,8 @@ enum { #define PSB_HIGH_REG_OFFS 0x0600 #define PSB_NUM_VBLANKS 2 -#define PSB_WATCHDOG_DELAY (DRM_HZ * 2) -#define PSB_LID_DELAY (DRM_HZ / 10) +#define PSB_WATCHDOG_DELAY (HZ * 2) +#define PSB_LID_DELAY (HZ / 10) #define MDFLD_PNW_B0 0x04 #define MDFLD_PNW_C0 0x08 @@ -232,7 +232,7 @@ enum { #define MDFLD_DSR_RR 45 #define MDFLD_DPU_ENABLE (1 << 31) #define MDFLD_DSR_FULLSCREEN (1 << 30) -#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) +#define MDFLD_DSR_DELAY (HZ / MDFLD_DSR_RR) #define PSB_PWR_STATE_ON 1 #define PSB_PWR_STATE_OFF 2 @@ -769,7 +769,7 @@ extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, *psb_irq.c */ -extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t psb_irq_handler(int irq, void *arg); extern int psb_irq_enable_dpst(struct drm_device *dev); extern int psb_irq_disable_dpst(struct drm_device *dev); extern void psb_irq_preinstall(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index ba4830342d34..f883f9e4c524 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -200,7 +200,7 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) mid_pipe_event_handler(dev, 1); } -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) +irqreturn_t psb_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_psb_private *dev_priv = dev->dev_private; @@ -253,7 +253,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); (void) PSB_RVDC32(PSB_INT_IDENTITY_R); - DRM_READMEMORYBARRIER(); + rmb(); if (!handled) return IRQ_NONE; @@ -450,21 +450,6 @@ int psb_irq_disable_dpst(struct drm_device *dev) return 0; } -#ifdef PSB_FIXME -static int psb_vblank_do_wait(struct drm_device *dev, - unsigned int *sequence, atomic_t *counter) -{ - unsigned int cur_vblank; - int ret = 0; - DRM_WAIT_ON(ret, dev->vblank.queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1 << 23))); - *sequence = cur_vblank; - - return ret; -} -#endif - /* * It is used to enable VBLANK interrupt */ diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h index debb7f190c06..d0b45ffa1126 100644 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ b/drivers/gpu/drm/gma500/psb_irq.h @@ -32,7 +32,7 @@ void sysirq_uninit(struct drm_device *dev); void psb_irq_preinstall(struct drm_device *dev); int psb_irq_postinstall(struct drm_device *dev); void psb_irq_uninstall(struct drm_device *dev); -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); +irqreturn_t psb_irq_handler(int irq, void *arg); int psb_irq_enable_dpst(struct drm_device *dev); int psb_irq_disable_dpst(struct drm_device *dev); diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 249fdff305c6..aeace37415aa 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -1193,6 +1193,10 @@ static int i810_flip_bufs(struct drm_device *dev, void *data, int i810_driver_load(struct drm_device *dev, unsigned long flags) { + /* Our userspace depends upon the agp mapping support. */ + if (!dev->agp) + return -EINVAL; + pci_set_master(dev->pdev); return 0; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index d8180d22cedd..441ccf8f5bdc 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -57,7 +57,7 @@ static const struct file_operations i810_driver_fops = { static struct drm_driver driver = { .driver_features = - DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | + DRIVER_USE_AGP | DRIVER_HAVE_DMA, .dev_priv_size = sizeof(drm_i810_buf_priv_t), .load = i810_driver_load, diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 6199d0b5b958..73ed59eff139 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -1,8 +1,10 @@ config DRM_I915 tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" depends on DRM - depends on AGP - depends on AGP_INTEL + depends on X86 && PCI + depends on (AGP || AGP=n) + select INTEL_GTT + select AGP_INTEL if AGP # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs select SHMEM @@ -35,15 +37,14 @@ config DRM_I915 config DRM_I915_KMS bool "Enable modesetting on intel by default" depends on DRM_I915 + default y help - Choose this option if you want kernel modesetting enabled by default, - and you have a new enough userspace to support this. Running old - userspaces with this enabled will cause pain. Note that this causes - the driver to bind to PCI devices, which precludes loading things - like intelfb. + Choose this option if you want kernel modesetting enabled by default. + + If in doubt, say "Y". config DRM_I915_FBDEV - bool "Enable legacy fbdev support for the modesettting intel driver" + bool "Enable legacy fbdev support for the modesetting intel driver" depends on DRM_I915 select DRM_KMS_FB_HELPER select FB_CFB_FILLRECT @@ -55,9 +56,12 @@ config DRM_I915_FBDEV support. Note that this support also provide the linux console support on top of the intel modesetting driver. + If in doubt, say "Y". + config DRM_I915_PRELIMINARY_HW_SUPPORT bool "Enable preliminary support for prerelease Intel hardware by default" depends on DRM_I915 + default n help Choose this option if you have prerelease Intel hardware and want the i915 driver to support it by default. You can enable such support at @@ -65,3 +69,15 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT option changes the default for that module option. If in doubt, say "N". + +config DRM_I915_UMS + bool "Enable userspace modesetting on Intel hardware (DEPRECATED)" + depends on DRM_I915 + default n + help + Choose this option if you still need userspace modesetting. + + Userspace modesetting is deprecated for quite some time now, so + enable this only if you have ancient versions of the DDX drivers. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c index c4a255be6979..954acb2c7021 100644 --- a/drivers/gpu/drm/i915/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/dvo_ns2501.c @@ -87,49 +87,6 @@ struct ns2501_priv { * when switching the resolution. */ -static void enable_dvo(struct intel_dvo_device *dvo) -{ - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); - struct i2c_adapter *adapter = dvo->i2c_bus; - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - struct drm_i915_private *dev_priv = bus->dev_priv; - - DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__); - - ns->dvoc = I915_READ(DVO_C); - ns->pll_a = I915_READ(_DPLL_A); - ns->srcdim = I915_READ(DVOC_SRCDIM); - ns->fw_blc = I915_READ(FW_BLC); - - I915_WRITE(DVOC, 0x10004084); - I915_WRITE(_DPLL_A, 0xd0820000); - I915_WRITE(DVOC_SRCDIM, 0x400300); // 1024x768 - I915_WRITE(FW_BLC, 0x1080304); - - I915_WRITE(DVOC, 0x90004084); -} - -/* - * Restore the I915 registers modified by the above - * trigger function. - */ -static void restore_dvo(struct intel_dvo_device *dvo) -{ - struct i2c_adapter *adapter = dvo->i2c_bus; - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - struct drm_i915_private *dev_priv = bus->dev_priv; - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); - - I915_WRITE(DVOC, ns->dvoc); - I915_WRITE(_DPLL_A, ns->pll_a); - I915_WRITE(DVOC_SRCDIM, ns->srcdim); - I915_WRITE(FW_BLC, ns->fw_blc); -} - /* ** Read a register from the ns2501. ** Returns true if successful, false otherwise. @@ -300,7 +257,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, struct drm_display_mode *adjusted_mode) { bool ok; - bool restore = false; + int retries = 10; struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); DRM_DEBUG_KMS @@ -476,20 +433,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, ns->reg_8_shadow |= NS2501_8_BPAS; } ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow); - - if (!ok) { - if (restore) - restore_dvo(dvo); - enable_dvo(dvo); - restore = true; - } - } while (!ok); - /* - * Restore the old i915 registers before - * forcing the ns2501 on. - */ - if (restore) - restore_dvo(dvo); + } while (!ok && retries--); } /* set the NS2501 power state */ @@ -510,7 +454,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo) static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) { bool ok; - bool restore = false; + int retries = 10; struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); unsigned char ch; @@ -537,16 +481,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) ok &= ns2501_writeb(dvo, 0x35, enable ? 0xff : 0x00); - if (!ok) { - if (restore) - restore_dvo(dvo); - enable_dvo(dvo); - restore = true; - } - } while (!ok); - - if (restore) - restore_dvo(dvo); + } while (!ok && retries--); } } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6ed45a984230..13accf795548 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -947,7 +947,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) if (ret) return ret; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); reqf = I915_READ(GEN6_RPNSWREQ); reqf &= ~GEN6_TURBO_DISABLE; @@ -970,7 +970,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; cagf *= GT_FREQUENCY_MULTIPLIER; - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); @@ -1018,17 +1018,16 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); - val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1); + val = valleyview_rps_max_freq(dev_priv); seq_printf(m, "max GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, val)); + vlv_gpu_freq(dev_priv, val)); - val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM); + val = valleyview_rps_min_freq(dev_priv); seq_printf(m, "min GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, val)); + vlv_gpu_freq(dev_priv, val)); seq_printf(m, "current GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, - (freq_sts >> 8) & 0xff)); + vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); mutex_unlock(&dev_priv->rps.hw_lock); } else { seq_puts(m, "no P-state info available\n"); @@ -1565,13 +1564,21 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - unsigned forcewake_count; + unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0; spin_lock_irq(&dev_priv->uncore.lock); - forcewake_count = dev_priv->uncore.forcewake_count; + if (IS_VALLEYVIEW(dev)) { + fw_rendercount = dev_priv->uncore.fw_rendercount; + fw_mediacount = dev_priv->uncore.fw_mediacount; + } else + forcewake_count = dev_priv->uncore.forcewake_count; spin_unlock_irq(&dev_priv->uncore.lock); - seq_printf(m, "forcewake count = %u\n", forcewake_count); + if (IS_VALLEYVIEW(dev)) { + seq_printf(m, "fw_rendercount = %u\n", fw_rendercount); + seq_printf(m, "fw_mediacount = %u\n", fw_mediacount); + } else + seq_printf(m, "forcewake count = %u\n", forcewake_count); return 0; } @@ -1735,28 +1742,28 @@ static int i915_dpio_info(struct seq_file *m, void *data) seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL)); - seq_printf(m, "DPIO_DIV_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A)); - seq_printf(m, "DPIO_DIV_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B)); + seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0))); + seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1))); - seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A)); - seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B)); + seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0))); + seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1))); - seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A)); - seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B)); + seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0))); + seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1))); - seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A)); - seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B)); + seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0))); + seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1))); seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE)); + vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0)); mutex_unlock(&dev_priv->dpio_lock); @@ -1845,6 +1852,76 @@ static int i915_pc8_status(struct seq_file *m, void *unused) return 0; } +static const char *power_domain_str(enum intel_display_power_domain domain) +{ + switch (domain) { + case POWER_DOMAIN_PIPE_A: + return "PIPE_A"; + case POWER_DOMAIN_PIPE_B: + return "PIPE_B"; + case POWER_DOMAIN_PIPE_C: + return "PIPE_C"; + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + return "PIPE_A_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + return "PIPE_B_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + return "PIPE_C_PANEL_FITTER"; + case POWER_DOMAIN_TRANSCODER_A: + return "TRANSCODER_A"; + case POWER_DOMAIN_TRANSCODER_B: + return "TRANSCODER_B"; + case POWER_DOMAIN_TRANSCODER_C: + return "TRANSCODER_C"; + case POWER_DOMAIN_TRANSCODER_EDP: + return "TRANSCODER_EDP"; + case POWER_DOMAIN_VGA: + return "VGA"; + case POWER_DOMAIN_AUDIO: + return "AUDIO"; + case POWER_DOMAIN_INIT: + return "INIT"; + default: + WARN_ON(1); + return "?"; + } +} + +static int i915_power_domain_info(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + int i; + + mutex_lock(&power_domains->lock); + + seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count"); + for (i = 0; i < power_domains->power_well_count; i++) { + struct i915_power_well *power_well; + enum intel_display_power_domain power_domain; + + power_well = &power_domains->power_wells[i]; + seq_printf(m, "%-25s %d\n", power_well->name, + power_well->count); + + for (power_domain = 0; power_domain < POWER_DOMAIN_NUM; + power_domain++) { + if (!(BIT(power_domain) & power_well->domains)) + continue; + + seq_printf(m, " %-23s %d\n", + power_domain_str(power_domain), + power_domains->domain_use_count[power_domain]); + } + } + + mutex_unlock(&power_domains->lock); + + return 0; +} + struct pipe_crc_info { const char *name; struct drm_device *dev; @@ -1857,6 +1934,9 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) struct drm_i915_private *dev_priv = info->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; + if (info->pipe >= INTEL_INFO(info->dev)->num_pipes) + return -ENODEV; + spin_lock_irq(&pipe_crc->lock); if (pipe_crc->opened) { @@ -2347,7 +2427,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - u32 val; + u32 val = 0; /* shut up gcc */ int ret; if (pipe_crc->source == source) @@ -2742,7 +2822,7 @@ i915_drop_caches_set(void *data, u64 val) struct i915_vma *vma, *x; int ret; - DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val); + DRM_DEBUG("Dropping caches: 0x%08llx\n", val); /* No need to check and wait for gpu resets, only libdrm auto-restarts * on ioctls on -EAGAIN. */ @@ -2810,8 +2890,7 @@ i915_max_freq_get(void *data, u64 *val) return ret; if (IS_VALLEYVIEW(dev)) - *val = vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.max_delay); + *val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay); else *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -2841,9 +2920,9 @@ i915_max_freq_set(void *data, u64 val) * Turbo will still be enabled, but won't go above the set value. */ if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); dev_priv->rps.max_delay = val; - gen6_set_rps(dev, val); + valleyview_set_rps(dev, val); } else { do_div(val, GT_FREQUENCY_MULTIPLIER); dev_priv->rps.max_delay = val; @@ -2876,8 +2955,7 @@ i915_min_freq_get(void *data, u64 *val) return ret; if (IS_VALLEYVIEW(dev)) - *val = vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.min_delay); + *val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay); else *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -2907,7 +2985,7 @@ i915_min_freq_set(void *data, u64 val) * Turbo will still be enabled, but won't go below the set value. */ if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); dev_priv->rps.min_delay = val; valleyview_set_rps(dev, val); } else { @@ -2983,7 +3061,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file) if (INTEL_INFO(dev)->gen < 6) return 0; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); return 0; } @@ -2996,7 +3074,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file) if (INTEL_INFO(dev)->gen < 6) return 0; - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); return 0; } @@ -3079,6 +3157,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_energy_uJ", i915_energy_uJ, 0}, {"i915_pc8_status", i915_pc8_status, 0}, + {"i915_power_domain_info", i915_power_domain_info, 0}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) @@ -3102,10 +3181,10 @@ static const struct i915_debugfs_files { void intel_display_crc_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int i; + enum pipe pipe; - for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; + for_each_pipe(pipe) { + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; pipe_crc->opened = false; spin_lock_init(&pipe_crc->lock); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d045135..bf38e99410a4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -783,7 +783,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; if (ring->irq_get(ring)) { - DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, ring->irq_queue, 3 * HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); ring->irq_put(ring); } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000)) @@ -820,7 +820,7 @@ static int i915_irq_emit(struct drm_device *dev, void *data, result = i915_emit_irq(dev); mutex_unlock(&dev->struct_mutex); - if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { + if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } @@ -1008,8 +1008,8 @@ static int i915_getparam(struct drm_device *dev, void *data, return -EINVAL; } - if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { - DRM_ERROR("DRM_COPY_TO_USER failed\n"); + if (copy_to_user(param->value, &value, sizeof(int))) { + DRM_ERROR("copy_to_user failed\n"); return -EFAULT; } @@ -1476,6 +1476,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return -ENODEV; } + /* UMS needs agp support. */ + if (!drm_core_check_feature(dev, DRIVER_MODESET) && !dev->agp) + return -EINVAL; + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; @@ -1486,7 +1490,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); - spin_lock_init(&dev_priv->backlight.lock); + spin_lock_init(&dev_priv->backlight_lock); spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->mm.object_stat_lock); mutex_init(&dev_priv->dpio_lock); @@ -1639,8 +1643,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_gem_unload; } - if (HAS_POWER_WELL(dev)) - intel_power_domains_init(dev); + intel_power_domains_init(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); @@ -1667,8 +1670,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; out_power_well: - if (HAS_POWER_WELL(dev)) - intel_power_domains_remove(dev); + intel_power_domains_remove(dev); drm_vblank_cleanup(dev); out_gem_unload: if (dev_priv->mm.inactive_shrinker.scan_objects) @@ -1706,13 +1708,11 @@ int i915_driver_unload(struct drm_device *dev) intel_gpu_ips_teardown(); - if (HAS_POWER_WELL(dev)) { - /* The i915.ko module is still not prepared to be loaded when - * the power well is not enabled, so just enable it in case - * we're going to unload/reload. */ - intel_display_set_init_power(dev, true); - intel_power_domains_remove(dev); - } + /* The i915.ko module is still not prepared to be loaded when + * the power well is not enabled, so just enable it in case + * we're going to unload/reload. */ + intel_display_set_init_power(dev, true); + intel_power_domains_remove(dev); i915_teardown_sysfs(dev); @@ -1777,7 +1777,6 @@ int i915_driver_unload(struct drm_device *dev) list_del(&dev_priv->gtt.base.global_link); WARN_ON(!list_empty(&dev_priv->vm_list)); - drm_mm_takedown(&dev_priv->gtt.base.mm); drm_vblank_cleanup(dev); @@ -1908,6 +1907,7 @@ const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2e367a1c6a64..e570ad7a9dfe 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -114,7 +114,7 @@ MODULE_PARM_DESC(enable_hangcheck, "(default: true)"); int i915_enable_ppgtt __read_mostly = -1; -module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); +module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400); MODULE_PARM_DESC(i915_enable_ppgtt, "Enable PPGTT (default: true)"); @@ -155,7 +155,6 @@ MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only."); static struct drm_driver driver; -extern int intel_agp_enabled; static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, @@ -265,6 +264,7 @@ static const struct intel_device_info intel_ironlake_m_info = { static const struct intel_device_info intel_sandybridge_d_info = { .gen = 6, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, + .has_fbc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .has_llc = 1, }; @@ -280,6 +280,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { #define GEN7_FEATURES \ .gen = 7, .num_pipes = 3, \ .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1 @@ -292,7 +293,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { GEN7_FEATURES, .is_ivybridge = 1, .is_mobile = 1, - .has_fbc = 1, }; static const struct intel_device_info intel_ivybridge_q_info = { @@ -307,6 +307,7 @@ static const struct intel_device_info intel_valleyview_m_info = { .num_pipes = 2, .is_valleyview = 1, .display_mmio_offset = VLV_DISPLAY_BASE, + .has_fbc = 0, /* legal, last one wins */ .has_llc = 0, /* legal, last one wins */ }; @@ -315,6 +316,7 @@ static const struct intel_device_info intel_valleyview_d_info = { .num_pipes = 2, .is_valleyview = 1, .display_mmio_offset = VLV_DISPLAY_BASE, + .has_fbc = 0, /* legal, last one wins */ .has_llc = 0, /* legal, last one wins */ }; @@ -332,7 +334,6 @@ static const struct intel_device_info intel_haswell_m_info = { .is_mobile = 1, .has_ddi = 1, .has_fpga_dbg = 1, - .has_fbc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, }; @@ -761,14 +762,14 @@ int i915_reset(struct drm_device *dev) DRM_INFO("Simulated gpu hang, resetting stop_rings\n"); dev_priv->gpu_error.stop_rings = 0; if (ret == -ENODEV) { - DRM_ERROR("Reset not implemented, but ignoring " - "error for simulated gpu hangs\n"); + DRM_INFO("Reset not implemented, but ignoring " + "error for simulated gpu hangs\n"); ret = 0; } } if (ret) { - DRM_ERROR("Failed to reset chip.\n"); + DRM_ERROR("Failed to reset chip: %i\n", ret); mutex_unlock(&dev->struct_mutex); return ret; } @@ -789,12 +790,9 @@ int i915_reset(struct drm_device *dev) */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->ums.mm_suspended) { - bool hw_contexts_disabled = dev_priv->hw_contexts_disabled; dev_priv->ums.mm_suspended = 0; ret = i915_gem_init_hw(dev); - if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled) - DRM_ERROR("HW contexts didn't survive reset\n"); mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("Failed hw init on reset %d\n", ret); @@ -830,17 +828,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (PCI_FUNC(pdev->devfn)) return -ENODEV; - /* We've managed to ship a kms-enabled ddx that shipped with an XvMC - * implementation for gen3 (and only gen3) that used legacy drm maps - * (gasp!) to share buffers between X and the client. Hence we need to - * keep around the fake agp stuff for gen3, even when kms is enabled. */ - if (intel_info->gen != 3) { - driver.driver_features &= - ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); - } else if (!intel_agp_enabled) { - DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); - return -ENODEV; - } + driver.driver_features &= ~(DRIVER_USE_AGP); return drm_get_pci_dev(pdev, ent, &driver); } @@ -948,7 +936,7 @@ static struct drm_driver driver = { * deal with them for Intel hardware. */ .driver_features = - DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | + DRIVER_USE_AGP | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER, .load = i915_driver_load, @@ -1023,14 +1011,24 @@ static int __init i915_init(void) driver.driver_features &= ~DRIVER_MODESET; #endif - if (!(driver.driver_features & DRIVER_MODESET)) + if (!(driver.driver_features & DRIVER_MODESET)) { driver.get_vblank_timestamp = NULL; +#ifndef CONFIG_DRM_I915_UMS + /* Silently fail loading to not upset userspace. */ + return 0; +#endif + } return drm_pci_init(&driver, &i915_pci_driver); } static void __exit i915_exit(void) { +#ifndef CONFIG_DRM_I915_UMS + if (!(driver.driver_features & DRIVER_MODESET)) + return; /* Never loaded a driver. */ +#endif + drm_pci_exit(&driver, &i915_pci_driver); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecca070d..780f815b6c9f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -89,6 +89,18 @@ enum port { }; #define port_name(p) ((p) + 'A') +#define I915_NUM_PHYS_VLV 1 + +enum dpio_channel { + DPIO_CH0, + DPIO_CH1 +}; + +enum dpio_phy { + DPIO_PHY0, + DPIO_PHY1 +}; + enum intel_display_power_domain { POWER_DOMAIN_PIPE_A, POWER_DOMAIN_PIPE_B, @@ -101,6 +113,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + POWER_DOMAIN_AUDIO, POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, @@ -351,6 +364,7 @@ struct drm_i915_error_state { enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS]; }; +struct intel_connector; struct intel_crtc_config; struct intel_crtc; struct intel_limit; @@ -413,11 +427,20 @@ struct drm_i915_display_funcs { /* render clock increase/decrease */ /* display clock increase/decrease */ /* pll clock increase/decrease */ + + int (*setup_backlight)(struct intel_connector *connector); + uint32_t (*get_backlight)(struct intel_connector *connector); + void (*set_backlight)(struct intel_connector *connector, + uint32_t level); + void (*disable_backlight)(struct intel_connector *connector); + void (*enable_backlight)(struct intel_connector *connector); }; struct intel_uncore_funcs { - void (*force_wake_get)(struct drm_i915_private *dev_priv); - void (*force_wake_put)(struct drm_i915_private *dev_priv); + void (*force_wake_get)(struct drm_i915_private *dev_priv, + int fw_engine); + void (*force_wake_put)(struct drm_i915_private *dev_priv, + int fw_engine); uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace); uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace); @@ -442,6 +465,9 @@ struct intel_uncore { unsigned fifo_count; unsigned forcewake_count; + unsigned fw_rendercount; + unsigned fw_mediacount; + struct delayed_work force_wake_work; }; @@ -708,7 +734,6 @@ enum intel_sbi_destination { #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) -#define QUIRK_NO_PCH_PWM_ENABLE (1<<3) struct intel_fbdev; struct intel_fbc_work; @@ -761,8 +786,6 @@ struct i915_suspend_saved_registers { u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; u32 saveBLC_HIST_CTL_B; - u32 saveBLC_PWM_CTL_B; - u32 saveBLC_PWM_CTL2_B; u32 saveBLC_CPU_PWM_CTL; u32 saveBLC_CPU_PWM_CTL2; u32 saveFPB0; @@ -932,21 +955,29 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { + const char *name; + bool always_on; /* power well enable/disable usage count */ int count; + unsigned long domains; + void *data; + void (*set)(struct drm_device *dev, struct i915_power_well *power_well, + bool enable); + bool (*is_enabled)(struct drm_device *dev, + struct i915_power_well *power_well); }; -#define I915_MAX_POWER_WELLS 1 - struct i915_power_domains { /* * Power wells needed for initialization at driver init and suspend * time are on. They are kept on until after the first modeset. */ bool init_power_on; + int power_well_count; struct mutex lock; - struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; + int domain_use_count[POWER_DOMAIN_NUM]; + struct i915_power_well *power_wells; }; struct i915_dri1_state { @@ -1077,34 +1108,30 @@ struct i915_gpu_error { unsigned long missed_irq_rings; /** - * State variable and reset counter controlling the reset flow + * State variable controlling the reset flow and count * - * Upper bits are for the reset counter. This counter is used by the - * wait_seqno code to race-free noticed that a reset event happened and - * that it needs to restart the entire ioctl (since most likely the - * seqno it waited for won't ever signal anytime soon). + * This is a counter which gets incremented when reset is triggered, + * and again when reset has been handled. So odd values (lowest bit set) + * means that reset is in progress and even values that + * (reset_counter >> 1):th reset was successfully completed. + * + * If reset is not completed succesfully, the I915_WEDGE bit is + * set meaning that hardware is terminally sour and there is no + * recovery. All waiters on the reset_queue will be woken when + * that happens. + * + * This counter is used by the wait_seqno code to notice that reset + * event happened and it needs to restart the entire ioctl (since most + * likely the seqno it waited for won't ever signal anytime soon). * * This is important for lock-free wait paths, where no contended lock * naturally enforces the correct ordering between the bail-out of the * waiter and the gpu reset work code. - * - * Lowest bit controls the reset state machine: Set means a reset is in - * progress. This state will (presuming we don't have any bugs) decay - * into either unset (successful reset) or the special WEDGED value (hw - * terminally sour). All waiters on the reset_queue will be woken when - * that happens. */ atomic_t reset_counter; - /** - * Special values/flags for reset_counter - * - * Note that the code relies on - * I915_WEDGED & I915_RESET_IN_PROGRESS_FLAG - * being true. - */ #define I915_RESET_IN_PROGRESS_FLAG 1 -#define I915_WEDGED 0xffffffff +#define I915_WEDGED (1 << 31) /** * Waitqueue to signal when the reset has completed. Used by clients @@ -1368,13 +1395,8 @@ typedef struct drm_i915_private { struct intel_overlay *overlay; unsigned int sprite_scaling_enabled; - /* backlight */ - struct { - int level; - bool enabled; - spinlock_t lock; /* bl registers and the above bl fields */ - struct backlight_device *device; - } backlight; + /* backlight registers and fields in struct intel_panel */ + spinlock_t backlight_lock; /* LVDS info */ bool no_aux_handshake; @@ -1426,6 +1448,7 @@ typedef struct drm_i915_private { int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; struct intel_ddi_plls ddi_plls; + int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; /* Reclocking support */ bool render_reclock_avail; @@ -1470,7 +1493,6 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - bool hw_contexts_disabled; uint32_t hw_context_size; struct list_head context_list; @@ -1755,8 +1777,13 @@ struct drm_i915_file_private { #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0C00) -#define IS_ULT(dev) (IS_HASWELL(dev) && \ +#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ + (((dev)->pdev->device & 0xf) == 0x2 || \ + ((dev)->pdev->device & 0xf) == 0x6 || \ + ((dev)->pdev->device & 0xf) == 0xe)) +#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0A00) +#define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) @@ -1813,7 +1840,6 @@ struct drm_i915_file_private { #define HAS_IPS(dev) (IS_ULT(dev) || IS_BROADWELL(dev)) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) -#define HAS_POWER_WELL(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */ @@ -1908,7 +1934,6 @@ extern void intel_pm_init(struct drm_device *dev); extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev); extern void intel_uncore_init(struct drm_device *dev); -extern void intel_uncore_clear_errors(struct drm_device *dev); extern void intel_uncore_check_errors(struct drm_device *dev); extern void intel_uncore_fini(struct drm_device *dev); @@ -2060,12 +2085,17 @@ int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, static inline bool i915_reset_in_progress(struct i915_gpu_error *error) { return unlikely(atomic_read(&error->reset_counter) - & I915_RESET_IN_PROGRESS_FLAG); + & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED)); } static inline bool i915_terminally_wedged(struct i915_gpu_error *error) { - return atomic_read(&error->reset_counter) == I915_WEDGED; + return atomic_read(&error->reset_counter) & I915_WEDGED; +} + +static inline u32 i915_reset_count(struct i915_gpu_error *error) +{ + return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2; } void i915_gem_reset(struct drm_device *dev); @@ -2177,7 +2207,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, } /* i915_gem_context.c */ -void i915_gem_context_init(struct drm_device *dev); +int __must_check i915_gem_context_init(struct drm_device *dev); void i915_gem_context_fini(struct drm_device *dev); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct intel_ring_buffer *ring, @@ -2395,6 +2425,8 @@ extern int intel_enable_rc6(const struct drm_device *dev); extern bool i915_semaphore_is_enabled(struct drm_device *dev); int i915_reg_read_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); /* overlay */ extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); @@ -2410,8 +2442,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, * must be set to prevent GT core from power down and stale values being * returned. */ -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine); +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine); int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val); int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); @@ -2426,6 +2458,8 @@ u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); +u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg); +void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg); @@ -2435,8 +2469,27 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, enum intel_sbi_destination destination); -int vlv_gpu_freq(int ddr_freq, int val); -int vlv_freq_opcode(int ddr_freq, int val); +int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); +int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); + +void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine); +void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine); + +#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \ + (((reg) >= 0x2000 && (reg) < 0x4000) ||\ + ((reg) >= 0x5000 && (reg) < 0x8000) ||\ + ((reg) >= 0xB000 && (reg) < 0x12000) ||\ + ((reg) >= 0x2E000 && (reg) < 0x30000)) + +#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\ + (((reg) >= 0x12000 && (reg) < 0x14000) ||\ + ((reg) >= 0x22000 && (reg) < 0x24000) ||\ + ((reg) >= 0x30000 && (reg) < 0x40000)) + +#define FORCEWAKE_RENDER (1 << 0) +#define FORCEWAKE_MEDIA (1 << 1) +#define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA) + #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 621c7c67a643..182c521ec392 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4465,7 +4465,13 @@ i915_gem_init_hw(struct drm_device *dev) * XXX: There was some w/a described somewhere suggesting loading * contexts before PPGTT. */ - i915_gem_context_init(dev); + ret = i915_gem_context_init(dev); + if (ret) { + i915_gem_cleanup_ringbuffer(dev); + DRM_ERROR("Context initialization failed %d\n", ret); + return ret; + } + if (dev_priv->mm.aliasing_ppgtt) { ret = dev_priv->mm.aliasing_ppgtt->enable(dev); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 72a3df32292f..41877045a1a0 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -247,36 +247,34 @@ err_destroy: return ret; } -void i915_gem_context_init(struct drm_device *dev) +int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + int ret; - if (!HAS_HW_CONTEXTS(dev)) { - dev_priv->hw_contexts_disabled = true; - DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n"); - return; - } + if (!HAS_HW_CONTEXTS(dev)) + return 0; /* If called from reset, or thaw... we've been here already */ - if (dev_priv->hw_contexts_disabled || - dev_priv->ring[RCS].default_context) - return; + if (dev_priv->ring[RCS].default_context) + return 0; dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); if (dev_priv->hw_context_size > (1<<20)) { - dev_priv->hw_contexts_disabled = true; DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); - return; + return -E2BIG; } - if (create_default_context(dev_priv)) { - dev_priv->hw_contexts_disabled = true; - DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n"); - return; + ret = create_default_context(dev_priv); + if (ret) { + DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n", + ret); + return ret; } DRM_DEBUG_DRIVER("HW context support initialized\n"); + return 0; } void i915_gem_context_fini(struct drm_device *dev) @@ -284,7 +282,7 @@ void i915_gem_context_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(dev)) return; /* The only known way to stop the gpu from accessing the hw context is @@ -327,16 +325,16 @@ i915_gem_context_get_hang_stats(struct drm_device *dev, struct drm_file *file, u32 id) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; if (id == DEFAULT_CONTEXT_ID) return &file_priv->hang_stats; - ctx = NULL; - if (!dev_priv->hw_contexts_disabled) - ctx = i915_gem_context_get(file->driver_priv, id); + if (!HAS_HW_CONTEXTS(dev)) + return ERR_PTR(-ENOENT); + + ctx = i915_gem_context_get(file->driver_priv, id); if (ctx == NULL) return ERR_PTR(-ENOENT); @@ -494,8 +492,6 @@ static int do_switch(struct i915_hw_context *to) * @ring: ring for which we'll execute the context switch * @file_priv: file_priv associated with the context, may be NULL * @id: context id number - * @seqno: sequence number by which the new context will be switched to - * @flags: * * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, @@ -509,7 +505,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_i915_private *dev_priv = ring->dev->dev_private; struct i915_hw_context *to; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(ring->dev)) return 0; WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); @@ -534,7 +530,6 @@ int i915_switch_context(struct intel_ring_buffer *ring, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_context_create *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; @@ -543,7 +538,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(dev)) return -ENODEV; ret = i915_mutex_lock_interruptible(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b7e787fb4649..3c90dd1a3bbd 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -46,7 +46,7 @@ struct eb_vmas { }; static struct eb_vmas * -eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm) +eb_create(struct drm_i915_gem_execbuffer2 *args) { struct eb_vmas *eb = NULL; @@ -332,7 +332,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = target_vma->obj; target_obj = &target_vma->obj->base; - target_offset = i915_gem_obj_ggtt_offset(target_i915_obj); + target_offset = target_vma->node.start; /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and * pipe_control writes because the gpu doesn't properly redirect them @@ -479,8 +479,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma, } static int -i915_gem_execbuffer_relocate(struct eb_vmas *eb, - struct i915_address_space *vm) +i915_gem_execbuffer_relocate(struct eb_vmas *eb) { struct i915_vma *vma; int ret = 0; @@ -1106,7 +1105,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } - eb = eb_create(args, vm); + eb = eb_create(args); if (eb == NULL) { mutex_unlock(&dev->struct_mutex); ret = -ENOMEM; @@ -1129,7 +1128,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, /* The objects are in their final locations, apply the relocations. */ if (need_relocs) - ret = i915_gem_execbuffer_relocate(eb, vm); + ret = i915_gem_execbuffer_relocate(eb); if (ret) { if (ret == -EFAULT) { ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 38cb8d44a013..a54eaabb3a3e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -240,10 +240,16 @@ static int gen8_ppgtt_enable(struct drm_device *dev) for_each_ring(ring, dev_priv, j) { ret = gen8_write_pdp(ring, i, addr); if (ret) - return ret; + goto err_out; } } return 0; + +err_out: + for_each_ring(ring, dev_priv, j) + I915_WRITE(RING_MODE_GEN7(ring), + _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE)); + return ret; } static void gen8_ppgtt_clear_range(struct i915_address_space *vm, @@ -318,6 +324,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) container_of(vm, struct i915_hw_ppgtt, base); int i, j; + drm_mm_takedown(&vm->mm); + for (i = 0; i < ppgtt->num_pd_pages ; i++) { if (ppgtt->pd_dma_addr[i]) { pci_unmap_page(ppgtt->base.dev->pdev, @@ -337,8 +345,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) kfree(ppgtt->gen8_pt_dma_addr[i]); } - __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT); - __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT); + __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT)); + __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT)); } /** @@ -381,6 +389,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.cleanup = gen8_ppgtt_cleanup; + ppgtt->base.start = 0; + ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE; BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS); @@ -632,6 +642,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.scratch = dev_priv->gtt.base.scratch; + ppgtt->base.start = 0; + ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE; ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *), GFP_KERNEL); if (!ppgtt->pt_pages) @@ -1126,7 +1138,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, if (ret) DRM_DEBUG_KMS("Reservation failed\n"); obj->has_global_gtt_mapping = 1; - list_add(&vma->vma_link, &obj->vma_list); } dev_priv->gtt.base.start = start; @@ -1241,6 +1252,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; if (bdw_gmch_ctl) bdw_gmch_ctl = 1 << bdw_gmch_ctl; + if (bdw_gmch_ctl > 4) { + WARN_ON(!i915_preliminary_hw_support); + return 4<<20; + } + return bdw_gmch_ctl << 20; } @@ -1397,6 +1413,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm) { struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); + + drm_mm_takedown(&vm->mm); iounmap(gtt->gsm); teardown_scratch_page(vm->dev); } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d1dedc02f15..271560080ad5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -600,7 +600,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) * Cook up a vblank counter by also checking the pixel * counter against vblank start. */ - return ((high1 << 8) | low) + (pixel >= vbl_start); + return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; } static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) @@ -1015,10 +1015,8 @@ static void gen6_pm_rps_work(struct work_struct *work) /* sysfs frequency interfaces may have snuck in while servicing the * interrupt */ - if (new_delay < (int)dev_priv->rps.min_delay) - new_delay = dev_priv->rps.min_delay; - if (new_delay > (int)dev_priv->rps.max_delay) - new_delay = dev_priv->rps.max_delay; + new_delay = clamp_t(int, new_delay, + dev_priv->rps.min_delay, dev_priv->rps.max_delay); dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay; if (IS_VALLEYVIEW(dev_priv->dev)) @@ -1474,6 +1472,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915); + if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) + dp_aux_irq_handler(dev); + I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); } @@ -1993,7 +1994,7 @@ static void i915_error_work_func(struct work_struct *work) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, reset_done_event); } else { - atomic_set(&error->reset_counter, I915_WEDGED); + atomic_set_mask(I915_WEDGED, &error->reset_counter); } /* @@ -3655,6 +3656,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) intel_hpd_irq_handler(dev, hotplug_trigger, IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915); + if (IS_G4X(dev) && + (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)) + dp_aux_irq_handler(dev); + I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ee2742122a02..3be449d884a7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -354,6 +354,7 @@ #define IOSF_BYTE_ENABLES_SHIFT 4 #define IOSF_BAR_SHIFT 1 #define IOSF_SB_BUSY (1<<0) +#define IOSF_PORT_BUNIT 0x3 #define IOSF_PORT_PUNIT 0x4 #define IOSF_PORT_NC 0x11 #define IOSF_PORT_DPIO 0x12 @@ -364,9 +365,17 @@ #define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108) +/* See configdb bunit SB addr map */ +#define BUNIT_REG_BISOC 0x11 + #define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_WRITE 7 +#define PUNIT_REG_DSPFREQ 0x36 +#define DSPFREQSTAT_SHIFT 30 +#define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT) +#define DSPFREQGUAR_SHIFT 14 +#define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT) #define PUNIT_REG_PWRGT_CTRL 0x60 #define PUNIT_REG_PWRGT_STATUS 0x61 #define PUNIT_CLK_GATE 1 @@ -429,6 +438,7 @@ #define DSI_PLL_N1_DIV_MASK (3 << 16) #define DSI_PLL_M1_DIV_SHIFT 0 #define DSI_PLL_M1_DIV_MASK (0x1ff << 0) +#define CCK_DISPLAY_CLOCK_CONTROL 0x6b /* * DPIO - a special bus for various display related registers to hide behind @@ -447,15 +457,13 @@ #define DPIO_SFR_BYPASS (1<<1) #define DPIO_CMNRST (1<<0) -#define _DPIO_TX3_SWING_CTL4_A 0x690 -#define _DPIO_TX3_SWING_CTL4_B 0x2a90 -#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \ - _DPIO_TX3_SWING_CTL4_B) +#define DPIO_PHY(pipe) ((pipe) >> 1) +#define DPIO_PHY_IOSF_PORT(phy) (dev_priv->dpio_phy_iosf_port[phy]) /* * Per pipe/PLL DPIO regs */ -#define _DPIO_DIV_A 0x800c +#define _VLV_PLL_DW3_CH0 0x800c #define DPIO_POST_DIV_SHIFT (28) /* 3 bits */ #define DPIO_POST_DIV_DAC 0 #define DPIO_POST_DIV_HDMIDP 1 /* DAC 225-400M rate */ @@ -468,10 +476,10 @@ #define DPIO_ENABLE_CALIBRATION (1<<11) #define DPIO_M1DIV_SHIFT (8) /* 3 bits */ #define DPIO_M2DIV_MASK 0xff -#define _DPIO_DIV_B 0x802c -#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B) +#define _VLV_PLL_DW3_CH1 0x802c +#define VLV_PLL_DW3(ch) _PIPE(ch, _VLV_PLL_DW3_CH0, _VLV_PLL_DW3_CH1) -#define _DPIO_REFSFR_A 0x8014 +#define _VLV_PLL_DW5_CH0 0x8014 #define DPIO_REFSEL_OVERRIDE 27 #define DPIO_PLL_MODESEL_SHIFT 24 /* 3 bits */ #define DPIO_BIAS_CURRENT_CTL_SHIFT 21 /* 3 bits, always 0x7 */ @@ -479,118 +487,112 @@ #define DPIO_PLL_REFCLK_SEL_MASK 3 #define DPIO_DRIVER_CTL_SHIFT 12 /* always set to 0x8 */ #define DPIO_CLK_BIAS_CTL_SHIFT 8 /* always set to 0x5 */ -#define _DPIO_REFSFR_B 0x8034 -#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B) +#define _VLV_PLL_DW5_CH1 0x8034 +#define VLV_PLL_DW5(ch) _PIPE(ch, _VLV_PLL_DW5_CH0, _VLV_PLL_DW5_CH1) -#define _DPIO_CORE_CLK_A 0x801c -#define _DPIO_CORE_CLK_B 0x803c -#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) +#define _VLV_PLL_DW7_CH0 0x801c +#define _VLV_PLL_DW7_CH1 0x803c +#define VLV_PLL_DW7(ch) _PIPE(ch, _VLV_PLL_DW7_CH0, _VLV_PLL_DW7_CH1) -#define _DPIO_IREF_CTL_A 0x8040 -#define _DPIO_IREF_CTL_B 0x8060 -#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B) +#define _VLV_PLL_DW8_CH0 0x8040 +#define _VLV_PLL_DW8_CH1 0x8060 +#define VLV_PLL_DW8(ch) _PIPE(ch, _VLV_PLL_DW8_CH0, _VLV_PLL_DW8_CH1) -#define DPIO_IREF_BCAST 0xc044 -#define _DPIO_IREF_A 0x8044 -#define _DPIO_IREF_B 0x8064 -#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B) +#define VLV_PLL_DW9_BCAST 0xc044 +#define _VLV_PLL_DW9_CH0 0x8044 +#define _VLV_PLL_DW9_CH1 0x8064 +#define VLV_PLL_DW9(ch) _PIPE(ch, _VLV_PLL_DW9_CH0, _VLV_PLL_DW9_CH1) -#define _DPIO_PLL_CML_A 0x804c -#define _DPIO_PLL_CML_B 0x806c -#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B) +#define _VLV_PLL_DW10_CH0 0x8048 +#define _VLV_PLL_DW10_CH1 0x8068 +#define VLV_PLL_DW10(ch) _PIPE(ch, _VLV_PLL_DW10_CH0, _VLV_PLL_DW10_CH1) -#define _DPIO_LPF_COEFF_A 0x8048 -#define _DPIO_LPF_COEFF_B 0x8068 -#define DPIO_LPF_COEFF(pipe) _PIPE(pipe, _DPIO_LPF_COEFF_A, _DPIO_LPF_COEFF_B) +#define _VLV_PLL_DW11_CH0 0x804c +#define _VLV_PLL_DW11_CH1 0x806c +#define VLV_PLL_DW11(ch) _PIPE(ch, _VLV_PLL_DW11_CH0, _VLV_PLL_DW11_CH1) -#define DPIO_CALIBRATION 0x80ac +/* Spec for ref block start counts at DW10 */ +#define VLV_REF_DW13 0x80ac -#define DPIO_FASTCLK_DISABLE 0x8100 +#define VLV_CMN_DW0 0x8100 /* * Per DDI channel DPIO regs */ -#define _DPIO_PCS_TX_0 0x8200 -#define _DPIO_PCS_TX_1 0x8400 +#define _VLV_PCS_DW0_CH0 0x8200 +#define _VLV_PCS_DW0_CH1 0x8400 #define DPIO_PCS_TX_LANE2_RESET (1<<16) #define DPIO_PCS_TX_LANE1_RESET (1<<7) -#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1) +#define VLV_PCS_DW0(ch) _PORT(ch, _VLV_PCS_DW0_CH0, _VLV_PCS_DW0_CH1) -#define _DPIO_PCS_CLK_0 0x8204 -#define _DPIO_PCS_CLK_1 0x8404 +#define _VLV_PCS_DW1_CH0 0x8204 +#define _VLV_PCS_DW1_CH1 0x8404 #define DPIO_PCS_CLK_CRI_RXEB_EIOS_EN (1<<22) #define DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21) #define DPIO_PCS_CLK_DATAWIDTH_SHIFT (6) #define DPIO_PCS_CLK_SOFT_RESET (1<<5) -#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1) - -#define _DPIO_PCS_CTL_OVR1_A 0x8224 -#define _DPIO_PCS_CTL_OVR1_B 0x8424 -#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \ - _DPIO_PCS_CTL_OVR1_B) - -#define _DPIO_PCS_STAGGER0_A 0x822c -#define _DPIO_PCS_STAGGER0_B 0x842c -#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \ - _DPIO_PCS_STAGGER0_B) - -#define _DPIO_PCS_STAGGER1_A 0x8230 -#define _DPIO_PCS_STAGGER1_B 0x8430 -#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \ - _DPIO_PCS_STAGGER1_B) - -#define _DPIO_PCS_CLOCKBUF0_A 0x8238 -#define _DPIO_PCS_CLOCKBUF0_B 0x8438 -#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \ - _DPIO_PCS_CLOCKBUF0_B) - -#define _DPIO_PCS_CLOCKBUF8_A 0x825c -#define _DPIO_PCS_CLOCKBUF8_B 0x845c -#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \ - _DPIO_PCS_CLOCKBUF8_B) - -#define _DPIO_TX_SWING_CTL2_A 0x8288 -#define _DPIO_TX_SWING_CTL2_B 0x8488 -#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \ - _DPIO_TX_SWING_CTL2_B) - -#define _DPIO_TX_SWING_CTL3_A 0x828c -#define _DPIO_TX_SWING_CTL3_B 0x848c -#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \ - _DPIO_TX_SWING_CTL3_B) - -#define _DPIO_TX_SWING_CTL4_A 0x8290 -#define _DPIO_TX_SWING_CTL4_B 0x8490 -#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \ - _DPIO_TX_SWING_CTL4_B) - -#define _DPIO_TX_OCALINIT_0 0x8294 -#define _DPIO_TX_OCALINIT_1 0x8494 +#define VLV_PCS_DW1(ch) _PORT(ch, _VLV_PCS_DW1_CH0, _VLV_PCS_DW1_CH1) + +#define _VLV_PCS_DW8_CH0 0x8220 +#define _VLV_PCS_DW8_CH1 0x8420 +#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1) + +#define _VLV_PCS01_DW8_CH0 0x0220 +#define _VLV_PCS23_DW8_CH0 0x0420 +#define _VLV_PCS01_DW8_CH1 0x2620 +#define _VLV_PCS23_DW8_CH1 0x2820 +#define VLV_PCS01_DW8(port) _PORT(port, _VLV_PCS01_DW8_CH0, _VLV_PCS01_DW8_CH1) +#define VLV_PCS23_DW8(port) _PORT(port, _VLV_PCS23_DW8_CH0, _VLV_PCS23_DW8_CH1) + +#define _VLV_PCS_DW9_CH0 0x8224 +#define _VLV_PCS_DW9_CH1 0x8424 +#define VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1) + +#define _VLV_PCS_DW11_CH0 0x822c +#define _VLV_PCS_DW11_CH1 0x842c +#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1) + +#define _VLV_PCS_DW12_CH0 0x8230 +#define _VLV_PCS_DW12_CH1 0x8430 +#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1) + +#define _VLV_PCS_DW14_CH0 0x8238 +#define _VLV_PCS_DW14_CH1 0x8438 +#define VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1) + +#define _VLV_PCS_DW23_CH0 0x825c +#define _VLV_PCS_DW23_CH1 0x845c +#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1) + +#define _VLV_TX_DW2_CH0 0x8288 +#define _VLV_TX_DW2_CH1 0x8488 +#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1) + +#define _VLV_TX_DW3_CH0 0x828c +#define _VLV_TX_DW3_CH1 0x848c +#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1) + +#define _VLV_TX_DW4_CH0 0x8290 +#define _VLV_TX_DW4_CH1 0x8490 +#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1) + +#define _VLV_TX3_DW4_CH0 0x690 +#define _VLV_TX3_DW4_CH1 0x2a90 +#define VLV_TX3_DW4(ch) _PORT(ch, _VLV_TX3_DW4_CH0, _VLV_TX3_DW4_CH1) + +#define _VLV_TX_DW5_CH0 0x8294 +#define _VLV_TX_DW5_CH1 0x8494 #define DPIO_TX_OCALINIT_EN (1<<31) -#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \ - _DPIO_TX_OCALINIT_1) - -#define _DPIO_TX_CTL_0 0x82ac -#define _DPIO_TX_CTL_1 0x84ac -#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1) - -#define _DPIO_TX_LANE_0 0x82b8 -#define _DPIO_TX_LANE_1 0x84b8 -#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1) - -#define _DPIO_DATA_CHANNEL1 0x8220 -#define _DPIO_DATA_CHANNEL2 0x8420 -#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2) - -#define _DPIO_PORT0_PCS0 0x0220 -#define _DPIO_PORT0_PCS1 0x0420 -#define _DPIO_PORT1_PCS2 0x2620 -#define _DPIO_PORT1_PCS3 0x2820 -#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2) -#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3) -#define DPIO_DATA_CHANNEL1 0x8220 -#define DPIO_DATA_CHANNEL2 0x8420 +#define VLV_TX_DW5(ch) _PORT(ch, _VLV_TX_DW5_CH0, _VLV_TX_DW5_CH1) + +#define _VLV_TX_DW11_CH0 0x82ac +#define _VLV_TX_DW11_CH1 0x84ac +#define VLV_TX_DW11(ch) _PORT(ch, _VLV_TX_DW11_CH0, _VLV_TX_DW11_CH1) + +#define _VLV_TX_DW14_CH0 0x82b8 +#define _VLV_TX_DW14_CH1 0x84b8 +#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1) /* * Fence registers @@ -2130,6 +2132,10 @@ #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +#define DP_AUX_CHANNEL_D_INT_STATUS_G4X (1 << 6) +#define DP_AUX_CHANNEL_C_INT_STATUS_G4X (1 << 5) +#define DP_AUX_CHANNEL_B_INT_STATUS_G4X (1 << 4) +#define DP_AUX_CHANNEL_MASK_INT_STATUS_G4X (1 << 4) /* SDVO is different across gen3/4 */ #define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) #define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) @@ -3787,7 +3793,7 @@ #define _SPACNTR (VLV_DISPLAY_BASE + 0x72180) #define SP_ENABLE (1<<31) -#define SP_GEAMMA_ENABLE (1<<30) +#define SP_GAMMA_ENABLE (1<<30) #define SP_PIXFORMAT_MASK (0xf<<26) #define SP_FORMAT_YUV422 (0<<26) #define SP_FORMAT_BGR565 (5<<26) @@ -4851,12 +4857,16 @@ #define FORCEWAKE_MT_ENABLE (1<<5) #define GTFIFODBG 0x120000 -#define GT_FIFO_CPU_ERROR_MASK 7 +#define GT_FIFO_SBDROPERR (1<<6) +#define GT_FIFO_BLOBDROPERR (1<<5) +#define GT_FIFO_SB_READ_ABORTERR (1<<4) +#define GT_FIFO_DROPERR (1<<3) #define GT_FIFO_OVFERR (1<<2) #define GT_FIFO_IAWRERR (1<<1) #define GT_FIFO_IARDERR (1<<0) -#define GT_FIFO_FREE_ENTRIES 0x120008 +#define GTFIFOCTL 0x120008 +#define GT_FIFO_FREE_ENTRIES_MASK 0x7f #define GT_FIFO_NUM_RESERVED_ENTRIES 20 #define HSW_IDICR 0x9008 @@ -4890,6 +4900,7 @@ #define GEN6_RC_CTL_RC6_ENABLE (1<<18) #define GEN6_RC_CTL_RC1e_ENABLE (1<<20) #define GEN6_RC_CTL_RC7_ENABLE (1<<22) +#define VLV_RC_CTL_CTX_RST_PARALLEL (1<<24) #define GEN7_RC_CTL_TO_MODE (1<<28) #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) #define GEN6_RC_CTL_HW_ENABLE (1<<31) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 98790c7cccb1..6b8fef7fb3bb 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -192,7 +192,6 @@ static void i915_restore_vga(struct drm_device *dev) static void i915_save_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long flags; /* Display arbitration control */ if (INTEL_INFO(dev)->gen <= 4) @@ -203,46 +202,27 @@ static void i915_save_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_save_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); - /* LVDS state */ if (HAS_PCH_SPLIT(dev)) { dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL); - dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); - dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); - dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); - dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS); } else if (IS_VALLEYVIEW(dev)) { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->regfile.saveBLC_PWM_CTL = - I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(VLV_BLC_HIST_CTL(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL_B = - I915_READ(VLV_BLC_PWM_CTL(PIPE_B)); dev_priv->regfile.saveBLC_HIST_CTL_B = I915_READ(VLV_BLC_HIST_CTL(PIPE_B)); - dev_priv->regfile.saveBLC_PWM_CTL2_B = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_B)); } else { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); - if (INTEL_INFO(dev)->gen >= 4) - dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); if (IS_MOBILE(dev) && !IS_I830(dev)) dev_priv->regfile.saveLVDS = I915_READ(LVDS); } - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); - if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL); @@ -278,7 +258,6 @@ static void i915_restore_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 mask = 0xffffffff; - unsigned long flags; /* Display arbitration */ if (INTEL_INFO(dev)->gen <= 4) @@ -287,12 +266,6 @@ static void i915_restore_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_restore_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); - - /* LVDS state */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); - if (drm_core_check_feature(dev, DRIVER_MODESET)) mask = ~LVDS_PORT_EN; @@ -305,13 +278,6 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL); if (HAS_PCH_SPLIT(dev)) { - I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL); - I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); - /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2; - * otherwise we get blank eDP screen after S3 on some machines - */ - I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2); - I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL); I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); @@ -319,21 +285,12 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(RSTDBYCTL, dev_priv->regfile.saveMCHBAR_RENDER_STANDBY); } else if (IS_VALLEYVIEW(dev)) { - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A), dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL2); - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B), dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL2); } else { I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS); - I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL); I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); @@ -341,8 +298,6 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL); } - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); - /* only restore FBC info on the platform that supports FBC*/ intel_disable_fbc(dev); if (I915_HAS_FBC(dev)) { diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index cef38fd320a7..05d8b1680c22 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -183,13 +183,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj, int slice = (int)(uintptr_t)attr->private; int ret; + if (!HAS_HW_CONTEXTS(drm_dev)) + return -ENXIO; + ret = l3_access_valid(drm_dev, offset); if (ret) return ret; - if (dev_priv->hw_contexts_disabled) - return -ENXIO; - ret = i915_mutex_lock_interruptible(drm_dev); if (ret) return ret; @@ -259,7 +259,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, if (IS_VALLEYVIEW(dev_priv->dev)) { u32 freq; freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff); + ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff); } else { ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; } @@ -276,8 +276,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, struct drm_i915_private *dev_priv = dev->dev_private; return snprintf(buf, PAGE_SIZE, "%d\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay)); + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay)); } static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) @@ -291,7 +290,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) - ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay); + ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay); else ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -318,7 +317,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); hw_max = valleyview_rps_max_freq(dev_priv); hw_min = valleyview_rps_min_freq(dev_priv); @@ -342,15 +341,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, DRM_DEBUG("User requested overclocking to %d\n", val * GT_FREQUENCY_MULTIPLIER); + dev_priv->rps.max_delay = val; + if (dev_priv->rps.cur_delay > val) { - if (IS_VALLEYVIEW(dev_priv->dev)) - valleyview_set_rps(dev_priv->dev, val); + if (IS_VALLEYVIEW(dev)) + valleyview_set_rps(dev, val); else - gen6_set_rps(dev_priv->dev, val); + gen6_set_rps(dev, val); } - dev_priv->rps.max_delay = val; - mutex_unlock(&dev_priv->rps.hw_lock); return count; @@ -367,7 +366,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) - ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay); + ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay); else ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -394,7 +393,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); hw_max = valleyview_rps_max_freq(dev_priv); hw_min = valleyview_rps_min_freq(dev_priv); @@ -411,15 +410,15 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, return -EINVAL; } + dev_priv->rps.min_delay = val; + if (dev_priv->rps.cur_delay < val) { if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev, val); else - gen6_set_rps(dev_priv->dev, val); + gen6_set_rps(dev, val); } - dev_priv->rps.min_delay = val; - mutex_unlock(&dev_priv->rps.hw_lock); return count; diff --git a/drivers/gpu/drm/i915/i915_ums.c b/drivers/gpu/drm/i915/i915_ums.c index 967da4772c44..caa18e855815 100644 --- a/drivers/gpu/drm/i915/i915_ums.c +++ b/drivers/gpu/drm/i915/i915_ums.c @@ -270,6 +270,18 @@ void i915_save_display_reg(struct drm_device *dev) } /* FIXME: regfile.save TV & SDVO state */ + /* Backlight */ + if (HAS_PCH_SPLIT(dev)) { + dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); + dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); + dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); + } else { + dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + if (INTEL_INFO(dev)->gen >= 4) + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); + } + return; } @@ -280,6 +292,21 @@ void i915_restore_display_reg(struct drm_device *dev) int dpll_b_reg, fpb0_reg, fpb1_reg; int i; + /* Backlight */ + if (HAS_PCH_SPLIT(dev)) { + I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL); + I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); + /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2; + * otherwise we get blank eDP screen after S3 on some machines + */ + I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL); + } else { + if (INTEL_INFO(dev)->gen >= 4) + I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); + } + /* Display port ratios (must be done before clock is set) */ if (SUPPORTS_INTEGRATED_DP(dev)) { I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index b5b1b9b23adf..e2e39e65f109 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -222,8 +222,9 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_crt_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 526c8ded16b0..c8382f55870c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -713,8 +713,6 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) uint32_t reg, val; int clock = intel_crtc->config.port_clock; - /* TODO: reuse PLLs when possible (compare values) */ - intel_ddi_put_crtc_pll(crtc); if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { @@ -742,31 +740,40 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) } else if (type == INTEL_OUTPUT_HDMI) { unsigned p, n2, r2; - if (plls->wrpll1_refcount == 0) { + intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); + + val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | + WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | + WRPLL_DIVIDER_POST(p); + + if (val == I915_READ(WRPLL_CTL1)) { + DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n", + pipe_name(pipe)); + reg = WRPLL_CTL1; + } else if (val == I915_READ(WRPLL_CTL2)) { + DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n", + pipe_name(pipe)); + reg = WRPLL_CTL2; + } else if (plls->wrpll1_refcount == 0) { DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", pipe_name(pipe)); - plls->wrpll1_refcount++; reg = WRPLL_CTL1; - intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; } else if (plls->wrpll2_refcount == 0) { DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", pipe_name(pipe)); - plls->wrpll2_refcount++; reg = WRPLL_CTL2; - intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; } else { DRM_ERROR("No WRPLLs available!\n"); return false; } - WARN(I915_READ(reg) & WRPLL_PLL_ENABLE, - "WRPLL already enabled\n"); - - intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); - - val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | - WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | - WRPLL_DIVIDER_POST(p); + if (reg == WRPLL_CTL1) { + plls->wrpll1_refcount++; + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; + } else { + plls->wrpll2_refcount++; + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; + } } else if (type == INTEL_OUTPUT_ANALOG) { if (plls->spll_refcount == 0) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd4e839..0bb3d6d596d9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -748,10 +748,10 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, return intel_crtc->config.cpu_transcoder; } -static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) +static void g4x_wait_for_vblank(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 frame, frame_reg = PIPEFRAME(pipe); + u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe); frame = I915_READ(frame_reg); @@ -772,8 +772,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = dev->dev_private; int pipestat_reg = PIPESTAT(pipe); - if (INTEL_INFO(dev)->gen >= 5) { - ironlake_wait_for_vblank(dev, pipe); + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + g4x_wait_for_vblank(dev, pipe); return; } @@ -1361,6 +1361,7 @@ static void intel_init_dpio(struct drm_device *dev) if (!IS_VALLEYVIEW(dev)) return; + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; /* * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - * 6. De-assert cmn_reset/side_reset. Same as VLV X0. @@ -1494,18 +1495,25 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) POSTING_READ(DPLL(pipe)); } -void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) +void vlv_wait_port_ready(struct drm_i915_private *dev_priv, + struct intel_digital_port *dport) { u32 port_mask; - if (!port) + switch (dport->port) { + case PORT_B: port_mask = DPLL_PORTB_READY_MASK; - else + break; + case PORT_C: port_mask = DPLL_PORTC_READY_MASK; + break; + default: + BUG(); + } if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) WARN(1, "timed out waiting for port %c ready: 0x%08x\n", - 'B' + port, I915_READ(DPLL(0))); + port_name(dport->port), I915_READ(DPLL(0))); } /** @@ -2233,7 +2241,12 @@ void intel_display_handle_reset(struct drm_device *dev) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); mutex_lock(&crtc->mutex); - if (intel_crtc->active) + /* + * FIXME: Once we have proper support for primary planes (and + * disabling them without disabling the entire crtc) allow again + * a NULL crtc->fb. + */ + if (intel_crtc->active && crtc->fb) dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, crtc->y); mutex_unlock(&crtc->mutex); @@ -3910,6 +3923,174 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } +int valleyview_get_vco(struct drm_i915_private *dev_priv) +{ + int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; + + /* Obtain SKU information */ + mutex_lock(&dev_priv->dpio_lock); + hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) & + CCK_FUSE_HPLL_FREQ_MASK; + mutex_unlock(&dev_priv->dpio_lock); + + return vco_freq[hpll_freq]; +} + +/* Adjust CDclk dividers to allow high res or save power if possible */ +static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val, cmd; + + if (cdclk >= 320) /* jump to highest voltage for 400MHz too */ + cmd = 2; + else if (cdclk == 266) + cmd = 1; + else + cmd = 0; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); + val &= ~DSPFREQGUAR_MASK; + val |= (cmd << DSPFREQGUAR_SHIFT); + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val); + if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & + DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), + 50)) { + DRM_ERROR("timed out waiting for CDclk change\n"); + } + mutex_unlock(&dev_priv->rps.hw_lock); + + if (cdclk == 400) { + u32 divider, vco; + + vco = valleyview_get_vco(dev_priv); + divider = ((vco << 1) / cdclk) - 1; + + mutex_lock(&dev_priv->dpio_lock); + /* adjust cdclk divider */ + val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + val &= ~0xf; + val |= divider; + vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val); + mutex_unlock(&dev_priv->dpio_lock); + } + + mutex_lock(&dev_priv->dpio_lock); + /* adjust self-refresh exit latency value */ + val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC); + val &= ~0x7f; + + /* + * For high bandwidth configs, we set a higher latency in the bunit + * so that the core display fetch happens in time to avoid underruns. + */ + if (cdclk == 400) + val |= 4500 / 250; /* 4.5 usec */ + else + val |= 3000 / 250; /* 3.0 usec */ + vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); + mutex_unlock(&dev_priv->dpio_lock); + + /* Since we changed the CDclk, we need to update the GMBUSFREQ too */ + intel_i2c_reset(dev); +} + +static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) +{ + int cur_cdclk, vco; + int divider; + + vco = valleyview_get_vco(dev_priv); + + mutex_lock(&dev_priv->dpio_lock); + divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + mutex_unlock(&dev_priv->dpio_lock); + + divider &= 0xf; + + cur_cdclk = (vco << 1) / (divider + 1); + + return cur_cdclk; +} + +static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, + int max_pixclk) +{ + int cur_cdclk; + + cur_cdclk = valleyview_cur_cdclk(dev_priv); + + /* + * Really only a few cases to deal with, as only 4 CDclks are supported: + * 200MHz + * 267MHz + * 320MHz + * 400MHz + * So we check to see whether we're above 90% of the lower bin and + * adjust if needed. + */ + if (max_pixclk > 288000) { + return 400; + } else if (max_pixclk > 240000) { + return 320; + } else + return 266; + /* Looks like the 200MHz CDclk freq doesn't work on some configs */ +} + +static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv, + unsigned modeset_pipes, + struct intel_crtc_config *pipe_config) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *intel_crtc; + int max_pixclk = 0; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) { + if (modeset_pipes & (1 << intel_crtc->pipe)) + max_pixclk = max(max_pixclk, + pipe_config->adjusted_mode.crtc_clock); + else if (intel_crtc->base.enabled) + max_pixclk = max(max_pixclk, + intel_crtc->config.adjusted_mode.crtc_clock); + } + + return max_pixclk; +} + +static void valleyview_modeset_global_pipes(struct drm_device *dev, + unsigned *prepare_pipes, + unsigned modeset_pipes, + struct intel_crtc_config *pipe_config) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc; + int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes, + pipe_config); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + + if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk) + return; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) + if (intel_crtc->base.enabled) + *prepare_pipes |= (1 << intel_crtc->pipe); +} + +static void valleyview_modeset_global_resources(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + + if (req_cdclk != cur_cdclk) + valleyview_set_cdclk(dev, req_cdclk); +} + static void valleyview_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -4634,24 +4815,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); reg_val &= 0xffffff00; reg_val |= 0x00000030; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); reg_val &= 0x8cffffff; reg_val = 0x8c000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); reg_val &= 0xffffff00; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); reg_val &= 0x00ffffff; reg_val |= 0xb0000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); } static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc, @@ -4720,15 +4901,15 @@ static void vlv_update_pll(struct intel_crtc *crtc) vlv_pllb_recal_opamp(dev_priv, pipe); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe)); reg_val &= 0x00ffffff; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val); /* Disable fast lock */ - vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610); + vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610); /* Set idtafcrecal before PLL is enabled */ mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); @@ -4742,48 +4923,48 @@ static void vlv_update_pll(struct intel_crtc *crtc) * Note: don't use the DAC post divider as it seems unstable. */ mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); mdiv |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); /* Set HBR and RBR LPF coefficients */ if (crtc->config.port_clock == 162000 || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), 0x009f0003); else - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), 0x00d0000f); if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Use SSC source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df40000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df70000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df40000); } - coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe)); + coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) coreclk |= 0x01000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); - vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000); /* Enable DPIO clock input */ dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | @@ -5261,7 +5442,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc, int refclk = 100000; mutex_lock(&dev_priv->dpio_lock); - mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe)); + mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe)); mutex_unlock(&dev_priv->dpio_lock); clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7; @@ -6402,7 +6583,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) /* Make sure we're not on PC8 state before disabling PC8, otherwise * we'll hang the machine! */ - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -6436,7 +6617,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } void hsw_enable_pc8_work(struct work_struct *__work) @@ -9402,6 +9583,21 @@ static int __intel_set_mode(struct drm_crtc *crtc, "[modeset]"); } + /* + * See if the config requires any additional preparation, e.g. + * to adjust global state with pipes off. We need to do this + * here so we can get the modeset_pipe updated config for the new + * mode set on this crtc. For other crtcs we need to use the + * adjusted_mode bits in the crtc directly. + */ + if (IS_VALLEYVIEW(dev)) { + valleyview_modeset_global_pipes(dev, &prepare_pipes, + modeset_pipes, pipe_config); + + /* may have added more to prepare_pipes than we should */ + prepare_pipes &= ~disable_pipes; + } + for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); @@ -10412,8 +10608,11 @@ static void intel_init_display(struct drm_device *dev) } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; - } else if (IS_VALLEYVIEW(dev)) + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.modeset_global_resources = + valleyview_modeset_global_resources; dev_priv->display.write_eld = ironlake_write_eld; + } /* Default just returns -ENODEV to indicate unsupported */ dev_priv->display.queue_flip = intel_default_queue_flip; @@ -10440,6 +10639,8 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.queue_flip = intel_gen7_queue_flip; break; } + + intel_panel_init_backlight_funcs(dev); } /* @@ -10476,17 +10677,6 @@ static void quirk_invert_brightness(struct drm_device *dev) DRM_INFO("applying inverted panel brightness quirk\n"); } -/* - * Some machines (Dell XPS13) suffer broken backlight controls if - * BLM_PCH_PWM_ENABLE is set. - */ -static void quirk_no_pcm_pwm_enable(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; - DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); -} - struct intel_quirk { int device; int subsystem_vendor; @@ -10546,11 +10736,6 @@ static struct intel_quirk intel_quirks[] = { * seem to use inverted backlight PWM. */ { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness }, - - /* Dell XPS13 HD Sandy Bridge */ - { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, - /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ - { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable }, }; static void intel_init_quirks(struct drm_device *dev) @@ -10870,7 +11055,7 @@ void i915_redisable_vga(struct drm_device *dev) * level, just check if the power well is enabled instead of trying to * follow the "don't touch the power well if we don't need it" policy * the rest of the driver uses. */ - if (HAS_POWER_WELL(dev) && + if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0) return; @@ -11091,12 +11276,11 @@ void intel_modeset_cleanup(struct drm_device *dev) /* flush any delayed tasks or pending work */ flush_scheduled_work(); - /* destroy backlight, if any, before the connectors */ - intel_panel_destroy_backlight(dev); - - /* destroy the sysfs files before encoders/connectors */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) + /* destroy the backlight and sysfs files before encoders/connectors */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + intel_panel_destroy_backlight(connector); drm_sysfs_connector_remove(connector); + } drm_mode_config_cleanup(dev); @@ -11150,6 +11334,7 @@ struct intel_display_error_state { } cursor[I915_MAX_PIPES]; struct intel_pipe_error_state { + bool power_domain_on; u32 source; } pipe[I915_MAX_PIPES]; @@ -11164,6 +11349,7 @@ struct intel_display_error_state { } plane[I915_MAX_PIPES]; struct intel_transcoder_error_state { + bool power_domain_on; enum transcoder cpu_transcoder; u32 conf; @@ -11197,11 +11383,13 @@ intel_display_capture_error_state(struct drm_device *dev) if (error == NULL) return NULL; - if (HAS_POWER_WELL(dev)) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { - if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i))) + error->pipe[i].power_domain_on = + intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i)); + if (!error->pipe[i].power_domain_on) continue; if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { @@ -11237,8 +11425,9 @@ intel_display_capture_error_state(struct drm_device *dev) for (i = 0; i < error->num_transcoders; i++) { enum transcoder cpu_transcoder = transcoders[i]; - if (!intel_display_power_enabled(dev, - POWER_DOMAIN_TRANSCODER(cpu_transcoder))) + error->transcoder[i].power_domain_on = + intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i)); + if (!error->transcoder[i].power_domain_on) continue; error->transcoder[i].cpu_transcoder = cpu_transcoder; @@ -11268,11 +11457,13 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, return; err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); - if (HAS_POWER_WELL(dev)) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) err_printf(m, "PWR_WELL_CTL2: %08x\n", error->power_well_driver); for_each_pipe(i) { err_printf(m, "Pipe [%d]:\n", i); + err_printf(m, " Power: %s\n", + error->pipe[i].power_domain_on ? "on" : "off"); err_printf(m, " SRC: %08x\n", error->pipe[i].source); err_printf(m, "Plane [%d]:\n", i); @@ -11298,6 +11489,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, for (i = 0; i < error->num_transcoders; i++) { err_printf(m, "CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); + err_printf(m, " Power: %s\n", + error->transcoder[i].power_domain_on ? "on" : "off"); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 30c627c7b7ba..36f13c574571 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -142,7 +142,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; } -static int +static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, int i, ret, recv_bytes; uint32_t status; int try, precharge, clock = 0; - bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); + bool has_aux_irq = true; uint32_t timeout; /* dp aux is extremely sensitive to irq latency, hence request the @@ -542,7 +542,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, return -E2BIG; intel_dp_check_edp(intel_dp); - msg[0] = AUX_NATIVE_WRITE << 4; + msg[0] = DP_AUX_NATIVE_WRITE << 4; msg[1] = address >> 8; msg[2] = address & 0xff; msg[3] = send_bytes - 1; @@ -552,9 +552,10 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) break; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(100); else return -EIO; @@ -586,7 +587,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, return -E2BIG; intel_dp_check_edp(intel_dp); - msg[0] = AUX_NATIVE_READ << 4; + msg[0] = DP_AUX_NATIVE_READ << 4; msg[1] = address >> 8; msg[2] = address & 0xff; msg[3] = recv_bytes - 1; @@ -601,12 +602,12 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, return -EPROTO; if (ret < 0) return ret; - ack = reply[0]; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { + ack = reply[0] >> 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) { memcpy(recv, reply + 1, ret - 1); return ret - 1; } - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(100); else return -EIO; @@ -633,12 +634,12 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, intel_dp_check_edp(intel_dp); /* Set up the command byte */ if (mode & MODE_I2C_READ) - msg[0] = AUX_I2C_READ << 4; + msg[0] = DP_AUX_I2C_READ << 4; else - msg[0] = AUX_I2C_WRITE << 4; + msg[0] = DP_AUX_I2C_WRITE << 4; if (!(mode & MODE_I2C_STOP)) - msg[0] |= AUX_I2C_MOT << 4; + msg[0] |= DP_AUX_I2C_MOT << 4; msg[1] = address >> 8; msg[2] = address; @@ -675,17 +676,17 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, goto out; } - switch (reply[0] & AUX_NATIVE_REPLY_MASK) { - case AUX_NATIVE_REPLY_ACK: + switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) { + case DP_AUX_NATIVE_REPLY_ACK: /* I2C-over-AUX Reply field is only valid * when paired with AUX ACK. */ break; - case AUX_NATIVE_REPLY_NACK: + case DP_AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); ret = -EREMOTEIO; goto out; - case AUX_NATIVE_REPLY_DEFER: + case DP_AUX_NATIVE_REPLY_DEFER: /* * For now, just give more slack to branch devices. We * could check the DPCD for I2C bit rate capabilities, @@ -706,18 +707,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, goto out; } - switch (reply[0] & AUX_I2C_REPLY_MASK) { - case AUX_I2C_REPLY_ACK: + switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) { + case DP_AUX_I2C_REPLY_ACK: if (mode == MODE_I2C_READ) { *read_byte = reply[1]; } ret = reply_bytes - 1; goto out; - case AUX_I2C_REPLY_NACK: + case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); ret = -EREMOTEIO; goto out; - case AUX_I2C_REPLY_DEFER: + case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(100); break; @@ -1845,23 +1846,23 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; struct edp_power_seq power_seq; u32 val; mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); @@ -1872,7 +1873,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) intel_enable_dp(encoder); - vlv_wait_port_ready(dev_priv, port); + vlv_wait_port_ready(dev_priv, dport); } static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) @@ -1882,24 +1883,24 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000); mutex_unlock(&dev_priv->dpio_lock); } @@ -2050,7 +2051,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) unsigned long demph_reg_value, preemph_reg_value, uniqtranscale_reg_value; uint8_t train_set = intel_dp->train_set[0]; - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { @@ -2127,14 +2128,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) } mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000); mutex_unlock(&dev_priv->dpio_lock); return 0; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a18e88b3e425..2b5bcb617908 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -156,6 +156,17 @@ struct intel_encoder { struct intel_panel { struct drm_display_mode *fixed_mode; int fitting_mode; + + /* backlight */ + struct { + bool present; + u32 level; + u32 max; + bool enabled; + bool combination_mode; /* gen 2/4 only */ + bool active_low_pwm; + struct backlight_device *device; + } backlight; }; struct intel_connector { @@ -490,9 +501,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport) { switch (dport->port) { case PORT_B: - return 0; + return DPIO_CH0; case PORT_C: - return 1; + return DPIO_CH1; default: BUG(); } @@ -638,7 +649,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, void intel_wait_for_vblank(struct drm_device *dev, int pipe); void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); -void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port); +void vlv_wait_port_ready(struct drm_i915_private *dev_priv, + struct intel_digital_port *dport); bool intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_display_mode *mode, struct intel_load_detect_pipe *old); @@ -694,7 +706,7 @@ void i915_disable_vga_mem(struct drm_device *dev); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); void intel_display_set_init_power(struct drm_device *dev, bool enable); - +int valleyview_get_vco(struct drm_i915_private *dev_priv); /* intel_dp.c */ void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); @@ -808,7 +820,8 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, int intel_panel_setup_backlight(struct drm_connector *connector); void intel_panel_enable_backlight(struct intel_connector *connector); void intel_panel_disable_backlight(struct intel_connector *connector); -void intel_panel_destroy_backlight(struct drm_device *dev); +void intel_panel_destroy_backlight(struct drm_connector *connector); +void intel_panel_init_backlight_funcs(struct drm_device *dev); enum drm_connector_status intel_panel_detect(struct drm_device *dev); @@ -829,6 +842,8 @@ int intel_power_domains_init(struct drm_device *dev); void intel_power_domains_remove(struct drm_device *dev); bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); +bool intel_display_power_enabled_sw(struct drm_device *dev, + enum intel_display_power_domain domain); void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_put(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index d257b093ca68..7b9b350d29ae 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -251,8 +251,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, /* XXX: read flags, set to adjusted_mode */ } -static int intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_dsi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 3c7736546856..eeff998e52ef 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -234,8 +234,9 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_dvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_dvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 895fcb4fbd94..284c3eb066f6 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -57,18 +57,14 @@ static struct fb_ops intelfb_ops = { .fb_debug_leave = drm_fb_helper_debug_leave, }; -static int intelfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) +static int intelfb_alloc(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) { struct intel_fbdev *ifbdev = container_of(helper, struct intel_fbdev, helper); struct drm_device *dev = helper->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; - struct device *device = &dev->pdev->dev; int size, ret; /* we don't do packed 24bpp */ @@ -94,8 +90,6 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out; } - mutex_lock(&dev->struct_mutex); - /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); if (ret) { @@ -103,7 +97,50 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unref; } - info = framebuffer_alloc(0, device); + ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); + if (ret) + goto out_unpin; + + return 0; + +out_unpin: + i915_gem_object_unpin(obj); +out_unref: + drm_gem_object_unreference(&obj->base); +out: + return ret; +} + +static int intelfb_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct intel_fbdev *ifbdev = + container_of(helper, struct intel_fbdev, helper); + struct intel_framebuffer *intel_fb = &ifbdev->ifb; + struct drm_device *dev = helper->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct fb_info *info; + struct drm_framebuffer *fb; + struct drm_i915_gem_object *obj; + int size, ret; + + mutex_lock(&dev->struct_mutex); + + if (!intel_fb->obj) { + DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); + ret = intelfb_alloc(helper, sizes); + if (ret) + goto out_unlock; + } else { + DRM_DEBUG_KMS("re-using BIOS fb\n"); + sizes->fb_width = intel_fb->base.width; + sizes->fb_height = intel_fb->base.height; + } + + obj = intel_fb->obj; + size = obj->base.size; + + info = framebuffer_alloc(0, &dev->pdev->dev); if (!info) { ret = -ENOMEM; goto out_unpin; @@ -111,10 +148,6 @@ static int intelfb_create(struct drm_fb_helper *helper, info->par = helper; - ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); - if (ret) - goto out_unpin; - fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; @@ -170,17 +203,15 @@ static int intelfb_create(struct drm_fb_helper *helper, fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); - mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_unpin(obj); -out_unref: drm_gem_object_unreference(&obj->base); +out_unlock: mutex_unlock(&dev->struct_mutex); -out: return ret; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 03f9ca70530c..6a6ad0c78dc7 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -853,8 +853,9 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi) return 225000; } -static int intel_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) return MODE_CLOCK_HIGH; @@ -1081,7 +1082,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; u32 val; @@ -1090,41 +1091,33 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) /* Enable clock channels for this port */ mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); /* HDMI 1.0V-2dB */ - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), - 0x2b245f5f); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), - 0x5578b83a); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), - 0x0c782040); - vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port), - 0x2b247878); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), - 0x00002000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), - DPIO_TX_OCALINIT_EN); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040); + vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); /* Program lane clock */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), - 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), - 0x00400888); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); intel_enable_hdmi(encoder); - vlv_wait_port_ready(dev_priv, port); + vlv_wait_port_ready(dev_priv, dport); } static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) @@ -1134,7 +1127,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; if (!IS_VALLEYVIEW(dev)) @@ -1142,24 +1135,22 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); - - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), - 0x00002000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), - DPIO_TX_OCALINIT_EN); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000); + + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); mutex_unlock(&dev_priv->dpio_lock); } @@ -1169,13 +1160,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; /* Reset lanes to avoid HDMI flicker (VLV w/a) */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060); mutex_unlock(&dev_priv->dpio_lock); } diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2ca17b14b6c1..b1dc33f47899 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -82,20 +82,11 @@ static int get_disp_clk_div(struct drm_i915_private *dev_priv, static void gmbus_set_freq(struct drm_i915_private *dev_priv) { - int vco_freq[] = { 800, 1600, 2000, 2400 }; - int gmbus_freq = 0, cdclk_div, hpll_freq; + int vco, gmbus_freq = 0, cdclk_div; BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - /* Skip setting the gmbus freq if BIOS has already programmed it */ - if (I915_READ(GMBUSFREQ_VLV) != 0xA0) - return; - - /* Obtain SKU information */ - mutex_lock(&dev_priv->dpio_lock); - hpll_freq = - vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; - mutex_unlock(&dev_priv->dpio_lock); + vco = valleyview_get_vco(dev_priv); /* Get the CDCLK divide ratio */ cdclk_div = get_disp_clk_div(dev_priv, CDCLK); @@ -106,7 +97,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv) * in fact 1MHz is the correct frequency. */ if (cdclk_div) - gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div; + gmbus_freq = (vco << 1) / cdclk_div; if (WARN_ON(gmbus_freq == 0)) return; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index c3b4da7895ed..3deb58e2f394 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -256,8 +256,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder) POSTING_READ(lvds_encoder->reg); } -static int intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_lvds_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6d69a9bad865..a8febbd3017b 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -396,13 +396,10 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_encoder *encoder; struct drm_connector *connector; - struct intel_connector *intel_connector = NULL; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; + struct intel_connector *intel_connector; + struct intel_panel *panel; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; - u32 ret = 0; - bool found = false; DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); @@ -414,38 +411,24 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) return ASLC_BACKLIGHT_FAILED; mutex_lock(&dev->mode_config.mutex); + /* - * Could match the OpRegion connector here instead, but we'd also need - * to verify the connector could handle a backlight call. + * Update backlight on all connectors that support backlight (usually + * only one). */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->crtc == crtc) { - found = true; - break; - } - - if (!found) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->encoder == encoder) - intel_connector = to_intel_connector(connector); - - if (!intel_connector) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } - DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); - intel_panel_set_backlight(intel_connector, bclp, 255); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + intel_connector = to_intel_connector(connector); + panel = &intel_connector->panel; + if (panel->backlight.present) + intel_panel_set_backlight(intel_connector, bclp, 255); + } iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); -out: mutex_unlock(&dev->mode_config.mutex); - return ret; + + return 0; } static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f6..e480cf41c536 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -325,203 +325,170 @@ out: pipe_config->gmch_pfit.lvds_border_bits = border; } -static int is_backlight_combination_mode(struct drm_device *dev) +static int i915_panel_invert_brightness; +MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " + "(-1 force normal, 0 machine defaults, 1 force inversion), please " + "report PCI device ID, subsystem vendor and subsystem device ID " + "to dri-devel@lists.freedesktop.org, if your machine needs it. " + "It will then be included in an upcoming module version."); +module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); +static u32 intel_panel_compute_brightness(struct intel_connector *connector, + u32 val) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; - if (IS_GEN4(dev)) - return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; + WARN_ON(panel->backlight.max == 0); - if (IS_GEN2(dev)) - return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; + if (i915_panel_invert_brightness < 0) + return val; - return 0; + if (i915_panel_invert_brightness > 0 || + dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { + return panel->backlight.max - val; + } + + return val; } -/* XXX: query mode clock or hardware clock and program max PWM appropriately - * when it's 0. - */ -static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) +static u32 bdw_get_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock)); - - /* Restore the CTL value if it lost, e.g. GPU reset */ - if (HAS_PCH_SPLIT(dev_priv->dev)) { - val = I915_READ(BLC_PWM_PCH_CTL2); - if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { - dev_priv->regfile.saveBLC_PWM_CTL2 = val; - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL2; - I915_WRITE(BLC_PWM_PCH_CTL2, val); - } - } else if (IS_VALLEYVIEW(dev)) { - val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(pipe)); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), - dev_priv->regfile.saveBLC_PWM_CTL2); - } + return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; +} - if (!val) - val = 0x0f42ffff; - } else { - val = I915_READ(BLC_PWM_CTL); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - if (INTEL_INFO(dev)->gen >= 4) - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(BLC_PWM_CTL2); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(BLC_PWM_CTL, val); - if (INTEL_INFO(dev)->gen >= 4) - I915_WRITE(BLC_PWM_CTL2, - dev_priv->regfile.saveBLC_PWM_CTL2); - } - } +static u32 pch_get_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; - return val; + return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } -static u32 intel_panel_get_max_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 i9xx_get_backlight(struct intel_connector *connector) { - u32 max; + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 val; - max = i915_read_blc_pwm_ctl(dev, pipe); + val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (INTEL_INFO(dev)->gen < 4) + val >>= 1; - if (HAS_PCH_SPLIT(dev)) { - max >>= 16; - } else { - if (INTEL_INFO(dev)->gen < 4) - max >>= 17; - else - max >>= 16; + if (panel->backlight.combination_mode) { + u8 lbpc; - if (is_backlight_combination_mode(dev)) - max *= 0xff; + pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); + val *= lbpc; } - DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); - - return max; + return val; } -static int i915_panel_invert_brightness; -MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " - "(-1 force normal, 0 machine defaults, 1 force inversion), please " - "report PCI device ID, subsystem vendor and subsystem device ID " - "to dri-devel@lists.freedesktop.org, if your machine needs it. " - "It will then be included in an upcoming module version."); -module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); -static u32 intel_panel_compute_brightness(struct drm_device *dev, - enum pipe pipe, u32 val) +static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - if (i915_panel_invert_brightness < 0) - return val; + return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; +} - if (i915_panel_invert_brightness > 0 || - dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { - u32 max = intel_panel_get_max_backlight(dev, pipe); - if (max) - return max - val; - } +static u32 vlv_get_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + enum pipe pipe = intel_get_pipe_from_connector(connector); - return val; + return _vlv_get_backlight(dev, pipe); } -static u32 intel_panel_get_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 intel_panel_get_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val; unsigned long flags; - int reg; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); - if (HAS_PCH_SPLIT(dev)) { - val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - } else { - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; - - val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK; - if (INTEL_INFO(dev)->gen < 4) - val >>= 1; + val = dev_priv->display.get_backlight(connector); + val = intel_panel_compute_brightness(connector, val); - if (is_backlight_combination_mode(dev)) { - u8 lbpc; - - pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); - val *= lbpc; - } - } - - val = intel_panel_compute_brightness(dev, pipe, val); - - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); return val; } -static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) +static void bdw_set_backlight(struct intel_connector *connector, u32 level) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(BLC_PWM_CPU_CTL, val | level); + u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_PCH_CTL2, val | level); } -static void intel_panel_actually_set_backlight(struct drm_device *dev, - enum pipe pipe, u32 level) +static void pch_set_backlight(struct intel_connector *connector, u32 level) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; - int reg; - DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); - level = intel_panel_compute_brightness(dev, pipe, level); + tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); +} + +static void i9xx_set_backlight(struct intel_connector *connector, u32 level) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 tmp, mask; - if (HAS_PCH_SPLIT(dev)) - return intel_pch_panel_set_backlight(dev, level); + WARN_ON(panel->backlight.max == 0); - if (is_backlight_combination_mode(dev)) { - u32 max = intel_panel_get_max_backlight(dev, pipe); + if (panel->backlight.combination_mode) { u8 lbpc; - /* we're screwed, but keep behaviour backwards compatible */ - if (!max) - max = 1; - - lbpc = level * 0xfe / max + 1; + lbpc = level * 0xfe / panel->backlight.max + 1; level /= lbpc; pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; - - tmp = I915_READ(reg); - if (INTEL_INFO(dev)->gen < 4) + if (IS_GEN4(dev)) { + mask = BACKLIGHT_DUTY_CYCLE_MASK; + } else { level <<= 1; - tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(reg, tmp | level); + mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; + } + + tmp = I915_READ(BLC_PWM_CTL) & ~mask; + I915_WRITE(BLC_PWM_CTL, tmp | level); +} + +static void vlv_set_backlight(struct intel_connector *connector, u32 level) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); +} + +static void +intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); + + level = intel_panel_compute_brightness(connector, level); + dev_priv->display.set_backlight(connector, level); } /* set backlight brightness to level in range [0..max] */ @@ -530,6 +497,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 freq; unsigned long flags; @@ -537,34 +505,77 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, if (pipe == INVALID_PIPE) return; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); - freq = intel_panel_get_max_backlight(dev, pipe); - if (!freq) { - /* we are screwed, bail out */ - goto out; - } + WARN_ON(panel->backlight.max == 0); - /* scale to hardware, but be careful to not overflow */ + /* scale to hardware max, but be careful to not overflow */ + freq = panel->backlight.max; if (freq < max) level = level * freq / max; else level = freq / max * level; - dev_priv->backlight.level = level; - if (dev_priv->backlight.device) - dev_priv->backlight.device->props.brightness = level; + panel->backlight.level = level; + if (panel->backlight.device) + panel->backlight.device->props.brightness = level; - if (dev_priv->backlight.enabled) - intel_panel_actually_set_backlight(dev, pipe, level); -out: - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + if (panel->backlight.enabled) + intel_panel_actually_set_backlight(connector, level); + + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); +} + +static void pch_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + + intel_panel_actually_set_backlight(connector, 0); + + tmp = I915_READ(BLC_PWM_CPU_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); + + tmp = I915_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); +} + +static void i9xx_disable_backlight(struct intel_connector *connector) +{ + intel_panel_actually_set_backlight(connector, 0); +} + +static void i965_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + + intel_panel_actually_set_backlight(connector, 0); + + tmp = I915_READ(BLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); +} + +static void vlv_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + intel_panel_actually_set_backlight(connector, 0); + + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); } void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); unsigned long flags; @@ -582,141 +593,215 @@ void intel_panel_disable_backlight(struct intel_connector *connector) return; } - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); - dev_priv->backlight.enabled = false; - intel_panel_actually_set_backlight(dev, pipe, 0); + panel->backlight.enabled = false; + dev_priv->display.disable_backlight(connector); - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); +} - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; +static void bdw_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 pch_ctl1, pch_ctl2; + + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { + DRM_DEBUG_KMS("pch backlight already enabled\n"); + pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + } - I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); + pch_ctl2 = panel->backlight.max << 16; + I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); - if (HAS_PCH_SPLIT(dev)) { - tmp = I915_READ(BLC_PWM_PCH_CTL1); - tmp &= ~BLM_PCH_PWM_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); - } - } + pch_ctl1 = 0; + if (panel->backlight.active_low_pwm) + pch_ctl1 |= BLM_PCH_POLARITY; - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + /* BDW always uses the pch pwm controls. */ + pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; + + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + POSTING_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); + + /* This won't stick until the above enable. */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); } -void intel_panel_enable_backlight(struct intel_connector *connector) +static void pch_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); - unsigned long flags; + u32 cpu_ctl2, pch_ctl1, pch_ctl2; - if (pipe == INVALID_PIPE) - return; + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + if (cpu_ctl2 & BLM_PWM_ENABLE) { + WARN(1, "cpu backlight already enabled\n"); + cpu_ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); + } - DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { + DRM_DEBUG_KMS("pch backlight already enabled\n"); + pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + } - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + if (cpu_transcoder == TRANSCODER_EDP) + cpu_ctl2 = BLM_TRANSCODER_EDP; + else + cpu_ctl2 = BLM_PIPE(cpu_transcoder); + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); + POSTING_READ(BLC_PWM_CPU_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); + + /* This won't stick until the above enable. */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); + + pch_ctl2 = panel->backlight.max << 16; + I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); + + pch_ctl1 = 0; + if (panel->backlight.active_low_pwm) + pch_ctl1 |= BLM_PCH_POLARITY; + + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + POSTING_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); +} + +static void i9xx_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 ctl, freq; - if (dev_priv->backlight.level == 0) { - dev_priv->backlight.level = intel_panel_get_max_backlight(dev, - pipe); - if (dev_priv->backlight.device) - dev_priv->backlight.device->props.brightness = - dev_priv->backlight.level; + ctl = I915_READ(BLC_PWM_CTL); + if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { + WARN(1, "backlight already enabled\n"); + I915_WRITE(BLC_PWM_CTL, 0); } - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; + freq = panel->backlight.max; + if (panel->backlight.combination_mode) + freq /= 0xff; - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; + ctl = freq << 17; + if (IS_GEN2(dev) && panel->backlight.combination_mode) + ctl |= BLM_LEGACY_MODE; + if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) + ctl |= BLM_POLARITY_PNV; - tmp = I915_READ(reg); + I915_WRITE(BLC_PWM_CTL, ctl); + POSTING_READ(BLC_PWM_CTL); - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - goto set_level; + /* XXX: combine this into above write? */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); +} - if (INTEL_INFO(dev)->num_pipes == 3) - tmp &= ~BLM_PIPE_SELECT_IVB; - else - tmp &= ~BLM_PIPE_SELECT; +static void i965_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 ctl, ctl2, freq; - if (cpu_transcoder == TRANSCODER_EDP) - tmp |= BLM_TRANSCODER_EDP; - else - tmp |= BLM_PIPE(cpu_transcoder); - tmp &= ~BLM_PWM_ENABLE; - - I915_WRITE(reg, tmp); - POSTING_READ(reg); - I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - - if (HAS_PCH_SPLIT(dev) && - !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { - tmp = I915_READ(BLC_PWM_PCH_CTL1); - tmp |= BLM_PCH_PWM_ENABLE; - tmp &= ~BLM_PCH_OVERRIDE_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); - } + ctl2 = I915_READ(BLC_PWM_CTL2); + if (ctl2 & BLM_PWM_ENABLE) { + WARN(1, "backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CTL2, ctl2); } -set_level: - /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. - * BLC_PWM_CPU_CTL may be cleared to zero automatically when these - * registers are set. - */ - dev_priv->backlight.enabled = true; - intel_panel_actually_set_backlight(dev, pipe, - dev_priv->backlight.level); + freq = panel->backlight.max; + if (panel->backlight.combination_mode) + freq /= 0xff; + + ctl = freq << 16; + I915_WRITE(BLC_PWM_CTL, ctl); + + /* XXX: combine this into above write? */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + ctl2 = BLM_PIPE(pipe); + if (panel->backlight.combination_mode) + ctl2 |= BLM_COMBINATION_MODE; + if (panel->backlight.active_low_pwm) + ctl2 |= BLM_POLARITY_I965; + I915_WRITE(BLC_PWM_CTL2, ctl2); + POSTING_READ(BLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); } -/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */ -static void intel_panel_init_backlight_regs(struct drm_device *dev) +static void vlv_enable_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 ctl, ctl2; - if (IS_VALLEYVIEW(dev)) { - enum pipe pipe; + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + if (ctl2 & BLM_PWM_ENABLE) { + WARN(1, "backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); + } - for_each_pipe(pipe) { - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + ctl = panel->backlight.max << 16; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); - /* Skip if the modulation freq is already set */ - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) - continue; + /* XXX: combine this into above write? */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | - cur_val); - } - } + ctl2 = 0; + if (panel->backlight.active_low_pwm) + ctl2 |= BLM_POLARITY_I965; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); + POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } -static void intel_panel_init_backlight(struct drm_device *dev) +void intel_panel_enable_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + enum pipe pipe = intel_get_pipe_from_connector(connector); + unsigned long flags; + + if (pipe == INVALID_PIPE) + return; + + DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); + + spin_lock_irqsave(&dev_priv->backlight_lock, flags); + + WARN_ON(panel->backlight.max == 0); - intel_panel_init_backlight_regs(dev); + if (panel->backlight.level == 0) { + panel->backlight.level = panel->backlight.max; + if (panel->backlight.device) + panel->backlight.device->props.brightness = + panel->backlight.level; + } + + dev_priv->display.enable_backlight(connector); + panel->backlight.enabled = true; - dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); - dev_priv->backlight.enabled = dev_priv->backlight.level != 0; + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } enum drm_connector_status @@ -742,7 +827,7 @@ intel_panel_detect(struct drm_device *dev) } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) -static int intel_panel_update_status(struct backlight_device *bd) +static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; @@ -756,85 +841,306 @@ static int intel_panel_update_status(struct backlight_device *bd) return 0; } -static int intel_panel_get_brightness(struct backlight_device *bd) +static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; - enum pipe pipe; + int ret; mutex_lock(&dev->mode_config.mutex); - pipe = intel_get_pipe_from_connector(connector); + ret = intel_panel_get_backlight(connector); mutex_unlock(&dev->mode_config.mutex); - if (pipe == INVALID_PIPE) - return 0; - return intel_panel_get_backlight(connector->base.dev, pipe); + return ret; } -static const struct backlight_ops intel_panel_bl_ops = { - .update_status = intel_panel_update_status, - .get_brightness = intel_panel_get_brightness, +static const struct backlight_ops intel_backlight_device_ops = { + .update_status = intel_backlight_device_update_status, + .get_brightness = intel_backlight_device_get_brightness, }; -int intel_panel_setup_backlight(struct drm_connector *connector) +static int intel_backlight_device_register(struct intel_connector *connector) { - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; struct backlight_properties props; - unsigned long flags; - intel_panel_init_backlight(dev); - - if (WARN_ON(dev_priv->backlight.device)) + if (WARN_ON(panel->backlight.device)) return -ENODEV; + BUG_ON(panel->backlight.max == 0); + memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; - props.brightness = dev_priv->backlight.level; + props.brightness = panel->backlight.level; + props.max_brightness = panel->backlight.max; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); - props.max_brightness = intel_panel_get_max_backlight(dev, 0); - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); - - if (props.max_brightness == 0) { - DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); - return -ENODEV; - } - dev_priv->backlight.device = + /* + * Note: using the same name independent of the connector prevents + * registration of multiple backlight devices in the driver. + */ + panel->backlight.device = backlight_device_register("intel_backlight", - connector->kdev, - to_intel_connector(connector), - &intel_panel_bl_ops, &props); + connector->base.kdev, + connector, + &intel_backlight_device_ops, &props); - if (IS_ERR(dev_priv->backlight.device)) { + if (IS_ERR(panel->backlight.device)) { DRM_ERROR("Failed to register backlight: %ld\n", - PTR_ERR(dev_priv->backlight.device)); - dev_priv->backlight.device = NULL; + PTR_ERR(panel->backlight.device)); + panel->backlight.device = NULL; return -ENODEV; } return 0; } -void intel_panel_destroy_backlight(struct drm_device *dev) +static void intel_backlight_device_unregister(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + + if (panel->backlight.device) { + backlight_device_unregister(panel->backlight.device); + panel->backlight.device = NULL; + } +} +#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ +static int intel_backlight_device_register(struct intel_connector *connector) +{ + return 0; +} +static void intel_backlight_device_unregister(struct intel_connector *connector) +{ +} +#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ + +/* + * Note: The setup hooks can't assume pipe is set! + * + * XXX: Query mode clock or hardware clock and program PWM modulation frequency + * appropriately when it's 0. Use VBT and/or sane defaults. + */ +static int bdw_setup_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->backlight.device) { - backlight_device_unregister(dev_priv->backlight.device); - dev_priv->backlight.device = NULL; + struct intel_panel *panel = &connector->panel; + u32 pch_ctl1, pch_ctl2, val; + + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; + + pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); + panel->backlight.max = pch_ctl2 >> 16; + if (!panel->backlight.max) + return -ENODEV; + + val = bdw_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && + panel->backlight.level != 0; + + return 0; +} + +static int pch_setup_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; + + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; + + pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); + panel->backlight.max = pch_ctl2 >> 16; + if (!panel->backlight.max) + return -ENODEV; + + val = pch_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && + (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; + + return 0; +} + +static int i9xx_setup_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 ctl, val; + + ctl = I915_READ(BLC_PWM_CTL); + + if (IS_GEN2(dev)) + panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; + + if (IS_PINEVIEW(dev)) + panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; + + panel->backlight.max = ctl >> 17; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; + + if (!panel->backlight.max) + return -ENODEV; + + val = i9xx_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + panel->backlight.enabled = panel->backlight.level != 0; + + return 0; +} + +static int i965_setup_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + u32 ctl, ctl2, val; + + ctl2 = I915_READ(BLC_PWM_CTL2); + panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; + panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; + + ctl = I915_READ(BLC_PWM_CTL); + panel->backlight.max = ctl >> 16; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; + + if (!panel->backlight.max) + return -ENODEV; + + val = i9xx_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && + panel->backlight.level != 0; + + return 0; +} + +static int vlv_setup_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + enum pipe pipe; + u32 ctl, ctl2, val; + + for_each_pipe(pipe) { + u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + + /* Skip if the modulation freq is already set */ + if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) + continue; + + cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | + cur_val); } + + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); + panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; + + ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); + panel->backlight.max = ctl >> 16; + if (!panel->backlight.max) + return -ENODEV; + + val = _vlv_get_backlight(dev, PIPE_A); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && + panel->backlight.level != 0; + + return 0; } -#else + int intel_panel_setup_backlight(struct drm_connector *connector) { - intel_panel_init_backlight(connector->dev); + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_panel *panel = &intel_connector->panel; + unsigned long flags; + int ret; + + /* set level and max in panel struct */ + spin_lock_irqsave(&dev_priv->backlight_lock, flags); + ret = dev_priv->display.setup_backlight(intel_connector); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); + + if (ret) { + DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", + drm_get_connector_name(connector)); + return ret; + } + + intel_backlight_device_register(intel_connector); + + panel->backlight.present = true; + + DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, " + "sysfs interface %sregistered\n", + panel->backlight.enabled ? "enabled" : "disabled", + panel->backlight.level, panel->backlight.max, + panel->backlight.device ? "" : "not "); + return 0; } -void intel_panel_destroy_backlight(struct drm_device *dev) +void intel_panel_destroy_backlight(struct drm_connector *connector) { - return; + struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_panel *panel = &intel_connector->panel; + + panel->backlight.present = false; + intel_backlight_device_unregister(intel_connector); +} + +/* Set up chip specific backlight functions */ +void intel_panel_init_backlight_funcs(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_BROADWELL(dev)) { + dev_priv->display.setup_backlight = bdw_setup_backlight; + dev_priv->display.enable_backlight = bdw_enable_backlight; + dev_priv->display.disable_backlight = pch_disable_backlight; + dev_priv->display.set_backlight = bdw_set_backlight; + dev_priv->display.get_backlight = bdw_get_backlight; + } else if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.setup_backlight = pch_setup_backlight; + dev_priv->display.enable_backlight = pch_enable_backlight; + dev_priv->display.disable_backlight = pch_disable_backlight; + dev_priv->display.set_backlight = pch_set_backlight; + dev_priv->display.get_backlight = pch_get_backlight; + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.setup_backlight = vlv_setup_backlight; + dev_priv->display.enable_backlight = vlv_enable_backlight; + dev_priv->display.disable_backlight = vlv_disable_backlight; + dev_priv->display.set_backlight = vlv_set_backlight; + dev_priv->display.get_backlight = vlv_get_backlight; + } else if (IS_GEN4(dev)) { + dev_priv->display.setup_backlight = i965_setup_backlight; + dev_priv->display.enable_backlight = i965_enable_backlight; + dev_priv->display.disable_backlight = i965_disable_backlight; + dev_priv->display.set_backlight = i9xx_set_backlight; + dev_priv->display.get_backlight = i9xx_get_backlight; + } else { + dev_priv->display.setup_backlight = i9xx_setup_backlight; + dev_priv->display.enable_backlight = i9xx_enable_backlight; + dev_priv->display.disable_backlight = i9xx_disable_backlight; + dev_priv->display.set_backlight = i9xx_set_backlight; + dev_priv->display.get_backlight = i9xx_get_backlight; + } } -#endif int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e0d5e075b15..e6d98fe86b17 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -191,7 +191,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) u32 blt_ecoskpd; /* Make sure blitter notifies FBC of writes */ - gen6_gt_force_wake_get(dev_priv); + + /* Blitter is part of Media powerwell on VLV. No impact of + * his param in other platforms for now */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA); + blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << GEN6_BLITTER_LOCK_SHIFT; @@ -202,7 +206,8 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) GEN6_BLITTER_LOCK_SHIFT); I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); POSTING_READ(GEN6_BLITTER_ECOSKPD); - gen6_gt_force_wake_put(dev_priv); + + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); } static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) @@ -222,7 +227,9 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); /* Set persistent mode for front-buffer rendering, ala X. */ dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; - dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg); + dpfc_ctl |= DPFC_CTL_FENCE_EN; + if (IS_GEN5(dev)) + dpfc_ctl |= obj->fence_reg; I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | @@ -295,7 +302,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) sandybridge_blit_fbc_update(dev); - DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); } bool intel_fbc_enabled(struct drm_device *dev) @@ -3430,26 +3437,19 @@ static void ironlake_disable_drps(struct drm_device *dev) * ourselves, instead of doing a rmw cycle (which might result in us clearing * all limits and the gpu stuck at whatever frequency it is at atm). */ -static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) +static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val) { u32 limits; - limits = 0; - - if (*val >= dev_priv->rps.max_delay) - *val = dev_priv->rps.max_delay; - limits |= dev_priv->rps.max_delay << 24; - /* Only set the down limit when we've reached the lowest level to avoid * getting more interrupts, otherwise leave this clear. This prevents a * race in the hw when coming out of rc6: There's a tiny window where * the hw runs at the minimal clock before selecting the desired * frequency, if the down threshold expires in that window we will not * receive a down interrupt. */ - if (*val <= dev_priv->rps.min_delay) { - *val = dev_priv->rps.min_delay; + limits = dev_priv->rps.max_delay << 24; + if (val <= dev_priv->rps.min_delay) limits |= dev_priv->rps.min_delay << 16; - } return limits; } @@ -3549,7 +3549,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 limits = gen6_rps_limits(dev_priv, &val); WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_delay); @@ -3572,7 +3571,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val) /* Make sure we continue to get interrupts * until we hit the minimum or maximum frequencies. */ - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + gen6_rps_limits(dev_priv, val)); POSTING_READ(GEN6_RPNSWREQ); @@ -3607,48 +3607,18 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->rps.hw_lock); } -/* - * Wait until the previous freq change has completed, - * or the timeout elapsed, and then update our notion - * of the current GPU frequency. - */ -static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv) -{ - u32 pval; - - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); - - if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10)) - DRM_DEBUG_DRIVER("timed out waiting for Punit\n"); - - pval >>= 8; - - if (pval != dev_priv->rps.cur_delay) - DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay), - dev_priv->rps.cur_delay, - vlv_gpu_freq(dev_priv->mem_freq, pval), pval); - - dev_priv->rps.cur_delay = pval; -} - void valleyview_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; - gen6_rps_limits(dev_priv, &val); - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_delay); WARN_ON(val < dev_priv->rps.min_delay); - vlv_update_rps_cur_delay(dev_priv); - DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay, - vlv_gpu_freq(dev_priv->mem_freq, val), val); + vlv_gpu_freq(dev_priv, val), val); if (val == dev_priv->rps.cur_delay) return; @@ -3657,7 +3627,7 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) dev_priv->rps.cur_delay = val; - trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val)); + trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val)); } static void gen6_disable_rps_interrupts(struct drm_device *dev) @@ -3775,7 +3745,7 @@ static void gen8_enable_rps(struct drm_device *dev) /* 1c & 1d: Get forcewake during program sequence. Although the driver * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); /* 2a: Disable RC states. */ I915_WRITE(GEN6_RC_CONTROL, 0); @@ -3832,7 +3802,7 @@ static void gen8_enable_rps(struct drm_device *dev) gen6_enable_rps_interrupts(dev); - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } static void gen6_enable_rps(struct drm_device *dev) @@ -3862,7 +3832,7 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GTFIFODBG, gtfifodbg); } - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); @@ -3954,7 +3924,7 @@ static void gen6_enable_rps(struct drm_device *dev) DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); } - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } void gen6_update_ring_freq(struct drm_device *dev) @@ -4116,7 +4086,8 @@ static void valleyview_enable_rps(struct drm_device *dev) valleyview_setup_pctx(dev); - gen6_gt_force_wake_get(dev_priv); + /* If VLV, Forcewake all wells, else re-direct to regular path */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); @@ -4140,7 +4111,7 @@ static void valleyview_enable_rps(struct drm_device *dev) for_each_ring(ring, dev_priv, i) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); - I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); + I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); /* allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, @@ -4148,65 +4119,47 @@ static void valleyview_enable_rps(struct drm_device *dev) VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) - rc6_mode = GEN7_RC_CTL_TO_MODE; + rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; intel_print_rc6_info(dev, rc6_mode); I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - switch ((val >> 6) & 3) { - case 0: - case 1: - dev_priv->mem_freq = 800; - break; - case 2: - dev_priv->mem_freq = 1066; - break; - case 3: - dev_priv->mem_freq = 1333; - break; - } - DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no"); DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); dev_priv->rps.cur_delay = (val >> 8) & 0xff; DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay); dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv); dev_priv->rps.hw_max = dev_priv->rps.max_delay; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.max_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay), dev_priv->rps.max_delay); dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv); DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.min_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay), dev_priv->rps.min_delay); DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); gen6_enable_rps_interrupts(dev); - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } void ironlake_teardown_rc6(struct drm_device *dev) @@ -5463,6 +5416,26 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) static void valleyview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + mutex_unlock(&dev_priv->rps.hw_lock); + switch ((val >> 6) & 3) { + case 0: + dev_priv->mem_freq = 800; + break; + case 1: + dev_priv->mem_freq = 1066; + break; + case 2: + dev_priv->mem_freq = 1333; + break; + case 3: + dev_priv->mem_freq = 1333; + break; + } + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); @@ -5642,49 +5615,78 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } -static bool is_always_on_power_domain(struct drm_device *dev, - enum intel_display_power_domain domain) -{ - unsigned long always_on_domains; - - BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); +#define for_each_power_well(i, power_well, domain_mask, power_domains) \ + for (i = 0; \ + i < (power_domains)->power_well_count && \ + ((power_well) = &(power_domains)->power_wells[i]); \ + i++) \ + if ((power_well)->domains & (domain_mask)) - if (IS_BROADWELL(dev)) { - always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS; - } else if (IS_HASWELL(dev)) { - always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; - } else { - WARN_ON(1); - return true; - } - - return BIT(domain) & always_on_domains; -} +#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \ + for (i = (power_domains)->power_well_count - 1; \ + i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\ + i--) \ + if ((power_well)->domains & (domain_mask)) /** * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to * be enabled. */ +static bool hsw_power_well_enabled(struct drm_device *dev, + struct i915_power_well *power_well) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(HSW_PWR_WELL_DRIVER) == + (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); +} + +bool intel_display_power_enabled_sw(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains; + + power_domains = &dev_priv->power_domains; + + return power_domains->domain_use_count[domain]; +} + bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains; + struct i915_power_well *power_well; + bool is_enabled; + int i; - if (!HAS_POWER_WELL(dev)) - return true; + power_domains = &dev_priv->power_domains; - if (is_always_on_power_domain(dev, domain)) - return true; + is_enabled = true; - return I915_READ(HSW_PWR_WELL_DRIVER) == - (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); + mutex_lock(&power_domains->lock); + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { + if (power_well->always_on) + continue; + + if (!power_well->is_enabled(dev, power_well)) { + is_enabled = false; + break; + } + } + mutex_unlock(&power_domains->lock); + + return is_enabled; } -static void __intel_set_power_well(struct drm_device *dev, bool enable) +static void hsw_set_power_well(struct drm_device *dev, + struct i915_power_well *power_well, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; + unsigned long irqflags; uint32_t tmp; tmp = I915_READ(HSW_PWR_WELL_DRIVER); @@ -5702,9 +5704,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) HSW_PWR_WELL_STATE_ENABLED), 20)) DRM_ERROR("Timeout enabling power well\n"); } + + if (IS_BROADWELL(dev)) { + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), + dev_priv->de_irq_mask[PIPE_B]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), + ~dev_priv->de_irq_mask[PIPE_B] | + GEN8_PIPE_VBLANK); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), + dev_priv->de_irq_mask[PIPE_C]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), + ~dev_priv->de_irq_mask[PIPE_C] | + GEN8_PIPE_VBLANK); + POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + } } else { if (enable_requested) { - unsigned long irqflags; enum pipe p; I915_WRITE(HSW_PWR_WELL_DRIVER, 0); @@ -5731,16 +5748,17 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) static void __intel_power_well_get(struct drm_device *dev, struct i915_power_well *power_well) { - if (!power_well->count++) - __intel_set_power_well(dev, true); + if (!power_well->count++ && power_well->set) + power_well->set(dev, power_well, true); } static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { WARN_ON(!power_well->count); - if (!--power_well->count && i915_disable_power_well) - __intel_set_power_well(dev, false); + + if (!--power_well->count && power_well->set && i915_disable_power_well) + power_well->set(dev, power_well, false); } void intel_display_power_get(struct drm_device *dev, @@ -5748,17 +5766,18 @@ void intel_display_power_get(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains; - - if (!HAS_POWER_WELL(dev)) - return; - - if (is_always_on_power_domain(dev, domain)) - return; + struct i915_power_well *power_well; + int i; power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_get(dev, &power_domains->power_wells[0]); + + for_each_power_well(i, power_well, BIT(domain), power_domains) + __intel_power_well_get(dev, power_well); + + power_domains->domain_use_count[domain]++; + mutex_unlock(&power_domains->lock); } @@ -5767,17 +5786,19 @@ void intel_display_power_put(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains; - - if (!HAS_POWER_WELL(dev)) - return; - - if (is_always_on_power_domain(dev, domain)) - return; + struct i915_power_well *power_well; + int i; power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_put(dev, &power_domains->power_wells[0]); + + WARN_ON(!power_domains->domain_use_count[domain]); + power_domains->domain_use_count[domain]--; + + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) + __intel_power_well_put(dev, power_well); + mutex_unlock(&power_domains->lock); } @@ -5793,10 +5814,7 @@ void i915_request_power_well(void) dev_priv = container_of(hsw_pwr, struct drm_i915_private, power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5810,24 +5828,71 @@ void i915_release_power_well(void) dev_priv = container_of(hsw_pwr, struct drm_i915_private, power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO); } EXPORT_SYMBOL_GPL(i915_release_power_well); +static struct i915_power_well i9xx_always_on_power_well[] = { + { + .name = "always-on", + .always_on = 1, + .domains = POWER_DOMAIN_MASK, + }, +}; + +static struct i915_power_well hsw_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = HSW_ALWAYS_ON_POWER_DOMAINS, + }, + { + .name = "display", + .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS, + .is_enabled = hsw_power_well_enabled, + .set = hsw_set_power_well, + }, +}; + +static struct i915_power_well bdw_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = BDW_ALWAYS_ON_POWER_DOMAINS, + }, + { + .name = "display", + .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS, + .is_enabled = hsw_power_well_enabled, + .set = hsw_set_power_well, + }, +}; + +#define set_power_wells(power_domains, __power_wells) ({ \ + (power_domains)->power_wells = (__power_wells); \ + (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ +}) + int intel_power_domains_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; mutex_init(&power_domains->lock); - hsw_pwr = power_domains; - power_well = &power_domains->power_wells[0]; - power_well->count = 0; + /* + * The enabling order will be from lower to higher indexed wells, + * the disabling order is reversed. + */ + if (IS_HASWELL(dev)) { + set_power_wells(power_domains, hsw_power_wells); + hsw_pwr = power_domains; + } else if (IS_BROADWELL(dev)) { + set_power_wells(power_domains, bdw_power_wells); + hsw_pwr = power_domains; + } else { + set_power_wells(power_domains, i9xx_always_on_power_well); + } return 0; } @@ -5842,15 +5907,13 @@ static void intel_power_domains_resume(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; struct i915_power_well *power_well; - - if (!HAS_POWER_WELL(dev)) - return; + int i; mutex_lock(&power_domains->lock); - - power_well = &power_domains->power_wells[0]; - __intel_set_power_well(dev, power_well->count > 0); - + for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { + if (power_well->set) + power_well->set(dev, power_well, power_well->count > 0); + } mutex_unlock(&power_domains->lock); } @@ -5864,13 +5927,13 @@ void intel_power_domains_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!HAS_POWER_WELL(dev)) - return; - /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev, true); intel_power_domains_resume(dev); + if (!(IS_HASWELL(dev) || IS_BROADWELL(dev))) + return; + /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST) @@ -6075,59 +6138,48 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) return 0; } -int vlv_gpu_freq(int ddr_freq, int val) +int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val) { - int mult, base; + int div; - switch (ddr_freq) { + /* 4 x czclk */ + switch (dev_priv->mem_freq) { case 800: - mult = 20; - base = 120; + div = 10; break; case 1066: - mult = 22; - base = 133; + div = 12; break; case 1333: - mult = 21; - base = 125; + div = 16; break; default: return -1; } - return ((val - 0xbd) * mult) + base; + return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div); } -int vlv_freq_opcode(int ddr_freq, int val) +int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) { - int mult, base; + int mul; - switch (ddr_freq) { + /* 4 x czclk */ + switch (dev_priv->mem_freq) { case 800: - mult = 20; - base = 120; + mul = 10; break; case 1066: - mult = 22; - base = 133; + mul = 12; break; case 1333: - mult = 21; - base = 125; + mul = 16; break; default: return -1; } - val /= mult; - val -= base / mult; - val += 0xbd; - - if (val > 0xea) - val = 0xea; - - return val; + return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6; } void intel_pm_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337e6d67..e05a0216cd9b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -285,14 +285,16 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) if (!ring->fbc_dirty) return 0; - ret = intel_ring_begin(ring, 4); + ret = intel_ring_begin(ring, 6); if (ret) return ret; - intel_ring_emit(ring, MI_NOOP); /* WaFbcNukeOn3DBlt:ivb/hsw */ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, MSG_FBC_REND_STATE); intel_ring_emit(ring, value); + intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT); + intel_ring_emit(ring, MSG_FBC_REND_STATE); + intel_ring_emit(ring, ring->scratch.gtt_offset + 256); intel_ring_advance(ring); ring->fbc_dirty = false; @@ -354,7 +356,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, 0); intel_ring_advance(ring); - if (flush_domains) + if (!invalidate_domains && flush_domains) return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); return 0; @@ -436,7 +438,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) int ret = 0; u32 head; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); if (I915_NEED_GFX_HWS(dev)) intel_ring_setup_status_page(ring); @@ -509,7 +511,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); out: - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); return ret; } @@ -965,6 +967,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); } else { + /* XXX: gen8 returns to sanity */ mmio = RING_HWS_PGA(ring->mmio_base); } @@ -1029,11 +1032,6 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) if (!dev->irq_enabled) return false; - /* It looks like we need to prevent the gt from suspending while waiting - * for an notifiy irq, otherwise irqs seem to get lost on at least the - * blt/bsd rings on ivb. */ - gen6_gt_force_wake_get(dev_priv); - spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { if (HAS_L3_DPF(dev) && ring->id == RCS) @@ -1065,8 +1063,6 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); - - gen6_gt_force_wake_put(dev_priv); } static bool @@ -1837,7 +1833,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, } intel_ring_advance(ring); - if (IS_GEN7(dev) && flush) + if (IS_GEN7(dev) && !invalidate && flush) return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); return 0; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a583e8f718a7..2abeab09e883 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -413,23 +413,34 @@ static const struct _sdvo_cmd_name { static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, const void *args, int args_len) { - int i; + int i, pos = 0; +#define BUF_LEN 256 + char buffer[BUF_LEN]; + +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args) + - DRM_DEBUG_KMS("%s: W: %02X ", - SDVO_NAME(intel_sdvo), cmd); - for (i = 0; i < args_len; i++) - DRM_LOG_KMS("%02X ", ((u8 *)args)[i]); - for (; i < 8; i++) - DRM_LOG_KMS(" "); + for (i = 0; i < args_len; i++) { + BUF_PRINT("%02X ", ((u8 *)args)[i]); + } + for (; i < 8; i++) { + BUF_PRINT(" "); + } for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { if (cmd == sdvo_cmd_names[i].cmd) { - DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name); + BUF_PRINT("(%s)", sdvo_cmd_names[i].name); break; } } - if (i == ARRAY_SIZE(sdvo_cmd_names)) - DRM_LOG_KMS("(%02X)", cmd); - DRM_LOG_KMS("\n"); + if (i == ARRAY_SIZE(sdvo_cmd_names)) { + BUF_PRINT("(%02X)", cmd); + } + BUG_ON(pos >= BUF_LEN - 1); +#undef BUF_PRINT +#undef BUF_LEN + + DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); } static const char *cmd_status_names[] = { @@ -512,9 +523,10 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, { u8 retry = 15; /* 5 quick checks, followed by 10 long checks */ u8 status; - int i; + int i, pos = 0; +#define BUF_LEN 256 + char buffer[BUF_LEN]; - DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); /* * The documentation states that all commands will be @@ -551,10 +563,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, goto log_fail; } +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args) + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - DRM_LOG_KMS("(%s)", cmd_status_names[status]); + BUF_PRINT("(%s)", cmd_status_names[status]); else - DRM_LOG_KMS("(??? %d)", status); + BUF_PRINT("(??? %d)", status); if (status != SDVO_CMD_STATUS_SUCCESS) goto log_fail; @@ -565,13 +580,17 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, SDVO_I2C_RETURN_0 + i, &((u8 *)response)[i])) goto log_fail; - DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); + BUF_PRINT(" %02X", ((u8 *)response)[i]); } - DRM_LOG_KMS("\n"); + BUG_ON(pos >= BUF_LEN - 1); +#undef BUF_PRINT +#undef BUF_LEN + + DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer); return true; log_fail: - DRM_LOG_KMS("... failed\n"); + DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo)); return false; } @@ -1517,8 +1536,9 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_sdvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 9944d8135e87..cc6fbcde7d3d 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -90,6 +90,22 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) mutex_unlock(&dev_priv->dpio_lock); } +u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg) +{ + u32 val = 0; + + vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + PUNIT_OPCODE_REG_READ, reg, &val); + + return val; +} + +void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +{ + vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + PUNIT_OPCODE_REG_WRITE, reg, &val); +} + u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) { u32 val = 0; @@ -160,27 +176,18 @@ void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) PUNIT_OPCODE_REG_WRITE, reg, &val); } -static u32 vlv_get_phy_port(enum pipe pipe) -{ - u32 port = IOSF_PORT_DPIO; - - WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B)); - - return port; -} - u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)), DPIO_OPCODE_REG_READ, reg, &val); return val; } void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val) { - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)), DPIO_OPCODE_REG_WRITE, reg, &val); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b9fabf826f7d..90a3f6db8288 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, break; } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + sprctl |= SP_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) sprctl |= SP_TILED; @@ -257,6 +263,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, BUG(); } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + sprctl |= SPRITE_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) sprctl |= SPRITE_TILED; @@ -453,6 +465,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, BUG(); } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + dvscntr |= DVS_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) dvscntr |= DVS_TILED; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0b02078a0b84..0db5472b4dcd 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -64,7 +64,8 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, ECOBUS); } -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) { if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0, FORCEWAKE_ACK_TIMEOUT_MS)) @@ -89,7 +90,8 @@ static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, ECOBUS); } -static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv, + int fw_engine) { u32 forcewake_ack; @@ -121,12 +123,12 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) u32 gtfifodbg; gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG); - if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, - "MMIO read or write has been dropped %x\n", gtfifodbg)) - __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); + if (WARN(gtfifodbg, "GT wake FIFO error 0x%x\n", gtfifodbg)) + __raw_i915_write32(dev_priv, GTFIFODBG, gtfifodbg); } -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) { __raw_i915_write32(dev_priv, FORCEWAKE, 0); /* something from same cacheline, but !FORCEWAKE */ @@ -134,7 +136,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) gen6_gt_check_fifodbg(dev_priv); } -static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv, + int fw_engine) { __raw_i915_write32(dev_priv, FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); @@ -149,10 +152,10 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { int loop = 500; - u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { udelay(10); - fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; } if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) ++ret; @@ -171,38 +174,112 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV); } -static void vlv_force_wake_get(struct drm_i915_private *dev_priv) +static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) { - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0, - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); + /* Check for Render Engine */ + if (FORCEWAKE_RENDER & fw_engine) { + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_VLV) & + FORCEWAKE_KERNEL) == 0, + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: Render forcewake old ack to clear.\n"); - __raw_i915_write32(dev_priv, FORCEWAKE_VLV, - _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, - _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); + __raw_i915_write32(dev_priv, FORCEWAKE_VLV, + _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL), - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n"); + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_VLV) & + FORCEWAKE_KERNEL), + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: waiting for Render to ack.\n"); + } - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) & - FORCEWAKE_KERNEL), - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for media to ack forcewake request.\n"); + /* Check for Media Engine */ + if (FORCEWAKE_MEDIA & fw_engine) { + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_MEDIA_VLV) & + FORCEWAKE_KERNEL) == 0, + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: Media forcewake old ack to clear.\n"); + + __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, + _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); + + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_MEDIA_VLV) & + FORCEWAKE_KERNEL), + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: waiting for media to ack.\n"); + } /* WaRsForcewakeWaitTC0:vlv */ __gen6_gt_wait_for_thread_c0(dev_priv); + } -static void vlv_force_wake_put(struct drm_i915_private *dev_priv) +static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) { - __raw_i915_write32(dev_priv, FORCEWAKE_VLV, - _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, - _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + + /* Check for Render Engine */ + if (FORCEWAKE_RENDER & fw_engine) + __raw_i915_write32(dev_priv, FORCEWAKE_VLV, + _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + + + /* Check for Media Engine */ + if (FORCEWAKE_MEDIA & fw_engine) + __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, + _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + /* The below doubles as a POSTING_READ */ gen6_gt_check_fifodbg(dev_priv); + +} + +void vlv_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (FORCEWAKE_RENDER & fw_engine) { + if (dev_priv->uncore.fw_rendercount++ == 0) + dev_priv->uncore.funcs.force_wake_get(dev_priv, + FORCEWAKE_RENDER); + } + if (FORCEWAKE_MEDIA & fw_engine) { + if (dev_priv->uncore.fw_mediacount++ == 0) + dev_priv->uncore.funcs.force_wake_get(dev_priv, + FORCEWAKE_MEDIA); + } + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +void vlv_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + if (FORCEWAKE_RENDER & fw_engine) { + WARN_ON(dev_priv->uncore.fw_rendercount == 0); + if (--dev_priv->uncore.fw_rendercount == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv, + FORCEWAKE_RENDER); + } + + if (FORCEWAKE_MEDIA & fw_engine) { + WARN_ON(dev_priv->uncore.fw_mediacount == 0); + if (--dev_priv->uncore.fw_mediacount == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv, + FORCEWAKE_MEDIA); + } + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void gen6_force_wake_work(struct work_struct *work) @@ -213,7 +290,7 @@ static void gen6_force_wake_work(struct work_struct *work) spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (--dev_priv->uncore.forcewake_count == 0) - dev_priv->uncore.funcs.force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -281,29 +358,38 @@ void intel_uncore_sanitize(struct drm_device *dev) * be called at the beginning of the sequence followed by a call to * gen6_gt_force_wake_put() at the end of the sequence. */ -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) { unsigned long irqflags; if (!dev_priv->uncore.funcs.force_wake_get) return; + /* Redirect to VLV specific routine */ + if (IS_VALLEYVIEW(dev_priv->dev)) + return vlv_force_wake_get(dev_priv, fw_engine); + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (dev_priv->uncore.forcewake_count++ == 0) - dev_priv->uncore.funcs.force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } /* * see gen6_gt_force_wake_get() */ -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) { unsigned long irqflags; if (!dev_priv->uncore.funcs.force_wake_put) return; + /* Redirect to VLV specific routine */ + if (IS_VALLEYVIEW(dev_priv->dev)) + return vlv_force_wake_put(dev_priv, fw_engine); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (--dev_priv->uncore.forcewake_count == 0) { dev_priv->uncore.forcewake_count++; @@ -379,16 +465,51 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ REG_READ_HEADER(x); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ if (dev_priv->uncore.forcewake_count == 0) \ - dev_priv->uncore.funcs.force_wake_get(dev_priv); \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, \ + FORCEWAKE_ALL); \ val = __raw_i915_read##x(dev_priv, reg); \ if (dev_priv->uncore.forcewake_count == 0) \ - dev_priv->uncore.funcs.force_wake_put(dev_priv); \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, \ + FORCEWAKE_ALL); \ + } else { \ + val = __raw_i915_read##x(dev_priv, reg); \ + } \ + REG_READ_FOOTER; \ +} + +#define __vlv_read(x) \ +static u##x \ +vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ + unsigned fwengine = 0; \ + unsigned *fwcount; \ + REG_READ_HEADER(x); \ + if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) { \ + fwengine = FORCEWAKE_RENDER; \ + fwcount = &dev_priv->uncore.fw_rendercount; \ + } \ + else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) { \ + fwengine = FORCEWAKE_MEDIA; \ + fwcount = &dev_priv->uncore.fw_mediacount; \ + } \ + if (fwengine != 0) { \ + if ((*fwcount)++ == 0) \ + (dev_priv)->uncore.funcs.force_wake_get(dev_priv, \ + fwengine); \ + val = __raw_i915_read##x(dev_priv, reg); \ + if (--(*fwcount) == 0) \ + (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \ + fwengine); \ } else { \ val = __raw_i915_read##x(dev_priv, reg); \ } \ REG_READ_FOOTER; \ } + +__vlv_read(8) +__vlv_read(16) +__vlv_read(32) +__vlv_read(64) __gen6_read(8) __gen6_read(16) __gen6_read(32) @@ -402,6 +523,7 @@ __gen4_read(16) __gen4_read(32) __gen4_read(64) +#undef __vlv_read #undef __gen6_read #undef __gen5_read #undef __gen4_read @@ -489,11 +611,13 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \ REG_WRITE_HEADER; \ if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_get(dev_priv); \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, \ + FORCEWAKE_ALL); \ } \ __raw_i915_write##x(dev_priv, reg, val); \ if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_put(dev_priv); \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, \ + FORCEWAKE_ALL); \ } \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ } @@ -534,8 +658,8 @@ void intel_uncore_init(struct drm_device *dev) gen6_force_wake_work); if (IS_VALLEYVIEW(dev)) { - dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get; - dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put; + dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; + dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; } else if (IS_HASWELL(dev) || IS_GEN8(dev)) { dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; @@ -552,9 +676,9 @@ void intel_uncore_init(struct drm_device *dev) * forcewake being disabled. */ mutex_lock(&dev->struct_mutex); - __gen6_gt_force_wake_mt_get(dev_priv); + __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL); ecobus = __raw_i915_read32(dev_priv, ECOBUS); - __gen6_gt_force_wake_mt_put(dev_priv); + __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); if (ecobus & FORCEWAKE_MT_ENABLE) { @@ -601,10 +725,18 @@ void intel_uncore_init(struct drm_device *dev) dev_priv->uncore.funcs.mmio_writel = gen6_write32; dev_priv->uncore.funcs.mmio_writeq = gen6_write64; } - dev_priv->uncore.funcs.mmio_readb = gen6_read8; - dev_priv->uncore.funcs.mmio_readw = gen6_read16; - dev_priv->uncore.funcs.mmio_readl = gen6_read32; - dev_priv->uncore.funcs.mmio_readq = gen6_read64; + + if (IS_VALLEYVIEW(dev)) { + dev_priv->uncore.funcs.mmio_readb = vlv_read8; + dev_priv->uncore.funcs.mmio_readw = vlv_read16; + dev_priv->uncore.funcs.mmio_readl = vlv_read32; + dev_priv->uncore.funcs.mmio_readq = vlv_read64; + } else { + dev_priv->uncore.funcs.mmio_readb = gen6_read8; + dev_priv->uncore.funcs.mmio_readw = gen6_read16; + dev_priv->uncore.funcs.mmio_readl = gen6_read32; + dev_priv->uncore.funcs.mmio_readq = gen6_read64; + } break; case 5: dev_priv->uncore.funcs.mmio_writeb = gen5_write8; @@ -687,6 +819,43 @@ int i915_reg_read_ioctl(struct drm_device *dev, return 0; } +int i915_get_reset_stats_ioctl(struct drm_device *dev, + void *data, struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_reset_stats *args = data; + struct i915_ctx_hang_stats *hs; + int ret; + + if (args->flags || args->pad) + return -EINVAL; + + if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id); + if (IS_ERR(hs)) { + mutex_unlock(&dev->struct_mutex); + return PTR_ERR(hs); + } + + if (capable(CAP_SYS_ADMIN)) + args->reset_count = i915_reset_count(&dev_priv->gpu_error); + else + args->reset_count = 0; + + args->batch_active = hs->batch_active; + args->batch_pending = hs->batch_pending; + + mutex_unlock(&dev->struct_mutex); + + return 0; +} + static int i965_reset_complete(struct drm_device *dev) { u8 gdrst; @@ -770,12 +939,12 @@ static int gen6_do_reset(struct drm_device *dev) /* If reset with a user forcewake, try to restore, otherwise turn it off */ if (dev_priv->uncore.forcewake_count) - dev_priv->uncore.funcs.force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); else - dev_priv->uncore.funcs.force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); /* Restore fifo count */ - dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); return ret; @@ -784,6 +953,7 @@ static int gen6_do_reset(struct drm_device *dev) int intel_gpu_reset(struct drm_device *dev) { switch (INTEL_INFO(dev)->gen) { + case 8: case 7: case 6: return gen6_do_reset(dev); case 5: return ironlake_do_reset(dev); @@ -792,15 +962,6 @@ int intel_gpu_reset(struct drm_device *dev) } } -void intel_uncore_clear_errors(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - /* XXX needs spinlock around caller's grouping */ - if (HAS_FPGA_DBG_UNCLAIMED(dev)) - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); -} - void intel_uncore_check_errors(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 087db33f6cff..c3bf059ba720 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -1075,10 +1075,10 @@ static int mga_dma_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index ca4bc54ea214..fe453213600a 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -186,14 +186,14 @@ extern void mga_disable_vblank(struct drm_device *dev, int crtc); extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc); extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence); extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); -extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t mga_driver_irq_handler(int irq, void *arg); extern void mga_driver_irq_preinstall(struct drm_device *dev); extern int mga_driver_irq_postinstall(struct drm_device *dev); extern void mga_driver_irq_uninstall(struct drm_device *dev); extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() +#define mga_flush_write_combine() wmb() #define MGA_READ8(reg) DRM_READ8(dev_priv->mmio, (reg)) #define MGA_READ(reg) DRM_READ32(dev_priv->mmio, (reg)) diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index 2b0ceb8dc11b..1b071b8ff9dc 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -47,7 +47,7 @@ u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) } -irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) +irqreturn_t mga_driver_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; @@ -79,7 +79,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) MGA_WRITE(MGA_PRIMEND, prim_end); atomic_inc(&dev_priv->last_fence_retired); - DRM_WAKEUP(&dev_priv->fence_queue); + wake_up(&dev_priv->fence_queue); handled = 1; } @@ -128,7 +128,7 @@ int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) * by about a day rather than she wants to wait for years * using fences. */ - DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * HZ, (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) - *sequence) <= (1 << 23))); @@ -151,7 +151,7 @@ int mga_driver_irq_postinstall(struct drm_device *dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); + init_waitqueue_head(&dev_priv->fence_queue); /* Turn on soft trap interrupt. Vertical blank interrupts are enabled * in mga_enable_vblank. diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c index 37cc2fb4eadd..314685b7f41f 100644 --- a/drivers/gpu/drm/mga/mga_state.c +++ b/drivers/gpu/drm/mga/mga_state.c @@ -1029,7 +1029,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil return -EINVAL; } - if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { + if (copy_to_user(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 86537692e45c..28b57eb6f9a1 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -326,7 +326,7 @@ static void msm_lastclose(struct drm_device *dev) } } -static irqreturn_t msm_irq(DRM_IRQ_ARGS) +static irqreturn_t msm_irq(int irq, void *arg) { struct drm_device *dev = arg; struct msm_drm_private *priv = dev->dev_private; @@ -783,7 +783,7 @@ static int msm_pdev_probe(struct platform_device *pdev) static int msm_pdev_remove(struct platform_device *pdev) { - drm_platform_exit(&msm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 40f91e1e5842..c177272152e2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -100,7 +100,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max; - DRM_MEMORYBARRIER(); + mb(); /* Flush writes. */ nouveau_bo_rd32(pb, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 984004d66a6d..dc0e0c5cadb4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -155,7 +155,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data) } #define WRITE_PUT(val) do { \ - DRM_MEMORYBARRIER(); \ + mb(); \ nouveau_bo_rd32(chan->push.buffer, 0); \ nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ } while (0) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 40cf52e6d6d2..90074d620e31 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -143,7 +143,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) int ret; fence->channel = chan; - fence->timeout = jiffies + (15 * DRM_HZ); + fence->timeout = jiffies + (15 * HZ); fence->sequence = ++fctx->sequence; ret = fctx->emit(fence); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 78a27f8ad7d9..0447163cd2b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -506,7 +506,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, b->presumed.valid = 0; relocs++; - if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, + if (copy_to_user(&upbbo[nvbo->pbbo_index].presumed, &b->presumed, sizeof(b->presumed))) return -EFAULT; } @@ -593,7 +593,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) if (!mem) return ERR_PTR(-ENOMEM); - if (DRM_COPY_FROM_USER(mem, userptr, size)) { + if (copy_from_user(mem, userptr, size)) { u_free(mem); return ERR_PTR(-EFAULT); } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index e7fa3cd96743..13f294aeaefd 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -665,9 +665,9 @@ static int pdev_probe(struct platform_device *device) static int pdev_remove(struct platform_device *device) { DBG(""); - drm_platform_exit(&omap_drm_driver, device); - platform_driver_unregister(&omap_dmm_driver); + drm_put_dev(platform_get_drvdata(device)); + return 0; } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 07847693cf49..c88fea32dbf6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -141,7 +141,7 @@ int omap_gem_resume(struct device *dev); int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id); void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id); -irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); +irqreturn_t omap_irq_handler(int irq, void *arg); void omap_irq_preinstall(struct drm_device *dev); int omap_irq_postinstall(struct drm_device *dev); void omap_irq_uninstall(struct drm_device *dev); diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index f2b8f0668c0c..f466c4aaee94 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -123,12 +123,16 @@ static int omap_framebuffer_dirty(struct drm_framebuffer *fb, { int i; + drm_modeset_lock_all(fb->dev); + for (i = 0; i < num_clips; i++) { omap_framebuffer_flush(fb, clips[i].x1, clips[i].y1, clips[i].x2 - clips[i].x1, clips[i].y2 - clips[i].y1); } + drm_modeset_unlock_all(fb->dev); + return 0; } diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index cb858600185f..0e5336e5a791 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c @@ -173,7 +173,7 @@ void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id) dispc_runtime_put(); } -irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) +irqreturn_t omap_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct omap_drm_private *priv = dev->dev_private; @@ -308,7 +308,7 @@ int omap_drm_irq_uninstall(struct drm_device *dev) if (dev->num_crtcs) { spin_lock_irqsave(&dev->vbl_lock, irqflags); for (i = 0; i < dev->num_crtcs; i++) { - DRM_WAKEUP(&dev->vblank[i].queue); + wake_up(&dev->vblank[i].queue); dev->vblank[i].enabled = false; dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 5e827c29d194..b8f3bc7cf8f0 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -399,10 +399,14 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, struct qxl_bo *qobj; int inc = 1; + drm_modeset_lock_all(fb->dev); + qobj = gem_to_qxl_bo(qxl_fb->obj); /* if we aren't primary surface ignore this */ - if (!qobj->is_primary) + if (!qobj->is_primary) { + drm_modeset_unlock_all(fb->dev); return 0; + } if (!num_clips) { num_clips = 1; @@ -417,6 +421,9 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color, clips, num_clips, inc); + + drm_modeset_unlock_all(fb->dev); + return 0; } diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 7bda32f68d3b..36ed40ba773f 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -534,7 +534,7 @@ void qxl_debugfs_takedown(struct drm_minor *minor); /* qxl_irq.c */ int qxl_irq_init(struct qxl_device *qdev); -irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS); +irqreturn_t qxl_irq_handler(int irq, void *arg); /* qxl_fb.c */ int qxl_fb_init(struct qxl_device *qdev); diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 7b95c75e9626..0bb86e6d41b4 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -200,7 +200,7 @@ static int qxl_process_single_command(struct qxl_device *qdev, for (i = 0; i < cmd->relocs_num; ++i) { struct drm_qxl_reloc reloc; - if (DRM_COPY_FROM_USER(&reloc, + if (copy_from_user(&reloc, &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i], sizeof(reloc))) { ret = -EFAULT; @@ -297,7 +297,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, struct drm_qxl_command *commands = (struct drm_qxl_command *)(uintptr_t)execbuffer->commands; - if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num], + if (copy_from_user(&user_cmd, &commands[cmd_num], sizeof(user_cmd))) return -EFAULT; diff --git a/drivers/gpu/drm/qxl/qxl_irq.c b/drivers/gpu/drm/qxl/qxl_irq.c index 21393dc4700a..28f84b4fce32 100644 --- a/drivers/gpu/drm/qxl/qxl_irq.c +++ b/drivers/gpu/drm/qxl/qxl_irq.c @@ -25,7 +25,7 @@ #include "qxl_drv.h" -irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS) +irqreturn_t qxl_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct qxl_device *qdev = (struct qxl_device *)dev->dev_private; diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index c451257f08fb..59459fe4e8c5 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -892,10 +892,10 @@ static int r128_cce_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 56eb5e3f5439..5bf3f5ff805d 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h @@ -154,7 +154,7 @@ extern int r128_do_cleanup_cce(struct drm_device *dev); extern int r128_enable_vblank(struct drm_device *dev, int crtc); extern void r128_disable_vblank(struct drm_device *dev, int crtc); extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc); -extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t r128_driver_irq_handler(int irq, void *arg); extern void r128_driver_irq_preinstall(struct drm_device *dev); extern int r128_driver_irq_postinstall(struct drm_device *dev); extern void r128_driver_irq_uninstall(struct drm_device *dev); @@ -514,7 +514,7 @@ do { \ if (R128_VERBOSE) \ DRM_INFO("COMMIT_RING() tail=0x%06x\n", \ dev_priv->ring.tail); \ - DRM_MEMORYBARRIER(); \ + mb(); \ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail); \ R128_READ(R128_PM4_BUFFER_DL_WPTR); \ } while (0) diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c index 2ea4f09d2691..c2ae496babb7 100644 --- a/drivers/gpu/drm/r128/r128_irq.c +++ b/drivers/gpu/drm/r128/r128_irq.c @@ -44,7 +44,7 @@ u32 r128_get_vblank_counter(struct drm_device *dev, int crtc) return atomic_read(&dev_priv->vbl_received); } -irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) +irqreturn_t r128_driver_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c index 01dd9aef9f0e..e806dacd452f 100644 --- a/drivers/gpu/drm/r128/r128_state.c +++ b/drivers/gpu/drm/r128/r128_state.c @@ -895,31 +895,22 @@ static int r128_cce_dispatch_write_span(struct drm_device *dev, if (count > 4096 || count <= 0) return -EMSGSIZE; - if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) + if (copy_from_user(&x, depth->x, sizeof(x))) return -EFAULT; - if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) + if (copy_from_user(&y, depth->y, sizeof(y))) return -EFAULT; buffer_size = depth->n * sizeof(u32); - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; - if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { - kfree(buffer); - return -EFAULT; - } + buffer = memdup_user(depth->buffer, buffer_size); + if (IS_ERR(buffer)) + return PTR_ERR(buffer); mask_size = depth->n * sizeof(u8); if (depth->mask) { - mask = kmalloc(mask_size, GFP_KERNEL); - if (mask == NULL) { + mask = memdup_user(depth->mask, mask_size); + if (IS_ERR(mask)) { kfree(buffer); - return -ENOMEM; - } - if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { - kfree(buffer); - kfree(mask); - return -EFAULT; + return PTR_ERR(mask); } for (i = 0; i < count; i++, x++) { @@ -999,46 +990,33 @@ static int r128_cce_dispatch_write_pixels(struct drm_device *dev, kfree(x); return -ENOMEM; } - if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { + if (copy_from_user(x, depth->x, xbuf_size)) { kfree(x); kfree(y); return -EFAULT; } - if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) { + if (copy_from_user(y, depth->y, xbuf_size)) { kfree(x); kfree(y); return -EFAULT; } buffer_size = depth->n * sizeof(u32); - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (buffer == NULL) { - kfree(x); - kfree(y); - return -ENOMEM; - } - if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { + buffer = memdup_user(depth->buffer, buffer_size); + if (IS_ERR(buffer)) { kfree(x); kfree(y); - kfree(buffer); - return -EFAULT; + return PTR_ERR(buffer); } if (depth->mask) { mask_size = depth->n * sizeof(u8); - mask = kmalloc(mask_size, GFP_KERNEL); - if (mask == NULL) { - kfree(x); - kfree(y); - kfree(buffer); - return -ENOMEM; - } - if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { + mask = memdup_user(depth->mask, mask_size); + if (IS_ERR(mask)) { kfree(x); kfree(y); kfree(buffer); - kfree(mask); - return -EFAULT; + return PTR_ERR(mask); } for (i = 0; i < count; i++) { @@ -1107,9 +1085,9 @@ static int r128_cce_dispatch_read_span(struct drm_device *dev, if (count > 4096 || count <= 0) return -EMSGSIZE; - if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) + if (copy_from_user(&x, depth->x, sizeof(x))) return -EFAULT; - if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) + if (copy_from_user(&y, depth->y, sizeof(y))) return -EFAULT; BEGIN_RING(7); @@ -1162,12 +1140,12 @@ static int r128_cce_dispatch_read_pixels(struct drm_device *dev, kfree(x); return -ENOMEM; } - if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { + if (copy_from_user(x, depth->x, xbuf_size)) { kfree(x); kfree(y); return -EFAULT; } - if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) { + if (copy_from_user(y, depth->y, ybuf_size)) { kfree(x); kfree(y); return -EFAULT; @@ -1524,7 +1502,7 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file DEV_INIT_TEST_WITH_RETURN(dev_priv); - if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1622,7 +1600,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi return -EINVAL; } - if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { + if (copy_to_user(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index fb3ae07a1469..37289f67f965 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -157,7 +157,7 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, msg[0] = address; msg[1] = address >> 8; - msg[2] = AUX_NATIVE_WRITE << 4; + msg[2] = DP_AUX_NATIVE_WRITE << 4; msg[3] = (msg_bytes << 4) | (send_bytes - 1); memcpy(&msg[4], send, send_bytes); @@ -168,9 +168,10 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, continue; else if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) return send_bytes; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(400); else return -EIO; @@ -191,7 +192,7 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, msg[0] = address; msg[1] = address >> 8; - msg[2] = AUX_NATIVE_READ << 4; + msg[2] = DP_AUX_NATIVE_READ << 4; msg[3] = (msg_bytes << 4) | (recv_bytes - 1); for (retry = 0; retry < 4; retry++) { @@ -201,9 +202,10 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, continue; else if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) return ret; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) udelay(400); else if (ret == 0) return -EPROTO; @@ -246,12 +248,12 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, /* Set up the command byte */ if (mode & MODE_I2C_READ) - msg[2] = AUX_I2C_READ << 4; + msg[2] = DP_AUX_I2C_READ << 4; else - msg[2] = AUX_I2C_WRITE << 4; + msg[2] = DP_AUX_I2C_WRITE << 4; if (!(mode & MODE_I2C_STOP)) - msg[2] |= AUX_I2C_MOT << 4; + msg[2] |= DP_AUX_I2C_MOT << 4; msg[0] = address; msg[1] = address >> 8; @@ -282,16 +284,16 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, return ret; } - switch (ack & AUX_NATIVE_REPLY_MASK) { - case AUX_NATIVE_REPLY_ACK: + switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { + case DP_AUX_NATIVE_REPLY_ACK: /* I2C-over-AUX Reply field is only valid * when paired with AUX ACK. */ break; - case AUX_NATIVE_REPLY_NACK: + case DP_AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); return -EREMOTEIO; - case AUX_NATIVE_REPLY_DEFER: + case DP_AUX_NATIVE_REPLY_DEFER: DRM_DEBUG_KMS("aux_ch native defer\n"); udelay(400); continue; @@ -300,15 +302,15 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, return -EREMOTEIO; } - switch (ack & AUX_I2C_REPLY_MASK) { - case AUX_I2C_REPLY_ACK: + switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { + case DP_AUX_I2C_REPLY_ACK: if (mode == MODE_I2C_READ) *read_byte = reply[0]; return ret; - case AUX_I2C_REPLY_NACK: + case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); return -EREMOTEIO; - case AUX_I2C_REPLY_DEFER: + case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(400); break; diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 60170ea5e3a2..84b1d5367a11 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -75,7 +75,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); for (i = 0; i < nr; ++i) { - if (DRM_COPY_FROM_USER + if (copy_from_user (&box, &cmdbuf->boxes[n + i], sizeof(box))) { DRM_ERROR("copy cliprect faulted\n"); return -EFAULT; @@ -928,12 +928,12 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); *buf_idx *= 2; /* 8 bytes per buf */ - if (DRM_COPY_TO_USER(ref_age_base + *buf_idx, + if (copy_to_user(ref_age_base + *buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) return -EINVAL; - if (DRM_COPY_FROM_USER(&h_pending, + if (copy_from_user(&h_pending, ref_age_base + *buf_idx + 1, sizeof(u32))) return -EINVAL; @@ -943,7 +943,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, h_pending--; - if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1, + if (copy_to_user(ref_age_base + *buf_idx + 1, &h_pending, sizeof(u32))) return -EINVAL; diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index d8eb48bff0ed..8c9b7e26533c 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c @@ -2515,7 +2515,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, buf = radeon_freelist_get(dev); if (!buf) { DRM_DEBUG("EAGAIN\n"); - if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + if (copy_to_user(tex->image, image, sizeof(*image))) return -EFAULT; return -EAGAIN; } @@ -2528,7 +2528,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, buffer = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); - if (DRM_COPY_FROM_USER(buffer, data, pass_size)) { + if (copy_from_user(buffer, data, pass_size)) { DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 5dceea6f71ae..d824f7fed47d 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -2386,7 +2386,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, ib_chunk = &parser.chunks[parser.chunk_ib_idx]; parser.ib.length_dw = ib_chunk->length_dw; *l = parser.ib.length_dw; - if (DRM_COPY_FROM_USER(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) { + if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) { r = -EFAULT; r600_cs_parser_fini(&parser, r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 3cae2bbc1854..bb0d5c3a8311 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2020,10 +2020,10 @@ static int radeon_cp_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; @@ -2228,7 +2228,7 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv) dev_priv->ring.tail &= dev_priv->ring.tail_mask; - DRM_MEMORYBARRIER(); + mb(); GET_RING_HEAD( dev_priv ); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 0b366169d64d..a8e3342fd4a9 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -192,7 +192,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) return -ENOMEM; } chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); - if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr, + if (copy_from_user(p->chunks_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) { return -EFAULT; } @@ -208,7 +208,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) uint32_t __user *cdata; chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i]; - if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, + if (copy_from_user(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))) { return -EFAULT; } @@ -252,7 +252,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) if (p->chunks[i].kdata == NULL) { return -ENOMEM; } - if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) { + if (copy_from_user(p->chunks[i].kdata, cdata, size)) { return -EFAULT; } if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { @@ -472,7 +472,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser } parser->const_ib.is_const_ib = true; parser->const_ib.length_dw = ib_chunk->length_dw; - if (DRM_COPY_FROM_USER(parser->const_ib.ptr, + if (copy_from_user(parser->const_ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) return -EFAULT; @@ -495,7 +495,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser parser->ib.length_dw = ib_chunk->length_dw; if (ib_chunk->kdata) memcpy(parser->ib.ptr, ib_chunk->kdata, ib_chunk->length_dw * 4); - else if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) + else if (copy_from_user(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) return -EFAULT; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9f5ff28864f6..f6f30b9e9ff5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -101,7 +101,7 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, void radeon_driver_irq_preinstall_kms(struct drm_device *dev); int radeon_driver_irq_postinstall_kms(struct drm_device *dev); void radeon_driver_irq_uninstall_kms(struct drm_device *dev); -irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); +irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg); void radeon_gem_object_free(struct drm_gem_object *obj); int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 00e0d449021c..dafd812e4571 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -405,7 +405,7 @@ extern void radeon_do_release(struct drm_device * dev); extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); extern int radeon_enable_vblank(struct drm_device *dev, int crtc); extern void radeon_disable_vblank(struct drm_device *dev, int crtc); -extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg); extern void radeon_driver_irq_preinstall(struct drm_device * dev); extern int radeon_driver_irq_postinstall(struct drm_device *dev); extern void radeon_driver_irq_uninstall(struct drm_device * dev); diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 8d68e972789a..244b19bab2e7 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -181,7 +181,7 @@ static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_dis * tied to dma at all, this is just a hangover from dri prehistory. */ -irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) +irqreturn_t radeon_driver_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_radeon_private_t *dev_priv = @@ -203,7 +203,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) - DRM_WAKEUP(&dev_priv->swi_queue); + wake_up(&dev_priv->swi_queue); /* VBLANK interrupt */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { @@ -249,7 +249,7 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ, RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); return ret; @@ -302,7 +302,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr result = radeon_emit_irq(dev); - if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { + if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } @@ -354,7 +354,7 @@ int radeon_driver_irq_postinstall(struct drm_device *dev) (drm_radeon_private_t *) dev->dev_private; atomic_set(&dev_priv->swi_emitted, 0); - DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + init_waitqueue_head(&dev_priv->swi_queue); dev->max_vblank_count = 0x001fffff; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index ec6240b00469..089c9ffb0aa9 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -39,13 +39,13 @@ /** * radeon_driver_irq_handler_kms - irq handler for KMS * - * @DRM_IRQ_ARGS: args + * @int irq, void *arg: args * * This is the irq handler for the radeon KMS driver (all asics). * radeon_irq_process is a macro that points to the per-asic * irq handler callback. */ -irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) +irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 55d0b474bd37..daa28b6a6832 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -223,7 +223,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -269,7 +269,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) * * When returning, the value is 1 if filp owns hyper-z access, * 0 otherwise. */ - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -281,7 +281,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_WANT_CMASK: /* The same logic as Hyper-Z. */ - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -417,7 +417,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->fastfb_working; break; case RADEON_INFO_RING_WORKING: - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -465,7 +465,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; } - if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) { + if (copy_to_user(value_ptr, (char*)value, value_size)) { DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c index d54d2d7c9031..146d253f1131 100644 --- a/drivers/gpu/drm/radeon/radeon_mem.c +++ b/drivers/gpu/drm/radeon/radeon_mem.c @@ -243,7 +243,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p if (!block) return -ENOMEM; - if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, + if (copy_to_user(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 9214403ae173..ca2d71afeb02 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -463,7 +463,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) while (ring->wptr & ring->align_mask) { radeon_ring_write(ring, ring->nop); } - DRM_MEMORYBARRIER(); + mb(); radeon_ring_set_wptr(rdev, ring); } diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 4d20910899d4..956ab7f14e16 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -1810,7 +1810,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } if (!buf) { DRM_DEBUG("EAGAIN\n"); - if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + if (copy_to_user(tex->image, image, sizeof(*image))) return -EFAULT; return -EAGAIN; } @@ -1823,7 +1823,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, #define RADEON_COPY_MT(_buf, _data, _width) \ do { \ - if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ + if (copy_from_user(_buf, _data, (_width))) {\ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ return -EFAULT; \ } \ @@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, + if (copy_from_user(&depth_boxes, clear->depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]))) return -EFAULT; @@ -2436,7 +2436,7 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file return -EINVAL; } - if (DRM_COPY_FROM_USER(&image, + if (copy_from_user(&image, (drm_radeon_tex_image_t __user *) tex->image, sizeof(image))) return -EFAULT; @@ -2460,7 +2460,7 @@ static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); - if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2585,13 +2585,13 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file drm_radeon_prim_t prim; drm_radeon_tcl_prim_t tclprim; - if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim))) + if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim))) return -EFAULT; if (prim.stateidx != laststate) { drm_radeon_state_t state; - if (DRM_COPY_FROM_USER(&state, + if (copy_from_user(&state, &vertex->state[prim.stateidx], sizeof(state))) return -EFAULT; @@ -2799,7 +2799,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev, do { if (i < cmdbuf->nbox) { - if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) + if (copy_from_user(&box, &boxes[i], sizeof(box))) return -EFAULT; /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before @@ -3116,7 +3116,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil return -EINVAL; } - if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { + if (copy_to_user(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 71245d6f34a2..051fa874065a 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -142,7 +142,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, 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)) { + if (!rdev->ddev->agp) { DRM_ERROR("AGP is not enabled for memory type %u\n", (unsigned)type); return -EINVAL; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index a9d24e4bf792..fbf4be316d0b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -371,7 +371,6 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc, goto error; rcrtc->plane->format = format; - rcrtc->plane->pitch = crtc->fb->pitches[0]; rcrtc->plane->src_x = x; rcrtc->plane->src_y = y; @@ -413,7 +412,7 @@ static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, rcrtc->plane->src_x = x; rcrtc->plane->src_y = y; - rcar_du_crtc_update_base(to_rcar_crtc(crtc)); + rcar_du_crtc_update_base(rcrtc); return 0; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0023f9719cf1..792fd1d20e86 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -224,7 +224,9 @@ static int rcar_du_probe(struct platform_device *pdev) static int rcar_du_remove(struct platform_device *pdev) { - drm_platform_exit(&rcar_du_driver, pdev); + struct rcar_du_device *rcdu = platform_get_drvdata(pdev); + + drm_put_dev(rcdu->ddev); return 0; } @@ -249,8 +251,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = { }; static const struct rcar_du_device_info rcar_du_r8a7790_info = { - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B - | RCAR_DU_FEATURE_DEFR8, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES, .num_crtcs = 3, .routes = { /* R8A7790 has one RGB output, two LVDS outputs and one @@ -272,9 +274,29 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { .num_lvds = 2, }; +static const struct rcar_du_device_info rcar_du_r8a7791_info = { + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .num_crtcs = 2, + .routes = { + /* R8A7791 has one RGB output, one LVDS output and one + * (currently unsupported) TCON output. + */ + [RCAR_DU_OUTPUT_DPAD0] = { + .possible_crtcs = BIT(1), + .encoder_type = DRM_MODE_ENCODER_NONE, + }, + [RCAR_DU_OUTPUT_LVDS0] = { + .possible_crtcs = BIT(0), + .encoder_type = DRM_MODE_ENCODER_LVDS, + }, + }, + .num_lvds = 1, +}; + static const struct platform_device_id rcar_du_id_table[] = { { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info }, { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info }, + { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info }, { } }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 65d2d636b002..e31b735d3f25 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -28,8 +28,10 @@ struct rcar_du_device; struct rcar_du_lvdsenc; #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ -#define RCAR_DU_FEATURE_ALIGN_128B (1 << 1) /* Align pitches to 128 bytes */ -#define RCAR_DU_FEATURE_DEFR8 (1 << 2) /* Has DEFR8 register */ +#define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */ + +#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ +#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */ /* * struct rcar_du_output_routing - Output routing specification @@ -48,12 +50,14 @@ struct rcar_du_output_routing { /* * struct rcar_du_device_info - DU model-specific information * @features: device features (RCAR_DU_FEATURE_*) + * @quirks: device quirks (RCAR_DU_QUIRK_*) * @num_crtcs: total number of CRTCs * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) * @num_lvds: number of internal LVDS encoders */ struct rcar_du_device_info { unsigned int features; + unsigned int quirks; unsigned int num_crtcs; struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; unsigned int num_lvds; @@ -84,6 +88,12 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu, return rcdu->info->features & feature; } +static inline bool rcar_du_needs(struct rcar_du_device *rcdu, + unsigned int quirk) +{ + return rcdu->info->quirks & quirk; +} + static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg) { return ioread32(rcdu->mmio + reg); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index b31ac080c4a7..fbeabd9a281f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -119,7 +119,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev, /* The R8A7779 DU requires a 16 pixels pitch alignment as documented, * but the R8A7790 DU seems to require a 128 bytes pitch alignment. */ - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B)) + if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) align = 128; else align = 16 * args->bpp / 8; @@ -144,7 +144,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-EINVAL); } - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B)) + if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) align = 128; else align = 16 * format->bpp / 8; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index a0f6a1781925..df30a075d793 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -44,6 +44,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, const struct drm_display_mode *mode = &rcrtc->crtc.mode; unsigned int freq = mode->clock; u32 lvdcr0; + u32 lvdhcr; u32 pllcr; int ret; @@ -72,15 +73,19 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, * VSYNC -> CTRL1 * DISP -> CTRL2 * 0 -> CTRL3 - * - * Channels 1 and 3 are switched on ES1. */ rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO | LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC | LVDCTRCR_CTR0SEL_HSYNC); - rcar_lvds_write(lvds, LVDCHCR, - LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) | - LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1)); + + if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES)) + lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) + | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1); + else + lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1) + | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3); + + rcar_lvds_write(lvds, LVDCHCR, lvdhcr); /* Select the input, hardcode mode 0, enable LVDS operation and turn * bias circuitry on. @@ -144,18 +149,9 @@ static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds, sprintf(name, "lvds.%u", lvds->index); mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (mem == NULL) { - dev_err(&pdev->dev, "failed to get memory resource for %s\n", - name); - return -EINVAL; - } - lvds->mmio = devm_ioremap_resource(&pdev->dev, mem); - if (lvds->mmio == NULL) { - dev_err(&pdev->dev, "failed to remap memory resource for %s\n", - name); - return -ENOMEM; - } + if (IS_ERR(lvds->mmio)) + return PTR_ERR(lvds->mmio); lvds->clock = devm_clk_get(&pdev->dev, name); if (IS_ERR(lvds->clock)) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 53000644733f..3fb69d9ae61b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -104,6 +104,15 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane) { struct rcar_du_group *rgrp = plane->group; unsigned int index = plane->hwindex; + u32 mwr; + + /* Memory pitch (expressed in pixels) */ + if (plane->format->planes == 2) + mwr = plane->pitch; + else + mwr = plane->pitch * 8 / plane->format->bpp; + + rcar_du_plane_write(rgrp, index, PnMWR, mwr); /* The Y position is expressed in raster line units and must be doubled * for 32bpp formats, according to the R8A7790 datasheet. No mention of @@ -133,6 +142,8 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane, { struct drm_gem_cma_object *gem; + plane->pitch = fb->pitches[0]; + gem = drm_fb_cma_get_gem_obj(fb, 0); plane->dma[0] = gem->paddr + fb->offsets[0]; @@ -209,7 +220,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, struct rcar_du_group *rgrp = plane->group; u32 ddcr2 = PnDDCR2_CODE; u32 ddcr4; - u32 mwr; /* Data format * @@ -240,14 +250,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2); rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4); - /* Memory pitch (expressed in pixels) */ - if (plane->format->planes == 2) - mwr = plane->pitch; - else - mwr = plane->pitch * 8 / plane->format->bpp; - - rcar_du_plane_write(rgrp, index, PnMWR, mwr); - /* Destination position and size */ rcar_du_plane_write(rgrp, index, PnDSXR, plane->width); rcar_du_plane_write(rgrp, index, PnDSYR, plane->height); @@ -309,7 +311,6 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, rplane->crtc = crtc; rplane->format = format; - rplane->pitch = fb->pitches[0]; rplane->src_x = src_x >> 16; rplane->src_y = src_y >> 16; diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index b17d0710871a..d2b2df9e26f3 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -49,7 +49,7 @@ savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) #endif for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { - DRM_MEMORYBARRIER(); + mb(); status = dev_priv->status_ptr[0]; if ((status & mask) < threshold) return 0; @@ -123,7 +123,7 @@ savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e) int i; for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) { - DRM_MEMORYBARRIER(); + mb(); status = dev_priv->status_ptr[1]; if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff || (status & 0xffff) == 0) @@ -449,7 +449,7 @@ static void savage_dma_flush(drm_savage_private_t * dev_priv) } } - DRM_MEMORYBARRIER(); + mb(); /* do flush ... */ phys_addr = dev_priv->cmd_dma->offset + @@ -990,10 +990,10 @@ static int savage_bci_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index b35e75ed890c..c01ad0aeaa58 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c @@ -992,7 +992,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ if (kcmd_addr == NULL) return -ENOMEM; - if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr, + if (copy_from_user(kcmd_addr, cmdbuf->cmd_addr, cmdbuf->size * 8)) { kfree(kcmd_addr); @@ -1007,7 +1007,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ goto done; } - if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr, + if (copy_from_user(kvb_addr, cmdbuf->vb_addr, cmdbuf->vb_size)) { ret = -EFAULT; goto done; @@ -1022,7 +1022,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ goto done; } - if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr, + if (copy_from_user(kbox_addr, cmdbuf->box_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect))) { ret = -EFAULT; goto done; @@ -1032,7 +1032,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ /* Make sure writes to DMA buffers are finished before sending * DMA commands to the graphics hardware. */ - DRM_MEMORYBARRIER(); + mb(); /* Coming from user space. Don't know if the Xserver has * emitted wait commands. Assuming the worst. */ diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 562f9a401cf6..0428076f1ce8 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -37,14 +37,21 @@ * Clock management */ -static void shmob_drm_clk_on(struct shmob_drm_device *sdev) +static int shmob_drm_clk_on(struct shmob_drm_device *sdev) { - if (sdev->clock) - clk_prepare_enable(sdev->clock); + int ret; + + if (sdev->clock) { + ret = clk_prepare_enable(sdev->clock); + if (ret < 0) + return ret; + } #if 0 if (sdev->meram_dev && sdev->meram_dev->pdev) pm_runtime_get_sync(&sdev->meram_dev->pdev->dev); #endif + + return 0; } static void shmob_drm_clk_off(struct shmob_drm_device *sdev) @@ -161,6 +168,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc) struct drm_device *dev = sdev->ddev; struct drm_plane *plane; u32 value; + int ret; if (scrtc->started) return; @@ -170,7 +178,9 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc) return; /* Enable clocks before accessing the hardware. */ - shmob_drm_clk_on(sdev); + ret = shmob_drm_clk_on(sdev); + if (ret < 0) + return; /* Reset and enable the LCDC. */ lcdc_write(sdev, LDCNT2R, lcdc_read(sdev, LDCNT2R) | LDCNT2R_BR); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 015551866b4a..c839c9c89efb 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -336,7 +336,9 @@ static int shmob_drm_probe(struct platform_device *pdev) static int shmob_drm_remove(struct platform_device *pdev) { - drm_platform_exit(&shmob_drm_driver, pdev); + struct shmob_drm_device *sdev = platform_get_drvdata(pdev); + + drm_put_dev(sdev->ddev); return 0; } diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c index 01857d836350..0573be0d2933 100644 --- a/drivers/gpu/drm/sis/sis_mm.c +++ b/drivers/gpu/drm/sis/sis_mm.c @@ -266,7 +266,7 @@ int sis_idle(struct drm_device *dev) * because its polling frequency is too low. */ - end = jiffies + (DRM_HZ * 3); + end = jiffies + (HZ * 3); for (i = 0; i < 4; ++i) { do { diff --git a/drivers/gpu/drm/tegra/bus.c b/drivers/gpu/drm/tegra/bus.c index 565f8f7b9a47..e38e5967d77b 100644 --- a/drivers/gpu/drm/tegra/bus.c +++ b/drivers/gpu/drm/tegra/bus.c @@ -46,7 +46,6 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device) struct drm_device *drm; int ret; - INIT_LIST_HEAD(&driver->device_list); driver->bus = &drm_host1x_bus; drm = drm_dev_alloc(driver, &device->dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 116da199b942..0c22b6ca7fd2 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -311,7 +311,7 @@ static void tilcdc_lastclose(struct drm_device *dev) drm_fbdev_cma_restore_mode(priv->fbdev); } -static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS) +static irqreturn_t tilcdc_irq(int irq, void *arg) { struct drm_device *dev = arg; struct tilcdc_drm_private *priv = dev->dev_private; @@ -594,7 +594,7 @@ static int tilcdc_pdev_probe(struct platform_device *pdev) static int tilcdc_pdev_remove(struct platform_device *pdev) { - drm_platform_exit(&tilcdc_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 15b86a94949d..99aab8639089 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -593,7 +593,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, if (start_page > bo->num_pages) return -EINVAL; #if 0 - if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) + if (num_pages > 1 && !capable(CAP_SYS_ADMIN)) return -EPERM; #endif (void) ttm_mem_io_lock(man, false); diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 97e9d614700f..dbadd49e4c4a 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -403,15 +403,17 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, int i; int ret = 0; + drm_modeset_lock_all(fb->dev); + if (!ufb->active_16) - return 0; + goto unlock; if (ufb->obj->base.import_attach) { ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf, 0, ufb->obj->base.size, DMA_FROM_DEVICE); if (ret) - return ret; + goto unlock; } for (i = 0; i < num_clips; i++) { @@ -419,7 +421,7 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, clips[i].x2 - clips[i].x1, clips[i].y2 - clips[i].y1); if (ret) - break; + goto unlock; } if (ufb->obj->base.import_attach) { @@ -427,6 +429,10 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, 0, ufb->obj->base.size, DMA_FROM_DEVICE); } + + unlock: + drm_modeset_unlock_all(fb->dev); + return ret; } diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c index 652f9b43ec9d..a18479c6b6da 100644 --- a/drivers/gpu/drm/via/via_dma.c +++ b/drivers/gpu/drm/via/via_dma.c @@ -60,7 +60,7 @@ dev_priv->dma_low += 8; \ } -#define via_flush_write_combine() DRM_MEMORYBARRIER() +#define via_flush_write_combine() mb() #define VIA_OUT_RING_QW(w1, w2) do { \ *vb++ = (w1); \ @@ -234,13 +234,13 @@ static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *fil switch (init->func) { case VIA_INIT_DMA: - if (!DRM_SUSER(DRM_CURPROC)) + if (!capable(CAP_SYS_ADMIN)) retcode = -EPERM; else retcode = via_initialize(dev, dev_priv, init); break; case VIA_CLEANUP_DMA: - if (!DRM_SUSER(DRM_CURPROC)) + if (!capable(CAP_SYS_ADMIN)) retcode = -EPERM; else retcode = via_dma_cleanup(dev); @@ -273,7 +273,7 @@ static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *c if (cmd->size > VIA_PCI_BUF_SIZE) return -ENOMEM; - if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) + if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) return -EFAULT; /* @@ -346,7 +346,7 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device *dev, if (cmd->size > VIA_PCI_BUF_SIZE) return -ENOMEM; - if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) + if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) return -EFAULT; if ((ret = @@ -543,7 +543,7 @@ static void via_cmdbuf_start(drm_via_private_t *dev_priv) VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); - DRM_WRITEMEMORYBARRIER(); + wmb(); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); VIA_READ(VIA_REG_TRANSPACE); diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 8b0f25904e6d..ba33cf679180 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -217,7 +217,7 @@ via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine) VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); - DRM_WRITEMEMORYBARRIER(); + wmb(); VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); } @@ -338,7 +338,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) blitq->blits[cur]->aborted = blitq->aborting; blitq->done_blit_handle++; - DRM_WAKEUP(blitq->blit_queue + cur); + wake_up(blitq->blit_queue + cur); cur++; if (cur >= VIA_NUM_BLIT_SLOTS) @@ -363,7 +363,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) via_abort_dmablit(dev, engine); blitq->aborting = 1; - blitq->end = jiffies + DRM_HZ; + blitq->end = jiffies + HZ; } if (!blitq->is_active) { @@ -372,7 +372,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) blitq->is_active = 1; blitq->cur = cur; blitq->num_outstanding--; - blitq->end = jiffies + DRM_HZ; + blitq->end = jiffies + HZ; if (!timer_pending(&blitq->poll_timer)) mod_timer(&blitq->poll_timer, jiffies + 1); } else { @@ -436,7 +436,7 @@ via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) int ret = 0; if (via_dmablit_active(blitq, engine, handle, &queue)) { - DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, *queue, 3 * HZ, !via_dmablit_active(blitq, engine, handle, NULL)); } DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n", @@ -521,7 +521,7 @@ via_dmablit_workqueue(struct work_struct *work) spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - DRM_WAKEUP(&blitq->busy_queue); + wake_up(&blitq->busy_queue); via_free_sg_info(dev->pdev, cur_sg); kfree(cur_sg); @@ -561,8 +561,8 @@ via_init_dmablit(struct drm_device *dev) blitq->aborting = 0; spin_lock_init(&blitq->blit_lock); for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j) - DRM_INIT_WAITQUEUE(blitq->blit_queue + j); - DRM_INIT_WAITQUEUE(&blitq->busy_queue); + init_waitqueue_head(blitq->blit_queue + j); + init_waitqueue_head(&blitq->busy_queue); INIT_WORK(&blitq->wq, via_dmablit_workqueue); setup_timer(&blitq->poll_timer, via_dmablit_timer, (unsigned long)blitq); @@ -688,7 +688,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) while (blitq->num_free == 0) { spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0); + DRM_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0); if (ret) return (-EINTR == ret) ? -EAGAIN : ret; @@ -713,7 +713,7 @@ via_dmablit_release_slot(drm_via_blitq_t *blitq) spin_lock_irqsave(&blitq->blit_lock, irqsave); blitq->num_free++; spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - DRM_WAKEUP(&blitq->busy_queue); + wake_up(&blitq->busy_queue); } /* diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index a811ef2b505f..ad0273256beb 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -138,7 +138,7 @@ extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc); extern int via_enable_vblank(struct drm_device *dev, int crtc); extern void via_disable_vblank(struct drm_device *dev, int crtc); -extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t via_driver_irq_handler(int irq, void *arg); extern void via_driver_irq_preinstall(struct drm_device *dev); extern int via_driver_irq_postinstall(struct drm_device *dev); extern void via_driver_irq_uninstall(struct drm_device *dev); diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index ac98964297cf..1319433816d3 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -104,7 +104,7 @@ u32 via_get_vblank_counter(struct drm_device *dev, int crtc) return atomic_read(&dev_priv->vbl_received); } -irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) +irqreturn_t via_driver_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; @@ -138,7 +138,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) for (i = 0; i < dev_priv->num_irqs; ++i) { if (status & cur_irq->pending_mask) { atomic_inc(&cur_irq->irq_received); - DRM_WAKEUP(&cur_irq->irq_queue); + wake_up(&cur_irq->irq_queue); handled = 1; if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) via_dmablit_handler(dev, 0, 1); @@ -239,12 +239,12 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence cur_irq = dev_priv->via_irqs + real_irq; if (masks[real_irq][2] && !force_sequence) { - DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4])); cur_irq_sequence = atomic_read(&cur_irq->irq_received); } else { - DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) - *sequence) <= (1 << 23))); @@ -287,7 +287,7 @@ void via_driver_irq_preinstall(struct drm_device *dev) atomic_set(&cur_irq->irq_received, 0); cur_irq->enable_mask = dev_priv->irq_masks[i][0]; cur_irq->pending_mask = dev_priv->irq_masks[i][1]; - DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); + init_waitqueue_head(&cur_irq->irq_queue); dev_priv->irq_enable_mask |= cur_irq->enable_mask; dev_priv->irq_pending_mask |= cur_irq->pending_mask; cur_irq++; diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c index 6569efa2ff6e..a9ffbad1cfdd 100644 --- a/drivers/gpu/drm/via/via_video.c +++ b/drivers/gpu/drm/via/via_video.c @@ -36,7 +36,7 @@ void via_init_futex(drm_via_private_t *dev_priv) DRM_DEBUG("\n"); for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { - DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i])); + init_waitqueue_head(&(dev_priv->decoder_queue[i])); XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0; } } @@ -58,7 +58,7 @@ void via_release_futex(drm_via_private_t *dev_priv, int context) if ((_DRM_LOCKING_CONTEXT(*lock) == context)) { if (_DRM_LOCK_IS_HELD(*lock) && (*lock & _DRM_LOCK_CONT)) { - DRM_WAKEUP(&(dev_priv->decoder_queue[i])); + wake_up(&(dev_priv->decoder_queue[i])); } *lock = 0; } @@ -83,10 +83,10 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_ switch (fx->func) { case VIA_FUTEX_WAIT: DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], - (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val); + (fx->ms / 10) * (HZ / 100), *lock != fx->val); return ret; case VIA_FUTEX_WAKE: - DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock])); + wake_up(&(dev_priv->decoder_queue[fx->lock])); return 0; } return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 20890ad8408b..036629dd992a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -701,7 +701,7 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, * IRQs and wating - vmwgfx_irq.c */ -extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t vmw_irq_handler(int irq, void *arg); extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy, uint32_t seqno, bool interruptible, unsigned long timeout); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 4640adbcaf91..0c423766c441 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -30,7 +30,7 @@ #define VMW_FENCE_WRAP (1 << 24) -irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS) +irqreturn_t vmw_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *)arg; struct vmw_private *dev_priv = vmw_priv(dev); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 03f1c2038631..9f307e0f3603 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -609,9 +609,13 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, if (!dev_priv->sou_priv) return -EINVAL; + drm_modeset_lock_all(dev_priv->dev); + ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + drm_modeset_unlock_all(dev_priv->dev); return ret; + } if (!num_clips) { num_clips = 1; @@ -629,6 +633,9 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, clips, num_clips, inc, NULL); ttm_read_unlock(&vmaster->lock); + + drm_modeset_unlock_all(dev_priv->dev); + return 0; } @@ -953,9 +960,13 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, struct drm_clip_rect norect; int ret, increment = 1; + drm_modeset_lock_all(dev_priv->dev); + ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + drm_modeset_unlock_all(dev_priv->dev); return ret; + } if (!num_clips) { num_clips = 1; @@ -979,6 +990,9 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, } ttm_read_unlock(&vmaster->lock); + + drm_modeset_unlock_all(dev_priv->dev); + return ret; } diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 6bd015ac9d68..0507b662ae40 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -444,6 +444,8 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) if (!imx_drm_device_get()) ret = -EINVAL; + platform_set_drvdata(drm->platformdev, drm); + ret = 0; err_init: @@ -829,7 +831,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev) static int imx_drm_platform_remove(struct platform_device *pdev) { - drm_platform_exit(&imx_drm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 010d19105ebc..e296967a3abb 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1577,10 +1577,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, static int do_unregister_framebuffer(struct fb_info *fb_info); #define VGA_FB_PHYS 0xA0000 -static void do_remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary) +static int do_remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) { - int i; + int i, ret; /* check all firmware fbs and kick off if the base addr overlaps */ for (i = 0 ; i < FB_MAX; i++) { @@ -1599,22 +1599,29 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, printk(KERN_INFO "fb: conflicting fb hw usage " "%s vs %s - removing generic driver\n", name, registered_fb[i]->fix.id); - do_unregister_framebuffer(registered_fb[i]); + ret = do_unregister_framebuffer(registered_fb[i]); + if (ret) + return ret; } } + + return 0; } static int do_register_framebuffer(struct fb_info *fb_info) { - int i; + int i, ret; struct fb_event event; struct fb_videomode mode; if (fb_check_foreignness(fb_info)) return -ENOSYS; - do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, - fb_is_primary_device(fb_info)); + ret = do_remove_conflicting_framebuffers(fb_info->apertures, + fb_info->fix.id, + fb_is_primary_device(fb_info)); + if (ret) + return ret; if (num_registered_fb == FB_MAX) return -ENXIO; @@ -1739,12 +1746,16 @@ int unlink_framebuffer(struct fb_info *fb_info) } EXPORT_SYMBOL(unlink_framebuffer); -void remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary) +int remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) { + int ret; + mutex_lock(®istration_lock); - do_remove_conflicting_framebuffers(a, name, primary); + ret = do_remove_conflicting_framebuffers(a, name, primary); mutex_unlock(®istration_lock); + + return ret; } EXPORT_SYMBOL(remove_conflicting_framebuffers); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1d4a920ef7ff..2fe9b5d5d162 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -56,6 +56,7 @@ #include <linux/mutex.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/ratelimit.h> #if defined(__alpha__) || defined(__powerpc__) #include <asm/pgtable.h> /* For pte_wrprotect */ #endif @@ -136,7 +137,6 @@ int drm_err(const char *func, const char *format, ...); /* driver capabilities and requirements mask */ #define DRIVER_USE_AGP 0x1 -#define DRIVER_REQUIRE_AGP 0x2 #define DRIVER_PCI_DMA 0x8 #define DRIVER_SG 0x10 #define DRIVER_HAVE_DMA 0x20 @@ -180,6 +180,22 @@ int drm_err(const char *func, const char *format, ...); #define DRM_ERROR(fmt, ...) \ drm_err(__func__, fmt, ##__VA_ARGS__) +/** + * Rate limited error output. Like DRM_ERROR() but won't flood the log. + * + * \param fmt printf() like format string. + * \param arg arguments + */ +#define DRM_ERROR_RATELIMITED(fmt, ...) \ +({ \ + static DEFINE_RATELIMIT_STATE(_rs, \ + DEFAULT_RATELIMIT_INTERVAL, \ + DEFAULT_RATELIMIT_BURST); \ + \ + if (__ratelimit(&_rs)) \ + drm_err(__func__, fmt, ##__VA_ARGS__); \ +}) + #define DRM_INFO(fmt, ...) \ printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) @@ -422,7 +438,6 @@ struct drm_file { struct pid *pid; kuid_t uid; drm_magic_t magic; - unsigned long ioctl_count; struct list_head lhead; struct drm_minor *minor; unsigned long lock_count; @@ -511,7 +526,7 @@ struct drm_device_dma { */ struct drm_agp_mem { unsigned long handle; /**< handle */ - DRM_AGP_MEM *memory; + struct agp_memory *memory; unsigned long bound; /**< address */ int pages; struct list_head head; @@ -523,7 +538,7 @@ struct drm_agp_mem { * \sa drm_agp_init() and drm_device::agp. */ struct drm_agp_head { - DRM_AGP_KERN agp_info; /**< AGP device information */ + struct agp_kern_info agp_info; /**< AGP device information */ struct list_head memory; unsigned long mode; /**< AGP mode */ struct agp_bridge_data *bridge; @@ -750,10 +765,6 @@ struct drm_bus { int (*set_unique)(struct drm_device *dev, struct drm_master *master, struct drm_unique *unique); int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p); - /* hooks that are for PCI */ - int (*agp_init)(struct drm_device *dev); - void (*agp_destroy)(struct drm_device *dev); - }; /** @@ -903,7 +914,7 @@ struct drm_driver { /* these have to be filled in */ - irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); + irqreturn_t(*irq_handler) (int irq, void *arg); void (*irq_preinstall) (struct drm_device *dev); int (*irq_postinstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev); @@ -995,8 +1006,8 @@ struct drm_driver { } kdriver; struct drm_bus *bus; - /* List of devices hanging off this driver */ - struct list_head device_list; + /* List of devices hanging off this driver with stealth attach. */ + struct list_head legacy_dev_list; }; #define DRM_MINOR_UNASSIGNED 0 @@ -1085,7 +1096,7 @@ struct drm_vblank_crtc { * may contain multiple heads. */ struct drm_device { - struct list_head driver_item; /**< list of devices per driver */ + struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */ char *devname; /**< For /proc/interrupts */ int if_version; /**< Highest interface version set */ @@ -1098,8 +1109,6 @@ struct drm_device { /** \name Usage Counters */ /*@{ */ int open_count; /**< Outstanding files open */ - atomic_t ioctl_count; /**< Outstanding IOCTLs pending */ - atomic_t vma_count; /**< Outstanding vma areas open */ int buf_use; /**< Buffers in use -- cannot alloc */ atomic_t buf_alloc; /**< Buffer allocation in progress */ /*@} */ @@ -1268,6 +1277,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); /* Memory management support (drm_memory.h) */ #include <drm/drm_memory.h> + /* Misc. IOCTL support (drm_ioctl.h) */ extern int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -1461,6 +1471,30 @@ extern int drm_debugfs_create_files(const struct drm_info_list *files, extern int drm_debugfs_remove_files(const struct drm_info_list *files, int count, struct drm_minor *minor); extern int drm_debugfs_cleanup(struct drm_minor *minor); +#else +static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, + struct dentry *root) +{ + return 0; +} + +static inline int drm_debugfs_create_files(const struct drm_info_list *files, + int count, struct dentry *root, + struct drm_minor *minor) +{ + return 0; +} + +static inline int drm_debugfs_remove_files(const struct drm_info_list *files, + int count, struct drm_minor *minor) +{ + return 0; +} + +static inline int drm_debugfs_cleanup(struct drm_minor *minor) +{ + return 0; +} #endif /* Info file support */ @@ -1645,6 +1679,7 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev) return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP); } +void drm_pci_agp_destroy(struct drm_device *dev); extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); @@ -1660,7 +1695,6 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); /* platform section */ extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); -extern void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device); /* returns true if currently okay to sleep */ static __inline__ bool drm_can_sleep(void) diff --git a/include/drm/drm_agpsupport.h b/include/drm/drm_agpsupport.h index a184eeee9c96..86a02188074b 100644 --- a/include/drm/drm_agpsupport.h +++ b/include/drm/drm_agpsupport.h @@ -10,17 +10,16 @@ #if __OS_HAS_AGP -void drm_free_agp(DRM_AGP_MEM * handle, int pages); -int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); -int drm_unbind_agp(DRM_AGP_MEM * handle); -DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, +void drm_free_agp(struct agp_memory * handle, int pages); +int drm_bind_agp(struct agp_memory * handle, unsigned int start); +int drm_unbind_agp(struct agp_memory * handle); +struct agp_memory *drm_agp_bind_pages(struct drm_device *dev, struct page **pages, unsigned long num_pages, uint32_t gtt_offset, uint32_t type); struct drm_agp_head *drm_agp_init(struct drm_device *dev); -void drm_agp_destroy(struct drm_agp_head *agp); void drm_agp_clear(struct drm_device *dev); int drm_agp_acquire(struct drm_device *dev); int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, @@ -46,29 +45,23 @@ int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); int drm_agp_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); - -static inline int drm_core_has_AGP(struct drm_device *dev) -{ - return drm_core_check_feature(dev, DRIVER_USE_AGP); -} - #else /* __OS_HAS_AGP */ -static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages) +static inline void drm_free_agp(struct agp_memory * handle, int pages) { } -static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) +static inline int drm_bind_agp(struct agp_memory * handle, unsigned int start) { return -ENODEV; } -static inline int drm_unbind_agp(DRM_AGP_MEM * handle) +static inline int drm_unbind_agp(struct agp_memory * handle) { return -ENODEV; } -static inline DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, +static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev, struct page **pages, unsigned long num_pages, uint32_t gtt_offset, @@ -82,10 +75,6 @@ static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev) return NULL; } -static inline void drm_agp_destroy(struct drm_agp_head *agp) -{ -} - static inline void drm_agp_clear(struct drm_device *dev) { } @@ -183,12 +172,6 @@ static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data, { return -ENODEV; } - -static inline int drm_core_has_AGP(struct drm_device *dev) -{ - return 0; -} - #endif /* __OS_HAS_AGP */ #endif /* _DRM_AGPSUPPORT_H_ */ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index a92c3754e3bb..1d09050a8c00 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -41,22 +41,22 @@ * 1.2 formally includes both eDP and DPI definitions. */ -#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) +#define DP_AUX_I2C_WRITE 0x0 +#define DP_AUX_I2C_READ 0x1 +#define DP_AUX_I2C_STATUS 0x2 +#define DP_AUX_I2C_MOT 0x4 +#define DP_AUX_NATIVE_WRITE 0x8 +#define DP_AUX_NATIVE_READ 0x9 + +#define DP_AUX_NATIVE_REPLY_ACK (0x0 << 0) +#define DP_AUX_NATIVE_REPLY_NACK (0x1 << 0) +#define DP_AUX_NATIVE_REPLY_DEFER (0x2 << 0) +#define DP_AUX_NATIVE_REPLY_MASK (0x3 << 0) + +#define DP_AUX_I2C_REPLY_ACK (0x0 << 2) +#define DP_AUX_I2C_REPLY_NACK (0x1 << 2) +#define DP_AUX_I2C_REPLY_DEFER (0x2 << 2) +#define DP_AUX_I2C_REPLY_MASK (0x3 << 2) /* AUX CH addresses */ /* DPCD */ @@ -266,9 +266,10 @@ #define DP_TEST_REQUEST 0x218 # define DP_TEST_LINK_TRAINING (1 << 0) -# define DP_TEST_LINK_PATTERN (1 << 1) +# define DP_TEST_LINK_VIDEO_PATTERN (1 << 1) # define DP_TEST_LINK_EDID_READ (1 << 2) # define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */ +# define DP_TEST_LINK_FAUX_PATTERN (1 << 4) /* DPCD >= 1.2 */ #define DP_TEST_LINK_RATE 0x219 # define DP_LINK_RATE_162 (0x6) diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h index 815fafc6b4ad..86ab99bc0ac5 100644 --- a/include/drm/drm_os_linux.h +++ b/include/drm/drm_os_linux.h @@ -21,7 +21,6 @@ static inline void writeq(u64 val, void __iomem *reg) /** Current process ID */ #define DRM_CURRENTPID task_pid_nr(current) -#define DRM_SUSER(p) capable(CAP_SYS_ADMIN) #define DRM_UDELAY(d) udelay(d) /** Read a byte from a MMIO region */ #define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset)) @@ -35,45 +34,12 @@ static inline void writeq(u64 val, void __iomem *reg) #define DRM_WRITE16(map, offset, val) writew(val, ((void __iomem *)(map)->handle) + (offset)) /** Write a dword into a MMIO region */ #define DRM_WRITE32(map, offset, val) writel(val, ((void __iomem *)(map)->handle) + (offset)) -/** Read memory barrier */ /** Read a qword from a MMIO region - be careful using these unless you really understand them */ #define DRM_READ64(map, offset) readq(((void __iomem *)(map)->handle) + (offset)) /** Write a qword into a MMIO region */ #define DRM_WRITE64(map, offset, val) writeq(val, ((void __iomem *)(map)->handle) + (offset)) -#define DRM_READMEMORYBARRIER() rmb() -/** Write memory barrier */ -#define DRM_WRITEMEMORYBARRIER() wmb() -/** Read/write memory barrier */ -#define DRM_MEMORYBARRIER() mb() - -/** IRQ handler arguments and return type and values */ -#define DRM_IRQ_ARGS int irq, void *arg - -/** AGP types */ -#if __OS_HAS_AGP -#define DRM_AGP_MEM struct agp_memory -#define DRM_AGP_KERN struct agp_kern_info -#else -/* define some dummy types for non AGP supporting kernels */ -struct no_agp_kern { - unsigned long aper_base; - unsigned long aper_size; -}; -#define DRM_AGP_MEM int -#define DRM_AGP_KERN struct no_agp_kern -#endif - -/** Other copying of data to kernel space */ -#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \ - copy_from_user(arg1, arg2, arg3) -/** Other copying of data from kernel space */ -#define DRM_COPY_TO_USER(arg1, arg2, arg3) \ - copy_to_user(arg1, arg2, arg3) - -#define DRM_HZ HZ - #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ do { \ DECLARE_WAITQUEUE(entry, current); \ @@ -97,6 +63,3 @@ do { \ __set_current_state(TASK_RUNNING); \ remove_wait_queue(&(queue), &entry); \ } while (0) - -#define DRM_WAKEUP( queue ) wake_up( queue ) -#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) diff --git a/include/linux/fb.h b/include/linux/fb.h index 70c4836e4a9f..fe6ac956550e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -613,8 +613,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); extern int unlink_framebuffer(struct fb_info *fb_info); -extern void remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary); +extern int remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 9b24d65fed72..3c9a833992e8 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -181,7 +181,6 @@ enum drm_map_type { _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ - _DRM_GEM = 6, /**< GEM object (obsolete) */ }; /** diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 3a4e97bd8607..52aed893710a 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -222,6 +222,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_SET_CACHING 0x2f #define DRM_I915_GEM_GET_CACHING 0x30 #define DRM_I915_REG_READ 0x31 +#define DRM_I915_GET_RESET_STATS 0x32 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -271,6 +272,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) #define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) +#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1030,4 +1032,21 @@ struct drm_i915_reg_read { __u64 offset; __u64 val; /* Return value */ }; + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + #endif /* _UAPI_I915_DRM_H_ */ |