msm: mdss: specify HFlip and VFlip per pipe BW limit

Apply per pipe BW limit check based on HFlip/VFlip. Some
targets have different limits for BW based on usecase.

Change-Id: Ie23dba396b47ffb3fb910e746e4a992fe6d78ab9
Signed-off-by: Anusha Koduru <kanusha@codeaurora.org>
This commit is contained in:
Anusha Koduru 2015-07-24 15:27:23 +05:30 committed by David Keitel
parent 0bbece9015
commit 97746a102c
4 changed files with 139 additions and 8 deletions

View file

@ -427,8 +427,20 @@ Fudge Factors: Fudge factors are used to boost demand for
applied in scenarios where panel interface can
be more tolerant to memory latency such as
command mode panels.
- qcom,max-bandwidth-per-pipe-kbps: This value indicates the max bandwidth in KB
that a single pipe can support without underflow.
- qcom,max-bandwidth-per-pipe-kbps: A two dimensional array indicating the max
bandwidth in KB that a single pipe can support
without underflow for various usecases. The
first parameter indicates the usecase and the
second parameter gives the max bw allowed for
the usecase. Following are the enum values for
modes in different cases:
For default case, mode = 1
camera usecase, mode = 2
hflip usecase, mode = 4
vflip usecase, mode = 8
First parameter/mode value need to match enum,
mdss_mdp_max_bw_mode, present in
include/uapi/linux/msm_mdp.h.
- qcom,max-bw-settings: This two dimension array indicates the max bandwidth
in KB that has to be supported when particular
scenarios are involved such as camera, flip.
@ -612,6 +624,8 @@ Example:
qcom,max-bandwidth-low-kbps = <2300000>;
qcom,max-bandwidth-high-kbps = <3000000>;
qcom,max-bandwidth-per-pipe-kbps = <4 2100000>,
<8 1800000>;
qcom,max-bw-settings = <1 2300000>,
<2 1700000>,
<4 2300000>,

View file

