summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c11
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_defs.h4
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_drm.c8
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c49
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h3
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c22
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c12
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c6
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_intf.c9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_top.c4
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c12
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c2
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c7
-rw-r--r--drivers/gpu/msm/kgsl.c3
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c2
17 files changed, 112 insertions, 48 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index ac6c47bd33ae..3caa460aa5ba 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -263,8 +263,6 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
local_irq_restore(flags);
- do_div(ktime, NSEC_PER_SEC);
-
profile_buf->queue_time = ktime;
profile_buf->submit_time = ktime;
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index a66c7e80d2af..d3cb497411c4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -176,7 +176,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct msm_ringbuffer *ring = gpu->rb[submit->ring];
- unsigned i, ibs = 0;
+ unsigned i;
for (i = 0; i < submit->nr_cmds; i++) {
switch (submit->cmd[i].type) {
@@ -191,18 +191,11 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
OUT_RING(ring, submit->cmd[i].size);
- ibs++;
+ OUT_PKT2(ring);
break;
}
}
- /* on a320, at least, we seem to need to pad things out to an
- * even number of qwords to avoid issue w/ CP hanging on wrap-
- * around:
- */
- if (ibs % 2)
- OUT_PKT2(ring);
-
OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
OUT_RING(ring, submit->fence);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index d9fcec60693d..91501a2efd20 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -198,12 +198,12 @@ enum dsi_video_traffic_mode {
* @h_sync_width: HSYNC width in pixels.
* @h_front_porch: Horizontal fron porch in pixels.
* @h_skew:
- * @h_sync_polarity: Polarity of HSYNC (false is active low).
+ * @h_sync_polarity: Polarity of HSYNC (false is active high).
* @v_active: Active height of one frame in lines.
* @v_back_porch: Vertical back porch in lines.
* @v_sync_width: VSYNC width in lines.
* @v_front_porch: Vertical front porch in lines.
- * @v_sync_polarity: Polarity of VSYNC (false is active low).
+ * @v_sync_polarity: Polarity of VSYNC (false is active high).
* @refresh_rate: Refresh rate in Hz.
*/
struct dsi_mode_info {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 995cda97a2f0..c34713a13332 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -56,6 +56,10 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
dsi_mode->flags |= DSI_MODE_FLAG_DFPS;
if (msm_needs_vblank_pre_modeset(drm_mode))
dsi_mode->flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
+ dsi_mode->timing.h_sync_polarity =
+ (drm_mode->flags & DRM_MODE_FLAG_PHSYNC) ? false : true;
+ dsi_mode->timing.v_sync_polarity =
+ (drm_mode->flags & DRM_MODE_FLAG_PVSYNC) ? false : true;
}
static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -87,6 +91,10 @@ static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
if (dsi_mode->flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;
+ drm_mode->flags |= (dsi_mode->timing.h_sync_polarity) ?
+ DRM_MODE_FLAG_NHSYNC : DRM_MODE_FLAG_PHSYNC;
+ drm_mode->flags |= (dsi_mode->timing.v_sync_polarity) ?
+ DRM_MODE_FLAG_NVSYNC : DRM_MODE_FLAG_PVSYNC;
drm_mode_set_name(drm_mode);
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index c377f3759e67..4c70472bd338 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -23,6 +23,7 @@
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
#include "sde_kms.h"
#include "sde_connector.h"
@@ -967,6 +968,18 @@ static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi)
}
}
+static void _sde_hdmi_cec_irq(struct sde_hdmi *sde_hdmi)
+{
+ struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
+ u32 cec_intr = hdmi_read(hdmi, REG_HDMI_CEC_INT);
+
+ /* Routing interrupt to external CEC drivers */
+ if (cec_intr)
+ generic_handle_irq(irq_find_mapping(
+ sde_hdmi->irq_domain, 1));
+}
+
+
static irqreturn_t _sde_hdmi_irq(int irq, void *dev_id)
{
struct sde_hdmi *sde_hdmi = dev_id;
@@ -987,7 +1000,8 @@ static irqreturn_t _sde_hdmi_irq(int irq, void *dev_id)
if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported)
hdmi_hdcp_ctrl_irq(hdmi->hdcp_ctrl);
- /* TODO audio.. */
+ /* Process CEC: */
+ _sde_hdmi_cec_irq(sde_hdmi);
return IRQ_HANDLED;
}
@@ -2017,6 +2031,29 @@ static struct platform_driver sde_hdmi_driver = {
},
};
+static int sde_hdmi_irqdomain_map(struct irq_domain *domain,
+ unsigned int irq, irq_hw_number_t hwirq)
+{
+ struct sde_hdmi *display;
+ int rc;
+
+ if (!domain || !domain->host_data) {
+ pr_err("invalid parameters domain\n");
+ return -EINVAL;
+ }
+ display = domain->host_data;
+
+ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
+ rc = irq_set_chip_data(irq, display);
+
+ return rc;
+}
+
+static const struct irq_domain_ops sde_hdmi_irqdomain_ops = {
+ .map = sde_hdmi_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
{
int rc = 0;
@@ -2071,6 +2108,13 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
goto error;
}
+ display->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 8,
+ &sde_hdmi_irqdomain_ops, display);
+ if (!display->irq_domain) {
+ SDE_ERROR("failed to create IRQ domain\n");
+ goto error;
+ }
+
enc->bridge = hdmi->bridge;
priv->bridges[priv->num_bridges++] = hdmi->bridge;
@@ -2096,6 +2140,9 @@ int sde_hdmi_drm_deinit(struct sde_hdmi *display)
return -EINVAL;
}
+ if (display->irq_domain)
+ irq_domain_remove(display->irq_domain);
+
return rc;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index ffa9a27e7dfe..54506da4f9b0 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -86,6 +86,7 @@ struct sde_hdmi_ctrl {
* @hpd_work: HPD work structure.
* @codec_ready: If audio codec is ready.
* @client_notify_pending: If there is client notification pending.
+ * @irq_domain: IRQ domain structure.
* @root: Debug fs root entry.
*/
struct sde_hdmi {
@@ -114,6 +115,8 @@ struct sde_hdmi {
bool codec_ready;
bool client_notify_pending;
+ struct irq_domain *irq_domain;
+
/* DEBUG FS */
struct dentry *root;
};
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index d8791155236c..fa746d71cd3b 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
* Copyright (C) 2014 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -429,11 +429,21 @@ static void complete_commit(struct msm_commit *commit)
commit_destroy(commit);
}
+static int msm_atomic_commit_dispatch(struct drm_device *dev,
+ struct drm_atomic_state *state, struct msm_commit *commit);
+
static void fence_cb(struct msm_fence_cb *cb)
{
struct msm_commit *commit =
container_of(cb, struct msm_commit, fence_cb);
- complete_commit(commit);
+ int ret = -EINVAL;
+
+ ret = msm_atomic_commit_dispatch(commit->dev, commit->state, commit);
+ if (ret) {
+ DRM_ERROR("%s: atomic commit failed\n", __func__);
+ drm_atomic_state_free(commit->state);
+ commit_destroy(commit);
+ }
}
static void _msm_drm_commit_work_cb(struct kthread_work *work)
@@ -624,13 +634,7 @@ int msm_atomic_commit(struct drm_device *dev,
*/
if (async) {
- ret = msm_atomic_commit_dispatch(dev, state, commit);
- if (ret) {
- DRM_ERROR("%s: atomic commit failed\n", __func__);
- drm_atomic_state_free(state);
- commit_destroy(commit);
- goto error;
- }
+ msm_queue_fence_cb(dev, &commit->fence_cb, commit->fence);
return 0;
}
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index d5204221d902..41b4b5a4fd66 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -101,8 +101,6 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
return fence;
}
-#define MAX_CMDS 4
-
/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
* associated with the cmdstream submission for synchronization (and
* make it easier to unwind when things go wrong, etc). This only
@@ -127,7 +125,7 @@ struct msm_gem_submit {
uint32_t size; /* in dwords */
uint64_t iova;
uint32_t idx; /* cmdstream buffer idx in bos[] */
- } cmd[MAX_CMDS];
+ } *cmd; /* array of size nr_cmds */
struct {
uint32_t flags;
struct msm_gem_object *obj;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index ea7b4441fe99..12cc28acec18 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -34,10 +34,11 @@ static inline void __user *to_user_ptr(u64 address)
}
static struct msm_gem_submit *submit_create(struct drm_device *dev,
- struct msm_gem_address_space *aspace, int nr)
+ struct msm_gem_address_space *aspace, int nr_bos, int nr_cmds)
{
struct msm_gem_submit *submit;
- int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0]));
+ int sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) +
+ (nr_cmds * sizeof(*submit->cmd));
submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (submit) {
@@ -50,6 +51,8 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
submit->profile_buf_vaddr = NULL;
submit->profile_buf_iova = 0;
+ submit->cmd = (void *)&submit->bos[nr_bos];
+
submit->secure = false;
INIT_LIST_HEAD(&submit->bo_list);
@@ -393,12 +396,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
if (!gpu)
return -ENXIO;
- if (args->nr_cmds > MAX_CMDS)
- return -EINVAL;
-
mutex_lock(&dev->struct_mutex);
- submit = submit_create(dev, ctx->aspace, args->nr_bos);
+ submit = submit_create(dev, ctx->aspace, args->nr_bos, args->nr_cmds);
if (!submit) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index e61ff97d2ca4..0b6ee302e231 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -73,12 +73,6 @@ static void drm_mode_to_intf_timing_params(
timing->underflow_clr = 0xff;
timing->hsync_skew = mode->hskew;
- /* DSI controller cannot handle active-low sync signals. */
- if (vid_enc->hw_intf->cap->type == INTF_DSI) {
- timing->hsync_polarity = 0;
- timing->vsync_polarity = 0;
- }
-
/*
* For edp only:
* DISPLAY_V_START = (VBP * HCYCLE) + HBP
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.c b/drivers/gpu/drm/msm/sde/sde_hw_intf.c
index 3b34719e9971..042b0ee7909a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.c
@@ -157,13 +157,8 @@ static void sde_hw_intf_setup_timing_engine(struct sde_hw_intf *ctx,
display_hctl = (hsync_end_x << 16) | hsync_start_x;
den_polarity = 0;
- if (ctx->cap->type == INTF_HDMI) {
- hsync_polarity = p->yres >= 720 ? 0 : 1;
- vsync_polarity = p->yres >= 720 ? 0 : 1;
- } else {
- hsync_polarity = 0;
- vsync_polarity = 0;
- }
+ hsync_polarity = p->hsync_polarity;
+ vsync_polarity = p->vsync_polarity;
polarity_ctl = (den_polarity << 2) | /* DEN Polarity */
(vsync_polarity << 1) | /* VSYNC Polarity */
(hsync_polarity << 0); /* HSYNC Polarity */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index 1a5d469e6e7e..d6d2e41ff5aa 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -42,6 +42,10 @@ static void sde_hw_setup_split_pipe(struct sde_hw_mdp *mdp,
if (!mdp || !cfg)
return;
+ /* The SPLIT registers are only for DSI interfaces */
+ if ((cfg->intf != INTF_1) && (cfg->intf != INTF_2))
+ return;
+
if (cfg->en) {
if (cfg->mode == INTF_MODE_CMD) {
lower_pipe = FLD_SPLIT_DISPLAY_CMD;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 8fb7213277cc..b75391495778 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -66,8 +66,11 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
goto out_unlock;
+ ttm_bo_reference(bo);
up_read(&vma->vm_mm->mmap_sem);
(void) ttm_bo_wait(bo, false, true, false);
+ ttm_bo_unreserve(bo);
+ ttm_bo_unref(&bo);
goto out_unlock;
}
@@ -114,8 +117,10 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+ ttm_bo_reference(bo);
up_read(&vma->vm_mm->mmap_sem);
(void) ttm_bo_wait_unreserved(bo);
+ ttm_bo_unref(&bo);
}
return VM_FAULT_RETRY;
@@ -160,6 +165,13 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
if (unlikely(ret != 0)) {
retval = ret;
+
+ if (retval == VM_FAULT_RETRY &&
+ !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+ /* The BO has already been unreserved. */
+ return retval;
+ }
+
goto out_unlock;
}
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 0715022be6e3..dcc6651710fe 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -59,7 +59,7 @@ static const struct adreno_vbif_platform a5xx_vbif_platforms[] = {
{ adreno_is_a530, a530_vbif },
{ adreno_is_a512, a540_vbif },
{ adreno_is_a510, a530_vbif },
- { adreno_is_a508, a530_vbif },
+ { adreno_is_a508, a540_vbif },
{ adreno_is_a505, a530_vbif },
{ adreno_is_a506, a530_vbif },
};
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 54b8da5302e8..55f906c9cb90 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -2090,7 +2090,12 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
/* Turn off all the timers */
del_timer_sync(&dispatcher->timer);
del_timer_sync(&dispatcher->fault_timer);
- del_timer_sync(&adreno_dev->preempt.timer);
+ /*
+ * Deleting uninitialized timer will block for ever on kernel debug
+ * disable build. Hence skip del timer if it is not initialized.
+ */
+ if (adreno_is_preemption_enabled(adreno_dev))
+ del_timer_sync(&adreno_dev->preempt.timer);
mutex_lock(&device->mutex);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 50f55abd6db8..b2def8dea954 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1238,7 +1238,8 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr)
spin_lock(&private->mem_lock);
idr_for_each_entry(&private->mem_idr, entry, id) {
if (GPUADDR_IN_MEMDESC(gpuaddr, &entry->memdesc)) {
- ret = kgsl_mem_entry_get(entry);
+ if (!entry->pending_free)
+ ret = kgsl_mem_entry_get(entry);
break;
}
}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index af9fc1c15236..57d99c451952 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1547,6 +1547,8 @@ static int _setup_user_context(struct kgsl_mmu *mmu)
ret = PTR_ERR(mmu->defaultpagetable);
mmu->defaultpagetable = NULL;
return ret;
+ } else if (mmu->defaultpagetable == NULL) {
+ return -ENOMEM;
}
}