Merge branch 'msm-next-lumag-dpu' into msm-next-lumag

Merge DPU changes, resolving conflicts between branches. Full changelog
will be present in the final merge commit.

DPU:
 - DSPP sub-block flush on sc7280
 - support AR30 in addition to XR30 format
 - Allow using REC_0 and REC_1 to handle wide (4k) RGB planes

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
This commit is contained in:
Dmitry Baryshkov 2023-04-06 20:29:50 +03:00
commit 2470e93289
21 changed files with 1001 additions and 962 deletions

View File

@ -0,0 +1,133 @@
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/msm/qcom,sm8550-dpu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SM8550 Display DPU
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
$ref: /schemas/display/msm/dpu-common.yaml#
properties:
compatible:
const: qcom,sm8550-dpu
reg:
items:
- description: Address offset and size for mdp register set
- description: Address offset and size for vbif register set
reg-names:
items:
- const: mdp
- const: vbif
clocks:
items:
- description: Display AHB
- description: Display hf axi
- description: Display MDSS ahb
- description: Display lut
- description: Display core
- description: Display vsync
clock-names:
items:
- const: bus
- const: nrt_bus
- const: iface
- const: lut
- const: core
- const: vsync
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,sm8550-dispcc.h>
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
display-controller@ae01000 {
compatible = "qcom,sm8550-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp", "vbif";
clocks = <&gcc GCC_DISP_AHB_CLK>,
<&gcc GCC_DISP_HF_AXI_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "bus",
"nrt_bus",
"iface",
"lut",
"core",
"vsync";
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
assigned-clock-rates = <19200000>;
operating-points-v2 = <&mdp_opp_table>;
power-domains = <&rpmhpd SM8550_MMCX>;
interrupt-parent = <&mdss>;
interrupts = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
};
};
mdp_opp_table: opp-table {
compatible = "operating-points-v2";
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-325000000 {
opp-hz = /bits/ 64 <325000000>;
required-opps = <&rpmhpd_opp_svs>;
};
opp-375000000 {
opp-hz = /bits/ 64 <375000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
opp-514000000 {
opp-hz = /bits/ 64 <514000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};
...

View File

@ -401,6 +401,47 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
}
}
static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc,
struct drm_plane *plane,
struct dpu_crtc_mixer *mixer,
u32 num_mixers,
enum dpu_stage stage,
struct dpu_format *format,
uint64_t modifier,
struct dpu_sw_pipe *pipe,
unsigned int stage_idx,
struct dpu_hw_stage_cfg *stage_cfg
)
{
uint32_t lm_idx;
enum dpu_sspp sspp_idx;
struct drm_plane_state *state;
sspp_idx = pipe->sspp->idx;
state = plane->state;
trace_dpu_crtc_setup_mixer(DRMID(crtc), DRMID(plane),
state, to_dpu_plane_state(state), stage_idx,
format->base.pixel_format,
modifier);
DRM_DEBUG_ATOMIC("crtc %d stage:%d - plane %d sspp %d fb %d multirect_idx %d\n",
crtc->base.id,
stage,
plane->base.id,
sspp_idx - SSPP_NONE,
state->fb ? state->fb->base.id : -1,
pipe->multirect_index);
stage_cfg->stage[stage][stage_idx] = sspp_idx;
stage_cfg->multirect_index[stage][stage_idx] = pipe->multirect_index;
/* blend config update */
for (lm_idx = 0; lm_idx < num_mixers; lm_idx++)
mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl, sspp_idx);
}
static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer,
struct dpu_hw_stage_cfg *stage_cfg)
@ -413,15 +454,12 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct dpu_format *format;
struct dpu_hw_ctl *ctl = mixer->lm_ctl;
uint32_t stage_idx, lm_idx;
int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 };
uint32_t lm_idx;
bool bg_alpha_enable = false;
DECLARE_BITMAP(fetch_active, SSPP_MAX);
memset(fetch_active, 0, sizeof(fetch_active));
drm_atomic_crtc_for_each_plane(plane, crtc) {
enum dpu_sspp sspp_idx;
state = plane->state;
if (!state)
continue;
@ -432,40 +470,30 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
pstate = to_dpu_plane_state(state);
fb = state->fb;
sspp_idx = dpu_plane_pipe(plane);
set_bit(sspp_idx, fetch_active);
DRM_DEBUG_ATOMIC("crtc %d stage:%d - plane %d sspp %d fb %d\n",
crtc->base.id,
pstate->stage,
plane->base.id,
sspp_idx - SSPP_VIG0,
state->fb ? state->fb->base.id : -1);
format = to_dpu_format(msm_framebuffer_format(pstate->base.fb));
if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable)
bg_alpha_enable = true;
stage_idx = zpos_cnt[pstate->stage]++;
stage_cfg->stage[pstate->stage][stage_idx] =
sspp_idx;
stage_cfg->multirect_index[pstate->stage][stage_idx] =
pstate->multirect_index;
set_bit(pstate->pipe.sspp->idx, fetch_active);
_dpu_crtc_blend_setup_pipe(crtc, plane,
mixer, cstate->num_mixers,
pstate->stage,
format, fb ? fb->modifier : 0,
&pstate->pipe, 0, stage_cfg);
trace_dpu_crtc_setup_mixer(DRMID(crtc), DRMID(plane),
state, pstate, stage_idx,
sspp_idx - SSPP_VIG0,
format->base.pixel_format,
fb ? fb->modifier : 0);
if (pstate->r_pipe.sspp) {
set_bit(pstate->r_pipe.sspp->idx, fetch_active);
_dpu_crtc_blend_setup_pipe(crtc, plane,
mixer, cstate->num_mixers,
pstate->stage,
format, fb ? fb->modifier : 0,
&pstate->r_pipe, 1, stage_cfg);
}
/* blend config update */
for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
_dpu_crtc_setup_blend_cfg(mixer + lm_idx,
pstate, format);
mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl,
sspp_idx);
_dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format);
if (bg_alpha_enable && !format->alpha_enable)
mixer[lm_idx].mixer_op_mode = 0;
@ -768,7 +796,7 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc)
/* stage config flush mask */
ctl->ops.update_pending_flush_dspp(ctl,
mixer[i].hw_dspp->idx);
mixer[i].hw_dspp->idx, DPU_DSPP_PCC);
}
}
@ -1134,18 +1162,14 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(crtc);
}
struct plane_state {
struct dpu_plane_state *dpu_pstate;
const struct drm_plane_state *drm_pstate;
int stage;
u32 pipe_id;
};
static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
{
struct drm_crtc *crtc = cstate->crtc;
struct drm_encoder *encoder;
if (cstate->self_refresh_active)
return true;
drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) {
if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) {
return true;
@ -1162,151 +1186,46 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
crtc);
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
struct plane_state *pstates;
const struct drm_plane_state *pstate;
struct drm_plane *plane;
struct drm_display_mode *mode;
int cnt = 0, rc = 0, mixer_width = 0, i, z_pos;
int rc = 0;
struct dpu_multirect_plane_states multirect_plane[DPU_STAGE_MAX * 2];
int multirect_count = 0;
const struct drm_plane_state *pipe_staged[SSPP_MAX];
int left_zpos_cnt = 0, right_zpos_cnt = 0;
struct drm_rect crtc_rect = { 0 };
bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL);
if (!pstates)
return -ENOMEM;
if (!crtc_state->enable || !crtc_state->active) {
if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
crtc->base.id, crtc_state->enable,
crtc_state->active);
memset(&cstate->new_perf, 0, sizeof(cstate->new_perf));
goto end;
return 0;
}
mode = &crtc_state->adjusted_mode;
DRM_DEBUG_ATOMIC("%s: check\n", dpu_crtc->name);
/* force a full mode set if active state changed */
if (crtc_state->active_changed)
crtc_state->mode_changed = true;
memset(pipe_staged, 0, sizeof(pipe_staged));
if (cstate->num_mixers) {
mixer_width = mode->hdisplay / cstate->num_mixers;
if (cstate->num_mixers)
_dpu_crtc_setup_lm_bounds(crtc, crtc_state);
}
crtc_rect.x2 = mode->hdisplay;
crtc_rect.y2 = mode->vdisplay;
/* get plane state for all drm planes associated with crtc state */
/* FIXME: move this to dpu_plane_atomic_check? */
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
struct drm_rect dst, clip = crtc_rect;
if (IS_ERR_OR_NULL(pstate)) {
rc = PTR_ERR(pstate);
DPU_ERROR("%s: failed to get plane%d state, %d\n",
dpu_crtc->name, plane->base.id, rc);
goto end;
return rc;
}
if (cnt >= DPU_STAGE_MAX * 4)
continue;
if (!pstate->visible)
continue;
pstates[cnt].dpu_pstate = dpu_pstate;
pstates[cnt].drm_pstate = pstate;
pstates[cnt].stage = pstate->normalized_zpos;
pstates[cnt].pipe_id = dpu_plane_pipe(plane);
dpu_pstate->needs_dirtyfb = needs_dirtyfb;
if (pipe_staged[pstates[cnt].pipe_id]) {
multirect_plane[multirect_count].r0 =
pipe_staged[pstates[cnt].pipe_id];
multirect_plane[multirect_count].r1 = pstate;
multirect_count++;
pipe_staged[pstates[cnt].pipe_id] = NULL;
} else {
pipe_staged[pstates[cnt].pipe_id] = pstate;
}
cnt++;
dst = drm_plane_state_dest(pstate);
if (!drm_rect_intersect(&clip, &dst)) {
DPU_ERROR("invalid vertical/horizontal destination\n");
DPU_ERROR("display: " DRM_RECT_FMT " plane: "
DRM_RECT_FMT "\n", DRM_RECT_ARG(&crtc_rect),
DRM_RECT_ARG(&dst));
rc = -E2BIG;
goto end;
}
}
for (i = 1; i < SSPP_MAX; i++) {
if (pipe_staged[i])
dpu_plane_clear_multirect(pipe_staged[i]);
}
z_pos = -1;
for (i = 0; i < cnt; i++) {
/* reset counts at every new blend stage */
if (pstates[i].stage != z_pos) {
left_zpos_cnt = 0;
right_zpos_cnt = 0;
z_pos = pstates[i].stage;
}
/* verify z_pos setting before using it */
if (z_pos >= DPU_STAGE_MAX - DPU_STAGE_0) {
DPU_ERROR("> %d plane stages assigned\n",
DPU_STAGE_MAX - DPU_STAGE_0);
rc = -EINVAL;
goto end;
} else if (pstates[i].drm_pstate->crtc_x < mixer_width) {
if (left_zpos_cnt == 2) {
DPU_ERROR("> 2 planes @ stage %d on left\n",
z_pos);
rc = -EINVAL;
goto end;
}
left_zpos_cnt++;
} else {
if (right_zpos_cnt == 2) {
DPU_ERROR("> 2 planes @ stage %d on right\n",
z_pos);
rc = -EINVAL;
goto end;
}
right_zpos_cnt++;
}
pstates[i].dpu_pstate->stage = z_pos + DPU_STAGE_0;
DRM_DEBUG_ATOMIC("%s: zpos %d\n", dpu_crtc->name, z_pos);
}
for (i = 0; i < multirect_count; i++) {
if (dpu_plane_validate_multirect_v2(&multirect_plane[i])) {
DPU_ERROR(
"multirect validation failed for planes (%d - %d)\n",
multirect_plane[i].r0->plane->base.id,
multirect_plane[i].r1->plane->base.id);
rc = -EINVAL;
goto end;
}
}
atomic_inc(&_dpu_crtc_get_kms(crtc)->bandwidth_ref);
@ -1315,74 +1234,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
if (rc) {
DPU_ERROR("crtc%d failed performance check %d\n",
crtc->base.id, rc);
goto end;
return rc;
}
/* validate source split:
* use pstates sorted by stage to check planes on same stage
* we assume that all pipes are in source split so its valid to compare
* without taking into account left/right mixer placement
*/
for (i = 1; i < cnt; i++) {
struct plane_state *prv_pstate, *cur_pstate;
struct drm_rect left_rect, right_rect;
int32_t left_pid, right_pid;
int32_t stage;
prv_pstate = &pstates[i - 1];
cur_pstate = &pstates[i];
if (prv_pstate->stage != cur_pstate->stage)
continue;
stage = cur_pstate->stage;
left_pid = prv_pstate->dpu_pstate->base.plane->base.id;
left_rect = drm_plane_state_dest(prv_pstate->drm_pstate);
right_pid = cur_pstate->dpu_pstate->base.plane->base.id;
right_rect = drm_plane_state_dest(cur_pstate->drm_pstate);
if (right_rect.x1 < left_rect.x1) {
swap(left_pid, right_pid);
swap(left_rect, right_rect);
}
/**
* - planes are enumerated in pipe-priority order such that
* planes with lower drm_id must be left-most in a shared
* blend-stage when using source split.
* - planes in source split must be contiguous in width
* - planes in source split must have same dest yoff and height
*/
if (right_pid < left_pid) {
DPU_ERROR(
"invalid src split cfg. priority mismatch. stage: %d left: %d right: %d\n",
stage, left_pid, right_pid);
rc = -EINVAL;
goto end;
} else if (right_rect.x1 != drm_rect_width(&left_rect)) {
DPU_ERROR("non-contiguous coordinates for src split. "
"stage: %d left: " DRM_RECT_FMT " right: "
DRM_RECT_FMT "\n", stage,
DRM_RECT_ARG(&left_rect),
DRM_RECT_ARG(&right_rect));
rc = -EINVAL;
goto end;
} else if (left_rect.y1 != right_rect.y1 ||
drm_rect_height(&left_rect) != drm_rect_height(&right_rect)) {
DPU_ERROR("source split at stage: %d. invalid "
"yoff/height: left: " DRM_RECT_FMT " right: "
DRM_RECT_FMT "\n", stage,
DRM_RECT_ARG(&left_rect),
DRM_RECT_ARG(&right_rect));
rc = -EINVAL;
goto end;
}
}
end:
kfree(pstates);
return rc;
return 0;
}
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
@ -1499,8 +1354,16 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
state->crtc_x, state->crtc_y, state->crtc_w,
state->crtc_h);
seq_printf(s, "\tmultirect: mode: %d index: %d\n",
pstate->multirect_mode, pstate->multirect_index);
seq_printf(s, "\tsspp[0]:%s\n",
pstate->pipe.sspp->cap->name);
seq_printf(s, "\tmultirect[0]: mode: %d index: %d\n",
pstate->pipe.multirect_mode, pstate->pipe.multirect_index);
if (pstate->r_pipe.sspp) {
seq_printf(s, "\tsspp[1]:%s\n",
pstate->r_pipe.sspp->cap->name);
seq_printf(s, "\tmultirect[1]: mode: %d index: %d\n",
pstate->r_pipe.multirect_mode, pstate->r_pipe.multirect_index);
}
seq_puts(s, "\n");
}

