disp: msm: sde: add support for WD timer on INTF

Watchdog timer is moving from TOP to INTF. This change adds
support for movement and ensures backwards compatibility.

Vsync select only needs to specify whether or not to use
Timer 0 associated with the interface. It does not need to
select between Timer 0-4.

Signed-off-by: Samantha Tran <samtran@codeaurora.org>
Change-Id: I9d89a8cb1ea607e9fc0bdbffa0a6a9acceff7f13
This commit is contained in:
Samantha Tran
2020-09-16 17:20:32 -07:00
parent 77b66f2f84
commit e778d2688e
11 changed files with 92 additions and 55 deletions

View File

@@ -1083,8 +1083,7 @@ static int _sde_encoder_update_roi(struct drm_encoder *drm_enc)
return 0;
}
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
u32 vsync_source, bool is_dummy)
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, u32 vsync_source)
{
struct sde_vsync_source_cfg vsync_cfg = { 0 };
struct sde_kms *sde_kms;
@@ -1123,14 +1122,13 @@ void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
vsync_cfg.pp_count = sde_enc->num_phys_encs;
vsync_cfg.frame_rate = sde_enc->mode_info.frame_rate;
vsync_cfg.vsync_source = vsync_source;
vsync_cfg.is_dummy = is_dummy;
hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
}
}
static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
struct msm_display_info *disp_info, bool is_dummy)
struct msm_display_info *disp_info)
{
struct sde_encoder_phys *phys;
int i;
@@ -1148,24 +1146,19 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
}
if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_CMD_MODE)) {
if (is_dummy)
vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0 -
sde_enc->te_source;
else if (disp_info->is_te_using_watchdog_timer)
vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_4 +
sde_enc->te_source;
if (disp_info->is_te_using_watchdog_timer)
vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_4 + sde_enc->te_source;
else
vsync_source = sde_enc->te_source;
SDE_EVT32(DRMID(&sde_enc->base), vsync_source, is_dummy,
SDE_EVT32(DRMID(&sde_enc->base), vsync_source,
disp_info->is_te_using_watchdog_timer);
for (i = 0; i < sde_enc->num_phys_encs; i++) {
phys = sde_enc->phys_encs[i];
if (phys && phys->ops.setup_vsync_source)
phys->ops.setup_vsync_source(phys,
vsync_source, is_dummy);
phys->ops.setup_vsync_source(phys, vsync_source);
}
}
}
@@ -1189,7 +1182,7 @@ int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc,
memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info));
disp_info.is_te_using_watchdog_timer = watchdog_te;
_sde_encoder_update_vsync_source(sde_enc, &disp_info, false);
_sde_encoder_update_vsync_source(sde_enc, &disp_info);
sde_encoder_control_te(drm_enc, true);
@@ -2567,7 +2560,7 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
sde_enc->cur_master->hw_ctl,
&sde_enc->cur_master->intf_cfg_v1);
_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info, false);
_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info);
sde_encoder_control_te(drm_enc, true);
memset(&sde_enc->prv_conn_roi, 0, sizeof(sde_enc->prv_conn_roi));

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __SDE_ENCODER_PHYS_H__
@@ -185,8 +185,7 @@ struct sde_encoder_phys_ops {
int (*get_wr_line_count)(struct sde_encoder_phys *phys);
bool (*wait_dma_trigger)(struct sde_encoder_phys *phys);
int (*wait_for_active)(struct sde_encoder_phys *phys);
void (*setup_vsync_source)(struct sde_encoder_phys *phys,
u32 vsync_source, bool is_dummy);
void (*setup_vsync_source)(struct sde_encoder_phys *phys, u32 vsync_source);
u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys);
};
@@ -567,10 +566,8 @@ void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc);
* sde_encoder_helper_vsync_config - configure vsync source for cmd mode
* @phys_enc: Pointer to physical encoder structure
* @vsync_source: vsync source selection
* @is_dummy: used only for RSC
*/
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
u32 vsync_source, bool is_dummy);
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, u32 vsync_source);
/**
* sde_encoder_helper_wait_event_timeout - wait for event with timeout

View File

@@ -1935,13 +1935,25 @@ static void sde_encoder_phys_cmd_trigger_start(
}
static void sde_encoder_phys_cmd_setup_vsync_source(
struct sde_encoder_phys *phys_enc,
u32 vsync_source, bool is_dummy)
struct sde_encoder_phys *phys_enc, u32 vsync_source)
{
struct sde_encoder_virt *sde_enc;
if (!phys_enc || !phys_enc->hw_intf)
return;
sde_encoder_helper_vsync_config(phys_enc, vsync_source, is_dummy);
sde_enc = to_sde_encoder_virt(phys_enc->parent);
if (!sde_enc)
return;
if (sde_enc->disp_info.is_te_using_watchdog_timer &&
phys_enc->hw_intf->ops.setup_vsync_source) {
vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
phys_enc->hw_intf->ops.setup_vsync_source(phys_enc->hw_intf,
sde_enc->mode_info.frame_rate);
} else {
sde_encoder_helper_vsync_config(phys_enc, vsync_source);
}
if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel)
phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -2245,6 +2245,10 @@ static int sde_intf_parse_dt(struct device_node *np,
if (SDE_HW_MAJOR(sde_cfg->hwversion) >=
SDE_HW_MAJOR(SDE_HW_VER_700))
set_bit(SDE_INTF_TE_ALIGN_VSYNC, &intf->features);
if (SDE_HW_MAJOR(sde_cfg->hwversion) >=
SDE_HW_MAJOR(SDE_HW_VER_810))
set_bit(SDE_INTF_WD_TIMER, &intf->features);
}
end:
@@ -3804,6 +3808,8 @@ static int sde_top_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
major_version = SDE_HW_MAJOR(cfg->hwversion);
if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
set_bit(SDE_MDP_VSYNC_SEL, &cfg->mdp[0].features);
else if (major_version < SDE_HW_MAJOR(SDE_HW_VER_810))
set_bit(SDE_MDP_WD_TIMER, &cfg->mdp[0].features);
rc = _add_to_irq_offset_list(cfg, SDE_INTR_HWBLK_TOP,
SDE_INTR_TOP_INTR, cfg->mdp[0].base);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_CATALOG_H
@@ -208,6 +208,7 @@ struct sde_intr_irq_offsets {
* compression initial revision
* @SDE_MDP_UBWC_1_5, Universal Bandwidth compression version 1.5
* @SDE_MDP_VSYNC_SEL Vsync selection for command mode panels
* @SDE_MDP_WD_TIMER WD timer support
* @SDE_MDP_DHDR_MEMPOOL Dynamic HDR Metadata mempool present
* @SDE_MDP_DHDR_MEMPOOL_4K Dynamic HDR mempool is 4k aligned
* @SDE_MDP_MAX Maximum value
@@ -220,6 +221,7 @@ enum {
SDE_MDP_UBWC_1_0,
SDE_MDP_UBWC_1_5,
SDE_MDP_VSYNC_SEL,
SDE_MDP_WD_TIMER,
SDE_MDP_DHDR_MEMPOOL,
SDE_MDP_DHDR_MEMPOOL_4K,
SDE_MDP_MAX
@@ -473,6 +475,7 @@ enum {
* pixel data arrives to this INTF
* @SDE_INTF_TE INTF block has TE configuration support
* @SDE_INTF_TE_ALIGN_VSYNC INTF block has POMS Align vsync support
* @SDE_INTF_WD_TIMER INTF block has WD Timer support
* @SDE_INTF_STATUS INTF block has INTF_STATUS register
* @SDE_INTF_MAX
*/
@@ -480,6 +483,7 @@ enum {
SDE_INTF_INPUT_CTRL = 0x1,
SDE_INTF_TE,
SDE_INTF_TE_ALIGN_VSYNC,
SDE_INTF_WD_TIMER,
SDE_INTF_STATUS,
SDE_INTF_MAX
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/bitops.h>
@@ -166,6 +166,7 @@
#define SDE_INTR_DSICMD_2_INTO_STATIC BIT(6)
#define SDE_INTR_DSICMD_2_OUTOF_STATIC BIT(7)
#define SDE_INTR_PROG_LINE BIT(8)
#define SDE_INTR_INTF_WD_TIMER_0_DONE BIT(13)
/**
* AD4 interrupt status bit definitions
@@ -398,6 +399,7 @@ static struct sde_irq_type sde_irq_intf_map[] = {
SDE_INTR_DSICMD_2_OUTOF_STATIC, -1},
{ SDE_IRQ_TYPE_PROG_LINE, -1, SDE_INTR_PROG_LINE, -1},
{ SDE_IRQ_TYPE_WD_TIMER, -1, SDE_INTR_WD_TIMER_0_DONE, -1},
};
static struct sde_irq_type sde_irq_ad4_map[] = {

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/iopoll.h>
@@ -61,6 +61,9 @@
#define INTF_MISR_CTRL 0x180
#define INTF_MISR_SIGNATURE 0x184
#define INTF_WD_TIMER_0_CTL 0x230
#define INTF_WD_TIMER_0_CTL2 0x234
#define INTF_WD_TIMER_0_LOAD_VALUE 0x238
#define INTF_MUX 0x25C
#define INTF_UNDERRUN_COUNT 0x268
#define INTF_STATUS 0x26C
@@ -396,6 +399,29 @@ static void sde_hw_intf_setup_prg_fetch(
SDE_REG_WRITE(c, INTF_CONFIG, fetch_enable);
}
static void sde_hw_intf_setup_vsync_source(struct sde_hw_intf *intf,
u32 frame_rate)
{
struct sde_hw_blk_reg_map *c;
u32 reg;
if (!intf)
return;
c = &intf->hw;
SDE_REG_WRITE(c, INTF_WD_TIMER_0_LOAD_VALUE, CALCULATE_WD_LOAD_VALUE(frame_rate));
SDE_REG_WRITE(c, INTF_WD_TIMER_0_CTL, BIT(0)); /* clear timer */
reg = SDE_REG_READ(c, INTF_WD_TIMER_0_CTL2);
reg |= BIT(8); /* enable heartbeat timer */
reg |= BIT(0); /* enable WD timer */
SDE_REG_WRITE(c, INTF_WD_TIMER_0_CTL2, reg);
/* make sure that timers are enabled/disabled for vsync state */
wmb();
}
static void sde_hw_intf_bind_pingpong_blk(
struct sde_hw_intf *intf,
bool enable,
@@ -805,6 +831,9 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
if (cap & BIT(SDE_INTF_INPUT_CTRL))
ops->bind_pingpong_blk = sde_hw_intf_bind_pingpong_blk;
if (cap & BIT(SDE_INTF_WD_TIMER))
ops->setup_vsync_source = sde_hw_intf_setup_vsync_source;
if (cap & BIT(SDE_INTF_TE)) {
ops->setup_tearcheck = sde_hw_intf_setup_te_config;
ops->enable_tearcheck = sde_hw_intf_enable_te;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_INTF_H
@@ -78,6 +78,7 @@ struct intf_avr_params {
* @ get_line_count: reads current vertical line counter
* @ get_underrun_line_count: reads current underrun pixel clock count and
* converts it into line count
* @setup_vsync_source: Configure vsync source selection for intf
* @bind_pingpong_blk: enable/disable the connection with pingpong which will
* feed pixels to this interface
*/
@@ -112,6 +113,8 @@ struct sde_hw_intf_ops {
u32 (*get_line_count)(struct sde_hw_intf *intf);
u32 (*get_underrun_line_count)(struct sde_hw_intf *intf);
void (*setup_vsync_source)(struct sde_hw_intf *intf, u32 frame_rate);
void (*bind_pingpong_blk)(struct sde_hw_intf *intf,
bool enable,
const enum sde_pingpong pp);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_MDSS_H
@@ -61,6 +61,13 @@ enum sde_format_flags {
(((X)->fetch_mode == SDE_FETCH_UBWC) && \
test_bit(SDE_FORMAT_FLAG_COMPRESSED_BIT, (X)->flag))
#define MDP_TICK_COUNT 16
#define XO_CLK_RATE 19200
#define MS_TICKS_IN_SEC 1000
#define CALCULATE_WD_LOAD_VALUE(fps) \
((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps)))
#define SDE_BLEND_FG_ALPHA_FG_CONST (0 << 0)
#define SDE_BLEND_FG_ALPHA_BG_CONST (1 << 0)
#define SDE_BLEND_FG_ALPHA_FG_PIXEL (2 << 0)

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#include "sde_hwio.h"
@@ -50,16 +50,9 @@
#define MDP_WD_TIMER_4_CTL2 0x444
#define MDP_WD_TIMER_4_LOAD_VALUE 0x448
#define MDP_TICK_COUNT 16
#define XO_CLK_RATE 19200
#define MS_TICKS_IN_SEC 1000
#define AUTOREFRESH_TEST_POINT 0x2
#define TEST_MASK(id, tp) ((id << 4) | (tp << 1) | BIT(0))
#define CALCULATE_WD_LOAD_VALUE(fps) \
((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps)))
#define DCE_SEL 0x450
#define MDP_SID_VIG0 0x0
@@ -316,18 +309,13 @@ static void _update_vsync_source(struct sde_hw_mdp *mdp,
break;
}
if (cfg->is_dummy) {
SDE_REG_WRITE(c, wd_ctl2, 0x0);
} else {
SDE_REG_WRITE(c, wd_load_value,
CALCULATE_WD_LOAD_VALUE(cfg->frame_rate));
SDE_REG_WRITE(c, wd_load_value, CALCULATE_WD_LOAD_VALUE(cfg->frame_rate));
SDE_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */
reg = SDE_REG_READ(c, wd_ctl2);
reg |= BIT(8); /* enable heartbeat timer */
reg |= BIT(0); /* enable WD timer */
SDE_REG_WRITE(c, wd_ctl2, reg);
}
SDE_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */
reg = SDE_REG_READ(c, wd_ctl2);
reg |= BIT(8); /* enable heartbeat timer */
reg |= BIT(0); /* enable WD timer */
SDE_REG_WRITE(c, wd_ctl2, reg);
/* make sure that timers are enabled/disabled for vsync state */
wmb();
@@ -623,7 +611,6 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl;
ops->get_clk_ctrl_status = sde_hw_get_clk_ctrl_status;
ops->get_danger_status = sde_hw_get_danger_status;
ops->setup_vsync_source = sde_hw_setup_vsync_source;
ops->set_cwb_ppb_cntl = sde_hw_program_cwb_ppb_ctrl;
ops->get_safe_status = sde_hw_get_safe_status;
ops->get_split_flush_status = sde_hw_get_split_flush;
@@ -633,7 +620,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
ops->set_mdp_hw_events = sde_hw_mdp_events;
if (cap & BIT(SDE_MDP_VSYNC_SEL))
ops->setup_vsync_source = sde_hw_setup_vsync_source;
else
else if (cap & BIT(SDE_MDP_WD_TIMER))
ops->setup_vsync_source = sde_hw_setup_vsync_source_v1;
if (cap & BIT(SDE_MDP_DHDR_MEMPOOL_4K) ||

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_TOP_H
@@ -79,15 +79,12 @@ struct sde_danger_safe_status {
* @frame_rate: Display frame rate
* @ppnumber: ping pong index array
* @vsync_source: vsync source selection
* @is_dummy: a dummy source of vsync selection. It must not be selected for
* any case other than sde rsc idle request.
*/
struct sde_vsync_source_cfg {
u32 pp_count;
u32 frame_rate;
u32 ppnumber[PINGPONG_MAX];
u32 vsync_source;
bool is_dummy;
};
/**