| .. | .. |
|---|
| 4 | 4 | * Author: Finley Xiao <finley.xiao@rock-chips.com> |
|---|
| 5 | 5 | */ |
|---|
| 6 | 6 | |
|---|
| 7 | | -#include <dt-bindings/soc/rockchip-system-status.h> |
|---|
| 8 | 7 | #include <linux/clk-provider.h> |
|---|
| 9 | 8 | #include <linux/cpu.h> |
|---|
| 10 | 9 | #include <linux/cpufreq.h> |
|---|
| .. | .. |
|---|
| 24 | 23 | #include <linux/regulator/driver.h> |
|---|
| 25 | 24 | #include <linux/regulator/machine.h> |
|---|
| 26 | 25 | #include <linux/reboot.h> |
|---|
| 26 | +#include <linux/rockchip/rockchip_sip.h> |
|---|
| 27 | 27 | #include <linux/slab.h> |
|---|
| 28 | 28 | #include <linux/suspend.h> |
|---|
| 29 | 29 | #include <linux/thermal.h> |
|---|
| .. | .. |
|---|
| 246 | 246 | return video_info; |
|---|
| 247 | 247 | } |
|---|
| 248 | 248 | |
|---|
| 249 | | -static struct video_info *rockchip_find_video_info(const char *buf) |
|---|
| 250 | | -{ |
|---|
| 251 | | - struct video_info *info, *video_info; |
|---|
| 252 | | - |
|---|
| 253 | | - video_info = rockchip_parse_video_info(buf); |
|---|
| 254 | | - |
|---|
| 255 | | - if (!video_info) |
|---|
| 256 | | - return NULL; |
|---|
| 257 | | - |
|---|
| 258 | | - mutex_lock(&video_info_mutex); |
|---|
| 259 | | - list_for_each_entry(info, &video_info_list, node) { |
|---|
| 260 | | - if (info->width == video_info->width && |
|---|
| 261 | | - info->height == video_info->height && |
|---|
| 262 | | - info->ishevc == video_info->ishevc && |
|---|
| 263 | | - info->videoFramerate == video_info->videoFramerate && |
|---|
| 264 | | - info->streamBitrate == video_info->streamBitrate) { |
|---|
| 265 | | - mutex_unlock(&video_info_mutex); |
|---|
| 266 | | - kfree(video_info); |
|---|
| 267 | | - return info; |
|---|
| 268 | | - } |
|---|
| 269 | | - } |
|---|
| 270 | | - |
|---|
| 271 | | - mutex_unlock(&video_info_mutex); |
|---|
| 272 | | - kfree(video_info); |
|---|
| 273 | | - |
|---|
| 274 | | - return NULL; |
|---|
| 275 | | -} |
|---|
| 276 | | - |
|---|
| 277 | 249 | static void rockchip_add_video_info(struct video_info *video_info) |
|---|
| 278 | 250 | { |
|---|
| 279 | 251 | if (video_info) { |
|---|
| .. | .. |
|---|
| 285 | 257 | |
|---|
| 286 | 258 | static void rockchip_del_video_info(struct video_info *video_info) |
|---|
| 287 | 259 | { |
|---|
| 288 | | - if (video_info) { |
|---|
| 289 | | - mutex_lock(&video_info_mutex); |
|---|
| 290 | | - list_del(&video_info->node); |
|---|
| 291 | | - mutex_unlock(&video_info_mutex); |
|---|
| 292 | | - kfree(video_info); |
|---|
| 260 | + struct video_info *info, *tmp; |
|---|
| 261 | + |
|---|
| 262 | + if (!video_info) |
|---|
| 263 | + return; |
|---|
| 264 | + |
|---|
| 265 | + mutex_lock(&video_info_mutex); |
|---|
| 266 | + list_for_each_entry_safe(info, tmp, &video_info_list, node) { |
|---|
| 267 | + if (info->width == video_info->width && |
|---|
| 268 | + info->height == video_info->height && |
|---|
| 269 | + info->ishevc == video_info->ishevc && |
|---|
| 270 | + info->videoFramerate == video_info->videoFramerate && |
|---|
| 271 | + info->streamBitrate == video_info->streamBitrate) { |
|---|
| 272 | + list_del(&info->node); |
|---|
| 273 | + kfree(info); |
|---|
| 274 | + break; |
|---|
| 275 | + } |
|---|
| 293 | 276 | } |
|---|
| 277 | + kfree(video_info); |
|---|
| 278 | + mutex_unlock(&video_info_mutex); |
|---|
| 294 | 279 | } |
|---|
| 295 | 280 | |
|---|
| 296 | 281 | static void rockchip_update_video_info(void) |
|---|
| .. | .. |
|---|
| 338 | 323 | switch (buf[0]) { |
|---|
| 339 | 324 | case '0': |
|---|
| 340 | 325 | /* clear video flag */ |
|---|
| 341 | | - video_info = rockchip_find_video_info(buf); |
|---|
| 326 | + video_info = rockchip_parse_video_info(buf); |
|---|
| 342 | 327 | if (video_info) { |
|---|
| 343 | 328 | rockchip_del_video_info(video_info); |
|---|
| 344 | 329 | rockchip_update_video_info(); |
|---|
| .. | .. |
|---|
| 920 | 905 | bool is_low) |
|---|
| 921 | 906 | { |
|---|
| 922 | 907 | struct monitor_dev_profile *devp = info->devp; |
|---|
| 908 | + struct arm_smccc_res res; |
|---|
| 923 | 909 | int ret = 0; |
|---|
| 924 | 910 | |
|---|
| 925 | 911 | dev_dbg(info->dev, "low_temp %d\n", is_low); |
|---|
| .. | .. |
|---|
| 934 | 920 | |
|---|
| 935 | 921 | if (devp->update_volt) |
|---|
| 936 | 922 | devp->update_volt(info); |
|---|
| 923 | + |
|---|
| 924 | + if (devp->opp_info && devp->opp_info->pvtpll_low_temp) { |
|---|
| 925 | + res = sip_smc_pvtpll_config(PVTPLL_LOW_TEMP, |
|---|
| 926 | + devp->opp_info->pvtpll_clk_id, |
|---|
| 927 | + is_low, 0, 0, 0, 0); |
|---|
| 928 | + if (res.a0) |
|---|
| 929 | + dev_err(info->dev, |
|---|
| 930 | + "%s: error cfg id=%u low temp %d (%d)\n", |
|---|
| 931 | + __func__, devp->opp_info->pvtpll_clk_id, |
|---|
| 932 | + is_low, (int)res.a0); |
|---|
| 933 | + } |
|---|
| 937 | 934 | } |
|---|
| 938 | 935 | |
|---|
| 939 | 936 | static void rockchip_high_temp_adjust(struct monitor_dev_info *info, |
|---|
| .. | .. |
|---|
| 1338 | 1335 | rockchip_set_intermediate_rate(dev, opp_info, info->clk, |
|---|
| 1339 | 1336 | old_rate, new_rate, |
|---|
| 1340 | 1337 | true, is_set_clk); |
|---|
| 1338 | + |
|---|
| 1339 | + if (old_volt > new_volt) { |
|---|
| 1340 | + ret = regulator_set_voltage(vdd_reg, new_volt, INT_MAX); |
|---|
| 1341 | + if (ret) { |
|---|
| 1342 | + dev_err(dev, "%s: failed to set volt: %lu\n", |
|---|
| 1343 | + __func__, new_volt); |
|---|
| 1344 | + goto restore_voltage; |
|---|
| 1345 | + } |
|---|
| 1346 | + } |
|---|
| 1341 | 1347 | if (info->regulator_count > 1) { |
|---|
| 1342 | 1348 | ret = regulator_set_voltage(mem_reg, new_mem_volt, |
|---|
| 1343 | 1349 | INT_MAX); |
|---|
| .. | .. |
|---|
| 1347 | 1353 | goto restore_voltage; |
|---|
| 1348 | 1354 | } |
|---|
| 1349 | 1355 | } |
|---|
| 1350 | | - ret = regulator_set_voltage(vdd_reg, new_volt, INT_MAX); |
|---|
| 1351 | | - if (ret) { |
|---|
| 1352 | | - dev_err(dev, "%s: failed to set volt: %lu\n", |
|---|
| 1353 | | - __func__, new_volt); |
|---|
| 1354 | | - goto restore_voltage; |
|---|
| 1356 | + if (old_volt <= new_volt) { |
|---|
| 1357 | + ret = regulator_set_voltage(vdd_reg, new_volt, INT_MAX); |
|---|
| 1358 | + if (ret) { |
|---|
| 1359 | + dev_err(dev, "%s: failed to set volt: %lu\n", |
|---|
| 1360 | + __func__, new_volt); |
|---|
| 1361 | + goto restore_voltage; |
|---|
| 1362 | + } |
|---|
| 1355 | 1363 | } |
|---|
| 1356 | 1364 | rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm); |
|---|
| 1357 | 1365 | if (is_set_clk && clk_set_rate(info->clk, new_rate)) { |
|---|
| .. | .. |
|---|
| 1396 | 1404 | rockchip_get_read_margin(dev, opp_info, old_volt, &target_rm); |
|---|
| 1397 | 1405 | rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm); |
|---|
| 1398 | 1406 | restore_voltage: |
|---|
| 1407 | + if (old_volt <= new_volt) |
|---|
| 1408 | + regulator_set_voltage(vdd_reg, old_volt, INT_MAX); |
|---|
| 1399 | 1409 | if (info->regulator_count > 1) |
|---|
| 1400 | 1410 | regulator_set_voltage(mem_reg, old_mem_volt, INT_MAX); |
|---|
| 1401 | | - regulator_set_voltage(vdd_reg, old_volt, INT_MAX); |
|---|
| 1411 | + if (old_volt > new_volt) |
|---|
| 1412 | + regulator_set_voltage(vdd_reg, old_volt, INT_MAX); |
|---|
| 1402 | 1413 | disable_clk: |
|---|
| 1403 | 1414 | rockchip_monitor_disable_opp_clk(dev, opp_info); |
|---|
| 1404 | 1415 | unlock: |
|---|