Commit 7fa1d27b authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-fixes-2016-05-25' of...

Merge tag 'drm-intel-next-fixes-2016-05-25' of git://anongit.freedesktop.org/drm-intel into drm-next

I see the main drm pull got merged, here's the first batch of fixes for
4.7 already. Fixes all around, a large portion cc: stable stuff.

[airlied: the DP++ stuff is a regression fix].
* tag 'drm-intel-next-fixes-2016-05-25' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: Stop automatically retiring requests after a GPU hang
  drm/i915: Unify intel_ring_begin()
  drm/i915: Ignore stale wm register values on resume on ilk-bdw (v2)
  drm/i915/psr: Try to program link training times correctly
  drm/i915/bxt: Adjusting the error in horizontal timings retrieval
  drm/i915: Don't leave old junk in ilk active watermarks on readout
  drm/i915: s/DPPL/DPLL/ for SKL DPLLs
  drm/i915: Fix gen8 semaphores id for legacy mode
  drm/i915: Set crtc_state->lane_count for HDMI
  drm/i915/BXT: Retrieving the horizontal timing for DSI
  drm/i915: Protect gen7 irq_seqno_barrier with uncore lock
  drm/i915: Re-enable GGTT earlier during resume on pre-gen6 platforms
  drm/i915: Determine DP++ type 1 DVI adaptor presence based on VBT
  drm/i915: Enable/disable TMDS output buffers in DP++ adaptor as needed
  drm/i915: Respect DP++ adaptor TMDS clock limit
  drm: Add helper for DP++ adaptors
