static int exynos5_devfreq_isp_target(struct device *dev, unsigned long *target_freq, u32 flags) { int ret = 0; struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct devfreq_data_isp *data = platform_get_drvdata(pdev); struct devfreq *devfreq_isp = data->devfreq; struct opp *target_opp; int target_idx, old_idx; unsigned long target_volt; unsigned long old_freq; mutex_lock(&data->lock); rcu_read_lock(); target_opp = devfreq_recommended_opp(dev, target_freq, flags); if (IS_ERR(target_opp)) { rcu_read_unlock(); mutex_unlock(&data->lock); dev_err(dev, "DEVFREQ(ISP) : Invalid OPP to find\n"); ret = PTR_ERR(target_opp); goto out; } *target_freq = opp_get_freq(target_opp); target_volt = opp_get_voltage(target_opp); #ifdef CONFIG_EXYNOS_THERMAL target_volt = get_limit_voltage(target_volt, data->volt_offset); #endif rcu_read_unlock(); target_idx = exynos5_devfreq_get_idx(devfreq_isp_opp_list, data->max_state, *target_freq); old_idx = exynos5_devfreq_get_idx(devfreq_isp_opp_list, data->max_state, devfreq_isp->previous_freq); old_freq = devfreq_isp->previous_freq; if (target_idx < 0 || old_idx < 0) { ret = -EINVAL; goto out; } if (old_freq == *target_freq) goto out; pr_debug("ISP %lu ================> %lu\n", old_freq, *target_freq); if (old_freq < *target_freq) { if (data->isp_set_volt) data->isp_set_volt(data, target_volt, target_volt + VOLT_STEP, false); if (data->isp_set_freq) data->isp_set_freq(data, target_idx, old_idx); } else { if (data->isp_set_freq) data->isp_set_freq(data, target_idx, old_idx); if (data->isp_set_volt) data->isp_set_volt(data, target_volt, target_volt + VOLT_STEP, true); } out: mutex_unlock(&data->lock); return ret; }
static int exynos7_devfreq_disp_target(struct device *dev, unsigned long *target_freq, u32 flags) { int ret = 0; struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct devfreq_data_disp *data = platform_get_drvdata(pdev); struct devfreq *devfreq_disp = data->devfreq; struct opp *target_opp; int target_idx, old_idx; unsigned long target_volt; unsigned long old_freq; mutex_lock(&data->lock); rcu_read_lock(); target_opp = devfreq_recommended_opp(dev, target_freq, flags); if (IS_ERR(target_opp)) { rcu_read_unlock(); mutex_unlock(&data->lock); dev_err(dev, "DEVFREQ(DISP) : Invalid OPP to find\n"); return PTR_ERR(target_opp); } *target_freq = opp_get_freq(target_opp); target_volt = opp_get_voltage(target_opp); rcu_read_unlock(); target_idx = devfreq_get_opp_idx(devfreq_disp_opp_list, data->max_state, *target_freq); old_idx = devfreq_get_opp_idx(devfreq_disp_opp_list, data->max_state, devfreq_disp->previous_freq); old_freq = devfreq_disp->previous_freq; if (target_idx < 0 || old_idx < 0) { ret = -EINVAL; goto out; } if (old_freq == *target_freq) goto out; #ifdef CONFIG_EXYNOS_THERMAL target_volt = get_limit_voltage(target_volt, data->volt_offset, 0); #endif pr_debug("DISP LV_%d(%lu) ================> LV_%d(%lu, volt: %lu)\n", old_idx, old_freq, target_idx, *target_freq, target_volt); exynos_ss_freq(ESS_FLAG_DISP, old_freq, ESS_FLAG_IN); if (old_freq < *target_freq) { if (data->disp_set_volt) data->disp_set_volt(data, target_volt, REGULATOR_MAX_MICROVOLT); if (data->disp_set_freq) data->disp_set_freq(data, target_idx, old_idx); } else { if (data->disp_set_freq) data->disp_set_freq(data, target_idx, old_idx); if (data->disp_set_volt) data->disp_set_volt(data, target_volt, REGULATOR_MAX_MICROVOLT); } exynos_ss_freq(ESS_FLAG_DISP, *target_freq, ESS_FLAG_OUT); data->cur_freq = *target_freq; out: mutex_unlock(&data->lock); return ret; }
static int exynos5_devfreq_isp_probe(struct platform_device *pdev) { int ret = 0; struct devfreq_data_isp *data; struct exynos_devfreq_platdata *plat_data; struct opp *target_opp; unsigned long freq; unsigned long volt; data = kzalloc(sizeof(struct devfreq_data_isp), GFP_KERNEL); if (data == NULL) { pr_err("DEVFREQ(ISP) : Failed to allocate private data\n"); ret = -ENOMEM; goto err_data; } exynos5433_devfreq_isp_init(data); exynos5_devfreq_isp_profile.max_state = data->max_state; exynos5_devfreq_isp_profile.freq_table = kzalloc(sizeof(int) * data->max_state, GFP_KERNEL); if (exynos5_devfreq_isp_profile.freq_table == NULL) { pr_err("DEVFREQ(ISP) : Failed to allocate freq table\n"); ret = -ENOMEM; goto err_freqtable; } ret = exynos5_init_isp_table(&pdev->dev, data); if (ret) goto err_inittable; platform_set_drvdata(pdev, data); mutex_init(&data->lock); data->initial_freq = exynos5_devfreq_isp_profile.initial_freq; data->volt_offset = 0; isp_dev = data->dev = &pdev->dev; data->vdd_isp = regulator_get(NULL, "vdd_disp_cam0"); if (IS_ERR_OR_NULL(data->vdd_isp)) { pr_err("DEVFREQ(ISP) : Failed to get regulator\n"); goto err_inittable; } freq = DEVFREQ_INITIAL_FREQ; rcu_read_lock(); target_opp = devfreq_recommended_opp(data->dev, &freq, 0); if (IS_ERR(target_opp)) { rcu_read_unlock(); dev_err(data->dev, "DEVFREQ(ISP) : Invalid OPP to set voltage"); ret = PTR_ERR(target_opp); goto err_opp; } volt = opp_get_voltage(target_opp); #ifdef CONFIG_EXYNOS_THERMAL volt = get_limit_voltage(volt, data->volt_offset); #endif rcu_read_unlock(); if (data->isp_set_volt) data->isp_set_volt(data, volt, volt + VOLT_STEP, false); data->devfreq = devfreq_add_device(data->dev, &exynos5_devfreq_isp_profile, "simple_ondemand", &exynos5_devfreq_isp_governor_data); plat_data = data->dev->platform_data; data->devfreq->min_freq = plat_data->default_qos; data->devfreq->max_freq = exynos5_devfreq_isp_governor_data.cal_qos_max; register_reboot_notifier(&exynos5_isp_reboot_notifier); #ifdef CONFIG_EXYNOS_THERMAL data->tmu_notifier.notifier_call = exynos5_devfreq_isp_tmu_notifier; exynos_tmu_add_notifier(&data->tmu_notifier); #endif data->use_dvfs = true; return ret; err_opp: regulator_put(data->vdd_isp); err_inittable: devfreq_remove_device(data->devfreq); kfree(exynos5_devfreq_isp_profile.freq_table); err_freqtable: kfree(data); err_data: return ret; }
static int exynos5_devfreq_int_target(struct device *dev, unsigned long *target_freq, u32 flags) { int ret = 0; struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct devfreq_data_int *data = platform_get_drvdata(pdev); struct devfreq *devfreq_int = data->devfreq; struct opp *target_opp; int target_idx, old_idx; unsigned long target_volt; unsigned long old_freq; mutex_lock(&data->lock); rcu_read_lock(); target_opp = devfreq_recommended_opp(dev, target_freq, flags); if (IS_ERR(target_opp)) { rcu_read_unlock(); mutex_unlock(&data->lock); dev_err(dev, "DEVFREQ(INT) : Invalid OPP to find\n"); ret = PTR_ERR(target_opp); goto out; } *target_freq = opp_get_freq(target_opp); target_volt = opp_get_voltage(target_opp); #ifdef CONFIG_EXYNOS_THERMAL target_volt = get_limit_voltage(target_volt, data->volt_offset); #endif /* just want to save voltage before apply constraint with isp */ data->target_volt = target_volt; if (target_volt < data->volt_constraint_isp) target_volt = data->volt_constraint_isp; rcu_read_unlock(); target_idx = exynos5_devfreq_get_idx(devfreq_int_opp_list, data->max_state, *target_freq); old_idx = exynos5_devfreq_get_idx(devfreq_int_opp_list, data->max_state, devfreq_int->previous_freq); old_freq = devfreq_int->previous_freq; if (target_idx < 0 || old_idx < 0) { ret = -EINVAL; goto out; } if (old_freq == *target_freq) goto out; pr_debug("INT %lu ===================> %lu\n", old_freq, *target_freq); if (old_freq < *target_freq) { if (data->int_set_volt) data->int_set_volt(data, target_volt, target_volt + VOLT_STEP); set_match_abb(ID_INT, data->int_asv_abb_table[target_idx]); if (data->int_set_freq) data->int_set_freq(data, target_idx, old_idx); } else { if (data->int_set_freq) data->int_set_freq(data, target_idx, old_idx); set_match_abb(ID_INT, data->int_asv_abb_table[target_idx]); if (data->int_set_volt) data->int_set_volt(data, target_volt, target_volt + VOLT_STEP); } out: mutex_unlock(&data->lock); return ret; }