diff options
Diffstat (limited to 'drivers/gpu')
61 files changed, 417 insertions, 406 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 85071a1c4547..b0733153dfd2 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector) /* if equal delete the probed mode */ mode->status = pmode->status; /* Merge type bits together */ - mode->type = pmode->type; + mode->type |= pmode->type; list_del(&pmode->head); drm_mode_destroy(connector->dev, pmode); break; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index ebc01503d50e..6f3400f3978a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -36,9 +36,9 @@ enum exynos_crtc_mode { * @pipe: a crtc index created at load() with a new crtc object creation * and the crtc object would be set to private->crtc array * to get a crtc object corresponding to this pipe from private->crtc - * array when irq interrupt occured. the reason of using this pipe is that + * array when irq interrupt occurred. the reason of using this pipe is that * drm framework doesn't support multiple irq yet. - * we can refer to the crtc to current hardware interrupt occured through + * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. * @dpms: store the crtc dpms value * @mode: store the crtc mode value diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 8adfc8f1e08f..30d76b2ff9c2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -345,7 +345,7 @@ static bool fimc_check_ovf(struct fimc_context *ctx) fimc_write(cfg, EXYNOS_CIWDOFST); - dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n", + dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n", ctx->id, status); return true; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 7bccedca487a..380aec28840b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1126,7 +1126,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, * G2D interrupt event once current command list execution is * finished. * Otherwise only ACF bit should be set to INTEN register so - * that one interrupt is occured after all command lists + * that one interrupt is occurred after all command lists * have been completed. */ if (node->event) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 1ade191d84f4..be59d50d8b16 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -652,7 +652,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, int ret; /* - * alocate memory to be used for framebuffer. + * allocate memory to be used for framebuffer. * - this callback would be called by user application * with DRM_IOCTL_MODE_CREATE_DUMB command. */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 702ec3abe85c..b8c818ba2ff4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -60,7 +60,7 @@ struct exynos_drm_gem_buf { * @vma: a pointer to vm_area. * @flags: indicate memory type to allocated buffer and cache attruibute. * - * P.S. this object would be transfered to user as kms_bo.handle so + * P.S. this object would be transferred to user as kms_bo.handle so * user can access the buffer through kms_bo.handle. */ struct exynos_drm_gem_obj { diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index cd6aebd53bd0..fa75059a6104 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1301,13 +1301,13 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id) status = gsc_read(GSC_IRQ); if (status & GSC_IRQ_STATUS_OR_IRQ) { - dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n", + dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n", ctx->id, status); return IRQ_NONE; } if (status & GSC_IRQ_STATUS_OR_FRM_DONE) { - dev_dbg(ippdrv->dev, "occured frame done at %d, status 0x%x.\n", + dev_dbg(ippdrv->dev, "occurred frame done at %d, status 0x%x.\n", ctx->id, status); buf_id[EXYNOS_DRM_OPS_SRC] = gsc_get_src_buf_index(ctx); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 824e0705c8d3..d519a4e5fe40 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -335,7 +335,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data, } else { /* * Getting ippdrv capability by ipp_id. - * some deivce not supported wb, output interface. + * some device not supported wb, output interface. * so, user application detect correct ipp driver * using this ioctl. */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h index 4cadbea7dbde..ab1634befc05 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h @@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work { /* * A structure of command node. * - * @priv: IPP private infomation. + * @priv: IPP private information. * @list: list head to command queue information. * @event_list: list head of event. * @mem_list: list head to source,destination memory queue information. @@ -92,7 +92,7 @@ struct drm_exynos_ipp_buf_info { }; /* - * A structure of wb setting infomation. + * A structure of wb setting information. * * @enable: enable flag for wb. * @refresh: HZ of the refresh rate. diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index 143eba3309c5..ea7dfc59d796 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -26,13 +26,13 @@ #include "intel_bios.h" #include "power.h" +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE static void do_gma_backlight_set(struct drm_device *dev) { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = dev->dev_private; backlight_update_status(dev_priv->backlight_device); -#endif } +#endif void gma_backlight_enable(struct drm_device *dev) { diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index ad0d6de938f3..13ec6283bf59 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -22,7 +22,6 @@ * */ #include <linux/acpi.h> -#include <linux/acpi_io.h> #include "psb_drv.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 41838eaa799c..d4ae48b04cf2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -38,7 +38,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ intel_ringbuffer.o \ intel_overlay.o \ intel_sprite.o \ - intel_opregion.o \ intel_sideband.o \ intel_uncore.o \ dvo_ch7xxx.o \ @@ -51,7 +50,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915-$(CONFIG_COMPAT) += i915_ioc32.o -i915-$(CONFIG_ACPI) += intel_acpi.o +i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 90fcccba17b0..1caa5e34fbe3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2339,8 +2339,8 @@ extern void intel_i2c_reset(struct drm_device *dev); /* intel_opregion.c */ struct intel_encoder; -extern int intel_opregion_setup(struct drm_device *dev); #ifdef CONFIG_ACPI +extern int intel_opregion_setup(struct drm_device *dev); extern void intel_opregion_init(struct drm_device *dev); extern void intel_opregion_fini(struct drm_device *dev); extern void intel_opregion_asle_intr(struct drm_device *dev); @@ -2349,6 +2349,7 @@ extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, extern int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state); #else +static inline int intel_opregion_setup(struct drm_device *dev) { return 0; } static inline void intel_opregion_init(struct drm_device *dev) { return; } static inline void intel_opregion_fini(struct drm_device *dev) { return; } static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 621c7c67a643..76d3d1ab73c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2343,15 +2343,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request) kfree(request); } -static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, - struct intel_ring_buffer *ring) +static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) { - u32 completed_seqno; - u32 acthd; + u32 completed_seqno = ring->get_seqno(ring, false); + u32 acthd = intel_ring_get_active_head(ring); + struct drm_i915_gem_request *request; + + list_for_each_entry(request, &ring->request_list, list) { + if (i915_seqno_passed(completed_seqno, request->seqno)) + continue; - acthd = intel_ring_get_active_head(ring); - completed_seqno = ring->get_seqno(ring, false); + i915_set_reset_status(ring, request, acthd); + } +} +static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) +{ while (!list_empty(&ring->request_list)) { struct drm_i915_gem_request *request; @@ -2359,9 +2368,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, struct drm_i915_gem_request, list); - if (request->seqno > completed_seqno) - i915_set_reset_status(ring, request, acthd); - i915_gem_free_request(request); } @@ -2403,8 +2409,16 @@ void i915_gem_reset(struct drm_device *dev) struct intel_ring_buffer *ring; int i; + /* + * Before we free the objects from the requests, we need to inspect + * them for finding the guilty party. As the requests only borrow + * their reference to the objects, the inspection must be done first. + */ + for_each_ring(ring, dev_priv, i) + i915_gem_reset_ring_status(dev_priv, ring); + for_each_ring(ring, dev_priv, i) - i915_gem_reset_ring_lists(dev_priv, ring); + i915_gem_reset_ring_cleanup(dev_priv, ring); i915_gem_cleanup_ringbuffer(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b7e787fb4649..a3ba9a8cd687 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -93,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb, { struct drm_i915_gem_object *obj; struct list_head objects; - int i, ret = 0; + int i, ret; INIT_LIST_HEAD(&objects); spin_lock(&file->table_lock); @@ -106,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb, DRM_DEBUG("Invalid object handle %d at index %d\n", exec[i].handle, i); ret = -ENOENT; - goto out; + goto err; } if (!list_empty(&obj->obj_exec_link)) { @@ -114,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb, DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n", obj, exec[i].handle, i); ret = -EINVAL; - goto out; + goto err; } drm_gem_object_reference(&obj->base); @@ -123,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb, spin_unlock(&file->table_lock); i = 0; - list_for_each_entry(obj, &objects, obj_exec_link) { + while (!list_empty(&objects)) { struct i915_vma *vma; + obj = list_first_entry(&objects, + struct drm_i915_gem_object, + obj_exec_link); + /* * NOTE: We can leak any vmas created here when something fails * later on. But that's no issue since vma_unbind can deal with @@ -138,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb, if (IS_ERR(vma)) { DRM_DEBUG("Failed to lookup VMA\n"); ret = PTR_ERR(vma); - goto out; + goto err; } + /* Transfer ownership from the objects list to the vmas list. */ list_add_tail(&vma->exec_list, &eb->vmas); + list_del_init(&obj->obj_exec_link); vma->exec_entry = &exec[i]; if (eb->and < 0) { @@ -155,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb, ++i; } + return 0; + -out: +err: while (!list_empty(&objects)) { obj = list_first_entry(&objects, struct drm_i915_gem_object, obj_exec_link); list_del_init(&obj->obj_exec_link); - if (ret) - drm_gem_object_unreference(&obj->base); + drm_gem_object_unreference(&obj->base); } + /* + * Objects already transfered to the vmas list will be unreferenced by + * eb_destroy. + */ + return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c79dd2b1f70e..3540569948db 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -906,14 +906,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, WARN_ON(readq(>t_entries[i-1]) != gen8_pte_encode(addr, level, true)); -#if 0 /* TODO: Still needed on GEN8? */ /* This next bit makes the above posting read even more important. We * want to flush the TLBs only after we're certain all the PTE updates * have finished. */ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); -#endif } /* @@ -1267,14 +1265,14 @@ static int ggtt_probe_common(struct drm_device *dev, size_t gtt_size) { struct drm_i915_private *dev_priv = dev->dev_private; - phys_addr_t gtt_bus_addr; + phys_addr_t gtt_phys_addr; int ret; /* For Modern GENs the PTEs and register space are split in the BAR */ - gtt_bus_addr = pci_resource_start(dev->pdev, 0) + + gtt_phys_addr = pci_resource_start(dev->pdev, 0) + (pci_resource_len(dev->pdev, 0) / 2); - dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); + dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); if (!dev_priv->gtt.gsm) { DRM_ERROR("Failed to map the gtt page table\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d1dedc02f15..f13d5edc39d5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2713,6 +2713,8 @@ static void gen8_irq_preinstall(struct drm_device *dev) #undef GEN8_IRQ_INIT_NDX POSTING_READ(GEN8_PCU_IIR); + + ibx_irq_preinstall(dev); } static void ibx_hpd_irq_setup(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index dfff0907f70e..d96eee1ae9c5 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -6,14 +6,10 @@ #include <linux/pci.h> #include <linux/acpi.h> #include <linux/vga_switcheroo.h> -#include <acpi/acpi_drivers.h> - #include <drm/drmP.h> #include "i915_drv.h" #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ - -#define INTEL_DSM_FN_SUPPORTED_FUNCTIONS 0 /* No args */ #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */ static struct intel_dsm_priv { @@ -28,61 +24,6 @@ static const u8 intel_dsm_guid[] = { 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c }; -static int intel_dsm(acpi_handle handle, int func) -{ - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object params[4]; - union acpi_object *obj; - u32 result; - int ret = 0; - - input.count = 4; - input.pointer = params; - params[0].type = ACPI_TYPE_BUFFER; - params[0].buffer.length = sizeof(intel_dsm_guid); - params[0].buffer.pointer = (char *)intel_dsm_guid; - params[1].type = ACPI_TYPE_INTEGER; - params[1].integer.value = INTEL_DSM_REVISION_ID; - params[2].type = ACPI_TYPE_INTEGER; - params[2].integer.value = func; - params[3].type = ACPI_TYPE_PACKAGE; - params[3].package.count = 0; - params[3].package.elements = NULL; - - ret = acpi_evaluate_object(handle, "_DSM", &input, &output); - if (ret) { - DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); - return ret; - } - - obj = (union acpi_object *)output.pointer; - - result = 0; - switch (obj->type) { - case ACPI_TYPE_INTEGER: - result = obj->integer.value; - break; - - case ACPI_TYPE_BUFFER: - if (obj->buffer.length == 4) { - result = (obj->buffer.pointer[0] | - (obj->buffer.pointer[1] << 8) | - (obj->buffer.pointer[2] << 16) | - (obj->buffer.pointer[3] << 24)); - break; - } - default: - ret = -EINVAL; - break; - } - if (result == 0x80000002) - ret = -ENODEV; - - kfree(output.pointer); - return ret; -} - static char *intel_dsm_port_name(u8 id) { switch (id) { @@ -137,83 +78,56 @@ static char *intel_dsm_mux_type(u8 type) static void intel_dsm_platform_mux_info(void) { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object params[4]; - union acpi_object *pkg; - int i, ret; - - input.count = 4; - input.pointer = params; - params[0].type = ACPI_TYPE_BUFFER; - params[0].buffer.length = sizeof(intel_dsm_guid); - params[0].buffer.pointer = (char *)intel_dsm_guid; - params[1].type = ACPI_TYPE_INTEGER; - params[1].integer.value = INTEL_DSM_REVISION_ID; - params[2].type = ACPI_TYPE_INTEGER; - params[2].integer.value = INTEL_DSM_FN_PLATFORM_MUX_INFO; - params[3].type = ACPI_TYPE_PACKAGE; - params[3].package.count = 0; - params[3].package.elements = NULL; - - ret = acpi_evaluate_object(intel_dsm_priv.dhandle, "_DSM", &input, - &output); - if (ret) { - DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); - goto out; + int i; + union acpi_object *pkg, *connector_count; + + pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, intel_dsm_guid, + INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO, + NULL, ACPI_TYPE_PACKAGE); + if (!pkg) { + DRM_DEBUG_DRIVER("failed to evaluate _DSM\n"); + return; } - pkg = (union acpi_object *)output.pointer; - - if (pkg->type == ACPI_TYPE_PACKAGE) { - union acpi_object *connector_count = &pkg->package.elements[0]; - DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", - (unsigned long long)connector_count->integer.value); - for (i = 1; i < pkg->package.count; i++) { - union acpi_object *obj = &pkg->package.elements[i]; - union acpi_object *connector_id = - &obj->package.elements[0]; - union acpi_object *info = &obj->package.elements[1]; - DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", - (unsigned long long)connector_id->integer.value); - DRM_DEBUG_DRIVER(" port id: %s\n", - intel_dsm_port_name(info->buffer.pointer[0])); - DRM_DEBUG_DRIVER(" display mux info: %s\n", - intel_dsm_mux_type(info->buffer.pointer[1])); - DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", - intel_dsm_mux_type(info->buffer.pointer[2])); - DRM_DEBUG_DRIVER(" hpd mux info: %s\n", - intel_dsm_mux_type(info->buffer.pointer[3])); - } + connector_count = &pkg->package.elements[0]; + DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", + (unsigned long long)connector_count->integer.value); + for (i = 1; i < pkg->package.count; i++) { + union acpi_object *obj = &pkg->package.elements[i]; + union acpi_object *connector_id = &obj->package.elements[0]; + union acpi_object *info = &obj->package.elements[1]; + DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", + (unsigned long long)connector_id->integer.value); + DRM_DEBUG_DRIVER(" port id: %s\n", + intel_dsm_port_name(info->buffer.pointer[0])); + DRM_DEBUG_DRIVER(" display mux info: %s\n", + intel_dsm_mux_type(info->buffer.pointer[1])); + DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", + intel_dsm_mux_type(info->buffer.pointer[2])); + DRM_DEBUG_DRIVER(" hpd mux info: %s\n", + intel_dsm_mux_type(info->buffer.pointer[3])); } -out: - kfree(output.pointer); + ACPI_FREE(pkg); } static bool intel_dsm_pci_probe(struct pci_dev *pdev) { acpi_handle dhandle; - int ret; dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; - if (!acpi_has_method(dhandle, "_DSM")) { + if (!acpi_check_dsm(dhandle, intel_dsm_guid, INTEL_DSM_REVISION_ID, + 1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) { DRM_DEBUG_KMS("no _DSM method for intel device\n"); return false; } - ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS); - if (ret < 0) { - DRM_DEBUG_KMS("failed to get supported _DSM functions\n"); - return false; - } - intel_dsm_priv.dhandle = dhandle; - intel_dsm_platform_mux_info(); + return true; } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 526c8ded16b0..b69dc3e66c16 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1057,12 +1057,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev) enum pipe pipe; struct intel_crtc *intel_crtc; + dev_priv->ddi_plls.spll_refcount = 0; + dev_priv->ddi_plls.wrpll1_refcount = 0; + dev_priv->ddi_plls.wrpll2_refcount = 0; + for_each_pipe(pipe) { intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); - if (!intel_crtc->active) + if (!intel_crtc->active) { + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; continue; + } intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, pipe); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8b8bde7dce53..2bde35d34eb9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6303,7 +6303,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) uint32_t val; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) - WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n", + WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); @@ -10541,11 +10541,20 @@ static struct intel_quirk intel_quirks[] = { /* Sony Vaio Y cannot use SSC on LVDS */ { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, - /* - * All GM45 Acer (and its brands eMachines and Packard Bell) laptops - * seem to use inverted backlight PWM. - */ - { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness }, + /* Acer Aspire 5734Z must invert backlight brightness */ + { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, + + /* Acer/eMachines G725 */ + { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, + + /* Acer/eMachines e725 */ + { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, + + /* Acer/Packard Bell NCL20 */ + { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness }, + + /* Acer Aspire 4736Z */ + { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, /* Dell XPS13 HD Sandy Bridge */ { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, @@ -11044,10 +11053,10 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); - drm_modeset_lock_all(dev); + mutex_lock(&dev->mode_config.mutex); drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, false); - drm_modeset_unlock_all(dev); + mutex_unlock(&dev->mode_config.mutex); } void intel_modeset_cleanup(struct drm_device *dev) @@ -11126,14 +11135,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector, int intel_modeset_vga_set_state(struct drm_device *dev, bool state) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; - pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl); + pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl); if (state) gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); + pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl); return 0; } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6d69a9bad865..9a8804bee5cd 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -28,7 +28,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/acpi.h> -#include <linux/acpi_io.h> #include <acpi/video.h> #include <drm/drmP.h> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3657ab43c8fd..26c29c173221 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5688,6 +5688,8 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) unsigned long irqflags; uint32_t tmp; + WARN_ON(dev_priv->pc8.enabled); + tmp = I915_READ(HSW_PWR_WELL_DRIVER); is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED; enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST; @@ -5747,16 +5749,24 @@ 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++) + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!power_well->count++) { + hsw_disable_package_c8(dev_priv); __intel_set_power_well(dev, true); + } } static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { + struct drm_i915_private *dev_priv = dev->dev_private; + WARN_ON(!power_well->count); - if (!--power_well->count && i915_disable_power_well) + if (!--power_well->count && i915_disable_power_well) { __intel_set_power_well(dev, false); + hsw_enable_package_c8(dev_priv); + } } void intel_display_power_get(struct drm_device *dev, diff --git a/drivers/gpu/drm/nouveau/core/core/subdev.c b/drivers/gpu/drm/nouveau/core/core/subdev.c index 48f06378d3f9..2ea5568b6cf5 100644 --- a/drivers/gpu/drm/nouveau/core/core/subdev.c +++ b/drivers/gpu/drm/nouveau/core/core/subdev.c @@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent, if (parent) { struct nouveau_device *device = nv_device(parent); - int subidx = nv_hclass(subdev) & 0xff; - subdev->debug = nouveau_dbgopt(device->dbgopt, subname); subdev->mmio = nv_subdev(device)->mmio; - device->subdev[subidx] = *pobject; } return 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index 9135b25a29d0..dd01c6c435d6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -268,6 +268,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, if (ret) return ret; + device->subdev[i] = devobj->subdev[i]; + /* note: can't init *any* subdevs until devinit has been run * due to not knowing exactly what the vbios init tables will * mess with. devinit also can't be run until all of its diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c index 8d06eef2b9ee..dbc5e33de94f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c @@ -161,7 +161,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 434bb4b0fa2e..5c8a63dc506a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -334,7 +334,7 @@ nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds) while ((mthd = &mthds[i++]) && (init = mthd->init)) { u32 addr = 0x80000000 | mthd->oclass; for (data = 0; init->count; init++) { - if (data != init->data) { + if (init == mthd->init || data != init->data) { nv_wr32(priv, 0x40448c, init->data); data = init->data; } diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index 8541aa382ff2..d89dbdf39b0d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -75,6 +75,11 @@ struct nouveau_fb { static inline struct nouveau_fb * nouveau_fb(void *obj) { + /* fbram uses this before device subdev pointer is valid */ + if (nv_iclass(obj, NV_SUBDEV_CLASS) && + nv_subidx(obj) == NVDEV_SUBDEV_FB) + return obj; + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB]; } diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 9fa5da723871..7f50a858b16f 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -73,7 +73,7 @@ struct nouveau_i2c { int (*identify)(struct nouveau_i2c *, int index, const char *what, struct nouveau_i2c_board_info *, bool (*match)(struct nouveau_i2c_port *, - struct i2c_board_info *)); + struct i2c_board_info *, void *), void *); struct list_head ports; }; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index ec7a54e91a08..4aca33887aaa 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -50,6 +50,13 @@ struct nouveau_instmem { static inline struct nouveau_instmem * nouveau_instmem(void *obj) { + /* nv04/nv40 impls need to create objects in their constructor, + * which is before the subdev pointer is valid + */ + if (nv_iclass(obj, NV_SUBDEV_CLASS) && + nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM) + return obj; + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 420908cb82b6..df1b1b423093 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -365,13 +365,13 @@ static u16 init_script(struct nouveau_bios *bios, int index) { struct nvbios_init init = { .bios = bios }; - u16 data; + u16 bmp_ver = bmp_version(bios), data; - if (bmp_version(bios) && bmp_version(bios) < 0x0510) { - if (index > 1) + if (bmp_ver && bmp_ver < 0x0510) { + if (index > 1 || bmp_ver < 0x0100) return 0x0000; - data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18); + data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18); return nv_ro16(bios, data + (index * 2)); } @@ -1294,7 +1294,11 @@ init_jump(struct nvbios_init *init) u16 offset = nv_ro16(bios, init->offset + 1); trace("JUMP\t0x%04x\n", offset); - init->offset = offset; + + if (init_exec(init)) + init->offset = offset; + else + init->offset += 3; } /** diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 041fd5edaebf..c33c03d2f4af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -197,7 +197,7 @@ static int nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, struct nouveau_i2c_board_info *info, bool (*match)(struct nouveau_i2c_port *, - struct i2c_board_info *)) + struct i2c_board_info *, void *), void *data) { struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); int i; @@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, } if (nv_probe_i2c(port, info[i].dev.addr) && - (!match || match(port, &info[i].dev))) { + (!match || match(port, &info[i].dev, data))) { nv_info(i2c, "detected %s: %s\n", what, info[i].dev.type); return i; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 129120473f6c..13c5af88a601 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -87,55 +87,39 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version) 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 }; u32 mxms_args[] = { 0x00000000 }; - union acpi_object args[4] = { - /* _DSM MUID */ - { .buffer.type = 3, - .buffer.length = sizeof(muid), - .buffer.pointer = muid, - }, - /* spec says this can be zero to mean "highest revision", but - * of course there's at least one bios out there which fails - * unless you pass in exactly the version it supports.. - */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = (version & 0xf0) << 4 | (version & 0x0f), - }, - /* MXMS function */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = 0x00000010, - }, - /* Pointer to MXMS arguments */ - { .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = sizeof(mxms_args), - .buffer.pointer = (char *)mxms_args, - }, + union acpi_object argv4 = { + .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = sizeof(mxms_args), + .buffer.pointer = (char *)mxms_args, }; - struct acpi_object_list list = { ARRAY_SIZE(args), args }; - struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; acpi_handle handle; - int ret; + int rev; handle = ACPI_HANDLE(&device->pdev->dev); if (!handle) return false; - ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); - if (ret) { - nv_debug(mxm, "DSM MXMS failed: %d\n", ret); + /* + * spec says this can be zero to mean "highest revision", but + * of course there's at least one bios out there which fails + * unless you pass in exactly the version it supports.. + */ + rev = (version & 0xf0) << 4 | (version & 0x0f); + obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4); + if (!obj) { + nv_debug(mxm, "DSM MXMS failed\n"); return false; } - obj = retn.pointer; if (obj->type == ACPI_TYPE_BUFFER) { mxm->mxms = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); - } else - if (obj->type == ACPI_TYPE_INTEGER) { + } else if (obj->type == ACPI_TYPE_INTEGER) { nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); } - kfree(obj); + ACPI_FREE(obj); return mxm->mxms != NULL; } #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c index af129c2e8113..64f8b4702bf7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c @@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info) static int mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb) { - struct nouveau_mxm *mxm = nouveau_mxm(bios); + struct nouveau_mxm *mxm = data; struct context ctx = { .outp = (u32 *)(bios->data + pdcb) }; u8 type, i2cidx, link, ver, len; u8 *conn; @@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm) return; } - dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry); + dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry); mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e44ed7b93c6d..7610fc5f8fa2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -29,9 +29,9 @@ static bool probe_monitoring_device(struct nouveau_i2c_port *i2c, - struct i2c_board_info *info) + struct i2c_board_info *info, void *data) { - struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); + struct nouveau_therm_priv *priv = data; struct nvbios_therm_sensor *sensor = &priv->bios_sensor; struct i2c_client *client; @@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) }; i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device); + board, probe_monitoring_device, therm); if (priv->ic) return; } @@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) }; i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device); + board, probe_monitoring_device, therm); if (priv->ic) return; } @@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) device. Let's try our static list. */ i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - nv_board_infos, probe_monitoring_device); + nv_board_infos, probe_monitoring_device, therm); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 936a71c59080..7fdc51e2a571 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) get_tmds_slave(encoder)) return; - type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); + type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL); if (type < 0) return; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index cc4b208ce546..244822df8ffc 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) struct nouveau_i2c *i2c = nouveau_i2c(drm->device); return i2c->identify(i2c, i2c_index, "TV encoder", - nv04_tv_encoder_info, NULL); + nv04_tv_encoder_info, NULL, NULL); } diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 6828d81ed7b9..900fae01793e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -447,6 +447,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) if (ret) goto done; + info->offset = ntfy->node->offset; + done: if (ret) nouveau_abi16_ntfy_fini(chan, ntfy); diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 95c740454049..3c149617cfcb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -1,15 +1,10 @@ #include <linux/pci.h> #include <linux/acpi.h> #include <linux/slab.h> -#include <acpi/acpi_drivers.h> -#include <acpi/acpi_bus.h> -#include <acpi/video.h> -#include <acpi/acpi.h> #include <linux/mxm-wmi.h> - #include <linux/vga_switcheroo.h> - #include <drm/drm_edid.h> +#include <acpi/video.h> #include "nouveau_drm.h" #include "nouveau_acpi.h" @@ -51,6 +46,7 @@ static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; acpi_handle dhandle; + acpi_handle other_handle; acpi_handle rom_handle; } nouveau_dsm_priv; @@ -77,124 +73,66 @@ static const char nouveau_op_dsm_muid[] = { static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object params[4]; + int i; union acpi_object *obj; - int i, err; char args_buff[4]; + union acpi_object argv4 = { + .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = 4, + .buffer.pointer = args_buff + }; - input.count = 4; - input.pointer = params; - params[0].type = ACPI_TYPE_BUFFER; - params[0].buffer.length = sizeof(nouveau_op_dsm_muid); - params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; - params[1].type = ACPI_TYPE_INTEGER; - params[1].integer.value = 0x00000100; - params[2].type = ACPI_TYPE_INTEGER; - params[2].integer.value = func; - params[3].type = ACPI_TYPE_BUFFER; - params[3].buffer.length = 4; /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ for (i = 0; i < 4; i++) args_buff[i] = (arg >> i * 8) & 0xFF; - params[3].buffer.pointer = args_buff; - err = acpi_evaluate_object(handle, "_DSM", &input, &output); - if (err) { - printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); - return err; - } - - obj = (union acpi_object *)output.pointer; - - if (obj->type == ACPI_TYPE_INTEGER) - if (obj->integer.value == 0x80000002) { - return -ENODEV; - } - - if (obj->type == ACPI_TYPE_BUFFER) { - if (obj->buffer.length == 4 && result) { - *result = 0; + *result = 0; + obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100, + func, &argv4, ACPI_TYPE_BUFFER); + if (!obj) { + acpi_handle_info(handle, "failed to evaluate _DSM\n"); + return AE_ERROR; + } else { + if (obj->buffer.length == 4) { *result |= obj->buffer.pointer[0]; *result |= (obj->buffer.pointer[1] << 8); *result |= (obj->buffer.pointer[2] << 16); *result |= (obj->buffer.pointer[3] << 24); } + ACPI_FREE(obj); } - kfree(output.pointer); return 0; } -static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) +static int nouveau_dsm(acpi_handle handle, int func, int arg) { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object params[4]; + int ret = 0; union acpi_object *obj; - int err; - - input.count = 4; - input.pointer = params; - params[0].type = ACPI_TYPE_BUFFER; - params[0].buffer.length = sizeof(nouveau_dsm_muid); - params[0].buffer.pointer = (char *)nouveau_dsm_muid; - params[1].type = ACPI_TYPE_INTEGER; - params[1].integer.value = 0x00000102; - params[2].type = ACPI_TYPE_INTEGER; - params[2].integer.value = func; - params[3].type = ACPI_TYPE_INTEGER; - params[3].integer.value = arg; - - err = acpi_evaluate_object(handle, "_DSM", &input, &output); - if (err) { - printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); - return err; - } - - obj = (union acpi_object *)output.pointer; - - if (obj->type == ACPI_TYPE_INTEGER) + union acpi_object argv4 = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = arg, + }; + + obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102, + func, &argv4, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_info(handle, "failed to evaluate _DSM\n"); + return AE_ERROR; + } else { if (obj->integer.value == 0x80000002) - return -ENODEV; - - if (obj->type == ACPI_TYPE_BUFFER) { - if (obj->buffer.length == 4 && result) { - *result = 0; - *result |= obj->buffer.pointer[0]; - *result |= (obj->buffer.pointer[1] << 8); - *result |= (obj->buffer.pointer[2] << 16); - *result |= (obj->buffer.pointer[3] << 24); - } + ret = -ENODEV; + ACPI_FREE(obj); } - kfree(output.pointer); - return 0; -} - -/* Returns 1 if a DSM function is usable and 0 otherwise */ -static int nouveau_test_dsm(acpi_handle test_handle, - int (*dsm_func)(acpi_handle, int, int, uint32_t *), - int sfnc) -{ - u32 result = 0; - - /* Function 0 returns a Buffer containing available functions. The args - * parameter is ignored for function 0, so just put 0 in it */ - if (dsm_func(test_handle, 0, 0, &result)) - return 0; - - /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If - * the n-th bit is enabled, function n is supported */ - return result & 1 && result & (1 << sfnc); + return ret; } static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) { mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); - return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); + return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); } static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) @@ -204,7 +142,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero arg = NOUVEAU_DSM_POWER_SPEED; else arg = NOUVEAU_DSM_POWER_STAMINA; - nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); + nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); return 0; } @@ -260,14 +198,16 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) if (!dhandle) return false; - if (!acpi_has_method(dhandle, "_DSM")) + if (!acpi_has_method(dhandle, "_DSM")) { + nouveau_dsm_priv.other_handle = dhandle; return false; - - if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) + } + if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, + 1 << NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, - NOUVEAU_DSM_OPTIMUS_CAPS)) + if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100, + 1 << NOUVEAU_DSM_OPTIMUS_CAPS)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval & NOUVEAU_DSM_HAS_OPT) { @@ -338,6 +278,16 @@ static bool nouveau_dsm_detect(void) printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", acpi_method_name); nouveau_dsm_priv.dsm_detected = true; + /* + * On some systems hotplug events are generated for the device + * being switched off when _DSM is executed. They cause ACPI + * hotplug to trigger and attempt to remove the device from + * the system, which causes it to break down. Prevent that from + * happening by setting the no_hotplug flag for the involved + * ACPI device objects. + */ + acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); + acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle); ret = true; } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 29c3efdfc7dd..25ea82f8def3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -610,7 +610,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ret = nouveau_fence_sync(fence, chan); nouveau_fence_unref(&fence); if (ret) - return ret; + goto fail_free; if (new_bo != old_bo) { ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); diff --git a/drivers/gpu/drm/qxl/Kconfig b/drivers/gpu/drm/qxl/Kconfig index 037d324bf58f..38c2bb72e456 100644 --- a/drivers/gpu/drm/qxl/Kconfig +++ b/drivers/gpu/drm/qxl/Kconfig @@ -5,8 +5,11 @@ config DRM_QXL select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT select FB_DEFERRED_IO - select DRM_KMS_HELPER + select DRM_KMS_HELPER select DRM_KMS_FB_HELPER - select DRM_TTM + select DRM_TTM + select CRC32 help - QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting. + QXL virtual GPU for Spice virtualization desktop integration. + Do not enable this driver unless your distro ships a corresponding + X.org QXL driver that can handle kernel modesetting. diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 5e827c29d194..d70aafb83307 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -24,7 +24,7 @@ */ -#include "linux/crc32.h" +#include <linux/crc32.h> #include "qxl_drv.h" #include "qxl_object.h" diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index b1970596a782..0b9621c9aeea 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1143,31 +1143,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, } if (tiling_flags & RADEON_TILING_MACRO) { - if (rdev->family >= CHIP_BONAIRE) - tmp = rdev->config.cik.tile_config; - else if (rdev->family >= CHIP_TAHITI) - tmp = rdev->config.si.tile_config; - else if (rdev->family >= CHIP_CAYMAN) - tmp = rdev->config.cayman.tile_config; - else - tmp = rdev->config.evergreen.tile_config; + evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); - switch ((tmp & 0xf0) >> 4) { - case 0: /* 4 banks */ - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); - break; - case 1: /* 8 banks */ - default: - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); - break; - case 2: /* 16 banks */ - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); - break; + /* Set NUM_BANKS. */ + if (rdev->family >= CHIP_BONAIRE) { + unsigned tileb, index, num_banks, tile_split_bytes; + + /* Calculate the macrotile mode index. */ + tile_split_bytes = 64 << tile_split; + tileb = 8 * 8 * target_fb->bits_per_pixel / 8; + tileb = min(tile_split_bytes, tileb); + + for (index = 0; tileb > 64; index++) { + tileb >>= 1; + } + + if (index >= 16) { + DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", + target_fb->bits_per_pixel, tile_split); + return -EINVAL; + } + + num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; + fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); + } else { + /* SI and older. */ + if (rdev->family >= CHIP_TAHITI) + tmp = rdev->config.si.tile_config; + else if (rdev->family >= CHIP_CAYMAN) + tmp = rdev->config.cayman.tile_config; + else + tmp = rdev->config.evergreen.tile_config; + + switch ((tmp & 0xf0) >> 4) { + case 0: /* 4 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); + break; + case 1: /* 8 banks */ + default: + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); + break; + case 2: /* 16 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); + break; + } } fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); - - evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split); fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw); fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh); @@ -1180,19 +1202,12 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); if (rdev->family >= CHIP_BONAIRE) { - u32 num_pipe_configs = rdev->config.cik.max_tile_pipes; - u32 num_rb = rdev->config.cik.max_backends_per_se; - if (num_pipe_configs > 8) - num_pipe_configs = 8; - if (num_pipe_configs == 8) - fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16); - else if (num_pipe_configs == 4) { - if (num_rb == 4) - fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16); - else if (num_rb < 4) - fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16); - } else if (num_pipe_configs == 2) - fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2); + /* Read the pipe config from the 2D TILED SCANOUT mode. + * It should be the same for the other modes too, but not all + * modes set the pipe config field. */ + u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f; + + fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config); } else if ((rdev->family == CHIP_TAHITI) || (rdev->family == CHIP_PITCAIRN)) fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index b43a3a3c9067..e950fabd7f5e 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3057,7 +3057,7 @@ static u32 cik_create_bitmask(u32 bit_width) * Returns the disabled RB bitmask. */ static u32 cik_get_rb_disabled(struct radeon_device *rdev, - u32 max_rb_num, u32 se_num, + u32 max_rb_num_per_se, u32 sh_per_se) { u32 data, mask; @@ -3071,7 +3071,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev, data >>= BACKEND_DISABLE_SHIFT; - mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se); + mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se); return data & mask; } @@ -3088,7 +3088,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev, */ static void cik_setup_rb(struct radeon_device *rdev, u32 se_num, u32 sh_per_se, - u32 max_rb_num) + u32 max_rb_num_per_se) { int i, j; u32 data, mask; @@ -3098,7 +3098,7 @@ static void cik_setup_rb(struct radeon_device *rdev, for (i = 0; i < se_num; i++) { for (j = 0; j < sh_per_se; j++) { cik_select_se_sh(rdev, i, j); - data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); + data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se); if (rdev->family == CHIP_HAWAII) disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH); else @@ -3108,12 +3108,14 @@ static void cik_setup_rb(struct radeon_device *rdev, cik_select_se_sh(rdev, 0xffffffff, 0xffffffff); mask = 1; - for (i = 0; i < max_rb_num; i++) { + for (i = 0; i < max_rb_num_per_se * se_num; i++) { if (!(disabled_rbs & mask)) enabled_rbs |= mask; mask <<= 1; } + rdev->config.cik.backend_enable_mask = enabled_rbs; + for (i = 0; i < se_num; i++) { cik_select_se_sh(rdev, i, 0xffffffff); data = 0; diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index de86493cbc44..713a5d359901 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -174,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) } sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); return; } @@ -235,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) } sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read SADs: %d\n", sad_count); return; } @@ -308,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev) rdev->audio.enabled = true; if (ASIC_IS_DCE8(rdev)) - rdev->audio.num_pins = 7; + rdev->audio.num_pins = 6; + else if (ASIC_IS_DCE61(rdev)) + rdev->audio.num_pins = 4; else rdev->audio.num_pins = 6; diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index aa695c4feb3d..0c6d5cef4cf1 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) } sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); return; } @@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder) } sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read SADs: %d\n", sad_count); return; } diff --git a/drivers/gpu/drm/radeon/mkregtable.c b/drivers/gpu/drm/radeon/mkregtable.c index af85299f2126..4a85bb644e24 100644 --- a/drivers/gpu/drm/radeon/mkregtable.c +++ b/drivers/gpu/drm/radeon/mkregtable.c @@ -655,7 +655,7 @@ static int parser_auth(struct table *t, const char *filename) /* first line will contain the last register * and gpu name */ - sscanf(buf, "%s %s", gpu_name, last_reg_s); + sscanf(buf, "%9s %9s", gpu_name, last_reg_s); t->gpu_prefix = gpu_name; last_reg = strtol(last_reg_s, NULL, 16); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 11aab2ab54ce..f59a9e9fccf8 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -895,6 +895,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x999C)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; } else if ((rdev->pdev->device == 0x9903) || (rdev->pdev->device == 0x9904) || (rdev->pdev->device == 0x990A) || @@ -905,6 +909,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x999D)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; } else if ((rdev->pdev->device == 0x9919) || (rdev->pdev->device == 0x9990) || (rdev->pdev->device == 0x9991) || @@ -915,9 +923,17 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x99A0)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; + rdev->config.cayman.max_hw_contexts = 4; + rdev->config.cayman.sx_max_export_size = 128; + rdev->config.cayman.sx_max_export_pos_size = 32; + rdev->config.cayman.sx_max_export_smx_size = 96; } else { rdev->config.cayman.max_simds_per_se = 2; rdev->config.cayman.max_backends_per_se = 1; + rdev->config.cayman.max_hw_contexts = 4; + rdev->config.cayman.sx_max_export_size = 128; + rdev->config.cayman.sx_max_export_pos_size = 32; + rdev->config.cayman.sx_max_export_smx_size = 96; } rdev->config.cayman.max_texture_channel_caches = 2; rdev->config.cayman.max_gprs = 256; @@ -925,10 +941,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.max_gs_threads = 32; rdev->config.cayman.max_stack_entries = 512; rdev->config.cayman.sx_num_of_sets = 8; - rdev->config.cayman.sx_max_export_size = 256; - rdev->config.cayman.sx_max_export_pos_size = 64; - rdev->config.cayman.sx_max_export_smx_size = 192; - rdev->config.cayman.max_hw_contexts = 8; rdev->config.cayman.sq_num_cf_insts = 2; rdev->config.cayman.sc_prim_fifo_size = 0x40; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b1f990d0eaa1..45e1f447bc79 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1940,7 +1940,7 @@ struct si_asic { unsigned sc_earlyz_tile_fifo_size; unsigned num_tile_pipes; - unsigned num_backends_per_se; + unsigned backend_enable_mask; unsigned backend_disable_mask_per_asic; unsigned backend_map; unsigned num_texture_channel_caches; @@ -1970,7 +1970,7 @@ struct cik_asic { unsigned sc_earlyz_tile_fifo_size; unsigned num_tile_pipes; - unsigned num_backends_per_se; + unsigned backend_enable_mask; unsigned backend_disable_mask_per_asic; unsigned backend_map; unsigned num_texture_channel_caches; diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 98a9074b306b..77e9d07c55b6 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -25,18 +25,14 @@ #include <linux/acpi.h> #include <linux/slab.h> #include <linux/power_supply.h> -#include <acpi/acpi_drivers.h> -#include <acpi/acpi_bus.h> +#include <linux/vga_switcheroo.h> #include <acpi/video.h> - #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include "radeon.h" #include "radeon_acpi.h" #include "atom.h" -#include <linux/vga_switcheroo.h> - #define ACPI_AC_CLASS "ac_adapter" extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 9d302eaeea15..485848f889f5 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -33,6 +33,7 @@ static struct radeon_atpx_priv { bool atpx_detected; /* handle for device - and atpx */ acpi_handle dhandle; + acpi_handle other_handle; struct radeon_atpx atpx; } radeon_atpx_priv; @@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) return false; status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + radeon_atpx_priv.other_handle = dhandle; return false; - + } radeon_atpx_priv.dhandle = dhandle; radeon_atpx_priv.atpx.handle = atpx_handle; return true; @@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void) printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", acpi_method_name); radeon_atpx_priv.atpx_detected = true; + /* + * On some systems hotplug events are generated for the device + * being switched off when ATPX is executed. They cause ACPI + * hotplug to trigger and attempt to remove the device from + * the system, which causes it to break down. Prevent that from + * happening by setting the no_hotplug flag for the involved + * ACPI device objects. + */ + acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); + acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); return true; } return false; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 1958b36ad0e5..db39ea36bf22 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -77,9 +77,10 @@ * 2.33.0 - Add SI tiling mode array query * 2.34.0 - Add CIK tiling mode array query * 2.35.0 - Add CIK macrotile mode array query + * 2.36.0 - Fix CIK DCE tiling setup */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 35 +#define KMS_DRIVER_MINOR 36 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 55d0b474bd37..21d593c0ecaf 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -461,6 +461,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) case RADEON_INFO_SI_CP_DMA_COMPUTE: *value = 1; break; + case RADEON_INFO_SI_BACKEND_ENABLED_MASK: + if (rdev->family >= CHIP_BONAIRE) { + *value = rdev->config.cik.backend_enable_mask; + } else if (rdev->family >= CHIP_TAHITI) { + *value = rdev->config.si.backend_enable_mask; + } else { + DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n"); + } + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 373d088bac66..b9c0529b4a2e 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -473,7 +473,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, return -EINVAL; } - if ((start >> 28) != (end >> 28)) { + if ((start >> 28) != ((end - 1) >> 28)) { DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n", start, end); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 913b025ae9b3..374499db20c7 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2328,6 +2328,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev) pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, ASIC_INTERNAL_MEMORY_SS, 0); + /* disable ss, causes hangs on some cayman boards */ + if (rdev->family == CHIP_CAYMAN) { + pi->sclk_ss = false; + pi->mclk_ss = false; + } + if (pi->sclk_ss || pi->mclk_ss) pi->dynamic_ss = true; else diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index a36736dab5e0..85e1edfaa3be 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2811,7 +2811,7 @@ static void si_setup_spi(struct radeon_device *rdev, } static u32 si_get_rb_disabled(struct radeon_device *rdev, - u32 max_rb_num, u32 se_num, + u32 max_rb_num_per_se, u32 sh_per_se) { u32 data, mask; @@ -2825,14 +2825,14 @@ static u32 si_get_rb_disabled(struct radeon_device *rdev, data >>= BACKEND_DISABLE_SHIFT; - mask = si_create_bitmask(max_rb_num / se_num / sh_per_se); + mask = si_create_bitmask(max_rb_num_per_se / sh_per_se); return data & mask; } static void si_setup_rb(struct radeon_device *rdev, u32 se_num, u32 sh_per_se, - u32 max_rb_num) + u32 max_rb_num_per_se) { int i, j; u32 data, mask; @@ -2842,19 +2842,21 @@ static void si_setup_rb(struct radeon_device *rdev, for (i = 0; i < se_num; i++) { for (j = 0; j < sh_per_se; j++) { si_select_se_sh(rdev, i, j); - data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); + data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se); disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); } } si_select_se_sh(rdev, 0xffffffff, 0xffffffff); mask = 1; - for (i = 0; i < max_rb_num; i++) { + for (i = 0; i < max_rb_num_per_se * se_num; i++) { if (!(disabled_rbs & mask)) enabled_rbs |= mask; mask <<= 1; } + rdev->config.si.backend_enable_mask = enabled_rbs; + for (i = 0; i < se_num; i++) { si_select_se_sh(rdev, i, 0xffffffff); data = 0; diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 8961ba6a34b8..8db9b3bce001 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -2,6 +2,7 @@ config DRM_TEGRA bool "NVIDIA Tegra DRM" depends on ARCH_TEGRA || ARCH_MULTIPLATFORM depends on DRM + depends on RESET_CONTROLLER select TEGRA_HOST1X select DRM_KMS_HELPER select DRM_KMS_FB_HELPER diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ae1cb31ead7e..cd7f1e499616 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -8,8 +8,8 @@ */ #include <linux/clk.h> -#include <linux/clk/tegra.h> #include <linux/debugfs.h> +#include <linux/reset.h> #include "dc.h" #include "drm.h" @@ -712,7 +712,7 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) unsigned long value; /* hardware initialization */ - tegra_periph_reset_deassert(dc->clk); + reset_control_deassert(dc->rst); usleep_range(10000, 20000); if (dc->pipe) @@ -1187,6 +1187,12 @@ static int tegra_dc_probe(struct platform_device *pdev) return PTR_ERR(dc->clk); } + dc->rst = devm_reset_control_get(&pdev->dev, "dc"); + if (IS_ERR(dc->rst)) { + dev_err(&pdev->dev, "failed to get reset\n"); + return PTR_ERR(dc->rst); + } + err = clk_prepare_enable(dc->clk); if (err < 0) return err; diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 7da0b923131f..266aae08a3bd 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -19,6 +19,8 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fixed.h> +struct reset_control; + struct tegra_fb { struct drm_framebuffer base; struct tegra_bo **planes; @@ -93,6 +95,7 @@ struct tegra_dc { int pipe; struct clk *clk; + struct reset_control *rst; void __iomem *regs; int irq; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 4cec8f526af7..0cbb24b1ae04 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -11,6 +11,7 @@ #include <linux/host1x.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/reset.h> #include <linux/tegra-powergate.h> #include "drm.h" @@ -22,6 +23,8 @@ struct gr3d { struct host1x_channel *channel; struct clk *clk_secondary; struct clk *clk; + struct reset_control *rst_secondary; + struct reset_control *rst; DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS); }; @@ -255,15 +258,29 @@ static int gr3d_probe(struct platform_device *pdev) return PTR_ERR(gr3d->clk); } + gr3d->rst = devm_reset_control_get(&pdev->dev, "3d"); + if (IS_ERR(gr3d->rst)) { + dev_err(&pdev->dev, "cannot get reset\n"); + return PTR_ERR(gr3d->rst); + } + if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) { gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2"); if (IS_ERR(gr3d->clk)) { dev_err(&pdev->dev, "cannot get secondary clock\n"); return PTR_ERR(gr3d->clk); } + + gr3d->rst_secondary = devm_reset_control_get(&pdev->dev, + "3d2"); + if (IS_ERR(gr3d->rst_secondary)) { + dev_err(&pdev->dev, "cannot get secondary reset\n"); + return PTR_ERR(gr3d->rst_secondary); + } } - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk); + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk, + gr3d->rst); if (err < 0) { dev_err(&pdev->dev, "failed to power up 3D unit\n"); return err; @@ -271,7 +288,8 @@ static int gr3d_probe(struct platform_device *pdev) if (gr3d->clk_secondary) { err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1, - gr3d->clk_secondary); + gr3d->clk_secondary, + gr3d->rst_secondary); if (err < 0) { dev_err(&pdev->dev, "failed to power up secondary 3D unit\n"); diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 0cd9bc2056e8..7f6253ea5cb5 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -8,10 +8,10 @@ */ #include <linux/clk.h> -#include <linux/clk/tegra.h> #include <linux/debugfs.h> #include <linux/hdmi.h> #include <linux/regulator/consumer.h> +#include <linux/reset.h> #include "hdmi.h" #include "drm.h" @@ -49,6 +49,7 @@ struct tegra_hdmi { struct clk *clk_parent; struct clk *clk; + struct reset_control *rst; const struct tegra_hdmi_config *config; @@ -731,9 +732,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) return err; } - tegra_periph_reset_assert(hdmi->clk); + reset_control_assert(hdmi->rst); usleep_range(1000, 2000); - tegra_periph_reset_deassert(hdmi->clk); + reset_control_deassert(hdmi->rst); tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS); @@ -912,7 +913,7 @@ static int tegra_output_hdmi_disable(struct tegra_output *output) { struct tegra_hdmi *hdmi = to_hdmi(output); - tegra_periph_reset_assert(hdmi->clk); + reset_control_assert(hdmi->rst); clk_disable(hdmi->clk); regulator_disable(hdmi->pll); @@ -1338,6 +1339,12 @@ static int tegra_hdmi_probe(struct platform_device *pdev) return PTR_ERR(hdmi->clk); } + hdmi->rst = devm_reset_control_get(&pdev->dev, "hdmi"); + if (IS_ERR(hdmi->rst)) { + dev_err(&pdev->dev, "failed to get reset\n"); + return PTR_ERR(hdmi->rst); + } + err = clk_prepare(hdmi->clk); if (err < 0) return err; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 15b86a94949d..406152152315 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -353,7 +353,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, * Don't move nonexistent data. Clear destination instead. */ if (old_iomap == NULL && - (ttm == NULL || ttm->state == tt_unpopulated)) { + (ttm == NULL || (ttm->state == tt_unpopulated && + !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) { memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE); goto out2; } |