Commit 1f192b9e authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2022-06-09' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

two fixes for panel self-refresh handling, and one to fix
multiple output support on AST.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20220609100754.kvrkjy67gqabjuee@houat
parents 88bfb6db 477277c7
...@@ -160,13 +160,12 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) ...@@ -160,13 +160,12 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower)
} }
if (bDPExecute) if (bDPExecute)
ast->tx_chip_type = AST_TX_ASTDP; ast->tx_chip_types |= BIT(AST_TX_ASTDP);
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
ASTDP_HOST_EDID_READ_DONE); ASTDP_HOST_EDID_READ_DONE);
} else }
ast->tx_chip_type = AST_TX_NONE;
} }
......
...@@ -450,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev) ...@@ -450,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev)
ast_init_dvo(dev); ast_init_dvo(dev);
break; break;
default: default:
if (ast->tx_chip_type == AST_TX_SIL164) if (ast->tx_chip_types & BIT(AST_TX_SIL164))
ast_init_dvo(dev); ast_init_dvo(dev);
else else
ast_init_analog(dev); ast_init_analog(dev);
......
...@@ -73,6 +73,11 @@ enum ast_tx_chip { ...@@ -73,6 +73,11 @@ enum ast_tx_chip {
AST_TX_ASTDP, AST_TX_ASTDP,
}; };
#define AST_TX_NONE_BIT BIT(AST_TX_NONE)
#define AST_TX_SIL164_BIT BIT(AST_TX_SIL164)
#define AST_TX_DP501_BIT BIT(AST_TX_DP501)
#define AST_TX_ASTDP_BIT BIT(AST_TX_ASTDP)
#define AST_DRAM_512Mx16 0 #define AST_DRAM_512Mx16 0
#define AST_DRAM_1Gx16 1 #define AST_DRAM_1Gx16 1
#define AST_DRAM_512Mx32 2 #define AST_DRAM_512Mx32 2
...@@ -173,7 +178,7 @@ struct ast_private { ...@@ -173,7 +178,7 @@ struct ast_private {
struct drm_plane primary_plane; struct drm_plane primary_plane;
struct ast_cursor_plane cursor_plane; struct ast_cursor_plane cursor_plane;
struct drm_crtc crtc; struct drm_crtc crtc;
union { struct {
struct { struct {
struct drm_encoder encoder; struct drm_encoder encoder;
struct ast_vga_connector vga_connector; struct ast_vga_connector vga_connector;
...@@ -199,7 +204,7 @@ struct ast_private { ...@@ -199,7 +204,7 @@ struct ast_private {
ast_use_defaults ast_use_defaults
} config_mode; } config_mode;
enum ast_tx_chip tx_chip_type; unsigned long tx_chip_types; /* bitfield of enum ast_chip_type */
u8 *dp501_fw_addr; u8 *dp501_fw_addr;
const struct firmware *dp501_fw; /* dp501 fw */ const struct firmware *dp501_fw; /* dp501 fw */
}; };
......
...@@ -216,7 +216,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ...@@ -216,7 +216,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
} }
/* Check 3rd Tx option (digital output afaik) */ /* Check 3rd Tx option (digital output afaik) */
ast->tx_chip_type = AST_TX_NONE; ast->tx_chip_types |= AST_TX_NONE_BIT;
/* /*
* VGACRA3 Enhanced Color Mode Register, check if DVO is already * VGACRA3 Enhanced Color Mode Register, check if DVO is already
...@@ -229,7 +229,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ...@@ -229,7 +229,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
if (!*need_post) { if (!*need_post) {
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff); jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff);
if (jreg & 0x80) if (jreg & 0x80)
ast->tx_chip_type = AST_TX_SIL164; ast->tx_chip_types = AST_TX_SIL164_BIT;
} }
if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) { if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
...@@ -241,7 +241,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ...@@ -241,7 +241,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
switch (jreg) { switch (jreg) {
case 0x04: case 0x04:
ast->tx_chip_type = AST_TX_SIL164; ast->tx_chip_types = AST_TX_SIL164_BIT;
break; break;
case 0x08: case 0x08:
ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);
...@@ -254,22 +254,19 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ...@@ -254,22 +254,19 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
} }
fallthrough; fallthrough;
case 0x0c: case 0x0c:
ast->tx_chip_type = AST_TX_DP501; ast->tx_chip_types = AST_TX_DP501_BIT;
} }
} else if (ast->chip == AST2600) } else if (ast->chip == AST2600)
ast_dp_launch(&ast->base, 0); ast_dp_launch(&ast->base, 0);
/* Print stuff for diagnostic purposes */ /* Print stuff for diagnostic purposes */
switch(ast->tx_chip_type) { if (ast->tx_chip_types & AST_TX_NONE_BIT)
case AST_TX_SIL164: drm_info(dev, "Using analog VGA\n");
if (ast->tx_chip_types & AST_TX_SIL164_BIT)
drm_info(dev, "Using Sil164 TMDS transmitter\n"); drm_info(dev, "Using Sil164 TMDS transmitter\n");
break; if (ast->tx_chip_types & AST_TX_DP501_BIT)
case AST_TX_DP501:
drm_info(dev, "Using DP501 DisplayPort transmitter\n"); drm_info(dev, "Using DP501 DisplayPort transmitter\n");
break;
default:
drm_info(dev, "Analog VGA only\n");
}
return 0; return 0;
} }
......
...@@ -997,10 +997,10 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -997,10 +997,10 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0); ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0);
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
if (ast->tx_chip_type == AST_TX_DP501) if (ast->tx_chip_types & AST_TX_DP501_BIT)
ast_set_dp501_video_output(crtc->dev, 1); ast_set_dp501_video_output(crtc->dev, 1);
if (ast->tx_chip_type == AST_TX_ASTDP) { if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON); ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
ast_wait_for_vretrace(ast); ast_wait_for_vretrace(ast);
ast_dp_set_on_off(crtc->dev, 1); ast_dp_set_on_off(crtc->dev, 1);
...@@ -1012,17 +1012,17 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -1012,17 +1012,17 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
ch = mode; ch = mode;
if (ast->tx_chip_type == AST_TX_DP501) if (ast->tx_chip_types & AST_TX_DP501_BIT)
ast_set_dp501_video_output(crtc->dev, 0); ast_set_dp501_video_output(crtc->dev, 0);
break;
if (ast->tx_chip_type == AST_TX_ASTDP) { if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ast_dp_set_on_off(crtc->dev, 0); ast_dp_set_on_off(crtc->dev, 0);
ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF); ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
} }
ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0x20); ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0x20);
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
break;
} }
} }
...@@ -1155,7 +1155,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, ...@@ -1155,7 +1155,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
ast_crtc_load_lut(ast, crtc); ast_crtc_load_lut(ast, crtc);
//Set Aspeed Display-Port //Set Aspeed Display-Port
if (ast->tx_chip_type == AST_TX_ASTDP) if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
ast_dp_set_mode(crtc, vbios_mode_info); ast_dp_set_mode(crtc, vbios_mode_info);
mutex_unlock(&ast->ioregs_lock); mutex_unlock(&ast->ioregs_lock);
...@@ -1739,22 +1739,26 @@ int ast_mode_config_init(struct ast_private *ast) ...@@ -1739,22 +1739,26 @@ int ast_mode_config_init(struct ast_private *ast)
ast_crtc_init(dev); ast_crtc_init(dev);
switch (ast->tx_chip_type) { if (ast->tx_chip_types & AST_TX_NONE_BIT) {
case AST_TX_NONE:
ret = ast_vga_output_init(ast); ret = ast_vga_output_init(ast);
break; if (ret)
case AST_TX_SIL164: return ret;
}
if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
ret = ast_sil164_output_init(ast); ret = ast_sil164_output_init(ast);
break; if (ret)
case AST_TX_DP501: return ret;
}
if (ast->tx_chip_types & AST_TX_DP501_BIT) {
ret = ast_dp501_output_init(ast); ret = ast_dp501_output_init(ast);
break; if (ret)
case AST_TX_ASTDP: return ret;
}
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ret = ast_astdp_output_init(ast); ret = ast_astdp_output_init(ast);
break; if (ret)
return ret;
} }
if (ret)
return ret;
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
......
...@@ -391,7 +391,7 @@ void ast_post_gpu(struct drm_device *dev) ...@@ -391,7 +391,7 @@ void ast_post_gpu(struct drm_device *dev)
ast_init_3rdtx(dev); ast_init_3rdtx(dev);
} else { } else {
if (ast->tx_chip_type != AST_TX_NONE) if (ast->tx_chip_types & AST_TX_SIL164_BIT)
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
} }
} }
......
...@@ -1266,6 +1266,25 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge, ...@@ -1266,6 +1266,25 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
return 0; return 0;
} }
static
struct drm_crtc *analogix_dp_get_old_crtc(struct analogix_dp_device *dp,
struct drm_atomic_state *state)
{
struct drm_encoder *encoder = dp->encoder;
struct drm_connector *connector;
struct drm_connector_state *conn_state;
connector = drm_atomic_get_old_connector_for_encoder(state, encoder);
if (!connector)
return NULL;
conn_state = drm_atomic_get_old_connector_state(state, connector);
if (!conn_state)
return NULL;
return conn_state->crtc;
}
static static
struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
struct drm_atomic_state *state) struct drm_atomic_state *state)
...@@ -1446,14 +1465,16 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, ...@@ -1446,14 +1465,16 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
{ {
struct drm_atomic_state *old_state = old_bridge_state->base.state; struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private; struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc; struct drm_crtc *old_crtc, *new_crtc;
struct drm_crtc_state *old_crtc_state = NULL;
struct drm_crtc_state *new_crtc_state = NULL; struct drm_crtc_state *new_crtc_state = NULL;
int ret;
crtc = analogix_dp_get_new_crtc(dp, old_state); new_crtc = analogix_dp_get_new_crtc(dp, old_state);
if (!crtc) if (!new_crtc)
goto out; goto out;
new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc); new_crtc_state = drm_atomic_get_new_crtc_state(old_state, new_crtc);
if (!new_crtc_state) if (!new_crtc_state)
goto out; goto out;
...@@ -1462,6 +1483,19 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, ...@@ -1462,6 +1483,19 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
return; return;
out: out:
old_crtc = analogix_dp_get_old_crtc(dp, old_state);
if (old_crtc) {
old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
old_crtc);
/* When moving from PSR to fully disabled, exit PSR first. */
if (old_crtc_state && old_crtc_state->self_refresh_active) {
ret = analogix_dp_disable_psr(dp);
if (ret)
DRM_ERROR("Failed to disable psr (%d)\n", ret);
}
}
analogix_dp_bridge_disable(bridge); analogix_dp_bridge_disable(bridge);
} }
......
...@@ -1011,9 +1011,19 @@ crtc_needs_disable(struct drm_crtc_state *old_state, ...@@ -1011,9 +1011,19 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
return drm_atomic_crtc_effectively_active(old_state); return drm_atomic_crtc_effectively_active(old_state);
/* /*
* We need to run through the crtc_funcs->disable() function if the CRTC * We need to disable bridge(s) and CRTC if we're transitioning out of
* is currently on, if it's transitioning to self refresh mode, or if * self-refresh and changing CRTCs at the same time, because the
* it's in self refresh mode and needs to be fully disabled. * bridge tracks self-refresh status via CRTC state.
*/
if (old_state->self_refresh_active &&
old_state->crtc != new_state->crtc)
return true;
/*
* We also need to run through the crtc_funcs->disable() function if
* the CRTC is currently on, if it's transitioning to self refresh
* mode, or if it's in self refresh mode and needs to be fully
* disabled.
*/ */
return old_state->active || return old_state->active ||
(old_state->self_refresh_active && !new_state->active) || (old_state->self_refresh_active && !new_state->active) ||
......
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