static void nvhost_scale_notify(struct platform_device *pdev, bool busy) { struct nvhost_device_data *pdata = platform_get_drvdata(pdev); struct nvhost_device_profile *profile = pdata->power_profile; struct devfreq *devfreq = pdata->power_manager; /* Is the device profile initialised? */ if (!profile) return; /* inform edp about new constraint */ if (pdata->gpu_edp_device) { u32 avg = 0; actmon_op().read_avg_norm(profile->actmon, &avg); BUG(); /* the next line passes a bogus frequency */ tegra_edp_notify_gpu_load(avg, 0); } /* If defreq is disabled, set the freq to max or min */ if (!devfreq) { unsigned long freq = busy ? UINT_MAX : 0; nvhost_scale_target(&pdev->dev, &freq, 0); return; } mutex_lock(&devfreq->lock); if (!profile->actmon) update_load_estimate(profile, busy); profile->dev_stat.busy = busy; update_devfreq(devfreq); mutex_unlock(&devfreq->lock); }
void nvhost_scale3d_callback(struct nvhost_device_profile *profile, unsigned long freq) { struct nvhost_gr3d_params *gr3d_params = profile->private_data; struct nvhost_device_data *pdata = platform_get_drvdata(profile->pdev); struct nvhost_emc_params *emc_params = &gr3d_params->emc_params; long hz; long after; /* Set EMC clockrate */ after = (long) clk_get_rate(clk(profile, gr3d_params->clk_3d)); hz = nvhost_scale3d_get_emc_rate(emc_params, after); nvhost_module_set_devfreq_rate(profile->pdev, gr3d_params->clk_3d_emc, hz); if (pdata->gpu_edp_device) { u32 avg = 0; actmon_op().read_avg_norm(profile->actmon, &avg); tegra_edp_notify_gpu_load(avg); } }
static int nvhost_scale3d_get_dev_status(struct device *d, struct devfreq_dev_status *stat) { struct platform_device *dev = to_platform_device(d); struct nvhost_master *host_master = nvhost_get_host(dev); struct nvhost_devfreq_ext_stat *ext_stat = power_profile.dev_stat->private_data; u32 avg = 0; ktime_t t; /* Make sure there are correct values for the current frequency */ power_profile.dev_stat->current_frequency = clk_get_rate(power_profile.clk_3d); /* Copy the contents of the current device status */ ext_stat->busy = power_profile.last_event_type; *stat = *power_profile.dev_stat; /* Read and scale AVG. AVG is scaled to interval 0-dt, where dt * is the last time it was read. (this is really clumsy, but the * governor uses internally time differences) */ actmon_op().read_avg_norm(host_master, &avg); t = ktime_get(); stat->total_time = ktime_us_delta(t, power_profile.last_request_time); stat->busy_time = (avg * stat->total_time) / 1000; power_profile.last_request_time = t; /* Finally, clear out the local values */ power_profile.dev_stat->total_time = 0; power_profile.dev_stat->busy_time = 0; power_profile.last_event_type = DEVICE_UNKNOWN; tegra_edp_notify_gpu_load(avg); return 0; }