msm: mdss: handle multiple MDP interrupt register sets

This change enhances the existing MDP ISR routine handlers
to handle multiple MDP register sets. Maintain IRQ
handlers and callbacks in a single file.

Change-Id: Iea6e77be1eaab5ccf2fd89f7c98e2dd328af7de0
Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org>
This commit is contained in:
Jeykumar Sankaran 2016-03-09 15:03:00 -08:00 committed by Kyle Yan
parent 8e11c85eb8
commit 1e1bf68fa5
8 changed files with 417 additions and 388 deletions

View file

@ -338,7 +338,7 @@ struct mdss_data_type {
u32 default_ot_wr_limit;
struct irq_domain *irq_domain;
u32 mdp_irq_mask;
u32 *mdp_irq_mask;
u32 mdp_hist_irq_mask;
int suspend_fs_ena;

View file

@ -89,6 +89,7 @@ struct msm_mdp_interface mdp5 = {
#define MEM_PROTECT_SD_CTRL_FLAT 0x14
static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_SPINLOCK(mdss_mdp_intr_lock);
static DEFINE_MUTEX(mdp_clk_lock);
static DEFINE_MUTEX(mdp_iommu_ref_cnt_lock);
static DEFINE_MUTEX(mdp_fs_idle_pc_lock);
@ -149,6 +150,83 @@ u32 invalid_mdp107_wb_output_fmts[] = {
MDP_BGRX_8888,
};
/*
* struct intr_call - array of intr handlers
* @func: intr handler
* @arg: requested argument to the handler
*/
struct intr_callback {
void (*func)(void *);
void *arg;
};
/*
* struct mdss_mdp_intr_reg - array of MDP intr register sets
* @clr_off: offset to CLEAR reg
* @en_off: offset to ENABLE reg
* @status_off: offset to STATUS reg
*/
struct mdss_mdp_intr_reg {
u32 clr_off;
u32 en_off;
u32 status_off;
};
/*
* struct mdss_mdp_irq - maps each irq with i/f
* @intr_type: type of interface
* @intf_num: i/f the irq is associated with
* @irq_mask: corresponding bit in the reg set
* @reg_idx: which reg set to program
*/
struct mdss_mdp_irq {
u32 intr_type;
u32 intf_num;
u32 irq_mask;
u32 reg_idx;
};
static struct mdss_mdp_intr_reg mdp_intr_reg[] = {
{ MDSS_MDP_REG_INTR_CLEAR, MDSS_MDP_REG_INTR_EN,
MDSS_MDP_REG_INTR_STATUS },
{ MDSS_MDP_REG_INTR2_CLEAR, MDSS_MDP_REG_INTR2_EN,
MDSS_MDP_REG_INTR2_STATUS }
};
static struct mdss_mdp_irq mdp_irq_map[] = {
{ MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 1, MDSS_MDP_INTR_INTF_0_UNDERRUN, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 2, MDSS_MDP_INTR_INTF_1_UNDERRUN, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 3, MDSS_MDP_INTR_INTF_2_UNDERRUN, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 4, MDSS_MDP_INTR_INTF_3_UNDERRUN, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 1, MDSS_MDP_INTR_INTF_0_VSYNC, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 2, MDSS_MDP_INTR_INTF_1_VSYNC, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 3, MDSS_MDP_INTR_INTF_2_VSYNC, 0},
{ MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 4, MDSS_MDP_INTR_INTF_3_VSYNC, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 0, MDSS_MDP_INTR_PING_PONG_0_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 1, MDSS_MDP_INTR_PING_PONG_1_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 2, MDSS_MDP_INTR_PING_PONG_2_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 3, MDSS_MDP_INTR_PING_PONG_3_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 0, MDSS_MDP_INTR_PING_PONG_0_RD_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 1, MDSS_MDP_INTR_PING_PONG_1_RD_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 2, MDSS_MDP_INTR_PING_PONG_2_RD_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 3, MDSS_MDP_INTR_PING_PONG_3_RD_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 0, MDSS_MDP_INTR_PING_PONG_0_WR_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 1, MDSS_MDP_INTR_PING_PONG_1_WR_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 2, MDSS_MDP_INTR_PING_PONG_2_WR_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 3, MDSS_MDP_INTR_PING_PONG_3_WR_PTR, 0},
{ MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, 0, MDSS_MDP_INTR_WB_0_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, 1, MDSS_MDP_INTR_WB_1_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_WB_WFD_COMP, 0, MDSS_MDP_INTR_WB_2_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 0, MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 1, MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 2, MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 3, MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0},
{ MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 2, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1},
{ MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 3, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1}
};
static struct intr_callback *mdp_intr_cb;
static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on);
static int mdss_mdp_parse_dt(struct platform_device *pdev);
static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev);
@ -157,9 +235,9 @@ static int mdss_mdp_parse_dt_wb(struct platform_device *pdev);
static int mdss_mdp_parse_dt_ctl(struct platform_device *pdev);
static int mdss_mdp_parse_dt_video_intf(struct platform_device *pdev);
static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
char *prop_name, u32 *offsets, int len);
char *prop_name, u32 *offsets, int len);
static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
char *prop_name);
char *prop_name);
static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev);
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
@ -168,6 +246,21 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev);
static int mdss_mdp_parse_dt_cdm(struct platform_device *pdev);
static int mdss_mdp_parse_dt_dsc(struct platform_device *pdev);
static inline u32 is_mdp_irq_enabled(void)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
int i;
for (i = 0; i < ARRAY_SIZE(mdp_intr_reg); i++)
if (mdata->mdp_irq_mask[i] != 0)
return 1;
if (mdata->mdp_hist_irq_mask)
return 1;
return 0;
}
u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
{
/* The adreno GPU hardware requires that the pitch be aligned to
@ -612,12 +705,23 @@ int mdss_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx)
#endif
static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num)
static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num)
{
if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN ||
intr_type == MDSS_MDP_IRQ_INTF_VSYNC)
intf_num = (intf_num - MDSS_MDP_INTF0) * 2;
return 1 << (intr_type + intf_num);
int i;
for (i = 0; i < ARRAY_SIZE(mdp_irq_map); i++) {
if (intr_type == mdp_irq_map[i].intr_type &&
intf_num == mdp_irq_map[i].intf_num)
return i;
}
return -EINVAL;
}
u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num)
{
int idx = mdss_mdp_intr2index(intr_type, intf_num);
return (idx < 0) ? 0 : mdp_irq_map[idx].irq_mask;
}
/* function assumes that mdp is clocked to access hw registers */
@ -625,38 +729,55 @@ void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
u32 intr_type, u32 intf_num)
{
unsigned long irq_flags;
u32 irq;
int irq_idx;
struct mdss_mdp_intr_reg reg;
struct mdss_mdp_irq irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
irq_idx = mdss_mdp_intr2index(intr_type, intf_num);
if (irq_idx < 0) {
pr_err("invalid irq request\n");
return;
}
pr_debug("clearing mdp irq mask=%x\n", irq);
irq = mdp_irq_map[irq_idx];
reg = mdp_intr_reg[irq.reg_idx];
pr_debug("clearing mdp irq mask=%x\n", irq.irq_mask);
spin_lock_irqsave(&mdp_lock, irq_flags);
writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off);
spin_unlock_irqrestore(&mdp_lock, irq_flags);
}
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
{
u32 irq;
int irq_idx, idx;
unsigned long irq_flags;
int ret = 0;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_intr_reg reg;
struct mdss_mdp_irq irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
irq_idx = mdss_mdp_intr2index(intr_type, intf_num);
if (irq_idx < 0) {
pr_err("invalid irq request\n");
return -EINVAL;
}
irq = mdp_irq_map[irq_idx];
reg = mdp_intr_reg[irq.reg_idx];
spin_lock_irqsave(&mdp_lock, irq_flags);
if (mdata->mdp_irq_mask & irq) {
if (mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask) {
pr_warn("MDSS MDP IRQ-0x%x is already set, mask=%x\n",
irq, mdata->mdp_irq_mask);
irq.irq_mask, mdata->mdp_irq_mask[idx]);
ret = -EBUSY;
} else {
pr_debug("MDP IRQ mask old=%x new=%x\n",
mdata->mdp_irq_mask, irq);
mdata->mdp_irq_mask |= irq;
writel_relaxed(irq, mdata->mdp_base +
MDSS_MDP_REG_INTR_CLEAR);
writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base +
MDSS_MDP_REG_INTR_EN);
mdata->mdp_irq_mask[irq.reg_idx], irq.irq_mask);
mdata->mdp_irq_mask[irq.reg_idx] |= irq.irq_mask;
writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off);
writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx],
mdata->mdp_base + reg.en_off);
mdata->mdss_util->enable_irq(&mdss_mdp_hw);
}
spin_unlock_irqrestore(&mdp_lock, irq_flags);
@ -673,7 +794,7 @@ int mdss_mdp_hist_irq_enable(u32 irq)
irq, mdata->mdp_hist_irq_mask);
ret = -EBUSY;
} else {
pr_debug("MDP IRQ mask old=%x new=%x\n",
pr_debug("mask old=%x new=%x\n",
mdata->mdp_hist_irq_mask, irq);
mdata->mdp_hist_irq_mask |= irq;
writel_relaxed(irq, mdata->mdp_base +
@ -688,47 +809,61 @@ int mdss_mdp_hist_irq_enable(u32 irq)
void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num)
{
u32 irq;
int irq_idx;
unsigned long irq_flags;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_intr_reg reg;
struct mdss_mdp_irq irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
irq_idx = mdss_mdp_intr2index(intr_type, intf_num);
if (irq_idx < 0) {
pr_err("invalid irq request\n");
return;
}
irq = mdp_irq_map[irq_idx];
reg = mdp_intr_reg[irq.reg_idx];
spin_lock_irqsave(&mdp_lock, irq_flags);
if (!(mdata->mdp_irq_mask & irq)) {
if (!(mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask)) {
pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
irq, mdata->mdp_irq_mask);
irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]);
} else {
mdata->mdp_irq_mask &= ~irq;
writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base +
MDSS_MDP_REG_INTR_EN);
if ((mdata->mdp_irq_mask == 0) &&
(mdata->mdp_hist_irq_mask == 0))
mdata->mdp_irq_mask[irq.reg_idx] &= ~irq.irq_mask;
writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx],
mdata->mdp_base + reg.en_off);
if (!is_mdp_irq_enabled())
mdata->mdss_util->disable_irq(&mdss_mdp_hw);
}
spin_unlock_irqrestore(&mdp_lock, irq_flags);
}
/*
* This function is used to check and clear the status of
* INTR and does not handle INTR2 and HIST_INTR
*/
/* This function is used to check and clear the status of MDP interrupts */
void mdss_mdp_intr_check_and_clear(u32 intr_type, u32 intf_num)
{
u32 status, irq;
u32 status;
int irq_idx;
unsigned long irq_flags;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_intr_reg reg;
struct mdss_mdp_irq irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
irq_idx = mdss_mdp_intr2index(intr_type, intf_num);
if (irq_idx < 0) {
pr_err("invalid irq request\n");
return;
}
irq = mdp_irq_map[irq_idx];
reg = mdp_intr_reg[irq.reg_idx];
spin_lock_irqsave(&mdp_lock, irq_flags);
status = irq & readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_INTR_STATUS);
status = irq.irq_mask & readl_relaxed(mdata->mdp_base +
reg.status_off);
if (status) {
pr_debug("clearing irq: intr_type:%d, intf_num:%d\n",
intr_type, intf_num);
writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off);
}
spin_unlock_irqrestore(&mdp_lock, irq_flags);
}
@ -744,8 +879,7 @@ void mdss_mdp_hist_irq_disable(u32 irq)
mdata->mdp_hist_irq_mask &= ~irq;
writel_relaxed(mdata->mdp_hist_irq_mask, mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_EN);
if ((mdata->mdp_irq_mask == 0) &&
(mdata->mdp_hist_irq_mask == 0))
if (!is_mdp_irq_enabled())
mdata->mdss_util->disable_irq(&mdss_mdp_hw);
}
}
@ -762,24 +896,163 @@ void mdss_mdp_hist_irq_disable(u32 irq)
*/
void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num)
{
u32 irq;
int irq_idx;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_intr_reg reg;
struct mdss_mdp_irq irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
irq_idx = mdss_mdp_intr2index(intr_type, intf_num);
if (irq_idx < 0) {
pr_err("invalid irq request\n");
return;
}
if (!(mdata->mdp_irq_mask & irq)) {
irq = mdp_irq_map[irq_idx];
reg = mdp_intr_reg[irq.reg_idx];
if (!(mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask)) {
pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
irq, mdata->mdp_irq_mask);
irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]);
} else {
mdata->mdp_irq_mask &= ~irq;
writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base +
MDSS_MDP_REG_INTR_EN);
if ((mdata->mdp_irq_mask == 0) &&
(mdata->mdp_hist_irq_mask == 0))
mdata->mdp_irq_mask[irq.reg_idx] &= ~irq.irq_mask;
writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx],
mdata->mdp_base + reg.en_off);
if (!is_mdp_irq_enabled())
mdata->mdss_util->disable_irq_nosync(&mdss_mdp_hw);
}
}
int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg)
{
unsigned long flags;
int index;
index = mdss_mdp_intr2index(intr_type, intf_num);
if (index < 0) {
pr_warn("invalid intr type=%u intf_numf_num=%u\n",
intr_type, intf_num);
return -EINVAL;
}
spin_lock_irqsave(&mdss_mdp_intr_lock, flags);
WARN(mdp_intr_cb[index].func && fnc_ptr,
"replacing current intr callback for ndx=%d\n", index);
mdp_intr_cb[index].func = fnc_ptr;
mdp_intr_cb[index].arg = arg;
spin_unlock_irqrestore(&mdss_mdp_intr_lock, flags);
return 0;
}
int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg)
{
int index;
index = mdss_mdp_intr2index(intr_type, intf_num);
if (index < 0) {
pr_warn("invalid intr Typee=%u intf_num=%u\n",
intr_type, intf_num);
return -EINVAL;
}
WARN(mdp_intr_cb[index].func && fnc_ptr,
"replacing current intr callbackack for ndx=%d\n",
index);
mdp_intr_cb[index].func = fnc_ptr;
mdp_intr_cb[index].arg = arg;
return 0;
}
static inline void mdss_mdp_intr_done(int index)
{
void (*fnc)(void *);
void *arg;
spin_lock(&mdss_mdp_intr_lock);
fnc = mdp_intr_cb[index].func;
arg = mdp_intr_cb[index].arg;
spin_unlock(&mdss_mdp_intr_lock);
if (fnc)
fnc(arg);
}
irqreturn_t mdss_mdp_isr(int irq, void *ptr)
{
struct mdss_data_type *mdata = ptr;
u32 isr, mask, hist_isr, hist_mask;
int i, j;
if (!mdata->clk_ena)
return IRQ_HANDLED;
for (i = 0; i < ARRAY_SIZE(mdp_intr_reg); i++) {
struct mdss_mdp_intr_reg reg = mdp_intr_reg[i];
isr = readl_relaxed(mdata->mdp_base + reg.status_off);
if (isr == 0)
continue;
mask = readl_relaxed(mdata->mdp_base + reg.en_off);
writel_relaxed(isr, mdata->mdp_base + reg.clr_off);
pr_debug("%s: reg:%d isr=%x mask=%x\n",
__func__, i+1, isr, mask);
isr &= mask;
if (isr == 0)
continue;
for (j = 0; j < ARRAY_SIZE(mdp_irq_map); j++)
if (mdp_irq_map[j].reg_idx == i &&
(isr & mdp_irq_map[j].irq_mask))
mdss_mdp_intr_done(j);
if (!i) {
if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, false);
if (isr & MDSS_MDP_INTR_PING_PONG_1_DONE)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, false);
if (isr & MDSS_MDP_INTR_INTF_0_VSYNC)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP, true);
if (isr & MDSS_MDP_INTR_INTF_1_VSYNC)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, true);
if (isr & MDSS_MDP_INTR_INTF_2_VSYNC)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, true);
if (isr & MDSS_MDP_INTR_INTF_3_VSYNC)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI, true);
if (isr & MDSS_MDP_INTR_WB_0_DONE)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
if (isr & MDSS_MDP_INTR_WB_1_DONE)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
if (isr & MDSS_MDP_INTR_WB_2_DONE)
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
}
}
hist_isr = readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_STATUS);
if (hist_isr != 0) {
hist_mask = readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_EN);
writel_relaxed(hist_isr, mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_CLEAR);
hist_isr &= hist_mask;
if (hist_isr != 0)
mdss_mdp_hist_intr_done(hist_isr);
}
return IRQ_HANDLED;
}
static int mdss_mdp_clk_update(u32 clk_idx, u32 enable)
{
int ret = -ENODEV;
@ -2366,6 +2639,16 @@ static int mdss_mdp_probe(struct platform_device *pdev)
if (!display_on)
mdss_mdp_footswitch_ctrl_splash(false);
mdp_intr_cb = kcalloc(ARRAY_SIZE(mdp_irq_map),
sizeof(struct intr_callback), GFP_KERNEL);
if (mdp_intr_cb == NULL)
return -ENOMEM;
mdss_res->mdp_irq_mask = kcalloc(ARRAY_SIZE(mdp_intr_reg),
sizeof(u32), GFP_KERNEL);
if (mdss_res->mdp_irq_mask == NULL)
return -ENOMEM;
pr_info("mdss version = 0x%x, bootloader display is %s\n",
mdata->mdp_rev, display_on ? "on" : "off");

View file

@ -1388,6 +1388,7 @@ int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg);
int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg);
u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num);
void mdss_mdp_footswitch_ctrl_splash(int on);
void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable);

