forked from Minki/linux
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_COMP1_PLAY_REG_OFFSET 0x6c
|
||||
#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_CONFIG_REG 0x51ca
|
||||
@ -77,7 +81,7 @@
|
||||
#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
|
||||
|
||||
#define ACP_TIMEOUT_LOOP 0x000000FF
|
||||
#define ACP_DEVS 3
|
||||
#define ACP_DEVS 4
|
||||
#define ACP_SRC_ID 162
|
||||
|
||||
enum {
|
||||
@ -316,14 +320,13 @@ static int acp_hw_init(void *handle)
|
||||
if (adev->acp.acp_cell == NULL)
|
||||
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) {
|
||||
kfree(adev->acp.acp_cell);
|
||||
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) {
|
||||
kfree(adev->acp.acp_res);
|
||||
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_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].flags = IORESOURCE_MEM;
|
||||
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].end = acp_base + ACP_I2S_CAP_REGS_END;
|
||||
|
||||
adev->acp.acp_res[3].name = "acp2x_dma_irq";
|
||||
adev->acp.acp_res[3].flags = IORESOURCE_IRQ;
|
||||
adev->acp.acp_res[3].start = amdgpu_irq_create_mapping(adev, 162);
|
||||
adev->acp.acp_res[3].end = adev->acp.acp_res[3].start;
|
||||
adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap";
|
||||
adev->acp.acp_res[3].flags = IORESOURCE_MEM;
|
||||
adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_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].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].platform_data = &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].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,
|
||||
ACP_DEVS);
|
||||
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 &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
|
||||
cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
|
||||
|
||||
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, 0x1028, 0x0812, 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 },
|
||||
};
|
||||
|
||||
|
@ -2747,6 +2747,9 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Make sure IB tests flushed */
|
||||
flush_delayed_work(&adev->late_init_work);
|
||||
|
||||
/* blat the mode back in */
|
||||
if (fbcon) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* TODO hbr2 compliance eye output is unstable
|
||||
/* TODO Raven hbr2 compliance eye output is unstable
|
||||
* (toggling on and off) with debugger break
|
||||
* This caueses intermittent PHY automation failure
|
||||
* 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)
|
||||
{
|
||||
union phy_test_pattern dpcd_test_pattern;
|
||||
@ -1832,13 +1830,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||
break;
|
||||
case PHY_TEST_PATTERN_CP2520_1:
|
||||
/* 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_HBR2_COMPLIANCE_EYE;
|
||||
break;
|
||||
case PHY_TEST_PATTERN_CP2520_2:
|
||||
/* 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_HBR2_COMPLIANCE_EYE;
|
||||
break;
|
||||
|
@ -76,6 +76,7 @@ struct dc_caps {
|
||||
bool is_apu;
|
||||
bool dual_link_dvi;
|
||||
bool post_blend_color_processing;
|
||||
bool force_dp_tps4_for_cp2520;
|
||||
};
|
||||
|
||||
struct dc_dcc_surface_param {
|
||||
|
@ -1027,6 +1027,8 @@ static bool construct(
|
||||
dc->caps.max_slave_planes = 1;
|
||||
dc->caps.is_apu = true;
|
||||
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)
|
||||
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)->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);
|
||||
|
||||
nv04_crtc_create(dev, 0);
|
||||
|
@ -1585,8 +1585,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
|
||||
*****************************************************************************/
|
||||
|
||||
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_core *core = disp->core;
|
||||
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
|
||||
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);
|
||||
interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -1693,15 +1711,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
/* Flush disable. */
|
||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||
if (atom->flush_disable) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -1762,18 +1773,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
}
|
||||
|
||||
/* Flush update. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
nv50_disp_atomic_commit_wndw(state, interlock);
|
||||
|
||||
if (interlock[NV50_DISP_INTERLOCK_CORE]) {
|
||||
if (interlock[NV50_DISP_INTERLOCK_BASE] ||
|
||||
interlock[NV50_DISP_INTERLOCK_OVLY] ||
|
||||
interlock[NV50_DISP_INTERLOCK_WNDW] ||
|
||||
!atom->state.legacy_cursor_update)
|
||||
nv50_disp_atomic_commit_core(drm, interlock);
|
||||
nv50_disp_atomic_commit_core(state, interlock);
|
||||
else
|
||||
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);
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (crtc->state->enable) {
|
||||
if (crtc->state->active) {
|
||||
if (!drm->have_disp_power_ref) {
|
||||
drm->have_disp_power_ref = true;
|
||||
return 0;
|
||||
@ -2119,10 +2126,6 @@ nv50_display_destroy(struct drm_device *dev)
|
||||
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
|
||||
nv50_display_create(struct drm_device *dev)
|
||||
{
|
||||
@ -2147,8 +2150,6 @@ nv50_display_create(struct drm_device *dev)
|
||||
disp->disp = &nouveau_display(dev)->disp;
|
||||
dev->mode_config.funcs = &nv50_disp_func;
|
||||
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 */
|
||||
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 nvif_device *device = &drm->client.device;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
INIT_LIST_HEAD(&drm->bl_connectors);
|
||||
|
||||
@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev)
|
||||
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 &&
|
||||
connector->connector_type != DRM_MODE_CONNECTOR_eDP)
|
||||
continue;
|
||||
@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1208,14 +1208,19 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_connector *nv_connector = NULL;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
int type, ret = 0;
|
||||
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);
|
||||
if (nv_connector->index == index)
|
||||
if (nv_connector->index == index) {
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
return connector;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
|
||||
if (!nv_connector)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include "nouveau_crtc.h"
|
||||
#include "nouveau_encoder.h"
|
||||
|
||||
struct nvkm_i2c_port;
|
||||
|
||||
@ -60,19 +61,46 @@ static inline struct nouveau_connector *nouveau_connector(
|
||||
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 *
|
||||
nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
|
||||
{
|
||||
struct drm_device *dev = nv_crtc->base.dev;
|
||||
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);
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder && connector->encoder->crtc == crtc)
|
||||
return nouveau_connector(connector);
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
|
||||
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 *
|
||||
|
@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev)
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
int ret;
|
||||
|
||||
ret = disp->init(dev);
|
||||
@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev)
|
||||
return ret;
|
||||
|
||||
/* 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);
|
||||
nvif_notify_get(&conn->hpd);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
/* enable flip completion events */
|
||||
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_drm *drm = nouveau_drm(dev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
if (!suspend) {
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
nvif_notify_put(&conn->hpd);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
disp->fini(dev);
|
||||
|
@ -81,6 +81,10 @@ MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
|
||||
int nouveau_modeset = -1;
|
||||
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)");
|
||||
static int nouveau_runtime_pm = -1;
|
||||
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);
|
||||
|
||||
if (nouveau_atomic)
|
||||
driver_pci.driver_features |= DRIVER_ATOMIC;
|
||||
|
||||
ret = drm_get_pci_dev(pdev, pent, &driver_pci);
|
||||
if (ret) {
|
||||
nvkm_device_del(&device);
|
||||
@ -874,22 +881,11 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
||||
static int
|
||||
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()) {
|
||||
pm_runtime_forbid(dev);
|
||||
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_autosuspend(dev);
|
||||
/* 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;
|
||||
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");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@ -626,7 +626,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
||||
if (b->presumed.valid)
|
||||
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");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
@ -140,6 +140,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
|
||||
if (fb->func->init)
|
||||
fb->func->init(fb);
|
||||
|
||||
if (fb->func->init_remapper)
|
||||
fb->func->init_remapper(fb);
|
||||
|
||||
if (fb->func->init_page) {
|
||||
ret = fb->func->init_page(fb);
|
||||
if (WARN_ON(ret))
|
||||
|
@ -36,6 +36,14 @@ gp100_fb_init_unkn(struct nvkm_fb *base)
|
||||
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
|
||||
gp100_fb_init(struct nvkm_fb *base)
|
||||
{
|
||||
@ -56,6 +64,7 @@ gp100_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gp100_fb_init,
|
||||
.init_remapper = gp100_fb_init_remapper,
|
||||
.init_page = gm200_fb_init_page,
|
||||
.init_unkn = gp100_fb_init_unkn,
|
||||
.ram_new = gp100_ram_new,
|
||||
|
@ -31,6 +31,7 @@ gp102_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gp100_fb_init,
|
||||
.init_remapper = gp100_fb_init_remapper,
|
||||
.init_page = gm200_fb_init_page,
|
||||
.ram_new = gp100_ram_new,
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ struct nvkm_fb_func {
|
||||
u32 (*tags)(struct nvkm_fb *);
|
||||
int (*oneinit)(struct nvkm_fb *);
|
||||
void (*init)(struct nvkm_fb *);
|
||||
void (*init_remapper)(struct nvkm_fb *);
|
||||
int (*init_page)(struct nvkm_fb *);
|
||||
void (*init_unkn)(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 *);
|
||||
|
||||
void gp100_fb_init_remapper(struct nvkm_fb *);
|
||||
void gp100_fb_init_unkn(struct nvkm_fb *);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user