summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c')
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c121
1 files changed, 61 insertions, 60 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 9b62451b01ee..594e2d10b000 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -66,6 +66,8 @@ int dpu_rm_destroy(struct dpu_rm *rm)
}
}
+ mutex_destroy(&rm->rm_lock);
+
return 0;
}
@@ -83,6 +85,8 @@ int dpu_rm_init(struct dpu_rm *rm,
/* Clear, setup lists */
memset(rm, 0, sizeof(*rm));
+ mutex_init(&rm->rm_lock);
+
/* Interrogate HW catalog and create tracking items for hw blocks */
for (i = 0; i < cat->mixer_count; i++) {
struct dpu_hw_mixer *hw;
@@ -226,14 +230,13 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
* @Return: true if lm matches all requirements, false otherwise
*/
static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
- struct dpu_global_state *global_state,
uint32_t enc_id, int lm_idx, int *pp_idx)
{
const struct dpu_lm_cfg *lm_cfg;
int idx;
/* Already reserved? */
- if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
+ if (reserved_by_other(rm->mixer_to_enc_id, lm_idx, enc_id)) {
DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
return false;
}
@@ -245,7 +248,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
return false;
}
- if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
+ if (reserved_by_other(rm->pingpong_to_enc_id, idx, enc_id)) {
DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
lm_cfg->pingpong);
return false;
@@ -254,9 +257,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
return true;
}
-static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
- struct dpu_global_state *global_state,
- uint32_t enc_id,
+static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
struct dpu_rm_requirements *reqs)
{
@@ -278,8 +279,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
lm_count = 0;
lm_idx[lm_count] = i;
- if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
- enc_id, i, &pp_idx[lm_count])) {
+ if (!_dpu_rm_check_lm_and_get_connected_blks(
+ rm, enc_id, i, &pp_idx[lm_count])) {
continue;
}
@@ -297,9 +298,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
continue;
}
- if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
- global_state, enc_id, j,
- &pp_idx[lm_count])) {
+ if (!_dpu_rm_check_lm_and_get_connected_blks(
+ rm, enc_id, j, &pp_idx[lm_count])) {
continue;
}
@@ -314,8 +314,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
}
for (i = 0; i < lm_count; i++) {
- global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
- global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
+ rm->mixer_to_enc_id[lm_idx[i]] = enc_id;
+ rm->pingpong_to_enc_id[pp_idx[i]] = enc_id;
trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
pp_idx[i] + PINGPONG_0);
@@ -326,7 +326,6 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
static int _dpu_rm_reserve_ctls(
struct dpu_rm *rm,
- struct dpu_global_state *global_state,
uint32_t enc_id,
const struct msm_display_topology *top)
{
@@ -346,7 +345,7 @@ static int _dpu_rm_reserve_ctls(
if (!rm->ctl_blks[j])
continue;
- if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
+ if (reserved_by_other(rm->ctl_to_enc_id, j, enc_id))
continue;
ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
@@ -370,7 +369,7 @@ static int _dpu_rm_reserve_ctls(
return -ENAVAIL;
for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
- global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
+ rm->ctl_to_enc_id[ctl_idx[i]] = enc_id;
trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
}
@@ -379,34 +378,27 @@ static int _dpu_rm_reserve_ctls(
static int _dpu_rm_reserve_intf(
struct dpu_rm *rm,
- struct dpu_global_state *global_state,
uint32_t enc_id,
uint32_t id)
{
int idx = id - INTF_0;
- if (idx < 0 || idx >= ARRAY_SIZE(rm->intf_blks)) {
- DPU_ERROR("invalid intf id: %d", id);
- return -EINVAL;
- }
-
if (!rm->intf_blks[idx]) {
DPU_ERROR("couldn't find intf id %d\n", id);
return -EINVAL;
}
- if (reserved_by_other(global_state->intf_to_enc_id, idx, enc_id)) {
+ if (reserved_by_other(rm->intf_to_enc_id, idx, enc_id)) {
DPU_ERROR("intf id %d already reserved\n", id);
return -ENAVAIL;
}
- global_state->intf_to_enc_id[idx] = enc_id;
+ rm->intf_to_enc_id[idx] = enc_id;
return 0;
}
static int _dpu_rm_reserve_intf_related_hw(
struct dpu_rm *rm,
- struct dpu_global_state *global_state,
uint32_t enc_id,
struct dpu_encoder_hw_resources *hw_res)
{
@@ -417,7 +409,7 @@ static int _dpu_rm_reserve_intf_related_hw(
if (hw_res->intfs[i] == INTF_MODE_NONE)
continue;
id = i + INTF_0;
- ret = _dpu_rm_reserve_intf(rm, global_state, enc_id, id);
+ ret = _dpu_rm_reserve_intf(rm, enc_id, id);
if (ret)
return ret;
}
@@ -427,27 +419,24 @@ static int _dpu_rm_reserve_intf_related_hw(
static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
- struct dpu_global_state *global_state,
struct drm_encoder *enc,
struct dpu_rm_requirements *reqs)
{
int ret;
- ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
+ ret = _dpu_rm_reserve_lms(rm, enc->base.id, reqs);
if (ret) {
DPU_ERROR("unable to find appropriate mixers\n");
return ret;
}
- ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
- &reqs->topology);
+ ret = _dpu_rm_reserve_ctls(rm, enc->base.id, &reqs->topology);
if (ret) {
DPU_ERROR("unable to find appropriate CTL\n");
return ret;
}
- ret = _dpu_rm_reserve_intf_related_hw(rm, global_state, enc->base.id,
- &reqs->hw_res);
+ ret = _dpu_rm_reserve_intf_related_hw(rm, enc->base.id, &reqs->hw_res);
if (ret)
return ret;
@@ -481,25 +470,33 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
}
}
-void dpu_rm_release(struct dpu_global_state *global_state,
- struct drm_encoder *enc)
+static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id)
+{
+ _dpu_rm_clear_mapping(rm->pingpong_to_enc_id,
+ ARRAY_SIZE(rm->pingpong_to_enc_id), enc_id);
+ _dpu_rm_clear_mapping(rm->mixer_to_enc_id,
+ ARRAY_SIZE(rm->mixer_to_enc_id), enc_id);
+ _dpu_rm_clear_mapping(rm->ctl_to_enc_id,
+ ARRAY_SIZE(rm->ctl_to_enc_id), enc_id);
+ _dpu_rm_clear_mapping(rm->intf_to_enc_id,
+ ARRAY_SIZE(rm->intf_to_enc_id), enc_id);
+}
+
+void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
{
- _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
- ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
- ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
- ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->intf_to_enc_id,
- ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
+ mutex_lock(&rm->rm_lock);
+
+ _dpu_rm_release_reservation(rm, enc->base.id);
+
+ mutex_unlock(&rm->rm_lock);
}
int dpu_rm_reserve(
struct dpu_rm *rm,
- struct dpu_global_state *global_state,
struct drm_encoder *enc,
struct drm_crtc_state *crtc_state,
- struct msm_display_topology topology)
+ struct msm_display_topology topology,
+ bool test_only)
{
struct dpu_rm_requirements reqs;
int ret;
@@ -508,31 +505,35 @@ int dpu_rm_reserve(
if (!drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
- if (IS_ERR(global_state)) {
- DPU_ERROR("failed to global state\n");
- return PTR_ERR(global_state);
- }
+ DRM_DEBUG_KMS("reserving hw for enc %d crtc %d test_only %d\n",
+ enc->base.id, crtc_state->crtc->base.id, test_only);
- DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
- enc->base.id, crtc_state->crtc->base.id);
+ mutex_lock(&rm->rm_lock);
ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
if (ret) {
DPU_ERROR("failed to populate hw requirements\n");
- return ret;
+ goto end;
}
- ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
- if (ret)
+ ret = _dpu_rm_make_reservation(rm, enc, &reqs);
+ if (ret) {
DPU_ERROR("failed to reserve hw resources: %d\n", ret);
+ _dpu_rm_release_reservation(rm, enc->base.id);
+ } else if (test_only) {
+ /* test_only: test the reservation and then undo */
+ DPU_DEBUG("test_only: discard test [enc: %d]\n",
+ enc->base.id);
+ _dpu_rm_release_reservation(rm, enc->base.id);
+ }
-
+end:
+ mutex_unlock(&rm->rm_lock);
return ret;
}
-int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
- struct dpu_global_state *global_state, uint32_t enc_id,
+int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
{
struct dpu_hw_blk **hw_blks;
@@ -542,22 +543,22 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
switch (type) {
case DPU_HW_BLK_PINGPONG:
hw_blks = rm->pingpong_blks;
- hw_to_enc_id = global_state->pingpong_to_enc_id;
+ hw_to_enc_id = rm->pingpong_to_enc_id;
max_blks = ARRAY_SIZE(rm->pingpong_blks);
break;
case DPU_HW_BLK_LM:
hw_blks = rm->mixer_blks;
- hw_to_enc_id = global_state->mixer_to_enc_id;
+ hw_to_enc_id = rm->mixer_to_enc_id;
max_blks = ARRAY_SIZE(rm->mixer_blks);
break;
case DPU_HW_BLK_CTL:
hw_blks = rm->ctl_blks;
- hw_to_enc_id = global_state->ctl_to_enc_id;
+ hw_to_enc_id = rm->ctl_to_enc_id;
max_blks = ARRAY_SIZE(rm->ctl_blks);
break;
case DPU_HW_BLK_INTF:
hw_blks = rm->intf_blks;
- hw_to_enc_id = global_state->intf_to_enc_id;
+ hw_to_enc_id = rm->intf_to_enc_id;
max_blks = ARRAY_SIZE(rm->intf_blks);
break;
default: