summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/latency_allowance.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/latency_allowance.c b/arch/arm/mach-tegra/latency_allowance.c
index e3f0199d91e8..9b35a07eddc4 100644
--- a/arch/arm/mach-tegra/latency_allowance.c
+++ b/arch/arm/mach-tegra/latency_allowance.c
@@ -23,11 +23,13 @@
#include <linux/spinlock_types.h>
#include <linux/spinlock.h>
#include <linux/stringify.h>
+#include <linux/clk.h>
#include <asm/bug.h>
#include <asm/io.h>
#include <asm/string.h>
#include <mach/iomap.h>
#include <mach/io.h>
+#include <mach/clk.h>
#include <mach/latency_allowance.h>
#include "la_priv_common.h"
#include "tegra3_la_priv.h"
@@ -44,6 +46,105 @@
/* Bug 995270 */
#define HACK_LA_FIFO 1
+/* Hack program PTSA */
+#if defined (CONFIG_ARCH_TEGRA_11x_SOC)
+#define HACK_PROGRAM_PTSA 1
+#else
+#define HACK_PROGRAM_PTSA 0
+#endif
+
+#if HACK_PROGRAM_PTSA
+#define MC_DIS_PTSA_RATE_0 0x41c
+#define MC_DIS_PTSA_MIN_0 0x420
+#define MC_DIS_PTSA_MAX_0 0x424
+#define MC_DISB_PTSA_RATE_0 0x428
+#define MC_DISB_PTSA_MIN_0 0x42c
+#define MC_DISB_PTSA_MAX_0 0x430
+#define MC_VE_PTSA_RATE_0 0x434
+#define MC_VE_PTSA_MIN_0 0x438
+#define MC_VE_PTSA_MAX_0 0x43c
+#define MC_RING2_PTSA_RATE_0 0x440
+#define MC_RING2_PTSA_MIN_0 0x444
+#define MC_RING2_PTSA_MAX_0 0x448
+#define MC_MLL_MPCORER_PTSA_RATE_0 0x44c
+#define MC_MLL_MPCORER_PTSA_MIN_0 0x450
+#define MC_MLL_MPCORER_PTSA_MAX_0 0x454
+#define MC_SMMU_SMMU_PTSA_RATE_0 0x458
+#define MC_SMMU_SMMU_PTSA_MIN_0 0x45c
+#define MC_SMMU_SMMU_PTSA_MAX_0 0x460
+#define MC_R0_DIS_PTSA_RATE_0 0x464
+#define MC_R0_DIS_PTSA_MIN_0 0x468
+#define MC_R0_DIS_PTSA_MAX_0 0x46c
+#define MC_R0_DISB_PTSA_RATE_0 0x470
+#define MC_R0_DISB_PTSA_MIN_0 0x474
+#define MC_R0_DISB_PTSA_MAX_0 0x478
+#define MC_RING1_PTSA_RATE_0 0x47c
+#define MC_RING1_PTSA_MIN_0 0x480
+#define MC_RING1_PTSA_MAX_0 0x484
+
+#define MC_DIS_EXTRA_SNAP_LEVELS_0 0x2ac
+#define MC_HEG_EXTRA_SNAP_LEVELS_0 0x2b0
+#define MC_EMEM_ARB_MISC0_0 0x0d8
+#define MC_PTSA_GRANT_DECREMENT_0 0x960
+
+#define BASE_EMC_FREQ_MHZ 500
+#define MAX_CAMERA_BW_MHZ 528
+
+static unsigned int get_ptsa_rate(unsigned int bw)
+{
+ /* 16 = 2 channels * 2 ddr * 4 bytes */
+ unsigned int base_memory_bw = 16 * BASE_EMC_FREQ_MHZ;
+ unsigned int rate = 281 * bw / base_memory_bw;
+ if (rate > 255)
+ rate = 255;
+ return rate;
+}
+
+static unsigned int disp_bw_array[10];
+
+static void update_display_ptsa_rate(void)
+{
+ unsigned int num_active = (disp_bw_array[0] != 0) +
+ (disp_bw_array[1] != 0) +
+ (disp_bw_array[2] != 0);
+ unsigned int num_activeb = (disp_bw_array[5] != 0) +
+ (disp_bw_array[6] != 0) +
+ (disp_bw_array[7] != 0);
+ unsigned int max_bw = disp_bw_array[0];
+ unsigned int max_bwb = disp_bw_array[5];
+ unsigned int rate_dis;
+ unsigned int rate_disb;
+ unsigned long ring1_rate;
+
+ max_bw = max(disp_bw_array[0], disp_bw_array[1]);
+ max_bw = max(max_bw, disp_bw_array[2]);
+
+ max_bwb = max(disp_bw_array[5], disp_bw_array[6]);
+ max_bwb = max(max_bwb, disp_bw_array[7]);
+
+ rate_dis = get_ptsa_rate(num_active * max_bw);
+ rate_disb = get_ptsa_rate(num_activeb * max_bwb);
+
+ writel(rate_dis, MC_RA(DIS_PTSA_RATE_0));
+ writel(rate_disb, MC_RA(DISB_PTSA_RATE_0));
+
+
+ ring1_rate = readl(MC_RA(DIS_PTSA_RATE_0)) +
+ readl(MC_RA(DISB_PTSA_RATE_0)) +
+ readl(MC_RA(VE_PTSA_RATE_0)) +
+ readl(MC_RA(RING2_PTSA_RATE_0));
+ la_debug("max_bw=0x%x, max_bwb=0x%x, num_active=0x%x, num_activeb=0x%x,"
+ "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x ",
+ max_bw, max_bwb, num_active, num_activeb, disp_bw_array[0],disp_bw_array[1],
+ disp_bw_array[2],disp_bw_array[5],disp_bw_array[6],disp_bw_array[7]);
+ la_debug("dis=0x%x, disb=0x%x, ve=0x%x, rng2=0x%x, rng1=0x%lx",
+ readl(MC_RA(DIS_PTSA_RATE_0)), readl(MC_RA(DISB_PTSA_RATE_0)),
+ readl(MC_RA(VE_PTSA_RATE_0)), readl(MC_RA(RING2_PTSA_RATE_0)), ring1_rate);
+ writel(ring1_rate / 2, MC_RA(RING1_PTSA_RATE_0));
+}
+
+#endif
+
static struct dentry *latency_debug_dir;
static DEFINE_SPINLOCK(safety_lock);
static unsigned short id_to_index[ID(MAX_ID) + 1];
@@ -109,6 +210,12 @@ int tegra_set_latency_allowance(enum tegra_la_id id,
ci = &la_info_array[idx];
fifo_size_in_atoms = ci->fifo_size_in_atoms;
+#if HACK_PROGRAM_PTSA
+ if (id >= TEGRA_LA_DISPLAY_0A && id <= TEGRA_LA_DISPLAY_HCB) {
+ disp_bw_array[id - TEGRA_LA_DISPLAY_0A] = bandwidth_in_mbps;
+ update_display_ptsa_rate();
+ }
+#endif
#if HACK_LA_FIFO
/* pretend that our FIFO is only as deep as the lowest fullness
* we expect to see */
@@ -346,6 +453,11 @@ late_initcall(tegra_latency_allowance_debugfs_init);
static int __init tegra_latency_allowance_init(void)
{
unsigned int i;
+ struct clk *emc_clk __attribute__((unused));
+ unsigned long emc_freq __attribute__((unused));
+ unsigned long same_freq __attribute__((unused));
+ unsigned long grant_dec __attribute__((unused));
+ unsigned long ring1_rate __attribute__((unused));
la_scaling_enable_count = 0;
memset(&id_to_index[0], 0xFF, sizeof(id_to_index));
@@ -363,6 +475,63 @@ static int __init tegra_latency_allowance_init(void)
tegra_set_latency_allowance(TEGRA_LA_G2DR, 20);
tegra_set_latency_allowance(TEGRA_LA_G2DW, 20);
#endif
+
+#if HACK_PROGRAM_PTSA
+ emc_clk = clk_get(NULL, "emc");
+ la_debug("**** emc clk_rate=%luMHz", clk_get_rate(emc_clk)/1000000);
+
+ emc_freq = clk_get_rate(emc_clk);
+ emc_freq /= 1000000;
+ /* Compute initial value for grant dec */
+ same_freq = readl(MC_RA(EMEM_ARB_MISC0_0));
+ same_freq = same_freq >> 27 & 1;
+ grant_dec = 256 * (same_freq ? 2 : 1) * emc_freq;
+ if (grant_dec > 511)
+ grant_dec = 511;
+ writel(grant_dec, MC_RA(PTSA_GRANT_DECREMENT_0));
+
+ writel(0x3d, MC_RA(DIS_PTSA_MIN_0));
+ writel(0x14, MC_RA(DIS_PTSA_MAX_0));
+
+ writel(0x3d, MC_RA(DISB_PTSA_MIN_0));
+ writel(0x14, MC_RA(DISB_PTSA_MAX_0));
+
+ writel(get_ptsa_rate(MAX_CAMERA_BW_MHZ), MC_RA(VE_PTSA_RATE_0));
+ writel(0x3d, MC_RA(VE_PTSA_MIN_0));
+ writel(0x14, MC_RA(VE_PTSA_MAX_0));
+
+ writel(0x01, MC_RA(RING2_PTSA_RATE_0));
+ writel(0x3f, MC_RA(RING2_PTSA_MIN_0));
+ writel(0x05, MC_RA(RING2_PTSA_MAX_0));
+
+ writel(38 * emc_freq / BASE_EMC_FREQ_MHZ,
+ MC_RA(MLL_MPCORER_PTSA_RATE_0));
+ writel(0x3f, MC_RA(MLL_MPCORER_PTSA_MIN_0));
+ writel(0x05, MC_RA(MLL_MPCORER_PTSA_MAX_0));
+
+ writel(0x01, MC_RA(SMMU_SMMU_PTSA_RATE_0));
+ writel(0x01, MC_RA(SMMU_SMMU_PTSA_MIN_0));
+ writel(0x01, MC_RA(SMMU_SMMU_PTSA_MAX_0));
+
+ writel(0x00, MC_RA(R0_DIS_PTSA_RATE_0));
+ writel(0x3f, MC_RA(R0_DIS_PTSA_MIN_0));
+ writel(0x3f, MC_RA(R0_DIS_PTSA_MAX_0));
+
+ writel(0x00, MC_RA(R0_DISB_PTSA_RATE_0));
+ writel(0x3f, MC_RA(R0_DISB_PTSA_MIN_0));
+ writel(0x3f, MC_RA(R0_DISB_PTSA_MAX_0));
+
+ ring1_rate = readl(MC_RA(DIS_PTSA_RATE_0)) +
+ readl(MC_RA(DISB_PTSA_RATE_0)) +
+ readl(MC_RA(VE_PTSA_RATE_0)) +
+ readl(MC_RA(RING2_PTSA_RATE_0));
+ writel(ring1_rate / 2, MC_RA(RING1_PTSA_RATE_0));
+ writel(0x36, MC_RA(RING1_PTSA_MIN_0));
+ writel(0x1f, MC_RA(RING1_PTSA_MAX_0));
+
+ writel(0x00, MC_RA(DIS_EXTRA_SNAP_LEVELS_0));
+ writel(0x03, MC_RA(HEG_EXTRA_SNAP_LEVELS_0));
+#endif
return 0;
}