parents 79b3c716 157d2c7f
...@@ -1626,6 +1626,12 @@ void intel_crt_init(struct drm_device *dev) ...@@ -1626,6 +1626,12 @@ void intel_crt_init(struct drm_device *dev)
!Pdrivers/gpu/drm/drm_dp_helper.c dp helpers !Pdrivers/gpu/drm/drm_dp_helper.c dp helpers
!Iinclude/drm/drm_dp_helper.h !Iinclude/drm/drm_dp_helper.h
!Edrivers/gpu/drm/drm_dp_helper.c !Edrivers/gpu/drm/drm_dp_helper.c
</sect2>
<sect2>
<title>Display Port Dual Mode Adaptor Helper Functions Reference</title>
!Pdrivers/gpu/drm/drm_dp_dual_mode_helper.c dp dual mode helpers
!Iinclude/drm/drm_dp_dual_mode_helper.h
!Edrivers/gpu/drm/drm_dp_dual_mode_helper.c
</sect2> </sect2>
<sect2> <sect2>
<title>Display Port MST Helper Functions Reference</title> <title>Display Port MST Helper Functions Reference</title>
......
...@@ -23,7 +23,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o ...@@ -23,7 +23,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_kms_helper_common.o drm_dp_dual_mode_helper.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
......
This diff is collapsed.
...@@ -1183,6 +1183,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) ...@@ -1183,6 +1183,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
if (ret) if (ret)
return ret; return ret;
ret = i915_ggtt_enable_hw(dev);
if (ret) {
DRM_ERROR("failed to enable GGTT\n");
goto out_ggtt;
}
/* WARNING: Apparently we must kick fbdev drivers before vgacon, /* WARNING: Apparently we must kick fbdev drivers before vgacon,
* otherwise the vga fbdev driver falls over. */ * otherwise the vga fbdev driver falls over. */
ret = i915_kick_out_firmware_fb(dev_priv); ret = i915_kick_out_firmware_fb(dev_priv);
......
...@@ -734,9 +734,14 @@ int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state) ...@@ -734,9 +734,14 @@ int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state)
static int i915_drm_resume(struct drm_device *dev) static int i915_drm_resume(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
disable_rpm_wakeref_asserts(dev_priv); disable_rpm_wakeref_asserts(dev_priv);
ret = i915_ggtt_enable_hw(dev);
if (ret)
DRM_ERROR("failed to re-enable GGTT\n");
intel_csr_ucode_resume(dev_priv); intel_csr_ucode_resume(dev_priv);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -3482,6 +3482,7 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size); ...@@ -3482,6 +3482,7 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size);
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port); bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
enum port port); enum port port);
......
...@@ -1456,7 +1456,10 @@ i915_wait_request(struct drm_i915_gem_request *req) ...@@ -1456,7 +1456,10 @@ i915_wait_request(struct drm_i915_gem_request *req)
if (ret) if (ret)
return ret; return ret;
__i915_gem_request_retire__upto(req); /* If the GPU hung, we want to keep the requests to find the guilty. */
if (req->reset_counter == i915_reset_counter(&dev_priv->gpu_error))
__i915_gem_request_retire__upto(req);
return 0; return 0;
} }
...@@ -1513,7 +1516,8 @@ i915_gem_object_retire_request(struct drm_i915_gem_object *obj, ...@@ -1513,7 +1516,8 @@ i915_gem_object_retire_request(struct drm_i915_gem_object *obj,
else if (obj->last_write_req == req) else if (obj->last_write_req == req)
i915_gem_object_retire__write(obj); i915_gem_object_retire__write(obj);
__i915_gem_request_retire__upto(req); if (req->reset_counter == i915_reset_counter(&req->i915->gpu_error))
__i915_gem_request_retire__upto(req);
} }
/* A nonblocking variant of the above wait. This is a highly dangerous routine /* A nonblocking variant of the above wait. This is a highly dangerous routine
...@@ -4860,9 +4864,6 @@ i915_gem_init_hw(struct drm_device *dev) ...@@ -4860,9 +4864,6 @@ i915_gem_init_hw(struct drm_device *dev)
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
int ret, j; int ret, j;
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
/* Double layer security blanket, see i915_gem_init() */ /* Double layer security blanket, see i915_gem_init() */
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
......
...@@ -3236,6 +3236,14 @@ int i915_ggtt_init_hw(struct drm_device *dev) ...@@ -3236,6 +3236,14 @@ int i915_ggtt_init_hw(struct drm_device *dev)
return ret; return ret;
} }
int i915_ggtt_enable_hw(struct drm_device *dev)
{
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
return 0;
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev) void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
......
...@@ -514,6 +514,7 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n) ...@@ -514,6 +514,7 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n)
} }
int i915_ggtt_init_hw(struct drm_device *dev); int i915_ggtt_init_hw(struct drm_device *dev);
int i915_ggtt_enable_hw(struct drm_device *dev);
void i915_gem_init_ggtt(struct drm_device *dev); void i915_gem_init_ggtt(struct drm_device *dev);
void i915_ggtt_cleanup_hw(struct drm_device *dev); void i915_ggtt_cleanup_hw(struct drm_device *dev);
......
...@@ -1578,6 +1578,42 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) ...@@ -1578,6 +1578,42 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
return false; return false;
} }
bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port)
{
static const struct {
u16 dp, hdmi;
} port_mapping[] = {
/*
* Buggy VBTs may declare DP ports as having
* HDMI type dvo_port :( So let's check both.
*/
[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
};
int i;
if (port == PORT_A || port >= ARRAY_SIZE(port_mapping))
return false;
if (!dev_priv->vbt.child_dev_num)
return false;
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
const union child_device_config *p_child =
&dev_priv->vbt.child_dev[i];
if ((p_child->common.dvo_port == port_mapping[port].dp ||
p_child->common.dvo_port == port_mapping[port].hdmi) &&
(p_child->common.device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) ==
(DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS))
return true;
}
return false;
}
/** /**
* intel_bios_is_dsi_present - is DSI present in VBT * intel_bios_is_dsi_present - is DSI present in VBT
* @dev_priv: i915 device instance * @dev_priv: i915 device instance
......
...@@ -1601,6 +1601,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) ...@@ -1601,6 +1601,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
enum port port = intel_ddi_get_encoder_port(intel_encoder); enum port port = intel_ddi_get_encoder_port(intel_encoder);
int type = intel_encoder->type; int type = intel_encoder->type;
if (type == INTEL_OUTPUT_HDMI) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
}
intel_prepare_ddi_buffer(intel_encoder); intel_prepare_ddi_buffer(intel_encoder);
if (type == INTEL_OUTPUT_EDP) { if (type == INTEL_OUTPUT_EDP) {
...@@ -1667,6 +1673,12 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) ...@@ -1667,6 +1673,12 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
DPLL_CTRL2_DDI_CLK_OFF(port))); DPLL_CTRL2_DDI_CLK_OFF(port)));
else if (INTEL_INFO(dev)->gen < 9) else if (INTEL_INFO(dev)->gen < 9)
I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
if (type == INTEL_OUTPUT_HDMI) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
}
} }
static void intel_enable_ddi(struct intel_encoder *intel_encoder) static void intel_enable_ddi(struct intel_encoder *intel_encoder)
...@@ -2180,8 +2192,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder, ...@@ -2180,8 +2192,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config))
pipe_config->has_infoframe = true; pipe_config->has_infoframe = true;
break; /* fall through */
case TRANS_DDI_MODE_SELECT_DVI: case TRANS_DDI_MODE_SELECT_DVI:
pipe_config->lane_count = 4;
break;
case TRANS_DDI_MODE_SELECT_FDI: case TRANS_DDI_MODE_SELECT_FDI:
break; break;
case TRANS_DDI_MODE_SELECT_DP_SST: case TRANS_DDI_MODE_SELECT_DP_SST:
......
...@@ -12005,6 +12005,9 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -12005,6 +12005,9 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n"); DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
return ret; return ret;
} }
} else if (dev_priv->display.compute_intermediate_wm) {
if (HAS_PCH_SPLIT(dev_priv) && INTEL_GEN(dev_priv) < 9)
pipe_config->wm.intermediate = pipe_config->wm.optimal.ilk;
} }
if (INTEL_INFO(dev)->gen >= 9) { if (INTEL_INFO(dev)->gen >= 9) {
...@@ -15990,6 +15993,9 @@ void intel_display_resume(struct drm_device *dev) ...@@ -15990,6 +15993,9 @@ void intel_display_resume(struct drm_device *dev)
state->acquire_ctx = &ctx; state->acquire_ctx = &ctx;
/* ignore any reset values/BIOS leftovers in the WM registers */
to_intel_atomic_state(state)->skip_intermediate_wm = true;
for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) {
/* /*
* Force recalculation even if we restore * Force recalculation even if we restore
......
...@@ -1702,9 +1702,9 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { ...@@ -1702,9 +1702,9 @@ static const struct intel_dpll_mgr hsw_pll_mgr = {
static const struct dpll_info skl_plls[] = { static const struct dpll_info skl_plls[] = {
{ "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON }, { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
{ "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
{ "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
{ "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
{ NULL, -1, NULL, }, { NULL, -1, NULL, },
}; };
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_dp_dual_mode_helper.h>
#include <drm/drm_dp_mst_helper.h> #include <drm/drm_dp_mst_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
...@@ -753,6 +754,10 @@ struct cxsr_latency { ...@@ -753,6 +754,10 @@ struct cxsr_latency {
struct intel_hdmi { struct intel_hdmi {
i915_reg_t hdmi_reg; i915_reg_t hdmi_reg;
int ddc_bus; int ddc_bus;
struct {
enum drm_dp_dual_mode_type type;
int max_tmds_clock;
} dp_dual_mode;
bool limited_color_range; bool limited_color_range;
bool color_range_auto; bool color_range_auto;
bool has_hdmi_sink; bool has_hdmi_sink;
...@@ -1401,6 +1406,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -1401,6 +1406,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
bool intel_hdmi_compute_config(struct intel_encoder *encoder, bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config); struct intel_crtc_state *pipe_config);
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
/* intel_lvds.c */ /* intel_lvds.c */
......
...@@ -46,6 +46,22 @@ static const struct { ...@@ -46,6 +46,22 @@ static const struct {
}, },
}; };
/* return pixels in terms of txbyteclkhs */
static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
u16 burst_mode_ratio)
{
return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp * burst_mode_ratio,
8 * 100), lane_count);
}
/* return pixels equvalent to txbyteclkhs */
static u16 pixels_from_txbyteclkhs(u16 clk_hs, int bpp, int lane_count,
u16 burst_mode_ratio)
{
return DIV_ROUND_UP((clk_hs * lane_count * 8 * 100),
(bpp * burst_mode_ratio));
}
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt) enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
{ {
/* It just so happens the VBT matches register contents. */ /* It just so happens the VBT matches register contents. */
...@@ -780,10 +796,19 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, ...@@ -780,10 +796,19 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *adjusted_mode = struct drm_display_mode *adjusted_mode =
&pipe_config->base.adjusted_mode; &pipe_config->base.adjusted_mode;
struct drm_display_mode *adjusted_mode_sw;
struct intel_crtc *intel_crtc;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
unsigned int lane_count = intel_dsi->lane_count;
unsigned int bpp, fmt; unsigned int bpp, fmt;
enum port port; enum port port;
u16 vfp, vsync, vbp; u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
u16 hfp_sw, hsync_sw, hbp_sw;
u16 crtc_htotal_sw, crtc_hsync_start_sw, crtc_hsync_end_sw,
crtc_hblank_start_sw, crtc_hblank_end_sw;
intel_crtc = to_intel_crtc(encoder->base.crtc);
adjusted_mode_sw = &intel_crtc->config->base.adjusted_mode;
/* /*
* Atleast one port is active as encoder->get_config called only if * Atleast one port is active as encoder->get_config called only if
...@@ -808,26 +833,118 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, ...@@ -808,26 +833,118 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vtotal =
I915_READ(BXT_MIPI_TRANS_VTOTAL(port)); I915_READ(BXT_MIPI_TRANS_VTOTAL(port));
hactive = adjusted_mode->crtc_hdisplay;
hfp = I915_READ(MIPI_HFP_COUNT(port));
/* /*
* TODO: Retrieve hfp, hsync and hbp. Adjust them for dual link and * Meaningful for video mode non-burst sync pulse mode only,
* calculate hsync_start, hsync_end, htotal and hblank_end * can be zero for non-burst sync events and burst modes
*/ */
hsync = I915_READ(MIPI_HSYNC_PADDING_COUNT(port));
hbp = I915_READ(MIPI_HBP_COUNT(port));
/* harizontal values are in terms of high speed byte clock */
hfp = pixels_from_txbyteclkhs(hfp, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hsync = pixels_from_txbyteclkhs(hsync, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hbp = pixels_from_txbyteclkhs(hbp, bpp, lane_count,
intel_dsi->burst_mode_ratio);
if (intel_dsi->dual_link) {
hfp *= 2;
hsync *= 2;
hbp *= 2;
}
/* vertical values are in terms of lines */ /* vertical values are in terms of lines */
vfp = I915_READ(MIPI_VFP_COUNT(port)); vfp = I915_READ(MIPI_VFP_COUNT(port));
vsync = I915_READ(MIPI_VSYNC_PADDING_COUNT(port)); vsync = I915_READ(MIPI_VSYNC_PADDING_COUNT(port));
vbp = I915_READ(MIPI_VBP_COUNT(port)); vbp = I915_READ(MIPI_VBP_COUNT(port));
adjusted_mode->crtc_htotal = hactive + hfp + hsync + hbp;
adjusted_mode->crtc_hsync_start = hfp + adjusted_mode->crtc_hdisplay;
adjusted_mode->crtc_hsync_end = hsync + adjusted_mode->crtc_hsync_start;
adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay; adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay;
adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal;
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vsync_start = vfp + adjusted_mode->crtc_vdisplay;
vfp + adjusted_mode->crtc_vdisplay; adjusted_mode->crtc_vsync_end = vsync + adjusted_mode->crtc_vsync_start;
adjusted_mode->crtc_vsync_end =
vsync + adjusted_mode->crtc_vsync_start;
adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay; adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay;
adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal; adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal;
}
/*
* In BXT DSI there is no regs programmed with few horizontal timings
* in Pixels but txbyteclkhs.. So retrieval process adds some
* ROUND_UP ERRORS in the process of PIXELS<==>txbyteclkhs.
* Actually here for the given adjusted_mode, we are calculating the
* value programmed to the port and then back to the horizontal timing
* param in pixels. This is the expected value, including roundup errors
* And if that is same as retrieved value from port, then
* (HW state) adjusted_mode's horizontal timings are corrected to
* match with SW state to nullify the errors.
*/
/* Calculating the value programmed to the Port register */
hfp_sw = adjusted_mode_sw->crtc_hsync_start -
adjusted_mode_sw->crtc_hdisplay;
hsync_sw = adjusted_mode_sw->crtc_hsync_end -
adjusted_mode_sw->crtc_hsync_start;
hbp_sw = adjusted_mode_sw->crtc_htotal -
adjusted_mode_sw->crtc_hsync_end;
if (intel_dsi->dual_link) {
hfp_sw /= 2;
hsync_sw /= 2;
hbp_sw /= 2;
}
hfp_sw = txbyteclkhs(hfp_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hsync_sw = txbyteclkhs(hsync_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hbp_sw = txbyteclkhs(hbp_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
/* Reverse calculating the adjusted mode parameters from port reg vals*/
hfp_sw = pixels_from_txbyteclkhs(hfp_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hsync_sw = pixels_from_txbyteclkhs(hsync_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hbp_sw = pixels_from_txbyteclkhs(hbp_sw, bpp, lane_count,
intel_dsi->burst_mode_ratio);
if (intel_dsi->dual_link) {
hfp_sw *= 2;
hsync_sw *= 2;
hbp_sw *= 2;
}
crtc_htotal_sw = adjusted_mode_sw->crtc_hdisplay + hfp_sw +
hsync_sw + hbp_sw;
crtc_hsync_start_sw = hfp_sw + adjusted_mode_sw->crtc_hdisplay;
crtc_hsync_end_sw = hsync_sw + crtc_hsync_start_sw;
crtc_hblank_start_sw = adjusted_mode_sw->crtc_hdisplay;
crtc_hblank_end_sw = crtc_htotal_sw;
if (adjusted_mode->crtc_htotal == crtc_htotal_sw)
adjusted_mode->crtc_htotal = adjusted_mode_sw->crtc_htotal;
if (adjusted_mode->crtc_hsync_start == crtc_hsync_start_sw)
adjusted_mode->crtc_hsync_start =
adjusted_mode_sw->crtc_hsync_start;
if (adjusted_mode->crtc_hsync_end == crtc_hsync_end_sw)
adjusted_mode->crtc_hsync_end =
adjusted_mode_sw->crtc_hsync_end;
if (adjusted_mode->crtc_hblank_start == crtc_hblank_start_sw)
adjusted_mode->crtc_hblank_start =
adjusted_mode_sw->crtc_hblank_start;
if (adjusted_mode->crtc_hblank_end == crtc_hblank_end_sw)
adjusted_mode->crtc_hblank_end =
adjusted_mode_sw->crtc_hblank_end;
}
static void intel_dsi_get_config(struct intel_encoder *encoder, static void intel_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config) struct intel_crtc_state *pipe_config)
...@@ -891,14 +1008,6 @@ static u16 txclkesc(u32 divider, unsigned int us) ...@@ -891,14 +1008,6 @@ static u16 txclkesc(u32 divider, unsigned int us)
} }
} }
/* return pixels in terms of txbyteclkhs */
static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
u16 burst_mode_ratio)
{
return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp * burst_mode_ratio,
8 * 100), lane_count);
}
static void set_dsi_timings(struct drm_encoder *encoder, static void set_dsi_timings(struct drm_encoder *encoder,
const struct drm_display_mode *adjusted_mode) const struct drm_display_mode *adjusted_mode)
{ {
......
...@@ -836,6 +836,22 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, ...@@ -836,6 +836,22 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
} }
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi));
struct i2c_adapter *adapter =
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
return;
DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n",
enable ? "Enabling" : "Disabling");
drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type,
adapter, enable);
}
static void intel_hdmi_prepare(struct intel_encoder *encoder) static void intel_hdmi_prepare(struct intel_encoder *encoder)
{ {
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
...@@ -845,6 +861,8 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) ...@@ -845,6 +861,8 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder)
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
u32 hdmi_val; u32 hdmi_val;
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
hdmi_val = SDVO_ENCODING_HDMI; hdmi_val = SDVO_ENCODING_HDMI;
if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range)
hdmi_val |= HDMI_COLOR_RANGE_16_235; hdmi_val |= HDMI_COLOR_RANGE_16_235;
...@@ -953,6 +971,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, ...@@ -953,6 +971,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
dotclock /= pipe_config->pixel_multiplier; dotclock /= pipe_config->pixel_multiplier;
pipe_config->base.adjusted_mode.crtc_clock = dotclock; pipe_config->base.adjusted_mode.crtc_clock = dotclock;
pipe_config->lane_count = 4;
} }
static void intel_enable_hdmi_audio(struct intel_encoder *encoder) static void intel_enable_hdmi_audio(struct intel_encoder *encoder)
...@@ -1140,6 +1160,8 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) ...@@ -1140,6 +1160,8 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
} }
intel_hdmi->set_infoframes(&encoder->base, false, NULL); intel_hdmi->set_infoframes(&encoder->base, false, NULL);
intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
} }
static void g4x_disable_hdmi(struct intel_encoder *encoder) static void g4x_disable_hdmi(struct intel_encoder *encoder)
...@@ -1165,27 +1187,42 @@ static void pch_post_disable_hdmi(struct intel_encoder *encoder) ...@@ -1165,27 +1187,42 @@ static void pch_post_disable_hdmi(struct intel_encoder *encoder)
intel_disable_hdmi(encoder); intel_disable_hdmi(encoder);
} }
static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = intel_hdmi_to_dev(hdmi); if (IS_G4X(dev_priv))
if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
return 165000; return 165000;
else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
return 300000; return 300000;
else else
return 225000; return 225000;
} }
static int hdmi_port_clock_limit(struct intel_hdmi *hdmi,
bool respect_downstream_limits)
{
struct drm_device *dev = intel_hdmi_to_dev(hdmi);
int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
if (respect_downstream_limits) {
if (hdmi->dp_dual_mode.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
hdmi->dp_dual_mode.max_tmds_clock);
if (!hdmi->has_hdmi_sink)
max_tmds_clock = min(max_tmds_clock, 165000);
}
return max_tmds_clock;
}
static enum drm_mode_status static enum drm_mode_status
hdmi_port_clock_valid(struct intel_hdmi *hdmi, hdmi_port_clock_valid(struct intel_hdmi *hdmi,
int clock, bool respect_dvi_limit) int clock, bool respect_downstream_limits)
{ {
struct drm_device *dev = intel_hdmi_to_dev(hdmi); struct drm_device *dev = intel_hdmi_to_dev(hdmi);
if (clock < 25000) if (clock < 25000)
return MODE_CLOCK_LOW; return MODE_CLOCK_LOW;
if (clock > hdmi_port_clock_limit(hdmi, respect_dvi_limit)) if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits))
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
/* BXT DPLL can't generate 223-240 MHz */ /* BXT DPLL can't generate 223-240 MHz */
...@@ -1309,7 +1346,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -1309,7 +1346,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
* within limits. * within limits.
*/ */
if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink &&
hdmi_port_clock_valid(intel_hdmi, clock_12bpc, false) == MODE_OK && hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true) == MODE_OK &&
hdmi_12bpc_possible(pipe_config)) { hdmi_12bpc_possible(pipe_config)) {
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
desired_bpp = 12*3; desired_bpp = 12*3;
...@@ -1337,6 +1374,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -1337,6 +1374,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
/* Set user selected PAR to incoming mode's member */ /* Set user selected PAR to incoming mode's member */
adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
pipe_config->lane_count = 4;
return true; return true;
} }
...@@ -1349,10 +1388,57 @@ intel_hdmi_unset_edid(struct drm_connector *connector) ...@@ -1349,10 +1388,57 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
intel_hdmi->has_audio = false; intel_hdmi->has_audio = false;
intel_hdmi->rgb_quant_range_selectable = false; intel_hdmi->rgb_quant_range_selectable = false;
intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
kfree(to_intel_connector(connector)->detect_edid); kfree(to_intel_connector(connector)->detect_edid);
to_intel_connector(connector)->detect_edid = NULL; to_intel_connector(connector)->detect_edid = NULL;
} }
static void
intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
enum port port = hdmi_to_dig_port(hdmi)->port;
struct i2c_adapter *adapter =
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter);
/*
* Type 1 DVI adaptors are not required to implement any
* registers, so we can't always detect their presence.
* Ideally we should be able to check the state of the
* CONFIG1 pin, but no such luck on our hardware.
*
* The only method left to us is to check the VBT to see
* if the port is a dual mode capable DP port. But let's
* only do that when we sucesfully read the EDID, to avoid
* confusing log messages about DP dual mode adaptors when
* there's nothing connected to the port.
*/
if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
if (has_edid &&
intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
DRM_DEBUG_KMS("Assuming DP dual mode adaptor presence based on VBT\n");
type = DRM_DP_DUAL_MODE_TYPE1_DVI;
} else {
type = DRM_DP_DUAL_MODE_NONE;
}
}
if (type == DRM_DP_DUAL_MODE_NONE)
return;
hdmi->dp_dual_mode.type = type;
hdmi->dp_dual_mode.max_tmds_clock =
drm_dp_dual_mode_max_tmds_clock(type, adapter);
DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",
drm_dp_get_dual_mode_type_name(type),
hdmi->dp_dual_mode.max_tmds_clock);
}
static bool static bool
intel_hdmi_set_edid(struct drm_connector *connector, bool force) intel_hdmi_set_edid(struct drm_connector *connector, bool force)
{ {
...@@ -1368,6 +1454,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force) ...@@ -1368,6 +1454,8 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
intel_gmbus_get_adapter(dev_priv, intel_gmbus_get_adapter(dev_priv,
intel_hdmi->ddc_bus)); intel_hdmi->ddc_bus));
intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
} }
......
...@@ -721,48 +721,6 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request ...@@ -721,48 +721,6 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
return ret; return ret;
} }
static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
int bytes)
{
struct intel_ringbuffer *ringbuf = req->ringbuf;
struct intel_engine_cs *engine = req->engine;
struct drm_i915_gem_request *target;
unsigned space;
int ret;
if (intel_ring_space(ringbuf) >= bytes)
return 0;
/* The whole point of reserving space is to not wait! */
WARN_ON(ringbuf->reserved_in_use);
list_for_each_entry(target, &engine->request_list, list) {
/*
* The request queue is per-engine, so can contain requests
* from multiple ringbuffers. Here, we must ignore any that
* aren't from the ringbuffer we're considering.
*/
if (target->ringbuf != ringbuf)
continue;
/* Would completion of this request free enough space? */
space = __intel_ring_space(target->postfix, ringbuf->tail,
ringbuf->size);
if (space >= bytes)
break;
}
if (WARN_ON(&target->list == &engine->request_list))
return -ENOSPC;
ret = i915_wait_request(target);
if (ret)
return ret;
ringbuf->space = space;
return 0;
}
/* /*
* intel_logical_ring_advance_and_submit() - advance the tail and submit the workload * intel_logical_ring_advance_and_submit() - advance the tail and submit the workload
* @request: Request to advance the logical ringbuffer of. * @request: Request to advance the logical ringbuffer of.
...@@ -814,92 +772,6 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) ...@@ -814,92 +772,6 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
return 0; return 0;
} }
static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf)
{
uint32_t __iomem *virt;
int rem = ringbuf->size - ringbuf->tail;
virt = ringbuf->virtual_start + ringbuf->tail;
rem /= 4;
while (rem--)
iowrite32(MI_NOOP, virt++);
ringbuf->tail = 0;
intel_ring_update_space(ringbuf);
}
static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes)
{
struct intel_ringbuffer *ringbuf = req->ringbuf;
int remain_usable = ringbuf->effective_size - ringbuf->tail;
int remain_actual = ringbuf->size - ringbuf->tail;
int ret, total_bytes, wait_bytes = 0;
bool need_wrap = false;
if (ringbuf->reserved_in_use)
total_bytes = bytes;
else
total_bytes = bytes + ringbuf->reserved_size;
if (unlikely(bytes > remain_usable)) {
/*
* Not enough space for the basic request. So need to flush
* out the remainder and then wait for base + reserved.
*/
wait_bytes = remain_actual + total_bytes;
need_wrap = true;
} else {
if (unlikely(total_bytes > remain_usable)) {
/*
* The base request will fit but the reserved space
* falls off the end. So don't need an immediate wrap
* and only need to effectively wait for the reserved
* size space from the start of ringbuffer.
*/
wait_bytes = remain_actual + ringbuf->reserved_size;
} else if (total_bytes > ringbuf->space) {
/* No wrapping required, just waiting. */
wait_bytes = total_bytes;
}
}
if (wait_bytes) {
ret = logical_ring_wait_for_space(req, wait_bytes);
if (unlikely(ret))
return ret;
if (need_wrap)
__wrap_ring_buffer(ringbuf);
}
return 0;
}
/**
* intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands
*
* @req: The request to start some new work for
* @num_dwords: number of DWORDs that we plan to write to the ringbuffer.
*
* The ringbuffer might not be ready to accept the commands right away (maybe it needs to
* be wrapped, or wait a bit for the tail to be updated). This function takes care of that
* and also preallocates a request (every workload submission is still mediated through
* requests, same as it did with legacy ringbuffer submission).
*
* Return: non-zero if the ringbuffer is not ready to be written to.
*/
int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
{
int ret;
ret = logical_ring_prepare(req, num_dwords * sizeof(uint32_t));
if (ret)
return ret;
req->ringbuf->space -= num_dwords * sizeof(uint32_t);
return 0;
}
int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request) int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request)
{ {
/* /*
...@@ -912,7 +784,7 @@ int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request) ...@@ -912,7 +784,7 @@ int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request)
*/ */
intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST); intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST);
return intel_logical_ring_begin(request, 0); return intel_ring_begin(request, 0);
} }
/** /**
...@@ -982,7 +854,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, ...@@ -982,7 +854,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
if (engine == &dev_priv->engine[RCS] && if (engine == &dev_priv->engine[RCS] &&
instp_mode != dev_priv->relative_constants_mode) { instp_mode != dev_priv->relative_constants_mode) {
ret = intel_logical_ring_begin(params->request, 4); ret = intel_ring_begin(params->request, 4);
if (ret) if (ret)
return ret; return ret;
...@@ -1178,7 +1050,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) ...@@ -1178,7 +1050,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
if (ret) if (ret)
return ret; return ret;
ret = intel_logical_ring_begin(req, w->count * 2 + 2); ret = intel_ring_begin(req, w->count * 2 + 2);
if (ret) if (ret)
return ret; return ret;
...@@ -1669,7 +1541,7 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) ...@@ -1669,7 +1541,7 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
const int num_lri_cmds = GEN8_LEGACY_PDPES * 2; const int num_lri_cmds = GEN8_LEGACY_PDPES * 2;
int i, ret; int i, ret;
ret = intel_logical_ring_begin(req, num_lri_cmds * 2 + 2); ret = intel_ring_begin(req, num_lri_cmds * 2 + 2);
if (ret) if (ret)
return ret; return ret;
...@@ -1716,7 +1588,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, ...@@ -1716,7 +1588,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
req->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(req->engine); req->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(req->engine);
} }
ret = intel_logical_ring_begin(req, 4); ret = intel_ring_begin(req, 4);
if (ret) if (ret)
return ret; return ret;
...@@ -1778,7 +1650,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request, ...@@ -1778,7 +1650,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request,
uint32_t cmd; uint32_t cmd;
int ret; int ret;
ret = intel_logical_ring_begin(request, 4); ret = intel_ring_begin(request, 4);
if (ret) if (ret)
return ret; return ret;
...@@ -1846,7 +1718,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, ...@@ -1846,7 +1718,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
vf_flush_wa = true; vf_flush_wa = true;
} }
ret = intel_logical_ring_begin(request, vf_flush_wa ? 12 : 6); ret = intel_ring_begin(request, vf_flush_wa ? 12 : 6);
if (ret) if (ret)
return ret; return ret;
...@@ -1920,7 +1792,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request) ...@@ -1920,7 +1792,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
struct intel_ringbuffer *ringbuf = request->ringbuf; struct intel_ringbuffer *ringbuf = request->ringbuf;
int ret; int ret;
ret = intel_logical_ring_begin(request, 6 + WA_TAIL_DWORDS); ret = intel_ring_begin(request, 6 + WA_TAIL_DWORDS);
if (ret) if (ret)
return ret; return ret;
...@@ -1944,7 +1816,7 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request) ...@@ -1944,7 +1816,7 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request)
struct intel_ringbuffer *ringbuf = request->ringbuf; struct intel_ringbuffer *ringbuf = request->ringbuf;
int ret; int ret;
ret = intel_logical_ring_begin(request, 8 + WA_TAIL_DWORDS); ret = intel_ring_begin(request, 8 + WA_TAIL_DWORDS);
if (ret) if (ret)
return ret; return ret;
......
...@@ -63,7 +63,6 @@ int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request); ...@@ -63,7 +63,6 @@ int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request);
void intel_logical_ring_stop(struct intel_engine_cs *engine); void intel_logical_ring_stop(struct intel_engine_cs *engine);
void intel_logical_ring_cleanup(struct intel_engine_cs *engine); void intel_logical_ring_cleanup(struct intel_engine_cs *engine);
int intel_logical_rings_init(struct drm_device *dev); int intel_logical_rings_init(struct drm_device *dev);
int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords);
int logical_ring_flush_all_caches(struct drm_i915_gem_request *req); int logical_ring_flush_all_caches(struct drm_i915_gem_request *req);
/** /**
......
...@@ -239,11 +239,9 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req, ...@@ -239,11 +239,9 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req,
if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES)) if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
return -ENODEV; return -ENODEV;
ret = intel_logical_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES); ret = intel_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
if (ret) { if (ret)
DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
return ret; return ret;
}
intel_logical_ring_emit(ringbuf, intel_logical_ring_emit(ringbuf,
MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES)); MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES));
...@@ -305,11 +303,9 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req, ...@@ -305,11 +303,9 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES)) if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
return -ENODEV; return -ENODEV;
ret = intel_logical_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES); ret = intel_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
if (ret) { if (ret)
DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
return ret; return ret;
}
intel_logical_ring_emit(ringbuf, intel_logical_ring_emit(ringbuf,
MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2)); MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2));
......
...@@ -3904,6 +3904,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) ...@@ -3904,6 +3904,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
memset(active, 0, sizeof(*active));
active->pipe_enabled = intel_crtc->active; active->pipe_enabled = intel_crtc->active;
if (active->pipe_enabled) { if (active->pipe_enabled) {
......
...@@ -280,7 +280,10 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -280,7 +280,10 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
* with the 5 or 6 idle patterns. * with the 5 or 6 idle patterns.
*/ */
uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
uint32_t val = 0x0; uint32_t val = EDP_PSR_ENABLE;
val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
if (IS_HASWELL(dev)) if (IS_HASWELL(dev))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
...@@ -288,14 +291,50 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -288,14 +291,50 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
if (dev_priv->psr.link_standby) if (dev_priv->psr.link_standby)
val |= EDP_PSR_LINK_STANDBY; val |= EDP_PSR_LINK_STANDBY;
I915_WRITE(EDP_PSR_CTL, val | if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | val |= EDP_PSR_TP1_TIME_2500us;
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
EDP_PSR_ENABLE); val |= EDP_PSR_TP1_TIME_500us;
else if (dev_priv->vbt.psr.tp1_wakeup_time > 0)
val |= EDP_PSR_TP1_TIME_100us;
else
val |= EDP_PSR_TP1_TIME_0us;
if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
val |= EDP_PSR_TP2_TP3_TIME_2500us;
else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
val |= EDP_PSR_TP2_TP3_TIME_500us;
else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
val |= EDP_PSR_TP2_TP3_TIME_100us;
else
val |= EDP_PSR_TP2_TP3_TIME_0us;
if (intel_dp_source_supports_hbr2(intel_dp) &&
drm_dp_tps3_supported(intel_dp->dpcd))
val |= EDP_PSR_TP1_TP3_SEL;
else
val |= EDP_PSR_TP1_TP2_SEL;
I915_WRITE(EDP_PSR_CTL, val);
if (!dev_priv->psr.psr2_support)
return;
/* FIXME: selective update is probably totally broken because it doesn't
* mesh at all with our frontbuffer tracking. And the hw alone isn't
* good enough. */
val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
val |= EDP_PSR2_TP2_TIME_2500;
else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
val |= EDP_PSR2_TP2_TIME_500;
else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
val |= EDP_PSR2_TP2_TIME_100;
else
val |= EDP_PSR2_TP2_TIME_50;
if (dev_priv->psr.psr2_support) I915_WRITE(EDP_PSR2_CTL, val);
I915_WRITE(EDP_PSR2_CTL, EDP_PSR2_ENABLE |
EDP_SU_TRACK_ENABLE | EDP_PSR2_TP2_TIME_100);
} }
static bool intel_psr_match_conditions(struct intel_dp *intel_dp) static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
......
This diff is collapsed.
...@@ -108,8 +108,6 @@ struct intel_ringbuffer { ...@@ -108,8 +108,6 @@ struct intel_ringbuffer {
int size; int size;
int effective_size; int effective_size;
int reserved_size; int reserved_size;
int reserved_tail;
bool reserved_in_use;
/** We track the position of the requests in the ring buffer, and /** We track the position of the requests in the ring buffer, and
* when each is retired we increment last_retired_head as the GPU * when each is retired we increment last_retired_head as the GPU
...@@ -156,7 +154,8 @@ struct intel_engine_cs { ...@@ -156,7 +154,8 @@ struct intel_engine_cs {
#define I915_NUM_ENGINES 5 #define I915_NUM_ENGINES 5
#define _VCS(n) (VCS + (n)) #define _VCS(n) (VCS + (n))
unsigned int exec_id; unsigned int exec_id;
unsigned int guc_id; unsigned int hw_id;
unsigned int guc_id; /* XXX same as hw_id? */
u32 mmio_base; u32 mmio_base;
struct drm_device *dev; struct drm_device *dev;
struct intel_ringbuffer *buffer; struct intel_ringbuffer *buffer;
...@@ -459,7 +458,6 @@ static inline void intel_ring_advance(struct intel_engine_cs *engine) ...@@ -459,7 +458,6 @@ static inline void intel_ring_advance(struct intel_engine_cs *engine)
} }
int __intel_ring_space(int head, int tail, int size); int __intel_ring_space(int head, int tail, int size);
void intel_ring_update_space(struct intel_ringbuffer *ringbuf); void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
int intel_ring_space(struct intel_ringbuffer *ringbuf);
bool intel_engine_stopped(struct intel_engine_cs *engine); bool intel_engine_stopped(struct intel_engine_cs *engine);
int __must_check intel_engine_idle(struct intel_engine_cs *engine); int __must_check intel_engine_idle(struct intel_engine_cs *engine);
......
...@@ -740,6 +740,7 @@ struct bdb_psr { ...@@ -740,6 +740,7 @@ struct bdb_psr {
#define DEVICE_TYPE_INT_TV 0x1009 #define DEVICE_TYPE_INT_TV 0x1009
#define DEVICE_TYPE_HDMI 0x60D2 #define DEVICE_TYPE_HDMI 0x60D2
#define DEVICE_TYPE_DP 0x68C6 #define DEVICE_TYPE_DP 0x68C6
#define DEVICE_TYPE_DP_DUAL_MODE 0x60D6
#define DEVICE_TYPE_eDP 0x78C6 #define DEVICE_TYPE_eDP 0x78C6
#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) #define DEVICE_TYPE_CLASS_EXTENSION (1 << 15)
...@@ -774,6 +775,17 @@ struct bdb_psr { ...@@ -774,6 +775,17 @@ struct bdb_psr {
DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
DEVICE_TYPE_ANALOG_OUTPUT) DEVICE_TYPE_ANALOG_OUTPUT)
#define DEVICE_TYPE_DP_DUAL_MODE_BITS \
(DEVICE_TYPE_INTERNAL_CONNECTOR | \
DEVICE_TYPE_MIPI_OUTPUT | \
DEVICE_TYPE_COMPOSITE_OUTPUT | \
DEVICE_TYPE_LVDS_SINGALING | \
DEVICE_TYPE_TMDS_DVI_SIGNALING | \
DEVICE_TYPE_VIDEO_SIGNALING | \
DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
DEVICE_TYPE_DIGITAL_OUTPUT | \
DEVICE_TYPE_ANALOG_OUTPUT)
/* define the DVO port for HDMI output type */ /* define the DVO port for HDMI output type */
#define DVO_B 1 #define DVO_B 1
#define DVO_C 2 #define DVO_C 2
......
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRM_DP_DUAL_MODE_HELPER_H
#define DRM_DP_DUAL_MODE_HELPER_H
#include <linux/types.h>
/*
* Optional for type 1 DVI adaptors
* Mandatory for type 1 HDMI and type 2 adaptors
*/
#define DP_DUAL_MODE_HDMI_ID 0x00 /* 00-0f */
#define DP_DUAL_MODE_HDMI_ID_LEN 16
/*
* Optional for type 1 adaptors
* Mandatory for type 2 adaptors
*/
#define DP_DUAL_MODE_ADAPTOR_ID 0x10
#define DP_DUAL_MODE_REV_MASK 0x07
#define DP_DUAL_MODE_REV_TYPE2 0x00
#define DP_DUAL_MODE_TYPE_MASK 0xf0
#define DP_DUAL_MODE_TYPE_TYPE2 0xa0
#define DP_DUAL_MODE_IEEE_OUI 0x11 /* 11-13*/
#define DP_DUAL_IEEE_OUI_LEN 3
#define DP_DUAL_DEVICE_ID 0x14 /* 14-19 */
#define DP_DUAL_DEVICE_ID_LEN 6
#define DP_DUAL_MODE_HARDWARE_REV 0x1a
#define DP_DUAL_MODE_FIRMWARE_MAJOR_REV 0x1b
#define DP_DUAL_MODE_FIRMWARE_MINOR_REV 0x1c
#define DP_DUAL_MODE_MAX_TMDS_CLOCK 0x1d
#define DP_DUAL_MODE_I2C_SPEED_CAP 0x1e
#define DP_DUAL_MODE_TMDS_OEN 0x20
#define DP_DUAL_MODE_TMDS_DISABLE 0x01
#define DP_DUAL_MODE_HDMI_PIN_CTRL 0x21
#define DP_DUAL_MODE_CEC_ENABLE 0x01
#define DP_DUAL_MODE_I2C_SPEED_CTRL 0x22
struct i2c_adapter;
ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
u8 offset, void *buffer, size_t size);
ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter,
u8 offset, const void *buffer, size_t size);
/**
* enum drm_dp_dual_mode_type - Type of the DP dual mode adaptor
* @DRM_DP_DUAL_MODE_NONE: No DP dual mode adaptor
* @DRM_DP_DUAL_MODE_UNKNOWN: Could be either none or type 1 DVI adaptor
* @DRM_DP_DUAL_MODE_TYPE1_DVI: Type 1 DVI adaptor
* @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor
* @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor
* @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor
*/
enum drm_dp_dual_mode_type {
DRM_DP_DUAL_MODE_NONE,
DRM_DP_DUAL_MODE_UNKNOWN,
DRM_DP_DUAL_MODE_TYPE1_DVI,
DRM_DP_DUAL_MODE_TYPE1_HDMI,
DRM_DP_DUAL_MODE_TYPE2_DVI,
DRM_DP_DUAL_MODE_TYPE2_HDMI,
};
enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter);
int drm_dp_dual_mode_max_tmds_clock(enum drm_dp_dual_mode_type type,
struct i2c_adapter *adapter);
int drm_dp_dual_mode_get_tmds_output(enum drm_dp_dual_mode_type type,
struct i2c_adapter *adapter, bool *enabled);
int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
struct i2c_adapter *adapter, bool enable);
const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment