|
@@ -42,9 +42,6 @@
|
|
#include "sde_trace.h"
|
|
#include "sde_trace.h"
|
|
#include "msm_drv.h"
|
|
#include "msm_drv.h"
|
|
|
|
|
|
-#define SDE_PSTATES_MAX (SDE_STAGE_MAX * 4)
|
|
|
|
-#define SDE_MULTIRECT_PLANE_MAX (SDE_STAGE_MAX * 2)
|
|
|
|
-
|
|
|
|
struct sde_crtc_custom_events {
|
|
struct sde_crtc_custom_events {
|
|
u32 event;
|
|
u32 event;
|
|
int (*func)(struct drm_crtc *crtc, bool en,
|
|
int (*func)(struct drm_crtc *crtc, bool en,
|
|
@@ -1257,13 +1254,6 @@ static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
|
|
sde_cp_crtc_res_change(crtc);
|
|
sde_cp_crtc_res_change(crtc);
|
|
}
|
|
}
|
|
|
|
|
|
-struct plane_state {
|
|
|
|
- struct sde_plane_state *sde_pstate;
|
|
|
|
- const struct drm_plane_state *drm_pstate;
|
|
|
|
- int stage;
|
|
|
|
- u32 pipe_id;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
static int pstate_cmp(const void *a, const void *b)
|
|
static int pstate_cmp(const void *a, const void *b)
|
|
{
|
|
{
|
|
struct plane_state *pa = (struct plane_state *)a;
|
|
struct plane_state *pa = (struct plane_state *)a;
|
|
@@ -1297,24 +1287,29 @@ static int pstate_cmp(const void *a, const void *b)
|
|
* we assume that all pipes are in source split so its valid to compare
|
|
* we assume that all pipes are in source split so its valid to compare
|
|
* without taking into account left/right mixer placement
|
|
* without taking into account left/right mixer placement
|
|
*/
|
|
*/
|
|
-static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc,
|
|
|
|
- struct plane_state *pstates, int cnt)
|
|
|
|
|
|
+static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc)
|
|
{
|
|
{
|
|
struct plane_state *prv_pstate, *cur_pstate;
|
|
struct plane_state *prv_pstate, *cur_pstate;
|
|
enum sde_layout prev_layout, cur_layout;
|
|
enum sde_layout prev_layout, cur_layout;
|
|
|
|
+ struct sde_crtc *sde_crtc;
|
|
struct sde_rect left_rect, right_rect;
|
|
struct sde_rect left_rect, right_rect;
|
|
struct sde_kms *sde_kms;
|
|
struct sde_kms *sde_kms;
|
|
|
|
+ struct plane_state *pstates;
|
|
int32_t left_pid, right_pid;
|
|
int32_t left_pid, right_pid;
|
|
int32_t stage;
|
|
int32_t stage;
|
|
int i, rc = 0;
|
|
int i, rc = 0;
|
|
|
|
|
|
|
|
+ sde_crtc = to_sde_crtc(crtc);
|
|
|
|
+
|
|
sde_kms = _sde_crtc_get_kms(crtc);
|
|
sde_kms = _sde_crtc_get_kms(crtc);
|
|
- if (!sde_kms || !sde_kms->catalog) {
|
|
|
|
|
|
+ if (!sde_kms || !sde_kms->catalog || !sde_crtc) {
|
|
SDE_ERROR("invalid parameters\n");
|
|
SDE_ERROR("invalid parameters\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 1; i < cnt; i++) {
|
|
|
|
|
|
+ pstates = sde_crtc->pstates;
|
|
|
|
+
|
|
|
|
+ for (i = 1; i < sde_crtc->num_pstates; i++) {
|
|
prv_pstate = &pstates[i - 1];
|
|
prv_pstate = &pstates[i - 1];
|
|
cur_pstate = &pstates[i];
|
|
cur_pstate = &pstates[i];
|
|
prev_layout = prv_pstate->sde_pstate->layout;
|
|
prev_layout = prv_pstate->sde_pstate->layout;
|
|
@@ -1492,7 +1487,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|
struct drm_plane_state *state;
|
|
struct drm_plane_state *state;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_plane_state *pstate = NULL;
|
|
struct sde_plane_state *pstate = NULL;
|
|
- struct plane_state *pstates = NULL;
|
|
|
|
|
|
+ struct plane_state *pstates;
|
|
struct sde_format *format;
|
|
struct sde_format *format;
|
|
struct sde_hw_ctl *ctl;
|
|
struct sde_hw_ctl *ctl;
|
|
struct sde_hw_mixer *lm;
|
|
struct sde_hw_mixer *lm;
|
|
@@ -1513,11 +1508,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|
ctl = mixer->hw_ctl;
|
|
ctl = mixer->hw_ctl;
|
|
lm = mixer->hw_lm;
|
|
lm = mixer->hw_lm;
|
|
cstate = to_sde_crtc_state(crtc->state);
|
|
cstate = to_sde_crtc_state(crtc->state);
|
|
- pstates = kcalloc(SDE_PSTATES_MAX,
|
|
|
|
- sizeof(struct plane_state), GFP_KERNEL);
|
|
|
|
- if (!pstates)
|
|
|
|
- return;
|
|
|
|
|
|
+ pstates = sde_crtc->pstates;
|
|
|
|
|
|
|
|
+ memset(sde_crtc->pstates, 0, sizeof(sde_crtc->pstates));
|
|
memset(fetch_active, 0, sizeof(fetch_active));
|
|
memset(fetch_active, 0, sizeof(fetch_active));
|
|
memset(zpos_cnt, 0, sizeof(zpos_cnt));
|
|
memset(zpos_cnt, 0, sizeof(zpos_cnt));
|
|
|
|
|
|
@@ -1550,7 +1543,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|
format = to_sde_format(msm_framebuffer_format(pstate->base.fb));
|
|
format = to_sde_format(msm_framebuffer_format(pstate->base.fb));
|
|
if (!format) {
|
|
if (!format) {
|
|
SDE_ERROR("invalid format\n");
|
|
SDE_ERROR("invalid format\n");
|
|
- goto end;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
blend_type = sde_plane_get_property(pstate,
|
|
blend_type = sde_plane_get_property(pstate,
|
|
@@ -1641,8 +1634,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-end:
|
|
|
|
- kfree(pstates);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void _sde_crtc_swap_mixers_for_right_partial_update(
|
|
static void _sde_crtc_swap_mixers_for_right_partial_update(
|
|
@@ -4523,12 +4514,19 @@ end:
|
|
}
|
|
}
|
|
|
|
|
|
static int _sde_crtc_check_secure_blend_config(struct drm_crtc *crtc,
|
|
static int _sde_crtc_check_secure_blend_config(struct drm_crtc *crtc,
|
|
- struct drm_crtc_state *state, struct plane_state pstates[],
|
|
|
|
- struct sde_crtc_state *cstate, struct sde_kms *sde_kms,
|
|
|
|
- int cnt, int secure, int fb_ns, int fb_sec, int fb_sec_dir)
|
|
|
|
|
|
+ struct drm_crtc_state *state, struct sde_crtc_state *cstate,
|
|
|
|
+ struct sde_kms *sde_kms, int secure, int fb_ns,
|
|
|
|
+ int fb_sec, int fb_sec_dir)
|
|
{
|
|
{
|
|
struct drm_plane *plane;
|
|
struct drm_plane *plane;
|
|
- int i;
|
|
|
|
|
|
+ int i, cnt;
|
|
|
|
+ struct plane_state *pstates;
|
|
|
|
+ struct sde_crtc *sde_crtc;
|
|
|
|
+
|
|
|
|
+ sde_crtc = to_sde_crtc(crtc);
|
|
|
|
+ cnt = sde_crtc->num_pstates;
|
|
|
|
+ pstates = sde_crtc->pstates;
|
|
|
|
+
|
|
if (secure == SDE_DRM_SEC_ONLY) {
|
|
if (secure == SDE_DRM_SEC_ONLY) {
|
|
/*
|
|
/*
|
|
* validate planes - only fb_sec_dir is allowed during sec_crtc
|
|
* validate planes - only fb_sec_dir is allowed during sec_crtc
|
|
@@ -4725,8 +4723,7 @@ static int _sde_crtc_check_secure_conn(struct drm_crtc *crtc,
|
|
}
|
|
}
|
|
|
|
|
|
static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
|
|
static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
|
|
- struct drm_crtc_state *state, struct plane_state pstates[],
|
|
|
|
- int cnt)
|
|
|
|
|
|
+ struct drm_crtc_state *state)
|
|
{
|
|
{
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_kms *sde_kms;
|
|
struct sde_kms *sde_kms;
|
|
@@ -4754,8 +4751,8 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
- rc = _sde_crtc_check_secure_blend_config(crtc, state, pstates, cstate,
|
|
|
|
- sde_kms, cnt, secure, fb_ns, fb_sec, fb_sec_dir);
|
|
|
|
|
|
+ rc = _sde_crtc_check_secure_blend_config(crtc, state, cstate,
|
|
|
|
+ sde_kms, secure, fb_ns, fb_sec, fb_sec_dir);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
@@ -4784,10 +4781,7 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
|
|
static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
|
|
static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
|
|
struct drm_crtc_state *state,
|
|
struct drm_crtc_state *state,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *mode,
|
|
- struct plane_state *pstates,
|
|
|
|
- struct drm_plane *plane,
|
|
|
|
- struct sde_multirect_plane_states *multirect_plane,
|
|
|
|
- int *cnt)
|
|
|
|
|
|
+ struct drm_plane *plane)
|
|
{
|
|
{
|
|
struct sde_crtc *sde_crtc;
|
|
struct sde_crtc *sde_crtc;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_crtc_state *cstate;
|
|
@@ -4796,6 +4790,9 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
|
|
int rc = 0, multirect_count = 0, i, mixer_width, mixer_height;
|
|
int rc = 0, multirect_count = 0, i, mixer_width, mixer_height;
|
|
int inc_sde_stage = 0;
|
|
int inc_sde_stage = 0;
|
|
struct sde_kms *kms;
|
|
struct sde_kms *kms;
|
|
|
|
+ int *cnt;
|
|
|
|
+ struct plane_state *pstates;
|
|
|
|
+ struct sde_multirect_plane_states *multirect_plane;
|
|
|
|
|
|
sde_crtc = to_sde_crtc(crtc);
|
|
sde_crtc = to_sde_crtc(crtc);
|
|
cstate = to_sde_crtc_state(state);
|
|
cstate = to_sde_crtc_state(state);
|
|
@@ -4806,6 +4803,13 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ cnt = &sde_crtc->num_pstates;
|
|
|
|
+ pstates = sde_crtc->pstates;
|
|
|
|
+ multirect_plane = sde_crtc->multirect;
|
|
|
|
+
|
|
|
|
+ *cnt = 0;
|
|
|
|
+ memset(sde_crtc->pstates, 0, sizeof(sde_crtc->pstates));
|
|
|
|
+ memset(sde_crtc->multirect, 0, sizeof(sde_crtc->multirect));
|
|
memset(pipe_staged, 0, sizeof(pipe_staged));
|
|
memset(pipe_staged, 0, sizeof(pipe_staged));
|
|
|
|
|
|
mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, mode);
|
|
mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, mode);
|
|
@@ -4911,16 +4915,16 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
|
|
|
|
|
|
static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|
static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|
struct sde_crtc *sde_crtc,
|
|
struct sde_crtc *sde_crtc,
|
|
- struct plane_state *pstates,
|
|
|
|
struct sde_crtc_state *cstate,
|
|
struct sde_crtc_state *cstate,
|
|
- struct drm_display_mode *mode,
|
|
|
|
- int cnt)
|
|
|
|
|
|
+ struct drm_display_mode *mode)
|
|
{
|
|
{
|
|
int rc = 0, i, z_pos;
|
|
int rc = 0, i, z_pos;
|
|
u32 zpos_cnt = 0;
|
|
u32 zpos_cnt = 0;
|
|
struct drm_crtc *crtc;
|
|
struct drm_crtc *crtc;
|
|
struct sde_kms *kms;
|
|
struct sde_kms *kms;
|
|
enum sde_layout layout;
|
|
enum sde_layout layout;
|
|
|
|
+ int cnt;
|
|
|
|
+ struct plane_state *pstates;
|
|
|
|
|
|
crtc = &sde_crtc->base;
|
|
crtc = &sde_crtc->base;
|
|
kms = _sde_crtc_get_kms(crtc);
|
|
kms = _sde_crtc_get_kms(crtc);
|
|
@@ -4930,6 +4934,9 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ pstates = sde_crtc->pstates;
|
|
|
|
+ cnt = sde_crtc->num_pstates;
|
|
|
|
+
|
|
sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
|
|
sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
|
|
|
|
|
|
rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt);
|
|
rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt);
|
|
@@ -4983,16 +4990,14 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
|
|
}
|
|
}
|
|
|
|
|
|
static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc,
|
|
static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc,
|
|
- struct drm_crtc_state *state,
|
|
|
|
- struct plane_state *pstates,
|
|
|
|
- struct sde_multirect_plane_states *multirect_plane)
|
|
|
|
|
|
+ struct drm_crtc_state *state)
|
|
{
|
|
{
|
|
struct sde_crtc *sde_crtc;
|
|
struct sde_crtc *sde_crtc;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_kms *kms;
|
|
struct sde_kms *kms;
|
|
struct drm_plane *plane = NULL;
|
|
struct drm_plane *plane = NULL;
|
|
struct drm_display_mode *mode;
|
|
struct drm_display_mode *mode;
|
|
- int rc = 0, cnt = 0;
|
|
|
|
|
|
+ int rc = 0;
|
|
|
|
|
|
kms = _sde_crtc_get_kms(crtc);
|
|
kms = _sde_crtc_get_kms(crtc);
|
|
|
|
|
|
@@ -5004,19 +5009,19 @@ static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc,
|
|
sde_crtc = to_sde_crtc(crtc);
|
|
sde_crtc = to_sde_crtc(crtc);
|
|
cstate = to_sde_crtc_state(state);
|
|
cstate = to_sde_crtc_state(state);
|
|
mode = &state->adjusted_mode;
|
|
mode = &state->adjusted_mode;
|
|
|
|
+ sde_crtc->num_pstates = 0;
|
|
|
|
|
|
/* get plane state for all drm planes associated with crtc state */
|
|
/* get plane state for all drm planes associated with crtc state */
|
|
- rc = _sde_crtc_check_get_pstates(crtc, state, mode, pstates,
|
|
|
|
- plane, multirect_plane, &cnt);
|
|
|
|
|
|
+ rc = _sde_crtc_check_get_pstates(crtc, state, mode, plane);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
/* assign mixer stages based on sorted zpos property */
|
|
/* assign mixer stages based on sorted zpos property */
|
|
- rc = _sde_crtc_check_zpos(state, sde_crtc, pstates, cstate, mode, cnt);
|
|
|
|
|
|
+ rc = _sde_crtc_check_zpos(state, sde_crtc, cstate, mode);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
- rc = _sde_crtc_check_secure_state(crtc, state, pstates, cnt);
|
|
|
|
|
|
+ rc = _sde_crtc_check_secure_state(crtc, state);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
@@ -5026,7 +5031,7 @@ static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc,
|
|
* we assume that all pipes are in source split so its valid to compare
|
|
* we assume that all pipes are in source split so its valid to compare
|
|
* without taking into account left/right mixer placement
|
|
* without taking into account left/right mixer placement
|
|
*/
|
|
*/
|
|
- rc = _sde_crtc_validate_src_split_order(crtc, pstates, cnt);
|
|
|
|
|
|
+ rc = _sde_crtc_validate_src_split_order(crtc);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
@@ -5094,11 +5099,9 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
|
{
|
|
{
|
|
struct drm_device *dev;
|
|
struct drm_device *dev;
|
|
struct sde_crtc *sde_crtc;
|
|
struct sde_crtc *sde_crtc;
|
|
- struct plane_state *pstates = NULL;
|
|
|
|
struct sde_crtc_state *cstate;
|
|
struct sde_crtc_state *cstate;
|
|
struct drm_display_mode *mode;
|
|
struct drm_display_mode *mode;
|
|
int rc = 0;
|
|
int rc = 0;
|
|
- struct sde_multirect_plane_states *multirect_plane = NULL;
|
|
|
|
struct drm_connector *conn;
|
|
struct drm_connector *conn;
|
|
struct drm_connector_list_iter conn_iter;
|
|
struct drm_connector_list_iter conn_iter;
|
|
|
|
|
|
@@ -5117,18 +5120,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
|
goto end;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
|
|
- pstates = kcalloc(SDE_PSTATES_MAX,
|
|
|
|
- sizeof(struct plane_state), GFP_KERNEL);
|
|
|
|
-
|
|
|
|
- multirect_plane = kcalloc(SDE_MULTIRECT_PLANE_MAX,
|
|
|
|
- sizeof(struct sde_multirect_plane_states),
|
|
|
|
- GFP_KERNEL);
|
|
|
|
-
|
|
|
|
- if (!pstates || !multirect_plane) {
|
|
|
|
- rc = -ENOMEM;
|
|
|
|
- goto end;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
mode = &state->adjusted_mode;
|
|
mode = &state->adjusted_mode;
|
|
SDE_DEBUG("%s: check", sde_crtc->name);
|
|
SDE_DEBUG("%s: check", sde_crtc->name);
|
|
|
|
|
|
@@ -5164,8 +5155,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
|
_sde_crtc_setup_is_ppsplit(state);
|
|
_sde_crtc_setup_is_ppsplit(state);
|
|
_sde_crtc_setup_lm_bounds(crtc, state);
|
|
_sde_crtc_setup_lm_bounds(crtc, state);
|
|
|
|
|
|
- rc = _sde_crtc_atomic_check_pstates(crtc, state, pstates,
|
|
|
|
- multirect_plane);
|
|
|
|
|
|
+ rc = _sde_crtc_atomic_check_pstates(crtc, state);
|
|
if (rc) {
|
|
if (rc) {
|
|
SDE_ERROR("crtc%d failed pstate check %d\n", crtc->base.id, rc);
|
|
SDE_ERROR("crtc%d failed pstate check %d\n", crtc->base.id, rc);
|
|
goto end;
|
|
goto end;
|
|
@@ -5191,8 +5181,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
|
|
goto end;
|
|
goto end;
|
|
}
|
|
}
|
|
end:
|
|
end:
|
|
- kfree(pstates);
|
|
|
|
- kfree(multirect_plane);
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|