disp: msm: add changes missing during snapshots

This change ports the missing changes from 4.14 to 4.19
that were missed. It includes changes up until
commit 0f8fb25421ff ("cnss2: Add device version to
SOC info structure").

Change-Id: Idfdfe891f146e389e3c65cc3fc4c98d93220e789
Signed-off-by: Samantha Tran <samtran@codeaurora.org>
This commit is contained in:
Samantha Tran
2019-05-23 11:27:41 -07:00
parent 5af1fe1891
commit 1ab07a4d7c
17 changed files with 196 additions and 22 deletions

View File

@@ -69,6 +69,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
sde/sde_hw_dsc.o \ sde/sde_hw_dsc.o \
sde/sde_hw_ds.o \ sde/sde_hw_ds.o \
sde/sde_fence.o \ sde/sde_fence.o \
sde/sde_hw_qdss.o \
msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \ msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
sde/sde_encoder_phys_wb.o \ sde/sde_encoder_phys_wb.o \

View File

@@ -417,6 +417,18 @@ struct dsi_mode_info {
struct msm_roi_caps roi_caps; struct msm_roi_caps roi_caps;
}; };
/**
* struct dsi_split_link_config - Split Link Configuration
* @split_link_enabled: Split Link Enabled.
* @num_sublinks: Number of sublinks.
* @lanes_per_sublink: Number of lanes per sublink.
*/
struct dsi_split_link_config {
bool split_link_enabled;
u32 num_sublinks;
u32 lanes_per_sublink;
};
/** /**
* struct dsi_host_common_cfg - Host configuration common to video and cmd mode * struct dsi_host_common_cfg - Host configuration common to video and cmd mode
* @dst_format: Destination pixel format. * @dst_format: Destination pixel format.
@@ -444,6 +456,7 @@ struct dsi_mode_info {
* true. * true.
* @ext_bridge_mode: External bridge is connected. * @ext_bridge_mode: External bridge is connected.
* @force_hs_clk_lane: Send continuous clock to the panel. * @force_hs_clk_lane: Send continuous clock to the panel.
* @dsi_split_link_config: Split Link Configuration.
*/ */
struct dsi_host_common_cfg { struct dsi_host_common_cfg {
enum dsi_pixel_format dst_format; enum dsi_pixel_format dst_format;
@@ -466,6 +479,7 @@ struct dsi_host_common_cfg {
bool append_tx_eot; bool append_tx_eot;
bool ext_bridge_mode; bool ext_bridge_mode;
bool force_hs_clk_lane; bool force_hs_clk_lane;
struct dsi_split_link_config split_link;
}; };
/** /**

View File

@@ -5403,6 +5403,7 @@ int dsi_display_get_info(struct drm_connector *connector,
{ {
struct dsi_display *display; struct dsi_display *display;
struct dsi_panel_phy_props phy_props; struct dsi_panel_phy_props phy_props;
struct dsi_host_common_cfg *host;
int i, rc; int i, rc;
if (!info || !disp) { if (!info || !disp) {
@@ -5470,6 +5471,9 @@ int dsi_display_get_info(struct drm_connector *connector,
info->te_source = display->te_source; info->te_source = display->te_source;
host = &display->panel->host_config;
if (host->split_link.split_link_enabled)
info->capabilities |= MSM_DISPLAY_SPLIT_LINK;
error: error:
mutex_unlock(&display->display_lock); mutex_unlock(&display->display_lock);
return rc; return rc;

View File

@@ -238,6 +238,7 @@ enum msm_display_compression_ratio {
* @MSM_DISPLAY_CAP_EDID: EDID supported * @MSM_DISPLAY_CAP_EDID: EDID supported
* @MSM_DISPLAY_ESD_ENABLED: ESD feature enabled * @MSM_DISPLAY_ESD_ENABLED: ESD feature enabled
* @MSM_DISPLAY_CAP_MST_MODE: Display with MST support * @MSM_DISPLAY_CAP_MST_MODE: Display with MST support
* @MSM_DISPLAY_SPLIT_LINK: Split Link enabled
*/ */
enum msm_display_caps { enum msm_display_caps {
MSM_DISPLAY_CAP_VID_MODE = BIT(0), MSM_DISPLAY_CAP_VID_MODE = BIT(0),
@@ -246,6 +247,7 @@ enum msm_display_caps {
MSM_DISPLAY_CAP_EDID = BIT(3), MSM_DISPLAY_CAP_EDID = BIT(3),
MSM_DISPLAY_ESD_ENABLED = BIT(4), MSM_DISPLAY_ESD_ENABLED = BIT(4),
MSM_DISPLAY_CAP_MST_MODE = BIT(5), MSM_DISPLAY_CAP_MST_MODE = BIT(5),
MSM_DISPLAY_SPLIT_LINK = BIT(6),
}; };
/** /**

View File

@@ -69,6 +69,7 @@ static void smmu_aspace_add_to_active(
{ {
WARN_ON(!mutex_is_locked(&aspace->list_lock)); WARN_ON(!mutex_is_locked(&aspace->list_lock));
list_move_tail(&msm_obj->iova_list, &aspace->active_list); list_move_tail(&msm_obj->iova_list, &aspace->active_list);
msm_obj->in_active_list = true;
} }
static void smmu_aspace_remove_from_active( static void smmu_aspace_remove_from_active(
@@ -82,6 +83,7 @@ static void smmu_aspace_remove_from_active(
list_for_each_entry_safe(msm_obj, next, &aspace->active_list, list_for_each_entry_safe(msm_obj, next, &aspace->active_list,
iova_list) { iova_list) {
if (msm_obj == obj) { if (msm_obj == obj) {
msm_obj->in_active_list = false;
list_del(&msm_obj->iova_list); list_del(&msm_obj->iova_list);
break; break;
} }

View File

@@ -37,6 +37,8 @@
#include "sde_crtc.h" #include "sde_crtc.h"
#include "sde_trace.h" #include "sde_trace.h"
#include "sde_core_irq.h" #include "sde_core_irq.h"
#include "sde_hw_top.h"
#include "sde_hw_qdss.h"
#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\ #define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
(e) ? (e)->base.base.id : -1, ##__VA_ARGS__) (e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -180,6 +182,7 @@ enum sde_enc_rc_states {
* @intfs_swapped Whether or not the phys_enc interfaces have been swapped * @intfs_swapped Whether or not the phys_enc interfaces have been swapped
* for partial update right-only cases, such as pingpong * for partial update right-only cases, such as pingpong
* split where virtual pingpong does not generate IRQs * split where virtual pingpong does not generate IRQs
@qdss_status: indicate if qdss is modified since last update
* @crtc_vblank_cb: Callback into the upper layer / CRTC for * @crtc_vblank_cb: Callback into the upper layer / CRTC for
* notification of the VBLANK * notification of the VBLANK
* @crtc_vblank_cb_data: Data from upper layer for VBLANK notification * @crtc_vblank_cb_data: Data from upper layer for VBLANK notification
@@ -248,6 +251,7 @@ struct sde_encoder_virt {
enum sde_dsc dirty_dsc_ids[MAX_CHANNELS_PER_ENC]; enum sde_dsc dirty_dsc_ids[MAX_CHANNELS_PER_ENC];
bool intfs_swapped; bool intfs_swapped;
bool qdss_status;
void (*crtc_vblank_cb)(void *data); void (*crtc_vblank_cb)(void *data);
void *crtc_vblank_cb_data; void *crtc_vblank_cb_data;
@@ -361,6 +365,20 @@ static bool _sde_encoder_is_dsc_enabled(struct drm_encoder *drm_enc)
return (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC); return (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC);
} }
static void sde_configure_qdss(struct sde_encoder_virt *sde_enc,
struct sde_hw_qdss *hw_qdss,
struct sde_encoder_phys *phys, bool enable)
{
if (sde_enc->qdss_status == enable)
return;
sde_enc->qdss_status = enable;
phys->hw_mdptop->ops.set_mdp_hw_events(phys->hw_mdptop,
sde_enc->qdss_status);
hw_qdss->ops.enable_qdss_events(hw_qdss, sde_enc->qdss_status);
}
static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id, static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id,
s64 timeout_ms, struct sde_encoder_wait_info *info) s64 timeout_ms, struct sde_encoder_wait_info *info)
{ {
@@ -778,7 +796,7 @@ void sde_encoder_helper_split_config(
enum sde_intf interface) enum sde_intf interface)
{ {
struct sde_encoder_virt *sde_enc; struct sde_encoder_virt *sde_enc;
struct split_pipe_cfg cfg = { 0 }; struct split_pipe_cfg *cfg;
struct sde_hw_mdp *hw_mdptop; struct sde_hw_mdp *hw_mdptop;
enum sde_rm_topology_name topology; enum sde_rm_topology_name topology;
struct msm_display_info *disp_info; struct msm_display_info *disp_info;
@@ -791,10 +809,15 @@ void sde_encoder_helper_split_config(
sde_enc = to_sde_encoder_virt(phys_enc->parent); sde_enc = to_sde_encoder_virt(phys_enc->parent);
hw_mdptop = phys_enc->hw_mdptop; hw_mdptop = phys_enc->hw_mdptop;
disp_info = &sde_enc->disp_info; disp_info = &sde_enc->disp_info;
cfg = &phys_enc->hw_intf->cfg;
memset(cfg, 0, sizeof(*cfg));
if (disp_info->intf_type != DRM_MODE_CONNECTOR_DSI) if (disp_info->intf_type != DRM_MODE_CONNECTOR_DSI)
return; return;
if (disp_info->capabilities & MSM_DISPLAY_SPLIT_LINK)
cfg->split_link_en = true;
/** /**
* disable split modes since encoder will be operating in as the only * disable split modes since encoder will be operating in as the only
* encoder, either for the entire use case in the case of, for example, * encoder, either for the entire use case in the case of, for example,
@@ -803,43 +826,43 @@ void sde_encoder_helper_split_config(
*/ */
if (phys_enc->split_role == ENC_ROLE_SOLO) { if (phys_enc->split_role == ENC_ROLE_SOLO) {
if (hw_mdptop->ops.setup_split_pipe) if (hw_mdptop->ops.setup_split_pipe)
hw_mdptop->ops.setup_split_pipe(hw_mdptop, &cfg); hw_mdptop->ops.setup_split_pipe(hw_mdptop, cfg);
if (hw_mdptop->ops.setup_pp_split) if (hw_mdptop->ops.setup_pp_split)
hw_mdptop->ops.setup_pp_split(hw_mdptop, &cfg); hw_mdptop->ops.setup_pp_split(hw_mdptop, cfg);
return; return;
} }
cfg.en = true; cfg->en = true;
cfg.mode = phys_enc->intf_mode; cfg->mode = phys_enc->intf_mode;
cfg.intf = interface; cfg->intf = interface;
if (cfg.en && phys_enc->ops.needs_single_flush && if (cfg->en && phys_enc->ops.needs_single_flush &&
phys_enc->ops.needs_single_flush(phys_enc)) phys_enc->ops.needs_single_flush(phys_enc))
cfg.split_flush_en = true; cfg->split_flush_en = true;
topology = sde_connector_get_topology_name(phys_enc->connector); topology = sde_connector_get_topology_name(phys_enc->connector);
if (topology == SDE_RM_TOPOLOGY_PPSPLIT) if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
cfg.pp_split_slave = cfg.intf; cfg->pp_split_slave = cfg->intf;
else else
cfg.pp_split_slave = INTF_MAX; cfg->pp_split_slave = INTF_MAX;
if (phys_enc->split_role == ENC_ROLE_MASTER) { if (phys_enc->split_role == ENC_ROLE_MASTER) {
SDE_DEBUG_ENC(sde_enc, "enable %d\n", cfg.en); SDE_DEBUG_ENC(sde_enc, "enable %d\n", cfg->en);
if (hw_mdptop->ops.setup_split_pipe) if (hw_mdptop->ops.setup_split_pipe)
hw_mdptop->ops.setup_split_pipe(hw_mdptop, &cfg); hw_mdptop->ops.setup_split_pipe(hw_mdptop, cfg);
} else if (sde_enc->hw_pp[0]) { } else if (sde_enc->hw_pp[0]) {
/* /*
* slave encoder * slave encoder
* - determine split index from master index, * - determine split index from master index,
* assume master is first pp * assume master is first pp
*/ */
cfg.pp_split_index = sde_enc->hw_pp[0]->idx - PINGPONG_0; cfg->pp_split_index = sde_enc->hw_pp[0]->idx - PINGPONG_0;
SDE_DEBUG_ENC(sde_enc, "master using pp%d\n", SDE_DEBUG_ENC(sde_enc, "master using pp%d\n",
cfg.pp_split_index); cfg->pp_split_index);
if (hw_mdptop->ops.setup_pp_split) if (hw_mdptop->ops.setup_pp_split)
hw_mdptop->ops.setup_pp_split(hw_mdptop, &cfg); hw_mdptop->ops.setup_pp_split(hw_mdptop, cfg);
} }
} }
@@ -2724,7 +2747,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct drm_connector *conn = NULL, *conn_iter; struct drm_connector *conn = NULL, *conn_iter;
struct sde_connector_state *sde_conn_state = NULL; struct sde_connector_state *sde_conn_state = NULL;
struct sde_connector *sde_conn = NULL; struct sde_connector *sde_conn = NULL;
struct sde_rm_hw_iter dsc_iter, pp_iter; struct sde_rm_hw_iter dsc_iter, pp_iter, qdss_iter;
struct sde_rm_hw_request request_hw; struct sde_rm_hw_request request_hw;
enum sde_intf_mode intf_mode; enum sde_intf_mode intf_mode;
@@ -2826,6 +2849,22 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
sde_enc->hw_pp[i] = (struct sde_hw_pingpong *) pp_iter.hw; sde_enc->hw_pp[i] = (struct sde_hw_pingpong *) pp_iter.hw;
} }
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
if (phys) {
sde_rm_init_hw_iter(&qdss_iter, drm_enc->base.id,
SDE_HW_BLK_QDSS);
for (i = 0; i < QDSS_MAX; i++) {
if (sde_rm_get_hw(&sde_kms->rm, &qdss_iter)) {
phys->hw_qdss =
(struct sde_hw_qdss *)qdss_iter.hw;
break;
}
}
}
}
sde_rm_init_hw_iter(&dsc_iter, drm_enc->base.id, SDE_HW_BLK_DSC); sde_rm_init_hw_iter(&dsc_iter, drm_enc->base.id, SDE_HW_BLK_DSC);
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
sde_enc->hw_dsc[i] = NULL; sde_enc->hw_dsc[i] = NULL;
@@ -4601,6 +4640,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
struct sde_encoder_virt *sde_enc; struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys; struct sde_encoder_phys *phys;
struct sde_kms *sde_kms = NULL; struct sde_kms *sde_kms = NULL;
struct sde_crtc *sde_crtc;
struct msm_drm_private *priv = NULL; struct msm_drm_private *priv = NULL;
bool needs_hw_reset = false; bool needs_hw_reset = false;
int ln_cnt1 = -EINVAL, i, rc, ret = 0; int ln_cnt1 = -EINVAL, i, rc, ret = 0;
@@ -4615,6 +4655,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
priv = drm_enc->dev->dev_private; priv = drm_enc->dev->dev_private;
sde_kms = to_sde_kms(priv->kms); sde_kms = to_sde_kms(priv->kms);
disp_info = &sde_enc->disp_info; disp_info = &sde_enc->disp_info;
sde_crtc = to_sde_crtc(sde_enc->crtc);
SDE_DEBUG_ENC(sde_enc, "\n"); SDE_DEBUG_ENC(sde_enc, "\n");
SDE_EVT32(DRMID(drm_enc)); SDE_EVT32(DRMID(drm_enc));
@@ -4701,6 +4742,10 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
_helper_flush_dsc(sde_enc); _helper_flush_dsc(sde_enc);
} }
if (sde_enc->cur_master && !sde_enc->cur_master->cont_splash_enabled)
sde_configure_qdss(sde_enc, sde_enc->cur_master->hw_qdss,
sde_enc->cur_master, sde_kms->qdss_enabled);
end: end:
SDE_ATRACE_END("sde_encoder_prepare_for_kickoff"); SDE_ATRACE_END("sde_encoder_prepare_for_kickoff");
return ret; return ret;
@@ -5518,6 +5563,7 @@ struct drm_encoder *sde_encoder_init_with_ops(
kthread_init_delayed_work(&sde_enc->delayed_off_work, kthread_init_delayed_work(&sde_enc->delayed_off_work,
sde_encoder_off_work); sde_encoder_off_work);
sde_enc->vblank_enabled = false; sde_enc->vblank_enabled = false;
sde_enc->qdss_status = false;
kthread_init_work(&sde_enc->vsync_event_work, kthread_init_work(&sde_enc->vsync_event_work,
sde_encoder_vsync_event_work_handler); sde_encoder_vsync_event_work_handler);

View File

@@ -250,6 +250,7 @@ struct sde_encoder_irq {
* @hw_ctl: Hardware interface to the ctl registers * @hw_ctl: Hardware interface to the ctl registers
* @hw_intf: Hardware interface to INTF registers * @hw_intf: Hardware interface to INTF registers
* @hw_cdm: Hardware interface to the cdm registers * @hw_cdm: Hardware interface to the cdm registers
* @hw_qdss: Hardware interface to the qdss registers
* @cdm_cfg: Chroma-down hardware configuration * @cdm_cfg: Chroma-down hardware configuration
* @hw_pp: Hardware interface to the ping pong registers * @hw_pp: Hardware interface to the ping pong registers
* @sde_kms: Pointer to the sde_kms top level * @sde_kms: Pointer to the sde_kms top level
@@ -298,6 +299,7 @@ struct sde_encoder_phys {
struct sde_hw_ctl *hw_ctl; struct sde_hw_ctl *hw_ctl;
struct sde_hw_intf *hw_intf; struct sde_hw_intf *hw_intf;
struct sde_hw_cdm *hw_cdm; struct sde_hw_cdm *hw_cdm;
struct sde_hw_qdss *hw_qdss;
struct sde_hw_cdm_cfg cdm_cfg; struct sde_hw_cdm_cfg cdm_cfg;
struct sde_hw_pingpong *hw_pp; struct sde_hw_pingpong *hw_pp;
struct sde_kms *sde_kms; struct sde_kms *sde_kms;

View File

@@ -385,8 +385,10 @@ static void sde_encoder_phys_vid_setup_timing_engine(
u32 qsync_min_fps = 0; u32 qsync_min_fps = 0;
unsigned long lock_flags; unsigned long lock_flags;
struct sde_hw_intf_cfg intf_cfg = { 0 }; struct sde_hw_intf_cfg intf_cfg = { 0 };
bool is_split_link = false;
if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl) { if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl ||
!phys_enc->hw_intf) {
SDE_ERROR("invalid encoder %d\n", !phys_enc); SDE_ERROR("invalid encoder %d\n", !phys_enc);
return; return;
} }
@@ -401,7 +403,8 @@ static void sde_encoder_phys_vid_setup_timing_engine(
SDE_DEBUG_VIDENC(vid_enc, "enabling mode:\n"); SDE_DEBUG_VIDENC(vid_enc, "enabling mode:\n");
drm_mode_debug_printmodeline(&mode); drm_mode_debug_printmodeline(&mode);
if (phys_enc->split_role != ENC_ROLE_SOLO) { is_split_link = phys_enc->hw_intf->cfg.split_link_en;
if (phys_enc->split_role != ENC_ROLE_SOLO || is_split_link) {
mode.hdisplay >>= 1; mode.hdisplay >>= 1;
mode.htotal >>= 1; mode.htotal >>= 1;
mode.hsync_start >>= 1; mode.hsync_start >>= 1;

View File

@@ -3641,7 +3641,8 @@ end:
return rc; return rc;
} }
int sde_qdss_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) static int sde_qdss_parse_dt(struct device_node *np,
struct sde_mdss_cfg *sde_cfg)
{ {
int rc, prop_count[HW_PROP_MAX], i; int rc, prop_count[HW_PROP_MAX], i;
struct sde_prop_value *prop_value = NULL; struct sde_prop_value *prop_value = NULL;

View File

@@ -308,6 +308,8 @@ static struct sde_irq_type sde_irq_intr2_map[] = {
{ SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_S0, { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_S0,
SDE_INTR_PING_PONG_S0_WR_PTR, -1}, SDE_INTR_PING_PONG_S0_WR_PTR, -1},
{ SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_1, SDE_INTR_CWB_1_OVERFLOW, -1},
{ SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_S0, { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_S0,
SDE_INTR_PING_PONG_S0_RD_PTR, -1}, SDE_INTR_PING_PONG_S0_RD_PTR, -1},

View File

@@ -8,7 +8,6 @@
#include "sde_hw_catalog.h" #include "sde_hw_catalog.h"
#include "sde_hw_intf.h" #include "sde_hw_intf.h"
#include "sde_dbg.h" #include "sde_dbg.h"
#include "sde_kms.h"
#define INTF_TIMING_ENGINE_EN 0x000 #define INTF_TIMING_ENGINE_EN 0x000
#define INTF_CONFIG 0x004 #define INTF_CONFIG 0x004
@@ -45,6 +44,7 @@
#define INTF_DEFLICKER_STRNG_COEFF 0x0F4 #define INTF_DEFLICKER_STRNG_COEFF 0x0F4
#define INTF_DEFLICKER_WEAK_COEFF 0x0F8 #define INTF_DEFLICKER_WEAK_COEFF 0x0F8
#define INTF_REG_SPLIT_LINK 0x080
#define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084 #define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084
#define INTF_PANEL_FORMAT 0x090 #define INTF_PANEL_FORMAT 0x090
#define INTF_TPG_ENABLE 0x100 #define INTF_TPG_ENABLE 0x100
@@ -294,6 +294,9 @@ static void sde_hw_intf_setup_timing_engine(struct sde_hw_intf *ctx,
if (p->wide_bus_en) if (p->wide_bus_en)
intf_cfg2 |= BIT(0); intf_cfg2 |= BIT(0);
if (ctx->cfg.split_link_en)
SDE_REG_WRITE(c, INTF_REG_SPLIT_LINK, 0x3);
SDE_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl); SDE_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl);
SDE_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); SDE_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period);
SDE_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0, SDE_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0,
@@ -370,6 +373,9 @@ static void sde_hw_intf_bind_pingpong_blk(
else else
mux_cfg |= 0xf; mux_cfg |= 0xf;
if (intf->cfg.split_link_en)
mux_cfg = 0x60000;
SDE_REG_WRITE(c, INTF_MUX, mux_cfg); SDE_REG_WRITE(c, INTF_MUX, mux_cfg);
} }

View File

@@ -10,6 +10,7 @@
#include "sde_hw_mdss.h" #include "sde_hw_mdss.h"
#include "sde_hw_util.h" #include "sde_hw_util.h"
#include "sde_hw_blk.h" #include "sde_hw_blk.h"
#include "sde_kms.h"
struct sde_hw_intf; struct sde_hw_intf;
@@ -186,6 +187,7 @@ struct sde_hw_intf {
enum sde_intf idx; enum sde_intf idx;
const struct sde_intf_cfg *cap; const struct sde_intf_cfg *cap;
const struct sde_mdss_cfg *mdss; const struct sde_mdss_cfg *mdss;
struct split_pipe_cfg cfg;
/* ops */ /* ops */
struct sde_hw_intf_ops ops; struct sde_hw_intf_ops ops;

View File

@@ -127,12 +127,16 @@ static void sde_hw_setup_pp_split(struct sde_hw_mdp *mdp,
if (!mdp || !cfg) if (!mdp || !cfg)
return; return;
if (cfg->en && cfg->pp_split_slave != INTF_MAX) { if (cfg->split_link_en) {
ppb_config |= BIT(16); /* split enable */
ppb_control = BIT(5); /* horz split*/
} else if (cfg->en && cfg->pp_split_slave != INTF_MAX) {
ppb_config |= (cfg->pp_split_slave - INTF_0 + 1) << 20; ppb_config |= (cfg->pp_split_slave - INTF_0 + 1) << 20;
ppb_config |= BIT(16); /* split enable */ ppb_config |= BIT(16); /* split enable */
ppb_control = BIT(5); /* horz split*/ ppb_control = BIT(5); /* horz split*/
} }
if (cfg->pp_split_index) {
if (cfg->pp_split_index && !cfg->split_link_en) {
SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, 0x0); SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, 0x0);
SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, 0x0); SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, 0x0);
SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, ppb_config); SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, ppb_config);
@@ -430,6 +434,18 @@ static void sde_hw_intf_audio_select(struct sde_hw_mdp *mdp)
SDE_REG_WRITE(c, HDMI_DP_CORE_SELECT, 0x1); SDE_REG_WRITE(c, HDMI_DP_CORE_SELECT, 0x1);
} }
static void sde_hw_mdp_events(struct sde_hw_mdp *mdp, bool enable)
{
struct sde_hw_blk_reg_map *c;
if (!mdp)
return;
c = &mdp->hw;
SDE_REG_WRITE(c, HW_EVENTS_CTL, enable);
}
struct sde_hw_sid *sde_hw_sid_init(void __iomem *addr, struct sde_hw_sid *sde_hw_sid_init(void __iomem *addr,
u32 sid_len, const struct sde_mdss_cfg *m) u32 sid_len, const struct sde_mdss_cfg *m)
{ {
@@ -512,6 +528,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
ops->setup_dce = sde_hw_setup_dce; ops->setup_dce = sde_hw_setup_dce;
ops->reset_ubwc = sde_hw_reset_ubwc; ops->reset_ubwc = sde_hw_reset_ubwc;
ops->intf_audio_select = sde_hw_intf_audio_select; ops->intf_audio_select = sde_hw_intf_audio_select;
ops->set_mdp_hw_events = sde_hw_mdp_events;
if (cap & BIT(SDE_MDP_VSYNC_SEL)) if (cap & BIT(SDE_MDP_VSYNC_SEL))
ops->setup_vsync_source = sde_hw_setup_vsync_source; ops->setup_vsync_source = sde_hw_setup_vsync_source;
else else

View File

@@ -38,6 +38,7 @@ struct traffic_shaper_cfg {
* @pp_split_idx: Ping pong index for ping pong split * @pp_split_idx: Ping pong index for ping pong split
* @split_flush_en: Allows both the paths to be flushed when master path is * @split_flush_en: Allows both the paths to be flushed when master path is
* flushed * flushed
* @split_link_en: Check if split link is enabled
*/ */
struct split_pipe_cfg { struct split_pipe_cfg {
bool en; bool en;
@@ -46,6 +47,7 @@ struct split_pipe_cfg {
enum sde_intf pp_split_slave; enum sde_intf pp_split_slave;
u32 pp_split_index; u32 pp_split_index;
bool split_flush_en; bool split_flush_en;
bool split_link_en;
}; };
/** /**
@@ -188,6 +190,13 @@ struct sde_hw_mdp_ops {
*/ */
void (*intf_audio_select)(struct sde_hw_mdp *mdp); void (*intf_audio_select)(struct sde_hw_mdp *mdp);
/**
* set_mdp_hw_events - enable qdss hardware events for mdp
* @mdp: mdp top context driver
* @enable: enable/disable hw events
*/
void (*set_mdp_hw_events)(struct sde_hw_mdp *mdp, bool enable);
/** /**
* set_cwb_ppb_cntl - select the data point for CWB * set_cwb_ppb_cntl - select the data point for CWB
* @mdp: mdp top context driver * @mdp: mdp top context driver

View File

@@ -145,6 +145,10 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms)
return rc; return rc;
} }
if (sde_kms->catalog->qdss_count)
debugfs_create_u32("qdss", 0600, debugfs_root,
(u32 *)&sde_kms->qdss_enabled);
return 0; return 0;
} }

View File

@@ -287,6 +287,7 @@ struct sde_kms {
struct mutex secure_transition_lock; struct mutex secure_transition_lock;
bool first_kickoff; bool first_kickoff;
bool qdss_enabled;
}; };
struct vsync_info { struct vsync_info {

View File

@@ -17,6 +17,7 @@
#include "sde_connector.h" #include "sde_connector.h"
#include "sde_hw_dsc.h" #include "sde_hw_dsc.h"
#include "sde_crtc.h" #include "sde_crtc.h"
#include "sde_hw_qdss.h"
#define RESERVED_BY_OTHER(h, r) \ #define RESERVED_BY_OTHER(h, r) \
(((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) ||\ (((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) ||\
@@ -322,6 +323,9 @@ static void _sde_rm_hw_destroy(enum sde_hw_blk_type type, void *hw)
case SDE_HW_BLK_DSC: case SDE_HW_BLK_DSC:
sde_hw_dsc_destroy(hw); sde_hw_dsc_destroy(hw);
break; break;
case SDE_HW_BLK_QDSS:
sde_hw_qdss_destroy(hw);
break;
case SDE_HW_BLK_SSPP: case SDE_HW_BLK_SSPP:
/* SSPPs are not managed by the resource manager */ /* SSPPs are not managed by the resource manager */
case SDE_HW_BLK_TOP: case SDE_HW_BLK_TOP:
@@ -410,6 +414,9 @@ static int _sde_rm_hw_blk_create(
case SDE_HW_BLK_DSC: case SDE_HW_BLK_DSC:
hw = sde_hw_dsc_init(id, mmio, cat); hw = sde_hw_dsc_init(id, mmio, cat);
break; break;
case SDE_HW_BLK_QDSS:
hw = sde_hw_qdss_init(id, mmio, cat);
break;
case SDE_HW_BLK_SSPP: case SDE_HW_BLK_SSPP:
/* SSPPs are not managed by the resource manager */ /* SSPPs are not managed by the resource manager */
case SDE_HW_BLK_TOP: case SDE_HW_BLK_TOP:
@@ -525,6 +532,15 @@ static int _sde_rm_hw_blk_create_new(struct sde_rm *rm,
} }
} }
for (i = 0; i < cat->qdss_count; i++) {
rc = _sde_rm_hw_blk_create(rm, cat, mmio, SDE_HW_BLK_QDSS,
cat->qdss[i].id, &cat->qdss[i]);
if (rc) {
SDE_ERROR("failed: qdss hw not available\n");
goto fail;
}
}
fail: fail:
return rc; return rc;
} }
@@ -1102,6 +1118,44 @@ static int _sde_rm_reserve_dsc(
return -ENAVAIL; return -ENAVAIL;
} }
static int _sde_rm_reserve_qdss(
struct sde_rm *rm,
struct sde_rm_rsvp *rsvp,
const struct sde_rm_topology_def *top,
u8 *_qdss_ids)
{
struct sde_rm_hw_iter iter;
struct msm_drm_private *priv = rm->dev->dev_private;
struct sde_kms *sde_kms;
if (!priv->kms) {
SDE_ERROR("invalid kms\n");
return -EINVAL;
}
sde_kms = to_sde_kms(priv->kms);
sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_QDSS);
while (_sde_rm_get_hw_locked(rm, &iter)) {
if (RESERVED_BY_OTHER(iter.blk, rsvp))
continue;
SDE_DEBUG("blk id = %d\n", iter.blk->id);
iter.blk->rsvp_nxt = rsvp;
SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
return 0;
}
if (!iter.hw && sde_kms->catalog->qdss_count) {
SDE_DEBUG("couldn't reserve qdss for type %d id %d\n",
SDE_HW_BLK_QDSS, iter.blk->id);
return -ENAVAIL;
}
return 0;
}
static int _sde_rm_reserve_cdm( static int _sde_rm_reserve_cdm(
struct sde_rm *rm, struct sde_rm *rm,
struct sde_rm_rsvp *rsvp, struct sde_rm_rsvp *rsvp,
@@ -1368,6 +1422,10 @@ static int _sde_rm_make_next_rsvp(struct sde_rm *rm, struct drm_encoder *enc,
if (ret) if (ret)
return ret; return ret;
ret = _sde_rm_reserve_qdss(rm, rsvp, reqs->topology, NULL);
if (ret)
return ret;
return ret; return ret;
} }