static ssize_t mali_gpu_fullspeed_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
	/*
	 * Check APE OPP status, on OPP50, clock is half.
	 */
	return sprintf(buf, "%s\n", (prcmu_get_ape_opp() == APE_100_OPP) ? "1" : "0");
}
Пример #2
0
static int ape_opp_read(struct seq_file *s, void *p)
{
	int opp;

	opp = prcmu_get_ape_opp();
	return seq_printf(s, "%s (%d)\n",
			(opp == APE_100_OPP) ? "100%" :
			(opp == APE_50_OPP) ? "50%" :
			"unknown", opp);
}
static ssize_t mali_gpu_vape_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
	u8 value;
	bool opp50;

	/*
	 * cocafe:
	 * Display Vape Seletion 1 only, 
	 * In APE 50OPP, Vape uses SEL2. 
	 * And the clocks are half.
	 */
	opp50 = (prcmu_get_ape_opp() != APE_100_OPP);
	prcmu_abb_read(AB8500_REGU_CTRL2, 
			opp50 ? AB8500_VAPE_SEL2 : AB8500_VAPE_SEL1,
			&value, 
			1);

	return sprintf(buf, "%u uV - 0x%x (OPP:%d)\n", vape_voltage(value), value, opp50 ? 50 : 100);
}
/* boost switching logic:
 * - boost_working means that freq is already set to high value
 * - boost_scheduled means that job is scheduled to turn boost either on or off
 * - boost_required is a flag for scheduled job telling it what to do with boost
 *
 * if we are in APE_50_OPP, skip boost
 * if we are in APE_100_OPP and util>boost_up_thresh, shedule boost if its not on or - if its on and scheduled to be turned off -  cancel that schedule
 * if boost is scheduled and not yet working and util < util_high_to_low, then cancel scheduled boost
 * if boost is on and util < boost_down_thresh, schedule boost to be turned off
 */
void mali_utilization_function(struct work_struct *ptr)
{
	/*By default, platform start with 50% APE OPP and 25% DDR OPP*/
	static u32 has_requested_low = 1;

	MALI_DEBUG_PRINT(5, ("MALI GPU utilization: %u\n", mali_last_utilization));

	mutex_lock(&mali_boost_lock);
	if ((!boost_required && !boost_working && !boost_scheduled) || !boost_enable) {
		// consider power saving mode (APE_50_OPP) only if we're not on boost
		int ape_opp = prcmu_get_ape_opp();
		/*
		if APE_OPP==100 because someone else wanted this (touchboost in particular) and not mali,
		we should check if utilization is high enough so we can also request high ape to maintain
		satisfying UI performance.
		*/
		int up_threshold = (ape_opp == APE_50_OPP && has_requested_low ? mali_utilization_low_to_high : (mali_utilization_high_to_low));

		if (mali_last_utilization >= up_threshold) {
			if (has_requested_low) {
				MALI_DEBUG_PRINT(5, ("MALI GPU utilization: %u SIGNAL_HIGH\n", mali_last_utilization));
				/*Request 100% APE_OPP.*/
				prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "mali", PRCMU_QOS_MAX_VALUE);
				/*
				* Since the utilization values will be reported higher
				* if DDR_OPP is lowered, we also request 100% DDR_OPP.
				*/
				prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "mali", PRCMU_QOS_MAX_VALUE);
				has_requested_low = 0;
				mutex_unlock(&mali_boost_lock);
				return;		//After we switch to APE_100_OPP we want to measure utilization once again before entering boost logic
			}
		} else {
			if (mali_last_utilization < mali_utilization_high_to_low) {
				if (!has_requested_low) {
					/*Remove APE_OPP and DDR_OPP requests*/
					prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "mali", PRCMU_QOS_DEFAULT_VALUE);
					prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "mali", PRCMU_QOS_DEFAULT_VALUE);
					MALI_DEBUG_PRINT(5, ("MALI GPU utilization: %u SIGNAL_LOW\n", mali_last_utilization));
					has_requested_low = 1;
				}
			}
		}
	}

	if (!has_requested_low && boost_enable) {
		// consider boost only if we are in APE_100_OPP mode
		if (!boost_required && mali_last_utilization > boost_upthreshold) {
			boost_required = true;
			if (!boost_scheduled) {
				//schedule job to turn boost on
				boost_scheduled = true;
				schedule_delayed_work(&mali_boost_delayedwork, msecs_to_jiffies(boost_delay));
			} else {
				//cancel job meant to turn boost off
				boost_scheduled = false;
				cancel_delayed_work(&mali_boost_delayedwork);
			}
		} else if (boost_required && !boost_working && mali_last_utilization < boost_downthreshold) {
			boost_required = false;
			if (boost_scheduled) {
				//if it's not working yet, but is scheduled to be turned on, than cancel scheduled job
				cancel_delayed_work(&mali_boost_delayedwork);
				boost_scheduled = false;
			}
		} else if (boost_working && mali_last_utilization < boost_downthreshold) {
			boost_required = false;
			if (!boost_scheduled) {
				// if boost is on and isn't yet scheduled to be turned off then schedule it
				boost_scheduled = true;
				schedule_delayed_work(&mali_boost_delayedwork, msecs_to_jiffies(boost_delay));
			}
		}
	}
	mutex_unlock(&mali_boost_lock);

}