^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Rockchip dmc common functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Finley Xiao <finley.xiao@rock-chips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <soc/rockchip/rockchip_dmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define msch_rl_to_dmcfreq(work) container_of(to_delayed_work(work), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct rockchip_dmcfreq, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) msch_rl_work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define MSCH_RL_DELAY_TIME 50 /* ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static struct dmcfreq_common_info *common_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static DECLARE_RWSEM(rockchip_dmcfreq_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) void rockchip_dmcfreq_lock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) down_read(&rockchip_dmcfreq_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) EXPORT_SYMBOL(rockchip_dmcfreq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) void rockchip_dmcfreq_lock_nested(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) down_read_nested(&rockchip_dmcfreq_sem, SINGLE_DEPTH_NESTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) EXPORT_SYMBOL(rockchip_dmcfreq_lock_nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) void rockchip_dmcfreq_unlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) up_read(&rockchip_dmcfreq_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) EXPORT_SYMBOL(rockchip_dmcfreq_unlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int rockchip_dmcfreq_write_trylock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return down_write_trylock(&rockchip_dmcfreq_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) EXPORT_SYMBOL(rockchip_dmcfreq_write_trylock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void rockchip_dmcfreq_write_unlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) up_write(&rockchip_dmcfreq_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL(rockchip_dmcfreq_write_unlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void set_msch_rl(unsigned int readlatency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) rockchip_dmcfreq_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_dbg(common_info->dev, "rl 0x%x -> 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) common_info->read_latency, readlatency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!common_info->set_msch_readlatency(readlatency))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) common_info->read_latency = readlatency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) dev_err(common_info->dev, "failed to set msch rl\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) rockchip_dmcfreq_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void set_msch_rl_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) set_msch_rl(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) common_info->is_msch_rl_work_started = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int rockchip_dmcfreq_vop_bandwidth_init(struct dmcfreq_common_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (info->set_msch_readlatency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) INIT_DELAYED_WORK(&info->msch_rl_work, set_msch_rl_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) common_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) EXPORT_SYMBOL(rockchip_dmcfreq_vop_bandwidth_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void rockchip_dmcfreq_vop_bandwidth_update(struct dmcfreq_vop_info *vop_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long vop_last_rate, target = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int readlatency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!common_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev_dbg(common_info->dev, "line bw=%u, frame bw=%u, pn=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) vop_info->line_bw_mbyte, vop_info->frame_bw_mbyte,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) vop_info->plane_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!common_info->vop_pn_rl_tbl || !common_info->set_msch_readlatency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) goto vop_bw_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; common_info->vop_pn_rl_tbl[i].rl != DMCFREQ_TABLE_END; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (vop_info->plane_num >= common_info->vop_pn_rl_tbl[i].pn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) readlatency = common_info->vop_pn_rl_tbl[i].rl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dev_dbg(common_info->dev, "pn=%u\n", vop_info->plane_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (readlatency) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) cancel_delayed_work_sync(&common_info->msch_rl_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) common_info->is_msch_rl_work_started = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (common_info->read_latency != readlatency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) set_msch_rl(readlatency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } else if (common_info->read_latency &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) !common_info->is_msch_rl_work_started) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) common_info->is_msch_rl_work_started = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) schedule_delayed_work(&common_info->msch_rl_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) msecs_to_jiffies(MSCH_RL_DELAY_TIME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) vop_bw_tbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!common_info->auto_freq_en || !common_info->vop_bw_tbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) goto vop_frame_bw_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for (i = 0; common_info->vop_bw_tbl[i].freq != DMCFREQ_TABLE_END; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (vop_info->line_bw_mbyte >= common_info->vop_bw_tbl[i].min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) target = common_info->vop_bw_tbl[i].freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) vop_frame_bw_tbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!common_info->auto_freq_en || !common_info->vop_frame_bw_tbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; common_info->vop_frame_bw_tbl[i].freq != DMCFREQ_TABLE_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (vop_info->frame_bw_mbyte >= common_info->vop_frame_bw_tbl[i].min) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (target < common_info->vop_frame_bw_tbl[i].freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) target = common_info->vop_frame_bw_tbl[i].freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) vop_last_rate = common_info->vop_req_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) common_info->vop_req_rate = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (target > vop_last_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) mutex_lock(&common_info->devfreq->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) update_devfreq(common_info->devfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mutex_unlock(&common_info->devfreq->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) EXPORT_SYMBOL(rockchip_dmcfreq_vop_bandwidth_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int rockchip_dmcfreq_vop_bandwidth_request(struct dmcfreq_vop_info *vop_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned long target = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (!common_info || !common_info->auto_freq_en ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) !common_info->vop_bw_tbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) for (i = 0; common_info->vop_bw_tbl[i].freq != DMCFREQ_TABLE_END; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (vop_info->line_bw_mbyte <= common_info->vop_bw_tbl[i].max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) target = common_info->vop_bw_tbl[i].freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) EXPORT_SYMBOL(rockchip_dmcfreq_vop_bandwidth_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) MODULE_DESCRIPTION("rockchip dmcfreq driver with devfreq framework");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) MODULE_LICENSE("GPL v2");