View File

@ -545,7 +545,8 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
struct drm_display_mode *mode)
struct drm_display_mode *mode,
struct drm_crtc_state *crtc_state)
{
struct msm_display_topology topology = {0};
int i, intf_count = 0;
@ -563,8 +564,7 @@ static struct msm_display_topology dpu_encoder_get_topology(
* 1 LM, 1 INTF
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
*
* Adding color blocks only to primary interface if available in
* sufficient number
* Add dspps to the reservation requirements if ctm is requested
*/
if (intf_count == 2)
topology.num_lm = 2;
@ -573,11 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
else
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) {
if (dpu_kms->catalog->dspp &&
(dpu_kms->catalog->dspp_count >= topology.num_lm))
topology.num_dspp = topology.num_lm;
}
if (crtc_state->ctm)
topology.num_dspp = topology.num_lm;
topology.num_intf = intf_count;
@ -638,25 +635,22 @@ static int dpu_encoder_virt_atomic_check(
if (ret) {
DPU_ERROR_ENC(dpu_enc,
"mode unsupported, phys idx %d\n", i);
break;
return ret;
}
}
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state);
/* Reserve dynamic resources now. */
if (!ret) {
/*
* Release and Allocate resources on every modeset
* Dont allocate when active is false.
*/
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
dpu_rm_release(global_state, drm_enc);
/*
* Release and Allocate resources on every modeset
* Dont allocate when active is false.
*/
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
dpu_rm_release(global_state, drm_enc);
if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
drm_enc, crtc_state, topology);
}
if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
drm_enc, crtc_state, topology);
}
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
@ -2094,25 +2088,6 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl);
}
void dpu_encoder_prepare_commit(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
struct dpu_encoder_phys *phys;
int i;
if (!drm_enc) {
DPU_ERROR("invalid encoder\n");
return;
}
dpu_enc = to_dpu_encoder_virt(drm_enc);
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
phys = dpu_enc->phys_encs[i];
if (phys->ops.prepare_commit)
phys->ops.prepare_commit(phys);
}
}
#ifdef CONFIG_DEBUG_FS
static int _dpu_encoder_status_show(struct seq_file *s, void *data)
{

View File

@ -146,13 +146,6 @@ struct drm_encoder *dpu_encoder_init(
int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
struct msm_display_info *disp_info);
/**
* dpu_encoder_prepare_commit - prepare encoder at the very beginning of an
* atomic commit, before any registers are written
* @drm_enc: Pointer to previously created drm encoder structure
*/
void dpu_encoder_prepare_commit(struct drm_encoder *drm_enc);
/**
* dpu_encoder_set_idle_timeout - set the idle timeout for video
* and command mode encoders.

View File

@ -40,6 +40,8 @@
#define DPU_ENC_MAX_POLL_TIMEOUT_US 2000
static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc);
static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc)
{
return (phys_enc->split_role != ENC_ROLE_SLAVE);
@ -565,6 +567,8 @@ static void dpu_encoder_phys_cmd_prepare_for_kickoff(
phys_enc->hw_pp->idx - PINGPONG_0);
}
dpu_encoder_phys_cmd_enable_te(phys_enc);
DPU_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n",
phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(&phys_enc->pending_kickoff_cnt));
@ -586,8 +590,7 @@ static bool dpu_encoder_phys_cmd_is_ongoing_pptx(
return false;
}
static void dpu_encoder_phys_cmd_prepare_commit(
struct dpu_encoder_phys *phys_enc)
static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc)
{
struct dpu_encoder_phys_cmd *cmd_enc =
to_dpu_encoder_phys_cmd(phys_enc);
@ -732,7 +735,6 @@ static void dpu_encoder_phys_cmd_trigger_start(
static void dpu_encoder_phys_cmd_init_ops(
struct dpu_encoder_phys_ops *ops)
{
ops->prepare_commit = dpu_encoder_phys_cmd_prepare_commit;
ops->is_master = dpu_encoder_phys_cmd_is_master;
ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set;
ops->enable = dpu_encoder_phys_cmd_enable;

View File

@ -536,6 +536,16 @@ static const struct dpu_format dpu_format_map_ubwc[] = {
true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
/* XRGB2101010 and ARGB2101010 purposely have the same color
* ordering. The hardware only supports ARGB2101010 UBWC
* natively.
*/
INTERLEAVED_RGB_FMT_TILED(ARGB2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
PSEUDO_YUV_FMT_TILED(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr,
@ -591,6 +601,7 @@ static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
{DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_ARGB2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
@ -918,8 +929,7 @@ int dpu_format_populate_layout(
struct drm_framebuffer *fb,
struct dpu_hw_fmt_layout *layout)
{
uint32_t plane_addr[DPU_MAX_PLANES];
int i, ret;
int ret;
if (!fb || !layout) {
DRM_ERROR("invalid arguments\n");
@ -940,9 +950,6 @@ int dpu_format_populate_layout(
if (ret)
return ret;
for (i = 0; i < DPU_MAX_PLANES; ++i)
plane_addr[i] = layout->plane_addr[i];
/* Populate the addresses given the fb */
if (DPU_FORMAT_IS_UBWC(layout->format) ||
DPU_FORMAT_IS_TILE(layout->format))
@ -950,10 +957,6 @@ int dpu_format_populate_layout(
else
ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
/* check if anything changed */
if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr)))
ret = -EAGAIN;
return ret;
}

View File

@ -27,9 +27,15 @@
#define VIG_SDM845_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3))
#define VIG_SDM845_MASK_SDMA \
(VIG_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define VIG_SC7180_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED4))
#define VIG_SC7180_MASK_SDMA \
(VIG_SC7180_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))
#define DMA_MSM8998_MASK \
@ -40,6 +46,9 @@
#define VIG_SC7280_MASK \
(VIG_SC7180_MASK | BIT(DPU_SSPP_INLINE_ROTATION))
#define VIG_SC7280_MASK_SDMA \
(VIG_SC7280_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define DMA_SDM845_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
@ -48,6 +57,12 @@
#define DMA_CURSOR_SDM845_MASK \
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
#define DMA_SDM845_MASK_SDMA \
(DMA_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define DMA_CURSOR_SDM845_MASK_SDMA \
(DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define DMA_CURSOR_MSM8998_MASK \
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
@ -66,7 +81,10 @@
(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
#define CTL_SC7280_MASK \
(BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_FETCH_ACTIVE) | BIT(DPU_CTL_VM_CFG))
(BIT(DPU_CTL_ACTIVE_CFG) | \
BIT(DPU_CTL_FETCH_ACTIVE) | \
BIT(DPU_CTL_VM_CFG) | \
BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH))
#define CTL_SM8550_MASK \
(CTL_SC7280_MASK | BIT(DPU_CTL_HAS_LAYER_EXT4))
@ -189,6 +207,7 @@ static const uint32_t plane_formats[] = {
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
@ -218,6 +237,7 @@ static const uint32_t plane_formats_yuv[] = {
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
@ -303,7 +323,6 @@ static const struct dpu_caps msm8998_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x7,
.qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
.ubwc_version = DPU_HW_UBWC_VER_10,
.has_src_split = true,
.has_dim_layer = true,
@ -318,7 +337,6 @@ static const struct dpu_caps msm8998_dpu_caps = {
static const struct dpu_caps qcm2290_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
.max_mixer_blendstages = 0x4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.has_dim_layer = true,
.has_idle_pc = true,
.max_linewidth = 2160,
@ -329,7 +347,6 @@ static const struct dpu_caps sdm845_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_20,
.has_src_split = true,
.has_dim_layer = true,
@ -345,7 +362,6 @@ static const struct dpu_caps sc7180_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x9,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_20,
.has_dim_layer = true,
.has_idle_pc = true,
@ -357,7 +373,6 @@ static const struct dpu_caps sm6115_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
.max_mixer_blendstages = 0x4,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_10,
.has_dim_layer = true,
.has_idle_pc = true,
@ -369,7 +384,6 @@ static const struct dpu_caps sm8150_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_30,
.has_src_split = true,
.has_dim_layer = true,
@ -385,7 +399,6 @@ static const struct dpu_caps sc8180x_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_30,
.has_src_split = true,
.has_dim_layer = true,
@ -401,7 +414,6 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
.max_mixer_width = 2560,
.max_mixer_blendstages = 11,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
.has_dim_layer = true,
@ -415,7 +427,6 @@ static const struct dpu_caps sm8250_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
.has_dim_layer = true,
@ -429,7 +440,6 @@ static const struct dpu_caps sm8350_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
.has_dim_layer = true,
@ -443,7 +453,6 @@ static const struct dpu_caps sm8450_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
.has_dim_layer = true,
@ -457,7 +466,6 @@ static const struct dpu_caps sm8550_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
.has_dim_layer = true,
@ -471,7 +479,6 @@ static const struct dpu_caps sc7280_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x7,
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_30,
.has_dim_layer = true,
.has_idle_pc = true,
@ -1197,21 +1204,21 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = {
};
static const struct dpu_sspp_cfg sdm845_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK_SDMA,
sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SDM845_MASK,
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SDM845_MASK_SDMA,
sdm845_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SDM845_MASK,
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SDM845_MASK_SDMA,
sdm845_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SDM845_MASK,
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SDM845_MASK_SDMA,
sdm845_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK_SDMA,
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK_SDMA,
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),
};
@ -1252,21 +1259,21 @@ static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 =
_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4);
static const struct dpu_sspp_cfg sm8250_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK,
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK_SDMA,
sm8250_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK,
SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK_SDMA,
sm8250_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK,
SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK_SDMA,
sm8250_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK,
SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK_SDMA,
sm8250_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK_SDMA,
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK_SDMA,
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),
};
@ -1333,13 +1340,13 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = {
};
static const struct dpu_sspp_cfg sc7280_sspp[] = {
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7280_MASK,
SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7280_MASK_SDMA,
sc7280_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK_SDMA,
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK_SDMA,
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),
};

View File

@ -19,8 +19,9 @@
*/
#define MAX_BLOCKS 12
#define DPU_HW_VER(MAJOR, MINOR, STEP) (((MAJOR & 0xF) << 28) |\
((MINOR & 0xFFF) << 16) |\
#define DPU_HW_VER(MAJOR, MINOR, STEP) \
((((unsigned int)MAJOR & 0xF) << 28) | \
((MINOR & 0xFFF) << 16) | \
(STEP & 0xFFFF))
#define DPU_HW_MAJOR(rev) ((rev) >> 28)
@ -169,10 +170,12 @@ enum {
* DSPP sub-blocks
* @DPU_DSPP_PCC Panel color correction block
* @DPU_DSPP_GC Gamma correction block
* @DPU_DSPP_IGC Inverse gamma correction block
*/
enum {
DPU_DSPP_PCC = 0x1,
DPU_DSPP_GC,
DPU_DSPP_IGC,
DPU_DSPP_MAX
};
@ -200,6 +203,7 @@ enum {
* @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs)
* @DPU_CTL_VM_CFG: CTL config to support multiple VMs
* @DPU_CTL_HAS_LAYER_EXT4: CTL has the CTL_LAYER_EXT4 register
* @DPU_CTL_DSPP_BLOCK_FLUSH: CTL config to support dspp sub-block flush
* @DPU_CTL_MAX
*/
enum {
@ -208,6 +212,7 @@ enum {
DPU_CTL_FETCH_ACTIVE,
DPU_CTL_VM_CFG,
DPU_CTL_HAS_LAYER_EXT4,
DPU_CTL_DSPP_SUB_BLOCK_FLUSH,
DPU_CTL_MAX
};
@ -395,7 +400,6 @@ struct dpu_rotation_cfg {
* @max_mixer_blendstages max layer mixer blend stages or
* supported z order
* @qseed_type qseed2 or qseed3 support.
* @smart_dma_rev Supported version of SmartDMA feature.
* @ubwc_version UBWC feature version (0x0 for not supported)
* @has_src_split source split feature status
* @has_dim_layer dim layer feature status
@ -410,7 +414,6 @@ struct dpu_caps {
u32 max_mixer_width;
u32 max_mixer_blendstages;
u32 qseed_type;
u32 smart_dma_rev;
u32 ubwc_version;
bool has_src_split;
bool has_dim_layer;

View File

@ -26,15 +26,16 @@
#define CTL_SW_RESET 0x030
#define CTL_LAYER_EXTN_OFFSET 0x40
#define CTL_MERGE_3D_ACTIVE 0x0E4
#define CTL_DSC_ACTIVE 0x0E8
#define CTL_WB_ACTIVE 0x0EC
#define CTL_INTF_ACTIVE 0x0F4
#define CTL_FETCH_PIPE_ACTIVE 0x0FC
#define CTL_MERGE_3D_FLUSH 0x100
#define CTL_DSC_ACTIVE 0x0E8
#define CTL_DSC_FLUSH 0x104
#define CTL_WB_FLUSH 0x108
#define CTL_INTF_FLUSH 0x110
#define CTL_INTF_MASTER 0x134
#define CTL_FETCH_PIPE_ACTIVE 0x0FC
#define CTL_DSPP_n_FLUSH(n) ((0x13C) + ((n) * 4))
#define CTL_MIXER_BORDER_OUT BIT(24)
#define CTL_FLUSH_MASK_CTL BIT(17)
@ -44,6 +45,7 @@
#define DSC_IDX 22
#define INTF_IDX 31
#define WB_IDX 16
#define DSPP_IDX 29 /* From DPU hw rev 7.x.x */
#define CTL_INVALID_BIT 0xffff
#define CTL_DEFAULT_GROUP_ID 0xf
@ -115,6 +117,9 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
dpu_hw_ctl_get_flush_register(ctx));
ctx->pending_flush_mask = 0x0;
memset(ctx->pending_dspp_flush_mask, 0,
sizeof(ctx->pending_dspp_flush_mask));
}
static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx,
@ -132,6 +137,8 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
{
int dspp;
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@ -142,6 +149,13 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
ctx->pending_wb_flush_mask);
if (ctx->pending_flush_mask & BIT(DSPP_IDX))
for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {
if (ctx->pending_dspp_flush_mask[dspp - DSPP_0])
DPU_REG_WRITE(&ctx->hw,
CTL_DSPP_n_FLUSH(dspp - DSPP_0),
ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
}
DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
}
@ -289,7 +303,7 @@ static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
}
static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
enum dpu_dspp dspp)
enum dpu_dspp dspp, u32 dspp_sub_blk)
{
switch (dspp) {
case DSPP_0:
@ -309,6 +323,29 @@ static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
}
}
static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(
struct dpu_hw_ctl *ctx, enum dpu_dspp dspp, u32 dspp_sub_blk)
{
if (dspp >= DSPP_MAX)
return;
switch (dspp_sub_blk) {
case DPU_DSPP_IGC:
ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(2);
break;
case DPU_DSPP_PCC:
ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);
break;
case DPU_DSPP_GC:
ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(5);
break;
default:
return;
}
ctx->pending_flush_mask |= BIT(DSPP_IDX);
}
static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
@ -630,7 +667,11 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp;
ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer;
ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;
if (cap & BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH))
ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks;
else
ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;
if (cap & BIT(DPU_CTL_FETCH_ACTIVE))
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
};

