mirror of https://gitee.com/openkylin/linux.git
Three fixes for vc4 that addresses dual-display breakages
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCX3bOIAAKCRDj7w1vZxhR xVzcAPwNXvrMIukXSJsyHH/Vu00avUrwh/dgaNV2nMU3bqmWDAEAhNsdZPmdSva+ 6rfry1bBUI4nTLgo7ac9PbCHyflw/QQ= =zfJ7 -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-fixes-2020-10-02' of git://anongit.freedesktop.org/drm/drm-misc into drm-next Three fixes for vc4 that addresses dual-display breakages Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20201002065243.ry7gp4or3ywhluer@gilmour.lan
This commit is contained in:
commit
083320ebe6
|
@ -852,11 +852,19 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc,
|
||||||
|
|
||||||
void vc4_crtc_reset(struct drm_crtc *crtc)
|
void vc4_crtc_reset(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
|
struct vc4_crtc_state *vc4_crtc_state;
|
||||||
|
|
||||||
if (crtc->state)
|
if (crtc->state)
|
||||||
vc4_crtc_destroy_state(crtc, crtc->state);
|
vc4_crtc_destroy_state(crtc, crtc->state);
|
||||||
crtc->state = kzalloc(sizeof(struct vc4_crtc_state), GFP_KERNEL);
|
|
||||||
if (crtc->state)
|
vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL);
|
||||||
__drm_atomic_helper_crtc_reset(crtc, crtc->state);
|
if (!vc4_crtc_state) {
|
||||||
|
crtc->state = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
|
||||||
|
__drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_crtc_funcs vc4_crtc_funcs = {
|
static const struct drm_crtc_funcs vc4_crtc_funcs = {
|
||||||
|
|
|
@ -532,6 +532,8 @@ struct vc4_crtc_state {
|
||||||
} margins;
|
} margins;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1)
|
||||||
|
|
||||||
static inline struct vc4_crtc_state *
|
static inline struct vc4_crtc_state *
|
||||||
to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
|
to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -616,7 +616,7 @@ static int
|
||||||
vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
|
vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
|
||||||
{
|
{
|
||||||
unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
|
unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
@ -629,6 +629,8 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
|
||||||
* modified.
|
* modified.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
|
struct drm_crtc_state *crtc_state;
|
||||||
|
|
||||||
if (!crtc->state->enable)
|
if (!crtc->state->enable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -637,15 +639,23 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
|
||||||
return PTR_ERR(crtc_state);
|
return PTR_ERR(crtc_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
|
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||||
struct vc4_crtc_state *vc4_crtc_state =
|
struct vc4_crtc_state *new_vc4_crtc_state =
|
||||||
to_vc4_crtc_state(crtc_state);
|
to_vc4_crtc_state(new_crtc_state);
|
||||||
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
||||||
unsigned int matching_channels;
|
unsigned int matching_channels;
|
||||||
|
|
||||||
if (!crtc_state->active)
|
if (old_crtc_state->enable && !new_crtc_state->enable)
|
||||||
|
new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
|
||||||
|
|
||||||
|
if (!new_crtc_state->enable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) {
|
||||||
|
unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The problem we have to solve here is that we have
|
* The problem we have to solve here is that we have
|
||||||
* up to 7 encoders, connected to up to 6 CRTCs.
|
* up to 7 encoders, connected to up to 6 CRTCs.
|
||||||
|
@ -674,7 +684,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
|
||||||
if (matching_channels) {
|
if (matching_channels) {
|
||||||
unsigned int channel = ffs(matching_channels) - 1;
|
unsigned int channel = ffs(matching_channels) - 1;
|
||||||
|
|
||||||
vc4_crtc_state->assigned_channel = channel;
|
new_vc4_crtc_state->assigned_channel = channel;
|
||||||
unassigned_channels &= ~BIT(channel);
|
unassigned_channels &= ~BIT(channel);
|
||||||
} else {
|
} else {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Reference in New Issue