View file

@ -60,6 +60,9 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val)
#define MDSS_MDP_REG_HW_VERSION 0x0
#define MDSS_MDP_REG_DISP_INTF_SEL 0x00004
#define MDSS_MDP_REG_INTR2_EN 0x00008
#define MDSS_MDP_REG_INTR2_STATUS 0x0000C
#define MDSS_MDP_REG_INTR2_CLEAR 0x0002C
#define MDSS_MDP_REG_INTR_EN 0x00010
#define MDSS_MDP_REG_INTR_STATUS 0x00014
#define MDSS_MDP_REG_INTR_CLEAR 0x00018
@ -115,6 +118,9 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val)
#define MDSS_MDP_INTR_INTF_3_UNDERRUN BIT(30)
#define MDSS_MDP_INTR_INTF_3_VSYNC BIT(31)
#define MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW BIT(14)
#define MDSS_MDP_INTR2_PING_PONG_3_CWB_OVERFLOW BIT(15)
#define MDSS_MDP_HIST_INTR_VIG_0_DONE BIT(0)
#define MDSS_MDP_HIST_INTR_VIG_0_RESET_DONE BIT(1)
#define MDSS_MDP_HIST_INTR_VIG_1_DONE BIT(4)
@ -133,14 +139,15 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val)
#define MDSS_MDP_HIST_INTR_DSPP_3_RESET_DONE BIT(23)
enum mdss_mdp_intr_type {
MDSS_MDP_IRQ_WB_ROT_COMP = 0,
MDSS_MDP_IRQ_WB_WFD = 4,
MDSS_MDP_IRQ_PING_PONG_COMP = 8,
MDSS_MDP_IRQ_PING_PONG_RD_PTR = 12,
MDSS_MDP_IRQ_PING_PONG_WR_PTR = 16,
MDSS_MDP_IRQ_PING_PONG_AUTO_REF = 20,
MDSS_MDP_IRQ_INTF_UNDER_RUN = 24,
MDSS_MDP_IRQ_INTF_VSYNC = 25,
MDSS_MDP_IRQ_TYPE_WB_ROT_COMP,
MDSS_MDP_IRQ_TYPE_WB_WFD_COMP,
MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW,
};
#define MDSS_MDP_REG_IGC_VIG_BASE 0x200

