Commit d5a0f2e7 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-2014-08-08' of git://anongit.freedesktop.org/drm-intel into drm-next

- Setting dp M2/N2 values plus state checker support (Vandana Kannan)
- chv power well support (Ville)
- DP training pattern 3 support for chv (Ville)
- cleanup of the hsw/bdw ddi pll code, prep work for skl (Damien)
- dsi video burst mode support (Shobhit)
- piles of other chv fixes all over (Ville et. al.)
- cleanup of the ddi translation tables setup code (Damien)
- 180 deg rotation support (Ville & Sonika Jindal)

* tag 'drm-intel-next-2014-08-08' of git://anongit.freedesktop.org/drm-intel: (59 commits)
  drm/i915: Update DRIVER_DATE to 20140808
  drm/i915: No busy-loop wait_for in the ring init code
  drm/i915: Add sprite watermark programming for VLV and CHV
  drm/i915: Round-up clock and limit drain latency
  drm/i915: Generalize drain latency computation
  drm/i915: Free pending page flip events at .preclose()
  drm/i915: clean up PPGTT checking logic
  drm/i915: Polish the chv cmnlane resrt macros
  drm/i915: Hack to tie both common lanes together on chv
  drm/i915: Add cherryview_update_wm()
  drm/i915: Update DDL only for current CRTC
  drm/i915: Parametrize VLV_DDL registers
  drm/i915: Fill out the FWx watermark register defines
  drm: Resetting rotation property
  drm/i915: Add rotation property for sprites
  drm: Add rotation_property to mode_config
  drm/i915: Make intel_plane_restore() return an error
  drm/i915: Add 180 degree sprite rotation support
  drm/i915: Introduce a for_each_intel_encoder() macro
  drm/i915: Demote the DRRS messages to debug messages
  ...
