msm: mdss: Refactor ping pong split configurations
Refactor ping pong split programming to make it generic enough to support the feature on multiple targets. Change-Id: Ic2a1cad97c354997de81f06e449ab78a1864fda2 Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org> (cherry picked from commit 472bb7cff9aae26cac323c6cb5d01ffb1de206ab) [veeras@codeaurora.org: Resolve merge conflict in mdss_mdp_intf_cmd.c and mdss_mdp_intf_video.c] Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org> ../../../../tools/gator/daemon/events_xml.h
This commit is contained in:
parent
1c9334a895
commit
80b557c07f
7 changed files with 337 additions and 214 deletions
|
@ -449,6 +449,11 @@ Fudge Factors: Fudge factors are used to boost demand for
|
|||
- qcom,max-pipe-width: This value specifies the maximum MDP SSPP width
|
||||
the device supports. If not specified, a default value
|
||||
of 2048 will be applied.
|
||||
- qcom,mdss-slave-pingpong-off: Offset address for the extra TE block which needs
|
||||
to be programmed when pingpong split feature is enabled.
|
||||
Offset is calculated from the "mdp_phys"
|
||||
register value. Mandatory when qcom,mdss-has-dst-split
|
||||
is enabled.
|
||||
|
||||
Optional subnodes:
|
||||
- mdss_fb: Child nodes representing the frame buffer virtual devices.
|
||||
|
@ -666,6 +671,7 @@ Example:
|
|||
0x00021500 0x00021700>;
|
||||
qcom,mdss-cdm-off = <0x0007A200>;
|
||||
qcom,mdss-ppb-off = <0x0000420>;
|
||||
qcom,mdss-slave-pingpong-off = <0x00073000>
|
||||
|
||||
/* buffer parameters to calculate prefill bandwidth */
|
||||
qcom,mdss-prefill-outstanding-buffer-bytes = <1024>;
|
||||
|
|
|
@ -314,8 +314,10 @@ struct mdss_data_type {
|
|||
u32 max_target_zorder;
|
||||
u8 ncursor_pipes;
|
||||
u32 max_cursor_size;
|
||||
|
||||
u32 nppb;
|
||||
struct mdss_mdp_ppb *ppb;
|
||||
char __iomem *slave_pingpong_base;
|
||||
|
||||
struct mdss_mdp_mixer *mixer_intf;
|
||||
struct mdss_mdp_mixer *mixer_wb;
|
||||
|
|
|
@ -2695,7 +2695,7 @@ static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev)
|
|||
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
|
||||
{
|
||||
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
|
||||
u32 data;
|
||||
u32 data, slave_pingpong_off;
|
||||
const char *wfd_data;
|
||||
int rc;
|
||||
struct property *prop = NULL;
|
||||
|
@ -2763,6 +2763,18 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
|
|||
mdata->has_pingpong_split = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,mdss-has-dst-split");
|
||||
|
||||
if (mdata->has_pingpong_split) {
|
||||
rc = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,mdss-slave-pingpong-off",
|
||||
&slave_pingpong_off);
|
||||
if (rc) {
|
||||
pr_err("Error in device tree: slave pingpong offset\n");
|
||||
return rc;
|
||||
}
|
||||
mdata->slave_pingpong_base = mdata->mdss_io.base +
|
||||
slave_pingpong_off;
|
||||
}
|
||||
|
||||
/*
|
||||
* 2x factor on AB because bus driver will divide by 2
|
||||
* due to 2x ports to BIMC
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
#define CURSOR_PIPE_LEFT 0
|
||||
#define CURSOR_PIPE_RIGHT 1
|
||||
|
||||
#define MASTER_CTX 0
|
||||
#define SLAVE_CTX 1
|
||||
|
||||
/*
|
||||
* Recommendation is to have different ot depending on the fps
|
||||
* and resolution, but since current SW doesn't support different
|
||||
|
@ -300,6 +303,7 @@ struct mdss_mdp_ctl {
|
|||
struct blocking_notifier_head notifier_head;
|
||||
|
||||
void *priv_data;
|
||||
void *intf_ctx[2];
|
||||
u32 wb_type;
|
||||
bool prg_fet;
|
||||
|
||||
|
|
|
@ -2399,6 +2399,12 @@ static void mdss_mdp_ctl_split_display_enable(int enable,
|
|||
lower |= BIT(4);
|
||||
else
|
||||
lower |= BIT(8);
|
||||
/*
|
||||
* Enable SMART_PANEL_FREE_RUN if ping pong split
|
||||
* is enabled.
|
||||
*/
|
||||
if (is_pingpong_split(main_ctl->mfd))
|
||||
lower |= BIT(2);
|
||||
upper = lower;
|
||||
} else {
|
||||
/* interface controlling sw trigger (video mode) */
|
||||
|
|
|
@ -61,6 +61,7 @@ struct mdss_mdp_cmd_ctx {
|
|||
struct mdss_intf_recovery intf_recovery;
|
||||
struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */
|
||||
u32 pp_timeout_report_cnt;
|
||||
int pingpong_split_slave;
|
||||
};
|
||||
|
||||
struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
|
||||
|
@ -122,14 +123,15 @@ exit:
|
|||
}
|
||||
|
||||
|
||||
static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_mdp_mixer *mixer, bool enable)
|
||||
static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
|
||||
struct mdss_mdp_cmd_ctx *ctx, bool enable)
|
||||
{
|
||||
struct mdss_mdp_pp_tear_check *te = NULL;
|
||||
struct mdss_panel_info *pinfo;
|
||||
u32 vsync_clk_speed_hz, total_lines, vclks_line, cfg = 0;
|
||||
char __iomem *pingpong_base;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_ctl *ctl = ctx->ctl;
|
||||
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
|
||||
|
||||
if (IS_ERR_OR_NULL(ctl->panel_data)) {
|
||||
pr_err("no panel data\n");
|
||||
|
@ -174,9 +176,9 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
|
|||
}
|
||||
|
||||
pingpong_base = mixer->pingpong_base;
|
||||
/* for dst split pp_num is cmd session (0 and 1) */
|
||||
if (is_pingpong_split(ctl->mfd))
|
||||
pingpong_base += ctx->pp_num * SPLIT_MIXER_OFFSET;
|
||||
|
||||
if (ctx->pingpong_split_slave)
|
||||
pingpong_base = mdata->slave_pingpong_base;
|
||||
|
||||
mdss_mdp_pingpong_write(pingpong_base,
|
||||
MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
|
||||
|
@ -203,14 +205,16 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable)
|
||||
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
|
||||
bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mdss_mdp_mixer *mixer;
|
||||
struct mdss_mdp_ctl *ctl = ctx->ctl;
|
||||
|
||||
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
|
||||
if (mixer) {
|
||||
rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable);
|
||||
rc = mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
@ -218,9 +222,9 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable)
|
|||
if (!(ctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE)) {
|
||||
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
|
||||
if (mixer)
|
||||
rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable);
|
||||
rc = mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
|
||||
}
|
||||
err:
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -296,7 +300,7 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx)
|
|||
static void mdss_mdp_cmd_readptr_done(void *arg)
|
||||
{
|
||||
struct mdss_mdp_ctl *ctl = arg;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
struct mdss_mdp_vsync_handler *tmp;
|
||||
ktime_t vsync_time;
|
||||
|
||||
|
@ -382,7 +386,7 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event)
|
|||
static void mdss_mdp_cmd_pingpong_done(void *arg)
|
||||
{
|
||||
struct mdss_mdp_ctl *ctl = arg;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
struct mdss_mdp_vsync_handler *tmp;
|
||||
ktime_t vsync_time;
|
||||
u32 status;
|
||||
|
@ -463,7 +467,8 @@ static void clk_ctrl_work(struct work_struct *work)
|
|||
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl) {
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
sctx =
|
||||
(struct mdss_mdp_cmd_ctx *)sctl->intf_ctx[MASTER_CTX];
|
||||
} else {
|
||||
/* slave ctl, let master ctl do clk control */
|
||||
mutex_unlock(&cmd_clk_mtx);
|
||||
|
@ -488,7 +493,7 @@ static int mdss_mdp_cmd_add_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
unsigned long flags;
|
||||
bool enable_rdptr = false;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("%s: invalid ctx\n", __func__);
|
||||
return -ENODEV;
|
||||
|
@ -498,7 +503,7 @@ static int mdss_mdp_cmd_add_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
ctx->rdptr_enabled);
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
if (!handle->enabled) {
|
||||
|
@ -536,7 +541,7 @@ static int mdss_mdp_cmd_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("%s: invalid ctx\n", __func__);
|
||||
return -ENODEV;
|
||||
|
@ -546,7 +551,7 @@ static int mdss_mdp_cmd_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
ctx->rdptr_enabled, 0x88888);
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
spin_lock_irqsave(&ctx->clk_lock, flags);
|
||||
if (handle->enabled) {
|
||||
|
@ -593,7 +598,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -682,14 +687,14 @@ static void mdss_mdp_cmd_set_sync_ctx(
|
|||
{
|
||||
struct mdss_mdp_cmd_ctx *ctx, *sctx;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *)ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *)ctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
if (!sctl) {
|
||||
ctx->sync_ctx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
sctx = (struct mdss_mdp_cmd_ctx *)sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_cmd_ctx *)sctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
if (!sctl->roi.w && !sctl->roi.h) {
|
||||
/* left only */
|
||||
|
@ -734,14 +739,14 @@ static int mdss_mdp_cmd_panel_on(struct mdss_mdp_ctl *ctl,
|
|||
struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
|
||||
int rc = 0;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (sctl)
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
if (!__mdss_mdp_cmd_is_panel_power_on_interactive(ctx)) {
|
||||
rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_LINK_READY, NULL);
|
||||
|
@ -779,7 +784,7 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
|
|||
pr_err("invalid ctl structure\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -876,7 +881,7 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
struct mdss_mdp_ctl *sctl = NULL;
|
||||
struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -900,7 +905,7 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
PERF_HW_MDP_STATE, PERF_STATUS_BUSY);
|
||||
|
||||
if (sctl) {
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
mdss_mdp_ctl_perf_set_transaction_status(sctl,
|
||||
PERF_HW_MDP_STATE, PERF_STATUS_BUSY);
|
||||
}
|
||||
|
@ -977,44 +982,26 @@ int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl)
|
|||
{
|
||||
pr_debug("%s: called for ctl%d\n", __func__, ctl->num);
|
||||
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
|
||||
if (mdss_mdp_cmd_tearcheck_setup(ctl, true))
|
||||
if (mdss_mdp_cmd_tearcheck_setup(ctl->intf_ctx[MASTER_CTX], true))
|
||||
pr_warn("%s: tearcheck setup failed\n", __func__);
|
||||
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
||||
int panel_power_state)
|
||||
int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_mdp_cmd_ctx *ctx, int panel_power_state)
|
||||
{
|
||||
struct mdss_mdp_ctl *sctl = NULL;
|
||||
struct mdss_mdp_cmd_ctx *sctx = NULL;
|
||||
struct mdss_mdp_cmd_ctx *ctx;
|
||||
struct mdss_mdp_ctl *sctl = NULL;
|
||||
unsigned long flags;
|
||||
unsigned long sflags;
|
||||
int need_wait = 0;
|
||||
int ret = 0;
|
||||
int hz;
|
||||
|
||||
if (session >= MAX_SESSIONS)
|
||||
return 0;
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
ret = mdss_mdp_cmd_intfs_stop(ctl, (session + 1),
|
||||
panel_power_state);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
if (sctl)
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->priv_data;
|
||||
|
||||
ctx = &mdss_mdp_cmd_ctx_list[session];
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("invalid ctx session: %d\n", session);
|
||||
return -ENODEV;
|
||||
}
|
||||
sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
/* intf stopped, no more kickoff */
|
||||
ctx->intf_stopped = 1;
|
||||
|
@ -1057,11 +1044,11 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
|||
|
||||
mdss_mdp_cmd_clk_off(ctx);
|
||||
flush_work(&ctx->pp_done_work);
|
||||
mdss_mdp_cmd_tearcheck_setup(ctl, false);
|
||||
mdss_mdp_cmd_tearcheck_setup(ctx, false);
|
||||
|
||||
if (mdss_panel_is_power_on(panel_power_state)) {
|
||||
pr_debug("%s: intf stopped with panel on\n", __func__);
|
||||
goto end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
|
||||
|
@ -1071,9 +1058,39 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
|||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
end:
|
||||
pr_debug("%s:-\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
||||
int panel_power_state)
|
||||
{
|
||||
struct mdss_mdp_cmd_ctx *ctx;
|
||||
|
||||
if (session >= MAX_SESSIONS)
|
||||
return 0;
|
||||
|
||||
ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("invalid ctx session: %d\n", session);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mdss_mdp_cmd_ctx_stop(ctl, ctx, panel_power_state);
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
session += 1;
|
||||
|
||||
if (session >= MAX_SESSIONS)
|
||||
return 0;
|
||||
|
||||
ctx = ctl->intf_ctx[SLAVE_CTX];
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("invalid ctx session: %d\n", session);
|
||||
return -ENODEV;
|
||||
}
|
||||
mdss_mdp_cmd_ctx_stop(ctl, ctx, panel_power_state);
|
||||
}
|
||||
pr_debug("%s:-\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1101,7 @@ static int mdss_mdp_cmd_stop_sub(struct mdss_mdp_ctl *ctl,
|
|||
struct mdss_mdp_vsync_handler *tmp, *handle;
|
||||
int session;
|
||||
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -1102,7 +1119,7 @@ static int mdss_mdp_cmd_stop_sub(struct mdss_mdp_ctl *ctl,
|
|||
|
||||
int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
||||
{
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
bool panel_off = false;
|
||||
bool turn_off_clocks = false;
|
||||
|
@ -1215,7 +1232,8 @@ panel_events:
|
|||
}
|
||||
|
||||
pr_debug("%s: turn off panel\n", __func__);
|
||||
ctl->priv_data = NULL;
|
||||
ctl->intf_ctx[MASTER_CTX] = NULL;
|
||||
ctl->intf_ctx[SLAVE_CTX] = NULL;
|
||||
ctl->ops.stop_fnc = NULL;
|
||||
ctl->ops.display_fnc = NULL;
|
||||
ctl->ops.wait_pingpong = NULL;
|
||||
|
@ -1233,6 +1251,51 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_mdp_cmd_ctx *ctx, int pp_num,
|
||||
int pingpong_split_slave) {
|
||||
int ret = 0;
|
||||
|
||||
ctx->ctl = ctl;
|
||||
ctx->pp_num = pp_num;
|
||||
ctx->pingpong_split_slave = pingpong_split_slave;
|
||||
ctx->pp_timeout_report_cnt = 0;
|
||||
init_waitqueue_head(&ctx->pp_waitq);
|
||||
init_completion(&ctx->stop_comp);
|
||||
init_completion(&ctx->readptr_done);
|
||||
spin_lock_init(&ctx->clk_lock);
|
||||
spin_lock_init(&ctx->koff_lock);
|
||||
mutex_init(&ctx->clk_mtx);
|
||||
mutex_init(&ctx->autorefresh_mtx);
|
||||
INIT_WORK(&ctx->clk_work, clk_ctrl_work);
|
||||
INIT_WORK(&ctx->pp_done_work, pingpong_done_work);
|
||||
atomic_set(&ctx->pp_done_cnt, 0);
|
||||
ctx->autorefresh_off_pending = false;
|
||||
ctx->autorefresh_init = false;
|
||||
INIT_LIST_HEAD(&ctx->vsync_handlers);
|
||||
|
||||
ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery;
|
||||
ctx->intf_recovery.data = ctx;
|
||||
|
||||
ctx->intf_stopped = 0;
|
||||
|
||||
pr_debug("%s: ctx=%p num=%d\n", __func__, ctx, ctx->pp_num);
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
|
||||
ctx->pp_num, mdss_mdp_cmd_readptr_done, ctl);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
|
||||
mdss_mdp_cmd_pingpong_done, ctl);
|
||||
|
||||
ret = mdss_mdp_cmd_tearcheck_setup(ctx, true);
|
||||
if (ret)
|
||||
pr_err("tearcheck setup failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
|
||||
int session)
|
||||
{
|
||||
|
@ -1244,12 +1307,6 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
|
|||
if (session >= MAX_SESSIONS)
|
||||
return 0;
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
ret = mdss_mdp_cmd_intfs_setup(ctl, (session + 1));
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
ctx = &mdss_mdp_cmd_ctx_list[session];
|
||||
if (ctx->ref_cnt) {
|
||||
|
@ -1281,51 +1338,43 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ctl->priv_data = ctx;
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
ctl->intf_ctx[MASTER_CTX] = ctx;
|
||||
|
||||
ret = mdss_mdp_cmd_ctx_setup(ctl, ctx, session, false);
|
||||
if (ret) {
|
||||
pr_err("mdss_mdp_cmd_ctx_setup failed for ping ping: %d\n",
|
||||
mixer->num);
|
||||
ctx->ref_cnt--;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ctx->ctl = ctl;
|
||||
ctx->pp_num = (is_pingpong_split(ctl->mfd) ? session : mixer->num);
|
||||
ctx->pp_timeout_report_cnt = 0;
|
||||
init_waitqueue_head(&ctx->pp_waitq);
|
||||
init_completion(&ctx->stop_comp);
|
||||
init_completion(&ctx->readptr_done);
|
||||
spin_lock_init(&ctx->clk_lock);
|
||||
spin_lock_init(&ctx->koff_lock);
|
||||
mutex_init(&ctx->clk_mtx);
|
||||
mutex_init(&ctx->autorefresh_mtx);
|
||||
INIT_WORK(&ctx->clk_work, clk_ctrl_work);
|
||||
INIT_WORK(&ctx->pp_done_work, pingpong_done_work);
|
||||
atomic_set(&ctx->pp_done_cnt, 0);
|
||||
ctx->autorefresh_off_pending = false;
|
||||
ctx->autorefresh_init = false;
|
||||
INIT_LIST_HEAD(&ctx->vsync_handlers);
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
session += 1;
|
||||
if (session >= MAX_SESSIONS)
|
||||
return 0;
|
||||
ctx = &mdss_mdp_cmd_ctx_list[session];
|
||||
if (ctx->ref_cnt) {
|
||||
if (mdss_panel_is_power_on(ctx->panel_power_state)) {
|
||||
pr_debug("%s: cmd_start with panel always on\n",
|
||||
__func__);
|
||||
mdss_mdp_cmd_restore(ctl);
|
||||
return mdss_mdp_cmd_panel_on(ctl, sctl);
|
||||
} else {
|
||||
pr_err("Intf %d already in use\n", session);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
ctx->ref_cnt++;
|
||||
|
||||
ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery;
|
||||
ctx->intf_recovery.data = ctx;
|
||||
ctl->intf_ctx[SLAVE_CTX] = ctx;
|
||||
|
||||
ctx->intf_stopped = 0;
|
||||
|
||||
pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__,
|
||||
ctx, ctx->pp_num, mixer->num);
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
ctx->rdptr_enabled);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
|
||||
ctx->pp_num, mdss_mdp_cmd_readptr_done, ctl);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
|
||||
mdss_mdp_cmd_pingpong_done, ctl);
|
||||
|
||||
ret = mdss_mdp_cmd_tearcheck_setup(ctl, true);
|
||||
if (ret) {
|
||||
pr_err("tearcheck setup failed\n");
|
||||
return ret;
|
||||
ret = mdss_mdp_cmd_ctx_setup(ctl, ctx, session, true);
|
||||
if (ret) {
|
||||
pr_err("mdss_mdp_cmd_ctx_setup failed for slave ping pong block");
|
||||
ctx->ref_cnt--;
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
|
||||
|
|
|
@ -91,9 +91,9 @@ static inline u32 mdss_mdp_video_line_count(struct mdss_mdp_ctl *ctl)
|
|||
{
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
u32 line_cnt = 0;
|
||||
if (!ctl || !ctl->priv_data)
|
||||
if (!ctl || !ctl->intf_ctx[MASTER_CTX])
|
||||
goto line_count_exit;
|
||||
ctx = ctl->priv_data;
|
||||
ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
line_cnt = mdp_video_read(ctx, MDSS_MDP_REG_INTF_LINE_COUNT);
|
||||
line_count_exit:
|
||||
return line_cnt;
|
||||
|
@ -149,7 +149,7 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
|
|||
return;
|
||||
}
|
||||
|
||||
ctx = ctl->priv_data;
|
||||
ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
pr_debug("%s: ctl num = %d, event = %d\n",
|
||||
__func__, ctl->num, event);
|
||||
|
||||
|
@ -214,17 +214,16 @@ static void mdss_mdp_video_intf_recovery(void *data, int event)
|
|||
}
|
||||
|
||||
static int mdss_mdp_video_timegen_setup(struct mdss_mdp_ctl *ctl,
|
||||
struct intf_timing_params *p)
|
||||
struct intf_timing_params *p,
|
||||
struct mdss_mdp_video_ctx *ctx)
|
||||
{
|
||||
u32 hsync_period, vsync_period;
|
||||
u32 hsync_start_x, hsync_end_x, display_v_start, display_v_end;
|
||||
u32 active_h_start, active_h_end, active_v_start, active_v_end;
|
||||
u32 den_polarity, hsync_polarity, vsync_polarity;
|
||||
u32 display_hctl, active_hctl, hsync_ctl, polarity_ctl;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
struct mdss_data_type *mdata;
|
||||
|
||||
ctx = ctl->priv_data;
|
||||
mdata = ctl->mdata;
|
||||
hsync_period = p->hsync_pulse_width + p->h_back_porch +
|
||||
p->width + p->h_front_porch;
|
||||
|
@ -332,7 +331,7 @@ static int mdss_mdp_video_timegen_setup(struct mdss_mdp_ctl *ctl,
|
|||
|
||||
static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
|
||||
{
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
mutex_lock(&ctx->vsync_mtx);
|
||||
if (atomic_inc_return(&ctx->vsync_ref) == 1)
|
||||
|
@ -345,7 +344,7 @@ static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
|
|||
|
||||
static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
|
||||
{
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
|
||||
mutex_lock(&ctx->vsync_mtx);
|
||||
if (atomic_dec_return(&ctx->vsync_ref) == 0)
|
||||
|
@ -366,7 +365,7 @@ static int mdss_mdp_video_add_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx for ctl=%d\n", ctl->num);
|
||||
ret = -ENODEV;
|
||||
|
@ -395,7 +394,7 @@ static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
unsigned long flags;
|
||||
bool irq_dis = false;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx for ctl=%d\n", ctl->num);
|
||||
return -ENODEV;
|
||||
|
@ -415,42 +414,12 @@ static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_panel_data *pdata, int inum)
|
||||
static int mdss_mdp_video_ctx_stop(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_panel_info *pinfo, struct mdss_mdp_video_ctx *ctx)
|
||||
{
|
||||
struct mdss_data_type *mdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
struct mdss_mdp_vsync_handler *tmp, *handle;
|
||||
struct mdss_mdp_ctl *sctl;
|
||||
int rc = 0;
|
||||
u32 frame_rate = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (pdata == NULL)
|
||||
return 0;
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
ret = mdss_mdp_video_intfs_stop(ctl, pdata->next, (inum + 1));
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdata = ctl->mdata;
|
||||
pinfo = &pdata->panel_info;
|
||||
|
||||
if (inum < mdata->nintf) {
|
||||
ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + inum;
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0));
|
||||
return -ENODEV;
|
||||
}
|
||||
pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num,
|
||||
ctx->intf_num, ctx->base);
|
||||
} else {
|
||||
pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&ctl->offlock);
|
||||
if (ctx->timegen_en) {
|
||||
|
@ -464,8 +433,7 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
|
|||
|
||||
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
|
||||
/* wait for at least one VSYNC for proper TG OFF */
|
||||
frame_rate = mdss_panel_get_framerate
|
||||
(&(ctl->panel_data->panel_info));
|
||||
frame_rate = mdss_panel_get_framerate(pinfo);
|
||||
if (!(frame_rate >= 24 && frame_rate <= 240))
|
||||
frame_rate = 24;
|
||||
msleep((1000/frame_rate) + 1);
|
||||
|
@ -487,13 +455,10 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
|
|||
mdss_bus_bandwidth_ctrl(false);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
|
||||
mdss_mdp_video_remove_vsync_handler(ctl, handle);
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC,
|
||||
(inum + MDSS_MDP_INTF0), NULL, NULL);
|
||||
ctx->intf_num, NULL, NULL);
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN,
|
||||
(inum + MDSS_MDP_INTF0), NULL, NULL);
|
||||
ctx->intf_num, NULL, NULL);
|
||||
|
||||
ctx->ref_cnt--;
|
||||
end:
|
||||
|
@ -501,6 +466,61 @@ end:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_panel_data *pdata, int inum)
|
||||
{
|
||||
struct mdss_data_type *mdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
struct mdss_mdp_vsync_handler *tmp, *handle;
|
||||
int ret = 0;
|
||||
|
||||
if (pdata == NULL)
|
||||
return 0;
|
||||
|
||||
mdata = ctl->mdata;
|
||||
pinfo = &pdata->panel_info;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0));
|
||||
return -ENODEV;
|
||||
}
|
||||
pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num, ctx->intf_num,
|
||||
ctx->base);
|
||||
|
||||
ret = mdss_mdp_video_ctx_stop(ctl, pinfo, ctx);
|
||||
if (ret) {
|
||||
pr_err("mdss_mdp_video_ctx_stop failed for intf: %d",
|
||||
ctx->intf_num);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
pinfo = &pdata->next->panel_info;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[SLAVE_CTX];
|
||||
if (!ctx->ref_cnt) {
|
||||
pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0));
|
||||
return -ENODEV;
|
||||
}
|
||||
pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num,
|
||||
ctx->intf_num, ctx->base);
|
||||
|
||||
ret = mdss_mdp_video_ctx_stop(ctl, pinfo, ctx);
|
||||
if (ret) {
|
||||
pr_err("mdss_mdp_video_ctx_stop failed for intf: %d",
|
||||
ctx->intf_num);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
|
||||
mdss_mdp_video_remove_vsync_handler(ctl, handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
||||
{
|
||||
|
@ -516,7 +536,7 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
|||
MDSS_XLOG(ctl->num, ctl->vsync_cnt);
|
||||
|
||||
mdss_mdp_ctl_reset(ctl);
|
||||
ctl->priv_data = NULL;
|
||||
ctl->intf_ctx[MASTER_CTX] = NULL;
|
||||
|
||||
if (ctl->cdm) {
|
||||
mdss_mdp_cdm_destroy(ctl->cdm);
|
||||
|
@ -528,7 +548,7 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
|||
static void mdss_mdp_video_vsync_intr_done(void *arg)
|
||||
{
|
||||
struct mdss_mdp_ctl *ctl = arg;
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
struct mdss_mdp_vsync_handler *tmp;
|
||||
ktime_t vsync_time;
|
||||
|
||||
|
@ -556,7 +576,7 @@ static void mdss_mdp_video_vsync_intr_done(void *arg)
|
|||
|
||||
static int mdss_mdp_video_pollwait(struct mdss_mdp_ctl *ctl)
|
||||
{
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_video_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
|
||||
u32 mask, status;
|
||||
int rc;
|
||||
|
||||
|
@ -598,7 +618,7 @@ static int mdss_mdp_video_wait4comp(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
struct mdss_mdp_video_ctx *ctx;
|
||||
int rc;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -774,7 +794,7 @@ static int mdss_mdp_video_dfps_wait4vsync(struct mdss_mdp_ctl *ctl)
|
|||
int rc = 0;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -840,9 +860,8 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl,
|
|||
int rc = 0;
|
||||
u32 hsync_period, vsync_period;
|
||||
struct mdss_data_type *mdata;
|
||||
u32 inum = ctl->intf_num - MDSS_MDP_INTF0;
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -850,28 +869,15 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl,
|
|||
|
||||
mdata = ctl->mdata;
|
||||
if (sctl) {
|
||||
sctx = (struct mdss_mdp_video_ctx *) sctl->priv_data;
|
||||
sctx = (struct mdss_mdp_video_ctx *) sctl->intf_ctx[MASTER_CTX];
|
||||
if (!sctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else if (is_pingpong_split(ctl->mfd)) {
|
||||
/*
|
||||
* On targets when destination split is enabled, mixer swap
|
||||
* is not valid. So we can safely assume that ctl->intf_num
|
||||
* is INTF1. For this case, increment inum to retrieve sctx.
|
||||
*/
|
||||
inum += 1;
|
||||
if (inum < mdata->nintf) {
|
||||
sctx = ((struct mdss_mdp_video_ctx *)
|
||||
mdata->video_intf) + inum;
|
||||
if (!sctx) {
|
||||
pr_err("invalid sctx\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
pr_err("Invalid intf number: %d\n",
|
||||
(inum + MDSS_MDP_INTF0));
|
||||
sctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[SLAVE_CTX];
|
||||
if (!sctx) {
|
||||
pr_err("invalid sctx\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
@ -992,7 +998,7 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
|
|||
|
||||
pr_debug("kickoff ctl=%d\n", ctl->num);
|
||||
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
|
@ -1071,7 +1077,7 @@ int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
|
|||
struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
|
||||
off = 0;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
|
||||
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx for ctl=%d\n", ctl->num);
|
||||
return -ENODEV;
|
||||
|
@ -1218,43 +1224,14 @@ static int mdss_mdp_video_cdm_setup(struct mdss_mdp_cdm *cdm,
|
|||
setup.output_height = pinfo->yres + pinfo->lcdc.yres_pad;
|
||||
return mdss_mdp_cdm_setup(cdm, &setup);
|
||||
}
|
||||
static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_panel_data *pdata, int inum)
|
||||
|
||||
static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_mdp_video_ctx *ctx, struct mdss_panel_info *pinfo)
|
||||
{
|
||||
struct mdss_data_type *mdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
struct intf_timing_params itp = {0};
|
||||
u32 dst_bpp;
|
||||
int ret = 0;
|
||||
struct mdss_data_type *mdata = ctl->mdata;
|
||||
|
||||
if (pdata == NULL)
|
||||
return 0;
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
ret = mdss_mdp_video_intfs_setup(ctl, pdata->next, (inum + 1));
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdata = ctl->mdata;
|
||||
pinfo = &pdata->panel_info;
|
||||
|
||||
if (inum < mdata->nintf) {
|
||||
ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + inum;
|
||||
if (ctx->ref_cnt) {
|
||||
pr_err("Intf %d already in use\n",
|
||||
(inum + MDSS_MDP_INTF0));
|
||||
return -EBUSY;
|
||||
}
|
||||
pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
|
||||
ctx->ref_cnt++;
|
||||
} else {
|
||||
pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctl->priv_data = ctx;
|
||||
ctx->intf_type = ctl->intf_type;
|
||||
init_completion(&ctx->vsync_comp);
|
||||
spin_lock_init(&ctx->vsync_lock);
|
||||
|
@ -1295,10 +1272,10 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
|
|||
}
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC,
|
||||
(inum + MDSS_MDP_INTF0),
|
||||
mdss_mdp_video_vsync_intr_done, ctl);
|
||||
ctx->intf_num, mdss_mdp_video_vsync_intr_done,
|
||||
ctl);
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN,
|
||||
(inum + MDSS_MDP_INTF0),
|
||||
ctx->intf_num,
|
||||
mdss_mdp_video_underrun_intr_done, ctl);
|
||||
|
||||
dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp);
|
||||
|
@ -1337,16 +1314,83 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
|
|||
itp.hsync_pulse_width >>= 1;
|
||||
}
|
||||
if (!ctl->panel_data->panel_info.cont_splash_enabled) {
|
||||
if (mdss_mdp_video_timegen_setup(ctl, &itp)) {
|
||||
if (mdss_mdp_video_timegen_setup(ctl, &itp, ctx)) {
|
||||
pr_err("unable to set timing parameters intfs: %d\n",
|
||||
(inum + MDSS_MDP_INTF0));
|
||||
ctx->intf_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
mdss_mdp_fetch_start_config(ctx, ctl);
|
||||
}
|
||||
|
||||
mdp_video_write(ctx, MDSS_MDP_REG_INTF_PANEL_FORMAT, ctl->dst_format);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
|
||||
struct mdss_panel_data *pdata, int inum)
|
||||
{
|
||||
struct mdss_data_type *mdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
struct mdss_mdp_video_ctx *ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (pdata == NULL)
|
||||
return 0;
|
||||
|
||||
mdata = ctl->mdata;
|
||||
pinfo = &pdata->panel_info;
|
||||
|
||||
if (inum < mdata->nintf) {
|
||||
ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + inum;
|
||||
if (ctx->ref_cnt) {
|
||||
pr_err("Intf %d already in use\n",
|
||||
(inum + MDSS_MDP_INTF0));
|
||||
return -EBUSY;
|
||||
}
|
||||
pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
|
||||
ctx->ref_cnt++;
|
||||
} else {
|
||||
pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctl->intf_ctx[MASTER_CTX] = ctx;
|
||||
ret = mdss_mdp_video_ctx_setup(ctl, ctx, pinfo);
|
||||
if (ret) {
|
||||
pr_err("Video context setup failed for interface: %d\n",
|
||||
ctx->intf_num);
|
||||
ctx->ref_cnt--;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (is_pingpong_split(ctl->mfd)) {
|
||||
if ((inum + 1) >= mdata->nintf) {
|
||||
pr_err("Intf not available for ping pong split: (%d)\n",
|
||||
(inum + 1 + MDSS_MDP_INTF0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) +
|
||||
inum + 1;
|
||||
if (ctx->ref_cnt) {
|
||||
pr_err("Intf %d already in use\n",
|
||||
(inum + MDSS_MDP_INTF0));
|
||||
return -EBUSY;
|
||||
}
|
||||
pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
|
||||
ctx->ref_cnt++;
|
||||
|
||||
ctl->intf_ctx[SLAVE_CTX] = ctx;
|
||||
pinfo = &pdata->next->panel_info;
|
||||
ret = mdss_mdp_video_ctx_setup(ctl, ctx, pinfo);
|
||||
if (ret) {
|
||||
pr_err("Video context setup failed for interface: %d\n",
|
||||
ctx->intf_num);
|
||||
ctx->ref_cnt--;
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue