disp: msm: sde: add programmable lineptr support for writeback

From MDSS 9.0, writeback supports a programmable lineptr support, which
generates an interrupt when the configured writeback output height is
reached. Add software support to configure the prog_line and to process
the interrupt.

Change-Id: I3293ad2984c51417e4691c5b11e9c9a010067e1c
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Veera Sundaram Sankaran
2021-07-07 11:21:29 -07:00
父節點 0cf7ba9a4a
當前提交 95300ca3df
共有 8 個文件被更改,包括 98 次插入0 次删除

查看文件

@@ -205,6 +205,7 @@ struct sde_encoder_phys_ops {
* @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning
* autorefresh has triggered a double buffer flip
* @INTR_IDX_WRPTR: Writepointer start interrupt for cmd mode panel
* @INTR_IDX_WB_LINEPTR: Programmable lineptr interrupt for WB
*/
enum sde_intr_idx {
INTR_IDX_VSYNC,
@@ -221,6 +222,7 @@ enum sde_intr_idx {
INTR_IDX_PP5_OVFL,
INTR_IDX_PP_CWB_OVFL,
INTR_IDX_WRPTR,
INTR_IDX_WB_LINEPTR,
INTR_IDX_MAX,
};

查看文件

@@ -1283,6 +1283,19 @@ static void sde_encoder_phys_wb_done_irq(void *arg, int irq_idx)
_sde_encoder_phys_wb_frame_done_helper(arg, false);
}
static void sde_encoder_phys_wb_lineptr_irq(void *arg, int irq_idx)
{
struct sde_encoder_phys_wb *wb_enc = arg;
struct sde_encoder_phys *phys_enc;
if (!wb_enc)
return;
phys_enc = &wb_enc->base;
SDE_EVT32_IRQ(DRMID(phys_enc->parent), WBID(wb_enc));
}
/**
* sde_encoder_phys_wb_irq_ctrl - irq control of WB
* @phys: Pointer to physical encoder
@@ -2133,6 +2146,13 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init(
irq->intr_idx = INTR_IDX_CTL_START;
irq->cb.func = sde_encoder_phys_wb_ctl_start_irq;
irq = &phys_enc->irq[INTR_IDX_WB_LINEPTR];
irq->name = "lineptr_irq";
irq->hw_idx = wb_enc->hw_wb->idx;
irq->intr_type = SDE_IRQ_TYPE_WB_PROG_LINE;
irq->intr_idx = INTR_IDX_WB_LINEPTR;
irq->cb.func = sde_encoder_phys_wb_lineptr_irq;
if (wb_cfg && (wb_cfg->features & BIT(SDE_WB_HAS_DCWB))) {
irq = &phys_enc->irq[INTR_IDX_PP_CWB_OVFL];
irq->name = "pp_cwb0_overflow";

查看文件

@@ -1348,6 +1348,10 @@ static int _add_to_irq_offset_list(struct sde_mdss_cfg *sde_cfg,
if (instance >= LTM_MAX)
err = true;
break;
case SDE_INTR_HWBLK_WB:
if (instance >= WB_MAX)
err = true;
break;
default:
SDE_ERROR("invalid hwblk_type: %d", blk_type);
return -EINVAL;
@@ -2555,6 +2559,11 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
set_bit(SDE_WB_INPUT_CTRL, &wb->features);
if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_900))
set_bit(SDE_WB_PROG_LINE, &wb->features);
rc = _add_to_irq_offset_list(sde_cfg, SDE_INTR_HWBLK_WB, wb->id, wb->base);
if (test_bit(SDE_FEATURE_DEDICATED_CWB, sde_cfg->features)) {
set_bit(SDE_WB_HAS_DCWB, &wb->features);
if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))

查看文件

@@ -196,6 +196,7 @@ enum sde_intr_hwblk_type {
SDE_INTR_HWBLK_AD4,
SDE_INTR_HWBLK_INTF_TEAR,
SDE_INTR_HWBLK_LTM,
SDE_INTR_HWBLK_WB,
SDE_INTR_HWBLK_MAX
};
@@ -552,6 +553,7 @@ enum {
* @SDE_WB_CWB_CTRL Separate CWB control is available for configuring
* @SDE_WB_DCWB_CTRL Separate DCWB control is available for configuring
* @SDE_WB_CWB_DITHER_CTRL CWB dither is available for configuring
* @SDE_WB_PROG_LINE Writeback block supports programmable line ptr
* @SDE_WB_MAX maximum value
*/
enum {
@@ -573,6 +575,7 @@ enum {
SDE_WB_CWB_CTRL,
SDE_WB_DCWB_CTRL,
SDE_WB_CWB_DITHER_CTRL,
SDE_WB_PROG_LINE,
SDE_WB_MAX
};

查看文件

@@ -27,6 +27,9 @@
#define MDP_LTM_INTR_EN_OFF 0x50
#define MDP_LTM_INTR_STATUS_OFF 0x54
#define MDP_LTM_INTR_CLEAR_OFF 0x58
#define MDP_WB_INTR_EN_OFF 0x18C
#define MDP_WB_INTR_STATUS_OFF 0x190
#define MDP_WB_INTR_CLEAR_OFF 0x194
/**
* WB interrupt status bit definitions
@@ -193,6 +196,11 @@
#define SDE_INTR_LTM_STATS_DONE BIT(0)
#define SDE_INTR_LTM_STATS_WB_PB BIT(5)
/**
* WB interrupt status bit definitions
*/
#define SDE_INTR_WB_PROG_LINE BIT(0)
/**
* struct sde_intr_reg - array of SDE register sets
* @clr_off: offset to CLEAR reg
@@ -425,6 +433,10 @@ static struct sde_irq_type sde_irq_ltm_map[] = {
{ SDE_IRQ_TYPE_LTM_STATS_WB_PB, -1, SDE_INTR_LTM_STATS_WB_PB, -1},
};
static struct sde_irq_type sde_irq_wb_map[] = {
{ SDE_IRQ_TYPE_WB_PROG_LINE, -1, SDE_INTR_WB_PROG_LINE, -1},
};
static int sde_hw_intr_irqidx_lookup(struct sde_hw_intr *intr,
enum sde_intr_type intr_type, u32 instance_idx)
{
@@ -867,6 +879,12 @@ static int _set_sde_irq_tbl_offset(struct sde_intr_reg *sde_irq,
sde_irq->en_off = base_offset + MDP_LTM_INTR_EN_OFF;
sde_irq->status_off = base_offset + MDP_LTM_INTR_STATUS_OFF;
break;
case SDE_INTR_HWBLK_WB:
sde_irq->clr_off = base_offset + MDP_WB_INTR_CLEAR_OFF;
sde_irq->en_off = base_offset + MDP_WB_INTR_EN_OFF;
sde_irq->status_off = base_offset + MDP_WB_INTR_STATUS_OFF;
break;
default:
pr_err("unrecognized intr blk type %d\n",
item->type);
@@ -956,6 +974,9 @@ static inline u32 _get_irq_map_size(struct sde_intr_irq_offsets *item)
case SDE_INTR_HWBLK_LTM:
ret = ARRAY_SIZE(sde_irq_ltm_map);
break;
case SDE_INTR_HWBLK_WB:
ret = ARRAY_SIZE(sde_irq_wb_map);
break;
default:
pr_err("invalid type: %d\n", item->type);
}
@@ -1006,6 +1027,9 @@ static inline struct sde_irq_type *_get_irq_map_addr(
case SDE_INTR_HWBLK_LTM:
ret = sde_irq_ltm_map;
break;
case SDE_INTR_HWBLK_WB:
ret = sde_irq_wb_map;
break;
default:
pr_err("invalid type: %d\n", item->type);
}

查看文件

@@ -56,6 +56,7 @@
* @SDE_IRQ_TYPE_INTF_TEAR_TE_CHECK: INTF Tear TE detection
* @SDE_IRQ_TYPE_LTM_STATS_DONE: LTM stats done interrupt
* @SDE_IRQ_TYPE_LTM_STATS_WB_PB: LTM stats WB push back interrupt
* @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt for WB
* @SDE_IRQ_TYPE_RESERVED: Reserved for expansion
*/
enum sde_intr_type {
@@ -93,6 +94,7 @@ enum sde_intr_type {
SDE_IRQ_TYPE_INTF_TEAR_TE_CHECK,
SDE_IRQ_TYPE_LTM_STATS_DONE,
SDE_IRQ_TYPE_LTM_STATS_WB_PB,
SDE_IRQ_TYPE_WB_PROG_LINE,
SDE_IRQ_TYPE_RESERVED,
};

查看文件

@@ -35,6 +35,8 @@
#define WB_CROP_OFFSET 0x158
#define WB_CLK_CTRL 0x178
#define WB_CLK_STATUS 0x17C
#define WB_LINE_COUNT 0x184
#define WB_PROG_LINE_COUNT 0x188
#define WB_CSC_BASE 0x260
#define WB_DST_ADDR_SW_STATUS 0x2B0
#define WB_CDP_CNTL 0x2B4
@@ -530,6 +532,24 @@ static int sde_hw_wb_get_clk_ctrl_status(struct sde_hw_blk_reg_map *hw,
return 0;
}
static u32 sde_hw_wb_get_line_count(struct sde_hw_wb *ctx)
{
struct sde_hw_blk_reg_map *c;
c = &ctx->hw;
return SDE_REG_READ(c, WB_LINE_COUNT) & 0xFFFF;
}
static void sde_hw_wb_set_prog_line_count(struct sde_hw_wb *ctx, u32 val)
{
struct sde_hw_blk_reg_map *c;
c = &ctx->hw;
SDE_REG_WRITE(c, WB_PROG_LINE_COUNT, val);
}
static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
unsigned long features)
{
@@ -557,6 +577,11 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
if (test_bit(SDE_WB_CWB_DITHER_CTRL, &features))
ops->program_cwb_dither_ctrl = sde_hw_wb_program_cwb_dither_ctrl;
if (test_bit(SDE_WB_PROG_LINE, &features)) {
ops->get_line_count = sde_hw_wb_get_line_count;
ops->set_prog_line_count = sde_hw_wb_set_prog_line_count;
}
}
struct sde_hw_blk_reg_map *sde_hw_wb_init(enum sde_wb idx,

查看文件

@@ -162,6 +162,19 @@ struct sde_hw_wb_ops {
*/
void (*program_cwb_dither_ctrl)(struct sde_hw_wb *ctx,
const enum sde_dcwb dcwb_idx, void *cfg, size_t len, bool enable);
/**
* get_line_count - get current wb output linecount
* @ctx: Pointer to wb context
*/
u32 (*get_line_count)(struct sde_hw_wb *ctx);
/**
* set_prog_line_count - set wb programmable line
* @ctx: Pointer to wb context
* @line_count: programmable line-count value
*/
void (*set_prog_line_count)(struct sde_hw_wb *ctx, u32 line_count);
};
/**