parents c0ee755f 2c0827cf
...@@ -3400,6 +3400,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis> ...@@ -3400,6 +3400,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
<sect2> <sect2>
<title>Vertical Blanking and Interrupt Handling Functions Reference</title> <title>Vertical Blanking and Interrupt Handling Functions Reference</title>
!Edrivers/gpu/drm/drm_irq.c !Edrivers/gpu/drm/drm_irq.c
!Iinclude/drm/drmP.h drm_crtc_vblank_waitqueue
</sect2> </sect2>
</sect1> </sect1>
......
...@@ -291,10 +291,17 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) ...@@ -291,10 +291,17 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
drm_warn_on_modeset_not_all_locked(dev); drm_warn_on_modeset_not_all_locked(dev);
list_for_each_entry(plane, &dev->mode_config.plane_list, head) list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY) if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane); drm_plane_force_disable(plane);
if (dev->mode_config.rotation_property) {
drm_object_property_set_value(&plane->base,
dev->mode_config.rotation_property,
BIT(DRM_ROTATE_0));
}
}
for (i = 0; i < fb_helper->crtc_count; i++) { for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
struct drm_crtc *crtc = mode_set->crtc; struct drm_crtc *crtc = mode_set->crtc;
......
...@@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused) ...@@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
return 0; return 0;
} }
static int i915_fbc_fc_get(void *data, u64 *val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev))
return -ENODEV;
drm_modeset_lock_all(dev);
*val = dev_priv->fbc.false_color;
drm_modeset_unlock_all(dev);
return 0;
}
static int i915_fbc_fc_set(void *data, u64 val)
{
struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg;
if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev))
return -ENODEV;
drm_modeset_lock_all(dev);
reg = I915_READ(ILK_DPFC_CONTROL);
dev_priv->fbc.false_color = val;
I915_WRITE(ILK_DPFC_CONTROL, val ?
(reg | FBC_CTL_FALSE_COLOR) :
(reg & ~FBC_CTL_FALSE_COLOR));
drm_modeset_unlock_all(dev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_fc_fops,
i915_fbc_fc_get, i915_fbc_fc_set,
"%llu\n");
static int i915_ips_status(struct seq_file *m, void *unused) static int i915_ips_status(struct seq_file *m, void *unused)
{ {
struct drm_info_node *node = m->private; struct drm_info_node *node = m->private;
...@@ -2667,8 +2708,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, ...@@ -2667,8 +2708,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,
*source = INTEL_PIPE_CRC_SOURCE_PIPE; *source = INTEL_PIPE_CRC_SOURCE_PIPE;
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, for_each_intel_encoder(dev, encoder) {
base.head) {
if (!encoder->base.crtc) if (!encoder->base.crtc)
continue; continue;
...@@ -3957,6 +3997,7 @@ static const struct i915_debugfs_files { ...@@ -3957,6 +3997,7 @@ static const struct i915_debugfs_files {
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, {"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
{"i915_spr_wm_latency", &i915_spr_wm_latency_fops}, {"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
{"i915_cur_wm_latency", &i915_cur_wm_latency_fops}, {"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
{"i915_fbc_false_color", &i915_fbc_fc_fops},
}; };
void intel_display_crc_init(struct drm_device *dev) void intel_display_crc_init(struct drm_device *dev)
......
...@@ -1981,6 +1981,9 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file) ...@@ -1981,6 +1981,9 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
i915_gem_context_close(dev, file); i915_gem_context_close(dev, file);
i915_gem_release(dev, file); i915_gem_release(dev, file);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_modeset_preclose(dev, file);
} }
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#define DRIVER_NAME "i915" #define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics" #define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20140725" #define DRIVER_DATE "20140808"
enum pipe { enum pipe {
INVALID_PIPE = -1, INVALID_PIPE = -1,
...@@ -171,6 +171,11 @@ enum hpd_pin { ...@@ -171,6 +171,11 @@ enum hpd_pin {
#define for_each_intel_crtc(dev, intel_crtc) \ #define for_each_intel_crtc(dev, intel_crtc) \
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
#define for_each_intel_encoder(dev, intel_encoder) \
list_for_each_entry(intel_encoder, \
&(dev)->mode_config.encoder_list, \
base.head)
#define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
if ((intel_encoder)->base.crtc == (__crtc)) if ((intel_encoder)->base.crtc == (__crtc))
...@@ -197,10 +202,13 @@ enum intel_dpll_id { ...@@ -197,10 +202,13 @@ enum intel_dpll_id {
#define I915_NUM_PLLS 2 #define I915_NUM_PLLS 2
struct intel_dpll_hw_state { struct intel_dpll_hw_state {
/* i9xx, pch plls */
uint32_t dpll; uint32_t dpll;
uint32_t dpll_md; uint32_t dpll_md;
uint32_t fp0; uint32_t fp0;
uint32_t fp1; uint32_t fp1;
/* hsw, bdw */
uint32_t wrpll; uint32_t wrpll;
}; };
...@@ -634,6 +642,8 @@ struct i915_fbc { ...@@ -634,6 +642,8 @@ struct i915_fbc {
struct drm_mm_node compressed_fb; struct drm_mm_node compressed_fb;
struct drm_mm_node *compressed_llb; struct drm_mm_node *compressed_llb;
bool false_color;
struct intel_fbc_work { struct intel_fbc_work {
struct delayed_work work; struct delayed_work work;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -1227,6 +1237,12 @@ enum modeset_restore { ...@@ -1227,6 +1237,12 @@ enum modeset_restore {
}; };
struct ddi_vbt_port_info { struct ddi_vbt_port_info {
/*
* This is an index in the HDMI/DVI DDI buffer translation table.
* The special value HDMI_LEVEL_SHIFT_UNKNOWN means the VBT didn't
* populate this field.
*/
#define HDMI_LEVEL_SHIFT_UNKNOWN 0xff
uint8_t hdmi_level_shift; uint8_t hdmi_level_shift;
uint8_t supports_dvi:1; uint8_t supports_dvi:1;
...@@ -2049,8 +2065,8 @@ struct drm_i915_cmd_table { ...@@ -2049,8 +2065,8 @@ struct drm_i915_cmd_table {
#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev)) #define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))
#define USES_PPGTT(dev) intel_enable_ppgtt(dev, false) #define USES_PPGTT(dev) (i915.enable_ppgtt)
#define USES_FULL_PPGTT(dev) intel_enable_ppgtt(dev, true) #define USES_FULL_PPGTT(dev) (i915.enable_ppgtt == 2)
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
......
...@@ -33,17 +33,6 @@ ...@@ -33,17 +33,6 @@
static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv); static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv);
static void chv_setup_private_ppat(struct drm_i915_private *dev_priv); static void chv_setup_private_ppat(struct drm_i915_private *dev_priv);
bool intel_enable_ppgtt(struct drm_device *dev, bool full)
{
if (i915.enable_ppgtt == 0)
return false;
if (i915.enable_ppgtt == 1 && full)
return false;
return true;
}
static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
{ {
if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
......
...@@ -272,7 +272,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev); ...@@ -272,7 +272,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev);
void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start, void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
unsigned long mappable_end, unsigned long end); unsigned long mappable_end, unsigned long end);
bool intel_enable_ppgtt(struct drm_device *dev, bool full);
int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt); int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
void i915_check_and_clear_faults(struct drm_device *dev); void i915_check_and_clear_faults(struct drm_device *dev);
......
...@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) ...@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{ {
assert_spin_locked(&dev_priv->irq_lock); assert_spin_locked(&dev_priv->irq_lock);
if (!intel_irqs_enabled(dev_priv)) if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return; return;
if ((dev_priv->irq_mask & mask) != mask) { if ((dev_priv->irq_mask & mask) != mask) {
...@@ -1984,14 +1984,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) ...@@ -1984,14 +1984,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe) static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
{ {
struct intel_crtc *crtc;
if (!drm_handle_vblank(dev, pipe)) if (!drm_handle_vblank(dev, pipe))
return false; return false;
crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
wake_up(&crtc->vbl_wait);
return true; return true;
} }
...@@ -3522,18 +3517,17 @@ static void cherryview_irq_preinstall(struct drm_device *dev) ...@@ -3522,18 +3517,17 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
static void ibx_hpd_irq_setup(struct drm_device *dev) static void ibx_hpd_irq_setup(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
u32 hotplug_irqs, hotplug, enabled_irqs = 0; u32 hotplug_irqs, hotplug, enabled_irqs = 0;
if (HAS_PCH_IBX(dev)) { if (HAS_PCH_IBX(dev)) {
hotplug_irqs = SDE_HOTPLUG_MASK; hotplug_irqs = SDE_HOTPLUG_MASK;
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin]; enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
} else { } else {
hotplug_irqs = SDE_HOTPLUG_MASK_CPT; hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin]; enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
} }
...@@ -4444,7 +4438,6 @@ static int i965_irq_postinstall(struct drm_device *dev) ...@@ -4444,7 +4438,6 @@ static int i965_irq_postinstall(struct drm_device *dev)
static void i915_hpd_irq_setup(struct drm_device *dev) static void i915_hpd_irq_setup(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
u32 hotplug_en; u32 hotplug_en;
...@@ -4455,7 +4448,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev) ...@@ -4455,7 +4448,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
hotplug_en &= ~HOTPLUG_INT_EN_MASK; hotplug_en &= ~HOTPLUG_INT_EN_MASK;
/* Note HDMI and DP share hotplug bits */ /* Note HDMI and DP share hotplug bits */
/* enable bits are the same for all generations */ /* enable bits are the same for all generations */
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin]; hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
/* Programming the CRT detection parameters tends /* Programming the CRT detection parameters tends
......
This diff is collapsed.
...@@ -976,13 +976,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, ...@@ -976,13 +976,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
if (bdb->version >= 158) { if (bdb->version >= 158) {
/* The VBT HDMI level shift values match the table we have. */ /* The VBT HDMI level shift values match the table we have. */
hdmi_level_shift = child->raw[7] & 0xF; hdmi_level_shift = child->raw[7] & 0xF;
if (hdmi_level_shift < 0xC) {
DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
port_name(port), port_name(port),
hdmi_level_shift); hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift; info->hdmi_level_shift = hdmi_level_shift;
} }
}
} }
static void parse_ddi_ports(struct drm_i915_private *dev_priv, static void parse_ddi_ports(struct drm_i915_private *dev_priv,
...@@ -1114,8 +1112,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) ...@@ -1114,8 +1112,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
struct ddi_vbt_port_info *info = struct ddi_vbt_port_info *info =
&dev_priv->vbt.ddi_port_info[port]; &dev_priv->vbt.ddi_port_info[port];
/* Recommended BSpec default: 800mV 0dB. */ info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN;
info->hdmi_level_shift = 6;
info->supports_dvi = (port != PORT_A && port != PORT_E); info->supports_dvi = (port != PORT_A && port != PORT_E);
info->supports_hdmi = info->supports_dvi; info->supports_hdmi = info->supports_dvi;
......
...@@ -802,7 +802,8 @@ struct mipi_config { ...@@ -802,7 +802,8 @@ struct mipi_config {
u16 rsvd4; u16 rsvd4;
u8 rsvd5[5]; u8 rsvd5;
u32 target_burst_mode_freq;
u32 dsi_ddr_clk; u32 dsi_ddr_clk;
u32 bridge_ref_clk; u32 bridge_ref_clk;
......
This diff is collapsed.
This diff is collapsed.
...@@ -828,20 +828,6 @@ intel_dp_set_clock(struct intel_encoder *encoder, ...@@ -828,20 +828,6 @@ intel_dp_set_clock(struct intel_encoder *encoder,
} }
} }
static void
intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum transcoder transcoder = crtc->config.cpu_transcoder;
I915_WRITE(PIPE_DATA_M2(transcoder),
TU_SIZE(m_n->tu) | m_n->gmch_m);
I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
}
bool bool
intel_dp_compute_config(struct intel_encoder *encoder, intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config) struct intel_crtc_config *pipe_config)
...@@ -867,6 +853,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -867,6 +853,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
pipe_config->has_pch_encoder = true; pipe_config->has_pch_encoder = true;
pipe_config->has_dp_encoder = true; pipe_config->has_dp_encoder = true;
pipe_config->has_drrs = false;
pipe_config->has_audio = intel_dp->has_audio; pipe_config->has_audio = intel_dp->has_audio;
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
...@@ -970,13 +957,14 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -970,13 +957,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (intel_connector->panel.downclock_mode != NULL && if (intel_connector->panel.downclock_mode != NULL &&
intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
pipe_config->has_drrs = true;
intel_link_compute_m_n(bpp, lane_count, intel_link_compute_m_n(bpp, lane_count,
intel_connector->panel.downclock_mode->clock, intel_connector->panel.downclock_mode->clock,
pipe_config->port_clock, pipe_config->port_clock,
&pipe_config->dp_m2_n2); &pipe_config->dp_m2_n2);
} }
if (HAS_DDI(dev)) if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
else else
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
...@@ -2293,6 +2281,8 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) ...@@ -2293,6 +2281,8 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
u32 val; u32 val;
intel_dp_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */ /* program left/right clock distribution */
...@@ -2659,8 +2649,8 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp) ...@@ -2659,8 +2649,8 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)
/* Program swing margin */ /* Program swing margin */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK; val &= ~DPIO_SWING_MARGIN000_MASK;
val |= margin_reg_value << DPIO_SWING_MARGIN_SHIFT; val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
} }
...@@ -2971,6 +2961,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2971,6 +2961,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
} }
} else { } else {
if (IS_CHERRYVIEW(dev))
*DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
*DP &= ~DP_LINK_TRAIN_MASK; *DP &= ~DP_LINK_TRAIN_MASK;
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
...@@ -2984,8 +2977,12 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -2984,8 +2977,12 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
*DP |= DP_LINK_TRAIN_PAT_2; *DP |= DP_LINK_TRAIN_PAT_2;
break; break;
case DP_TRAINING_PATTERN_3: case DP_TRAINING_PATTERN_3:
if (IS_CHERRYVIEW(dev)) {
*DP |= DP_LINK_TRAIN_PAT_3_CHV;
} else {
DRM_ERROR("DP training pattern 3 not supported\n"); DRM_ERROR("DP training pattern 3 not supported\n");
*DP |= DP_LINK_TRAIN_PAT_2; *DP |= DP_LINK_TRAIN_PAT_2;
}
break; break;
} }
} }
...@@ -3272,6 +3269,9 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -3272,6 +3269,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else { } else {
if (IS_CHERRYVIEW(dev))
DP &= ~DP_LINK_TRAIN_MASK_CHV;
else
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
} }
...@@ -4415,7 +4415,7 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) ...@@ -4415,7 +4415,7 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
val = I915_READ(reg); val = I915_READ(reg);
if (index > DRRS_HIGH_RR) { if (index > DRRS_HIGH_RR) {
val |= PIPECONF_EDP_RR_MODE_SWITCH; val |= PIPECONF_EDP_RR_MODE_SWITCH;
intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); intel_dp_set_m_n(intel_crtc);
} else { } else {
val &= ~PIPECONF_EDP_RR_MODE_SWITCH; val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
} }
...@@ -4455,7 +4455,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4455,7 +4455,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
} }
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
DRM_INFO("VBT doesn't support DRRS\n"); DRM_DEBUG_KMS("VBT doesn't support DRRS\n");
return NULL; return NULL;
} }
...@@ -4463,7 +4463,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4463,7 +4463,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
(dev, fixed_mode, connector); (dev, fixed_mode, connector);
if (!downclock_mode) { if (!downclock_mode) {
DRM_INFO("DRRS not supported\n"); DRM_DEBUG_KMS("DRRS not supported\n");
return NULL; return NULL;
} }
...@@ -4474,7 +4474,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, ...@@ -4474,7 +4474,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n"); DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n");
return downclock_mode; return downclock_mode;
} }
......
...@@ -330,6 +330,7 @@ struct intel_crtc_config { ...@@ -330,6 +330,7 @@ struct intel_crtc_config {
/* m2_n2 for eDP downclock */ /* m2_n2 for eDP downclock */
struct intel_link_m_n dp_m2_n2; struct intel_link_m_n dp_m2_n2;
bool has_drrs;
/* /*
* Frequence the dpll for the port should run at. Differs from the * Frequence the dpll for the port should run at. Differs from the
...@@ -430,8 +431,6 @@ struct intel_crtc { ...@@ -430,8 +431,6 @@ struct intel_crtc {
struct intel_pipe_wm active; struct intel_pipe_wm active;
} wm; } wm;
wait_queue_head_t vbl_wait;
int scanline_offset; int scanline_offset;
struct intel_mmio_flip mmio_flip; struct intel_mmio_flip mmio_flip;
}; };
...@@ -455,6 +454,7 @@ struct intel_plane { ...@@ -455,6 +454,7 @@ struct intel_plane {
unsigned int crtc_w, crtc_h; unsigned int crtc_w, crtc_h;
uint32_t src_x, src_y; uint32_t src_x, src_y;
uint32_t src_w, src_h; uint32_t src_w, src_h;
unsigned int rotation;
/* Since we need to change the watermarks before/after /* Since we need to change the watermarks before/after
* enabling/disabling the planes, we need to store the parameters here * enabling/disabling the planes, we need to store the parameters here
...@@ -882,6 +882,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv); ...@@ -882,6 +882,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv);
void hsw_disable_pc8(struct drm_i915_private *dev_priv); void hsw_disable_pc8(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc, void intel_dp_get_m_n(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config); struct intel_crtc_config *pipe_config);
void intel_dp_set_m_n(struct intel_crtc *crtc);
int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
void void
ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
...@@ -896,7 +897,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -896,7 +897,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_config *pipe_config); struct intel_crtc_config *pipe_config);
int intel_format_to_fourcc(int format); int intel_format_to_fourcc(int format);
void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc); void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
/* intel_dp.c */ /* intel_dp.c */
void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
...@@ -1091,7 +1092,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); ...@@ -1091,7 +1092,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
void intel_flush_primary_plane(struct drm_i915_private *dev_priv, void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
enum plane plane); enum plane plane);
void intel_plane_restore(struct drm_plane *plane); int intel_plane_restore(struct drm_plane *plane);
void intel_plane_disable(struct drm_plane *plane); void intel_plane_disable(struct drm_plane *plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data, int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
......
...@@ -423,9 +423,11 @@ static u16 txclkesc(u32 divider, unsigned int us) ...@@ -423,9 +423,11 @@ static u16 txclkesc(u32 divider, unsigned int us)
} }
/* return pixels in terms of txbyteclkhs */ /* return pixels in terms of txbyteclkhs */
static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count) static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
u16 burst_mode_ratio)
{ {
return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp, 8), lane_count); 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,
...@@ -451,10 +453,12 @@ static void set_dsi_timings(struct drm_encoder *encoder, ...@@ -451,10 +453,12 @@ static void set_dsi_timings(struct drm_encoder *encoder,
vbp = mode->vtotal - mode->vsync_end; vbp = mode->vtotal - mode->vsync_end;
/* horizontal values are in terms of high speed byte clock */ /* horizontal values are in terms of high speed byte clock */
hactive = txbyteclkhs(hactive, bpp, lane_count); hactive = txbyteclkhs(hactive, bpp, lane_count,
hfp = txbyteclkhs(hfp, bpp, lane_count); intel_dsi->burst_mode_ratio);
hsync = txbyteclkhs(hsync, bpp, lane_count); hfp = txbyteclkhs(hfp, bpp, lane_count, intel_dsi->burst_mode_ratio);
hbp = txbyteclkhs(hbp, bpp, lane_count); hsync = txbyteclkhs(hsync, bpp, lane_count,
intel_dsi->burst_mode_ratio);
hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio);
I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive);
I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); I915_WRITE(MIPI_HFP_COUNT(pipe), hfp);
...@@ -541,12 +545,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) ...@@ -541,12 +545,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
intel_dsi->video_mode_format == VIDEO_MODE_BURST) { intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->htotal, bpp, txbyteclkhs(adjusted_mode->htotal, bpp,
intel_dsi->lane_count) + 1); intel_dsi->lane_count,
intel_dsi->burst_mode_ratio) + 1);
} else { } else {
I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
txbyteclkhs(adjusted_mode->vtotal * txbyteclkhs(adjusted_mode->vtotal *
adjusted_mode->htotal, adjusted_mode->htotal,
bpp, intel_dsi->lane_count) + 1); bpp, intel_dsi->lane_count,
intel_dsi->burst_mode_ratio) + 1);
} }
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout); I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val); I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
......
...@@ -116,6 +116,8 @@ struct intel_dsi { ...@@ -116,6 +116,8 @@ struct intel_dsi {
u16 clk_hs_to_lp_count; u16 clk_hs_to_lp_count;
u16 init_count; u16 init_count;
u32 pclk;
u16 burst_mode_ratio;
/* all delays in ms */ /* all delays in ms */
u16 backlight_off_delay; u16 backlight_off_delay;
......
...@@ -271,6 +271,8 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -271,6 +271,8 @@ static bool generic_init(struct intel_dsi_device *dsi)
u32 ths_prepare_ns, tclk_trail_ns; u32 ths_prepare_ns, tclk_trail_ns;
u32 tclk_prepare_clkzero, ths_prepare_hszero; u32 tclk_prepare_clkzero, ths_prepare_hszero;
u32 lp_to_hs_switch, hs_to_lp_switch; u32 lp_to_hs_switch, hs_to_lp_switch;
u32 pclk, computed_ddr;
u16 burst_mode_ratio;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
...@@ -284,8 +286,6 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -284,8 +286,6 @@ static bool generic_init(struct intel_dsi_device *dsi)
else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565) else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565)
bits_per_pixel = 16; bits_per_pixel = 16;
bitrate = (mode->clock * bits_per_pixel) / intel_dsi->lane_count;
intel_dsi->operation_mode = mipi_config->is_cmd_mode; intel_dsi->operation_mode = mipi_config->is_cmd_mode;
intel_dsi->video_mode_format = mipi_config->video_transfer_mode; intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel; intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
...@@ -297,6 +297,40 @@ static bool generic_init(struct intel_dsi_device *dsi) ...@@ -297,6 +297,40 @@ static bool generic_init(struct intel_dsi_device *dsi)
intel_dsi->video_frmt_cfg_bits = intel_dsi->video_frmt_cfg_bits =
mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0; mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
pclk = mode->clock;
/* Burst Mode Ratio
* Target ddr frequency from VBT / non burst ddr freq
* multiply by 100 to preserve remainder
*/
if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
if (mipi_config->target_burst_mode_freq) {
computed_ddr =
(pclk * bits_per_pixel) / intel_dsi->lane_count;
if (mipi_config->target_burst_mode_freq <
computed_ddr) {
DRM_ERROR("Burst mode freq is less than computed\n");
return false;
}
burst_mode_ratio = DIV_ROUND_UP(
mipi_config->target_burst_mode_freq * 100,
computed_ddr);
pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100);
} else {
DRM_ERROR("Burst mode target is not set\n");
return false;
}
} else
burst_mode_ratio = 100;
intel_dsi->burst_mode_ratio = burst_mode_ratio;
intel_dsi->pclk = pclk;
bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count;
switch (intel_dsi->escape_clk_div) { switch (intel_dsi->escape_clk_div) {
case 0: case 0:
tlpx_ns = 50; tlpx_ns = 50;
......
...@@ -134,8 +134,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode, ...@@ -134,8 +134,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
#else #else
/* Get DSI clock from pixel clock */ /* Get DSI clock from pixel clock */
static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode, static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
int pixel_format, int lane_count)
{ {
u32 dsi_clk_khz; u32 dsi_clk_khz;
u32 bpp; u32 bpp;
...@@ -156,7 +155,7 @@ static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode, ...@@ -156,7 +155,7 @@ static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
/* DSI data rate = pixel clock * bits per pixel / lane count /* DSI data rate = pixel clock * bits per pixel / lane count
pixel clock is converted from KHz to Hz */ pixel clock is converted from KHz to Hz */
dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count); dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count);
return dsi_clk_khz; return dsi_clk_khz;
} }
...@@ -228,14 +227,12 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) ...@@ -228,14 +227,12 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
static void vlv_configure_dsi_pll(struct intel_encoder *encoder) static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
int ret; int ret;
struct dsi_mnp dsi_mnp; struct dsi_mnp dsi_mnp;
u32 dsi_clk; u32 dsi_clk;
dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format, dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
intel_dsi->lane_count); intel_dsi->lane_count);
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp); ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
......
...@@ -885,7 +885,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc) ...@@ -885,7 +885,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
if (HAS_GMCH_DISPLAY(dev)) if (HAS_GMCH_DISPLAY(dev))
return false; return false;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { for_each_intel_encoder(dev, encoder) {
if (encoder->new_crtc != crtc) if (encoder->new_crtc != crtc)
continue; continue;
...@@ -1260,6 +1260,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) ...@@ -1260,6 +1260,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
u32 val; u32 val;
intel_hdmi_prepare(encoder);
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
/* program left/right clock distribution */ /* program left/right clock distribution */
...@@ -1429,8 +1431,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) ...@@ -1429,8 +1431,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN_MASK; val &= ~DPIO_SWING_MARGIN000_MASK;
val |= 102 << DPIO_SWING_MARGIN_SHIFT; val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
} }
......
...@@ -823,8 +823,7 @@ bool intel_is_dual_link_lvds(struct drm_device *dev) ...@@ -823,8 +823,7 @@ bool intel_is_dual_link_lvds(struct drm_device *dev)
struct intel_encoder *encoder; struct intel_encoder *encoder;
struct intel_lvds_encoder *lvds_encoder; struct intel_lvds_encoder *lvds_encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, for_each_intel_encoder(dev, encoder) {
base.head) {
if (encoder->type == INTEL_OUTPUT_LVDS) { if (encoder->type == INTEL_OUTPUT_LVDS) {
lvds_encoder = to_lvds_encoder(&encoder->base); lvds_encoder = to_lvds_encoder(&encoder->base);
......
This diff is collapsed.
...@@ -476,8 +476,8 @@ static bool stop_ring(struct intel_engine_cs *ring) ...@@ -476,8 +476,8 @@ static bool stop_ring(struct intel_engine_cs *ring)
if (!IS_GEN2(ring->dev)) { if (!IS_GEN2(ring->dev)) {
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
return false; return false;
} }
} }
......
...@@ -53,6 +53,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -53,6 +53,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
long timeout = msecs_to_jiffies_timeout(1); long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start; int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex)); WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
...@@ -81,7 +82,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -81,7 +82,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
* other CPUs can see the task state update by the time we * other CPUs can see the task state update by the time we
* read the scanline. * read the scanline.
*/ */
prepare_to_wait(&crtc->vbl_wait, &wait, TASK_UNINTERRUPTIBLE); prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
scanline = intel_get_crtc_scanline(crtc); scanline = intel_get_crtc_scanline(crtc);
if (scanline < min || scanline > max) if (scanline < min || scanline > max)
...@@ -100,7 +101,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl ...@@ -100,7 +101,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
local_irq_disable(); local_irq_disable();
} }
finish_wait(&crtc->vbl_wait, &wait); finish_wait(wq, &wait);
drm_vblank_put(dev, pipe); drm_vblank_put(dev, pipe);
...@@ -163,6 +164,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, ...@@ -163,6 +164,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
sprctl &= ~SP_PIXFORMAT_MASK; sprctl &= ~SP_PIXFORMAT_MASK;
sprctl &= ~SP_YUV_BYTE_ORDER_MASK; sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
sprctl &= ~SP_TILED; sprctl &= ~SP_TILED;
sprctl &= ~SP_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_YUYV: case DRM_FORMAT_YUYV:
...@@ -235,6 +237,14 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, ...@@ -235,6 +237,14 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
fb->pitches[0]); fb->pitches[0]);
linear_offset -= sprsurf_offset; linear_offset -= sprsurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SP_ROTATE_180;
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -364,6 +374,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -364,6 +374,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
sprctl &= ~SPRITE_RGB_ORDER_RGBX; sprctl &= ~SPRITE_RGB_ORDER_RGBX;
sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
sprctl &= ~SPRITE_TILED; sprctl &= ~SPRITE_TILED;
sprctl &= ~SPRITE_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
...@@ -426,6 +437,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -426,6 +437,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]); pixel_size, fb->pitches[0]);
linear_offset -= sprsurf_offset; linear_offset -= sprsurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
/* HSW and BDW does this automagically in hardware */
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] +
src_w * pixel_size;
}
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -571,6 +594,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -571,6 +594,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
dvscntr &= ~DVS_RGB_ORDER_XBGR; dvscntr &= ~DVS_RGB_ORDER_XBGR;
dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
dvscntr &= ~DVS_TILED; dvscntr &= ~DVS_TILED;
dvscntr &= ~DVS_ROTATE_180;
switch (fb->pixel_format) { switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
...@@ -628,6 +652,14 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -628,6 +652,14 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
pixel_size, fb->pitches[0]); pixel_size, fb->pitches[0]);
linear_offset -= dvssurf_offset; linear_offset -= dvssurf_offset;
if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
dvscntr |= DVS_ROTATE_180;
x += src_w;
y += src_h;
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
}
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
intel_update_primary_plane(intel_crtc); intel_update_primary_plane(intel_crtc);
...@@ -895,6 +927,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -895,6 +927,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
max_scale = intel_plane->max_downscale << 16; max_scale = intel_plane->max_downscale << 16;
min_scale = intel_plane->can_scale ? 1 : (1 << 16); min_scale = intel_plane->can_scale ? 1 : (1 << 16);
drm_rect_rotate(&src, fb->width << 16, fb->height << 16,
intel_plane->rotation);
hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale); hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
BUG_ON(hscale < 0); BUG_ON(hscale < 0);
...@@ -933,6 +968,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -933,6 +968,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
drm_rect_width(&dst) * hscale - drm_rect_width(&src), drm_rect_width(&dst) * hscale - drm_rect_width(&src),
drm_rect_height(&dst) * vscale - drm_rect_height(&src)); drm_rect_height(&dst) * vscale - drm_rect_height(&src));
drm_rect_rotate_inv(&src, fb->width << 16, fb->height << 16,
intel_plane->rotation);
/* sanity check to make sure the src viewport wasn't enlarged */ /* sanity check to make sure the src viewport wasn't enlarged */
WARN_ON(src.x1 < (int) src_x || WARN_ON(src.x1 < (int) src_x ||
src.y1 < (int) src_y || src.y1 < (int) src_y ||
...@@ -1180,14 +1218,38 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, ...@@ -1180,14 +1218,38 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
return ret; return ret;
} }
void intel_plane_restore(struct drm_plane *plane) static int intel_plane_set_property(struct drm_plane *plane,
struct drm_property *prop,
uint64_t val)
{
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
uint64_t old_val;
int ret = -ENOENT;
if (prop == dev->mode_config.rotation_property) {
/* exactly one rotation angle please */
if (hweight32(val & 0xf) != 1)
return -EINVAL;
old_val = intel_plane->rotation;
intel_plane->rotation = val;
ret = intel_plane_restore(plane);
if (ret)
intel_plane->rotation = old_val;
}
return ret;
}
int intel_plane_restore(struct drm_plane *plane)
{ {
struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane *intel_plane = to_intel_plane(plane);
if (!plane->crtc || !plane->fb) if (!plane->crtc || !plane->fb)
return; return 0;
intel_update_plane(plane, plane->crtc, plane->fb, return intel_update_plane(plane, plane->crtc, plane->fb,
intel_plane->crtc_x, intel_plane->crtc_y, intel_plane->crtc_x, intel_plane->crtc_y,
intel_plane->crtc_w, intel_plane->crtc_h, intel_plane->crtc_w, intel_plane->crtc_h,
intel_plane->src_x, intel_plane->src_y, intel_plane->src_x, intel_plane->src_y,
...@@ -1206,6 +1268,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { ...@@ -1206,6 +1268,7 @@ static const struct drm_plane_funcs intel_plane_funcs = {
.update_plane = intel_update_plane, .update_plane = intel_update_plane,
.disable_plane = intel_disable_plane, .disable_plane = intel_disable_plane,
.destroy = intel_destroy_plane, .destroy = intel_destroy_plane,
.set_property = intel_plane_set_property,
}; };
static uint32_t ilk_plane_formats[] = { static uint32_t ilk_plane_formats[] = {
...@@ -1310,13 +1373,28 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ...@@ -1310,13 +1373,28 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
intel_plane->pipe = pipe; intel_plane->pipe = pipe;
intel_plane->plane = plane; intel_plane->plane = plane;
intel_plane->rotation = BIT(DRM_ROTATE_0);
possible_crtcs = (1 << pipe); possible_crtcs = (1 << pipe);
ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs, &intel_plane_funcs,
plane_formats, num_plane_formats, plane_formats, num_plane_formats,
false); false);
if (ret) if (ret) {
kfree(intel_plane); kfree(intel_plane);
goto out;
}
if (!dev->mode_config.rotation_property)
dev->mode_config.rotation_property =
drm_mode_create_rotation_property(dev,
BIT(DRM_ROTATE_0) |
BIT(DRM_ROTATE_180));
if (dev->mode_config.rotation_property)
drm_object_attach_property(&intel_plane->base.base,
dev->mode_config.rotation_property,
intel_plane->rotation);
out:
return ret; return ret;
} }
...@@ -1313,6 +1313,17 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, ...@@ -1313,6 +1313,17 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
/**
* drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
* @crtc: which CRTC's vblank waitqueue to retrieve
*
* This function returns a pointer to the vblank waitqueue for the CRTC.
* Drivers can use this to implement vblank waits using wait_event() & co.
*/
static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
{
return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;
}
/* Modesetting support */ /* Modesetting support */
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
......
...@@ -825,6 +825,7 @@ struct drm_mode_config { ...@@ -825,6 +825,7 @@ struct drm_mode_config {
struct drm_property *dpms_property; struct drm_property *dpms_property;
struct drm_property *path_property; struct drm_property *path_property;
struct drm_property *plane_type_property; struct drm_property *plane_type_property;
struct drm_property *rotation_property;
/* DVI-I properties */ /* DVI-I properties */
struct drm_property *dvi_i_subconnector_property; struct drm_property *dvi_i_subconnector_property;
......
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