Commit 2470e932 authored by Dmitry Baryshkov's avatar Dmitry Baryshkov

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: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
parents 6ec59381 c6c65568
# 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>;
};
};
};
...
...@@ -401,6 +401,47 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) ...@@ -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, static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer, struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer,
struct dpu_hw_stage_cfg *stage_cfg) struct dpu_hw_stage_cfg *stage_cfg)
...@@ -413,15 +454,12 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, ...@@ -413,15 +454,12 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct dpu_format *format; struct dpu_format *format;
struct dpu_hw_ctl *ctl = mixer->lm_ctl; struct dpu_hw_ctl *ctl = mixer->lm_ctl;
uint32_t stage_idx, lm_idx; uint32_t lm_idx;
int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 };
bool bg_alpha_enable = false; bool bg_alpha_enable = false;
DECLARE_BITMAP(fetch_active, SSPP_MAX); DECLARE_BITMAP(fetch_active, SSPP_MAX);
memset(fetch_active, 0, sizeof(fetch_active)); memset(fetch_active, 0, sizeof(fetch_active));
drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) {
enum dpu_sspp sspp_idx;
state = plane->state; state = plane->state;
if (!state) if (!state)
continue; continue;
...@@ -432,40 +470,30 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, ...@@ -432,40 +470,30 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
pstate = to_dpu_plane_state(state); pstate = to_dpu_plane_state(state);
fb = state->fb; 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)); format = to_dpu_format(msm_framebuffer_format(pstate->base.fb));
if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable) if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable)
bg_alpha_enable = true; bg_alpha_enable = true;
stage_idx = zpos_cnt[pstate->stage]++; set_bit(pstate->pipe.sspp->idx, fetch_active);
stage_cfg->stage[pstate->stage][stage_idx] = _dpu_crtc_blend_setup_pipe(crtc, plane,
sspp_idx; mixer, cstate->num_mixers,
stage_cfg->multirect_index[pstate->stage][stage_idx] = pstate->stage,
pstate->multirect_index; format, fb ? fb->modifier : 0,
&pstate->pipe, 0, stage_cfg);
trace_dpu_crtc_setup_mixer(DRMID(crtc), DRMID(plane),
state, pstate, stage_idx, if (pstate->r_pipe.sspp) {
sspp_idx - SSPP_VIG0, set_bit(pstate->r_pipe.sspp->idx, fetch_active);
format->base.pixel_format, _dpu_crtc_blend_setup_pipe(crtc, plane,
fb ? fb->modifier : 0); mixer, cstate->num_mixers,
pstate->stage,
format, fb ? fb->modifier : 0,
&pstate->r_pipe, 1, stage_cfg);
}
/* blend config update */ /* blend config update */
for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) { for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
_dpu_crtc_setup_blend_cfg(mixer + lm_idx, _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format);
pstate, format);
mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl,
sspp_idx);
if (bg_alpha_enable && !format->alpha_enable) if (bg_alpha_enable && !format->alpha_enable)
mixer[lm_idx].mixer_op_mode = 0; mixer[lm_idx].mixer_op_mode = 0;
...@@ -768,7 +796,7 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) ...@@ -768,7 +796,7 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc)
/* stage config flush mask */ /* stage config flush mask */
ctl->ops.update_pending_flush_dspp(ctl, 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, ...@@ -1134,18 +1162,14 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(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) static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
{ {
struct drm_crtc *crtc = cstate->crtc; struct drm_crtc *crtc = cstate->crtc;
struct drm_encoder *encoder; struct drm_encoder *encoder;
if (cstate->self_refresh_active)
return true;
drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) { drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) {
if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) { if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) {
return true; return true;
...@@ -1162,151 +1186,46 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -1162,151 +1186,46 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
crtc); crtc);
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state); struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
struct plane_state *pstates;
const struct drm_plane_state *pstate; const struct drm_plane_state *pstate;
struct drm_plane *plane; 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); bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
if (!pstates)
return -ENOMEM;
if (!crtc_state->enable || !crtc_state->active) {
DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n", DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
crtc->base.id, crtc_state->enable, crtc->base.id, crtc_state->enable,
crtc_state->active); crtc_state->active);
memset(&cstate->new_perf, 0, sizeof(cstate->new_perf)); 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); DRM_DEBUG_ATOMIC("%s: check\n", dpu_crtc->name);
/* force a full mode set if active state changed */ /* force a full mode set if active state changed */
if (crtc_state->active_changed) if (crtc_state->active_changed)
crtc_state->mode_changed = true; crtc_state->mode_changed = true;
memset(pipe_staged, 0, sizeof(pipe_staged)); if (cstate->num_mixers)
if (cstate->num_mixers) {
mixer_width = mode->hdisplay / cstate->num_mixers;
_dpu_crtc_setup_lm_bounds(crtc, crtc_state); _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) { drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate); struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
struct drm_rect dst, clip = crtc_rect;
if (IS_ERR_OR_NULL(pstate)) { if (IS_ERR_OR_NULL(pstate)) {
rc = PTR_ERR(pstate); rc = PTR_ERR(pstate);
DPU_ERROR("%s: failed to get plane%d state, %d\n", DPU_ERROR("%s: failed to get plane%d state, %d\n",
dpu_crtc->name, plane->base.id, rc); dpu_crtc->name, plane->base.id, rc);
goto end; return rc;
} }
if (cnt >= DPU_STAGE_MAX * 4)
continue;
if (!pstate->visible) if (!pstate->visible)
continue; 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; 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); atomic_inc(&_dpu_crtc_get_kms(crtc)->bandwidth_ref);
...@@ -1315,74 +1234,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -1315,74 +1234,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
if (rc) { if (rc) {
DPU_ERROR("crtc%d failed performance check %d\n", DPU_ERROR("crtc%d failed performance check %d\n",
crtc->base.id, rc); crtc->base.id, rc);
goto end; return rc;
} }
/* validate source split: return 0;
* 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;
} }
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en) 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) ...@@ -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", 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_x, state->crtc_y, state->crtc_w,
state->crtc_h); state->crtc_h);
seq_printf(s, "\tmultirect: mode: %d index: %d\n", seq_printf(s, "\tsspp[0]:%s\n",
pstate->multirect_mode, pstate->multirect_index); 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"); seq_puts(s, "\n");
} }
......
...@@ -545,7 +545,8 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc) ...@@ -545,7 +545,8 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
static struct msm_display_topology dpu_encoder_get_topology( static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc, struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms, 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}; struct msm_display_topology topology = {0};
int i, intf_count = 0; int i, intf_count = 0;
...@@ -563,8 +564,7 @@ static struct msm_display_topology dpu_encoder_get_topology( ...@@ -563,8 +564,7 @@ static struct msm_display_topology dpu_encoder_get_topology(
* 1 LM, 1 INTF * 1 LM, 1 INTF
* 2 LM, 1 INTF (stream merge to support high resolution interfaces) * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
* *
* Adding color blocks only to primary interface if available in * Add dspps to the reservation requirements if ctm is requested
* sufficient number
*/ */
if (intf_count == 2) if (intf_count == 2)
topology.num_lm = 2; topology.num_lm = 2;
...@@ -573,11 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology( ...@@ -573,11 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
else else
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) { if (crtc_state->ctm)
if (dpu_kms->catalog->dspp && topology.num_dspp = topology.num_lm;
(dpu_kms->catalog->dspp_count >= topology.num_lm))
topology.num_dspp = topology.num_lm;
}
topology.num_intf = intf_count; topology.num_intf = intf_count;
...@@ -638,25 +635,22 @@ static int dpu_encoder_virt_atomic_check( ...@@ -638,25 +635,22 @@ static int dpu_encoder_virt_atomic_check(
if (ret) { if (ret) {
DPU_ERROR_ENC(dpu_enc, DPU_ERROR_ENC(dpu_enc,
"mode unsupported, phys idx %d\n", i); "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.
* 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 (drm_atomic_crtc_needs_modeset(crtc_state)) {
dpu_rm_release(global_state, drm_enc);
if (!crtc_state->active_changed || crtc_state->enable) if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(&dpu_kms->rm, global_state, ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
drm_enc, crtc_state, topology); drm_enc, crtc_state, topology);
}
} }
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags); 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) ...@@ -2094,25 +2088,6 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl); 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 #ifdef CONFIG_DEBUG_FS
static int _dpu_encoder_status_show(struct seq_file *s, void *data) static int _dpu_encoder_status_show(struct seq_file *s, void *data)
{ {
......
...@@ -146,13 +146,6 @@ struct drm_encoder *dpu_encoder_init( ...@@ -146,13 +146,6 @@ struct drm_encoder *dpu_encoder_init(
int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
struct msm_display_info *disp_info); 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 * dpu_encoder_set_idle_timeout - set the idle timeout for video
* and command mode encoders. * and command mode encoders.
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#define DPU_ENC_MAX_POLL_TIMEOUT_US 2000 #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) static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc)
{ {
return (phys_enc->split_role != ENC_ROLE_SLAVE); return (phys_enc->split_role != ENC_ROLE_SLAVE);
...@@ -565,6 +567,8 @@ static void dpu_encoder_phys_cmd_prepare_for_kickoff( ...@@ -565,6 +567,8 @@ static void dpu_encoder_phys_cmd_prepare_for_kickoff(
phys_enc->hw_pp->idx - PINGPONG_0); 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", DPU_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n",
phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(&phys_enc->pending_kickoff_cnt)); atomic_read(&phys_enc->pending_kickoff_cnt));
...@@ -586,8 +590,7 @@ static bool dpu_encoder_phys_cmd_is_ongoing_pptx( ...@@ -586,8 +590,7 @@ static bool dpu_encoder_phys_cmd_is_ongoing_pptx(
return false; return false;
} }
static void dpu_encoder_phys_cmd_prepare_commit( static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc)
struct dpu_encoder_phys *phys_enc)
{ {
struct dpu_encoder_phys_cmd *cmd_enc = struct dpu_encoder_phys_cmd *cmd_enc =
to_dpu_encoder_phys_cmd(phys_enc); to_dpu_encoder_phys_cmd(phys_enc);
...@@ -732,7 +735,6 @@ static void dpu_encoder_phys_cmd_trigger_start( ...@@ -732,7 +735,6 @@ static void dpu_encoder_phys_cmd_trigger_start(
static void dpu_encoder_phys_cmd_init_ops( static void dpu_encoder_phys_cmd_init_ops(
struct dpu_encoder_phys_ops *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->is_master = dpu_encoder_phys_cmd_is_master;
ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set; ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set;
ops->enable = dpu_encoder_phys_cmd_enable; ops->enable = dpu_encoder_phys_cmd_enable;
......
...@@ -536,6 +536,16 @@ static const struct dpu_format dpu_format_map_ubwc[] = { ...@@ -536,6 +536,16 @@ static const struct dpu_format dpu_format_map_ubwc[] = {
true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED, true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 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, PSEUDO_YUV_FMT_TILED(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr, C1_B_Cb, C2_R_Cr,
...@@ -591,6 +601,7 @@ static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt) ...@@ -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_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC}, {DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC}, {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_ARGB2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC}, {DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC}, {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC}, {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
...@@ -918,8 +929,7 @@ int dpu_format_populate_layout( ...@@ -918,8 +929,7 @@ int dpu_format_populate_layout(
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
struct dpu_hw_fmt_layout *layout) struct dpu_hw_fmt_layout *layout)
{ {
uint32_t plane_addr[DPU_MAX_PLANES]; int ret;
int i, ret;
if (!fb || !layout) { if (!fb || !layout) {
DRM_ERROR("invalid arguments\n"); DRM_ERROR("invalid arguments\n");
...@@ -940,9 +950,6 @@ int dpu_format_populate_layout( ...@@ -940,9 +950,6 @@ int dpu_format_populate_layout(
if (ret) if (ret)
return ret; return ret;
for (i = 0; i < DPU_MAX_PLANES; ++i)
plane_addr[i] = layout->plane_addr[i];
/* Populate the addresses given the fb */ /* Populate the addresses given the fb */
if (DPU_FORMAT_IS_UBWC(layout->format) || if (DPU_FORMAT_IS_UBWC(layout->format) ||
DPU_FORMAT_IS_TILE(layout->format)) DPU_FORMAT_IS_TILE(layout->format))
...@@ -950,10 +957,6 @@ int dpu_format_populate_layout( ...@@ -950,10 +957,6 @@ int dpu_format_populate_layout(
else else
ret = _dpu_format_populate_addrs_linear(aspace, fb, layout); 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; return ret;
} }
......
...@@ -27,9 +27,15 @@ ...@@ -27,9 +27,15 @@
#define VIG_SDM845_MASK \ #define VIG_SDM845_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3)) (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 \ #define VIG_SC7180_MASK \
(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED4)) (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 VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))
#define DMA_MSM8998_MASK \ #define DMA_MSM8998_MASK \
...@@ -40,6 +46,9 @@ ...@@ -40,6 +46,9 @@
#define VIG_SC7280_MASK \ #define VIG_SC7280_MASK \
(VIG_SC7180_MASK | BIT(DPU_SSPP_INLINE_ROTATION)) (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 \ #define DMA_SDM845_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
...@@ -48,6 +57,12 @@ ...@@ -48,6 +57,12 @@
#define DMA_CURSOR_SDM845_MASK \ #define DMA_CURSOR_SDM845_MASK \
(DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR)) (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 \ #define DMA_CURSOR_MSM8998_MASK \
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR)) (DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
...@@ -66,7 +81,10 @@ ...@@ -66,7 +81,10 @@
(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
#define CTL_SC7280_MASK \ #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 \ #define CTL_SM8550_MASK \
(CTL_SC7280_MASK | BIT(DPU_CTL_HAS_LAYER_EXT4)) (CTL_SC7280_MASK | BIT(DPU_CTL_HAS_LAYER_EXT4))
...@@ -189,6 +207,7 @@ static const uint32_t plane_formats[] = { ...@@ -189,6 +207,7 @@ static const uint32_t plane_formats[] = {
DRM_FORMAT_RGBX8888, DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888, DRM_FORMAT_BGRX8888,
DRM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010,
DRM_FORMAT_RGB888, DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888, DRM_FORMAT_BGR888,
...@@ -218,6 +237,7 @@ static const uint32_t plane_formats_yuv[] = { ...@@ -218,6 +237,7 @@ static const uint32_t plane_formats_yuv[] = {
DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRX8888, DRM_FORMAT_BGRX8888,
DRM_FORMAT_BGRA8888, DRM_FORMAT_BGRA8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888,
...@@ -303,7 +323,6 @@ static const struct dpu_caps msm8998_dpu_caps = { ...@@ -303,7 +323,6 @@ static const struct dpu_caps msm8998_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x7, .max_mixer_blendstages = 0x7,
.qseed_type = DPU_SSPP_SCALER_QSEED3, .qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V1,
.ubwc_version = DPU_HW_UBWC_VER_10, .ubwc_version = DPU_HW_UBWC_VER_10,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -318,7 +337,6 @@ static const struct dpu_caps msm8998_dpu_caps = { ...@@ -318,7 +337,6 @@ static const struct dpu_caps msm8998_dpu_caps = {
static const struct dpu_caps qcm2290_dpu_caps = { static const struct dpu_caps qcm2290_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
.max_mixer_blendstages = 0x4, .max_mixer_blendstages = 0x4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.has_dim_layer = true, .has_dim_layer = true,
.has_idle_pc = true, .has_idle_pc = true,
.max_linewidth = 2160, .max_linewidth = 2160,
...@@ -329,7 +347,6 @@ static const struct dpu_caps sdm845_dpu_caps = { ...@@ -329,7 +347,6 @@ static const struct dpu_caps sdm845_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3, .qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_20, .ubwc_version = DPU_HW_UBWC_VER_20,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -345,7 +362,6 @@ static const struct dpu_caps sc7180_dpu_caps = { ...@@ -345,7 +362,6 @@ static const struct dpu_caps sc7180_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x9, .max_mixer_blendstages = 0x9,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_20, .ubwc_version = DPU_HW_UBWC_VER_20,
.has_dim_layer = true, .has_dim_layer = true,
.has_idle_pc = true, .has_idle_pc = true,
...@@ -357,7 +373,6 @@ static const struct dpu_caps sm6115_dpu_caps = { ...@@ -357,7 +373,6 @@ static const struct dpu_caps sm6115_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
.max_mixer_blendstages = 0x4, .max_mixer_blendstages = 0x4,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_10, .ubwc_version = DPU_HW_UBWC_VER_10,
.has_dim_layer = true, .has_dim_layer = true,
.has_idle_pc = true, .has_idle_pc = true,
...@@ -369,7 +384,6 @@ static const struct dpu_caps sm8150_dpu_caps = { ...@@ -369,7 +384,6 @@ static const struct dpu_caps sm8150_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3, .qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_30, .ubwc_version = DPU_HW_UBWC_VER_30,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -385,7 +399,6 @@ static const struct dpu_caps sc8180x_dpu_caps = { ...@@ -385,7 +399,6 @@ static const struct dpu_caps sc8180x_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED3, .qseed_type = DPU_SSPP_SCALER_QSEED3,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_30, .ubwc_version = DPU_HW_UBWC_VER_30,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -401,7 +414,6 @@ static const struct dpu_caps sc8280xp_dpu_caps = { ...@@ -401,7 +414,6 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
.max_mixer_width = 2560, .max_mixer_width = 2560,
.max_mixer_blendstages = 11, .max_mixer_blendstages = 11,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40, .ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -415,7 +427,6 @@ static const struct dpu_caps sm8250_dpu_caps = { ...@@ -415,7 +427,6 @@ static const struct dpu_caps sm8250_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40, .ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -429,7 +440,6 @@ static const struct dpu_caps sm8350_dpu_caps = { ...@@ -429,7 +440,6 @@ static const struct dpu_caps sm8350_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40, .ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -443,7 +453,6 @@ static const struct dpu_caps sm8450_dpu_caps = { ...@@ -443,7 +453,6 @@ static const struct dpu_caps sm8450_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40, .ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -457,7 +466,6 @@ static const struct dpu_caps sm8550_dpu_caps = { ...@@ -457,7 +466,6 @@ static const struct dpu_caps sm8550_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb, .max_mixer_blendstages = 0xb,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40, .ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true, .has_src_split = true,
.has_dim_layer = true, .has_dim_layer = true,
...@@ -471,7 +479,6 @@ static const struct dpu_caps sc7280_dpu_caps = { ...@@ -471,7 +479,6 @@ static const struct dpu_caps sc7280_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0x7, .max_mixer_blendstages = 0x7,
.qseed_type = DPU_SSPP_SCALER_QSEED4, .qseed_type = DPU_SSPP_SCALER_QSEED4,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2,
.ubwc_version = DPU_HW_UBWC_VER_30, .ubwc_version = DPU_HW_UBWC_VER_30,
.has_dim_layer = true, .has_dim_layer = true,
.has_idle_pc = true, .has_idle_pc = true,
...@@ -1197,21 +1204,21 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = { ...@@ -1197,21 +1204,21 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = {
}; };
static const struct dpu_sspp_cfg sdm845_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), 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), 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), 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), 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), 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), 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), 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), 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 = ...@@ -1252,21 +1259,21 @@ static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 =
_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4); _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4);
static const struct dpu_sspp_cfg sm8250_sspp[] = { 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), 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), 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), 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), 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), 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), 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), 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), sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),
}; };
...@@ -1333,13 +1340,13 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { ...@@ -1333,13 +1340,13 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = {
}; };
static const struct dpu_sspp_cfg sc7280_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), 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), 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), 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), sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),
}; };
......
...@@ -19,8 +19,9 @@ ...@@ -19,8 +19,9 @@
*/ */
#define MAX_BLOCKS 12 #define MAX_BLOCKS 12
#define DPU_HW_VER(MAJOR, MINOR, STEP) (((MAJOR & 0xF) << 28) |\ #define DPU_HW_VER(MAJOR, MINOR, STEP) \
((MINOR & 0xFFF) << 16) |\ ((((unsigned int)MAJOR & 0xF) << 28) | \
((MINOR & 0xFFF) << 16) | \
(STEP & 0xFFFF)) (STEP & 0xFFFF))
#define DPU_HW_MAJOR(rev) ((rev) >> 28) #define DPU_HW_MAJOR(rev) ((rev) >> 28)
...@@ -169,10 +170,12 @@ enum { ...@@ -169,10 +170,12 @@ enum {
* DSPP sub-blocks * DSPP sub-blocks
* @DPU_DSPP_PCC Panel color correction block * @DPU_DSPP_PCC Panel color correction block
* @DPU_DSPP_GC Gamma correction block * @DPU_DSPP_GC Gamma correction block
* @DPU_DSPP_IGC Inverse gamma correction block
*/ */
enum { enum {
DPU_DSPP_PCC = 0x1, DPU_DSPP_PCC = 0x1,
DPU_DSPP_GC, DPU_DSPP_GC,
DPU_DSPP_IGC,
DPU_DSPP_MAX DPU_DSPP_MAX
}; };
...@@ -200,6 +203,7 @@ enum { ...@@ -200,6 +203,7 @@ enum {
* @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs) * @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs)
* @DPU_CTL_VM_CFG: CTL config to support multiple VMs * @DPU_CTL_VM_CFG: CTL config to support multiple VMs
* @DPU_CTL_HAS_LAYER_EXT4: CTL has the CTL_LAYER_EXT4 register * @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 * @DPU_CTL_MAX
*/ */
enum { enum {
...@@ -208,6 +212,7 @@ enum { ...@@ -208,6 +212,7 @@ enum {
DPU_CTL_FETCH_ACTIVE, DPU_CTL_FETCH_ACTIVE,
DPU_CTL_VM_CFG, DPU_CTL_VM_CFG,
DPU_CTL_HAS_LAYER_EXT4, DPU_CTL_HAS_LAYER_EXT4,
DPU_CTL_DSPP_SUB_BLOCK_FLUSH,
DPU_CTL_MAX DPU_CTL_MAX
}; };
...@@ -395,7 +400,6 @@ struct dpu_rotation_cfg { ...@@ -395,7 +400,6 @@ struct dpu_rotation_cfg {
* @max_mixer_blendstages max layer mixer blend stages or * @max_mixer_blendstages max layer mixer blend stages or
* supported z order * supported z order
* @qseed_type qseed2 or qseed3 support. * @qseed_type qseed2 or qseed3 support.
* @smart_dma_rev Supported version of SmartDMA feature.
* @ubwc_version UBWC feature version (0x0 for not supported) * @ubwc_version UBWC feature version (0x0 for not supported)
* @has_src_split source split feature status * @has_src_split source split feature status
* @has_dim_layer dim layer feature status * @has_dim_layer dim layer feature status
...@@ -410,7 +414,6 @@ struct dpu_caps { ...@@ -410,7 +414,6 @@ struct dpu_caps {
u32 max_mixer_width; u32 max_mixer_width;
u32 max_mixer_blendstages; u32 max_mixer_blendstages;
u32 qseed_type; u32 qseed_type;
u32 smart_dma_rev;
u32 ubwc_version; u32 ubwc_version;
bool has_src_split; bool has_src_split;
bool has_dim_layer; bool has_dim_layer;
......
...@@ -26,15 +26,16 @@ ...@@ -26,15 +26,16 @@
#define CTL_SW_RESET 0x030 #define CTL_SW_RESET 0x030
#define CTL_LAYER_EXTN_OFFSET 0x40 #define CTL_LAYER_EXTN_OFFSET 0x40
#define CTL_MERGE_3D_ACTIVE 0x0E4 #define CTL_MERGE_3D_ACTIVE 0x0E4
#define CTL_DSC_ACTIVE 0x0E8
#define CTL_WB_ACTIVE 0x0EC #define CTL_WB_ACTIVE 0x0EC
#define CTL_INTF_ACTIVE 0x0F4 #define CTL_INTF_ACTIVE 0x0F4
#define CTL_FETCH_PIPE_ACTIVE 0x0FC
#define CTL_MERGE_3D_FLUSH 0x100 #define CTL_MERGE_3D_FLUSH 0x100
#define CTL_DSC_ACTIVE 0x0E8
#define CTL_DSC_FLUSH 0x104 #define CTL_DSC_FLUSH 0x104
#define CTL_WB_FLUSH 0x108 #define CTL_WB_FLUSH 0x108
#define CTL_INTF_FLUSH 0x110 #define CTL_INTF_FLUSH 0x110
#define CTL_INTF_MASTER 0x134 #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_MIXER_BORDER_OUT BIT(24)
#define CTL_FLUSH_MASK_CTL BIT(17) #define CTL_FLUSH_MASK_CTL BIT(17)
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
#define DSC_IDX 22 #define DSC_IDX 22
#define INTF_IDX 31 #define INTF_IDX 31
#define WB_IDX 16 #define WB_IDX 16
#define DSPP_IDX 29 /* From DPU hw rev 7.x.x */
#define CTL_INVALID_BIT 0xffff #define CTL_INVALID_BIT 0xffff
#define CTL_DEFAULT_GROUP_ID 0xf #define CTL_DEFAULT_GROUP_ID 0xf
...@@ -115,6 +117,9 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx) ...@@ -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, trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
dpu_hw_ctl_get_flush_register(ctx)); dpu_hw_ctl_get_flush_register(ctx));
ctx->pending_flush_mask = 0x0; 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, 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) ...@@ -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) 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)) if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH, DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask); ctx->pending_merge_3d_flush_mask);
...@@ -142,6 +149,13 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx) ...@@ -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, DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
ctx->pending_wb_flush_mask); 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); 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, ...@@ -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, 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) { switch (dspp) {
case DSPP_0: case DSPP_0:
...@@ -309,6 +323,29 @@ static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx, ...@@ -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) 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; struct dpu_hw_blk_reg_map *c = &ctx->hw;
...@@ -630,7 +667,11 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ...@@ -630,7 +667,11 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp; 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_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)) if (cap & BIT(DPU_CTL_FETCH_ACTIVE))
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
}; };
......
...@@ -152,9 +152,11 @@ struct dpu_hw_ctl_ops { ...@@ -152,9 +152,11 @@ struct dpu_hw_ctl_ops {
* No effect on hardware * No effect on hardware
* @ctx : ctl path ctx pointer * @ctx : ctl path ctx pointer
* @blk : DSPP block index * @blk : DSPP block index
* @dspp_sub_blk : DSPP sub-block index
*/ */
void (*update_pending_flush_dspp)(struct dpu_hw_ctl *ctx, 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 * Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer * @ctx : ctl path ctx pointer
...@@ -242,6 +244,7 @@ struct dpu_hw_ctl { ...@@ -242,6 +244,7 @@ struct dpu_hw_ctl {
u32 pending_intf_flush_mask; u32 pending_intf_flush_mask;
u32 pending_wb_flush_mask; u32 pending_wb_flush_mask;
u32 pending_merge_3d_flush_mask; u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
/* ops */ /* ops */
struct dpu_hw_ctl_ops ops; struct dpu_hw_ctl_ops ops;
......
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
#define TS_CLK 19200000 #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, int s_id,
u32 *idx) u32 *idx)
{ {
...@@ -168,17 +168,16 @@ static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx, ...@@ -168,17 +168,16 @@ static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx,
return rc; return rc;
} }
static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx, static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
enum dpu_sspp_multirect_index index,
enum dpu_sspp_multirect_mode mode)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 mode_mask; u32 mode_mask;
u32 idx; u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return; 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 * if rect index is RECT_SOLO, we cannot expect a
* virtual plane sharing the same SSPP id. So we go * 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, ...@@ -187,8 +186,8 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx,
mode_mask = 0; mode_mask = 0;
} else { } else {
mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx); mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx);
mode_mask |= index; mode_mask |= pipe->multirect_index;
if (mode == DPU_SSPP_MULTIRECT_TIME_MX) if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX)
mode_mask |= BIT(2); mode_mask |= BIT(2);
else else
mode_mask &= ~BIT(2); mode_mask &= ~BIT(2);
...@@ -197,7 +196,7 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx, ...@@ -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); 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 mask, u8 en)
{ {
u32 idx; u32 idx;
...@@ -218,7 +217,7 @@ static void _sspp_setup_opmode(struct dpu_hw_pipe *ctx, ...@@ -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); 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 mask, u8 en)
{ {
u32 idx; u32 idx;
...@@ -239,10 +238,10 @@ static void _sspp_setup_csc10_opmode(struct dpu_hw_pipe *ctx, ...@@ -239,10 +238,10 @@ static void _sspp_setup_csc10_opmode(struct dpu_hw_pipe *ctx,
/* /*
* Setup source pixel format, flip, * Setup source pixel format, flip,
*/ */
static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx, static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, u32 flags, const struct dpu_format *fmt, u32 flags)
enum dpu_sspp_multirect_index rect_mode)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_blk_reg_map *c; struct dpu_hw_blk_reg_map *c;
u32 chroma_samp, unpack, src_format; u32 chroma_samp, unpack, src_format;
u32 opmode = 0; u32 opmode = 0;
...@@ -253,7 +252,8 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx, ...@@ -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) if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !fmt)
return; 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; op_mode_off = SSPP_SRC_OP_MODE;
unpack_pat_off = SSPP_SRC_UNPACK_PATTERN; unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
format_off = SSPP_SRC_FORMAT; format_off = SSPP_SRC_FORMAT;
...@@ -360,7 +360,7 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx, ...@@ -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)); 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_pixel_ext *pe_ext)
{ {
struct dpu_hw_blk_reg_map *c; struct dpu_hw_blk_reg_map *c;
...@@ -418,23 +418,22 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx, ...@@ -418,23 +418,22 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx,
tot_req_pixels[3]); tot_req_pixels[3]);
} }
static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx, static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp *ctx,
struct dpu_hw_pipe_cfg *sspp, struct dpu_hw_scaler3_cfg *scaler3_cfg,
void *scaler_cfg) const struct dpu_format *format)
{ {
u32 idx; 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) || !scaler3_cfg)
return; return;
dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx, dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx,
ctx->cap->sblk->scaler_blk.version, 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; u32 idx;
...@@ -447,12 +446,12 @@ static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_pipe *ctx) ...@@ -447,12 +446,12 @@ static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_pipe *ctx)
/* /*
* dpu_hw_sspp_setup_rects() * dpu_hw_sspp_setup_rects()
*/ */
static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx, static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,
struct dpu_hw_pipe_cfg *cfg, struct dpu_sw_pipe_cfg *cfg)
enum dpu_sspp_multirect_index rect_index)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_blk_reg_map *c; 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 src_size_off, src_xy_off, out_size_off, out_xy_off;
u32 idx; u32 idx;
...@@ -461,7 +460,8 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx, ...@@ -461,7 +460,8 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx,
c = &ctx->hw; 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_size_off = SSPP_SRC_SIZE;
src_xy_off = SSPP_SRC_XY; src_xy_off = SSPP_SRC_XY;
out_size_off = SSPP_OUT_SIZE; out_size_off = SSPP_OUT_SIZE;
...@@ -482,68 +482,69 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx, ...@@ -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) | dst_size = (drm_rect_height(&cfg->dst_rect) << 16) |
drm_rect_width(&cfg->dst_rect); 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 */ /* rectangle register programming */
DPU_REG_WRITE(c, src_size_off + idx, src_size); DPU_REG_WRITE(c, src_size_off + idx, src_size);
DPU_REG_WRITE(c, src_xy_off + idx, src_xy); 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_size_off + idx, dst_size);
DPU_REG_WRITE(c, out_xy_off + idx, dst_xy); 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, static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
struct dpu_hw_pipe_cfg *cfg, struct dpu_hw_fmt_layout *layout)
enum dpu_sspp_multirect_index rect_mode)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 ystride0, ystride1;
int i; int i;
u32 idx; u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return; return;
if (rect_mode == DPU_SSPP_RECT_SOLO) { if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
for (i = 0; i < ARRAY_SIZE(cfg->layout.plane_addr); i++) for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++)
DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4, DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4,
cfg->layout.plane_addr[i]); layout->plane_addr[i]);
} else if (rect_mode == DPU_SSPP_RECT_0) { } else if (pipe->multirect_index == DPU_SSPP_RECT_0) {
DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx, 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, DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR + idx,
cfg->layout.plane_addr[2]); layout->plane_addr[2]);
} else { } else {
DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR + idx, 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, 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) const struct dpu_csc_cfg *data)
{ {
u32 idx; u32 idx;
...@@ -560,22 +561,28 @@ static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx, ...@@ -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); dpu_hw_csc_setup(&ctx->hw, idx, data, csc10);
} }
static void dpu_hw_sspp_setup_solidfill(struct dpu_hw_pipe *ctx, u32 color, enum static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
dpu_sspp_multirect_index rect_index)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_fmt_layout cfg;
u32 idx; u32 idx;
if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return; 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); DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color);
else else
DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx, DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx,
color); 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 danger_lut,
u32 safe_lut) u32 safe_lut)
{ {
...@@ -588,7 +595,7 @@ static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx, ...@@ -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); 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) u64 creq_lut)
{ {
u32 idx; u32 idx;
...@@ -605,7 +612,7 @@ static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx, ...@@ -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) struct dpu_hw_pipe_qos_cfg *cfg)
{ {
u32 idx; u32 idx;
...@@ -630,10 +637,10 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx, ...@@ -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); DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl);
} }
static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
struct dpu_hw_cdp_cfg *cfg, struct dpu_hw_cdp_cfg *cfg)
enum dpu_sspp_multirect_index index)
{ {
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 idx; u32 idx;
u32 cdp_cntl = 0; u32 cdp_cntl = 0;
u32 cdp_cntl_offset = 0; u32 cdp_cntl_offset = 0;
...@@ -644,7 +651,8 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, ...@@ -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)) if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
return; 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; cdp_cntl_offset = SSPP_CDP_CNTL;
else else
cdp_cntl_offset = SSPP_CDP_CNTL_REC1; cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
...@@ -661,7 +669,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, ...@@ -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); 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) unsigned long features)
{ {
if (test_bit(DPU_SSPP_SRC, &features)) { if (test_bit(DPU_SSPP_SRC, &features)) {
...@@ -699,7 +707,8 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c, ...@@ -699,7 +707,8 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c,
} }
#ifdef CONFIG_DEBUG_FS #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_cfg *cfg = hw_pipe->cap;
const struct dpu_sspp_sub_blks *sblk = cfg->sblk; 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, ...@@ -783,10 +792,10 @@ static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
return ERR_PTR(-ENOMEM); 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) 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; const struct dpu_sspp_cfg *cfg;
if (!addr || !catalog) if (!addr || !catalog)
...@@ -812,7 +821,7 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx, ...@@ -812,7 +821,7 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
return hw_pipe; 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); kfree(ctx);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "dpu_hw_util.h" #include "dpu_hw_util.h"
#include "dpu_formats.h" #include "dpu_formats.h"
struct dpu_hw_pipe; struct dpu_hw_sspp;
/** /**
* Flags * Flags
...@@ -153,20 +153,14 @@ struct dpu_hw_pixel_ext { ...@@ -153,20 +153,14 @@ struct dpu_hw_pixel_ext {
}; };
/** /**
* struct dpu_hw_pipe_cfg : Pipe description * struct dpu_sw_pipe_cfg : software pipe configuration
* @layout: format layout information for programming buffer to hardware
* @src_rect: src ROI, caller takes into account the different operations * @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field * such as decimation, flip etc to program this field
* @dest_rect: destination ROI. * @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_sw_pipe_cfg {
struct dpu_hw_fmt_layout layout;
struct drm_rect src_rect; struct drm_rect src_rect;
struct drm_rect dst_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 { ...@@ -201,6 +195,18 @@ struct dpu_hw_pipe_ts_cfg {
u64 time; 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 * 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 * Caller must call the init function to get the pipe context for each pipe
...@@ -209,77 +215,65 @@ struct dpu_hw_pipe_ts_cfg { ...@@ -209,77 +215,65 @@ struct dpu_hw_pipe_ts_cfg {
struct dpu_hw_sspp_ops { struct dpu_hw_sspp_ops {
/** /**
* setup_format - setup pixel format cropping rectangle, flip * 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 * @cfg: Pointer to pipe config structure
* @flags: Extra flags for format config * @flags: Extra flags for format config
* @index: rectangle index in multirect
*/ */
void (*setup_format)(struct dpu_hw_pipe *ctx, void (*setup_format)(struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, u32 flags, const struct dpu_format *fmt, u32 flags);
enum dpu_sspp_multirect_index index);
/** /**
* setup_rects - setup pipe ROI rectangles * setup_rects - setup pipe ROI rectangles
* @ctx: Pointer to pipe context * @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure * @cfg: Pointer to pipe config structure
* @index: rectangle index in multirect
*/ */
void (*setup_rects)(struct dpu_hw_pipe *ctx, void (*setup_rects)(struct dpu_sw_pipe *pipe,
struct dpu_hw_pipe_cfg *cfg, struct dpu_sw_pipe_cfg *cfg);
enum dpu_sspp_multirect_index index);
/** /**
* setup_pe - setup pipe pixel extension * setup_pe - setup pipe pixel extension
* @ctx: Pointer to pipe context * @ctx: Pointer to pipe context
* @pe_ext: Pointer to pixel ext settings * @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); struct dpu_hw_pixel_ext *pe_ext);
/** /**
* setup_sourceaddress - setup pipe source addresses * setup_sourceaddress - setup pipe source addresses
* @ctx: Pointer to pipe context * @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure * @layout: format layout information for programming buffer to hardware
* @index: rectangle index in multirect
*/ */
void (*setup_sourceaddress)(struct dpu_hw_pipe *ctx, void (*setup_sourceaddress)(struct dpu_sw_pipe *ctx,
struct dpu_hw_pipe_cfg *cfg, struct dpu_hw_fmt_layout *layout);
enum dpu_sspp_multirect_index index);
/** /**
* setup_csc - setup color space coversion * setup_csc - setup color space coversion
* @ctx: Pointer to pipe context * @ctx: Pointer to pipe context
* @data: Pointer to config structure * @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 * setup_solidfill - enable/disable colorfill
* @ctx: Pointer to pipe context * @pipe: Pointer to software pipe context
* @const_color: Fill color value * @const_color: Fill color value
* @flags: Pipe flags * @flags: Pipe flags
* @index: rectangle index in multirect
*/ */
void (*setup_solidfill)(struct dpu_hw_pipe *ctx, u32 color, void (*setup_solidfill)(struct dpu_sw_pipe *pipe, u32 color);
enum dpu_sspp_multirect_index index);
/** /**
* setup_multirect - setup multirect configuration * setup_multirect - setup multirect configuration
* @ctx: Pointer to pipe context * @pipe: Pointer to software pipe context
* @index: rectangle index in multirect
* @mode: parallel fetch / time multiplex multirect mode
*/ */
void (*setup_multirect)(struct dpu_hw_pipe *ctx, void (*setup_multirect)(struct dpu_sw_pipe *pipe);
enum dpu_sspp_multirect_index index,
enum dpu_sspp_multirect_mode mode);
/** /**
* setup_sharpening - setup sharpening * setup_sharpening - setup sharpening
* @ctx: Pointer to pipe context * @ctx: Pointer to pipe context
* @cfg: Pointer to config structure * @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); struct dpu_hw_sharp_cfg *cfg);
/** /**
...@@ -289,7 +283,7 @@ struct dpu_hw_sspp_ops { ...@@ -289,7 +283,7 @@ struct dpu_hw_sspp_ops {
* @safe_lut: LUT for generate safe level based on fill level * @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 danger_lut,
u32 safe_lut); u32 safe_lut);
...@@ -299,7 +293,7 @@ struct dpu_hw_sspp_ops { ...@@ -299,7 +293,7 @@ struct dpu_hw_sspp_ops {
* @creq_lut: LUT for generate creq level based on fill level * @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); u64 creq_lut);
/** /**
...@@ -308,7 +302,7 @@ struct dpu_hw_sspp_ops { ...@@ -308,7 +302,7 @@ struct dpu_hw_sspp_ops {
* @cfg: Pointer to pipe QoS configuration * @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); struct dpu_hw_pipe_qos_cfg *cfg);
/** /**
...@@ -316,38 +310,35 @@ struct dpu_hw_sspp_ops { ...@@ -316,38 +310,35 @@ struct dpu_hw_sspp_ops {
* @ctx: Pointer to pipe context * @ctx: Pointer to pipe context
* @cfg: Pointer to histogram configuration * @cfg: Pointer to histogram configuration
*/ */
void (*setup_histogram)(struct dpu_hw_pipe *ctx, void (*setup_histogram)(struct dpu_hw_sspp *ctx,
void *cfg); void *cfg);
/** /**
* setup_scaler - setup scaler * setup_scaler - setup scaler
* @ctx: Pointer to pipe context * @scaler3_cfg: Pointer to scaler configuration
* @pipe_cfg: Pointer to pipe configuration * @format: pixel format parameters
* @scaler_cfg: Pointer to scaler configuration
*/ */
void (*setup_scaler)(struct dpu_hw_pipe *ctx, void (*setup_scaler)(struct dpu_hw_sspp *ctx,
struct dpu_hw_pipe_cfg *pipe_cfg, struct dpu_hw_scaler3_cfg *scaler3_cfg,
void *scaler_cfg); const struct dpu_format *format);
/** /**
* get_scaler_ver - get scaler h/w version * get_scaler_ver - get scaler h/w version
* @ctx: Pointer to pipe context * @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 * setup_cdp - setup client driven prefetch
* @ctx: Pointer to pipe context * @pipe: Pointer to software pipe context
* @cfg: Pointer to cdp configuration * @cfg: Pointer to cdp configuration
* @index: rectangle index in multirect
*/ */
void (*setup_cdp)(struct dpu_hw_pipe *ctx, void (*setup_cdp)(struct dpu_sw_pipe *pipe,
struct dpu_hw_cdp_cfg *cfg, struct dpu_hw_cdp_cfg *cfg);
enum dpu_sspp_multirect_index index);
}; };
/** /**
* struct dpu_hw_pipe - pipe description * struct dpu_hw_sspp - pipe description
* @base: hardware block base structure * @base: hardware block base structure
* @hw: block hardware details * @hw: block hardware details
* @catalog: back pointer to catalog * @catalog: back pointer to catalog
...@@ -356,7 +347,7 @@ struct dpu_hw_sspp_ops { ...@@ -356,7 +347,7 @@ struct dpu_hw_sspp_ops {
* @cap: pointer to layer_cfg * @cap: pointer to layer_cfg
* @ops: pointer to operations possible for this pipe * @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 base;
struct dpu_hw_blk_reg_map hw; struct dpu_hw_blk_reg_map hw;
const struct dpu_mdss_cfg *catalog; const struct dpu_mdss_cfg *catalog;
...@@ -378,7 +369,7 @@ struct dpu_kms; ...@@ -378,7 +369,7 @@ struct dpu_kms;
* @addr: Mapped register io address of MDP * @addr: Mapped register io address of MDP
* @catalog : Pointer to mdss catalog data * @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); 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, ...@@ -386,10 +377,10 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
* should be called during Hw pipe cleanup. * should be called during Hw pipe cleanup.
* @ctx: Pointer to SSPP driver context returned by dpu_hw_sspp_init * @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_sspp *hw_pipe, struct dpu_kms *kms,
int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms, struct dentry *entry); struct dentry *entry);
#endif /*_DPU_HW_SSPP_H */ #endif /*_DPU_HW_SSPP_H */
...@@ -250,6 +250,24 @@ void dpu_debugfs_create_regset32(const char *name, umode_t mode, ...@@ -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); 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) static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
{ {
struct dpu_kms *dpu_kms = to_dpu_kms(kms); struct dpu_kms *dpu_kms = to_dpu_kms(kms);
...@@ -411,26 +429,6 @@ static void dpu_kms_disable_commit(struct msm_kms *kms) ...@@ -411,26 +429,6 @@ static void dpu_kms_disable_commit(struct msm_kms *kms)
pm_runtime_put_sync(&dpu_kms->pdev->dev); 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) static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask)
{ {
struct dpu_kms *dpu_kms = to_dpu_kms(kms); struct dpu_kms *dpu_kms = to_dpu_kms(kms);
...@@ -939,7 +937,6 @@ static const struct msm_kms_funcs kms_funcs = { ...@@ -939,7 +937,6 @@ static const struct msm_kms_funcs kms_funcs = {
.irq = dpu_core_irq, .irq = dpu_core_irq,
.enable_commit = dpu_kms_enable_commit, .enable_commit = dpu_kms_enable_commit,
.disable_commit = dpu_kms_disable_commit, .disable_commit = dpu_kms_disable_commit,
.prepare_commit = dpu_kms_prepare_commit,
.flush_commit = dpu_kms_flush_commit, .flush_commit = dpu_kms_flush_commit,
.wait_flush = dpu_kms_wait_flush, .wait_flush = dpu_kms_wait_flush,
.complete_commit = dpu_kms_complete_commit, .complete_commit = dpu_kms_complete_commit,
......
...@@ -47,13 +47,6 @@ ...@@ -47,13 +47,6 @@
#define DPU_PLANE_COLOR_FILL_FLAG BIT(31) #define DPU_PLANE_COLOR_FILL_FLAG BIT(31)
#define DPU_ZPOS_MAX 255 #define DPU_ZPOS_MAX 255
/* multirect rect index */
enum {
R0,
R1,
R_MAX
};
/* /*
* Default Preload Values * Default Preload Values
*/ */
...@@ -69,6 +62,7 @@ static const uint32_t qcom_compressed_supported_formats[] = { ...@@ -69,6 +62,7 @@ static const uint32_t qcom_compressed_supported_formats[] = {
DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888,
DRM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010,
DRM_FORMAT_BGR565, DRM_FORMAT_BGR565,
...@@ -104,7 +98,6 @@ struct dpu_plane { ...@@ -104,7 +98,6 @@ struct dpu_plane {
enum dpu_sspp pipe; enum dpu_sspp pipe;
struct dpu_hw_pipe *pipe_hw;
uint32_t color_fill; uint32_t color_fill;
bool is_error; bool is_error;
bool is_rt_pipe; bool is_rt_pipe;
...@@ -128,21 +121,19 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) ...@@ -128,21 +121,19 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane)
/** /**
* _dpu_plane_calc_bw - calculate bandwidth required for a plane * _dpu_plane_calc_bw - calculate bandwidth required for a plane
* @plane: Pointer to drm plane. * @catalog: Points to dpu catalog structure
* @fb: Pointer to framebuffer associated with the given plane * @fmt: Pointer to source buffer format
* @mode: Pointer to drm display mode
* @pipe_cfg: Pointer to pipe configuration * @pipe_cfg: Pointer to pipe configuration
* Result: Updates calculated bandwidth in the plane state. * Result: Updates calculated bandwidth in the plane state.
* BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest)
* Prefill BW Equation: line src bytes * line_time * Prefill BW Equation: line src bytes * line_time
*/ */
static void _dpu_plane_calc_bw(struct drm_plane *plane, static u64 _dpu_plane_calc_bw(const struct dpu_mdss_cfg *catalog,
struct drm_framebuffer *fb, const struct dpu_format *fmt,
struct dpu_hw_pipe_cfg *pipe_cfg) const struct drm_display_mode *mode,
struct dpu_sw_pipe_cfg *pipe_cfg)
{ {
struct dpu_plane_state *pstate;
struct drm_display_mode *mode;
const struct dpu_format *fmt = NULL;
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
int src_width, src_height, dst_height, fps; int src_width, src_height, dst_height, fps;
u64 plane_prefill_bw; u64 plane_prefill_bw;
u64 plane_bw; u64 plane_bw;
...@@ -150,11 +141,6 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, ...@@ -150,11 +141,6 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane,
u64 scale_factor; u64 scale_factor;
int vbp, vpw, vfp; int vbp, vpw, vfp;
pstate = to_dpu_plane_state(plane->state);
mode = &plane->state->crtc->mode;
fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier);
src_width = drm_rect_width(&pipe_cfg->src_rect); src_width = drm_rect_width(&pipe_cfg->src_rect);
src_height = drm_rect_height(&pipe_cfg->src_rect); src_height = drm_rect_height(&pipe_cfg->src_rect);
dst_height = drm_rect_height(&pipe_cfg->dst_rect); dst_height = drm_rect_height(&pipe_cfg->dst_rect);
...@@ -162,7 +148,7 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, ...@@ -162,7 +148,7 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane,
vbp = mode->vtotal - mode->vsync_end; vbp = mode->vtotal - mode->vsync_end;
vpw = mode->vsync_end - mode->vsync_start; vpw = mode->vsync_end - mode->vsync_start;
vfp = mode->vsync_start - mode->vdisplay; vfp = mode->vsync_start - mode->vdisplay;
hw_latency_lines = dpu_kms->catalog->perf->min_prefill_lines; hw_latency_lines = catalog->perf->min_prefill_lines;
scale_factor = src_height > dst_height ? scale_factor = src_height > dst_height ?
mult_frac(src_height, 1, dst_height) : 1; mult_frac(src_height, 1, dst_height) : 1;
...@@ -182,61 +168,60 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, ...@@ -182,61 +168,60 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane,
do_div(plane_prefill_bw, hw_latency_lines); do_div(plane_prefill_bw, hw_latency_lines);
pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw); return max(plane_bw, plane_prefill_bw);
} }
/** /**
* _dpu_plane_calc_clk - calculate clock required for a plane * _dpu_plane_calc_clk - calculate clock required for a plane
* @plane: Pointer to drm plane. * @mode: Pointer to drm display mode
* @pipe_cfg: Pointer to pipe configuration * @pipe_cfg: Pointer to pipe configuration
* Result: Updates calculated clock in the plane state. * Result: Updates calculated clock in the plane state.
* Clock equation: dst_w * v_total * fps * (src_h / dst_h) * Clock equation: dst_w * v_total * fps * (src_h / dst_h)
*/ */
static void _dpu_plane_calc_clk(struct drm_plane *plane, struct dpu_hw_pipe_cfg *pipe_cfg) static u64 _dpu_plane_calc_clk(const struct drm_display_mode *mode,
struct dpu_sw_pipe_cfg *pipe_cfg)
{ {
struct dpu_plane_state *pstate;
struct drm_display_mode *mode;
int dst_width, src_height, dst_height, fps; int dst_width, src_height, dst_height, fps;
u64 plane_clk;
pstate = to_dpu_plane_state(plane->state);
mode = &plane->state->crtc->mode;
src_height = drm_rect_height(&pipe_cfg->src_rect); src_height = drm_rect_height(&pipe_cfg->src_rect);
dst_width = drm_rect_width(&pipe_cfg->dst_rect); dst_width = drm_rect_width(&pipe_cfg->dst_rect);
dst_height = drm_rect_height(&pipe_cfg->dst_rect); dst_height = drm_rect_height(&pipe_cfg->dst_rect);
fps = drm_mode_vrefresh(mode); fps = drm_mode_vrefresh(mode);
pstate->plane_clk = plane_clk =
dst_width * mode->vtotal * fps; dst_width * mode->vtotal * fps;
if (src_height > dst_height) { if (src_height > dst_height) {
pstate->plane_clk *= src_height; plane_clk *= src_height;
do_div(pstate->plane_clk, dst_height); do_div(plane_clk, dst_height);
} }
return plane_clk;
} }
/** /**
* _dpu_plane_calc_fill_level - calculate fill level of the given source format * _dpu_plane_calc_fill_level - calculate fill level of the given source format
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @pipe: Pointer to software pipe
* @fmt: Pointer to source buffer format * @fmt: Pointer to source buffer format
* @src_width: width of source buffer * @src_width: width of source buffer
* Return: fill level corresponding to the source buffer/format or 0 if error * Return: fill level corresponding to the source buffer/format or 0 if error
*/ */
static int _dpu_plane_calc_fill_level(struct drm_plane *plane, static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, u32 src_width) const struct dpu_format *fmt, u32 src_width)
{ {
struct dpu_plane *pdpu; struct dpu_plane *pdpu;
struct dpu_plane_state *pstate;
u32 fixed_buff_size; u32 fixed_buff_size;
u32 total_fl; u32 total_fl;
if (!fmt || !plane->state || !src_width || !fmt->bpp) { if (!fmt || !pipe || !src_width || !fmt->bpp) {
DPU_ERROR("invalid arguments\n"); DPU_ERROR("invalid arguments\n");
return 0; return 0;
} }
pdpu = to_dpu_plane(plane); pdpu = to_dpu_plane(plane);
pstate = to_dpu_plane_state(plane->state);
fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; fixed_buff_size = pdpu->catalog->caps->pixel_ram_size;
/* FIXME: in multirect case account for the src_width of all the planes */ /* FIXME: in multirect case account for the src_width of all the planes */
...@@ -252,7 +237,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, ...@@ -252,7 +237,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
((src_width + 32) * fmt->bpp); ((src_width + 32) * fmt->bpp);
} }
} else { } else {
if (pstate->multirect_mode == DPU_SSPP_MULTIRECT_PARALLEL) { if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_PARALLEL) {
total_fl = (fixed_buff_size / 2) * 2 / total_fl = (fixed_buff_size / 2) * 2 /
((src_width + 32) * fmt->bpp); ((src_width + 32) * fmt->bpp);
} else { } else {
...@@ -262,7 +247,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, ...@@ -262,7 +247,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
} }
DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s w:%u fl:%u\n", DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s w:%u fl:%u\n",
pdpu->pipe - SSPP_VIG0, pipe->sspp->idx - SSPP_VIG0,
(char *)&fmt->base.pixel_format, (char *)&fmt->base.pixel_format,
src_width, total_fl); src_width, total_fl);
...@@ -272,24 +257,22 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, ...@@ -272,24 +257,22 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
/** /**
* _dpu_plane_set_qos_lut - set QoS LUT of the given plane * _dpu_plane_set_qos_lut - set QoS LUT of the given plane
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @fb: Pointer to framebuffer associated with the given plane * @pipe: Pointer to software pipe
* @fmt: Pointer to source buffer format
* @pipe_cfg: Pointer to pipe configuration * @pipe_cfg: Pointer to pipe configuration
*/ */
static void _dpu_plane_set_qos_lut(struct drm_plane *plane, static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
struct drm_framebuffer *fb, struct dpu_hw_pipe_cfg *pipe_cfg) struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt, struct dpu_sw_pipe_cfg *pipe_cfg)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
const struct dpu_format *fmt = NULL;
u64 qos_lut; u64 qos_lut;
u32 total_fl = 0, lut_usage; u32 total_fl = 0, lut_usage;
if (!pdpu->is_rt_pipe) { if (!pdpu->is_rt_pipe) {
lut_usage = DPU_QOS_LUT_USAGE_NRT; lut_usage = DPU_QOS_LUT_USAGE_NRT;
} else { } else {
fmt = dpu_get_dpu_format_ext( total_fl = _dpu_plane_calc_fill_level(plane, pipe, fmt,
fb->format->format,
fb->modifier);
total_fl = _dpu_plane_calc_fill_level(plane, fmt,
drm_rect_width(&pipe_cfg->src_rect)); drm_rect_width(&pipe_cfg->src_rect));
if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) if (fmt && DPU_FORMAT_IS_LINEAR(fmt))
...@@ -301,7 +284,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, ...@@ -301,7 +284,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
qos_lut = _dpu_hw_get_qos_lut( qos_lut = _dpu_hw_get_qos_lut(
&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl); &pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0, trace_dpu_perf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0,
(fmt) ? fmt->base.pixel_format : 0, (fmt) ? fmt->base.pixel_format : 0,
pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage); pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage);
...@@ -310,19 +293,20 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, ...@@ -310,19 +293,20 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
fmt ? (char *)&fmt->base.pixel_format : NULL, fmt ? (char *)&fmt->base.pixel_format : NULL,
pdpu->is_rt_pipe, total_fl, qos_lut); pdpu->is_rt_pipe, total_fl, qos_lut);
pdpu->pipe_hw->ops.setup_creq_lut(pdpu->pipe_hw, qos_lut); pipe->sspp->ops.setup_creq_lut(pipe->sspp, qos_lut);
} }
/** /**
* _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane * _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @fb: Pointer to framebuffer associated with the given plane * @pipe: Pointer to software pipe
* @fmt: Pointer to source buffer format
*/ */
static void _dpu_plane_set_danger_lut(struct drm_plane *plane, static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
struct drm_framebuffer *fb) struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
const struct dpu_format *fmt = NULL;
u32 danger_lut, safe_lut; u32 danger_lut, safe_lut;
if (!pdpu->is_rt_pipe) { if (!pdpu->is_rt_pipe) {
...@@ -331,10 +315,6 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane, ...@@ -331,10 +315,6 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
safe_lut = pdpu->catalog->perf->safe_lut_tbl safe_lut = pdpu->catalog->perf->safe_lut_tbl
[DPU_QOS_LUT_USAGE_NRT]; [DPU_QOS_LUT_USAGE_NRT];
} else { } else {
fmt = dpu_get_dpu_format_ext(
fb->format->format,
fb->modifier);
if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) { if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
danger_lut = pdpu->catalog->perf->danger_lut_tbl danger_lut = pdpu->catalog->perf->danger_lut_tbl
[DPU_QOS_LUT_USAGE_LINEAR]; [DPU_QOS_LUT_USAGE_LINEAR];
...@@ -361,17 +341,19 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane, ...@@ -361,17 +341,19 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
danger_lut, danger_lut,
safe_lut); safe_lut);
pdpu->pipe_hw->ops.setup_danger_safe_lut(pdpu->pipe_hw, pipe->sspp->ops.setup_danger_safe_lut(pipe->sspp,
danger_lut, safe_lut); danger_lut, safe_lut);
} }
/** /**
* _dpu_plane_set_qos_ctrl - set QoS control of the given plane * _dpu_plane_set_qos_ctrl - set QoS control of the given plane
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @pipe: Pointer to software pipe
* @enable: true to enable QoS control * @enable: true to enable QoS control
* @flags: QoS control mode (enum dpu_plane_qos) * @flags: QoS control mode (enum dpu_plane_qos)
*/ */
static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
bool enable, u32 flags) bool enable, u32 flags)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
...@@ -380,9 +362,9 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, ...@@ -380,9 +362,9 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
memset(&pipe_qos_cfg, 0, sizeof(pipe_qos_cfg)); memset(&pipe_qos_cfg, 0, sizeof(pipe_qos_cfg));
if (flags & DPU_PLANE_QOS_VBLANK_CTRL) { if (flags & DPU_PLANE_QOS_VBLANK_CTRL) {
pipe_qos_cfg.creq_vblank = pdpu->pipe_hw->cap->sblk->creq_vblank; pipe_qos_cfg.creq_vblank = pipe->sspp->cap->sblk->creq_vblank;
pipe_qos_cfg.danger_vblank = pipe_qos_cfg.danger_vblank =
pdpu->pipe_hw->cap->sblk->danger_vblank; pipe->sspp->cap->sblk->danger_vblank;
pipe_qos_cfg.vblank_en = enable; pipe_qos_cfg.vblank_en = enable;
} }
...@@ -408,32 +390,35 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, ...@@ -408,32 +390,35 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
pipe_qos_cfg.danger_vblank, pipe_qos_cfg.danger_vblank,
pdpu->is_rt_pipe); pdpu->is_rt_pipe);
pdpu->pipe_hw->ops.setup_qos_ctrl(pdpu->pipe_hw, pipe->sspp->ops.setup_qos_ctrl(pipe->sspp,
&pipe_qos_cfg); &pipe_qos_cfg);
} }
/** /**
* _dpu_plane_set_ot_limit - set OT limit for the given plane * _dpu_plane_set_ot_limit - set OT limit for the given plane
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @crtc: Pointer to drm crtc * @pipe: Pointer to software pipe
* @pipe_cfg: Pointer to pipe configuration * @pipe_cfg: Pointer to pipe configuration
* @frame_rate: CRTC's frame rate
*/ */
static void _dpu_plane_set_ot_limit(struct drm_plane *plane, static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
struct drm_crtc *crtc, struct dpu_hw_pipe_cfg *pipe_cfg) struct dpu_sw_pipe *pipe,
struct dpu_sw_pipe_cfg *pipe_cfg,
int frame_rate)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_vbif_set_ot_params ot_params; struct dpu_vbif_set_ot_params ot_params;
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
memset(&ot_params, 0, sizeof(ot_params)); memset(&ot_params, 0, sizeof(ot_params));
ot_params.xin_id = pdpu->pipe_hw->cap->xin_id; ot_params.xin_id = pipe->sspp->cap->xin_id;
ot_params.num = pdpu->pipe_hw->idx - SSPP_NONE; ot_params.num = pipe->sspp->idx - SSPP_NONE;
ot_params.width = drm_rect_width(&pipe_cfg->src_rect); ot_params.width = drm_rect_width(&pipe_cfg->src_rect);
ot_params.height = drm_rect_height(&pipe_cfg->src_rect); ot_params.height = drm_rect_height(&pipe_cfg->src_rect);
ot_params.is_wfd = !pdpu->is_rt_pipe; ot_params.is_wfd = !pdpu->is_rt_pipe;
ot_params.frame_rate = drm_mode_vrefresh(&crtc->mode); ot_params.frame_rate = frame_rate;
ot_params.vbif_idx = VBIF_RT; ot_params.vbif_idx = VBIF_RT;
ot_params.clk_ctrl = pdpu->pipe_hw->cap->clk_ctrl; ot_params.clk_ctrl = pipe->sspp->cap->clk_ctrl;
ot_params.rd = true; ot_params.rd = true;
dpu_vbif_set_ot_limit(dpu_kms, &ot_params); dpu_vbif_set_ot_limit(dpu_kms, &ot_params);
...@@ -442,8 +427,10 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, ...@@ -442,8 +427,10 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
/** /**
* _dpu_plane_set_qos_remap - set vbif QoS for the given plane * _dpu_plane_set_qos_remap - set vbif QoS for the given plane
* @plane: Pointer to drm plane * @plane: Pointer to drm plane
* @pipe: Pointer to software pipe
*/ */
static void _dpu_plane_set_qos_remap(struct drm_plane *plane) static void _dpu_plane_set_qos_remap(struct drm_plane *plane,
struct dpu_sw_pipe *pipe)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_vbif_set_qos_params qos_params; struct dpu_vbif_set_qos_params qos_params;
...@@ -451,9 +438,9 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane) ...@@ -451,9 +438,9 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
memset(&qos_params, 0, sizeof(qos_params)); memset(&qos_params, 0, sizeof(qos_params));
qos_params.vbif_idx = VBIF_RT; qos_params.vbif_idx = VBIF_RT;
qos_params.clk_ctrl = pdpu->pipe_hw->cap->clk_ctrl; qos_params.clk_ctrl = pipe->sspp->cap->clk_ctrl;
qos_params.xin_id = pdpu->pipe_hw->cap->xin_id; qos_params.xin_id = pipe->sspp->cap->xin_id;
qos_params.num = pdpu->pipe_hw->idx - SSPP_VIG0; qos_params.num = pipe->sspp->idx - SSPP_VIG0;
qos_params.is_rt = pdpu->is_rt_pipe; qos_params.is_rt = pdpu->is_rt_pipe;
DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n", DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
...@@ -465,39 +452,15 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane) ...@@ -465,39 +452,15 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
dpu_vbif_set_qos_remap(dpu_kms, &qos_params); dpu_vbif_set_qos_remap(dpu_kms, &qos_params);
} }
static void _dpu_plane_set_scanout(struct drm_plane *plane, static void _dpu_plane_setup_scaler3(struct dpu_hw_sspp *pipe_hw,
struct dpu_plane_state *pstate,
struct dpu_hw_pipe_cfg *pipe_cfg,
struct drm_framebuffer *fb)
{
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
struct msm_gem_address_space *aspace = kms->base.aspace;
int ret;
ret = dpu_format_populate_layout(aspace, fb, &pipe_cfg->layout);
if (ret == -EAGAIN)
DPU_DEBUG_PLANE(pdpu, "not updating same src addrs\n");
else if (ret)
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
else if (pdpu->pipe_hw->ops.setup_sourceaddress) {
trace_dpu_plane_set_scanout(pdpu->pipe_hw->idx,
&pipe_cfg->layout,
pstate->multirect_index);
pdpu->pipe_hw->ops.setup_sourceaddress(pdpu->pipe_hw, pipe_cfg,
pstate->multirect_index);
}
}
static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
struct dpu_plane_state *pstate,
uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
struct dpu_hw_scaler3_cfg *scale_cfg, struct dpu_hw_scaler3_cfg *scale_cfg,
const struct dpu_format *fmt, const struct dpu_format *fmt,
uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v,
unsigned int rotation)
{ {
uint32_t i; uint32_t i;
bool inline_rotation = pstate->rotation & DRM_MODE_ROTATE_90; bool inline_rotation = rotation & DRM_MODE_ROTATE_90;
/* /*
* For inline rotation cases, scaler config is post-rotation, * For inline rotation cases, scaler config is post-rotation,
...@@ -536,7 +499,7 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, ...@@ -536,7 +499,7 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
scale_cfg->src_height[i] /= chroma_subsmpl_v; scale_cfg->src_height[i] /= chroma_subsmpl_v;
} }
if (pdpu->pipe_hw->cap->features & if (pipe_hw->cap->features &
BIT(DPU_SSPP_SCALER_QSEED4)) { BIT(DPU_SSPP_SCALER_QSEED4)) {
scale_cfg->preload_x[i] = DPU_QSEED4_DEFAULT_PRELOAD_H; scale_cfg->preload_x[i] = DPU_QSEED4_DEFAULT_PRELOAD_H;
scale_cfg->preload_y[i] = DPU_QSEED4_DEFAULT_PRELOAD_V; scale_cfg->preload_y[i] = DPU_QSEED4_DEFAULT_PRELOAD_V;
...@@ -607,36 +570,28 @@ static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { ...@@ -607,36 +570,28 @@ static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = {
{ 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,}, { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
}; };
static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_plane *pdpu, const struct dpu_format *fmt) static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_sw_pipe *pipe,
const struct dpu_format *fmt)
{ {
const struct dpu_csc_cfg *csc_ptr; const struct dpu_csc_cfg *csc_ptr;
if (!pdpu) {
DPU_ERROR("invalid plane\n");
return NULL;
}
if (!DPU_FORMAT_IS_YUV(fmt)) if (!DPU_FORMAT_IS_YUV(fmt))
return NULL; return NULL;
if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->pipe_hw->cap->features) if (BIT(DPU_SSPP_CSC_10BIT) & pipe->sspp->cap->features)
csc_ptr = &dpu_csc10_YUV2RGB_601L; csc_ptr = &dpu_csc10_YUV2RGB_601L;
else else
csc_ptr = &dpu_csc_YUV2RGB_601L; csc_ptr = &dpu_csc_YUV2RGB_601L;
DPU_DEBUG_PLANE(pdpu, "using 0x%X 0x%X 0x%X...\n",
csc_ptr->csc_mv[0],
csc_ptr->csc_mv[1],
csc_ptr->csc_mv[2]);
return csc_ptr; return csc_ptr;
} }
static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, static void _dpu_plane_setup_scaler(struct dpu_sw_pipe *pipe,
struct dpu_plane_state *pstate,
const struct dpu_format *fmt, bool color_fill, const struct dpu_format *fmt, bool color_fill,
struct dpu_hw_pipe_cfg *pipe_cfg) struct dpu_sw_pipe_cfg *pipe_cfg,
unsigned int rotation)
{ {
struct dpu_hw_sspp *pipe_hw = pipe->sspp;
const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format); const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format);
struct dpu_hw_scaler3_cfg scaler3_cfg; struct dpu_hw_scaler3_cfg scaler3_cfg;
struct dpu_hw_pixel_ext pixel_ext; struct dpu_hw_pixel_ext pixel_ext;
...@@ -650,20 +605,21 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, ...@@ -650,20 +605,21 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
/* don't chroma subsample if decimating */ /* don't chroma subsample if decimating */
/* update scaler. calculate default config for QSEED3 */ /* update scaler. calculate default config for QSEED3 */
_dpu_plane_setup_scaler3(pdpu, pstate, _dpu_plane_setup_scaler3(pipe_hw,
src_width, src_width,
src_height, src_height,
dst_width, dst_width,
dst_height, dst_height,
&scaler3_cfg, fmt, &scaler3_cfg, fmt,
info->hsub, info->vsub); info->hsub, info->vsub,
rotation);
/* configure pixel extension based on scalar config */ /* configure pixel extension based on scalar config */
_dpu_plane_setup_pixel_ext(&scaler3_cfg, &pixel_ext, _dpu_plane_setup_pixel_ext(&scaler3_cfg, &pixel_ext,
src_width, src_height, info->hsub, info->vsub); src_width, src_height, info->hsub, info->vsub);
if (pdpu->pipe_hw->ops.setup_pe) if (pipe_hw->ops.setup_pe)
pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw, pipe_hw->ops.setup_pe(pipe_hw,
&pixel_ext); &pixel_ext);
/** /**
...@@ -671,11 +627,44 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, ...@@ -671,11 +627,44 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
* bypassed. Still we need to update alpha and bitwidth * bypassed. Still we need to update alpha and bitwidth
* ONLY for RECT0 * ONLY for RECT0
*/ */
if (pdpu->pipe_hw->ops.setup_scaler && if (pipe_hw->ops.setup_scaler &&
pstate->multirect_index != DPU_SSPP_RECT_1) pipe->multirect_index != DPU_SSPP_RECT_1)
pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw, pipe_hw->ops.setup_scaler(pipe_hw,
pipe_cfg, &scaler3_cfg,
&scaler3_cfg); fmt);
}
static void _dpu_plane_color_fill_pipe(struct dpu_plane_state *pstate,
struct dpu_sw_pipe *pipe,
struct drm_rect *dst_rect,
u32 fill_color,
const struct dpu_format *fmt)
{
struct dpu_sw_pipe_cfg pipe_cfg;
/* update sspp */
if (!pipe->sspp->ops.setup_solidfill)
return;
pipe->sspp->ops.setup_solidfill(pipe, fill_color);
/* override scaler/decimation if solid fill */
pipe_cfg.dst_rect = *dst_rect;
pipe_cfg.src_rect.x1 = 0;
pipe_cfg.src_rect.y1 = 0;
pipe_cfg.src_rect.x2 =
drm_rect_width(&pipe_cfg.dst_rect);
pipe_cfg.src_rect.y2 =
drm_rect_height(&pipe_cfg.dst_rect);
if (pipe->sspp->ops.setup_format)
pipe->sspp->ops.setup_format(pipe, fmt, DPU_SSPP_SOLID_FILL);
if (pipe->sspp->ops.setup_rects)
pipe->sspp->ops.setup_rects(pipe, &pipe_cfg);
_dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg, pstate->rotation);
} }
/** /**
...@@ -683,15 +672,14 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, ...@@ -683,15 +672,14 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
* @pdpu: Pointer to DPU plane object * @pdpu: Pointer to DPU plane object
* @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
* @alpha: 8-bit fill alpha value, 255 selects 100% alpha * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
* Returns: 0 on success
*/ */
static int _dpu_plane_color_fill(struct dpu_plane *pdpu, static void _dpu_plane_color_fill(struct dpu_plane *pdpu,
uint32_t color, uint32_t alpha) uint32_t color, uint32_t alpha)
{ {
const struct dpu_format *fmt; const struct dpu_format *fmt;
const struct drm_plane *plane = &pdpu->base; const struct drm_plane *plane = &pdpu->base;
struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
struct dpu_hw_pipe_cfg pipe_cfg; u32 fill_color = (color & 0xFFFFFF) | ((alpha & 0xFF) << 24);
DPU_DEBUG_PLANE(pdpu, "\n"); DPU_DEBUG_PLANE(pdpu, "\n");
...@@ -700,156 +688,17 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, ...@@ -700,156 +688,17 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
* h/w only supports RGB variants * h/w only supports RGB variants
*/ */
fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR8888); fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR8888);
/* should not happen ever */
if (!fmt)
return;
/* update sspp */ /* update sspp */
if (fmt && pdpu->pipe_hw->ops.setup_solidfill) { _dpu_plane_color_fill_pipe(pstate, &pstate->pipe, &pstate->pipe_cfg.dst_rect,
pdpu->pipe_hw->ops.setup_solidfill(pdpu->pipe_hw, fill_color, fmt);
(color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
pstate->multirect_index);
/* override scaler/decimation if solid fill */
pipe_cfg.dst_rect = pstate->base.dst;
pipe_cfg.src_rect.x1 = 0;
pipe_cfg.src_rect.y1 = 0;
pipe_cfg.src_rect.x2 =
drm_rect_width(&pipe_cfg.dst_rect);
pipe_cfg.src_rect.y2 =
drm_rect_height(&pipe_cfg.dst_rect);
if (pdpu->pipe_hw->ops.setup_format)
pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw,
fmt, DPU_SSPP_SOLID_FILL,
pstate->multirect_index);
if (pdpu->pipe_hw->ops.setup_rects)
pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw,
&pipe_cfg,
pstate->multirect_index);
_dpu_plane_setup_scaler(pdpu, pstate, fmt, true, &pipe_cfg);
}
return 0;
}
void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state)
{
struct dpu_plane_state *pstate = to_dpu_plane_state(drm_state);
pstate->multirect_index = DPU_SSPP_RECT_SOLO;
pstate->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
}
int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
{
struct dpu_plane_state *pstate[R_MAX];
const struct drm_plane_state *drm_state[R_MAX];
struct drm_rect src[R_MAX], dst[R_MAX];
struct dpu_plane *dpu_plane[R_MAX];
const struct dpu_format *fmt[R_MAX];
int i, buffer_lines;
unsigned int max_tile_height = 1;
bool parallel_fetch_qualified = true;
bool has_tiled_rect = false;
for (i = 0; i < R_MAX; i++) {
const struct msm_format *msm_fmt;
drm_state[i] = i ? plane->r1 : plane->r0;
msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
fmt[i] = to_dpu_format(msm_fmt);
if (DPU_FORMAT_IS_UBWC(fmt[i])) {
has_tiled_rect = true;
if (fmt[i]->tile_height > max_tile_height)
max_tile_height = fmt[i]->tile_height;
}
}
for (i = 0; i < R_MAX; i++) {
int width_threshold;
pstate[i] = to_dpu_plane_state(drm_state[i]);
dpu_plane[i] = to_dpu_plane(drm_state[i]->plane);
if (pstate[i] == NULL) {
DPU_ERROR("DPU plane state of plane id %d is NULL\n",
drm_state[i]->plane->base.id);
return -EINVAL;
}
src[i].x1 = drm_state[i]->src_x >> 16;
src[i].y1 = drm_state[i]->src_y >> 16;
src[i].x2 = src[i].x1 + (drm_state[i]->src_w >> 16);
src[i].y2 = src[i].y1 + (drm_state[i]->src_h >> 16);
dst[i] = drm_plane_state_dest(drm_state[i]);
if (drm_rect_calc_hscale(&src[i], &dst[i], 1, 1) != 1 ||
drm_rect_calc_vscale(&src[i], &dst[i], 1, 1) != 1) {
DPU_ERROR_PLANE(dpu_plane[i],
"scaling is not supported in multirect mode\n");
return -EINVAL;
}
if (DPU_FORMAT_IS_YUV(fmt[i])) {
DPU_ERROR_PLANE(dpu_plane[i],
"Unsupported format for multirect mode\n");
return -EINVAL;
}
/**
* SSPP PD_MEM is split half - one for each RECT.
* Tiled formats need 5 lines of buffering while fetching
* whereas linear formats need only 2 lines.
* So we cannot support more than half of the supported SSPP
* width for tiled formats.
*/
width_threshold = dpu_plane[i]->catalog->caps->max_linewidth;
if (has_tiled_rect)
width_threshold /= 2;
if (parallel_fetch_qualified &&
drm_rect_width(&src[i]) > width_threshold)
parallel_fetch_qualified = false;
}
/* Validate RECT's and set the mode */
/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
if (parallel_fetch_qualified) {
pstate[R0]->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
pstate[R1]->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
goto done;
}
/* TIME_MX Mode */
buffer_lines = 2 * max_tile_height;
if (dst[R1].y1 >= dst[R0].y2 + buffer_lines || if (pstate->r_pipe.sspp)
dst[R0].y1 >= dst[R1].y2 + buffer_lines) { _dpu_plane_color_fill_pipe(pstate, &pstate->r_pipe, &pstate->r_pipe_cfg.dst_rect,
pstate[R0]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; fill_color, fmt);
pstate[R1]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
} else {
DPU_ERROR(
"No multirect mode possible for the planes (%d - %d)\n",
drm_state[R0]->plane->base.id,
drm_state[R1]->plane->base.id);
return -EINVAL;
}
done:
pstate[R0]->multirect_index = DPU_SSPP_RECT_0;
pstate[R1]->multirect_index = DPU_SSPP_RECT_1;
DPU_DEBUG_PLANE(dpu_plane[R0], "R0: %d - %d\n",
pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
DPU_DEBUG_PLANE(dpu_plane[R1], "R1: %d - %d\n",
pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
return 0;
} }
static int dpu_plane_prepare_fb(struct drm_plane *plane, static int dpu_plane_prepare_fb(struct drm_plane *plane,
...@@ -914,25 +763,6 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane, ...@@ -914,25 +763,6 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane,
old_pstate->needs_dirtyfb); old_pstate->needs_dirtyfb);
} }
static bool dpu_plane_validate_src(struct drm_rect *src,
struct drm_rect *fb_rect,
uint32_t min_src_size)
{
/* Ensure fb size is supported */
if (drm_rect_width(fb_rect) > MAX_IMG_WIDTH ||
drm_rect_height(fb_rect) > MAX_IMG_HEIGHT)
return false;
/* Ensure src rect is above the minimum size */
if (drm_rect_width(src) < min_src_size ||
drm_rect_height(src) < min_src_size)
return false;
/* Ensure src is fully encapsulated in fb */
return drm_rect_intersect(fb_rect, src) &&
drm_rect_equals(fb_rect, src);
}
static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu,
const struct dpu_sspp_sub_blks *sblk, const struct dpu_sspp_sub_blks *sblk,
struct drm_rect src, const struct dpu_format *fmt) struct drm_rect src, const struct dpu_format *fmt)
...@@ -961,6 +791,53 @@ static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, ...@@ -961,6 +791,53 @@ static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu,
return 0; return 0;
} }
static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
struct dpu_sw_pipe *pipe,
struct dpu_sw_pipe_cfg *pipe_cfg,
const struct dpu_format *fmt)
{
uint32_t min_src_size;
min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1;
if (DPU_FORMAT_IS_YUV(fmt) &&
(!(pipe->sspp->cap->features & DPU_SSPP_SCALER) ||
!(pipe->sspp->cap->features & DPU_SSPP_CSC_ANY))) {
DPU_DEBUG_PLANE(pdpu,
"plane doesn't have scaler/csc for yuv\n");
return -EINVAL;
}
/* check src bounds */
if (drm_rect_width(&pipe_cfg->src_rect) < min_src_size ||
drm_rect_height(&pipe_cfg->src_rect) < min_src_size) {
DPU_DEBUG_PLANE(pdpu, "invalid source " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->src_rect));
return -E2BIG;
}
/* valid yuv image */
if (DPU_FORMAT_IS_YUV(fmt) &&
(pipe_cfg->src_rect.x1 & 0x1 ||
pipe_cfg->src_rect.y1 & 0x1 ||
drm_rect_width(&pipe_cfg->src_rect) & 0x1 ||
drm_rect_height(&pipe_cfg->src_rect) & 0x1)) {
DPU_DEBUG_PLANE(pdpu, "invalid yuv source " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->src_rect));
return -EINVAL;
}
/* min dst support */
if (drm_rect_width(&pipe_cfg->dst_rect) < 0x1 ||
drm_rect_height(&pipe_cfg->dst_rect) < 0x1) {
DPU_DEBUG_PLANE(pdpu, "invalid dest rect " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->dst_rect));
return -EINVAL;
}
return 0;
}
static int dpu_plane_atomic_check(struct drm_plane *plane, static int dpu_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
...@@ -969,14 +846,18 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, ...@@ -969,14 +846,18 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
int ret = 0, min_scale; int ret = 0, min_scale;
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state); struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
struct dpu_sw_pipe *pipe = &pstate->pipe;
struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
const struct drm_crtc_state *crtc_state = NULL; const struct drm_crtc_state *crtc_state = NULL;
const struct dpu_format *fmt; const struct dpu_format *fmt;
struct drm_rect src, dst, fb_rect = { 0 }; struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
uint32_t min_src_size, max_linewidth; struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
struct drm_rect fb_rect = { 0 };
uint32_t max_linewidth;
unsigned int rotation; unsigned int rotation;
uint32_t supported_rotations; uint32_t supported_rotations;
const struct dpu_sspp_cfg *pipe_hw_caps = pdpu->pipe_hw->cap; const struct dpu_sspp_cfg *pipe_hw_caps = pstate->pipe.sspp->cap;
const struct dpu_sspp_sub_blks *sblk = pdpu->pipe_hw->cap->sblk; const struct dpu_sspp_sub_blks *sblk = pstate->pipe.sspp->cap->sblk;
if (new_plane_state->crtc) if (new_plane_state->crtc)
crtc_state = drm_atomic_get_new_crtc_state(state, crtc_state = drm_atomic_get_new_crtc_state(state,
...@@ -994,55 +875,99 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, ...@@ -994,55 +875,99 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
if (!new_plane_state->visible) if (!new_plane_state->visible)
return 0; return 0;
src.x1 = new_plane_state->src_x >> 16; pipe->multirect_index = DPU_SSPP_RECT_SOLO;
src.y1 = new_plane_state->src_y >> 16; pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
src.x2 = src.x1 + (new_plane_state->src_w >> 16); r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
src.y2 = src.y1 + (new_plane_state->src_h >> 16); r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
r_pipe->sspp = NULL;
pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos;
if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) {
DPU_ERROR("> %d plane stages assigned\n",
pdpu->catalog->caps->max_mixer_blendstages - DPU_STAGE_0);
return -EINVAL;
}
pipe_cfg->src_rect = new_plane_state->src;
/* state->src is 16.16, src_rect is not */
pipe_cfg->src_rect.x1 >>= 16;
pipe_cfg->src_rect.x2 >>= 16;
pipe_cfg->src_rect.y1 >>= 16;
pipe_cfg->src_rect.y2 >>= 16;
dst = drm_plane_state_dest(new_plane_state); pipe_cfg->dst_rect = new_plane_state->dst;
fb_rect.x2 = new_plane_state->fb->width; fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height; fb_rect.y2 = new_plane_state->fb->height;
max_linewidth = pdpu->catalog->caps->max_linewidth; /* Ensure fb size is supported */
if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH ||
drm_rect_height(&fb_rect) > MAX_IMG_HEIGHT) {
DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&fb_rect));
return -E2BIG;
}
fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb));
min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; max_linewidth = pdpu->catalog->caps->max_linewidth;
if (DPU_FORMAT_IS_YUV(fmt) && if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
(!(pipe_hw_caps->features & DPU_SSPP_SCALER) || /*
!(pipe_hw_caps->features & DPU_SSPP_CSC_ANY))) { * In parallel multirect case only the half of the usual width
DPU_DEBUG_PLANE(pdpu, * is supported for tiled formats. If we are here, we know that
"plane doesn't have scaler/csc for yuv\n"); * full width is more than max_linewidth, thus each rect is
return -EINVAL; * wider than allowed.
*/
if (DPU_FORMAT_IS_UBWC(fmt)) {
DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, tiled format\n",
DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
return -E2BIG;
}
/* check src bounds */ if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
} else if (!dpu_plane_validate_src(&src, &fb_rect, min_src_size)) { DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
DPU_DEBUG_PLANE(pdpu, "invalid source " DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
DRM_RECT_ARG(&src)); return -E2BIG;
return -E2BIG; }
/* valid yuv image */ if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) ||
} else if (DPU_FORMAT_IS_YUV(fmt) && drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect) ||
(src.x1 & 0x1 || src.y1 & 0x1 || (!test_bit(DPU_SSPP_SMART_DMA_V1, &pipe->sspp->cap->features) &&
drm_rect_width(&src) & 0x1 || !test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) ||
drm_rect_height(&src) & 0x1)) { DPU_FORMAT_IS_YUV(fmt)) {
DPU_DEBUG_PLANE(pdpu, "invalid yuv source " DRM_RECT_FMT "\n", DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, can't use split source\n",
DRM_RECT_ARG(&src)); DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
return -EINVAL; return -E2BIG;
}
/* min dst support */ /*
} else if (drm_rect_width(&dst) < 0x1 || drm_rect_height(&dst) < 0x1) { * Use multirect for wide plane. We do not support dynamic
DPU_DEBUG_PLANE(pdpu, "invalid dest rect " DRM_RECT_FMT "\n", * assignment of SSPPs, so we know the configuration.
DRM_RECT_ARG(&dst)); */
return -EINVAL; pipe->multirect_index = DPU_SSPP_RECT_0;
pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
r_pipe->sspp = pipe->sspp;
r_pipe->multirect_index = DPU_SSPP_RECT_1;
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
*r_pipe_cfg = *pipe_cfg;
pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
}
/* check decimated source width */ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
} else if (drm_rect_width(&src) > max_linewidth) { if (ret)
DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", return ret;
DRM_RECT_ARG(&src), max_linewidth);
return -E2BIG; if (r_pipe->sspp) {
ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt);
if (ret)
return ret;
} }
supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0; supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0;
...@@ -1055,7 +980,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, ...@@ -1055,7 +980,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
if ((pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) && if ((pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) &&
(rotation & DRM_MODE_ROTATE_90)) { (rotation & DRM_MODE_ROTATE_90)) {
ret = dpu_plane_check_inline_rotation(pdpu, sblk, src, fmt); ret = dpu_plane_check_inline_rotation(pdpu, sblk, pipe_cfg->src_rect, fmt);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -1066,6 +991,28 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, ...@@ -1066,6 +991,28 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return 0; return 0;
} }
static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe)
{
const struct dpu_format *format =
to_dpu_format(msm_framebuffer_format(pdpu->base.state->fb));
const struct dpu_csc_cfg *csc_ptr;
if (!pipe->sspp || !pipe->sspp->ops.setup_csc)
return;
csc_ptr = _dpu_plane_get_csc(pipe, format);
if (!csc_ptr)
return;
DPU_DEBUG_PLANE(pdpu, "using 0x%X 0x%X 0x%X...\n",
csc_ptr->csc_mv[0],
csc_ptr->csc_mv[1],
csc_ptr->csc_mv[2]);
pipe->sspp->ops.setup_csc(pipe->sspp, csc_ptr);
}
void dpu_plane_flush(struct drm_plane *plane) void dpu_plane_flush(struct drm_plane *plane)
{ {
struct dpu_plane *pdpu; struct dpu_plane *pdpu;
...@@ -1089,12 +1036,9 @@ void dpu_plane_flush(struct drm_plane *plane) ...@@ -1089,12 +1036,9 @@ void dpu_plane_flush(struct drm_plane *plane)
else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG)
/* force 100% alpha */ /* force 100% alpha */
_dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF);
else if (pdpu->pipe_hw && pdpu->pipe_hw->ops.setup_csc) { else {
const struct dpu_format *fmt = to_dpu_format(msm_framebuffer_format(plane->state->fb)); dpu_plane_flush_csc(pdpu, &pstate->pipe);
const struct dpu_csc_cfg *csc_ptr = _dpu_plane_get_csc(pdpu, fmt); dpu_plane_flush_csc(pdpu, &pstate->r_pipe);
if (csc_ptr)
pdpu->pipe_hw->ops.setup_csc(pdpu->pipe_hw, csc_ptr);
} }
/* flag h/w flush complete */ /* flag h/w flush complete */
...@@ -1118,45 +1062,24 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error) ...@@ -1118,45 +1062,24 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error)
pdpu->is_error = error; pdpu->is_error = error;
} }
static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
struct dpu_sw_pipe_cfg *pipe_cfg,
const struct dpu_format *fmt,
int frame_rate,
struct dpu_hw_fmt_layout *layout)
{ {
uint32_t src_flags; uint32_t src_flags;
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
struct drm_plane_state *state = plane->state; struct drm_plane_state *state = plane->state;
struct dpu_plane_state *pstate = to_dpu_plane_state(state); struct dpu_plane_state *pstate = to_dpu_plane_state(state);
struct drm_crtc *crtc = state->crtc;
struct drm_framebuffer *fb = state->fb;
bool is_rt_pipe;
const struct dpu_format *fmt =
to_dpu_format(msm_framebuffer_format(fb));
struct dpu_hw_pipe_cfg pipe_cfg;
memset(&pipe_cfg, 0, sizeof(struct dpu_hw_pipe_cfg));
_dpu_plane_set_scanout(plane, pstate, &pipe_cfg, fb); if (layout && pipe->sspp->ops.setup_sourceaddress) {
trace_dpu_plane_set_scanout(pipe, layout);
pstate->pending = true; pipe->sspp->ops.setup_sourceaddress(pipe, layout);
}
is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT);
pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe);
pdpu->is_rt_pipe = is_rt_pipe;
_dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL);
DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT
", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src),
crtc->base.id, DRM_RECT_ARG(&state->dst),
(char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt));
pipe_cfg.src_rect = state->src;
/* state->src is 16.16, src_rect is not */
pipe_cfg.src_rect.x1 >>= 16;
pipe_cfg.src_rect.x2 >>= 16;
pipe_cfg.src_rect.y1 >>= 16;
pipe_cfg.src_rect.y2 >>= 16;
pipe_cfg.dst_rect = state->dst; _dpu_plane_set_qos_ctrl(plane, pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
/* override for color fill */ /* override for color fill */
if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
...@@ -1164,21 +1087,18 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) ...@@ -1164,21 +1087,18 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
return; return;
} }
if (pdpu->pipe_hw->ops.setup_rects) { if (pipe->sspp->ops.setup_rects) {
pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw, pipe->sspp->ops.setup_rects(pipe,
&pipe_cfg, pipe_cfg);
pstate->multirect_index);
} }
_dpu_plane_setup_scaler(pdpu, pstate, fmt, false, &pipe_cfg); _dpu_plane_setup_scaler(pipe, fmt, false, pipe_cfg, pstate->rotation);
if (pdpu->pipe_hw->ops.setup_multirect) if (pipe->sspp->ops.setup_multirect)
pdpu->pipe_hw->ops.setup_multirect( pipe->sspp->ops.setup_multirect(
pdpu->pipe_hw, pipe);
pstate->multirect_index,
pstate->multirect_mode);
if (pdpu->pipe_hw->ops.setup_format) { if (pipe->sspp->ops.setup_format) {
unsigned int rotation = pstate->rotation; unsigned int rotation = pstate->rotation;
src_flags = 0x0; src_flags = 0x0;
...@@ -1193,10 +1113,9 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) ...@@ -1193,10 +1113,9 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
src_flags |= DPU_SSPP_ROT_90; src_flags |= DPU_SSPP_ROT_90;
/* update format */ /* update format */
pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw, fmt, src_flags, pipe->sspp->ops.setup_format(pipe, fmt, src_flags);
pstate->multirect_index);
if (pdpu->pipe_hw->ops.setup_cdp) { if (pipe->sspp->ops.setup_cdp) {
struct dpu_hw_cdp_cfg cdp_cfg; struct dpu_hw_cdp_cfg cdp_cfg;
memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg)); memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
...@@ -1210,35 +1129,100 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) ...@@ -1210,35 +1129,100 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
DPU_FORMAT_IS_TILE(fmt); DPU_FORMAT_IS_TILE(fmt);
cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64;
pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, &cdp_cfg, pstate->multirect_index); pipe->sspp->ops.setup_cdp(pipe, &cdp_cfg);
} }
} }
_dpu_plane_set_qos_lut(plane, fb, &pipe_cfg); _dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);
_dpu_plane_set_danger_lut(plane, fb); _dpu_plane_set_danger_lut(plane, pipe, fmt);
if (plane->type != DRM_PLANE_TYPE_CURSOR) { if (plane->type != DRM_PLANE_TYPE_CURSOR) {
_dpu_plane_set_qos_ctrl(plane, true, DPU_PLANE_QOS_PANIC_CTRL); _dpu_plane_set_qos_ctrl(plane, pipe, true, DPU_PLANE_QOS_PANIC_CTRL);
_dpu_plane_set_ot_limit(plane, crtc, &pipe_cfg); _dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate);
} }
if (pstate->needs_qos_remap) { if (pstate->needs_qos_remap)
pstate->needs_qos_remap = false; _dpu_plane_set_qos_remap(plane, pipe);
_dpu_plane_set_qos_remap(plane); }
static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
{
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct drm_plane_state *state = plane->state;
struct dpu_plane_state *pstate = to_dpu_plane_state(state);
struct dpu_sw_pipe *pipe = &pstate->pipe;
struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
struct drm_crtc *crtc = state->crtc;
struct drm_framebuffer *fb = state->fb;
bool is_rt_pipe;
const struct dpu_format *fmt =
to_dpu_format(msm_framebuffer_format(fb));
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
struct msm_gem_address_space *aspace = kms->base.aspace;
struct dpu_hw_fmt_layout layout;
bool layout_valid = false;
int ret;
ret = dpu_format_populate_layout(aspace, fb, &layout);
if (ret)
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
else
layout_valid = true;
pstate->pending = true;
is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT);
pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe);
pdpu->is_rt_pipe = is_rt_pipe;
DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT
", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src),
crtc->base.id, DRM_RECT_ARG(&state->dst),
(char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt));
dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt,
drm_mode_vrefresh(&crtc->mode),
layout_valid ? &layout : NULL);
if (r_pipe->sspp) {
dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
drm_mode_vrefresh(&crtc->mode),
layout_valid ? &layout : NULL);
} }
_dpu_plane_calc_bw(plane, fb, &pipe_cfg); if (pstate->needs_qos_remap)
pstate->needs_qos_remap = false;
pstate->plane_fetch_bw = _dpu_plane_calc_bw(pdpu->catalog, fmt,
&crtc->mode, pipe_cfg);
pstate->plane_clk = _dpu_plane_calc_clk(&crtc->mode, pipe_cfg);
_dpu_plane_calc_clk(plane, &pipe_cfg); if (r_pipe->sspp) {
pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt, &crtc->mode, r_pipe_cfg);
pstate->plane_clk = max(pstate->plane_clk, _dpu_plane_calc_clk(&crtc->mode, r_pipe_cfg));
}
} }
static void _dpu_plane_atomic_disable(struct drm_plane *plane) static void _dpu_plane_atomic_disable(struct drm_plane *plane)
{ {
struct drm_plane_state *state = plane->state; struct drm_plane_state *state = plane->state;
struct dpu_plane_state *pstate = to_dpu_plane_state(state); struct dpu_plane_state *pstate = to_dpu_plane_state(state);
struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
trace_dpu_plane_disable(DRMID(plane), false, trace_dpu_plane_disable(DRMID(plane), false,
pstate->multirect_mode); pstate->pipe.multirect_mode);
if (r_pipe->sspp) {
r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
if (r_pipe->sspp->ops.setup_multirect)
r_pipe->sspp->ops.setup_multirect(r_pipe);
}
pstate->pending = true; pstate->pending = true;
} }
...@@ -1264,19 +1248,22 @@ static void dpu_plane_atomic_update(struct drm_plane *plane, ...@@ -1264,19 +1248,22 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
static void dpu_plane_destroy(struct drm_plane *plane) static void dpu_plane_destroy(struct drm_plane *plane)
{ {
struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
struct dpu_plane_state *pstate;
DPU_DEBUG_PLANE(pdpu, "\n"); DPU_DEBUG_PLANE(pdpu, "\n");
if (pdpu) { if (pdpu) {
_dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL); pstate = to_dpu_plane_state(plane->state);
_dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
if (pstate->r_pipe.sspp)
_dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
mutex_destroy(&pdpu->lock); mutex_destroy(&pdpu->lock);
/* this will destroy the states as well */ /* this will destroy the states as well */
drm_plane_cleanup(plane); drm_plane_cleanup(plane);
dpu_hw_sspp_destroy(pdpu->pipe_hw);
kfree(pdpu); kfree(pdpu);
} }
} }
...@@ -1352,18 +1339,36 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p, ...@@ -1352,18 +1339,36 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p,
const struct drm_plane_state *state) const struct drm_plane_state *state)
{ {
const struct dpu_plane_state *pstate = to_dpu_plane_state(state); const struct dpu_plane_state *pstate = to_dpu_plane_state(state);
const struct dpu_plane *pdpu = to_dpu_plane(state->plane); const struct dpu_sw_pipe *pipe = &pstate->pipe;
const struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
const struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
const struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
drm_printf(p, "\tstage=%d\n", pstate->stage); drm_printf(p, "\tstage=%d\n", pstate->stage);
drm_printf(p, "\tsspp=%s\n", pdpu->pipe_hw->cap->name);
drm_printf(p, "\tmultirect_mode=%s\n", dpu_get_multirect_mode(pstate->multirect_mode)); drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
drm_printf(p, "\tmultirect_index=%s\n", dpu_get_multirect_index(pstate->multirect_index)); drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode));
drm_printf(p, "\tmultirect_index[0]=%s\n",
dpu_get_multirect_index(pipe->multirect_index));
drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
if (r_pipe->sspp) {
drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
drm_printf(p, "\tmultirect_mode[1]=%s\n",
dpu_get_multirect_mode(r_pipe->multirect_mode));
drm_printf(p, "\tmultirect_index[1]=%s\n",
dpu_get_multirect_index(r_pipe->multirect_index));
drm_printf(p, "\tsrc[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->src_rect));
drm_printf(p, "\tdst[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->dst_rect));
}
} }
static void dpu_plane_reset(struct drm_plane *plane) static void dpu_plane_reset(struct drm_plane *plane)
{ {
struct dpu_plane *pdpu; struct dpu_plane *pdpu;
struct dpu_plane_state *pstate; struct dpu_plane_state *pstate;
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
if (!plane) { if (!plane) {
DPU_ERROR("invalid plane\n"); DPU_ERROR("invalid plane\n");
...@@ -1385,6 +1390,16 @@ static void dpu_plane_reset(struct drm_plane *plane) ...@@ -1385,6 +1390,16 @@ static void dpu_plane_reset(struct drm_plane *plane)
return; return;
} }
/*
* Set the SSPP here until we have proper virtualized DPU planes.
* This is the place where the state is allocated, so fill it fully.
*/
pstate->pipe.sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO;
pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE;
pstate->r_pipe.sspp = NULL;
__drm_atomic_helper_plane_reset(plane, &pstate->base); __drm_atomic_helper_plane_reset(plane, &pstate->base);
} }
...@@ -1392,31 +1407,18 @@ static void dpu_plane_reset(struct drm_plane *plane) ...@@ -1392,31 +1407,18 @@ static void dpu_plane_reset(struct drm_plane *plane)
void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
{ {
struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
if (!pdpu->is_rt_pipe) if (!pdpu->is_rt_pipe)
return; return;
pm_runtime_get_sync(&dpu_kms->pdev->dev); pm_runtime_get_sync(&dpu_kms->pdev->dev);
_dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL); _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable, DPU_PLANE_QOS_PANIC_CTRL);
if (pstate->r_pipe.sspp)
_dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable, DPU_PLANE_QOS_PANIC_CTRL);
pm_runtime_put_sync(&dpu_kms->pdev->dev); pm_runtime_put_sync(&dpu_kms->pdev->dev);
} }
/* SSPP live inside dpu_plane private data only. Enumerate them here. */
void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
{
struct drm_plane *plane;
struct dentry *entry = debugfs_create_dir("sspp", debugfs_root);
if (IS_ERR(entry))
return;
drm_for_each_plane(plane, dpu_kms->dev) {
struct dpu_plane *pdpu = to_dpu_plane(plane);
_dpu_hw_sspp_init_debugfs(pdpu->pipe_hw, dpu_kms, entry);
}
}
#endif #endif
static bool dpu_plane_format_mod_supported(struct drm_plane *plane, static bool dpu_plane_format_mod_supported(struct drm_plane *plane,
...@@ -1450,11 +1452,6 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = { ...@@ -1450,11 +1452,6 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = {
.atomic_update = dpu_plane_atomic_update, .atomic_update = dpu_plane_atomic_update,
}; };
enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane)
{
return plane ? to_dpu_plane(plane)->pipe : SSPP_NONE;
}
/* initialize plane */ /* initialize plane */
struct drm_plane *dpu_plane_init(struct drm_device *dev, struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t pipe, enum drm_plane_type type, uint32_t pipe, enum drm_plane_type type,
...@@ -1465,6 +1462,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, ...@@ -1465,6 +1462,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
struct dpu_plane *pdpu; struct dpu_plane *pdpu;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
struct dpu_kms *kms = to_dpu_kms(priv->kms); struct dpu_kms *kms = to_dpu_kms(priv->kms);
struct dpu_hw_sspp *pipe_hw;
uint32_t num_formats; uint32_t num_formats;
uint32_t supported_rotations; uint32_t supported_rotations;
int ret = -EINVAL; int ret = -EINVAL;
...@@ -1482,24 +1480,20 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, ...@@ -1482,24 +1480,20 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
pdpu->pipe = pipe; pdpu->pipe = pipe;
/* initialize underlying h/w driver */ /* initialize underlying h/w driver */
pdpu->pipe_hw = dpu_hw_sspp_init(pipe, kms->mmio, kms->catalog); pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
if (IS_ERR(pdpu->pipe_hw)) { if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
DPU_ERROR("[%u]SSPP init failed\n", pipe); DPU_ERROR("[%u]SSPP is invalid\n", pipe);
ret = PTR_ERR(pdpu->pipe_hw);
goto clean_plane; goto clean_plane;
} else if (!pdpu->pipe_hw->cap || !pdpu->pipe_hw->cap->sblk) {
DPU_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
goto clean_sspp;
} }
format_list = pdpu->pipe_hw->cap->sblk->format_list; format_list = pipe_hw->cap->sblk->format_list;
num_formats = pdpu->pipe_hw->cap->sblk->num_formats; num_formats = pipe_hw->cap->sblk->num_formats;
ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
format_list, num_formats, format_list, num_formats,
supported_format_modifiers, type, NULL); supported_format_modifiers, type, NULL);
if (ret) if (ret)
goto clean_sspp; goto clean_plane;
pdpu->catalog = kms->catalog; pdpu->catalog = kms->catalog;
...@@ -1515,7 +1509,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, ...@@ -1515,7 +1509,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
if (pdpu->pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION)) if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION))
supported_rotations |= DRM_MODE_ROTATE_MASK; supported_rotations |= DRM_MODE_ROTATE_MASK;
drm_plane_create_rotation_property(plane, drm_plane_create_rotation_property(plane,
...@@ -1532,9 +1526,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, ...@@ -1532,9 +1526,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
pipe, plane->base.id); pipe, plane->base.id);
return plane; return plane;
clean_sspp:
if (pdpu && pdpu->pipe_hw)
dpu_hw_sspp_destroy(pdpu->pipe_hw);
clean_plane: clean_plane:
kfree(pdpu); kfree(pdpu);
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
* struct dpu_plane_state: Define dpu extension of drm plane state object * struct dpu_plane_state: Define dpu extension of drm plane state object
* @base: base drm plane state object * @base: base drm plane state object
* @aspace: pointer to address space for input/output buffers * @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 * @stage: assigned by crtc blender
* @needs_qos_remap: qos remap settings need to be updated * @needs_qos_remap: qos remap settings need to be updated
* @multirect_index: index of the rectangle of SSPP * @multirect_index: index of the rectangle of SSPP
...@@ -31,10 +35,12 @@ ...@@ -31,10 +35,12 @@
struct dpu_plane_state { struct dpu_plane_state {
struct drm_plane_state base; struct drm_plane_state base;
struct msm_gem_address_space *aspace; 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; enum dpu_stage stage;
bool needs_qos_remap; bool needs_qos_remap;
uint32_t multirect_index;
uint32_t multirect_mode;
bool pending; bool pending;
u64 plane_fetch_bw; u64 plane_fetch_bw;
...@@ -44,26 +50,9 @@ struct dpu_plane_state { ...@@ -44,26 +50,9 @@ struct dpu_plane_state {
unsigned int rotation; 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) \ #define to_dpu_plane_state(x) \
container_of(x, struct dpu_plane_state, base) 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 * dpu_plane_flush - final plane operations before commit flush
* @plane: Pointer to drm plane structure * @plane: Pointer to drm plane structure
...@@ -88,19 +77,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, ...@@ -88,19 +77,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t pipe, enum drm_plane_type type, uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs); 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 * dpu_plane_color_fill - enables color fill on plane
* @plane: Pointer to DRM plane object * @plane: Pointer to DRM plane object
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "dpu_hw_lm.h" #include "dpu_hw_lm.h"
#include "dpu_hw_ctl.h" #include "dpu_hw_ctl.h"
#include "dpu_hw_pingpong.h" #include "dpu_hw_pingpong.h"
#include "dpu_hw_sspp.h"
#include "dpu_hw_intf.h" #include "dpu_hw_intf.h"
#include "dpu_hw_wb.h" #include "dpu_hw_wb.h"
#include "dpu_hw_dspp.h" #include "dpu_hw_dspp.h"
...@@ -91,6 +92,9 @@ int dpu_rm_destroy(struct dpu_rm *rm) ...@@ -91,6 +92,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++) for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
dpu_hw_wb_destroy(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; return 0;
} }
...@@ -255,6 +259,24 @@ int dpu_rm_init(struct dpu_rm *rm, ...@@ -255,6 +259,24 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dsc_blks[dsc->id - DSC_0] = &hw->base; 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; return 0;
fail: fail:
......
...@@ -21,6 +21,7 @@ struct dpu_global_state; ...@@ -21,6 +21,7 @@ struct dpu_global_state;
* @hw_intf: array of intf hardware resources * @hw_intf: array of intf hardware resources
* @hw_wb: array of wb hardware resources * @hw_wb: array of wb hardware resources
* @dspp_blks: array of dspp hardware resources * @dspp_blks: array of dspp hardware resources
* @hw_sspp: array of sspp hardware resources
*/ */
struct dpu_rm { struct dpu_rm {
struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0]; struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
...@@ -31,6 +32,7 @@ struct dpu_rm { ...@@ -31,6 +32,7 @@ struct dpu_rm {
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; 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 *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_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_ ...@@ -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]; 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__ */ #endif /* __DPU_RM_H__ */
...@@ -633,9 +633,9 @@ TRACE_EVENT(dpu_enc_phys_vid_irq_ctrl, ...@@ -633,9 +633,9 @@ TRACE_EVENT(dpu_enc_phys_vid_irq_ctrl,
TRACE_EVENT(dpu_crtc_setup_mixer, TRACE_EVENT(dpu_crtc_setup_mixer,
TP_PROTO(uint32_t crtc_id, uint32_t plane_id, TP_PROTO(uint32_t crtc_id, uint32_t plane_id,
struct drm_plane_state *state, struct dpu_plane_state *pstate, 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), 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), pixel_format, modifier),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( uint32_t, crtc_id ) __field( uint32_t, crtc_id )
...@@ -659,9 +659,9 @@ TRACE_EVENT(dpu_crtc_setup_mixer, ...@@ -659,9 +659,9 @@ TRACE_EVENT(dpu_crtc_setup_mixer,
__entry->dst_rect = drm_plane_state_dest(state); __entry->dst_rect = drm_plane_state_dest(state);
__entry->stage_idx = stage_idx; __entry->stage_idx = stage_idx;
__entry->stage = pstate->stage; __entry->stage = pstate->stage;
__entry->sspp = sspp; __entry->sspp = pstate->pipe.sspp->idx;
__entry->multirect_idx = pstate->multirect_index; __entry->multirect_idx = pstate->pipe.multirect_index;
__entry->multirect_mode = pstate->multirect_mode; __entry->multirect_mode = pstate->pipe.multirect_mode;
__entry->pixel_format = pixel_format; __entry->pixel_format = pixel_format;
__entry->modifier = modifier; __entry->modifier = modifier;
), ),
...@@ -762,18 +762,17 @@ TRACE_EVENT(dpu_crtc_disable_frame_pending, ...@@ -762,18 +762,17 @@ TRACE_EVENT(dpu_crtc_disable_frame_pending,
); );
TRACE_EVENT(dpu_plane_set_scanout, TRACE_EVENT(dpu_plane_set_scanout,
TP_PROTO(enum dpu_sspp index, struct dpu_hw_fmt_layout *layout, TP_PROTO(struct dpu_sw_pipe *pipe, struct dpu_hw_fmt_layout *layout),
enum dpu_sspp_multirect_index multirect_index), TP_ARGS(pipe, layout),
TP_ARGS(index, layout, multirect_index),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( enum dpu_sspp, index ) __field( enum dpu_sspp, index )
__field_struct( struct dpu_hw_fmt_layout, layout ) __field_struct( struct dpu_hw_fmt_layout, layout )
__field( enum dpu_sspp_multirect_index, multirect_index) __field( enum dpu_sspp_multirect_index, multirect_index)
), ),
TP_fast_assign( TP_fast_assign(
__entry->index = index; __entry->index = pipe->sspp->idx;
__entry->layout = *layout; __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]} " TP_printk("index:%d layout:{%ux%u @ [%u/%u, %u/%u, %u/%u, %u/%u]} "
"multirect_index:%d", __entry->index, __entry->layout.width, "multirect_index:%d", __entry->index, __entry->layout.width,
......
...@@ -179,6 +179,24 @@ static unsigned get_crtc_mask(struct drm_atomic_state *state) ...@@ -179,6 +179,24 @@ static unsigned get_crtc_mask(struct drm_atomic_state *state)
return mask; 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) void msm_atomic_commit_tail(struct drm_atomic_state *state)
{ {
struct drm_device *dev = state->dev; struct drm_device *dev = state->dev;
......
...@@ -58,7 +58,7 @@ static void msm_deinit_vram(struct drm_device *ddev); ...@@ -58,7 +58,7 @@ static void msm_deinit_vram(struct drm_device *ddev);
static const struct drm_mode_config_funcs mode_config_funcs = { static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = msm_framebuffer_create, .fb_create = msm_framebuffer_create,
.atomic_check = drm_atomic_helper_check, .atomic_check = msm_atomic_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
......
...@@ -258,6 +258,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, ...@@ -258,6 +258,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer,
struct msm_kms *kms, int crtc_idx); struct msm_kms *kms, int crtc_idx);
void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer);
void msm_atomic_commit_tail(struct drm_atomic_state *state); 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); 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_clear(struct drm_atomic_state *state);
void msm_atomic_state_free(struct drm_atomic_state *state); void msm_atomic_state_free(struct drm_atomic_state *state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment