static int _set_opp()

in core.c [995:1078]


static int _set_opp(struct device *dev, struct opp_table *opp_table,
		    struct dev_pm_opp *opp, unsigned long freq)
{
	struct dev_pm_opp *old_opp;
	int scaling_down, ret;

	if (unlikely(!opp))
		return _disable_opp_table(dev, opp_table);

	/* Find the currently set OPP if we don't know already */
	if (unlikely(!opp_table->current_opp))
		_find_current_opp(dev, opp_table);

	old_opp = opp_table->current_opp;

	/* Return early if nothing to do */
	if (old_opp == opp && opp_table->current_rate == freq &&
	    opp_table->enabled) {
		dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__);
		return 0;
	}

	dev_dbg(dev, "%s: switching OPP: Freq %lu -> %lu Hz, Level %u -> %u, Bw %u -> %u\n",
		__func__, opp_table->current_rate, freq, old_opp->level,
		opp->level, old_opp->bandwidth ? old_opp->bandwidth[0].peak : 0,
		opp->bandwidth ? opp->bandwidth[0].peak : 0);

	scaling_down = _opp_compare_key(old_opp, opp);
	if (scaling_down == -1)
		scaling_down = 0;

	/* Scaling up? Configure required OPPs before frequency */
	if (!scaling_down) {
		ret = _set_required_opps(dev, opp_table, opp, true);
		if (ret) {
			dev_err(dev, "Failed to set required opps: %d\n", ret);
			return ret;
		}

		ret = _set_opp_bw(opp_table, opp, dev);
		if (ret) {
			dev_err(dev, "Failed to set bw: %d\n", ret);
			return ret;
		}
	}

	if (opp_table->set_opp) {
		ret = _set_opp_custom(opp_table, dev, opp, freq);
	} else if (opp_table->regulators) {
		ret = _generic_set_opp_regulator(opp_table, dev, opp, freq,
						 scaling_down);
	} else {
		/* Only frequency scaling */
		ret = _generic_set_opp_clk_only(dev, opp_table->clk, freq);
	}

	if (ret)
		return ret;

	/* Scaling down? Configure required OPPs after frequency */
	if (scaling_down) {
		ret = _set_opp_bw(opp_table, opp, dev);
		if (ret) {
			dev_err(dev, "Failed to set bw: %d\n", ret);
			return ret;
		}

		ret = _set_required_opps(dev, opp_table, opp, false);
		if (ret) {
			dev_err(dev, "Failed to set required opps: %d\n", ret);
			return ret;
		}
	}

	opp_table->enabled = true;
	dev_pm_opp_put(old_opp);

	/* Make sure current_opp doesn't get freed */
	dev_pm_opp_get(opp);
	opp_table->current_opp = opp;
	opp_table->current_rate = freq;

	return ret;
}