Use the PM-WIP-OPP branch apis for generating the opp list for DSP. This allows for scaling accross 3430,3440,3450 and 3630 series. Caveat: does not handle dynamic addition of opp after the bridgedriver is inserted - this can be done once the framework for the same is made available Cc: Ameya Palande <ameya.palande@xxxxxxxxx> Cc: Deepak Chitriki <deepak.chitriki@xxxxxx> Cc: Felipe Contreras <felipe.contreras@xxxxxxxxx> Cc: Hiroshi Doyu <hiroshi.doyu@xxxxxxxxx> Cc: Omar Ramirez Luna <omar.ramirez@xxxxxx> Signed-off-by: Nishanth Menon <nm@xxxxxx> --- caveat: this does not use the ENUM implementation yet, this can be once it is merged to pm-wip-opp branch. arch/arm/mach-omap2/dspbridge.c | 99 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 98 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c index 26b860f..935afd7 100644 --- a/arch/arm/mach-omap2/dspbridge.c +++ b/arch/arm/mach-omap2/dspbridge.c @@ -15,6 +15,20 @@ #ifdef CONFIG_BRIDGE_DVFS #include <mach/omap-pm.h> +#include <plat/opp.h> +/* + * The DSP load balancer works on the following logic: + * Opp frequencies: + * 0 <---------> Freq 1 <------------> Freq 2 <---------> Freq 3 + * DSP Thresholds for the frequencies: + * 0M<-------X-> Freq 1 <-------M--X-> Freq 2 <----M--X-> Freq 3 + * Where, M is the minimal threshold and X is maximum threshold + * + * if from Freq x to Freq y; where x > y, transition happens on M + * if from Freq x to Freq y; where x < y, transition happens on X + */ +#define BRIDGE_THRESH_HIGH_PERCENT 95 +#define BRIDGE_THRESH_LOW_PERCENT 88 #endif #include <dspbridge/host_os.h> @@ -42,7 +56,90 @@ static struct dspbridge_platform_data dspbridge_pdata __initdata = { static int get_opp_table(struct dspbridge_platform_data *pdata) { #ifdef CONFIG_BRIDGE_DVFS - /* Do nothing now - fill based on PM implementation */ + int mpu_freqs; + int dsp_freqs; + int i; + struct omap_opp *opp; + unsigned long freq, old_rate; + + mpu_freqs = opp_get_opp_count(mpu_opps); + dsp_freqs = opp_get_opp_count(dsp_opps); + if (mpu_freqs < 0 || dsp_freqs < 0 || mpu_freqs != dsp_freqs) { + pr_err("mpu and dsp frequencies are inconsistent! " + "mpu_freqs=%d dsp_freqs=%d\n", mpu_freqs, dsp_freqs); + return -EINVAL; + } + /* allocate memory if we have opps initialized */ + pdata->mpu_speeds = kzalloc(sizeof(u32) * mpu_freqs, + GFP_KERNEL); + if (!pdata->mpu_speeds) { + pr_err("unable to allocate memory for the mpu" + "frequencies\n"); + return -ENOMEM; + } + opp = mpu_opps; + i = 0; + freq = 0; + while (!IS_ERR(opp = opp_find_freq_ceil(opp, &freq))) { + pdata->mpu_speeds[i] = freq; + freq++; + i++; + } + pdata->mpu_num_speeds = mpu_freqs; + pdata->mpu_min_speed = pdata->mpu_speeds[0]; + pdata->mpu_max_speed = pdata->mpu_speeds[mpu_freqs - 1]; + /* need an initial terminator */ + pdata->dsp_freq_table = kzalloc( + sizeof(struct dsp_shm_freq_table) * + (dsp_freqs + 1), GFP_KERNEL); + if (!pdata->dsp_freq_table) { + pr_err("unable to allocate memory for the dsp" + "frequencies\n"); + return -ENOMEM; + } + + opp = dsp_opps; + i = 1; + freq = 0; + old_rate = 0; + /* + * the freq table is in terms of khz.. so we need to + * divide by 1000 + */ + while (!IS_ERR(opp = opp_find_freq_ceil(opp, &freq))) { + /* dsp frequencies are in khz */ + u32 rate = freq / 1000; + /* + * On certain 34xx silicons, certain OPPs are duplicated + * for DSP - handle those by copying previous opp value + */ + if (rate == old_rate) { + memcpy(&pdata->dsp_freq_table[i], + &pdata->dsp_freq_table[i-1], + sizeof(struct dsp_shm_freq_table)); + } else { + pdata->dsp_freq_table[i].dsp_freq = rate; + pdata->dsp_freq_table[i].u_volts = + opp_get_voltage(opp); + /* + * min threshold: + * NOTE: index 1 needs a min of 0! else no + * scaling happens at DSP! + */ + pdata->dsp_freq_table[i].thresh_min_freq = + ((old_rate * BRIDGE_THRESH_LOW_PERCENT) / 100); + + /* max threshold */ + pdata->dsp_freq_table[i].thresh_max_freq = + ((rate * BRIDGE_THRESH_HIGH_PERCENT) / 100); + } + old_rate = rate; + freq++; + i++; + } + /* the last entry should map with maximum rate */ + pdata->dsp_freq_table[i - 1].thresh_max_freq = old_rate; + pdata->dsp_num_speeds = dsp_freqs; #endif return 0; } -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html