summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2011-05-19 09:35:16 +0300
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:47:06 -0800
commit6f4a299341a041e1806b9f5f8c7c0b7f1cf79b05 (patch)
treea38c40f7e9302cff74495b6037e7f69af48cf3c6 /drivers/video
parent631c72bca98bfcad320da08328629339f8b75d1c (diff)
nvhost: Make 3D workaround Tegra3 A01 only
3D hardware workaround is needed for Tegra3 A01 only. With this patch, we read run-time whether it should be enabled or not. Workaround should be removed once A01's have been phased out. Bug 786316 Original-Change-Id: Icd1b85b30a53c74d2e5c7a6df65a805d1fe5147c Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/32136 Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Rebase-Id: R6053c07b62aea3c2710d0d2ad6b5647a9fcf486b
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/tegra/host/nvhost_3dctx.c128
-rw-r--r--drivers/video/tegra/host/nvhost_hardware.h21
2 files changed, 94 insertions, 55 deletions
diff --git a/drivers/video/tegra/host/nvhost_3dctx.c b/drivers/video/tegra/host/nvhost_3dctx.c
index 18d8a1d138b3..ecbca73454aa 100644
--- a/drivers/video/tegra/host/nvhost_3dctx.c
+++ b/drivers/video/tegra/host/nvhost_3dctx.c
@@ -24,6 +24,7 @@
#include "dev.h"
#include <mach/gpufuse.h>
+#include <mach/hardware.h>
#include <linux/slab.h>
#define NV_WAR_789194 1
@@ -35,6 +36,7 @@ static bool s_is_v1 = false;
#else
static bool s_is_v1 = true;
#endif
+static bool s_war_insert_syncpoints;
const struct hwctx_reginfo ctxsave_regs_3d_global[] = {
HWCTX_REGINFO(0, 0xe00, 4, DIRECT),
@@ -152,7 +154,8 @@ static void restore_indirect(u32 *ptr, u32 offset_reg, u32 offset,
static void restore_end(u32 *ptr)
{
/* syncpt increment to track restore gather. */
- ptr[0] = nvhost_opcode_imm(0x0, 0x100 | NVSYNCPT_3D);
+ ptr[0] = nvhost_opcode_imm_incr_syncpt(NV_CLASS_HOST_SYNCPT_OP_DONE,
+ NVSYNCPT_3D);
}
#define RESTORE_END_SIZE 1
@@ -270,34 +273,42 @@ static void __init switch_gpu(struct save_info *info,
u32 save_dest_sets,
u32 restore_dest_sets)
{
-#if NV_WAR_789194
- if (info->ptr) {
- info->ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID,
- 0, 0);
- info->ptr[1] = nvhost_opcode_nonincr(0x905, 2);
- info->ptr[2] = nvhost_opcode_imm(0, 0x200 | NVSYNCPT_3D);
- info->ptr[3] = nvhost_opcode_imm(0xb00, restore_dest_sets);
- info->ptr[4] = nvhost_opcode_imm(0, 0x200 | NVSYNCPT_3D);
- info->ptr[5] = nvhost_opcode_imm(0xb00, save_dest_sets);
- info->ptr[6] = nvhost_opcode_imm(0xb01, save_src_set);
- info->ptr += 7;
- }
- info->save_count += 7;
- info->restore_count += 2;
- info->save_incrs += 1;
- info->restore_incrs += 1;
-#else
- if (info->ptr) {
- info->ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID,
- 0x905, 1);
- info->ptr[1] = nvhost_opcode_imm(0xb00, restore_dest_sets);
- info->ptr[2] = nvhost_opcode_imm(0xb00, save_dest_sets);
- info->ptr[3] = nvhost_opcode_imm(0xb01, save_src_set);
- info->ptr += 4;
+ if (s_war_insert_syncpoints) {
+ if (info->ptr) {
+ info->ptr[0] = nvhost_opcode_setclass(
+ NV_GRAPHICS_3D_CLASS_ID,
+ 0, 0);
+ info->ptr[1] = nvhost_opcode_nonincr(0x905, 2);
+ info->ptr[2] = nvhost_opcode_imm_incr_syncpt(
+ NV_CLASS_HOST_SYNCPT_RD_DONE,
+ NVSYNCPT_3D);
+ info->ptr[3] = nvhost_opcode_imm(0xb00,
+ restore_dest_sets);
+ info->ptr[4] = nvhost_opcode_imm_incr_syncpt(
+ NV_CLASS_HOST_SYNCPT_RD_DONE,
+ NVSYNCPT_3D);
+ info->ptr[5] = nvhost_opcode_imm(0xb00, save_dest_sets);
+ info->ptr[6] = nvhost_opcode_imm(0xb01, save_src_set);
+ info->ptr += 7;
+ }
+ info->save_count += 7;
+ info->restore_count += 2;
+ info->save_incrs += 1;
+ info->restore_incrs += 1;
+ } else {
+ if (info->ptr) {
+ info->ptr[0] = nvhost_opcode_setclass(
+ NV_GRAPHICS_3D_CLASS_ID,
+ 0x905, 1);
+ info->ptr[1] = nvhost_opcode_imm(0xb00,
+ restore_dest_sets);
+ info->ptr[2] = nvhost_opcode_imm(0xb00, save_dest_sets);
+ info->ptr[3] = nvhost_opcode_imm(0xb01, save_src_set);
+ info->ptr += 4;
+ }
+ info->save_count += 4;
+ info->restore_count += 1;
}
- info->save_count += 4;
- info->restore_count += 1;
-#endif
}
static void __init setup_save(const struct ctx_saver *saver, u32 *ptr)
@@ -309,6 +320,7 @@ static void __init setup_save(const struct ctx_saver *saver, u32 *ptr)
saver->save_incrs,
1
};
+ int save_end_size = saver->save_end_size;
BUG_ON(register_sets > 2);
if (info.ptr) {
@@ -349,19 +361,20 @@ static void __init setup_save(const struct ctx_saver *saver, u32 *ptr)
if (register_sets == 2)
switch_gpu(&info, 0, 2, 3);
+ if (s_war_insert_syncpoints) {
+ if (s_is_v1)
+ info.save_incrs += register_sets;
+ save_end_size++;
+ }
+
if (info.ptr) {
saver->save_end(info.ptr);
- info.ptr += saver->save_end_size;
+ info.ptr += save_end_size;
}
wmb();
-#ifdef NV_WAR_789194
- if (s_is_v1)
- info.save_incrs += register_sets;
-#endif
-
- save_size = info.save_count + saver->save_end_size;
+ save_size = info.save_count + save_end_size;
restore_size = info.restore_count + RESTORE_END_SIZE;
save_incrs = info.save_incrs;
save_thresh = save_incrs - saver->save_thresh_offset;
@@ -383,14 +396,16 @@ static void __init save_begin_v0(u32 *ptr)
{
/* 3d: when done, increment syncpt to base+1 */
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0);
- ptr[1] = nvhost_opcode_imm(0, 0x100 | NVSYNCPT_3D); /* incr 1 */
+ ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_CLASS_HOST_SYNCPT_OP_DONE,
+ NVSYNCPT_3D); /* incr 1 */
/* host: wait for syncpt base+1 */
ptr[2] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1);
ptr[3] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D,
NVWAITBASE_3D, 1);
/* host: signal context read thread to start reading */
- ptr[4] = nvhost_opcode_imm(0, NVSYNCPT_3D); /* incr 2 */
+ ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_CLASS_HOST_SYNCPT_IMMEDIATE,
+ NVSYNCPT_3D); /* incr 2 */
}
#define SAVE_BEGIN_V0_SIZE 5
@@ -502,7 +517,9 @@ static void save_push_v1(struct nvhost_cdma *cdma,
/* wait for 3d idle */
nvhost_cdma_push(cdma,
nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0),
- nvhost_opcode_imm(0, 0x100 | NVSYNCPT_3D));
+ nvhost_opcode_imm_incr_syncpt(
+ NV_CLASS_HOST_SYNCPT_OP_DONE,
+ NVSYNCPT_3D));
nvhost_cdma_push(cdma,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1),
@@ -521,11 +538,12 @@ static void save_push_v1(struct nvhost_cdma *cdma,
nvhost_cdma_push(cdma,
nvhost_opcode_nonincr(0x904, 1),
ctx->restore_phys + restore_set1_offset * 4);
-#if NV_WAR_789194
- nvhost_cdma_push(cdma,
+ if (s_war_insert_syncpoints)
+ nvhost_cdma_push(cdma,
NVHOST_OPCODE_NOOP,
- nvhost_opcode_imm(0, 0x200 | NVSYNCPT_3D));
-#endif
+ nvhost_opcode_imm_incr_syncpt(
+ NV_CLASS_HOST_SYNCPT_RD_DONE,
+ NVSYNCPT_3D));
}
nvhost_cdma_push(cdma,
nvhost_opcode_imm(0xb00, 1),
@@ -589,14 +607,17 @@ static void __init save_end_v1(u32 *ptr)
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0x905, 1);
restore_end(ptr + 1);
ptr += RESTORE_END_SIZE;
- /* reset to sli if necessary */
-#if NV_WAR_789194
- ptr[1] = nvhost_opcode_imm(0, 0x200 | NVSYNCPT_3D);
- ptr += 1;
-#endif
+ /* reset to two register sets if necessary */
+ if (s_war_insert_syncpoints) {
+ ptr[1] = nvhost_opcode_imm_incr_syncpt(
+ NV_CLASS_HOST_SYNCPT_RD_DONE,
+ NVSYNCPT_3D);
+ ptr += 1;
+ }
ptr[1] = nvhost_opcode_imm(0xb00, (1 << register_sets) - 1);
/* op_done syncpt incr to flush FDC */
- ptr[2] = nvhost_opcode_imm(0, 0x100 | NVSYNCPT_3D);
+ ptr[2] = nvhost_opcode_imm_incr_syncpt(NV_CLASS_HOST_SYNCPT_OP_DONE,
+ NVSYNCPT_3D);
/* host wait for that syncpt incr, and advance the wait base */
ptr[3] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
NV_CLASS_HOST_WAIT_SYNCPT_BASE,
@@ -612,14 +633,10 @@ static void __init save_end_v1(u32 *ptr)
/* send reg reads back to host */
ptr[7] = nvhost_opcode_imm(0xe40, 0);
/* final syncpt increment to release waiters */
- ptr[8] = nvhost_opcode_imm(0, NVSYNCPT_3D);
+ ptr[8] = nvhost_opcode_imm_incr_syncpt(NV_CLASS_HOST_SYNCPT_IMMEDIATE,
+ NVSYNCPT_3D);
}
-#if NV_WAR_789194
-#define SAVE_END_V1_SIZE (10 + RESTORE_END_SIZE)
-#else
#define SAVE_END_V1_SIZE (9 + RESTORE_END_SIZE)
-#endif
-
/*** ctx3d ***/
@@ -768,6 +785,9 @@ int __init nvhost_3dctx_handler_init(struct nvhost_hwctx_handler *h)
register_sets = tegra_gpu_register_sets();
BUG_ON(register_sets == 0 || register_sets > 2);
+ s_war_insert_syncpoints = tegra_get_chipid() == TEGRA_CHIPID_TEGRA3
+ && tegra_get_revision() == TEGRA_REVISION_A01;
+
setup_save(saver, NULL);
save_buf = nvmap_alloc(nvmap, save_size * 4, 32,
diff --git a/drivers/video/tegra/host/nvhost_hardware.h b/drivers/video/tegra/host/nvhost_hardware.h
index 3cb2901d4369..8fa219595789 100644
--- a/drivers/video/tegra/host/nvhost_hardware.h
+++ b/drivers/video/tegra/host/nvhost_hardware.h
@@ -130,7 +130,7 @@ static inline unsigned int nvhost_sync_mlock_owner_owner_chid(u32 reg)
}
-/* host class */
+/* host class methods */
enum {
NV_CLASS_HOST_INCR_SYNCPT = 0x0,
NV_CLASS_HOST_WAIT_SYNCPT = 0x8,
@@ -139,6 +139,13 @@ enum {
NV_CLASS_HOST_INDOFF = 0x2d,
NV_CLASS_HOST_INDDATA = 0x2e
};
+/* sync point conditionals */
+enum {
+ NV_CLASS_HOST_SYNCPT_IMMEDIATE = 0x0,
+ NV_CLASS_HOST_SYNCPT_OP_DONE = 0x1,
+ NV_CLASS_HOST_SYNCPT_RD_DONE = 0x2,
+ NV_CLASS_HOST_SYNCPT_REG_WR_SAFE = 0x3,
+};
static inline u32 nvhost_class_host_wait_syncpt(
unsigned indx, unsigned threshold)
@@ -158,6 +165,12 @@ static inline u32 nvhost_class_host_incr_syncpt_base(
return (base_indx << 24) | offset;
}
+static inline u32 nvhost_class_host_incr_syncpt(
+ unsigned cond, unsigned indx)
+{
+ return (cond << 8) | indx;
+}
+
enum {
NV_HOST_MODULE_HOST1X = 0,
NV_HOST_MODULE_MPE = 1,
@@ -210,6 +223,12 @@ static inline u32 nvhost_opcode_imm(unsigned offset, unsigned value)
return (4 << 28) | (offset << 16) | value;
}
+static inline u32 nvhost_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
+{
+ return nvhost_opcode_imm(NV_CLASS_HOST_INCR_SYNCPT,
+ nvhost_class_host_incr_syncpt(cond, indx));
+}
+
static inline u32 nvhost_opcode_restart(unsigned address)
{
return (5 << 28) | (address >> 4);