Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eef17de5 authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Set DDR qos level based on GPU bus IB vote



For the highest IB vote, enable DDR qos level which increases
performance by disabling certain DDR low power states.

Change-Id: Iaabc99f724ca6f2b8de2a95da00f73608209e97f
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent 5bf38f99
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -129,6 +129,36 @@ static void a6xx_gmu_wrapper_init(struct adreno_device *adreno_dev)
		dev_warn(device->dev, "gmu_wrapper ioremap failed\n");
}

static int match_name(struct device *dev, void *data)
{
	struct device *parent = data;

	return (!strcmp(dev_name(dev), dev_name(parent)));
}

static void find_ddr_qos_device(struct adreno_device *adreno_dev)
{
	struct device *devfreq_dev, *ddr_qos_dev;
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);

	if (device->pwrctrl.ddr_qos_devfreq)
		return;

	ddr_qos_dev = bus_find_device_by_name(&platform_bus_type, NULL,
			"soc:qcom,kgsl-ddr-qos");

	if (!ddr_qos_dev)
		return;

	/* Devfreq device has the same name as its parent device */
	devfreq_dev = device_find_child(ddr_qos_dev, ddr_qos_dev, match_name);
	if (!devfreq_dev)
		return;

	device->pwrctrl.ddr_qos_devfreq = container_of(devfreq_dev,
					struct devfreq, dev);
}

int a6xx_init(struct adreno_device *adreno_dev)
{
	const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev);
@@ -157,6 +187,8 @@ int a6xx_init(struct adreno_device *adreno_dev)
			return PTR_ERR(adreno_dev->pwrup_reglist);
	}

	find_ddr_qos_device(adreno_dev);

	return a6xx_get_cp_init_cmds(adreno_dev);
}

+42 −2
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@

#include <linux/interconnect.h>
#include <linux/of.h>
#include <linux/devfreq.h>

#include "../../devfreq/governor.h"
#include "kgsl_bus.h"
#include "kgsl_device.h"
#include "kgsl_trace.h"
@@ -30,6 +32,36 @@ static u32 _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
	return (pwr->bus_percent_ab * pwr->bus_max) / 100;
}

static void set_ddr_qos(struct kgsl_device *device, int buslevel)
{
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct devfreq *dev = pwr->ddr_qos_devfreq;
	static unsigned long cur_min_freq;
	unsigned long new_min_freq = DEVFREQ_MIN_FREQ;
	int ret;

	if (!dev)
		return;

	/*
	 * Instead of creating a new dummy governor, we are using powersave
	 * governor for this devfreq device. Therefore, modify the minimum
	 * frequency to point to the desired QOS level.
	 */
	if (buslevel == pwr->pwrlevels[0].bus_max)
		new_min_freq = DEVFREQ_MAX_FREQ;

	if (new_min_freq == cur_min_freq)
		return;

	mutex_lock(&dev->lock);
	dev->min_freq = new_min_freq;
	ret = update_devfreq(dev);
	mutex_unlock(&dev->lock);

	if (!ret)
		cur_min_freq = new_min_freq;
}

int kgsl_bus_update(struct kgsl_device *device,
			 enum kgsl_bus_vote vote_state)
@@ -37,7 +69,7 @@ int kgsl_bus_update(struct kgsl_device *device,
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	/* FIXME: this might be wrong? */
	int cur = pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
	int buslevel = 0;
	int ret, buslevel = 0;
	u32 ab;

	/* the bus should be ON to update the active frequency */
@@ -68,7 +100,13 @@ int kgsl_bus_update(struct kgsl_device *device,
	/* buslevel is the IB vote, update the AB */
	ab = _ab_buslevel_update(pwr, pwr->ddr_table[buslevel]);

	return device->ftbl->gpu_bus_set(device, buslevel, ab);
	ret = device->ftbl->gpu_bus_set(device, buslevel, ab);
	if (ret)
		return ret;

	set_ddr_qos(device, buslevel);

	return 0;
}

static void validate_pwrlevels(struct kgsl_device *device, u32 *ibs,
@@ -175,4 +213,6 @@ void kgsl_bus_close(struct kgsl_device *device)
	kfree(device->pwrctrl.ddr_table);
	device->pwrctrl.ddr_table = NULL;
	icc_put(device->pwrctrl.icc_path);
	if (device->pwrctrl.ddr_qos_devfreq)
		put_device(&device->pwrctrl.ddr_qos_devfreq->dev);
}
+2 −0
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ struct kgsl_pwrctrl {
	struct timer_list minbw_timer;
	/** @minbw_timeout - Timeout for entering minimum bandwidth state */
	u32 minbw_timeout;
	/** @ddr_qos_devfreq: Devfreq device for setting DDR qos policy */
	struct devfreq *ddr_qos_devfreq;
};

int kgsl_pwrctrl_init(struct kgsl_device *device);