View file

@ -1124,10 +1124,11 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event)
spin_lock_irqsave(&ctx->koff_lock, flags);
if (reset_done && atomic_add_unless(&ctx->koff_cnt, -1, 0)) {
pr_debug("%s: intf_num=%d\n", __func__, ctx->ctl->intf_num);
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
mdss_mdp_set_intr_callback_nosync(
MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
if (mdss_mdp_cmd_do_notifier(ctx))
notify_frame_timeout = true;
}
@ -1163,9 +1164,9 @@ static void mdss_mdp_cmd_pingpong_done(void *arg)
spin_lock(&ctx->koff_lock);
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
@ -1237,18 +1238,18 @@ static int mdss_mdp_setup_lineptr(struct mdss_mdp_cmd_ctx *ctx,
if (enable) {
/* enable clocks and irq */
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
ctx->default_pp_num);
} else {
/* disable clocks and irq */
mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
ctx->default_pp_num);
/*
* check the intr status and clear the irq before
* disabling the clocks
*/
mdss_mdp_intr_check_and_clear(
MDSS_MDP_IRQ_PING_PONG_WR_PTR,
MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
ctx->default_pp_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
@ -1392,9 +1393,9 @@ static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
return;
}
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
@ -1688,18 +1689,18 @@ static int mdss_mdp_setup_vsync(struct mdss_mdp_cmd_ctx *ctx,
if (enable) {
/* enable clocks and irq */
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
ctx->default_pp_num);
} else {
/* disable clocks and irq */
mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
ctx->default_pp_num);
/*
* check the intr status and clear the irq before
* disabling the clocks
*/
mdss_mdp_intr_check_and_clear(
MDSS_MDP_IRQ_PING_PONG_RD_PTR,
MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
ctx->default_pp_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
@ -1864,14 +1865,15 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
if (rc <= 0) {
u32 status, mask;
mask = BIT(MDSS_MDP_IRQ_PING_PONG_COMP + ctx->current_pp_num);
mask = mdss_mdp_get_irq_mask(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
status = mask & readl_relaxed(ctl->mdata->mdp_base +
MDSS_MDP_REG_INTR_STATUS);
MDSS_XLOG(status, rc, atomic_read(&ctx->koff_cnt));
if (status) {
pr_warn("pp done but irq not triggered\n");
mdss_mdp_irq_clear(ctl->mdata,
MDSS_MDP_IRQ_PING_PONG_COMP,
MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
local_irq_save(flags);
mdss_mdp_cmd_pingpong_done(ctl);
@ -1902,10 +1904,11 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
ctx->pp_timeout_report_cnt++;
rc = -EPERM;
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
mdss_mdp_set_intr_callback_nosync(
MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num, NULL, NULL);
if (atomic_add_unless(&ctx->koff_cnt, -1, 0)
&& mdss_mdp_cmd_do_notifier(ctx))
mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
@ -2277,7 +2280,7 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl)
static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
{
int rc;
u32 val, line_out, intr_type = MDSS_MDP_IRQ_PING_PONG_COMP;
u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
char __iomem *pp_base = ctl->mixer_left->pingpong_base;
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
@ -2301,7 +2304,7 @@ static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
MDSS_MDP_REG_PP_LINE_COUNT);
if (val == ctl->mixer_left->roi.h) {
mdss_mdp_irq_clear(ctl->mdata,
MDSS_MDP_IRQ_PING_PONG_COMP,
MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
mdss_mdp_irq_disable_nosync(intr_type,
ctx->current_pp_num);
@ -2329,9 +2332,9 @@ static void mdss_mdp_cmd_autorefresh_done(void *arg)
return;
}
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num, NULL, NULL);
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
@ -2400,9 +2403,9 @@ static void mdss_mdp_cmd_wait4_autorefresh_done(struct mdss_mdp_ctl *ctl)
reinit_completion(&ctx->autorefresh_done);
/* enable autorefresh done */
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num, mdss_mdp_cmd_autorefresh_done, ctl);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num);
/*
@ -2420,22 +2423,23 @@ static void mdss_mdp_cmd_wait4_autorefresh_done(struct mdss_mdp_ctl *ctl)
if (rc <= 0) {
u32 status, mask;
mask = BIT(MDSS_MDP_IRQ_PING_PONG_AUTO_REF +
ctx->current_pp_num);
mask = mdss_mdp_get_irq_mask(
MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num);
status = mask & readl_relaxed(ctl->mdata->mdp_base +
MDSS_MDP_REG_INTR_STATUS);
if (status) {
pr_warn("autorefresh done but irq not triggered\n");
mdss_mdp_irq_clear(ctl->mdata,
MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num);
local_irq_save(flags);
mdss_mdp_irq_disable_nosync(
MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num);
mdss_mdp_set_intr_callback_nosync(
MDSS_MDP_IRQ_PING_PONG_AUTO_REF,
MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF,
ctx->current_pp_num, NULL, NULL);
local_irq_restore(flags);
rc = 1;
@ -2663,13 +2667,14 @@ static int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
mdss_mdp_disable_autorefresh(ctl, sctl);
}
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num, mdss_mdp_cmd_pingpong_done, ctl);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->current_pp_num);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->current_pp_num);
if (sctx) {
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
sctx->current_pp_num, mdss_mdp_cmd_pingpong_done, sctl);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
sctx->current_pp_num);
}
@ -2805,11 +2810,11 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl,
return 0;
}
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
ctx->default_pp_num, NULL, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
ctx->default_pp_num, NULL, NULL);
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
ctx->default_pp_num, NULL, NULL);
memset(ctx, 0, sizeof(*ctx));
@ -3140,10 +3145,10 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
default_pp_num, aux_pp_num);
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR,
ctx->default_pp_num, mdss_mdp_cmd_readptr_done, ctl);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR,
ctx->default_pp_num, mdss_mdp_cmd_writeptr_done, ctl);
ret = mdss_mdp_cmd_tearcheck_setup(ctx, false);

View file

@ -34,9 +34,6 @@
/* Filter out input events for 1 vsync time after receiving an input event*/
#define INPUT_EVENT_HANDLER_DELAY_USECS 16000
#define MDP_INTR_MASK_INTF_VSYNC(intf_num) \
(1 << (2 * (intf_num - MDSS_MDP_INTF0) + MDSS_MDP_IRQ_INTF_VSYNC))
/* intf timing settings */
struct intf_timing_params {
u32 width;
@ -354,9 +351,10 @@ static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
mutex_lock(&ctx->vsync_mtx);
if (atomic_inc_return(&ctx->vsync_ref) == 1)
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctl->intf_num);
else if (clear)
mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctl->intf_num);
mutex_unlock(&ctx->vsync_mtx);
}
@ -367,7 +365,8 @@ static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
mutex_lock(&ctx->vsync_mtx);
if (atomic_dec_return(&ctx->vsync_ref) == 0)
mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctl->intf_num);
mutex_unlock(&ctx->vsync_mtx);
}
@ -450,11 +449,11 @@ void mdss_mdp_turn_off_time_engine(struct mdss_mdp_ctl *ctl,
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
ctx->timegen_en = false;
mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, ctl->intf_num);
sctl = mdss_mdp_get_split_ctl(ctl);
if (sctl)
mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
sctl->intf_num);
}
@ -489,9 +488,9 @@ static int mdss_mdp_video_ctx_stop(struct mdss_mdp_ctl *ctl,
mdss_bus_bandwidth_ctrl(false);
}
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctx->intf_num, NULL, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
ctx->intf_num, NULL, NULL);
ctx->ref_cnt--;
@ -614,7 +613,8 @@ static int mdss_mdp_video_pollwait(struct mdss_mdp_ctl *ctl)
u32 mask, status;
int rc;
mask = MDP_INTR_MASK_INTF_VSYNC(ctl->intf_num);
mask = mdss_mdp_get_irq_mask(MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctl->intf_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
rc = readl_poll_timeout(ctl->mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS,
@ -1140,10 +1140,11 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
ctl->intf_num);
sctl = mdss_mdp_get_split_ctl(ctl);
if (sctl)
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
sctl->intf_num);
mdss_bus_bandwidth_ctrl(true);
@ -1447,10 +1448,10 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl,
if (pinfo->compression_mode == COMPRESSION_DSC)
dsc = &pinfo->dsc;
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_VSYNC,
ctx->intf_num, mdss_mdp_video_vsync_intr_done,
ctl);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN,
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN,
ctx->intf_num,
mdss_mdp_video_underrun_intr_done, ctl);

