nouveau and amdgpu fixes
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbUUjOAAoJEAx081l5xIa+x9MP/A1LsxZlZd1dkzGfBoKHq9oc fIknKBDU372rExEM/f0J5mE00ETi/+4YnkTtQZ1eQKYUyUtxwUbX5hEdbwsKkN8H wQvENY+hqE0vplFLibUf/+ZveCwuFmk8DzsdzxvmmcBkrQGM7dnF4VE8Yb/DpwT7 VK8t4IDwkhdgVmqu445dgwtJIDyEKyxO1rlelDWS6BPXMi+ySwNRWaNZWxZG2n0J fozSor7nElkSd/795WOUM0B344K9ZiZaex4mJi7XcZgo/IWTB4l+PWKUTvQvBlaP HIZOvbBryISW/ingnLRmq2UsuHLpgmveZyBN4BLqcZettxc2EcIgKMlGHZdi2nSL OjPzfneTKeiV47kFK66Rns+NnpOPxatb0YF94AweFvpOhXS8XR2lzJOsIeTVyab8 Q1c0WMa70SD0bjRNRuX3HeVG9IKNnpEWYus1xDXC6aE79tBmIVCFSejMbVT3BC6V 5Fc/Jpx6ODtObXArr/XMZrMsKr6JPEGK6GobV/fvaddgAPj2hoqXESVE6b5ReI3y MlSvHGzIN8oar+2vtResGrDxJE27pgCw7big/IR+VV7RPLEP6Mpo3EgMnCyhhdZk S/a+RxgHDv+2KSOjwqm3mha3g74+R0qN5LbYf7ghOl/7zNaiKQ7xIdsf5UEgDp57 kkQXTu7fUdRunTtgcO8v =8E++ -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2018-07-20' of git://anongit.freedesktop.org/drm/drm Pull drm fixes from Dave Airlie: "Just two sets of driver fixes this week to follow up on the set from earlier in the week and hopefully get me realigned schedule wise. amdgpu: - ACP fix for boards with multiple I2S instances - DP fix for CZ, vega - hybrid laptop fixes - Resume regression fix nouveau: - large memory systems and Pascal fix - MST race fixes - runtime PM fix" * tag 'drm-fixes-2018-07-20' of git://anongit.freedesktop.org/drm/drm: drm/nouveau/fb/gp100-: disable address remapper drm/amd/amdgpu: creating two I2S instances for stoney/cz (v2) drm/amdgpu: add another ATPX quirk for TOPAZ drm/amd/display: Fix DP HBR2 Eye Diagram Pattern on Carrizo drm/amdgpu: Make sure IB tests flushed after IP resume drm/nouveau: Set DRIVER_ATOMIC cap earlier to fix debugfs drm/nouveau: Remove bogus crtc check in pmops_runtime_idle drm/nouveau/drm/nouveau: Fix runtime PM leak in nv50_disp_atomic_commit() drm/nouveau: Avoid looping through fake MST connectors drm/nouveau: Use drm_connector_list_iter_* for iterating connectors drm/nouveau/gem: off by one bugs in nouveau_gem_pushbuf_reloc_apply() drm/nouveau/kms/nv50-: ensure window updates are submitted when flushing mst disables
This commit is contained in:
commit
28c20cc73b
@ -57,6 +57,10 @@
|
|||||||
#define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8
|
#define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8
|
||||||
#define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c
|
#define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c
|
||||||
#define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68
|
#define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68
|
||||||
|
#define ACP_BT_PLAY_REGS_START 0x14970
|
||||||
|
#define ACP_BT_PLAY_REGS_END 0x14a24
|
||||||
|
#define ACP_BT_COMP1_REG_OFFSET 0xac
|
||||||
|
#define ACP_BT_COMP2_REG_OFFSET 0xa8
|
||||||
|
|
||||||
#define mmACP_PGFSM_RETAIN_REG 0x51c9
|
#define mmACP_PGFSM_RETAIN_REG 0x51c9
|
||||||
#define mmACP_PGFSM_CONFIG_REG 0x51ca
|
#define mmACP_PGFSM_CONFIG_REG 0x51ca
|
||||||
@ -77,7 +81,7 @@
|
|||||||
#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
|
#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
|
||||||
|
|
||||||
#define ACP_TIMEOUT_LOOP 0x000000FF
|
#define ACP_TIMEOUT_LOOP 0x000000FF
|
||||||
#define ACP_DEVS 3
|
#define ACP_DEVS 4
|
||||||
#define ACP_SRC_ID 162
|
#define ACP_SRC_ID 162
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -316,14 +320,13 @@ static int acp_hw_init(void *handle)
|
|||||||
if (adev->acp.acp_cell == NULL)
|
if (adev->acp.acp_cell == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
adev->acp.acp_res = kcalloc(4, sizeof(struct resource), GFP_KERNEL);
|
adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
|
||||||
|
|
||||||
if (adev->acp.acp_res == NULL) {
|
if (adev->acp.acp_res == NULL) {
|
||||||
kfree(adev->acp.acp_cell);
|
kfree(adev->acp.acp_cell);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s_pdata = kcalloc(2, sizeof(struct i2s_platform_data), GFP_KERNEL);
|
i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
|
||||||
if (i2s_pdata == NULL) {
|
if (i2s_pdata == NULL) {
|
||||||
kfree(adev->acp.acp_res);
|
kfree(adev->acp.acp_res);
|
||||||
kfree(adev->acp.acp_cell);
|
kfree(adev->acp.acp_cell);
|
||||||
@ -358,6 +361,20 @@ static int acp_hw_init(void *handle)
|
|||||||
i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
|
i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
|
||||||
i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
|
i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
|
||||||
|
|
||||||
|
i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
|
||||||
|
switch (adev->asic_type) {
|
||||||
|
case CHIP_STONEY:
|
||||||
|
i2s_pdata[2].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
|
||||||
|
i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000;
|
||||||
|
i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET;
|
||||||
|
i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET;
|
||||||
|
|
||||||
adev->acp.acp_res[0].name = "acp2x_dma";
|
adev->acp.acp_res[0].name = "acp2x_dma";
|
||||||
adev->acp.acp_res[0].flags = IORESOURCE_MEM;
|
adev->acp.acp_res[0].flags = IORESOURCE_MEM;
|
||||||
adev->acp.acp_res[0].start = acp_base;
|
adev->acp.acp_res[0].start = acp_base;
|
||||||
@ -373,13 +390,18 @@ static int acp_hw_init(void *handle)
|
|||||||
adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START;
|
adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START;
|
||||||
adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END;
|
adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END;
|
||||||
|
|
||||||
adev->acp.acp_res[3].name = "acp2x_dma_irq";
|
adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap";
|
||||||
adev->acp.acp_res[3].flags = IORESOURCE_IRQ;
|
adev->acp.acp_res[3].flags = IORESOURCE_MEM;
|
||||||
adev->acp.acp_res[3].start = amdgpu_irq_create_mapping(adev, 162);
|
adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_START;
|
||||||
adev->acp.acp_res[3].end = adev->acp.acp_res[3].start;
|
adev->acp.acp_res[3].end = acp_base + ACP_BT_PLAY_REGS_END;
|
||||||
|
|
||||||
|
adev->acp.acp_res[4].name = "acp2x_dma_irq";
|
||||||
|
adev->acp.acp_res[4].flags = IORESOURCE_IRQ;
|
||||||
|
adev->acp.acp_res[4].start = amdgpu_irq_create_mapping(adev, 162);
|
||||||
|
adev->acp.acp_res[4].end = adev->acp.acp_res[4].start;
|
||||||
|
|
||||||
adev->acp.acp_cell[0].name = "acp_audio_dma";
|
adev->acp.acp_cell[0].name = "acp_audio_dma";
|
||||||
adev->acp.acp_cell[0].num_resources = 4;
|
adev->acp.acp_cell[0].num_resources = 5;
|
||||||
adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
|
adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
|
||||||
adev->acp.acp_cell[0].platform_data = &adev->asic_type;
|
adev->acp.acp_cell[0].platform_data = &adev->asic_type;
|
||||||
adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
|
adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
|
||||||
@ -396,6 +418,12 @@ static int acp_hw_init(void *handle)
|
|||||||
adev->acp.acp_cell[2].platform_data = &i2s_pdata[1];
|
adev->acp.acp_cell[2].platform_data = &i2s_pdata[1];
|
||||||
adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data);
|
adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data);
|
||||||
|
|
||||||
|
adev->acp.acp_cell[3].name = "designware-i2s";
|
||||||
|
adev->acp.acp_cell[3].num_resources = 1;
|
||||||
|
adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3];
|
||||||
|
adev->acp.acp_cell[3].platform_data = &i2s_pdata[2];
|
||||||
|
adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data);
|
||||||
|
|
||||||
r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell,
|
r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell,
|
||||||
ACP_DEVS);
|
ACP_DEVS);
|
||||||
if (r)
|
if (r)
|
||||||
@ -451,7 +479,6 @@ static int acp_hw_init(void *handle)
|
|||||||
val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
|
val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
|
||||||
val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
|
val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
|
||||||
cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
|
cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,6 +575,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
|
|||||||
{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||||
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||||
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||||
|
{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 0, 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2747,6 +2747,9 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
/* Make sure IB tests flushed */
|
||||||
|
flush_delayed_work(&adev->late_init_work);
|
||||||
|
|
||||||
/* blat the mode back in */
|
/* blat the mode back in */
|
||||||
if (fbcon) {
|
if (fbcon) {
|
||||||
if (!amdgpu_device_has_dc_support(adev)) {
|
if (!amdgpu_device_has_dc_support(adev)) {
|
||||||
|
@ -1767,12 +1767,10 @@ static void dp_test_send_link_training(struct dc_link *link)
|
|||||||
dp_retrain_link_dp_test(link, &link_settings, false);
|
dp_retrain_link_dp_test(link, &link_settings, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO hbr2 compliance eye output is unstable
|
/* TODO Raven hbr2 compliance eye output is unstable
|
||||||
* (toggling on and off) with debugger break
|
* (toggling on and off) with debugger break
|
||||||
* This caueses intermittent PHY automation failure
|
* This caueses intermittent PHY automation failure
|
||||||
* Need to look into the root cause */
|
* Need to look into the root cause */
|
||||||
static uint8_t force_tps4_for_cp2520 = 1;
|
|
||||||
|
|
||||||
static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||||
{
|
{
|
||||||
union phy_test_pattern dpcd_test_pattern;
|
union phy_test_pattern dpcd_test_pattern;
|
||||||
@ -1832,13 +1830,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
|||||||
break;
|
break;
|
||||||
case PHY_TEST_PATTERN_CP2520_1:
|
case PHY_TEST_PATTERN_CP2520_1:
|
||||||
/* CP2520 pattern is unstable, temporarily use TPS4 instead */
|
/* CP2520 pattern is unstable, temporarily use TPS4 instead */
|
||||||
test_pattern = (force_tps4_for_cp2520 == 1) ?
|
test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
|
||||||
DP_TEST_PATTERN_TRAINING_PATTERN4 :
|
DP_TEST_PATTERN_TRAINING_PATTERN4 :
|
||||||
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
|
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
|
||||||
break;
|
break;
|
||||||
case PHY_TEST_PATTERN_CP2520_2:
|
case PHY_TEST_PATTERN_CP2520_2:
|
||||||
/* CP2520 pattern is unstable, temporarily use TPS4 instead */
|
/* CP2520 pattern is unstable, temporarily use TPS4 instead */
|
||||||
test_pattern = (force_tps4_for_cp2520 == 1) ?
|
test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
|
||||||
DP_TEST_PATTERN_TRAINING_PATTERN4 :
|
DP_TEST_PATTERN_TRAINING_PATTERN4 :
|
||||||
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
|
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
|
||||||
break;
|
break;
|
||||||
|
@ -76,6 +76,7 @@ struct dc_caps {
|
|||||||
bool is_apu;
|
bool is_apu;
|
||||||
bool dual_link_dvi;
|
bool dual_link_dvi;
|
||||||
bool post_blend_color_processing;
|
bool post_blend_color_processing;
|
||||||
|
bool force_dp_tps4_for_cp2520;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dc_dcc_surface_param {
|
struct dc_dcc_surface_param {
|
||||||
|
@ -1027,6 +1027,8 @@ static bool construct(
|
|||||||
dc->caps.max_slave_planes = 1;
|
dc->caps.max_slave_planes = 1;
|
||||||
dc->caps.is_apu = true;
|
dc->caps.is_apu = true;
|
||||||
dc->caps.post_blend_color_processing = false;
|
dc->caps.post_blend_color_processing = false;
|
||||||
|
/* Raven DP PHY HBR2 eye diagram pattern is not stable. Use TP4 */
|
||||||
|
dc->caps.force_dp_tps4_for_cp2520 = true;
|
||||||
|
|
||||||
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
|
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
|
||||||
dc->debug = debug_defaults_drv;
|
dc->debug = debug_defaults_drv;
|
||||||
|
@ -55,6 +55,9 @@ nv04_display_create(struct drm_device *dev)
|
|||||||
nouveau_display(dev)->init = nv04_display_init;
|
nouveau_display(dev)->init = nv04_display_init;
|
||||||
nouveau_display(dev)->fini = nv04_display_fini;
|
nouveau_display(dev)->fini = nv04_display_fini;
|
||||||
|
|
||||||
|
/* Pre-nv50 doesn't support atomic, so don't expose the ioctls */
|
||||||
|
dev->driver->driver_features &= ~DRIVER_ATOMIC;
|
||||||
|
|
||||||
nouveau_hw_save_vga_fonts(dev, 1);
|
nouveau_hw_save_vga_fonts(dev, 1);
|
||||||
|
|
||||||
nv04_crtc_create(dev, 0);
|
nv04_crtc_create(dev, 0);
|
||||||
|
@ -1585,8 +1585,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
|
nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock)
|
||||||
{
|
{
|
||||||
|
struct nouveau_drm *drm = nouveau_drm(state->dev);
|
||||||
struct nv50_disp *disp = nv50_disp(drm->dev);
|
struct nv50_disp *disp = nv50_disp(drm->dev);
|
||||||
struct nv50_core *core = disp->core;
|
struct nv50_core *core = disp->core;
|
||||||
struct nv50_mstm *mstm;
|
struct nv50_mstm *mstm;
|
||||||
@ -1617,6 +1618,22 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nv50_disp_atomic_commit_wndw(struct drm_atomic_state *state, u32 *interlock)
|
||||||
|
{
|
||||||
|
struct drm_plane_state *new_plane_state;
|
||||||
|
struct drm_plane *plane;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||||
|
struct nv50_wndw *wndw = nv50_wndw(plane);
|
||||||
|
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
||||||
|
if (wndw->func->update)
|
||||||
|
wndw->func->update(wndw, interlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||||
{
|
{
|
||||||
@ -1684,7 +1701,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
help->disable(encoder);
|
help->disable(encoder);
|
||||||
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
|
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
|
||||||
if (outp->flush_disable) {
|
if (outp->flush_disable) {
|
||||||
nv50_disp_atomic_commit_core(drm, interlock);
|
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||||
|
nv50_disp_atomic_commit_core(state, interlock);
|
||||||
memset(interlock, 0x00, sizeof(interlock));
|
memset(interlock, 0x00, sizeof(interlock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1693,15 +1711,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
/* Flush disable. */
|
/* Flush disable. */
|
||||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||||
if (atom->flush_disable) {
|
if (atom->flush_disable) {
|
||||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||||
struct nv50_wndw *wndw = nv50_wndw(plane);
|
nv50_disp_atomic_commit_core(state, interlock);
|
||||||
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
|
||||||
if (wndw->func->update)
|
|
||||||
wndw->func->update(wndw, interlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nv50_disp_atomic_commit_core(drm, interlock);
|
|
||||||
memset(interlock, 0x00, sizeof(interlock));
|
memset(interlock, 0x00, sizeof(interlock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1762,18 +1773,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Flush update. */
|
/* Flush update. */
|
||||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||||
struct nv50_wndw *wndw = nv50_wndw(plane);
|
|
||||||
if (interlock[wndw->interlock.type] & wndw->interlock.data) {
|
|
||||||
if (wndw->func->update)
|
|
||||||
wndw->func->update(wndw, interlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||||
if (interlock[NV50_DISP_INTERLOCK_BASE] ||
|
if (interlock[NV50_DISP_INTERLOCK_BASE] ||
|
||||||
|
interlock[NV50_DISP_INTERLOCK_OVLY] ||
|
||||||
|
interlock[NV50_DISP_INTERLOCK_WNDW] ||
|
||||||
!atom->state.legacy_cursor_update)
|
!atom->state.legacy_cursor_update)
|
||||||
nv50_disp_atomic_commit_core(drm, interlock);
|
nv50_disp_atomic_commit_core(state, interlock);
|
||||||
else
|
else
|
||||||
disp->core->func->update(disp->core, interlock, false);
|
disp->core->func->update(disp->core, interlock, false);
|
||||||
}
|
}
|
||||||
@ -1871,7 +1878,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
|
|||||||
nv50_disp_atomic_commit_tail(state);
|
nv50_disp_atomic_commit_tail(state);
|
||||||
|
|
||||||
drm_for_each_crtc(crtc, dev) {
|
drm_for_each_crtc(crtc, dev) {
|
||||||
if (crtc->state->enable) {
|
if (crtc->state->active) {
|
||||||
if (!drm->have_disp_power_ref) {
|
if (!drm->have_disp_power_ref) {
|
||||||
drm->have_disp_power_ref = true;
|
drm->have_disp_power_ref = true;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2119,10 +2126,6 @@ nv50_display_destroy(struct drm_device *dev)
|
|||||||
kfree(disp);
|
kfree(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
|
|
||||||
static int nouveau_atomic = 0;
|
|
||||||
module_param_named(atomic, nouveau_atomic, int, 0400);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
nv50_display_create(struct drm_device *dev)
|
nv50_display_create(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@ -2147,8 +2150,6 @@ nv50_display_create(struct drm_device *dev)
|
|||||||
disp->disp = &nouveau_display(dev)->disp;
|
disp->disp = &nouveau_display(dev)->disp;
|
||||||
dev->mode_config.funcs = &nv50_disp_func;
|
dev->mode_config.funcs = &nv50_disp_func;
|
||||||
dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
|
dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
|
||||||
if (nouveau_atomic)
|
|
||||||
dev->driver->driver_features |= DRIVER_ATOMIC;
|
|
||||||
|
|
||||||
/* small shared memory area we use for notifiers and semaphores */
|
/* small shared memory area we use for notifiers and semaphores */
|
||||||
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
|
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
|
||||||
|
@ -267,6 +267,7 @@ nouveau_backlight_init(struct drm_device *dev)
|
|||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||||
struct nvif_device *device = &drm->client.device;
|
struct nvif_device *device = &drm->client.device;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
struct drm_connector_list_iter conn_iter;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&drm->bl_connectors);
|
INIT_LIST_HEAD(&drm->bl_connectors);
|
||||||
|
|
||||||
@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||||
|
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||||
if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
|
if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
|
||||||
connector->connector_type != DRM_MODE_CONNECTOR_eDP)
|
connector->connector_type != DRM_MODE_CONNECTOR_eDP)
|
||||||
continue;
|
continue;
|
||||||
@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1208,14 +1208,19 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
|||||||
struct nouveau_display *disp = nouveau_display(dev);
|
struct nouveau_display *disp = nouveau_display(dev);
|
||||||
struct nouveau_connector *nv_connector = NULL;
|
struct nouveau_connector *nv_connector = NULL;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
struct drm_connector_list_iter conn_iter;
|
||||||
int type, ret = 0;
|
int type, ret = 0;
|
||||||
bool dummy;
|
bool dummy;
|
||||||
|
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||||
|
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||||
nv_connector = nouveau_connector(connector);
|
nv_connector = nouveau_connector(connector);
|
||||||
if (nv_connector->index == index)
|
if (nv_connector->index == index) {
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
return connector;
|
return connector;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
|
|
||||||
nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
|
nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
|
||||||
if (!nv_connector)
|
if (!nv_connector)
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <drm/drm_encoder.h>
|
#include <drm/drm_encoder.h>
|
||||||
#include <drm/drm_dp_helper.h>
|
#include <drm/drm_dp_helper.h>
|
||||||
#include "nouveau_crtc.h"
|
#include "nouveau_crtc.h"
|
||||||
|
#include "nouveau_encoder.h"
|
||||||
|
|
||||||
struct nvkm_i2c_port;
|
struct nvkm_i2c_port;
|
||||||
|
|
||||||
@ -60,19 +61,46 @@ static inline struct nouveau_connector *nouveau_connector(
|
|||||||
return container_of(con, struct nouveau_connector, base);
|
return container_of(con, struct nouveau_connector, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
nouveau_connector_is_mst(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
const struct nouveau_encoder *nv_encoder;
|
||||||
|
const struct drm_encoder *encoder;
|
||||||
|
|
||||||
|
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nv_encoder = find_encoder(connector, DCB_OUTPUT_ANY);
|
||||||
|
if (!nv_encoder)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
encoder = &nv_encoder->base.base;
|
||||||
|
return encoder->encoder_type == DRM_MODE_ENCODER_DPMST;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define nouveau_for_each_non_mst_connector_iter(connector, iter) \
|
||||||
|
drm_for_each_connector_iter(connector, iter) \
|
||||||
|
for_each_if(!nouveau_connector_is_mst(connector))
|
||||||
|
|
||||||
static inline struct nouveau_connector *
|
static inline struct nouveau_connector *
|
||||||
nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
|
nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = nv_crtc->base.dev;
|
struct drm_device *dev = nv_crtc->base.dev;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
struct drm_connector_list_iter conn_iter;
|
||||||
|
struct nouveau_connector *nv_connector = NULL;
|
||||||
struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
|
struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
|
||||||
|
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||||
if (connector->encoder && connector->encoder->crtc == crtc)
|
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||||
return nouveau_connector(connector);
|
if (connector->encoder && connector->encoder->crtc == crtc) {
|
||||||
|
nv_connector = nouveau_connector(connector);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
|
|
||||||
return NULL;
|
return nv_connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drm_connector *
|
struct drm_connector *
|
||||||
|
@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev)
|
|||||||
struct nouveau_display *disp = nouveau_display(dev);
|
struct nouveau_display *disp = nouveau_display(dev);
|
||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
struct drm_connector_list_iter conn_iter;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = disp->init(dev);
|
ret = disp->init(dev);
|
||||||
@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* enable hotplug interrupts */
|
/* enable hotplug interrupts */
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||||
|
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||||
nvif_notify_get(&conn->hpd);
|
nvif_notify_get(&conn->hpd);
|
||||||
}
|
}
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
|
|
||||||
/* enable flip completion events */
|
/* enable flip completion events */
|
||||||
nvif_notify_get(&drm->flip);
|
nvif_notify_get(&drm->flip);
|
||||||
@ -427,6 +430,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
|
|||||||
struct nouveau_display *disp = nouveau_display(dev);
|
struct nouveau_display *disp = nouveau_display(dev);
|
||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
struct drm_connector_list_iter conn_iter;
|
||||||
|
|
||||||
if (!suspend) {
|
if (!suspend) {
|
||||||
if (drm_drv_uses_atomic_modeset(dev))
|
if (drm_drv_uses_atomic_modeset(dev))
|
||||||
@ -439,10 +443,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
|
|||||||
nvif_notify_put(&drm->flip);
|
nvif_notify_put(&drm->flip);
|
||||||
|
|
||||||
/* disable hotplug interrupts */
|
/* disable hotplug interrupts */
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||||
|
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||||
nvif_notify_put(&conn->hpd);
|
nvif_notify_put(&conn->hpd);
|
||||||
}
|
}
|
||||||
|
drm_connector_list_iter_end(&conn_iter);
|
||||||
|
|
||||||
drm_kms_helper_poll_disable(dev);
|
drm_kms_helper_poll_disable(dev);
|
||||||
disp->fini(dev);
|
disp->fini(dev);
|
||||||
|
@ -81,6 +81,10 @@ MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
|
|||||||
int nouveau_modeset = -1;
|
int nouveau_modeset = -1;
|
||||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||||
|
|
||||||
|
MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
|
||||||
|
static int nouveau_atomic = 0;
|
||||||
|
module_param_named(atomic, nouveau_atomic, int, 0400);
|
||||||
|
|
||||||
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
|
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
|
||||||
static int nouveau_runtime_pm = -1;
|
static int nouveau_runtime_pm = -1;
|
||||||
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
|
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
|
||||||
@ -509,6 +513,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
|
|||||||
|
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
|
|
||||||
|
if (nouveau_atomic)
|
||||||
|
driver_pci.driver_features |= DRIVER_ATOMIC;
|
||||||
|
|
||||||
ret = drm_get_pci_dev(pdev, pent, &driver_pci);
|
ret = drm_get_pci_dev(pdev, pent, &driver_pci);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
nvkm_device_del(&device);
|
nvkm_device_del(&device);
|
||||||
@ -874,22 +881,11 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
|||||||
static int
|
static int
|
||||||
nouveau_pmops_runtime_idle(struct device *dev)
|
nouveau_pmops_runtime_idle(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
|
||||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
|
||||||
struct nouveau_drm *drm = nouveau_drm(drm_dev);
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
|
|
||||||
if (!nouveau_pmops_runtime()) {
|
if (!nouveau_pmops_runtime()) {
|
||||||
pm_runtime_forbid(dev);
|
pm_runtime_forbid(dev);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(crtc, &drm->dev->mode_config.crtc_list, head) {
|
|
||||||
if (crtc->enabled) {
|
|
||||||
DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pm_runtime_mark_last_busy(dev);
|
pm_runtime_mark_last_busy(dev);
|
||||||
pm_runtime_autosuspend(dev);
|
pm_runtime_autosuspend(dev);
|
||||||
/* we don't want the main rpm_idle to call suspend - we want to autosuspend */
|
/* we don't want the main rpm_idle to call suspend - we want to autosuspend */
|
||||||
|
@ -616,7 +616,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
|||||||
struct nouveau_bo *nvbo;
|
struct nouveau_bo *nvbo;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
if (unlikely(r->bo_index > req->nr_buffers)) {
|
if (unlikely(r->bo_index >= req->nr_buffers)) {
|
||||||
NV_PRINTK(err, cli, "reloc bo index invalid\n");
|
NV_PRINTK(err, cli, "reloc bo index invalid\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
@ -626,7 +626,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
|||||||
if (b->presumed.valid)
|
if (b->presumed.valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
|
if (unlikely(r->reloc_bo_index >= req->nr_buffers)) {
|
||||||
NV_PRINTK(err, cli, "reloc container bo index invalid\n");
|
NV_PRINTK(err, cli, "reloc container bo index invalid\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
|
@ -140,6 +140,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
|
|||||||
if (fb->func->init)
|
if (fb->func->init)
|
||||||
fb->func->init(fb);
|
fb->func->init(fb);
|
||||||
|
|
||||||
|
if (fb->func->init_remapper)
|
||||||
|
fb->func->init_remapper(fb);
|
||||||
|
|
||||||
if (fb->func->init_page) {
|
if (fb->func->init_page) {
|
||||||
ret = fb->func->init_page(fb);
|
ret = fb->func->init_page(fb);
|
||||||
if (WARN_ON(ret))
|
if (WARN_ON(ret))
|
||||||
|
@ -36,6 +36,14 @@ gp100_fb_init_unkn(struct nvkm_fb *base)
|
|||||||
nvkm_wr32(device, 0x1faccc, nvkm_rd32(device, 0x100ccc));
|
nvkm_wr32(device, 0x1faccc, nvkm_rd32(device, 0x100ccc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gp100_fb_init_remapper(struct nvkm_fb *fb)
|
||||||
|
{
|
||||||
|
struct nvkm_device *device = fb->subdev.device;
|
||||||
|
/* Disable address remapper. */
|
||||||
|
nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gp100_fb_init(struct nvkm_fb *base)
|
gp100_fb_init(struct nvkm_fb *base)
|
||||||
{
|
{
|
||||||
@ -56,6 +64,7 @@ gp100_fb = {
|
|||||||
.dtor = gf100_fb_dtor,
|
.dtor = gf100_fb_dtor,
|
||||||
.oneinit = gf100_fb_oneinit,
|
.oneinit = gf100_fb_oneinit,
|
||||||
.init = gp100_fb_init,
|
.init = gp100_fb_init,
|
||||||
|
.init_remapper = gp100_fb_init_remapper,
|
||||||
.init_page = gm200_fb_init_page,
|
.init_page = gm200_fb_init_page,
|
||||||
.init_unkn = gp100_fb_init_unkn,
|
.init_unkn = gp100_fb_init_unkn,
|
||||||
.ram_new = gp100_ram_new,
|
.ram_new = gp100_ram_new,
|
||||||
|
@ -31,6 +31,7 @@ gp102_fb = {
|
|||||||
.dtor = gf100_fb_dtor,
|
.dtor = gf100_fb_dtor,
|
||||||
.oneinit = gf100_fb_oneinit,
|
.oneinit = gf100_fb_oneinit,
|
||||||
.init = gp100_fb_init,
|
.init = gp100_fb_init,
|
||||||
|
.init_remapper = gp100_fb_init_remapper,
|
||||||
.init_page = gm200_fb_init_page,
|
.init_page = gm200_fb_init_page,
|
||||||
.ram_new = gp100_ram_new,
|
.ram_new = gp100_ram_new,
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ struct nvkm_fb_func {
|
|||||||
u32 (*tags)(struct nvkm_fb *);
|
u32 (*tags)(struct nvkm_fb *);
|
||||||
int (*oneinit)(struct nvkm_fb *);
|
int (*oneinit)(struct nvkm_fb *);
|
||||||
void (*init)(struct nvkm_fb *);
|
void (*init)(struct nvkm_fb *);
|
||||||
|
void (*init_remapper)(struct nvkm_fb *);
|
||||||
int (*init_page)(struct nvkm_fb *);
|
int (*init_page)(struct nvkm_fb *);
|
||||||
void (*init_unkn)(struct nvkm_fb *);
|
void (*init_unkn)(struct nvkm_fb *);
|
||||||
void (*intr)(struct nvkm_fb *);
|
void (*intr)(struct nvkm_fb *);
|
||||||
@ -69,5 +70,6 @@ int gf100_fb_init_page(struct nvkm_fb *);
|
|||||||
|
|
||||||
int gm200_fb_init_page(struct nvkm_fb *);
|
int gm200_fb_init_page(struct nvkm_fb *);
|
||||||
|
|
||||||
|
void gp100_fb_init_remapper(struct nvkm_fb *);
|
||||||
void gp100_fb_init_unkn(struct nvkm_fb *);
|
void gp100_fb_init_unkn(struct nvkm_fb *);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user