From 89ce4b0f4e7adda75ac7eec6aaa9b3516390cef2 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 8 Jan 2015 00:04:04 +0100 Subject: gpu: ipu-v3: do not divide by zero if the pixel clock is too large Even if an unsupported mode with a pixel clock larger than two times the 264 MHz IPU HSP clock is set, don't divide by zero. Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-di.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c index b61d6be97602..3ddfb3d0b64d 100644 --- a/drivers/gpu/ipu-v3/ipu-di.c +++ b/drivers/gpu/ipu-v3/ipu-di.c @@ -459,6 +459,8 @@ static void ipu_di_config_clock(struct ipu_di *di, clkrate = clk_get_rate(di->clk_ipu); div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock); + if (div == 0) + div = 1; rate = clkrate / div; error = rate / (sig->mode.pixelclock / 1000); -- cgit v1.2.3 From 081c80e85feabe9a0081f4db940fccb6443b81fb Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 7 Jan 2015 23:52:15 +0100 Subject: drm/imx: dw_hdmi-imx: add mode_valid callback prune unsupported modes This patch limits the pixel clock to 13.4 MHz - 266 MHz for i.MX6Q and 13.5 MHz - 270 MHz for i.MX6DL, which is the range documented in the HDMI Transmitter chapter of the respective reference manuals. Without this patch, when connected to a monitor capable of 2160p60 modes, dw_hdmi will happily report this mode and the IPU code will cause a division by zero in ipu_di_config_clock when trying to figure out how to divide the 264 MHz HSP clock down to ~600 MHz. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/dw_hdmi-imx.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 121d30ca2d44..d25aaef3cba6 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -136,11 +136,34 @@ static struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = { .destroy = drm_encoder_cleanup, }; +static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con, + struct drm_display_mode *mode) +{ + if (mode->clock < 13500) + return MODE_CLOCK_LOW; + if (mode->clock > 266000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con, + struct drm_display_mode *mode) +{ + if (mode->clock < 13500) + return MODE_CLOCK_LOW; + if (mode->clock > 270000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = { - .mpll_cfg = imx_mpll_cfg, - .cur_ctr = imx_cur_ctr, - .sym_term = imx_sym_term, - .dev_type = IMX6Q_HDMI, + .mpll_cfg = imx_mpll_cfg, + .cur_ctr = imx_cur_ctr, + .sym_term = imx_sym_term, + .dev_type = IMX6Q_HDMI, + .mode_valid = imx6q_hdmi_mode_valid, }; static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { @@ -148,6 +171,7 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { .cur_ctr = imx_cur_ctr, .sym_term = imx_sym_term, .dev_type = IMX6DL_HDMI, + .mode_valid = imx6dl_hdmi_mode_valid, }; static const struct of_device_id dw_hdmi_imx_dt_ids[] = { -- cgit v1.2.3 From 6e8958ec0ecfd83691e6854839f917d3eaca236b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 7 Jan 2015 23:49:41 +0100 Subject: drm/imx: dw_hdmi-imx: add end of array element to current control array The loop iterating over curr_ctrl in dw_hdmi terminates on mpixelclock == ~0UL, so there needs to be an end of list element here in case a mode with a pixel clock larger than 216 MHz is set. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index d25aaef3cba6..87fe8ed92ebe 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -70,7 +70,9 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = { 118800000, { 0x091c, 0x091c, 0x06dc }, }, { 216000000, { 0x06dc, 0x0b5c, 0x091c }, - } + }, { + ~0UL, { 0x0000, 0x0000, 0x0000 }, + }, }; static const struct dw_hdmi_sym_term imx_sym_term[] = { -- cgit v1.2.3 From 51dac94e801fb779789fa8e38bac7df306ac4fa7 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 17:10:01 +0100 Subject: drm/imx: imx-ldb: enable DI clock in encoder_mode_set Commit eb10d6355532 ("imx-drm: encoder prepare/mode_set must use adjusted mode") broke the first LVDS modeset by using crtc->hwmode before crtc mode_set is called. In fact, encoder prepare is not supposed to prepare the display clock at all. Rather encoder mode_set should be used to set the DI clock rate, before it is enabled by crtc commit. Reported-by: Liu Ying Tested-by: Fabio Estevam Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 1b86aac0b341..2d6dc94e1e64 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -163,22 +163,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; - struct drm_display_mode *mode = &encoder->crtc->hwmode; u32 pixel_fmt; - unsigned long serial_clk; - unsigned long di_clk = mode->clock * 1000; - int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); - - if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { - /* dual channel LVDS mode */ - serial_clk = 3500UL * mode->clock; - imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); - imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk); - } else { - serial_clk = 7000UL * mode->clock; - imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk, - di_clk); - } switch (imx_ldb_ch->chno) { case 0: @@ -247,6 +232,9 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; + unsigned long serial_clk; + unsigned long di_clk = mode->clock * 1000; + int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); if (mode->clock > 170000) { dev_warn(ldb->dev, @@ -257,6 +245,16 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, "%s: mode exceeds 85 MHz pixel clock\n", __func__); } + if (dual) { + serial_clk = 3500UL * mode->clock; + imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); + imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk); + } else { + serial_clk = 7000UL * mode->clock; + imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk, + di_clk); + } + /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */ if (imx_ldb_ch == &ldb->channel[0]) { if (mode->flags & DRM_MODE_FLAG_NVSYNC) -- cgit v1.2.3 From d70e96ae05928643a7b10b8a519dc27afe4750d0 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 23 Feb 2015 11:09:51 +0800 Subject: DRM: i.MX: parallel display: Support probe deferral for finding DRM panel Signed-off-by: Liu Ying Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 5e83e007080f..900dda6a8e71 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -236,8 +236,11 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) } panel_node = of_parse_phandle(np, "fsl,panel", 0); - if (panel_node) + if (panel_node) { imxpd->panel = of_drm_find_panel(panel_node); + if (!imxpd->panel) + return -EPROBE_DEFER; + } imxpd->dev = dev; -- cgit v1.2.3 From 9c58e8dbd3bfe7197323c88a784617afeffa9f87 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 3 Mar 2015 10:58:08 +0100 Subject: drm/rockchip: Flip select/depends in Kconfig Otherwise Kconfig gets confused and somehow ends up creating a 2nd drm submenu. I couldn't find i915 because of this any more at first. Cc: Andy Yan Cc: Russell King Cc: Philipp Zabel Cc: "Yann E. MORIN" Cc: linux-kbuild@vger.kernel.or Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/rockchip/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 35215f6867d3..c22310c91672 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -18,8 +18,8 @@ config DRM_ROCKCHIP config ROCKCHIP_DW_HDMI tristate "Rockchip specific extensions for Synopsys DW HDMI" - depends on DRM_ROCKCHIP select DRM_DW_HDMI + depends on DRM_ROCKCHIP help This selects support for Rockchip SoC specific extensions for the Synopsys DesignWare HDMI driver. If you want to -- cgit v1.2.3 From ed9ed50ccc2c16690b921171c809f6f15255ac65 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Mar 2015 20:58:43 +1000 Subject: Revert "drm/rockchip: Flip select/depends in Kconfig" This reverts commit 9c58e8dbd3bfe7197323c88a784617afeffa9f87. This doesn't seem to fully fix this, Kbuild who knows. Signed-off-by: Dave Airlie --- drivers/gpu/drm/rockchip/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index c22310c91672..35215f6867d3 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -18,8 +18,8 @@ config DRM_ROCKCHIP config ROCKCHIP_DW_HDMI tristate "Rockchip specific extensions for Synopsys DW HDMI" - select DRM_DW_HDMI depends on DRM_ROCKCHIP + select DRM_DW_HDMI help This selects support for Rockchip SoC specific extensions for the Synopsys DesignWare HDMI driver. If you want to -- cgit v1.2.3 From add7d7596612bac594201da151a3ed6f8e94fc33 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 10:04:11 -0500 Subject: drm/radeon: fix the audio dpms callbacks Don't touch the audio enable bits as these are already handled in display detection. Enable the hdmi secondary streams in hdmi enable to match dp. Rename dp dpms callback to be consistent with hdmi. bug: https://bugs.freedesktop.org/show_bug.cgi?id=89327 https://bugzilla.kernel.org/show_bug.cgi?id=93921 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/dce6_afmt.c | 28 ++++++----------- drivers/gpu/drm/radeon/evergreen_hdmi.c | 55 ++++++++++++--------------------- drivers/gpu/drm/radeon/r600_hdmi.c | 11 ------- drivers/gpu/drm/radeon/radeon_audio.c | 8 ++--- 4 files changed, 32 insertions(+), 70 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 192c80389151..9de14cfc0e80 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -288,36 +288,26 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev, WREG32(DCCG_AUDIO_DTO1_MODULE, clock); } -void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable) +void dce6_dp_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - uint32_t offset; if (!dig || !dig->afmt) return; - offset = dig->afmt->offset; - if (enable) { - if (dig->afmt->enabled) - return; - - WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); - WREG32(EVERGREEN_DP_SEC_CNTL + offset, - EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */ - EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */ - EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */ - EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */ - radeon_audio_enable(rdev, dig->afmt->pin, true); + WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset, + EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); + WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, + EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */ + EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */ + EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */ + EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */ } else { - if (!dig->afmt->enabled) - return; - - WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0); - radeon_audio_enable(rdev, dig->afmt->pin, false); + WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0); } dig->afmt->enabled = enable; diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 1d9aebc79595..bdf2ca8b0be4 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -350,20 +350,9 @@ void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; - WREG32(HDMI_INFOFRAME_CONTROL0 + offset, - HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ - HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ - WREG32(AFMT_INFOFRAME_CONTROL0 + offset, AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ - WREG32(HDMI_INFOFRAME_CONTROL1 + offset, - HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ - - WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, - HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ - HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ - WREG32(AFMT_60958_0 + offset, AFMT_60958_CS_CHANNEL_NUMBER_L(1)); @@ -408,15 +397,19 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!dig || !dig->afmt) return; - /* Silent, r600_hdmi_enable will raise WARN for us */ - if (enable && dig->afmt->enabled) - return; - if (!enable && !dig->afmt->enabled) - return; + if (enable) { + WREG32(HDMI_INFOFRAME_CONTROL1 + dig->afmt->offset, + HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ - if (!enable && dig->afmt->pin) { - radeon_audio_enable(rdev, dig->afmt->pin, 0); - dig->afmt->pin = NULL; + WREG32(HDMI_AUDIO_PACKET_CONTROL + dig->afmt->offset, + HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ + HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ + + WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, + HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ + HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ + } else { + WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, 0); } dig->afmt->enabled = enable; @@ -425,33 +418,28 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id); } -void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable) +void evergreen_dp_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - uint32_t offset; if (!dig || !dig->afmt) return; - offset = dig->afmt->offset; - if (enable) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; uint32_t val; - if (dig->afmt->enabled) - return; - - WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); + WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset, + EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); if (radeon_connector->con_priv) { dig_connector = radeon_connector->con_priv; - val = RREG32(EVERGREEN_DP_SEC_AUD_N + offset); + val = RREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset); val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf); if (dig_connector->dp_clock == 162000) @@ -459,21 +447,16 @@ void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable) else val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5); - WREG32(EVERGREEN_DP_SEC_AUD_N + offset, val); + WREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset, val); } - WREG32(EVERGREEN_DP_SEC_CNTL + offset, + WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */ EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */ EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */ EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */ - radeon_audio_enable(rdev, dig->afmt->pin, 0xf); } else { - if (!dig->afmt->enabled) - return; - - WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0); - radeon_audio_enable(rdev, dig->afmt->pin, 0); + WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0); } dig->afmt->enabled = enable; diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 62c91ed669ce..dd6606b8e23c 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -476,17 +476,6 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!dig || !dig->afmt) return; - /* Silent, r600_hdmi_enable will raise WARN for us */ - if (enable && dig->afmt->enabled) - return; - if (!enable && !dig->afmt->enabled) - return; - - if (!enable && dig->afmt->pin) { - radeon_audio_enable(rdev, dig->afmt->pin, 0); - dig->afmt->pin = NULL; - } - /* Older chipsets require setting HDMI and routing manually */ if (!ASIC_IS_DCE3(rdev)) { if (enable) diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index a3ceef6d9632..e4bb81245b9b 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -101,8 +101,8 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode); void r600_hdmi_enable(struct drm_encoder *encoder, bool enable); void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable); -void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable); -void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable); +void evergreen_dp_enable(struct drm_encoder *encoder, bool enable); +void dce6_dp_enable(struct drm_encoder *encoder, bool enable); static const u32 pin_offsets[7] = { @@ -210,7 +210,7 @@ static struct radeon_audio_funcs dce4_dp_funcs = { .set_avi_packet = evergreen_set_avi_packet, .set_audio_packet = dce4_set_audio_packet, .mode_set = radeon_audio_dp_mode_set, - .dpms = evergreen_enable_dp_audio_packets, + .dpms = evergreen_dp_enable, }; static struct radeon_audio_funcs dce6_hdmi_funcs = { @@ -240,7 +240,7 @@ static struct radeon_audio_funcs dce6_dp_funcs = { .set_avi_packet = evergreen_set_avi_packet, .set_audio_packet = dce4_set_audio_packet, .mode_set = radeon_audio_dp_mode_set, - .dpms = dce6_enable_dp_audio_packets, + .dpms = dce6_dp_enable, }; static void radeon_audio_interface_init(struct radeon_device *rdev) -- cgit v1.2.3 From d3c34d2c73481c39378dd91ec531564bb67a50df Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 10:36:39 -0500 Subject: drm/radeon: assign pin in detect We need the pin from detect on, it's too late in dpms. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index e4bb81245b9b..713949487a66 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -452,7 +452,7 @@ void radeon_audio_enable(struct radeon_device *rdev, } void radeon_audio_detect(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status) { struct radeon_device *rdev; struct radeon_encoder *radeon_encoder; @@ -483,6 +483,7 @@ void radeon_audio_detect(struct drm_connector *connector, else radeon_encoder->audio = rdev->audio.hdmi_funcs; + dig->afmt->pin = radeon_audio_get_pin(connector->encoder); radeon_audio_write_speaker_allocation(connector->encoder); radeon_audio_write_sad_regs(connector->encoder); if (connector->encoder->crtc) @@ -491,6 +492,7 @@ void radeon_audio_detect(struct drm_connector *connector, radeon_audio_enable(rdev, dig->afmt->pin, 0xf); } else { radeon_audio_enable(rdev, dig->afmt->pin, 0); + dig->afmt->pin = NULL; } } @@ -704,7 +706,6 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, return; /* disable audio prior to setting up hw */ - dig->afmt->pin = radeon_audio_get_pin(encoder); radeon_audio_enable(rdev, dig->afmt->pin, 0); radeon_audio_set_dto(encoder, mode->clock); @@ -734,7 +735,6 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, return; /* disable audio prior to setting up hw */ - dig->afmt->pin = radeon_audio_get_pin(encoder); radeon_audio_enable(rdev, dig->afmt->pin, 0); radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); -- cgit v1.2.3 From 88af339f9fe285cb93c264adc75545a3d3b50470 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 10:38:40 -0500 Subject: drm/radeon/audio: set mute around state setup To avoid possible sound artifacts while setting up audio. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_audio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 713949487a66..5b579582175b 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -705,13 +705,13 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, if (!dig || !dig->afmt) return; + radeon_audio_set_mute(encoder, true); /* disable audio prior to setting up hw */ radeon_audio_enable(rdev, dig->afmt->pin, 0); radeon_audio_set_dto(encoder, mode->clock); radeon_audio_set_vbi_packet(encoder); radeon_hdmi_set_color_depth(encoder); - radeon_audio_set_mute(encoder, false); radeon_audio_update_acr(encoder, mode->clock); radeon_audio_set_audio_packet(encoder); radeon_audio_select_pin(encoder); @@ -721,6 +721,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, /* enable audio after to setting up hw */ radeon_audio_enable(rdev, dig->afmt->pin, 0xf); + radeon_audio_set_mute(encoder, false); } static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, -- cgit v1.2.3 From 3ed7ceeabf4d6a6df02121cc7e4b46d39501b6e9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 10:42:21 -0500 Subject: drm/radeon: don't toggle audio state in modeset Should be done only at detect time to avoid spurious state changes on the audio side. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_audio.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 5b579582175b..c16191975916 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -696,9 +696,8 @@ static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute) * update the info frames with the data from the current display mode */ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + struct drm_display_mode *mode) { - struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; @@ -706,8 +705,6 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, return; radeon_audio_set_mute(encoder, true); - /* disable audio prior to setting up hw */ - radeon_audio_enable(rdev, dig->afmt->pin, 0); radeon_audio_set_dto(encoder, mode->clock); radeon_audio_set_vbi_packet(encoder); @@ -719,8 +716,6 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, if (radeon_audio_set_avi_packet(encoder, mode) < 0) return; - /* enable audio after to setting up hw */ - radeon_audio_enable(rdev, dig->afmt->pin, 0xf); radeon_audio_set_mute(encoder, false); } @@ -735,18 +730,12 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, if (!dig || !dig->afmt) return; - /* disable audio prior to setting up hw */ - radeon_audio_enable(rdev, dig->afmt->pin, 0); - radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); radeon_audio_set_audio_packet(encoder); radeon_audio_select_pin(encoder); if (radeon_audio_set_avi_packet(encoder, mode) < 0) return; - - /* enable audio after to setting up hw */ - radeon_audio_enable(rdev, dig->afmt->pin, 0xf); } void radeon_audio_mode_set(struct drm_encoder *encoder, -- cgit v1.2.3 From b20932dd62f77a96124ec8f0c7ad0908b5584526 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 10:51:40 -0500 Subject: drm/radeon/audio: update EDID derived fields in modeset We don't necessarily have an EDID at this point when audio detect gets called. Ideally we'd update these fields in detect, but that requires a larger rework of the display detect code. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_audio.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index c16191975916..31de59271007 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -484,11 +484,6 @@ void radeon_audio_detect(struct drm_connector *connector, radeon_encoder->audio = rdev->audio.hdmi_funcs; dig->afmt->pin = radeon_audio_get_pin(connector->encoder); - radeon_audio_write_speaker_allocation(connector->encoder); - radeon_audio_write_sad_regs(connector->encoder); - if (connector->encoder->crtc) - radeon_audio_write_latency_fields(connector->encoder, - &connector->encoder->crtc->mode); radeon_audio_enable(rdev, dig->afmt->pin, 0xf); } else { radeon_audio_enable(rdev, dig->afmt->pin, 0); @@ -706,6 +701,9 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, radeon_audio_set_mute(encoder, true); + radeon_audio_write_speaker_allocation(encoder); + radeon_audio_write_sad_regs(encoder); + radeon_audio_write_latency_fields(encoder, mode); radeon_audio_set_dto(encoder, mode->clock); radeon_audio_set_vbi_packet(encoder); radeon_hdmi_set_color_depth(encoder); @@ -730,6 +728,9 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, if (!dig || !dig->afmt) return; + radeon_audio_write_speaker_allocation(encoder); + radeon_audio_write_sad_regs(encoder); + radeon_audio_write_latency_fields(encoder, mode); radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); radeon_audio_set_audio_packet(encoder); radeon_audio_select_pin(encoder); -- cgit v1.2.3 From aeefd07e90e277f9ac5c242c8b2e6797373021a3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 14:43:47 -0500 Subject: drm/radeon: properly set dto for dp on DCE4/5 If DCPLL or ext PLL is used, use the disp clk. If PPLL is used, use the dp clock. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 4 ++-- drivers/gpu/drm/radeon/radeon_audio.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index bdf2ca8b0be4..c18d4ecbd95d 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -272,7 +272,7 @@ void dce4_hdmi_audio_set_dto(struct radeon_device *rdev, } void dce4_dp_audio_set_dto(struct radeon_device *rdev, - struct radeon_crtc *crtc, unsigned int clock) + struct radeon_crtc *crtc, unsigned int clock) { u32 value; @@ -294,7 +294,7 @@ void dce4_dp_audio_set_dto(struct radeon_device *rdev, * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); - WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10); + WREG32(DCCG_AUDIO_DTO1_MODULE, clock); } void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset) diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 31de59271007..b21ef69a34ac 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -724,6 +724,10 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; if (!dig || !dig->afmt) return; @@ -731,7 +735,10 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, radeon_audio_write_speaker_allocation(encoder); radeon_audio_write_sad_regs(encoder); radeon_audio_write_latency_fields(encoder, mode); - radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); + if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) + radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); + else + radeon_audio_set_dto(encoder, dig_connector->dp_clock); radeon_audio_set_audio_packet(encoder); radeon_audio_select_pin(encoder); -- cgit v1.2.3 From 5c046a57a5ecca7950943625a0cf5adfc601e861 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Feb 2015 17:26:53 -0500 Subject: drm/radeon: adjust audio callback order - Move it out of the UNIPHY case to handle older DCE blocks. - set audio dpms before video dpms Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_encoders.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 7fe7b749e182..c39c1d0d9d4e 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1626,7 +1626,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; bool travis_quirk = false; - int encoder_mode; if (connector) { radeon_connector = to_radeon_connector(connector); @@ -1722,13 +1721,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) } break; } - - encoder_mode = atombios_get_encoder_mode(encoder); - if (connector && (radeon_audio != 0) && - ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || - (ENCODER_MODE_IS_DP(encoder_mode) && - drm_detect_monitor_audio(radeon_connector_edid(connector))))) - radeon_audio_dpms(encoder, mode); } static void @@ -1737,10 +1729,19 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + int encoder_mode = atombios_get_encoder_mode(encoder); DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", radeon_encoder->encoder_id, mode, radeon_encoder->devices, radeon_encoder->active_device); + + if (connector && (radeon_audio != 0) && + ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || + (ENCODER_MODE_IS_DP(encoder_mode) && + drm_detect_monitor_audio(radeon_connector_edid(connector))))) + radeon_audio_dpms(encoder, mode); + switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: @@ -2170,12 +2171,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: /* handled in dpms */ - encoder_mode = atombios_get_encoder_mode(encoder); - if (connector && (radeon_audio != 0) && - ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || - (ENCODER_MODE_IS_DP(encoder_mode) && - drm_detect_monitor_audio(radeon_connector_edid(connector))))) - radeon_audio_mode_set(encoder, adjusted_mode); break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -2197,6 +2192,13 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, } atombios_apply_encoder_quirks(encoder, adjusted_mode); + + encoder_mode = atombios_get_encoder_mode(encoder); + if (connector && (radeon_audio != 0) && + ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || + (ENCODER_MODE_IS_DP(encoder_mode) && + drm_detect_monitor_audio(radeon_connector_edid(connector))))) + radeon_audio_mode_set(encoder, adjusted_mode); } static bool -- cgit v1.2.3 From b983a8f45898245c432afcfd7cf1bb34c5c4e577 Mon Sep 17 00:00:00 2001 From: Slava Grigorev Date: Mon, 2 Mar 2015 11:31:07 -0500 Subject: radeon/audio: fix whitespace Use proper tabs. Signed-off-by: Slava Grigorev Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/dce6_afmt.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 9de14cfc0e80..81a4f5405cd5 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -252,40 +252,40 @@ void dce6_audio_enable(struct radeon_device *rdev, void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, struct radeon_crtc *crtc, unsigned int clock) { - /* Two dtos; generally use dto0 for HDMI */ + /* Two dtos; generally use dto0 for HDMI */ u32 value = 0; - if (crtc) + if (crtc) value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); WREG32(DCCG_AUDIO_DTO_SOURCE, value); - /* Express [24MHz / target pixel clock] as an exact rational - * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE - * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator - */ - WREG32(DCCG_AUDIO_DTO0_PHASE, 24000); - WREG32(DCCG_AUDIO_DTO0_MODULE, clock); + /* Express [24MHz / target pixel clock] as an exact rational + * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE + * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator + */ + WREG32(DCCG_AUDIO_DTO0_PHASE, 24000); + WREG32(DCCG_AUDIO_DTO0_MODULE, clock); } void dce6_dp_audio_set_dto(struct radeon_device *rdev, struct radeon_crtc *crtc, unsigned int clock) { - /* Two dtos; generally use dto1 for DP */ + /* Two dtos; generally use dto1 for DP */ u32 value = 0; value |= DCCG_AUDIO_DTO_SEL; - if (crtc) + if (crtc) value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); WREG32(DCCG_AUDIO_DTO_SOURCE, value); - /* Express [24MHz / target pixel clock] as an exact rational - * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE - * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator - */ - WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); - WREG32(DCCG_AUDIO_DTO1_MODULE, clock); + /* Express [24MHz / target pixel clock] as an exact rational + * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE + * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator + */ + WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); + WREG32(DCCG_AUDIO_DTO1_MODULE, clock); } void dce6_dp_enable(struct drm_encoder *encoder, bool enable) -- cgit v1.2.3 From 2afa3265b21ada7583bf4a69defe4539ad4df7cf Mon Sep 17 00:00:00 2001 From: Slava Grigorev Date: Mon, 2 Mar 2015 12:05:29 -0500 Subject: radeon/audio: fix DP audio on DCE6 Split DCE6 and DCE8 programming of DCCG_AUDIO_DTO1 registers to properly enable DP audio for both DCE revisions. Signed-off-by: Slava Grigorev Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/dce6_afmt.c | 12 ++++++++++-- drivers/gpu/drm/radeon/sid.h | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 81a4f5405cd5..3adc2afe32aa 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -26,6 +26,9 @@ #include "radeon_audio.h" #include "sid.h" +#define DCE8_DCCG_AUDIO_DTO1_PHASE 0x05b8 +#define DCE8_DCCG_AUDIO_DTO1_MODULE 0x05bc + u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 block_offset, u32 reg) { @@ -284,8 +287,13 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev, * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ - WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); - WREG32(DCCG_AUDIO_DTO1_MODULE, clock); + if (ASIC_IS_DCE8(rdev)) { + WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000); + WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock); + } else { + WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); + WREG32(DCCG_AUDIO_DTO1_MODULE, clock); + } } void dce6_dp_enable(struct drm_encoder *encoder, bool enable) diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index c27118cab16a..99a9835c9f61 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -912,8 +912,8 @@ #define DCCG_AUDIO_DTO0_PHASE 0x05b0 #define DCCG_AUDIO_DTO0_MODULE 0x05b4 -#define DCCG_AUDIO_DTO1_PHASE 0x05b8 -#define DCCG_AUDIO_DTO1_MODULE 0x05bc +#define DCCG_AUDIO_DTO1_PHASE 0x05c0 +#define DCCG_AUDIO_DTO1_MODULE 0x05c4 #define AFMT_AUDIO_SRC_CONTROL 0x713c #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) -- cgit v1.2.3 From f957063fee6392bb9365370db6db74dc0b2dce0a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:36:26 -0500 Subject: drm/radeon: do a posting read in r100_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/r100.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 279801ca5110..04f2514f7564 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -728,6 +728,10 @@ int r100_irq_set(struct radeon_device *rdev) tmp |= RADEON_FP2_DETECT_MASK; } WREG32(RADEON_GEN_INT_CNTL, tmp); + + /* read back to post the write */ + RREG32(RADEON_GEN_INT_CNTL); + return 0; } -- cgit v1.2.3 From 54acf107e4e66d1f4a697e08a7f60dba9fcf07c3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:39:56 -0500 Subject: drm/radeon: do a posting read in rs600_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/rs600.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index d81182ad53ec..97a904835759 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -694,6 +694,10 @@ int rs600_irq_set(struct radeon_device *rdev) WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); if (ASIC_IS_DCE2(rdev)) WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); + + /* posting read */ + RREG32(R_000040_GEN_INT_CNTL); + return 0; } -- cgit v1.2.3 From 9d1393f23d5656cdd5f368efd60694d4aeed81d3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:41:31 -0500 Subject: drm/radeon: do a posting read in r600_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/r600.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 07a71a2488c9..2fcad344492f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3784,6 +3784,9 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(RV770_CG_THERMAL_INT, thermal_int); } + /* posting read */ + RREG32(R_000E50_SRBM_STATUS); + return 0; } -- cgit v1.2.3 From c320bb5f6dc0cb88a811cbaf839303e0a3916a92 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:42:53 -0500 Subject: drm/radeon: do a posting read in evergreen_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 4c0e24b3bb90..973df064c14f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4593,6 +4593,9 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); + /* posting read */ + RREG32(SRBM_STATUS); + return 0; } -- cgit v1.2.3 From 0586915ec10d0ae60de5cd3381ad25a704760402 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:43:53 -0500 Subject: drm/radeon: do a posting read in si_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index bcf516a8a2f1..e088e5558da0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6203,6 +6203,9 @@ int si_irq_set(struct radeon_device *rdev) WREG32(CG_THERMAL_INT, thermal_int); + /* posting read */ + RREG32(SRBM_STATUS); + return 0; } -- cgit v1.2.3 From cffefd9bb31cd35ab745d3b49005d10616d25bdc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Mar 2015 20:45:24 -0500 Subject: drm/radeon: do a posting read in cik_set_irq To make sure the writes go through the pci bridge. bug: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/cik.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0c993da9c8fb..3e670d344a20 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7555,6 +7555,9 @@ int cik_irq_set(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); + /* posting read */ + RREG32(SRBM_STATUS); + return 0; } -- cgit v1.2.3 From a28b2a47edcd0cb7c051b445f71a426000394606 Mon Sep 17 00:00:00 2001 From: Tommi Rantala Date: Mon, 2 Mar 2015 21:36:07 +0200 Subject: drm/radeon: fix DRM_IOCTL_RADEON_CS oops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing zeroed drm_radeon_cs struct to DRM_IOCTL_RADEON_CS produces the following oops. Fix by always calling INIT_LIST_HEAD() to avoid the crash in list_sort(). ---------------------------------- #include #include #include #include #include static const struct drm_radeon_cs cs; int main(int argc, char **argv) { return ioctl(open(argv[1], O_RDWR), DRM_IOCTL_RADEON_CS, &cs); } ---------------------------------- [ttrantal@test2 ~]$ ./main /dev/dri/card0 [ 46.904650] BUG: unable to handle kernel NULL pointer dereference at (null) [ 46.905022] IP: [] list_sort+0x42/0x240 [ 46.905022] PGD 68f29067 PUD 688b5067 PMD 0 [ 46.905022] Oops: 0002 [#1] SMP [ 46.905022] CPU: 0 PID: 2413 Comm: main Not tainted 4.0.0-rc1+ #58 [ 46.905022] Hardware name: Hewlett-Packard HP Compaq dc5750 Small Form Factor/0A64h, BIOS 786E3 v02.10 01/25/2007 [ 46.905022] task: ffff880058e2bcc0 ti: ffff880058e64000 task.ti: ffff880058e64000 [ 46.905022] RIP: 0010:[] [] list_sort+0x42/0x240 [ 46.905022] RSP: 0018:ffff880058e67998 EFLAGS: 00010246 [ 46.905022] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 46.905022] RDX: ffffffff81644410 RSI: ffff880058e67b40 RDI: ffff880058e67a58 [ 46.905022] RBP: ffff880058e67a88 R08: 0000000000000000 R09: 0000000000000000 [ 46.905022] R10: ffff880058e2bcc0 R11: ffffffff828e6ca0 R12: ffffffff81644410 [ 46.905022] R13: ffff8800694b8018 R14: 0000000000000000 R15: ffff880058e679b0 [ 46.905022] FS: 00007fdc65a65700(0000) GS:ffff88006d600000(0000) knlGS:0000000000000000 [ 46.905022] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 46.905022] CR2: 0000000000000000 CR3: 0000000058dd9000 CR4: 00000000000006f0 [ 46.905022] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 46.905022] DR3: 0000000000000000 DR6: 00000000ffff4ff0 DR7: 0000000000000400 [ 46.905022] Stack: [ 46.905022] ffff880058e67b40 ffff880058e2bcc0 ffff880058e67a78 0000000000000000 [ 46.905022] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 46.905022] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 46.905022] Call Trace: [ 46.905022] [] radeon_cs_parser_fini+0x195/0x220 [ 46.905022] [] radeon_cs_ioctl+0xa9/0x960 [ 46.905022] [] drm_ioctl+0x19c/0x640 [ 46.905022] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 46.905022] [] ? trace_hardirqs_on+0xd/0x10 [ 46.905022] [] radeon_drm_ioctl+0x46/0x80 [ 46.905022] [] do_vfs_ioctl+0x318/0x570 [ 46.905022] [] ? selinux_file_ioctl+0x56/0x110 [ 46.905022] [] SyS_ioctl+0x81/0xa0 [ 46.905022] [] system_call_fastpath+0x12/0x17 [ 46.905022] Code: 48 89 b5 10 ff ff ff 0f 84 03 01 00 00 4c 8d bd 28 ff ff ff 31 c0 48 89 fb b9 15 00 00 00 49 89 d4 4c 89 ff f3 48 ab 48 8b 46 08 <48> c7 00 00 00 00 00 48 8b 0e 48 85 c9 0f 84 7d 00 00 00 c7 85 [ 46.905022] RIP [] list_sort+0x42/0x240 [ 46.905022] RSP [ 46.905022] CR2: 0000000000000000 [ 47.149253] ---[ end trace 09576b4e8b2c20b8 ]--- Reviewed-by: Christian König Signed-off-by: Tommi Rantala Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_cs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index a579ed379f20..4d0f96cc3da4 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -256,11 +256,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) u32 ring = RADEON_CS_RING_GFX; s32 priority = 0; + INIT_LIST_HEAD(&p->validated); + if (!cs->num_chunks) { return 0; } + /* get chunks */ - INIT_LIST_HEAD(&p->validated); p->idx = 0; p->ib.sa_bo = NULL; p->const_ib.sa_bo = NULL; -- cgit v1.2.3 From 77ae5f4b48a0445426c9c1ef7c0f28b717e35d55 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 3 Mar 2015 17:00:43 -0500 Subject: drm/radeon: fix interlaced modes on DCE8 Need to double the viewport height. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index ed644a4f6f57..86807ee91bd1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1405,6 +1405,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, (x << 16) | y); viewport_w = crtc->mode.hdisplay; viewport_h = (crtc->mode.vdisplay + 1) & ~1; + if ((rdev->family >= CHIP_BONAIRE) && + (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)) + viewport_h *= 2; WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (viewport_w << 16) | viewport_h); -- cgit v1.2.3 From 54fc7c1c961cb39edfe31f8a3f5ba6414e134b37 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 26 Feb 2015 15:53:02 +0000 Subject: drm/i915: Check for driver readyness before handling an underrun interrupt When we takeover from the BIOS and install our interrupt handler, the BIOS may have left us a few surprises in the form of spontaneous interrupts. (This is especially likely on hardware like 965gm where display fifo underruns are continuous and the GMCH cannot filter that interrupt souce.) As we enable our IRQ early so that we can use it during hardware probing, our interrupt handler must be prepared to handle a few sources prior to being fully configured. As such, we need to add a simple is-ready check prior to dereferencing our KMS state for reporting underruns. Reported-by: Rob Clark Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1193972 Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Cc: stable@vger.kernel.org [Jani: dropped the extra !] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_fifo_underrun.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 04e248dd2259..54daa66c6970 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -282,16 +282,6 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, return ret; } -static bool -__cpu_fifo_underrun_reporting_enabled(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - return !intel_crtc->cpu_fifo_underrun_disabled; -} - /** * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state * @dev_priv: i915 device instance @@ -352,9 +342,15 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + /* We may be called too early in init, thanks BIOS! */ + if (crtc == NULL) + return; + /* GMCH can't disable fifo underruns, filter them. */ if (HAS_GMCH_DISPLAY(dev_priv->dev) && - !__cpu_fifo_underrun_reporting_enabled(dev_priv, pipe)) + to_intel_crtc(crtc)->cpu_fifo_underrun_disabled) return; if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) -- cgit v1.2.3 From ab3be73fa7b43f4c3648ce29b5fd649ea54d3adb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 2 Mar 2015 13:04:41 +0200 Subject: drm/i915: gen4: work around hang during hibernation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bjørn reported that his machine hang during hibernation and eventually bisected the problem to the following commit: commit da2bc1b9db3351addd293e5b82757efe1f77ed1d Author: Imre Deak Date: Thu Oct 23 19:23:26 2014 +0300 drm/i915: add poweroff_late handler The problem seems to be that after the kernel puts the device into D3 the BIOS still tries to access it, or otherwise assumes that it's in D0. This is clearly bogus, since ACPI mandates that devices are put into D3 by the OSPM if they are not wake-up sources. In the future we want to unify more of the driver's runtime and system suspend paths, for example by skipping all the system suspend/hibernation hooks if the device is runtime suspended already. Accordingly for all other platforms the goal is still to properly power down the device during hibernation. v2: - Another GEN4 Lenovo laptop had the same issue, while platforms from other vendors (including mobile and desktop, GEN4 and non-GEN4) seem to work fine. Based on this apply the workaround on all GEN4 Lenovo platforms. - add code comment about failing platforms (Ville) Reference: http://lists.freedesktop.org/archives/intel-gfx/2015-February/060633.html Reported-and-bisected-by: Bjørn Mork Cc: stable@vger.kernel.org # v3.19 Signed-off-by: Imre Deak Acked-by: Daniel Vetter Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8039cec71fc2..cc6ea53d2b81 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -622,7 +622,7 @@ static int i915_drm_suspend(struct drm_device *dev) return 0; } -static int i915_drm_suspend_late(struct drm_device *drm_dev) +static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) { struct drm_i915_private *dev_priv = drm_dev->dev_private; int ret; @@ -636,7 +636,17 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev) } pci_disable_device(drm_dev->pdev); - pci_set_power_state(drm_dev->pdev, PCI_D3hot); + /* + * During hibernation on some GEN4 platforms the BIOS may try to access + * the device even though it's already in D3 and hang the machine. So + * leave the device in D0 on those platforms and hope the BIOS will + * power down the device properly. Platforms where this was seen: + * Lenovo Thinkpad X301, X61s + */ + if (!(hibernation && + drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO && + INTEL_INFO(dev_priv)->gen == 4)) + pci_set_power_state(drm_dev->pdev, PCI_D3hot); return 0; } @@ -662,7 +672,7 @@ int i915_suspend_legacy(struct drm_device *dev, pm_message_t state) if (error) return error; - return i915_drm_suspend_late(dev); + return i915_drm_suspend_late(dev, false); } static int i915_drm_resume(struct drm_device *dev) @@ -950,7 +960,17 @@ static int i915_pm_suspend_late(struct device *dev) if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_suspend_late(drm_dev); + return i915_drm_suspend_late(drm_dev, false); +} + +static int i915_pm_poweroff_late(struct device *dev) +{ + struct drm_device *drm_dev = dev_to_i915(dev)->dev; + + if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + + return i915_drm_suspend_late(drm_dev, true); } static int i915_pm_resume_early(struct device *dev) @@ -1520,7 +1540,7 @@ static const struct dev_pm_ops i915_pm_ops = { .thaw_early = i915_pm_resume_early, .thaw = i915_pm_resume, .poweroff = i915_pm_suspend, - .poweroff_late = i915_pm_suspend_late, + .poweroff_late = i915_pm_poweroff_late, .restore_early = i915_pm_resume_early, .restore = i915_pm_resume, -- cgit v1.2.3 From 440fd5283a87345cdd4237bdf45fb01130ea0056 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 23 Jan 2015 09:05:06 +0100 Subject: drm/mm: Support 4 GiB and larger ranges The current implementation is limited by the number of addresses that fit into an unsigned long. This causes problems on 32-bit Tegra where unsigned long is 32-bit but drm_mm is used to manage an IOVA space of 4 GiB. Given the 32-bit limitation, the range is limited to 4 GiB - 1 (or 4 GiB - 4 KiB for page granularity). This commit changes the start and size of the range to be an unsigned 64-bit integer, thus allowing much larger ranges to be supported. [airlied: fix i915 warnings and coloring callback] Signed-off-by: Thierry Reding Reviewed-by: Alex Deucher Reviewed-by: Chris Wilson Signed-off-by: Dave Airlie fixupo --- drivers/gpu/drm/drm_mm.c | 152 +++++++++++++++++++----------------- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +- 3 files changed, 84 insertions(+), 78 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 04a209e2b66d..7fc6f8bd4821 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -91,29 +91,29 @@ */ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color, enum drm_mm_search_flags flags); static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color, - unsigned long start, - unsigned long end, + u64 start, + u64 end, enum drm_mm_search_flags flags); static void drm_mm_insert_helper(struct drm_mm_node *hole_node, struct drm_mm_node *node, - unsigned long size, unsigned alignment, + u64 size, unsigned alignment, unsigned long color, enum drm_mm_allocator_flags flags) { struct drm_mm *mm = hole_node->mm; - unsigned long hole_start = drm_mm_hole_node_start(hole_node); - unsigned long hole_end = drm_mm_hole_node_end(hole_node); - unsigned long adj_start = hole_start; - unsigned long adj_end = hole_end; + u64 hole_start = drm_mm_hole_node_start(hole_node); + u64 hole_end = drm_mm_hole_node_end(hole_node); + u64 adj_start = hole_start; + u64 adj_end = hole_end; BUG_ON(node->allocated); @@ -124,12 +124,15 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, adj_start = adj_end - size; if (alignment) { - unsigned tmp = adj_start % alignment; - if (tmp) { + u64 tmp = adj_start; + unsigned rem; + + rem = do_div(tmp, alignment); + if (rem) { if (flags & DRM_MM_CREATE_TOP) - adj_start -= tmp; + adj_start -= rem; else - adj_start += alignment - tmp; + adj_start += alignment - rem; } } @@ -176,9 +179,9 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) { struct drm_mm_node *hole; - unsigned long end = node->start + node->size; - unsigned long hole_start; - unsigned long hole_end; + u64 end = node->start + node->size; + u64 hole_start; + u64 hole_end; BUG_ON(node == NULL); @@ -227,7 +230,7 @@ EXPORT_SYMBOL(drm_mm_reserve_node); * 0 on success, -ENOSPC if there's no suitable hole. */ int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, - unsigned long size, unsigned alignment, + u64 size, unsigned alignment, unsigned long color, enum drm_mm_search_flags sflags, enum drm_mm_allocator_flags aflags) @@ -246,16 +249,16 @@ EXPORT_SYMBOL(drm_mm_insert_node_generic); static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, struct drm_mm_node *node, - unsigned long size, unsigned alignment, + u64 size, unsigned alignment, unsigned long color, - unsigned long start, unsigned long end, + u64 start, u64 end, enum drm_mm_allocator_flags flags) { struct drm_mm *mm = hole_node->mm; - unsigned long hole_start = drm_mm_hole_node_start(hole_node); - unsigned long hole_end = drm_mm_hole_node_end(hole_node); - unsigned long adj_start = hole_start; - unsigned long adj_end = hole_end; + u64 hole_start = drm_mm_hole_node_start(hole_node); + u64 hole_end = drm_mm_hole_node_end(hole_node); + u64 adj_start = hole_start; + u64 adj_end = hole_end; BUG_ON(!hole_node->hole_follows || node->allocated); @@ -271,12 +274,15 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, mm->color_adjust(hole_node, color, &adj_start, &adj_end); if (alignment) { - unsigned tmp = adj_start % alignment; - if (tmp) { + u64 tmp = adj_start; + unsigned rem; + + rem = do_div(tmp, alignment); + if (rem) { if (flags & DRM_MM_CREATE_TOP) - adj_start -= tmp; + adj_start -= rem; else - adj_start += alignment - tmp; + adj_start += alignment - rem; } } @@ -324,9 +330,9 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, * 0 on success, -ENOSPC if there's no suitable hole. */ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, - unsigned long size, unsigned alignment, + u64 size, unsigned alignment, unsigned long color, - unsigned long start, unsigned long end, + u64 start, u64 end, enum drm_mm_search_flags sflags, enum drm_mm_allocator_flags aflags) { @@ -387,32 +393,34 @@ void drm_mm_remove_node(struct drm_mm_node *node) } EXPORT_SYMBOL(drm_mm_remove_node); -static int check_free_hole(unsigned long start, unsigned long end, - unsigned long size, unsigned alignment) +static int check_free_hole(u64 start, u64 end, u64 size, unsigned alignment) { if (end - start < size) return 0; if (alignment) { - unsigned tmp = start % alignment; + u64 tmp = start; + unsigned rem; + + rem = do_div(tmp, alignment); if (tmp) - start += alignment - tmp; + start += alignment - rem; } return end >= start + size; } static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color, enum drm_mm_search_flags flags) { struct drm_mm_node *entry; struct drm_mm_node *best; - unsigned long adj_start; - unsigned long adj_end; - unsigned long best_size; + u64 adj_start; + u64 adj_end; + u64 best_size; BUG_ON(mm->scanned_blocks); @@ -421,7 +429,7 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, __drm_mm_for_each_hole(entry, mm, adj_start, adj_end, flags & DRM_MM_SEARCH_BELOW) { - unsigned long hole_size = adj_end - adj_start; + u64 hole_size = adj_end - adj_start; if (mm->color_adjust) { mm->color_adjust(entry, color, &adj_start, &adj_end); @@ -445,18 +453,18 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, } static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color, - unsigned long start, - unsigned long end, + u64 start, + u64 end, enum drm_mm_search_flags flags) { struct drm_mm_node *entry; struct drm_mm_node *best; - unsigned long adj_start; - unsigned long adj_end; - unsigned long best_size; + u64 adj_start; + u64 adj_end; + u64 best_size; BUG_ON(mm->scanned_blocks); @@ -465,7 +473,7 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ __drm_mm_for_each_hole(entry, mm, adj_start, adj_end, flags & DRM_MM_SEARCH_BELOW) { - unsigned long hole_size = adj_end - adj_start; + u64 hole_size = adj_end - adj_start; if (adj_start < start) adj_start = start; @@ -561,7 +569,7 @@ EXPORT_SYMBOL(drm_mm_replace_node); * adding/removing nodes to/from the scan list are allowed. */ void drm_mm_init_scan(struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color) { @@ -594,11 +602,11 @@ EXPORT_SYMBOL(drm_mm_init_scan); * adding/removing nodes to/from the scan list are allowed. */ void drm_mm_init_scan_with_range(struct drm_mm *mm, - unsigned long size, + u64 size, unsigned alignment, unsigned long color, - unsigned long start, - unsigned long end) + u64 start, + u64 end) { mm->scan_color = color; mm->scan_alignment = alignment; @@ -627,8 +635,8 @@ bool drm_mm_scan_add_block(struct drm_mm_node *node) { struct drm_mm *mm = node->mm; struct drm_mm_node *prev_node; - unsigned long hole_start, hole_end; - unsigned long adj_start, adj_end; + u64 hole_start, hole_end; + u64 adj_start, adj_end; mm->scanned_blocks++; @@ -731,7 +739,7 @@ EXPORT_SYMBOL(drm_mm_clean); * * Note that @mm must be cleared to 0 before calling this function. */ -void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) +void drm_mm_init(struct drm_mm * mm, u64 start, u64 size) { INIT_LIST_HEAD(&mm->hole_stack); mm->scanned_blocks = 0; @@ -766,18 +774,17 @@ void drm_mm_takedown(struct drm_mm * mm) } EXPORT_SYMBOL(drm_mm_takedown); -static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry, - const char *prefix) +static u64 drm_mm_debug_hole(struct drm_mm_node *entry, + const char *prefix) { - unsigned long hole_start, hole_end, hole_size; + u64 hole_start, hole_end, hole_size; if (entry->hole_follows) { hole_start = drm_mm_hole_node_start(entry); hole_end = drm_mm_hole_node_end(entry); hole_size = hole_end - hole_start; - printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n", - prefix, hole_start, hole_end, - hole_size); + pr_debug("%s %#llx-%#llx: %llu: free\n", prefix, hole_start, + hole_end, hole_size); return hole_size; } @@ -792,35 +799,34 @@ static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry, void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) { struct drm_mm_node *entry; - unsigned long total_used = 0, total_free = 0, total = 0; + u64 total_used = 0, total_free = 0, total = 0; total_free += drm_mm_debug_hole(&mm->head_node, prefix); drm_mm_for_each_node(entry, mm) { - printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n", - prefix, entry->start, entry->start + entry->size, - entry->size); + pr_debug("%s %#llx-%#llx: %llu: used\n", prefix, entry->start, + entry->start + entry->size, entry->size); total_used += entry->size; total_free += drm_mm_debug_hole(entry, prefix); } total = total_free + total_used; - printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total, - total_used, total_free); + pr_debug("%s total: %llu, used %llu free %llu\n", prefix, total, + total_used, total_free); } EXPORT_SYMBOL(drm_mm_debug_table); #if defined(CONFIG_DEBUG_FS) -static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) +static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) { - unsigned long hole_start, hole_end, hole_size; + u64 hole_start, hole_end, hole_size; if (entry->hole_follows) { hole_start = drm_mm_hole_node_start(entry); hole_end = drm_mm_hole_node_end(entry); hole_size = hole_end - hole_start; - seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", - hole_start, hole_end, hole_size); + seq_printf(m, "%#llx-%#llx: %llu: free\n", hole_start, + hole_end, hole_size); return hole_size; } @@ -835,20 +841,20 @@ static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *en int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) { struct drm_mm_node *entry; - unsigned long total_used = 0, total_free = 0, total = 0; + u64 total_used = 0, total_free = 0, total = 0; total_free += drm_mm_dump_hole(m, &mm->head_node); drm_mm_for_each_node(entry, mm) { - seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", - entry->start, entry->start + entry->size, - entry->size); + seq_printf(m, "%#016llx-%#016llx: %llu: used\n", entry->start, + entry->start + entry->size, entry->size); total_used += entry->size; total_free += drm_mm_dump_hole(m, entry); } total = total_free + total_used; - seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free); + seq_printf(m, "total: %llu, used %llu free %llu\n", total, + total_used, total_free); return 0; } EXPORT_SYMBOL(drm_mm_dump_table); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 96e811fe24ca..e8b18e542da4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -152,12 +152,12 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_puts(m, " (pp"); else seq_puts(m, " (g"); - seq_printf(m, "gtt offset: %08lx, size: %08lx, type: %u)", + seq_printf(m, "gtt offset: %08llx, size: %08llx, type: %u)", vma->node.start, vma->node.size, vma->ggtt_view.type); } if (obj->stolen) - seq_printf(m, " (stolen: %08lx)", obj->stolen->start); + seq_printf(m, " (stolen: %08llx)", obj->stolen->start); if (obj->pin_mappable || obj->fault_mappable) { char s[3], *t = s; if (obj->pin_mappable) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 746f77fb57a3..dccdc8aad2e2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1145,7 +1145,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); - DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n", + DRM_DEBUG_DRIVER("Allocated pde space (%lldM) at GTT entry: %llx\n", ppgtt->node.size >> 20, ppgtt->node.start / PAGE_SIZE); @@ -1713,8 +1713,8 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) static void i915_gtt_color_adjust(struct drm_mm_node *node, unsigned long color, - unsigned long *start, - unsigned long *end) + u64 *start, + u64 *end) { if (node->color != color) *start += 4096; -- cgit v1.2.3 From 54c4cd68ed7abd9f245722bee39464d04ddb4cfd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 4 Mar 2015 00:18:38 -0500 Subject: drm/ttm: device address space != CPU address space We need to store device offsets in 64 bit as the device address space may be larger than the CPU's. Fixes GPU init failures on radeons with 4GB or more of vram on 32 bit kernels. We put vram at the start of the GPU's address space so the gart aperture starts at 4 GB causing all GPU addresses in the gart aperture to get truncated. bug: https://bugs.freedesktop.org/show_bug.cgi?id=89072 [airlied: fix warning on nouveau build] Signed-off-by: Alex Deucher Cc: thellstrom@vmware.com Acked-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 79924e4b1b49..6751553abe4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -418,7 +418,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, nouveau_fbcon_zfill(dev, fbcon); /* To allow resizeing without swapping buffers */ - NV_INFO(drm, "allocated %dx%d fb: 0x%lx, bo %p\n", + NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n", nouveau_fb->base.width, nouveau_fb->base.height, nvbo->bo.offset, nvbo); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d395b0bef73b..8d9b7de25613 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -74,7 +74,7 @@ static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type) pr_err(" has_type: %d\n", man->has_type); pr_err(" use_type: %d\n", man->use_type); pr_err(" flags: 0x%08X\n", man->flags); - pr_err(" gpu_offset: 0x%08lX\n", man->gpu_offset); + pr_err(" gpu_offset: 0x%08llX\n", man->gpu_offset); pr_err(" size: %llu\n", man->size); pr_err(" available_caching: 0x%08X\n", man->available_caching); pr_err(" default_caching: 0x%08X\n", man->default_caching); -- cgit v1.2.3 From 5db0f6e880eb99ad400d5f1c646dffc7fd939c78 Mon Sep 17 00:00:00 2001 From: Stephane Viau Date: Fri, 20 Feb 2015 12:40:58 -0500 Subject: drm/msm/mdp5: fixup "drm/msm: fix fallout of atomic dpms changes" Commit 0b776d457b94 ("drm/msm: fix fallout of atomic dpms changes") has a typo in both mdp5_encoder_helper_funcs and mdp5_crtc_helper_funcs definitions: .dpms entry should be replaced by .disable and .enable Also fixed a typo in mdp5_encoder_enable(). Note that these typos are only present for MDP5. MDP4 is fine. Signed-off-by: Stephane Viau Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 46fac545dc2b..946b71b6e608 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -544,8 +544,8 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_fixup = mdp5_crtc_mode_fixup, .mode_set_nofb = mdp5_crtc_mode_set_nofb, - .prepare = mdp5_crtc_disable, - .commit = mdp5_crtc_enable, + .disable = mdp5_crtc_disable, + .enable = mdp5_crtc_enable, .atomic_check = mdp5_crtc_atomic_check, .atomic_begin = mdp5_crtc_atomic_begin, .atomic_flush = mdp5_crtc_atomic_flush, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index d6a14bb99988..af0e02fa4f48 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c @@ -267,14 +267,14 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder) mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); - mdp5_encoder->enabled = false; + mdp5_encoder->enabled = true; } static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { .mode_fixup = mdp5_encoder_mode_fixup, .mode_set = mdp5_encoder_mode_set, - .prepare = mdp5_encoder_disable, - .commit = mdp5_encoder_enable, + .disable = mdp5_encoder_disable, + .enable = mdp5_encoder_enable, }; /* initialize encoder */ -- cgit v1.2.3 From 8a4247d645a3b864e3359a5b60d41dc74a7a7b2a Mon Sep 17 00:00:00 2001 From: Stephane Viau Date: Fri, 20 Feb 2015 16:30:55 -0500 Subject: drm/msm: update generated headers (add 6th lm.base entry) Some target have up to 6 layer mixers (LM). Let the header file access the last LM's base address. Signed-off-by: Stephane Viau Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h index 09b4a25eb553..c276624290af 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h @@ -8,17 +8,9 @@ http://github.com/freedreno/envytools/ git clone https://github.com/freedreno/envytools.git The rules-ng-ng source files this header was generated from are: -- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49) -- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00) +- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml ( 27229 bytes, from 2015-02-10 17:00:41) +- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-06-02 18:31:15) +- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2015-01-23 16:20:19) Copyright (C) 2013-2015 by the following authors: - Rob Clark (robclark) @@ -910,6 +902,7 @@ static inline uint32_t __offset_LM(uint32_t idx) case 2: return (mdp5_cfg->lm.base[2]); case 3: return (mdp5_cfg->lm.base[3]); case 4: return (mdp5_cfg->lm.base[4]); + case 5: return (mdp5_cfg->lm.base[5]); default: return INVALID_IDX(idx); } } -- cgit v1.2.3 From ba0312a6108f5214efb4659c4dbba218c5b9eb8d Mon Sep 17 00:00:00 2001 From: Stephane Viau Date: Fri, 20 Feb 2015 16:30:56 -0500 Subject: drm/msm/mdp5: Avoid flushing registers when CRTC is disabled When a CRTC is disabled, no CTL is allocated to it (CRTC->ctl == NULL); in that case we should not try to FLUSH registers and do nothing instead. This can happen when we try to move a cursor but the CRTC's CTL (CONTROL) has not been allocated yet (inactive CRTC). It can also happens when we .atomic_check()/.atomic_flush() on a disabled CRTC. A CTL needs to be kept as long as the CRTC is alive. Releasing it after the last VBlank is safer than in .atomic_flush(). Signed-off-by: Stephane Viau Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 946b71b6e608..2aeae7351621 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -103,8 +103,8 @@ static void crtc_flush_all(struct drm_crtc *crtc) struct drm_plane *plane; uint32_t flush_mask = 0; - /* we could have already released CTL in the disable path: */ - if (!mdp5_crtc->ctl) + /* this should not happen: */ + if (WARN_ON(!mdp5_crtc->ctl)) return; drm_atomic_crtc_for_each_plane(plane, crtc) { @@ -143,6 +143,11 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) drm_atomic_crtc_for_each_plane(plane, crtc) { mdp5_plane_complete_flip(plane); } + + if (mdp5_crtc->ctl && !crtc->state->enable) { + mdp5_ctl_release(mdp5_crtc->ctl); + mdp5_crtc->ctl = NULL; + } } static void unref_cursor_worker(struct drm_flip_work *work, void *val) @@ -386,14 +391,17 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc) mdp5_crtc->event = crtc->state->event; spin_unlock_irqrestore(&dev->event_lock, flags); + /* + * If no CTL has been allocated in mdp5_crtc_atomic_check(), + * it means we are trying to flush a CRTC whose state is disabled: + * nothing else needs to be done. + */ + if (unlikely(!mdp5_crtc->ctl)) + return; + blend_setup(crtc); crtc_flush_all(crtc); request_pending(crtc, PENDING_FLIP); - - if (mdp5_crtc->ctl && !crtc->state->enable) { - mdp5_ctl_release(mdp5_crtc->ctl); - mdp5_crtc->ctl = NULL; - } } static int mdp5_crtc_set_property(struct drm_crtc *crtc, @@ -495,6 +503,10 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) uint32_t roi_h; unsigned long flags; + /* In case the CRTC is disabled, just drop the cursor update */ + if (unlikely(!crtc->state->enable)) + return 0; + x = (x > 0) ? x : 0; y = (y > 0) ? y : 0; -- cgit v1.2.3 From 5b2e2b6c5e542f7334dcaeb5b577d8328a5f2fc0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 23 Feb 2015 00:58:03 +0200 Subject: drm/msm/atomic: Don't leak atomic commit object when commit fails If the atomic commit fails due to completion wait interruption the atomic commit object is not freed and is thus leaked. Free it. Signed-off-by: Laurent Pinchart Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_atomic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 871aa2108dc6..18fd643b6e69 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -219,8 +219,10 @@ int msm_atomic_commit(struct drm_device *dev, * mark our set of crtc's as busy: */ ret = start_atomic(dev->dev_private, c->crtc_mask); - if (ret) + if (ret) { + kfree(c); return ret; + } /* * This is the point of no return - everything below never fails except -- cgit v1.2.3 From 58560890b3e33d789c4f13a10324af9c85c52308 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 24 Feb 2015 14:47:57 -0500 Subject: drm/msm/mdp5: fix cursor ROI If cursor is set near the edge of the screen, it is not valid to use the new cursor width/height as the ROI dimensions. Split out the ROI calc and use it both cursor_set and cursor_move. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 68 +++++++++++++++++++------------- 1 file changed, 40 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 2aeae7351621..4c4be4344653 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -62,8 +62,8 @@ struct mdp5_crtc { /* current cursor being scanned out: */ struct drm_gem_object *scanout_bo; - uint32_t width; - uint32_t height; + uint32_t width, height; + uint32_t x, y; } cursor; }; #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) @@ -411,6 +411,32 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc, return -EINVAL; } +static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h) +{ + struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); + uint32_t xres = crtc->mode.hdisplay; + uint32_t yres = crtc->mode.vdisplay; + + /* + * Cursor Region Of Interest (ROI) is a plane read from cursor + * buffer to render. The ROI region is determined by the visibility of + * the cursor point. In the default Cursor image the cursor point will + * be at the top left of the cursor image, unless it is specified + * otherwise using hotspot feature. + * + * If the cursor point reaches the right (xres - x < cursor.width) or + * bottom (yres - y < cursor.height) boundary of the screen, then ROI + * width and ROI height need to be evaluated to crop the cursor image + * accordingly. + * (xres-x) will be new cursor width when x > (xres - cursor.width) + * (yres-y) will be new cursor height when y > (yres - cursor.height) + */ + *roi_w = min(mdp5_crtc->cursor.width, xres - + mdp5_crtc->cursor.x); + *roi_h = min(mdp5_crtc->cursor.height, yres - + mdp5_crtc->cursor.y); +} + static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file, uint32_t handle, uint32_t width, uint32_t height) @@ -424,6 +450,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, unsigned int depth; enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); + uint32_t roi_w, roi_h; unsigned long flags; if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { @@ -454,6 +481,12 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); old_bo = mdp5_crtc->cursor.scanout_bo; + mdp5_crtc->cursor.scanout_bo = cursor_bo; + mdp5_crtc->cursor.width = width; + mdp5_crtc->cursor.height = height; + + get_roi(crtc, &roi_w, &roi_h); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); @@ -461,19 +494,15 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), - MDP5_LM_CURSOR_SIZE_ROI_H(height) | - MDP5_LM_CURSOR_SIZE_ROI_W(width)); + MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | + MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); - blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN; blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); - mdp5_crtc->cursor.scanout_bo = cursor_bo; - mdp5_crtc->cursor.width = width; - mdp5_crtc->cursor.height = height; spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true); @@ -497,8 +526,6 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct mdp5_kms *mdp5_kms = get_kms(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); - uint32_t xres = crtc->mode.hdisplay; - uint32_t yres = crtc->mode.vdisplay; uint32_t roi_w; uint32_t roi_h; unsigned long flags; @@ -507,25 +534,10 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) if (unlikely(!crtc->state->enable)) return 0; - x = (x > 0) ? x : 0; - y = (y > 0) ? y : 0; + mdp5_crtc->cursor.x = x = max(x, 0); + mdp5_crtc->cursor.y = y = max(y, 0); - /* - * Cursor Region Of Interest (ROI) is a plane read from cursor - * buffer to render. The ROI region is determined by the visiblity of - * the cursor point. In the default Cursor image the cursor point will - * be at the top left of the cursor image, unless it is specified - * otherwise using hotspot feature. - * - * If the cursor point reaches the right (xres - x < cursor.width) or - * bottom (yres - y < cursor.height) boundary of the screen, then ROI - * width and ROI height need to be evaluated to crop the cursor image - * accordingly. - * (xres-x) will be new cursor width when x > (xres - cursor.width) - * (yres-y) will be new cursor height when y > (yres - cursor.height) - */ - roi_w = min(mdp5_crtc->cursor.width, xres - x); - roi_h = min(mdp5_crtc->cursor.height, yres - y); + get_roi(crtc, &roi_w, &roi_h); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm), -- cgit v1.2.3 From 757fdfaf413c4a85dade5374b6f5c05d541cf32e Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 24 Feb 2015 15:29:37 -0500 Subject: drm/msm/mdp5: fix cursor blending Seems like we just want BLEND_EN and not BLEND_TRANSP_EN (setting the latter results in black pixels in the cursor image treated as transparent). Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 4c4be4344653..2f2863cf8b45 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -499,7 +499,6 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; - blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN; blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); -- cgit v1.2.3 From aa80a4a5190e697a6945849ab36fa7dabca815f3 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 2 Mar 2015 16:19:06 -0500 Subject: drm/msm: kexec fixes In kexec environment, we are more likely to encounter irq's already enabled from previous environment. At which point we find that writes to disable/clear pending irq's are slightly less than useless without first enabling clocks. TODO: full blown state read-in so kexec'd kernel can inherit the mode already setup. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c | 5 +++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c index 8edd531cb621..7369ee7f0c55 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c @@ -32,7 +32,10 @@ static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus) void mdp4_irq_preinstall(struct msm_kms *kms) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); + mdp4_enable(mdp4_kms); mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff); + mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000); + mdp4_disable(mdp4_kms); } int mdp4_irq_postinstall(struct msm_kms *kms) @@ -53,7 +56,9 @@ int mdp4_irq_postinstall(struct msm_kms *kms) void mdp4_irq_uninstall(struct msm_kms *kms) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); + mdp4_enable(mdp4_kms); mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000); + mdp4_disable(mdp4_kms); } irqreturn_t mdp4_irq(struct msm_kms *kms) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c index 70ac81edd40f..a9407105b9b7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c @@ -34,7 +34,10 @@ static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus) void mdp5_irq_preinstall(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + mdp5_enable(mdp5_kms); mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff); + mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000); + mdp5_disable(mdp5_kms); } int mdp5_irq_postinstall(struct msm_kms *kms) @@ -57,7 +60,9 @@ int mdp5_irq_postinstall(struct msm_kms *kms) void mdp5_irq_uninstall(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + mdp5_enable(mdp5_kms); mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000); + mdp5_disable(mdp5_kms); } static void mdp5_irq_mdp(struct mdp_kms *mdp_kms) -- cgit v1.2.3 From 9a6f5130143c17b91e0a3cbf5cc2d8c1e5a80a63 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 25 Feb 2015 13:45:26 +0000 Subject: drm: Don't assign fbs for universal cursor support to files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The internal framebuffers we create to remap legacy cursor ioctls to plane operations for the universal plane support shouldn't be linke to the file like normal userspace framebuffers. This bug goes back to the original universal cursor plane support introduced in commit 161d0dc1dccb17ff7a38f462c7c0d4ef8bcc5662 Author: Matt Roper Date: Tue Jun 10 08:28:10 2014 -0700 drm: Support legacy cursor ioctls via universal planes when possible (v4) The isn't too disastrous since fbs are small, we only create one when the cursor bo gets changed and ultimately they'll be reaped when the window server restarts. Conceptually we'd want to just pass NULL for file_priv when creating it, but the driver needs the file to lookup the underlying buffer object for cursor id. Instead let's move the file_priv linking out of add_framebuffer_internal() into the addfb ioctl implementation, which is the only place it is needed. And also rename the function for a more accurate since it only creates the fb, but doesn't add it anywhere. Signed-off-by: Daniel Vetter (fix & commit msg) Signed-off-by: Chris Wilson (provider of lipstick) Reviewed-by: Matt Roper Cc: Ville Syrjälä Cc: Matt Roper Cc: Rob Clark Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6b6b07ff720b..f6d04c7b5115 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -43,9 +43,10 @@ #include "drm_crtc_internal.h" #include "drm_internal.h" -static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, - struct drm_mode_fb_cmd2 *r, - struct drm_file *file_priv); +static struct drm_framebuffer * +internal_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd2 *r, + struct drm_file *file_priv); /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ @@ -2908,13 +2909,11 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, */ if (req->flags & DRM_MODE_CURSOR_BO) { if (req->handle) { - fb = add_framebuffer_internal(dev, &fbreq, file_priv); + fb = internal_framebuffer_create(dev, &fbreq, file_priv); if (IS_ERR(fb)) { DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); return PTR_ERR(fb); } - - drm_framebuffer_reference(fb); } else { fb = NULL; } @@ -3267,9 +3266,10 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) return 0; } -static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, - struct drm_mode_fb_cmd2 *r, - struct drm_file *file_priv) +static struct drm_framebuffer * +internal_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd2 *r, + struct drm_file *file_priv) { struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; @@ -3301,12 +3301,6 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, return fb; } - mutex_lock(&file_priv->fbs_lock); - r->fb_id = fb->base.id; - list_add(&fb->filp_head, &file_priv->fbs); - DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); - mutex_unlock(&file_priv->fbs_lock); - return fb; } @@ -3328,15 +3322,24 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, int drm_mode_addfb2(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_mode_fb_cmd2 *r = data; struct drm_framebuffer *fb; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - fb = add_framebuffer_internal(dev, data, file_priv); + fb = internal_framebuffer_create(dev, r, file_priv); if (IS_ERR(fb)) return PTR_ERR(fb); + /* Transfer ownership to the filp for reaping on close */ + + DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); + mutex_lock(&file_priv->fbs_lock); + r->fb_id = fb->base.id; + list_add(&fb->filp_head, &file_priv->fbs); + mutex_unlock(&file_priv->fbs_lock); + return 0; } -- cgit v1.2.3 From cd961bb9eebb630452f49dcbf3e5f0059428614a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 28 Jan 2015 10:02:23 +0100 Subject: drm/mst: fix recursive sleep warning on qlock With drm-next, we can get a backtrace from sleeping with mutex detection. this is due to the callback checking the txmsg state taking the mutex, which can cause a sleep inside a sleep, Daniel went over it and was happy we could drop this mutex in this case. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 9a5b68717ec8..379ab4555756 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -733,10 +733,14 @@ static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_sideband_msg_tx *txmsg) { bool ret; - mutex_lock(&mgr->qlock); + + /* + * All updates to txmsg->state are protected by mgr->qlock, and the two + * cases we check here are terminal states. For those the barriers + * provided by the wake_up/wait_event pair are enough. + */ ret = (txmsg->state == DRM_DP_SIDEBAND_TX_RX || txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT); - mutex_unlock(&mgr->qlock); return ret; } @@ -1363,12 +1367,13 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, return 0; } -/* must be called holding qlock */ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr) { struct drm_dp_sideband_msg_tx *txmsg; int ret; + WARN_ON(!mutex_is_locked(&mgr->qlock)); + /* construct a chunk from the first msg in the tx_msg queue */ if (list_empty(&mgr->tx_msg_downq)) { mgr->tx_down_in_progress = false; -- cgit v1.2.3 From 6c51d46f135b00c00373fcd029786ccef2b02b5b Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Fri, 6 Mar 2015 15:34:26 +0000 Subject: drm/i915: use in_interrupt() not in_irq() to check context The kernel in_irq() function tests for hard-IRQ context only, so if a system is run with the kernel 'threadirqs' option selected, the test in intel_check_page_flip() generates lots of warnings, because then it gets called in soft-IRQ context. We can instead use in_interrupt() which allows for either type of interrupt, while still detecting and complaining about misuse of the page flip code if it is ever called from non-interrupt context. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89321 Signed-off-by: Dave Gordon Reviewed-by: Daniel Vetter Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e730789b53b7..9943c20a741d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9716,7 +9716,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - WARN_ON(!in_irq()); + WARN_ON(!in_interrupt()); if (crtc == NULL) return; -- cgit v1.2.3 From 762e45836a047323defe9bdbbac534f0675ff027 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Mar 2015 18:09:26 +0000 Subject: drm/i915: Make WAIT_IOCTL negative timeouts be indefinite again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression from commit 5ed0bdf21a85d78e04f89f15ccf227562177cbd9 Author: Thomas Gleixner Date: Wed Jul 16 21:05:06 2014 +0000 drm: i915: Use nsec based interfaces that made a negative timeout return immediately rather than the previously defined behaviour of waiting indefinitely. Testcase: igt/gem_wait Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89494 Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ben Widawsky Cc: Kristian Høgsberg Cc: stable@vger.kernel.org Reviewed-by: Daniel Vetter [Jani: fixed a checkpatch complaint about whitespace.] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e5daad5f75fb..ac7fe39d38a3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2936,9 +2936,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) req = obj->last_read_req; /* Do this after OLR check to make sure we make forward progress polling - * on this IOCTL with a timeout <=0 (like busy ioctl) + * on this IOCTL with a timeout == 0 (like busy ioctl) */ - if (args->timeout_ns <= 0) { + if (args->timeout_ns == 0) { ret = -ETIME; goto out; } @@ -2948,7 +2948,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); - ret = __i915_wait_request(req, reset_counter, true, &args->timeout_ns, + ret = __i915_wait_request(req, reset_counter, true, + args->timeout_ns > 0 ? &args->timeout_ns : NULL, file->driver_priv); mutex_lock(&dev->struct_mutex); i915_gem_request_unreference(req); -- cgit v1.2.3 From 0cd0caad99a028568dd4a7c1b95777aadf4eb317 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 27 Feb 2015 18:11:09 +0200 Subject: drm/i915: Do both mt and gen6 style forcewake reset on ivb probe commit 05a2fb157e44 ("drm/i915: Consolidate forcewake code") failed to take into account that we have used to reset both the gen6 style and the multithreaded style forcewake registers. This is due to fact that ivb can use either, depending on how the bios has set up the machine. Mimic the old semantics before we have determined the correct variety and reset both before the ecobus probe. Cc: Chris Wilson Cc: Huang Ying Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_uncore.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index c47a3baa53d5..4e8fb891d4ea 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1048,8 +1048,14 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) /* We need to init first for ECOBUS access and then * determine later if we want to reinit, in case of MT access is - * not working + * not working. In this stage we don't know which flavour this + * ivb is, so it is better to reset also the gen6 fw registers + * before the ecobus check. */ + + __raw_i915_write32(dev_priv, FORCEWAKE, 0); + __raw_posting_read(dev_priv, ECOBUS); + fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, FORCEWAKE_MT, FORCEWAKE_MT_ACK); -- cgit v1.2.3 From 5e4f518959bdf8a4f9c8f80879e4a0f7a95d2cb3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Feb 2015 14:35:59 +0000 Subject: drm/i915: Prevent TLB error on first execution on SNB Long ago I found that I was getting sporadic errors when booting SNB, with the symptom being that the first batch died with IPEHR != *ACTHD, typically caused by the TLB being invalid. These magically disappeared if I held the forcewake during the entire ring initialisation sequence. (It can probably be shortened to a short critical section, but the whole initialisation is full of register writes and so we would be taking and releasing forcewake almost continually, and so holding it over the entire sequence will probably be a net win!) Note some of the kernels I encounted the issue already had the deferred forcewake release, so it is still relevant. I know that there have been a few other reports with similar failure conditions on SNB, I think such as References: https://bugs.freedesktop.org/show_bug.cgi?id=80913 v2: Wrap i915_gem_init_hw() with its own security blanket as we take that path following resume and reset. Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ac7fe39d38a3..5b205863b659 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4793,6 +4793,9 @@ i915_gem_init_hw(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) return -EIO; + /* Double layer security blanket, see i915_gem_init() */ + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + if (dev_priv->ellc_size) I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); @@ -4825,7 +4828,7 @@ i915_gem_init_hw(struct drm_device *dev) for_each_ring(ring, dev_priv, i) { ret = ring->init_hw(ring); if (ret) - return ret; + goto out; } for (i = 0; i < NUM_L3_SLICES(dev); i++) @@ -4842,9 +4845,11 @@ i915_gem_init_hw(struct drm_device *dev) DRM_ERROR("Context enable failed %d\n", ret); i915_gem_cleanup_ringbuffer(dev); - return ret; + goto out; } +out: + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return ret; } @@ -4878,6 +4883,14 @@ int i915_gem_init(struct drm_device *dev) dev_priv->gt.stop_ring = intel_logical_ring_stop; } + /* This is just a security blanket to placate dragons. + * On some systems, we very sporadically observe that the first TLBs + * used by the CS may be stale, despite us poking the TLB reset. If + * we hold the forcewake during initialisation these problems + * just magically go away. + */ + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + ret = i915_gem_init_userptr(dev); if (ret) goto out_unlock; @@ -4904,6 +4917,7 @@ int i915_gem_init(struct drm_device *dev) } out_unlock: + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); return ret; -- cgit v1.2.3 From b6610101718d4ab90d793c482625e98eb1262cad Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 3 Mar 2015 09:56:42 +0100 Subject: drm/radeon: fix wait to actually occur after the signaling callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A normal wait adds to the front of the tail. By doing something similar to fence_default_wait the fence code can run without racing. This is a complete fix for "panic on suspend from KDE with radeon", and a partial fix for "Radeon: System pauses on TAHITI". On tahiti si_irq_set needs to be fixed too, to completely flush the writes before radeon_fence_activity is called in radeon_fence_enable_signaling. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=90741 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=90861 Signed-off-by: Maarten Lankhorst Reported-by: Jon Arne Jørgensen Reported-and-tested-by: Gustaw Smolarczyk Cc: stable@vger.kernel.org (v3.18+) Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fence.c | 68 +++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index d13d1b5a859f..df09ca7c4889 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -1030,37 +1030,59 @@ static inline bool radeon_test_signaled(struct radeon_fence *fence) return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags); } +struct radeon_wait_cb { + struct fence_cb base; + struct task_struct *task; +}; + +static void +radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb) +{ + struct radeon_wait_cb *wait = + container_of(cb, struct radeon_wait_cb, base); + + wake_up_process(wait->task); +} + static signed long radeon_fence_default_wait(struct fence *f, bool intr, signed long t) { struct radeon_fence *fence = to_radeon_fence(f); struct radeon_device *rdev = fence->rdev; - bool signaled; + struct radeon_wait_cb cb; - fence_enable_sw_signaling(&fence->base); + cb.task = current; - /* - * This function has to return -EDEADLK, but cannot hold - * exclusive_lock during the wait because some callers - * may already hold it. This means checking needs_reset without - * lock, and not fiddling with any gpu internals. - * - * The callback installed with fence_enable_sw_signaling will - * run before our wait_event_*timeout call, so we will see - * both the signaled fence and the changes to needs_reset. - */ + if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb)) + return t; + + while (t > 0) { + if (intr) + set_current_state(TASK_INTERRUPTIBLE); + else + set_current_state(TASK_UNINTERRUPTIBLE); + + /* + * radeon_test_signaled must be called after + * set_current_state to prevent a race with wake_up_process + */ + if (radeon_test_signaled(fence)) + break; + + if (rdev->needs_reset) { + t = -EDEADLK; + break; + } + + t = schedule_timeout(t); + + if (t > 0 && intr && signal_pending(current)) + t = -ERESTARTSYS; + } + + __set_current_state(TASK_RUNNING); + fence_remove_callback(f, &cb.base); - if (intr) - t = wait_event_interruptible_timeout(rdev->fence_queue, - ((signaled = radeon_test_signaled(fence)) || - rdev->needs_reset), t); - else - t = wait_event_timeout(rdev->fence_queue, - ((signaled = radeon_test_signaled(fence)) || - rdev->needs_reset), t); - - if (t > 0 && !signaled) - return -EDEADLK; return t; } -- cgit v1.2.3 From a17d4996e051e78d164989b894608cf37cd5110b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 19 Feb 2015 09:40:28 +0100 Subject: drm/radeon: drop setting UPLL to sleep mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just keep it working, seems to fix some PLL problems. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=73378 Signed-off-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e088e5558da0..a7fb2735d4a9 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -7130,8 +7130,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); if (!vclk || !dclk) { - /* keep the Bypass mode, put PLL to sleep */ - WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); + /* keep the Bypass mode */ return 0; } @@ -7147,8 +7146,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) /* set VCO_MODE to 1 */ WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); - /* toggle UPLL_SLEEP to 1 then back to 0 */ - WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); + /* disable sleep mode */ WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); /* deassert UPLL_RESET */ -- cgit v1.2.3 From 5151adb37a5918957f4c33a8d8e7629c0fb00563 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 9 Mar 2015 01:56:21 -0700 Subject: drm/vmwgfx: Fix a couple of lock dependency violations Experimental lockdep annotation added to the TTM lock has unveiled a couple of lock dependency violations in the vmwgfx driver. In both cases it turns out that the device_private::reservation_sem is not needed so the offending code is moved out of that lock. Cc: Acked-by: Sinclair Yeh Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 8 +++----- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 14 +++----------- 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 33176d05db35..1e114893a001 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2780,13 +2780,11 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, NULL, arg->command_size, arg->throttle_us, (void __user *)(unsigned long)arg->fence_rep, NULL); - + ttm_read_unlock(&dev_priv->reservation_sem); if (unlikely(ret != 0)) - goto out_unlock; + return ret; vmw_kms_cursor_post_execbuf(dev_priv); -out_unlock: - ttm_read_unlock(&dev_priv->reservation_sem); - return ret; + return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 8725b79e7847..07cda8cbbddb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2033,23 +2033,17 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, int i; struct drm_mode_config *mode_config = &dev->mode_config; - ret = ttm_read_lock(&dev_priv->reservation_sem, true); - if (unlikely(ret != 0)) - return ret; - if (!arg->num_outputs) { struct drm_vmw_rect def_rect = {0, 0, 800, 600}; vmw_du_update_layout(dev_priv, 1, &def_rect); - goto out_unlock; + return 0; } rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect); rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect), GFP_KERNEL); - if (unlikely(!rects)) { - ret = -ENOMEM; - goto out_unlock; - } + if (unlikely(!rects)) + return -ENOMEM; user_rects = (void __user *)(unsigned long)arg->rects; ret = copy_from_user(rects, user_rects, rects_size); @@ -2074,7 +2068,5 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, out_free: kfree(rects); -out_unlock: - ttm_read_unlock(&dev_priv->reservation_sem); return ret; } -- cgit v1.2.3 From 3458390b9f0ba784481d23134798faee27b5f16f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 5 Mar 2015 02:33:24 -0800 Subject: drm/vmwgfx: Reorder device takedown somewhat To take down the MOB and GMR memory types, the driver may have to issue fence objects and thus make sure that the fence manager is taken down after those memory types. Reorder device init accordingly. Cc: Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 77 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 6c6b655defcf..74a2e2318693 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -725,32 +725,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) goto out_err1; } - ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, - (dev_priv->vram_size >> PAGE_SHIFT)); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed initializing memory manager for VRAM.\n"); - goto out_err2; - } - - dev_priv->has_gmr = true; - if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || - refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, - VMW_PL_GMR) != 0) { - DRM_INFO("No GMR memory available. " - "Graphics memory resources are very limited.\n"); - dev_priv->has_gmr = false; - } - - if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { - dev_priv->has_mob = true; - if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, - VMW_PL_MOB) != 0) { - DRM_INFO("No MOB memory available. " - "3D will be disabled.\n"); - dev_priv->has_mob = false; - } - } - dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start, dev_priv->mmio_size); @@ -813,6 +787,33 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) goto out_no_fman; } + + ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, + (dev_priv->vram_size >> PAGE_SHIFT)); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed initializing memory manager for VRAM.\n"); + goto out_no_vram; + } + + dev_priv->has_gmr = true; + if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || + refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, + VMW_PL_GMR) != 0) { + DRM_INFO("No GMR memory available. " + "Graphics memory resources are very limited.\n"); + dev_priv->has_gmr = false; + } + + if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { + dev_priv->has_mob = true; + if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, + VMW_PL_MOB) != 0) { + DRM_INFO("No MOB memory available. " + "3D will be disabled.\n"); + dev_priv->has_mob = false; + } + } + vmw_kms_save_vga(dev_priv); /* Start kms and overlay systems, needs fifo. */ @@ -838,6 +839,12 @@ out_no_fifo: vmw_kms_close(dev_priv); out_no_kms: vmw_kms_restore_vga(dev_priv); + if (dev_priv->has_mob) + (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); + if (dev_priv->has_gmr) + (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); + (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); +out_no_vram: vmw_fence_manager_takedown(dev_priv->fman); out_no_fman: if (dev_priv->capabilities & SVGA_CAP_IRQMASK) @@ -853,12 +860,6 @@ out_err4: iounmap(dev_priv->mmio_virt); out_err3: arch_phys_wc_del(dev_priv->mmio_mtrr); - if (dev_priv->has_mob) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); - if (dev_priv->has_gmr) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); - (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); -out_err2: (void)ttm_bo_device_release(&dev_priv->bdev); out_err1: vmw_ttm_global_release(dev_priv); @@ -887,6 +888,13 @@ static int vmw_driver_unload(struct drm_device *dev) } vmw_kms_close(dev_priv); vmw_overlay_close(dev_priv); + + if (dev_priv->has_mob) + (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); + if (dev_priv->has_gmr) + (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); + (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + vmw_fence_manager_takedown(dev_priv->fman); if (dev_priv->capabilities & SVGA_CAP_IRQMASK) drm_irq_uninstall(dev_priv->dev); @@ -898,11 +906,6 @@ static int vmw_driver_unload(struct drm_device *dev) ttm_object_device_release(&dev_priv->tdev); iounmap(dev_priv->mmio_virt); arch_phys_wc_del(dev_priv->mmio_mtrr); - if (dev_priv->has_mob) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); - if (dev_priv->has_gmr) - (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); - (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); (void)ttm_bo_device_release(&dev_priv->bdev); vmw_ttm_global_release(dev_priv); -- cgit v1.2.3 From da5efffc42222d09079a3427b60374a68200d798 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Jan 2015 15:17:07 +0000 Subject: drm/vmwgfx: Correctly NULLify dma buffer pointer on failure cppcheck on lines 917 and 977 show an ineffective assignment to the dma buffer pointer: [drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c:917]: [drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c:977]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it? On a successful DMA buffer lookup, the dma buffer pointer is assigned, however, on failure it currently is left in an undefined state. The original intention in the error exit path was to nullify the pointer on an error (which the original code failed to do properly). This patch fixes this also ensures all failure paths nullify the buffer pointer on the error return. Fortunately the callers to vmw_translate_mob_ptr and vmw_translate_guest_ptr are checking on a return status and not on the dma buffer pointer, so the original code worked. Reviewed-by: Thomas Hellstrom Signed-off-by: Colin Ian King --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 1e114893a001..654c8daeb5ab 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -890,7 +890,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use MOB buffer.\n"); - return -EINVAL; + ret = -EINVAL; + goto out_no_reloc; } bo = &vmw_bo->base; @@ -914,7 +915,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, out_no_reloc: vmw_dmabuf_unreference(&vmw_bo); - vmw_bo_p = NULL; + *vmw_bo_p = NULL; return ret; } @@ -951,7 +952,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use GMR region.\n"); - return -EINVAL; + ret = -EINVAL; + goto out_no_reloc; } bo = &vmw_bo->base; @@ -974,7 +976,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, out_no_reloc: vmw_dmabuf_unreference(&vmw_bo); - vmw_bo_p = NULL; + *vmw_bo_p = NULL; return ret; } -- cgit v1.2.3 From fd3e4d6e26288d12b566912f692e278e8db15b82 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 10 Mar 2015 11:07:40 -0700 Subject: drm/vmwgfx: Fix an issue with the device losing its irq line on module unload Starting with commit b4b55cda5874 ("x86/PCI: Refine the way to release PCI IRQ resources") the device lost its irq resource on module unload. While that's ok and apparently intentional, the driver never got the resource back on module load The code apparently wants drivers to disable the pci device at pci device driver removal, so lets do that. That fixes the issue. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 74a2e2318693..e13b9cbc304e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1238,6 +1238,7 @@ static void vmw_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); + pci_disable_device(pdev); drm_put_dev(dev); } -- cgit v1.2.3 From 046d669c62f37323ef0329c41d83a03c06b2087d Mon Sep 17 00:00:00 2001 From: Krzysztof Kolasa Date: Sun, 15 Mar 2015 20:22:36 +0100 Subject: [PATCH] drm/mm: Fix support 4 GiB and larger ranges bad argument if(tmp)... in check_free_hole fix oops: kernel BUG at drivers/gpu/drm/drm_mm.c:305! [airlied: excellent, this was my task for today]. Signed-off-by: Krzysztof Kolasa Reviewed-by: Chris wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 7fc6f8bd4821..1134526286c8 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -403,7 +403,7 @@ static int check_free_hole(u64 start, u64 end, u64 size, unsigned alignment) unsigned rem; rem = do_div(tmp, alignment); - if (tmp) + if (rem) start += alignment - rem; } -- cgit v1.2.3