View file

@ -76,7 +76,7 @@ struct mdss_mdp_writeback_ctx {
static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
{
.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
.intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP,
.intf_num = 0,
.xin_id = 3,
.clk_ctrl.reg_off = 0x2BC,
@ -84,7 +84,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
},
{
.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
.intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP,
.intf_num = 1,
.xin_id = 11,
.clk_ctrl.reg_off = 0x2BC,
@ -92,7 +92,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
},
{
.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
.intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP,
.intf_num = 0,
.xin_id = 3,
.clk_ctrl.reg_off = 0x2BC,
@ -100,7 +100,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
},
{
.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
.intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP,
.intf_num = 1,
.xin_id = 11,
.clk_ctrl.reg_off = 0x2BC,
@ -108,7 +108,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
},
{
.type = MDSS_MDP_WRITEBACK_TYPE_WFD,
.intr_type = MDSS_MDP_IRQ_WB_WFD,
.intr_type = MDSS_MDP_IRQ_TYPE_WB_WFD_COMP,
.intf_num = 0,
.xin_id = 6,
.clk_ctrl.reg_off = 0x2BC,
@ -889,7 +889,7 @@ int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl)
/* WB2 Intr Enable is BIT(2) in MDSS 1.8.0 */
if (ctl->mdata->mdp_rev == MDSS_MDP_HW_REV_108) {
ctx->intr_type = MDSS_MDP_IRQ_WB_ROT_COMP;
ctx->intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP;
ctx->intf_num = 2;
}
}

