// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
/** * _dpu_rm_get_lm_peer - get the id of a mixer which is a peer of the primary * @rm: dpu resource manager handle * @primary_idx: index of primary mixer in rm->mixer_blks[] * * Returns: lm peer mixed id on success or %-EINVAL on error
*/ staticint _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
{ conststruct dpu_lm_cfg *prim_lm_cfg;
staticint _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm, struct dpu_global_state *global_state,
uint32_t crtc_id, struct msm_display_topology *topology)
{ int num_cwb_mux = topology->num_lm, cwb_mux_count = 0; int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0; int cwb_pp_idx[MAX_BLOCKS]; int cwb_mux_idx[MAX_BLOCKS];
/* * Reserve additional dedicated CWB PINGPONG blocks and muxes for each * mixer * * TODO: add support reserving resources for platforms with no * PINGPONG_CWB
*/ for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
cwb_mux_count < num_cwb_mux; i++) { for (int j = 0; j < ARRAY_SIZE(rm->cwb_blks); j++) { /* * Odd LMs must be assigned to odd CWB muxes and even * LMs with even CWB muxes. * * Since the RM HW block array index is based on the HW * block ids, we can also use the array index to enforce * the odd/even rule. See dpu_rm_init() for more * information
*/ if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) ||
i % 2 != j % 2) continue;
if (cwb_mux_count != num_cwb_mux) {
DPU_ERROR("Unable to reserve all CWB PINGPONGs\n"); return -ENAVAIL;
}
for (int i = 0; i < cwb_mux_count; i++) {
global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
}
return 0;
}
/** * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets * proposed use case requirements, incl. hardwired dependent blocks like * pingpong * @rm: dpu resource manager handle * @global_state: resources shared across multiple kms objects * @crtc_id: crtc id requesting for allocation * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks * if lm, and all other hardwired blocks connected to the lm (pp) is * available and appropriate * @pp_idx: output parameter, index of pingpong block attached to the layer * mixer in rm->pingpong_blks[]. * @dspp_idx: output parameter, index of dspp block attached to the layer * mixer in rm->dspp_blks[]. * @topology: selected topology for the display * Return: true if lm matches all requirements, false otherwise
*/ staticbool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, struct dpu_global_state *global_state,
uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx, struct msm_display_topology *topology)
{ conststruct dpu_lm_cfg *lm_cfg; int idx;
for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
}
return 0;
}
staticint _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state, int start,
uint32_t crtc_id)
{ int i;
for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) { if (global_state->pingpong_to_crtc_id[i] == crtc_id) return i;
}
return -ENAVAIL;
}
staticint _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
{ /* * DSC with even index must be used with the PINGPONG with even index * DSC with odd index must be used with the PINGPONG with odd index
*/ if ((dsc_idx & 0x01) != (pp_idx & 0x01)) return -ENAVAIL;
return 0;
}
staticint _dpu_rm_dsc_alloc(struct dpu_rm *rm, struct dpu_global_state *global_state,
uint32_t crtc_id, conststruct msm_display_topology *top)
{ int num_dsc = 0; int pp_idx = 0; int dsc_idx; int ret;
for (dsc_idx = 0; dsc_idx < ARRAY_SIZE(rm->dsc_blks) &&
num_dsc < top->num_dsc; dsc_idx++) { if (!rm->dsc_blks[dsc_idx]) continue;
if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id)) continue;
staticint _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, struct dpu_global_state *global_state,
uint32_t crtc_id, conststruct msm_display_topology *top)
{ int num_dsc = 0; int dsc_idx, pp_idx = 0; int ret;
/* only start from even dsc index */ for (dsc_idx = 0; dsc_idx < ARRAY_SIZE(rm->dsc_blks) &&
num_dsc < top->num_dsc; dsc_idx += 2) { if (!rm->dsc_blks[dsc_idx] ||
!rm->dsc_blks[dsc_idx + 1]) continue;
/* consective dsc index to be paired */ if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id)) continue;
/** * dpu_rm_reserve - Given a CRTC->Encoder->Connector display chain, analyze * the use connections and user requirements, specified through related * topology control properties, and reserve hardware blocks to that * display chain. * HW blocks can then be accessed through dpu_rm_get_* functions. * HW Reservations should be released via dpu_rm_release_hw. * @rm: DPU Resource Manager handle * @global_state: resources shared across multiple kms objects * @crtc: DRM CRTC handle * @topology: Pointer to topology info for the display * @return: 0 on Success otherwise -ERROR
*/ int dpu_rm_reserve( struct dpu_rm *rm, struct dpu_global_state *global_state, struct drm_crtc *crtc, struct msm_display_topology *topology)
{ int ret;
if (IS_ERR(global_state)) {
DPU_ERROR("failed to global state\n"); return PTR_ERR(global_state);
}
DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
/** * dpu_rm_get_assigned_resources - Get hw resources of the given type that are * assigned to this encoder * @rm: DPU Resource Manager handle * @global_state: resources shared across multiple kms objects * @crtc: DRM CRTC handle * @type: resource type to return data for * @blks: pointer to the array to be filled by HW resources * @blks_size: size of the @blks array
*/ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, struct dpu_global_state *global_state, struct drm_crtc *crtc, enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
{
uint32_t crtc_id = crtc->base.id; struct dpu_hw_blk **hw_blks;
uint32_t *hw_to_crtc_id; int i, num_blks, max_blks;
switch (type) { case DPU_HW_BLK_PINGPONG: case DPU_HW_BLK_DCWB_PINGPONG:
hw_blks = rm->pingpong_blks;
hw_to_crtc_id = global_state->pingpong_to_crtc_id;
max_blks = ARRAY_SIZE(rm->pingpong_blks); break; case DPU_HW_BLK_LM:
hw_blks = rm->mixer_blks;
hw_to_crtc_id = global_state->mixer_to_crtc_id;
max_blks = ARRAY_SIZE(rm->mixer_blks); break; case DPU_HW_BLK_CTL:
hw_blks = rm->ctl_blks;
hw_to_crtc_id = global_state->ctl_to_crtc_id;
max_blks = ARRAY_SIZE(rm->ctl_blks); break; case DPU_HW_BLK_DSPP:
hw_blks = rm->dspp_blks;
hw_to_crtc_id = global_state->dspp_to_crtc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks); break; case DPU_HW_BLK_DSC:
hw_blks = rm->dsc_blks;
hw_to_crtc_id = global_state->dsc_to_crtc_id;
max_blks = ARRAY_SIZE(rm->dsc_blks); break; case DPU_HW_BLK_CDM:
hw_blks = &rm->cdm_blk;
hw_to_crtc_id = &global_state->cdm_to_crtc_id;
max_blks = 1; break; case DPU_HW_BLK_CWB:
hw_blks = rm->cwb_blks;
hw_to_crtc_id = global_state->cwb_to_crtc_id;
max_blks = ARRAY_SIZE(rm->cwb_blks); break; default:
DPU_ERROR("blk type %d not managed by rm\n", type); return 0;
}
num_blks = 0; for (i = 0; i < max_blks; i++) { if (hw_to_crtc_id[i] != crtc_id) continue;
if (type == DPU_HW_BLK_PINGPONG) { struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
if (pp->idx >= PINGPONG_CWB_0) continue;
}
if (type == DPU_HW_BLK_DCWB_PINGPONG) { struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
if (pp->idx < PINGPONG_CWB_0) continue;
}
if (num_blks == blks_size) {
DPU_ERROR("More than %d resources assigned to crtc %d\n",
blks_size, crtc_id); break;
} if (!hw_blks[i]) {
DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
type, crtc_id); break;
}
blks[num_blks++] = hw_blks[i];
}
/** * dpu_rm_print_state - output the RM private state * @p: DRM printer * @global_state: global state
*/ void dpu_rm_print_state(struct drm_printer *p, conststruct dpu_global_state *global_state)
{ conststruct dpu_rm *rm = global_state->rm; int i;
drm_puts(p, "resource mapping:\n");
drm_puts(p, "\tpingpong="); for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
global_state->pingpong_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tmixer="); for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->mixer_blks[i],
global_state->mixer_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tctl="); for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->ctl_blks[i],
global_state->ctl_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tdspp="); for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->dspp_blks[i],
global_state->dspp_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tdsc="); for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->dsc_blks[i],
global_state->dsc_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tsspp="); /* skip SSPP_NONE and start from the next index */ for (i = SSPP_NONE + 1; i < ARRAY_SIZE(global_state->sspp_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->hw_sspp[i] ? &rm->hw_sspp[i]->base : NULL,
global_state->sspp_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tcwb="); for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->cwb_blks[i],
global_state->cwb_to_crtc_id[i]);
drm_puts(p, "\n");
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.