View File

@ -152,9 +152,11 @@ struct dpu_hw_ctl_ops {
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : DSPP block index
* @dspp_sub_blk : DSPP sub-block index
*/
void (*update_pending_flush_dspp)(struct dpu_hw_ctl *ctx,
enum dpu_dspp blk);
enum dpu_dspp blk, u32 dspp_sub_blk);
/**
* Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer
@ -242,6 +244,7 @@ struct dpu_hw_ctl {
u32 pending_intf_flush_mask;
u32 pending_wb_flush_mask;
u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
/* ops */
struct dpu_hw_ctl_ops ops;

View File

@ -136,7 +136,7 @@
#define TS_CLK 19200000
static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx,
static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx,
int s_id,
u32 *idx)
{
@ -168,17 +168,16 @@ static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx,
return rc;
}
static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx,
enum dpu_sspp_multirect_index index,
enum dpu_sspp_multirect_mode mode)
static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 mode_mask;
u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return;
if (index == DPU_SSPP_RECT_SOLO) {
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
/**
* if rect index is RECT_SOLO, we cannot expect a
* virtual plane sharing the same SSPP id. So we go
@ -187,8 +186,8 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx,
mode_mask = 0;
} else {
mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx);
mode_mask |= index;
if (mode == DPU_SSPP_MULTIRECT_TIME_MX)
mode_mask |= pipe->multirect_index;
if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX)
mode_mask |= BIT(2);
else
mode_mask &= ~BIT(2);
@ -197,7 +196,7 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx, mode_mask);
}
static void _sspp_setup_opmode(struct dpu_hw_pipe *ctx,
static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
{
u32 idx;
@ -218,7 +217,7 @@ static void _sspp_setup_opmode(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(&ctx->hw, SSPP_VIG_OP_MODE + idx, opmode);
}
static void _sspp_setup_csc10_opmode(struct dpu_hw_pipe *ctx,
static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
{
u32 idx;
@ -239,10 +238,10 @@ static void _sspp_setup_csc10_opmode(struct dpu_hw_pipe *ctx,
/*
* Setup source pixel format, flip,
*/
static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx,
const struct dpu_format *fmt, u32 flags,
enum dpu_sspp_multirect_index rect_mode)
static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, u32 flags)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_blk_reg_map *c;
u32 chroma_samp, unpack, src_format;
u32 opmode = 0;
@ -253,7 +252,8 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx,
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !fmt)
return;
if (rect_mode == DPU_SSPP_RECT_SOLO || rect_mode == DPU_SSPP_RECT_0) {
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
pipe->multirect_index == DPU_SSPP_RECT_0) {
op_mode_off = SSPP_SRC_OP_MODE;
unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
format_off = SSPP_SRC_FORMAT;
@ -360,7 +360,7 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
}
static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx,
static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,
struct dpu_hw_pixel_ext *pe_ext)
{
struct dpu_hw_blk_reg_map *c;
@ -418,23 +418,22 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx,
tot_req_pixels[3]);
}
static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *sspp,
void *scaler_cfg)
static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp *ctx,
struct dpu_hw_scaler3_cfg *scaler3_cfg,
const struct dpu_format *format)
{
u32 idx;
struct dpu_hw_scaler3_cfg *scaler3_cfg = scaler_cfg;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp
if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx)
|| !scaler3_cfg)
return;
dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx,
ctx->cap->sblk->scaler_blk.version,
sspp->layout.format);
format);
}
static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_pipe *ctx)
static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_sspp *ctx)
{
u32 idx;
@ -447,12 +446,12 @@ static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_pipe *ctx)
/*
* dpu_hw_sspp_setup_rects()
*/
static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *cfg,
enum dpu_sspp_multirect_index rect_index)
static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,
struct dpu_sw_pipe_cfg *cfg)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_blk_reg_map *c;
u32 src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
u32 src_size, src_xy, dst_size, dst_xy;
u32 src_size_off, src_xy_off, out_size_off, out_xy_off;
u32 idx;
@ -461,7 +460,8 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx,
c = &ctx->hw;
if (rect_index == DPU_SSPP_RECT_SOLO || rect_index == DPU_SSPP_RECT_0) {
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
pipe->multirect_index == DPU_SSPP_RECT_0) {
src_size_off = SSPP_SRC_SIZE;
src_xy_off = SSPP_SRC_XY;
out_size_off = SSPP_OUT_SIZE;
@ -482,68 +482,69 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx,
dst_size = (drm_rect_height(&cfg->dst_rect) << 16) |
drm_rect_width(&cfg->dst_rect);
if (rect_index == DPU_SSPP_RECT_SOLO) {
ystride0 = (cfg->layout.plane_pitch[0]) |
(cfg->layout.plane_pitch[1] << 16);
ystride1 = (cfg->layout.plane_pitch[2]) |
(cfg->layout.plane_pitch[3] << 16);
} else {
ystride0 = DPU_REG_READ(c, SSPP_SRC_YSTRIDE0 + idx);
ystride1 = DPU_REG_READ(c, SSPP_SRC_YSTRIDE1 + idx);
if (rect_index == DPU_SSPP_RECT_0) {
ystride0 = (ystride0 & 0xFFFF0000) |
(cfg->layout.plane_pitch[0] & 0x0000FFFF);
ystride1 = (ystride1 & 0xFFFF0000)|
(cfg->layout.plane_pitch[2] & 0x0000FFFF);
} else {
ystride0 = (ystride0 & 0x0000FFFF) |
((cfg->layout.plane_pitch[0] << 16) &
0xFFFF0000);
ystride1 = (ystride1 & 0x0000FFFF) |
((cfg->layout.plane_pitch[2] << 16) &
0xFFFF0000);
}
}
/* rectangle register programming */
DPU_REG_WRITE(c, src_size_off + idx, src_size);
DPU_REG_WRITE(c, src_xy_off + idx, src_xy);
DPU_REG_WRITE(c, out_size_off + idx, dst_size);
DPU_REG_WRITE(c, out_xy_off + idx, dst_xy);
DPU_REG_WRITE(c, SSPP_SRC_YSTRIDE0 + idx, ystride0);
DPU_REG_WRITE(c, SSPP_SRC_YSTRIDE1 + idx, ystride1);
}
static void dpu_hw_sspp_setup_sourceaddress(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *cfg,
enum dpu_sspp_multirect_index rect_mode)
static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
struct dpu_hw_fmt_layout *layout)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 ystride0, ystride1;
int i;
u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return;
if (rect_mode == DPU_SSPP_RECT_SOLO) {
for (i = 0; i < ARRAY_SIZE(cfg->layout.plane_addr); i++)
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++)
DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4,
cfg->layout.plane_addr[i]);
} else if (rect_mode == DPU_SSPP_RECT_0) {
layout->plane_addr[i]);
} else if (pipe->multirect_index == DPU_SSPP_RECT_0) {
DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx,
cfg->layout.plane_addr[0]);
layout->plane_addr[0]);
DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR + idx,
cfg->layout.plane_addr[2]);
layout->plane_addr[2]);
} else {
DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR + idx,
cfg->layout.plane_addr[0]);
layout->plane_addr[0]);
DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR + idx,
cfg->layout.plane_addr[2]);
layout->plane_addr[2]);
}
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
ystride0 = (layout->plane_pitch[0]) |
(layout->plane_pitch[1] << 16);
ystride1 = (layout->plane_pitch[2]) |
(layout->plane_pitch[3] << 16);
} else {
ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx);
ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx);
if (pipe->multirect_index == DPU_SSPP_RECT_0) {
ystride0 = (ystride0 & 0xFFFF0000) |
(layout->plane_pitch[0] & 0x0000FFFF);
ystride1 = (ystride1 & 0xFFFF0000)|
(layout->plane_pitch[2] & 0x0000FFFF);
} else {
ystride0 = (ystride0 & 0x0000FFFF) |
((layout->plane_pitch[0] << 16) &
0xFFFF0000);
ystride1 = (ystride1 & 0x0000FFFF) |
((layout->plane_pitch[2] << 16) &
0xFFFF0000);
}
}
DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx, ystride0);
DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx, ystride1);
}
static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx,
static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx,
const struct dpu_csc_cfg *data)
{
u32 idx;
@ -560,22 +561,28 @@ static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx,
dpu_hw_csc_setup(&ctx->hw, idx, data, csc10);
}
static void dpu_hw_sspp_setup_solidfill(struct dpu_hw_pipe *ctx, u32 color, enum
dpu_sspp_multirect_index rect_index)
static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_fmt_layout cfg;
u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return;
if (rect_index == DPU_SSPP_RECT_SOLO || rect_index == DPU_SSPP_RECT_0)
/* cleanup source addresses */
memset(&cfg, 0, sizeof(cfg));
ctx->ops.setup_sourceaddress(pipe, &cfg);
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
pipe->multirect_index == DPU_SSPP_RECT_0)
DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color);
else
DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx,
color);
}
static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx,
static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_sspp *ctx,
u32 danger_lut,
u32 safe_lut)
{
@ -588,7 +595,7 @@ static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut);
}
static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx,
static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_sspp *ctx,
u64 creq_lut)
{
u32 idx;
@ -605,7 +612,7 @@ static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx,
}
}
static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx,
static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,
struct dpu_hw_pipe_qos_cfg *cfg)
{
u32 idx;
@ -630,10 +637,10 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl);
}
static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
struct dpu_hw_cdp_cfg *cfg,
enum dpu_sspp_multirect_index index)
static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
struct dpu_hw_cdp_cfg *cfg)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 idx;
u32 cdp_cntl = 0;
u32 cdp_cntl_offset = 0;
@ -644,7 +651,8 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return;
if (index == DPU_SSPP_RECT_SOLO || index == DPU_SSPP_RECT_0)
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
pipe->multirect_index == DPU_SSPP_RECT_0)
cdp_cntl_offset = SSPP_CDP_CNTL;
else
cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
@ -661,7 +669,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(&ctx->hw, cdp_cntl_offset, cdp_cntl);
}
static void _setup_layer_ops(struct dpu_hw_pipe *c,
static void _setup_layer_ops(struct dpu_hw_sspp *c,
unsigned long features)
{
if (test_bit(DPU_SSPP_SRC, &features)) {
@ -699,7 +707,8 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c,
}
#ifdef CONFIG_DEBUG_FS
int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms, struct dentry *entry)
int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
struct dentry *entry)
{
const struct dpu_sspp_cfg *cfg = hw_pipe->cap;
const struct dpu_sspp_sub_blks *sblk = cfg->sblk;
@ -783,10 +792,10 @@ static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
return ERR_PTR(-ENOMEM);
}
struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx,
void __iomem *addr, const struct dpu_mdss_cfg *catalog)
{
struct dpu_hw_pipe *hw_pipe;
struct dpu_hw_sspp *hw_pipe;
const struct dpu_sspp_cfg *cfg;
if (!addr || !catalog)
@ -812,7 +821,7 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
return hw_pipe;
}
void dpu_hw_sspp_destroy(struct dpu_hw_pipe *ctx)
void dpu_hw_sspp_destroy(struct dpu_hw_sspp *ctx)
{
kfree(ctx);
}

View File

@ -10,7 +10,7 @@
#include "dpu_hw_util.h"
#include "dpu_formats.h"
struct dpu_hw_pipe;
struct dpu_hw_sspp;
/**
* Flags
@ -153,20 +153,14 @@ struct dpu_hw_pixel_ext {
};
/**
* struct dpu_hw_pipe_cfg : Pipe description
* @layout: format layout information for programming buffer to hardware
* struct dpu_sw_pipe_cfg : software pipe configuration
* @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field
* @dest_rect: destination ROI.
* @index: index of the rectangle of SSPP
* @mode: parallel or time multiplex multirect mode
*/
struct dpu_hw_pipe_cfg {
struct dpu_hw_fmt_layout layout;
struct dpu_sw_pipe_cfg {
struct drm_rect src_rect;
struct drm_rect dst_rect;
enum dpu_sspp_multirect_index index;
enum dpu_sspp_multirect_mode mode;
};
/**
@ -201,6 +195,18 @@ struct dpu_hw_pipe_ts_cfg {
u64 time;
};
/**
* struct dpu_sw_pipe - software pipe description
* @sspp: backing SSPP pipe
* @index: index of the rectangle of SSPP
* @mode: parallel or time multiplex multirect mode
*/
struct dpu_sw_pipe {
struct dpu_hw_sspp *sspp;
enum dpu_sspp_multirect_index multirect_index;
enum dpu_sspp_multirect_mode multirect_mode;
};
/**
* struct dpu_hw_sspp_ops - interface to the SSPP Hw driver functions
* Caller must call the init function to get the pipe context for each pipe
@ -209,77 +215,65 @@ struct dpu_hw_pipe_ts_cfg {
struct dpu_hw_sspp_ops {
/**
* setup_format - setup pixel format cropping rectangle, flip
* @ctx: Pointer to pipe context
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
* @flags: Extra flags for format config
* @index: rectangle index in multirect
*/
void (*setup_format)(struct dpu_hw_pipe *ctx,
const struct dpu_format *fmt, u32 flags,
enum dpu_sspp_multirect_index index);
void (*setup_format)(struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, u32 flags);
/**
* setup_rects - setup pipe ROI rectangles
* @ctx: Pointer to pipe context
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
* @index: rectangle index in multirect
*/
void (*setup_rects)(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *cfg,
enum dpu_sspp_multirect_index index);
void (*setup_rects)(struct dpu_sw_pipe *pipe,
struct dpu_sw_pipe_cfg *cfg);
/**
* setup_pe - setup pipe pixel extension
* @ctx: Pointer to pipe context
* @pe_ext: Pointer to pixel ext settings
*/
void (*setup_pe)(struct dpu_hw_pipe *ctx,
void (*setup_pe)(struct dpu_hw_sspp *ctx,
struct dpu_hw_pixel_ext *pe_ext);
/**
* setup_sourceaddress - setup pipe source addresses
* @ctx: Pointer to pipe context
* @cfg: Pointer to pipe config structure
* @index: rectangle index in multirect
* @pipe: Pointer to software pipe context
* @layout: format layout information for programming buffer to hardware
*/
void (*setup_sourceaddress)(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *cfg,
enum dpu_sspp_multirect_index index);
void (*setup_sourceaddress)(struct dpu_sw_pipe *ctx,
struct dpu_hw_fmt_layout *layout);
/**
* setup_csc - setup color space coversion
* @ctx: Pointer to pipe context
* @data: Pointer to config structure
*/
void (*setup_csc)(struct dpu_hw_pipe *ctx, const struct dpu_csc_cfg *data);
void (*setup_csc)(struct dpu_hw_sspp *ctx, const struct dpu_csc_cfg *data);
/**
* setup_solidfill - enable/disable colorfill
* @ctx: Pointer to pipe context
* @pipe: Pointer to software pipe context
* @const_color: Fill color value
* @flags: Pipe flags
* @index: rectangle index in multirect
*/
void (*setup_solidfill)(struct dpu_hw_pipe *ctx, u32 color,
enum dpu_sspp_multirect_index index);
void (*setup_solidfill)(struct dpu_sw_pipe *pipe, u32 color);
/**
* setup_multirect - setup multirect configuration
* @ctx: Pointer to pipe context
* @index: rectangle index in multirect
* @mode: parallel fetch / time multiplex multirect mode
* @pipe: Pointer to software pipe context
*/
void (*setup_multirect)(struct dpu_hw_pipe *ctx,
enum dpu_sspp_multirect_index index,
enum dpu_sspp_multirect_mode mode);
void (*setup_multirect)(struct dpu_sw_pipe *pipe);
/**
* setup_sharpening - setup sharpening
* @ctx: Pointer to pipe context
* @cfg: Pointer to config structure
*/
void (*setup_sharpening)(struct dpu_hw_pipe *ctx,
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
struct dpu_hw_sharp_cfg *cfg);
/**
@ -289,7 +283,7 @@ struct dpu_hw_sspp_ops {
* @safe_lut: LUT for generate safe level based on fill level
*
*/
void (*setup_danger_safe_lut)(struct dpu_hw_pipe *ctx,
void (*setup_danger_safe_lut)(struct dpu_hw_sspp *ctx,
u32 danger_lut,
u32 safe_lut);
@ -299,7 +293,7 @@ struct dpu_hw_sspp_ops {
* @creq_lut: LUT for generate creq level based on fill level
*
*/
void (*setup_creq_lut)(struct dpu_hw_pipe *ctx,
void (*setup_creq_lut)(struct dpu_hw_sspp *ctx,
u64 creq_lut);
/**
@ -308,7 +302,7 @@ struct dpu_hw_sspp_ops {
* @cfg: Pointer to pipe QoS configuration
*
*/
void (*setup_qos_ctrl)(struct dpu_hw_pipe *ctx,
void (*setup_qos_ctrl)(struct dpu_hw_sspp *ctx,
struct dpu_hw_pipe_qos_cfg *cfg);
/**
@ -316,38 +310,35 @@ struct dpu_hw_sspp_ops {
* @ctx: Pointer to pipe context
* @cfg: Pointer to histogram configuration
*/
void (*setup_histogram)(struct dpu_hw_pipe *ctx,
void (*setup_histogram)(struct dpu_hw_sspp *ctx,
void *cfg);
/**
* setup_scaler - setup scaler
* @ctx: Pointer to pipe context
* @pipe_cfg: Pointer to pipe configuration
* @scaler_cfg: Pointer to scaler configuration
* @scaler3_cfg: Pointer to scaler configuration
* @format: pixel format parameters
*/
void (*setup_scaler)(struct dpu_hw_pipe *ctx,
struct dpu_hw_pipe_cfg *pipe_cfg,
void *scaler_cfg);
void (*setup_scaler)(struct dpu_hw_sspp *ctx,
struct dpu_hw_scaler3_cfg *scaler3_cfg,
const struct dpu_format *format);
/**
* get_scaler_ver - get scaler h/w version
* @ctx: Pointer to pipe context
*/
u32 (*get_scaler_ver)(struct dpu_hw_pipe *ctx);
u32 (*get_scaler_ver)(struct dpu_hw_sspp *ctx);
/**
* setup_cdp - setup client driven prefetch
* @ctx: Pointer to pipe context
* @pipe: Pointer to software pipe context
* @cfg: Pointer to cdp configuration
* @index: rectangle index in multirect
*/
void (*setup_cdp)(struct dpu_hw_pipe *ctx,
struct dpu_hw_cdp_cfg *cfg,
enum dpu_sspp_multirect_index index);
void (*setup_cdp)(struct dpu_sw_pipe *pipe,
struct dpu_hw_cdp_cfg *cfg);
};
/**
* struct dpu_hw_pipe - pipe description
* struct dpu_hw_sspp - pipe description
* @base: hardware block base structure
* @hw: block hardware details
* @catalog: back pointer to catalog
@ -356,7 +347,7 @@ struct dpu_hw_sspp_ops {
* @cap: pointer to layer_cfg
* @ops: pointer to operations possible for this pipe
*/
struct dpu_hw_pipe {
struct dpu_hw_sspp {
struct dpu_hw_blk base;
struct dpu_hw_blk_reg_map hw;
const struct dpu_mdss_cfg *catalog;
@ -378,7 +369,7 @@ struct dpu_kms;
* @addr: Mapped register io address of MDP
* @catalog : Pointer to mdss catalog data
*/
struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx,
void __iomem *addr, const struct dpu_mdss_cfg *catalog);
/**
@ -386,10 +377,10 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
* should be called during Hw pipe cleanup.
* @ctx: Pointer to SSPP driver context returned by dpu_hw_sspp_init
*/
void dpu_hw_sspp_destroy(struct dpu_hw_pipe *ctx);
void dpu_hw_sspp_destroy(struct dpu_hw_sspp *ctx);
void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root);
int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms, struct dentry *entry);
int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
struct dentry *entry);
#endif /*_DPU_HW_SSPP_H */

View File

@ -250,6 +250,24 @@ void dpu_debugfs_create_regset32(const char *name, umode_t mode,
debugfs_create_file(name, mode, parent, regset, &dpu_regset32_fops);
}
static void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
{
struct dentry *entry = debugfs_create_dir("sspp", debugfs_root);
int i;
if (IS_ERR(entry))
return;
for (i = SSPP_NONE; i < SSPP_MAX; i++) {
struct dpu_hw_sspp *hw = dpu_rm_get_sspp(&dpu_kms->rm, i);
if (!hw)
continue;
_dpu_hw_sspp_init_debugfs(hw, dpu_kms, entry);
}
}
static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
@ -411,26 +429,6 @@ static void dpu_kms_disable_commit(struct msm_kms *kms)
pm_runtime_put_sync(&dpu_kms->pdev->dev);
}
static void dpu_kms_prepare_commit(struct msm_kms *kms,
struct drm_atomic_state *state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
struct drm_encoder *encoder;
int i;
if (!kms)
return;
/* Call prepare_commit for all affected encoders */
for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
drm_for_each_encoder_mask(encoder, crtc->dev,
crtc_state->encoder_mask) {
dpu_encoder_prepare_commit(encoder);
}
}
}
static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
@ -939,7 +937,6 @@ static const struct msm_kms_funcs kms_funcs = {
.irq = dpu_core_irq,
.enable_commit = dpu_kms_enable_commit,
.disable_commit = dpu_kms_disable_commit,
.prepare_commit = dpu_kms_prepare_commit,
.flush_commit = dpu_kms_flush_commit,
.wait_flush = dpu_kms_wait_flush,
.complete_commit = dpu_kms_complete_commit,

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,10 @@
* struct dpu_plane_state: Define dpu extension of drm plane state object
* @base: base drm plane state object
* @aspace: pointer to address space for input/output buffers
* @pipe: software pipe description
* @r_pipe: software pipe description of the second pipe
* @pipe_cfg: software pipe configuration
* @r_pipe_cfg: software pipe configuration for the second pipe
* @stage: assigned by crtc blender
* @needs_qos_remap: qos remap settings need to be updated
* @multirect_index: index of the rectangle of SSPP
@ -31,10 +35,12 @@
struct dpu_plane_state {
struct drm_plane_state base;
struct msm_gem_address_space *aspace;
struct dpu_sw_pipe pipe;
struct dpu_sw_pipe r_pipe;
struct dpu_sw_pipe_cfg pipe_cfg;
struct dpu_sw_pipe_cfg r_pipe_cfg;
enum dpu_stage stage;
bool needs_qos_remap;
uint32_t multirect_index;
uint32_t multirect_mode;
bool pending;
u64 plane_fetch_bw;
@ -44,26 +50,9 @@ struct dpu_plane_state {
unsigned int rotation;
};
/**
* struct dpu_multirect_plane_states: Defines multirect pair of drm plane states
* @r0: drm plane configured on rect 0
* @r1: drm plane configured on rect 1
*/
struct dpu_multirect_plane_states {
const struct drm_plane_state *r0;
const struct drm_plane_state *r1;
};
#define to_dpu_plane_state(x) \
container_of(x, struct dpu_plane_state, base)
/**
* dpu_plane_pipe - return sspp identifier for the given plane
* @plane: Pointer to DRM plane object
* Returns: sspp identifier of the given plane
*/
enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane);
/**
* dpu_plane_flush - final plane operations before commit flush
* @plane: Pointer to drm plane structure
@ -88,19 +77,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs);
/**
* dpu_plane_validate_multirecti_v2 - validate the multirect planes
* against hw limitations
* @plane: drm plate states of the multirect pair
*/
int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane);
/**
* dpu_plane_clear_multirect - clear multirect bits for the given pipe
* @drm_state: Pointer to DRM plane state
*/
void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state);
/**
* dpu_plane_color_fill - enables color fill on plane
* @plane: Pointer to DRM plane object

View File

@ -8,6 +8,7 @@
#include "dpu_hw_lm.h"
#include "dpu_hw_ctl.h"
#include "dpu_hw_pingpong.h"
#include "dpu_hw_sspp.h"
#include "dpu_hw_intf.h"
#include "dpu_hw_wb.h"
#include "dpu_hw_dspp.h"
@ -91,6 +92,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
dpu_hw_wb_destroy(rm->hw_wb[i]);
for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++)
dpu_hw_sspp_destroy(rm->hw_sspp[i]);
return 0;
}
@ -255,6 +259,24 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
}
for (i = 0; i < cat->sspp_count; i++) {
struct dpu_hw_sspp *hw;
const struct dpu_sspp_cfg *sspp = &cat->sspp[i];
if (sspp->id < SSPP_NONE || sspp->id >= SSPP_MAX) {
DPU_ERROR("skip intf %d with invalid id\n", sspp->id);
continue;
}
hw = dpu_hw_sspp_init(sspp->id, mmio, cat);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed sspp object creation: err %d\n", rc);
goto fail;
}
rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
}
return 0;
fail:

View File

@ -21,6 +21,7 @@ struct dpu_global_state;
* @hw_intf: array of intf hardware resources
* @hw_wb: array of wb hardware resources
* @dspp_blks: array of dspp hardware resources
* @hw_sspp: array of sspp hardware resources
*/
struct dpu_rm {
struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
@ -31,6 +32,7 @@ struct dpu_rm {
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
};
/**
@ -108,5 +110,15 @@ static inline struct dpu_hw_wb *dpu_rm_get_wb(struct dpu_rm *rm, enum dpu_wb wb_
return rm->hw_wb[wb_idx - WB_0];
}
/**
* dpu_rm_get_sspp - Return a struct dpu_hw_sspp instance given it's index.
* @rm: DPU Resource Manager handle
* @sspp_idx: SSPP index
*/
static inline struct dpu_hw_sspp *dpu_rm_get_sspp(struct dpu_rm *rm, enum dpu_sspp sspp_idx)
{
return rm->hw_sspp[sspp_idx - SSPP_NONE];
}
#endif /* __DPU_RM_H__ */

View File

@ -633,9 +633,9 @@ TRACE_EVENT(dpu_enc_phys_vid_irq_ctrl,
TRACE_EVENT(dpu_crtc_setup_mixer,
TP_PROTO(uint32_t crtc_id, uint32_t plane_id,
struct drm_plane_state *state, struct dpu_plane_state *pstate,
uint32_t stage_idx, enum dpu_sspp sspp, uint32_t pixel_format,
uint32_t stage_idx, uint32_t pixel_format,
uint64_t modifier),
TP_ARGS(crtc_id, plane_id, state, pstate, stage_idx, sspp,
TP_ARGS(crtc_id, plane_id, state, pstate, stage_idx,
pixel_format, modifier),
TP_STRUCT__entry(
__field( uint32_t, crtc_id )
@ -659,9 +659,9 @@ TRACE_EVENT(dpu_crtc_setup_mixer,
__entry->dst_rect = drm_plane_state_dest(state);
__entry->stage_idx = stage_idx;
__entry->stage = pstate->stage;
__entry->sspp = sspp;
__entry->multirect_idx = pstate->multirect_index;
__entry->multirect_mode = pstate->multirect_mode;
__entry->sspp = pstate->pipe.sspp->idx;
__entry->multirect_idx = pstate->pipe.multirect_index;
__entry->multirect_mode = pstate->pipe.multirect_mode;
__entry->pixel_format = pixel_format;
__entry->modifier = modifier;
),
@ -762,18 +762,17 @@ TRACE_EVENT(dpu_crtc_disable_frame_pending,
);
TRACE_EVENT(dpu_plane_set_scanout,
TP_PROTO(enum dpu_sspp index, struct dpu_hw_fmt_layout *layout,
enum dpu_sspp_multirect_index multirect_index),
TP_ARGS(index, layout, multirect_index),
TP_PROTO(struct dpu_sw_pipe *pipe, struct dpu_hw_fmt_layout *layout),
TP_ARGS(pipe, layout),
TP_STRUCT__entry(
__field( enum dpu_sspp, index )
__field_struct( struct dpu_hw_fmt_layout, layout )
__field( enum dpu_sspp_multirect_index, multirect_index)
),
TP_fast_assign(
__entry->index = index;
__entry->index = pipe->sspp->idx;
__entry->layout = *layout;
__entry->multirect_index = multirect_index;
__entry->multirect_index = pipe->multirect_index;
),
TP_printk("index:%d layout:{%ux%u @ [%u/%u, %u/%u, %u/%u, %u/%u]} "
"multirect_index:%d", __entry->index, __entry->layout.width,

View File

@ -179,6 +179,24 @@ static unsigned get_crtc_mask(struct drm_atomic_state *state)
return mask;
}
int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
{
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct drm_crtc *crtc;
int i;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if ((old_crtc_state->ctm && !new_crtc_state->ctm) ||
(!old_crtc_state->ctm && new_crtc_state->ctm)) {
new_crtc_state->mode_changed = true;
state->allow_modeset = true;
}
}
return drm_atomic_helper_check(dev, state);
}
void msm_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;

View File

@ -58,7 +58,7 @@ static void msm_deinit_vram(struct drm_device *ddev);
static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = msm_framebuffer_create,
.atomic_check = drm_atomic_helper_check,
.atomic_check = msm_atomic_check,
.atomic_commit = drm_atomic_helper_commit,
};

View File

@ -258,6 +258,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer,
struct msm_kms *kms, int crtc_idx);
void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer);
void msm_atomic_commit_tail(struct drm_atomic_state *state);
int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
void msm_atomic_state_clear(struct drm_atomic_state *state);
void msm_atomic_state_free(struct drm_atomic_state *state);