View file

@ -32,274 +32,6 @@
#define PHY_ADDR_4G (1ULL<<32)
enum {
MDP_INTR_VSYNC_INTF_0,
MDP_INTR_VSYNC_INTF_1,
MDP_INTR_VSYNC_INTF_2,
MDP_INTR_VSYNC_INTF_3,
MDP_INTR_UNDERRUN_INTF_0,
MDP_INTR_UNDERRUN_INTF_1,
MDP_INTR_UNDERRUN_INTF_2,
MDP_INTR_UNDERRUN_INTF_3,
MDP_INTR_PING_PONG_0,
MDP_INTR_PING_PONG_1,
MDP_INTR_PING_PONG_2,
MDP_INTR_PING_PONG_3,
MDP_INTR_PING_PONG_0_RD_PTR,
MDP_INTR_PING_PONG_1_RD_PTR,
MDP_INTR_PING_PONG_2_RD_PTR,
MDP_INTR_PING_PONG_3_RD_PTR,
MDP_INTR_PING_PONG_0_WR_PTR,
MDP_INTR_PING_PONG_1_WR_PTR,
MDP_INTR_PING_PONG_2_WR_PTR,
MDP_INTR_PING_PONG_3_WR_PTR,
MDP_INTR_WB_0,
MDP_INTR_WB_1,
MDP_INTR_WB_2,
MDP_INTR_PING_PONG_0_AUTO_REF,
MDP_INTR_PING_PONG_1_AUTO_REF,
MDP_INTR_PING_PONG_2_AUTO_REF,
MDP_INTR_PING_PONG_3_AUTO_REF,
MDP_INTR_MAX,
};
struct intr_callback {
void (*func)(void *);
void *arg;
};
struct intr_callback mdp_intr_cb[MDP_INTR_MAX];
static DEFINE_SPINLOCK(mdss_mdp_intr_lock);
static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num)
{
int index = -1;
switch (intr_type) {
case MDSS_MDP_IRQ_INTF_UNDER_RUN:
index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0);
break;
case MDSS_MDP_IRQ_INTF_VSYNC:
index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0);
break;
case MDSS_MDP_IRQ_PING_PONG_COMP:
index = MDP_INTR_PING_PONG_0 + intf_num;
break;
case MDSS_MDP_IRQ_PING_PONG_RD_PTR:
index = MDP_INTR_PING_PONG_0_RD_PTR + intf_num;
break;
case MDSS_MDP_IRQ_PING_PONG_WR_PTR:
index = MDP_INTR_PING_PONG_0_WR_PTR + intf_num;
break;
case MDSS_MDP_IRQ_WB_ROT_COMP:
index = MDP_INTR_WB_0 + intf_num;
break;
case MDSS_MDP_IRQ_WB_WFD:
index = MDP_INTR_WB_2 + intf_num;
break;
case MDSS_MDP_IRQ_PING_PONG_AUTO_REF:
index = MDP_INTR_PING_PONG_0_AUTO_REF + intf_num;
break;
}
return index;
}
int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg)
{
unsigned long flags;
int index;
index = mdss_mdp_intr2index(intr_type, intf_num);
if (index < 0) {
pr_warn("invalid intr type=%u intf_num=%u\n",
intr_type, intf_num);
return -EINVAL;
}
spin_lock_irqsave(&mdss_mdp_intr_lock, flags);
WARN(mdp_intr_cb[index].func && fnc_ptr,
"replacing current intr callback for ndx=%d\n", index);
mdp_intr_cb[index].func = fnc_ptr;
mdp_intr_cb[index].arg = arg;
spin_unlock_irqrestore(&mdss_mdp_intr_lock, flags);
return 0;
}
int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num,
void (*fnc_ptr)(void *), void *arg)
{
int index;
index = mdss_mdp_intr2index(intr_type, intf_num);
if (index < 0) {
pr_warn("invalid intr type=%u intf_num=%u\n",
intr_type, intf_num);
return -EINVAL;
}
WARN(mdp_intr_cb[index].func && fnc_ptr,
"replacing current intr callback for ndx=%d\n", index);
mdp_intr_cb[index].func = fnc_ptr;
mdp_intr_cb[index].arg = arg;
return 0;
}
static inline void mdss_mdp_intr_done(int index)
{
void (*fnc)(void *);
void *arg;
spin_lock(&mdss_mdp_intr_lock);
fnc = mdp_intr_cb[index].func;
arg = mdp_intr_cb[index].arg;
spin_unlock(&mdss_mdp_intr_lock);
if (fnc)
fnc(arg);
}
irqreturn_t mdss_mdp_isr(int irq, void *ptr)
{
struct mdss_data_type *mdata = ptr;
u32 isr, mask, hist_isr, hist_mask;
if (!mdata->clk_ena)
return IRQ_HANDLED;
isr = readl_relaxed(mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS);
if (isr == 0)
goto mdp_isr_done;
mask = readl_relaxed(mdata->mdp_base + MDSS_MDP_REG_INTR_EN);
writel_relaxed(isr, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
pr_debug("%s: isr=%x mask=%x\n", __func__, isr, mask);
isr &= mask;
if (isr == 0)
goto mdp_isr_done;
if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN)
mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0);
if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN)
mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1);
if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN)
mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2);
if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN)
mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3);
if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE) {
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, false);
}
if (isr & MDSS_MDP_INTR_PING_PONG_1_DONE) {
mdss_mdp_intr_done(MDP_INTR_PING_PONG_1);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, false);
}
if (isr & MDSS_MDP_INTR_PING_PONG_2_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_2);
if (isr & MDSS_MDP_INTR_PING_PONG_3_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_3);
if (isr & MDSS_MDP_INTR_PING_PONG_0_RD_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_RD_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_1_RD_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_RD_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_2_RD_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_RD_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_3_RD_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_RD_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_0_WR_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_WR_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_1_WR_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_WR_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_2_WR_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_WR_PTR);
if (isr & MDSS_MDP_INTR_PING_PONG_3_WR_PTR)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_WR_PTR);
if (isr & MDSS_MDP_INTR_INTF_0_VSYNC) {
mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP, true);
}
if (isr & MDSS_MDP_INTR_INTF_1_VSYNC) {
mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_1);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, true);
}
if (isr & MDSS_MDP_INTR_INTF_2_VSYNC) {
mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_2);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, true);
}
if (isr & MDSS_MDP_INTR_INTF_3_VSYNC) {
mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_3);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI, true);
}
if (isr & MDSS_MDP_INTR_WB_0_DONE) {
mdss_mdp_intr_done(MDP_INTR_WB_0);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
}
if (isr & MDSS_MDP_INTR_WB_1_DONE) {
mdss_mdp_intr_done(MDP_INTR_WB_1);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
}
if (isr & ((mdata->mdp_rev == MDSS_MDP_HW_REV_108) ?
MDSS_MDP_INTR_WB_2_DONE >> 2 : MDSS_MDP_INTR_WB_2_DONE)) {
mdss_mdp_intr_done(MDP_INTR_WB_2);
mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true);
}
if (isr & MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_AUTO_REF);
if (isr & MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_AUTO_REF);
if (isr & MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_AUTO_REF);
if (isr & MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_AUTO_REF);
mdp_isr_done:
hist_isr = readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_STATUS);
if (hist_isr == 0)
goto hist_isr_done;
hist_mask = readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_EN);
writel_relaxed(hist_isr, mdata->mdp_base +
MDSS_MDP_REG_HIST_INTR_CLEAR);
hist_isr &= hist_mask;
if (hist_isr == 0)
goto hist_isr_done;
mdss_mdp_hist_intr_done(hist_isr);
hist_isr_done:
return IRQ_HANDLED;
}
void mdss_mdp_format_flag_removal(u32 *table, u32 num, u32 remove_bits)
{
struct mdss_mdp_format_params *fmt = NULL;