aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/hw/channel_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/hw/channel_hw.c')
-rw-r--r--drivers/gpu/host1x/hw/channel_hw.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index 95ea81172a83..27101c04a827 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -17,6 +17,7 @@
*/
#include <linux/host1x.h>
+#include <linux/iommu.h>
#include <linux/slab.h>
#include <trace/events/host1x.h>
@@ -60,15 +61,37 @@ static void trace_write_gather(struct host1x_cdma *cdma, struct host1x_bo *bo,
static void submit_gathers(struct host1x_job *job)
{
struct host1x_cdma *cdma = &job->channel->cdma;
+#if HOST1X_HW < 6
+ struct device *dev = job->channel->dev;
+#endif
unsigned int i;
for (i = 0; i < job->num_gathers; i++) {
struct host1x_job_gather *g = &job->gathers[i];
- u32 op1 = host1x_opcode_gather(g->words);
- u32 op2 = g->base + g->offset;
+ dma_addr_t addr = g->base + g->offset;
+ u32 op2, op3;
+
+ op2 = lower_32_bits(addr);
+ op3 = upper_32_bits(addr);
+
+ trace_write_gather(cdma, g->bo, g->offset, g->words);
+
+ if (op3 != 0) {
+#if HOST1X_HW >= 6
+ u32 op1 = host1x_opcode_gather_wide(g->words);
+ u32 op4 = HOST1X_OPCODE_NOP;
+
+ host1x_cdma_push_wide(cdma, op1, op2, op3, op4);
+#else
+ dev_err(dev, "invalid gather for push buffer %pad\n",
+ &addr);
+ continue;
+#endif
+ } else {
+ u32 op1 = host1x_opcode_gather(g->words);
- trace_write_gather(cdma, g->bo, g->offset, op1 & 0xffff);
- host1x_cdma_push(cdma, op1, op2);
+ host1x_cdma_push(cdma, op1, op2);
+ }
}
}
@@ -89,6 +112,16 @@ static inline void synchronize_syncpt_base(struct host1x_job *job)
HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value));
}
+static void host1x_channel_set_streamid(struct host1x_channel *channel)
+{
+#if HOST1X_HW >= 6
+ struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
+ u32 sid = spec ? spec->ids[0] & 0xffff : 0x7f;
+
+ host1x_ch_writel(channel, sid, HOST1X_CHANNEL_SMMU_STREAMID);
+#endif
+}
+
static int channel_submit(struct host1x_job *job)
{
struct host1x_channel *ch = job->channel;
@@ -120,6 +153,8 @@ static int channel_submit(struct host1x_job *job)
goto error;
}
+ host1x_channel_set_streamid(ch);
+
/* begin a CDMA submit */
err = host1x_cdma_begin(&ch->cdma, job);
if (err) {