diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-05-19 09:35:16 +0300 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:47:06 -0800 |
commit | 6f4a299341a041e1806b9f5f8c7c0b7f1cf79b05 (patch) | |
tree | a38c40f7e9302cff74495b6037e7f69af48cf3c6 /drivers/video | |
parent | 631c72bca98bfcad320da08328629339f8b75d1c (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.c | 128 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_hardware.h | 21 |
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); |