@ -433,6 +433,10 @@ struct mdss_data_type {
u32 bw_mode_bitmap;
u32 max_bw_settings_cnt;
struct mdss_max_bw_settings *max_per_pipe_bw_settings;
u32 mdss_per_pipe_bw_cnt;
u32 min_bw_per_pipe;
u32 bcolor0;
u32 bcolor1;
u32 bcolor2;

View file

@ -2995,6 +2995,63 @@ static void mdss_mdp_parse_max_bandwidth(struct platform_device *pdev)
mdata->max_bw_settings_cnt = max_bw_settings_cnt;
}
static void mdss_mdp_parse_per_pipe_bandwidth(struct platform_device *pdev)
{
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
struct mdss_max_bw_settings *max_bw_per_pipe_settings;
int max_bw_settings_cnt = 0;
const u32 *max_bw_settings;
u32 max_bw, min_bw, threshold, i = 0;
max_bw_settings = of_get_property(pdev->dev.of_node,
"qcom,max-bandwidth-per-pipe-kbps",
&max_bw_settings_cnt);
if (!max_bw_settings || !max_bw_settings_cnt) {
pr_debug("MDSS per pipe max bandwidth settings not found\n");
return;
}
/* Support targets where a common per pipe max bw is provided */
if ((max_bw_settings_cnt / sizeof(u32)) == 1) {
mdata->max_bw_per_pipe = be32_to_cpu(max_bw_settings[0]);
mdata->max_per_pipe_bw_settings = NULL;
pr_debug("Common per pipe max bandwidth provided\n");
return;
}
max_bw_settings_cnt /= 2 * sizeof(u32);
max_bw_per_pipe_settings = devm_kzalloc(&pdev->dev,
sizeof(struct mdss_max_bw_settings) * max_bw_settings_cnt,
GFP_KERNEL);
if (!max_bw_per_pipe_settings) {
pr_err("Memory allocation failed for max_bw_settings\n");
return;
}
mdss_mdp_parse_max_bw_array(max_bw_settings, max_bw_per_pipe_settings,
max_bw_settings_cnt);
mdata->max_per_pipe_bw_settings = max_bw_per_pipe_settings;
mdata->mdss_per_pipe_bw_cnt = max_bw_settings_cnt;
/* Calculate min and max allowed per pipe BW */
min_bw = mdata->max_bw_high;
max_bw = 0;
while (i < max_bw_settings_cnt) {
threshold = mdata->max_per_pipe_bw_settings[i].mdss_max_bw_val;
if (threshold > max_bw)
max_bw = threshold;
if (threshold < min_bw)
min_bw = threshold;
++i;
}
mdata->max_bw_per_pipe = max_bw;
mdata->min_bw_per_pipe = min_bw;
}
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
{
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@ -3123,11 +3180,7 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
if (rc)
pr_debug("max bandwidth (high) property not specified\n");
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,max-bandwidth-per-pipe-kbps", &mdata->max_bw_per_pipe);
if (rc)
pr_debug("max bandwidth (per pipe) property not specified\n");
mdss_mdp_parse_per_pipe_bandwidth(pdev);
mdss_mdp_parse_max_bandwidth(pdev);

View file

@ -1402,6 +1402,61 @@ int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
return 0;
}
static u32 mdss_mdp_get_bw_by_mode(struct mdss_max_bw_settings *settings,
int count, int key)
{
u32 value = 0, i = 0;
while (i < count) {
if (settings[i].mdss_max_bw_mode == key) {
value = settings[i].mdss_max_bw_val;
break;
}
++i;
}
return value;
}
static u32 mdss_mdp_get_max_pipe_bw(struct mdss_mdp_pipe *pipe)
{
struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata;
struct mdss_mdp_ctl *ctl = pipe->mixer_left->ctl;
u32 flags = 0, threshold = 0, panel_orientation;
panel_orientation = ctl->mfd->panel_orientation;
/* Check for panel orienatation */
panel_orientation = ctl->mfd->panel_orientation;
if (panel_orientation & MDP_FLIP_LR)
flags |= MDSS_MAX_BW_LIMIT_HFLIP;
if (panel_orientation & MDP_FLIP_UD)
flags |= MDSS_MAX_BW_LIMIT_VFLIP;
/* check for Hflip/Vflip in pipe */
if (pipe->flags & MDP_FLIP_LR)
flags |= MDSS_MAX_BW_LIMIT_HFLIP;
if (pipe->flags & MDP_FLIP_UD)
flags |= MDSS_MAX_BW_LIMIT_VFLIP;
if ((flags & MDSS_MAX_BW_LIMIT_HFLIP) &&
(flags & MDSS_MAX_BW_LIMIT_VFLIP)) {
threshold = mdata->min_bw_per_pipe;
} else if (flags & MDSS_MAX_BW_LIMIT_HFLIP) {
threshold = mdss_mdp_get_bw_by_mode(
mdata->max_per_pipe_bw_settings,
mdata->mdss_per_pipe_bw_cnt,
MDSS_MAX_BW_LIMIT_HFLIP);
} else if (flags & MDSS_MAX_BW_LIMIT_VFLIP) {
threshold = mdss_mdp_get_bw_by_mode(
mdata->max_per_pipe_bw_settings,
mdata->mdss_per_pipe_bw_cnt,
MDSS_MAX_BW_LIMIT_VFLIP);
}
return threshold ? threshold : mdata->max_bw_per_pipe;
}
int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
struct mdss_mdp_pipe *pipe)
{
@ -1427,7 +1482,12 @@ int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
/* convert bandwidth to kb */
pipe_bw = DIV_ROUND_UP_ULL(pipe_bw, 1000);
threshold = mdata->max_bw_per_pipe;
if (!mdata->max_per_pipe_bw_settings)
threshold = mdata->max_bw_per_pipe;
else
threshold = mdss_mdp_get_max_pipe_bw(pipe);
pr_debug("bw=%llu threshold=%u\n", pipe_bw, threshold);
if (threshold && pipe_bw > threshold) {