Commit e81f3d81 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-2013-05-20-merged' of...

Merge tag 'drm-intel-next-2013-05-20-merged' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

Daniel writes:
Highlights (copy-pasted from my testing cycle mails):
- fbc support for Haswell (Rodrigo)
- streamlined workaround comments, including an igt tool to grep for
  them (Damien)
- sdvo and TV out cleanups, including a fixup for sdvo multifunction devices
- refactor our eDP mess a bit (Imre)
- don't register the hdmi connector on haswell when desktop eDP is present
- vlv support is no longer preliminary!
- more vlv fixes from Jesse for stolen and dpll handling
- more flexible power well checking infrastructure from Paulo
- a few gtt patches from Ben
- a bit of OCD cleanups for transcoder #defines and an assorted pile
  of smaller things.
- fixes for the gmch modeset sequence
- a bit of OCD around plane/pipe usage (Ville)
- vlv turbo support (Jesse)
- tons of vlv modeset fixes (Jesse et al.)
- vlv pte write fixes (Kenneth Graunke)
- hpd filtering to avoid costly probes on unaffected outputs (Egbert Eich)
- intel dev_info cleanups and refactorings (Damien)
- vlv rc6 support (Jesse)
- random pile of fixes around non-24bpp modes handling
- asle/opregion cleanups and locking fixes (Jani)
- dp dpll refactoring
- improvements for reduced_clock computation on g4x/ilk+
- pfit state refactored to use pipe_config (Jesse)
- lots more computed modeset state moved to pipe_config, including readout
  and cross-check support
- fdi auto-dithering for ivb B/C links, using the neat pipe_config
  improvements
- drm_rect helpers plus sprite clipping fixes (Ville)
- hw context refcounting (Mika + Ben)

* tag 'drm-intel-next-2013-05-20-merged' of git://people.freedesktop.org/~danvet/drm-intel: (155 commits)
  drm/i915: add support for dvo Chrontel 7010B
  drm/i915: Use pipe config state to control gmch pfit enable/disable
  drm/i915: Use pipe_config state to disable ilk+ pfit
  drm/i915: panel fitter hw state readout&check support
  drm/i915: implement WADPOClockGatingDisable for LPT
  drm/i915: Add missing platform tags to FBC workaround comments
  drm/i915: rip out an unused lvds_reg variable
  drm/i915: Compute WR PLL dividers dynamically
  drm/i915: HSW FBC WaFbcDisableDpfcClockGating
  drm/i915: HSW FBC WaFbcAsynchFlipDisableFbcQueue
  drm/i915: Enable FBC at Haswell.
  drm/i915: IVB FBC WaFbcDisableDpfcClockGating
  drm/i915: IVB FBC WaFbcAsynchFlipDisableFbcQueue
  drm/i915: Add support for FBC on Ivybridge.
  drm/i915: Organize VBT stuff inside drm_i915_private
  drm/i915: make SDVO TV-out work for multifunction devices
  drm/i915: rip out now unused is_foo tracking from crtc code
  drm/i915: rip out TV-out lore ...
  drm/i915: drop TVclock special casing on ilk+
  drm/i915: move sdvo TV clock computation to intel_sdvo.c
  ...
parents 970fa986 e1b73cba
...@@ -1653,6 +1653,8 @@ void intel_crt_init(struct drm_device *dev) ...@@ -1653,6 +1653,8 @@ void intel_crt_init(struct drm_device *dev)
<sect2> <sect2>
<title>KMS API Functions</title> <title>KMS API Functions</title>
!Edrivers/gpu/drm/drm_crtc.c !Edrivers/gpu/drm/drm_crtc.c
!Edrivers/gpu/drm/drm_rect.c
!Finclude/drm/drm_rect.h
</sect2> </sect2>
</sect1> </sect1>
......
...@@ -12,7 +12,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ ...@@ -12,7 +12,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \ drm_crtc.o drm_modes.o drm_edid.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \
drm_trace_points.o drm_global.o drm_prime.o drm_trace_points.o drm_global.o drm_prime.o \
drm_rect.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
......
/*
* Copyright (C) 2011-2013 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 (including the next
* paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <drm/drmP.h>
#include <drm/drm_rect.h>
/**
* drm_rect_intersect - intersect two rectangles
* @r1: first rectangle
* @r2: second rectangle
*
* Calculate the intersection of rectangles @r1 and @r2.
* @r1 will be overwritten with the intersection.
*
* RETURNS:
* %true if rectangle @r1 is still visible after the operation,
* %false otherwise.
*/
bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
{
r1->x1 = max(r1->x1, r2->x1);
r1->y1 = max(r1->y1, r2->y1);
r1->x2 = min(r1->x2, r2->x2);
r1->y2 = min(r1->y2, r2->y2);
return drm_rect_visible(r1);
}
EXPORT_SYMBOL(drm_rect_intersect);
/**
* drm_rect_clip_scaled - perform a scaled clip operation
* @src: source window rectangle
* @dst: destination window rectangle
* @clip: clip rectangle
* @hscale: horizontal scaling factor
* @vscale: vertical scaling factor
*
* Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
* same amounts multiplied by @hscale and @vscale.
*
* RETURNS:
* %true if rectangle @dst is still visible after being clipped,
* %false otherwise
*/
bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
const struct drm_rect *clip,
int hscale, int vscale)
{
int diff;
diff = clip->x1 - dst->x1;
if (diff > 0) {
int64_t tmp = src->x1 + (int64_t) diff * hscale;
src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
}
diff = clip->y1 - dst->y1;
if (diff > 0) {
int64_t tmp = src->y1 + (int64_t) diff * vscale;
src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
}
diff = dst->x2 - clip->x2;
if (diff > 0) {
int64_t tmp = src->x2 - (int64_t) diff * hscale;
src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
}
diff = dst->y2 - clip->y2;
if (diff > 0) {
int64_t tmp = src->y2 - (int64_t) diff * vscale;
src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
}
return drm_rect_intersect(dst, clip);
}
EXPORT_SYMBOL(drm_rect_clip_scaled);
static int drm_calc_scale(int src, int dst)
{
int scale = 0;
if (src < 0 || dst < 0)
return -EINVAL;
if (dst == 0)
return 0;
scale = src / dst;
return scale;
}
/**
* drm_rect_calc_hscale - calculate the horizontal scaling factor
* @src: source window rectangle
* @dst: destination window rectangle
* @min_hscale: minimum allowed horizontal scaling factor
* @max_hscale: maximum allowed horizontal scaling factor
*
* Calculate the horizontal scaling factor as
* (@src width) / (@dst width).
*
* RETURNS:
* The horizontal scaling factor, or errno of out of limits.
*/
int drm_rect_calc_hscale(const struct drm_rect *src,
const struct drm_rect *dst,
int min_hscale, int max_hscale)
{
int src_w = drm_rect_width(src);
int dst_w = drm_rect_width(dst);
int hscale = drm_calc_scale(src_w, dst_w);
if (hscale < 0 || dst_w == 0)
return hscale;
if (hscale < min_hscale || hscale > max_hscale)
return -ERANGE;
return hscale;
}
EXPORT_SYMBOL(drm_rect_calc_hscale);
/**
* drm_rect_calc_vscale - calculate the vertical scaling factor
* @src: source window rectangle
* @dst: destination window rectangle
* @min_vscale: minimum allowed vertical scaling factor
* @max_vscale: maximum allowed vertical scaling factor
*
* Calculate the vertical scaling factor as
* (@src height) / (@dst height).
*
* RETURNS:
* The vertical scaling factor, or errno of out of limits.
*/
int drm_rect_calc_vscale(const struct drm_rect *src,
const struct drm_rect *dst,
int min_vscale, int max_vscale)
{
int src_h = drm_rect_height(src);
int dst_h = drm_rect_height(dst);
int vscale = drm_calc_scale(src_h, dst_h);
if (vscale < 0 || dst_h == 0)
return vscale;
if (vscale < min_vscale || vscale > max_vscale)
return -ERANGE;
return vscale;
}
EXPORT_SYMBOL(drm_rect_calc_vscale);
/**
* drm_calc_hscale_relaxed - calculate the horizontal scaling factor
* @src: source window rectangle
* @dst: destination window rectangle
* @min_hscale: minimum allowed horizontal scaling factor
* @max_hscale: maximum allowed horizontal scaling factor
*
* Calculate the horizontal scaling factor as
* (@src width) / (@dst width).
*
* If the calculated scaling factor is below @min_vscale,
* decrease the height of rectangle @dst to compensate.
*
* If the calculated scaling factor is above @max_vscale,
* decrease the height of rectangle @src to compensate.
*
* RETURNS:
* The horizontal scaling factor.
*/
int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
struct drm_rect *dst,
int min_hscale, int max_hscale)
{
int src_w = drm_rect_width(src);
int dst_w = drm_rect_width(dst);
int hscale = drm_calc_scale(src_w, dst_w);
if (hscale < 0 || dst_w == 0)
return hscale;
if (hscale < min_hscale) {
int max_dst_w = src_w / min_hscale;
drm_rect_adjust_size(dst, max_dst_w - dst_w, 0);
return min_hscale;
}
if (hscale > max_hscale) {
int max_src_w = dst_w * max_hscale;
drm_rect_adjust_size(src, max_src_w - src_w, 0);
return max_hscale;
}
return hscale;
}
EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed);
/**
* drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor
* @src: source window rectangle
* @dst: destination window rectangle
* @min_vscale: minimum allowed vertical scaling factor
* @max_vscale: maximum allowed vertical scaling factor
*
* Calculate the vertical scaling factor as
* (@src height) / (@dst height).
*
* If the calculated scaling factor is below @min_vscale,
* decrease the height of rectangle @dst to compensate.
*
* If the calculated scaling factor is above @max_vscale,
* decrease the height of rectangle @src to compensate.
*
* RETURNS:
* The vertical scaling factor.
*/
int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
struct drm_rect *dst,
int min_vscale, int max_vscale)
{
int src_h = drm_rect_height(src);
int dst_h = drm_rect_height(dst);
int vscale = drm_calc_scale(src_h, dst_h);
if (vscale < 0 || dst_h == 0)
return vscale;
if (vscale < min_vscale) {
int max_dst_h = src_h / min_vscale;
drm_rect_adjust_size(dst, 0, max_dst_h - dst_h);
return min_vscale;
}
if (vscale > max_vscale) {
int max_src_h = dst_h * max_vscale;
drm_rect_adjust_size(src, 0, max_src_h - src_h);
return max_vscale;
}
return vscale;
}
EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
/**
* drm_rect_debug_print - print the rectangle information
* @r: rectangle to print
* @fixed_point: rectangle is in 16.16 fixed point format
*/
void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point)
{
int w = drm_rect_width(r);
int h = drm_rect_height(r);
if (fixed_point)
DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n",
w >> 16, ((w & 0xffff) * 15625) >> 10,
h >> 16, ((h & 0xffff) * 15625) >> 10,
r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
else
DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
}
EXPORT_SYMBOL(drm_rect_debug_print);
...@@ -32,12 +32,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -32,12 +32,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define CH7xxx_REG_DID 0x4b #define CH7xxx_REG_DID 0x4b
#define CH7011_VID 0x83 /* 7010 as well */ #define CH7011_VID 0x83 /* 7010 as well */
#define CH7010B_VID 0x05
#define CH7009A_VID 0x84 #define CH7009A_VID 0x84
#define CH7009B_VID 0x85 #define CH7009B_VID 0x85
#define CH7301_VID 0x95 #define CH7301_VID 0x95
#define CH7xxx_VID 0x84 #define CH7xxx_VID 0x84
#define CH7xxx_DID 0x17 #define CH7xxx_DID 0x17
#define CH7010_DID 0x16
#define CH7xxx_NUM_REGS 0x4c #define CH7xxx_NUM_REGS 0x4c
...@@ -87,11 +89,20 @@ static struct ch7xxx_id_struct { ...@@ -87,11 +89,20 @@ static struct ch7xxx_id_struct {
char *name; char *name;
} ch7xxx_ids[] = { } ch7xxx_ids[] = {
{ CH7011_VID, "CH7011" }, { CH7011_VID, "CH7011" },
{ CH7010B_VID, "CH7010B" },
{ CH7009A_VID, "CH7009A" }, { CH7009A_VID, "CH7009A" },
{ CH7009B_VID, "CH7009B" }, { CH7009B_VID, "CH7009B" },
{ CH7301_VID, "CH7301" }, { CH7301_VID, "CH7301" },
}; };
static struct ch7xxx_did_struct {
uint8_t did;
char *name;
} ch7xxx_dids[] = {
{ CH7xxx_DID, "CH7XXX" },
{ CH7010_DID, "CH7010B" },
};
struct ch7xxx_priv { struct ch7xxx_priv {
bool quiet; bool quiet;
}; };
...@@ -108,6 +119,18 @@ static char *ch7xxx_get_id(uint8_t vid) ...@@ -108,6 +119,18 @@ static char *ch7xxx_get_id(uint8_t vid)
return NULL; return NULL;
} }
static char *ch7xxx_get_did(uint8_t did)
{
int i;
for (i = 0; i < ARRAY_SIZE(ch7xxx_dids); i++) {
if (ch7xxx_dids[i].did == did)
return ch7xxx_dids[i].name;
}
return NULL;
}
/** Reads an 8 bit register */ /** Reads an 8 bit register */
static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{ {
...@@ -179,7 +202,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, ...@@ -179,7 +202,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
/* this will detect the CH7xxx chip on the specified i2c bus */ /* this will detect the CH7xxx chip on the specified i2c bus */
struct ch7xxx_priv *ch7xxx; struct ch7xxx_priv *ch7xxx;
uint8_t vendor, device; uint8_t vendor, device;
char *name; char *name, *devid;
ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL); ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL);
if (ch7xxx == NULL) if (ch7xxx == NULL)
...@@ -204,7 +227,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, ...@@ -204,7 +227,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device)) if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device))
goto out; goto out;
if (device != CH7xxx_DID) { devid = ch7xxx_get_did(device);
if (!devid) {
DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s " DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
"slave %d.\n", "slave %d.\n",
vendor, adapter->name, dvo->slave_addr); vendor, adapter->name, dvo->slave_addr);
......
...@@ -61,11 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data) ...@@ -61,11 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data)
seq_printf(m, "gen: %d\n", info->gen); seq_printf(m, "gen: %d\n", info->gen);
seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev)); seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
#define DEV_INFO_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
#define DEV_INFO_SEP ; #define SEP_SEMICOLON ;
DEV_INFO_FLAGS; DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
#undef DEV_INFO_FLAG #undef PRINT_FLAG
#undef DEV_INFO_SEP #undef SEP_SEMICOLON
return 0; return 0;
} }
...@@ -941,7 +941,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) ...@@ -941,7 +941,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
MEMSTAT_VID_SHIFT); MEMSTAT_VID_SHIFT);
seq_printf(m, "Current P-state: %d\n", seq_printf(m, "Current P-state: %d\n",
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
} else if (IS_GEN6(dev) || IS_GEN7(dev)) { } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
...@@ -1009,6 +1009,27 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) ...@@ -1009,6 +1009,27 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
seq_printf(m, "Max overclocked frequency: %dMHz\n", seq_printf(m, "Max overclocked frequency: %dMHz\n",
dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER); dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
} else if (IS_VALLEYVIEW(dev)) {
u32 freq_sts, val;
mutex_lock(&dev_priv->rps.hw_lock);
valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS,
&freq_sts);
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
valleyview_punit_read(dev_priv, PUNIT_FUSE_BUS1, &val);
seq_printf(m, "max GPU freq: %d MHz\n",
vlv_gpu_freq(dev_priv->mem_freq, val));
valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val);
seq_printf(m, "min GPU freq: %d MHz\n",
vlv_gpu_freq(dev_priv->mem_freq, val));
seq_printf(m, "current GPU freq: %d MHz\n",
vlv_gpu_freq(dev_priv->mem_freq,
(freq_sts >> 8) & 0xff));
mutex_unlock(&dev_priv->rps.hw_lock);
} else { } else {
seq_printf(m, "no P-state info available\n"); seq_printf(m, "no P-state info available\n");
} }
...@@ -1812,7 +1833,11 @@ i915_max_freq_get(void *data, u64 *val) ...@@ -1812,7 +1833,11 @@ i915_max_freq_get(void *data, u64 *val)
if (ret) if (ret)
return ret; return ret;
*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; if (IS_VALLEYVIEW(dev))
*val = vlv_gpu_freq(dev_priv->mem_freq,
dev_priv->rps.max_delay);
else
*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return 0; return 0;
...@@ -1837,9 +1862,16 @@ i915_max_freq_set(void *data, u64 val) ...@@ -1837,9 +1862,16 @@ i915_max_freq_set(void *data, u64 val)
/* /*
* Turbo will still be enabled, but won't go above the set value. * Turbo will still be enabled, but won't go above the set value.
*/ */
do_div(val, GT_FREQUENCY_MULTIPLIER); if (IS_VALLEYVIEW(dev)) {
dev_priv->rps.max_delay = val; val = vlv_freq_opcode(dev_priv->mem_freq, val);
gen6_set_rps(dev, val); dev_priv->rps.max_delay = val;
gen6_set_rps(dev, val);
} else {
do_div(val, GT_FREQUENCY_MULTIPLIER);
dev_priv->rps.max_delay = val;
gen6_set_rps(dev, val);
}
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return 0; return 0;
...@@ -1863,7 +1895,11 @@ i915_min_freq_get(void *data, u64 *val) ...@@ -1863,7 +1895,11 @@ i915_min_freq_get(void *data, u64 *val)
if (ret) if (ret)
return ret; return ret;
*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; if (IS_VALLEYVIEW(dev))
*val = vlv_gpu_freq(dev_priv->mem_freq,
dev_priv->rps.min_delay);
else
*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return 0; return 0;
...@@ -1888,9 +1924,15 @@ i915_min_freq_set(void *data, u64 val) ...@@ -1888,9 +1924,15 @@ i915_min_freq_set(void *data, u64 val)
/* /*
* Turbo will still be enabled, but won't go below the set value. * Turbo will still be enabled, but won't go below the set value.
*/ */
do_div(val, GT_FREQUENCY_MULTIPLIER); if (IS_VALLEYVIEW(dev)) {
dev_priv->rps.min_delay = val; val = vlv_freq_opcode(dev_priv->mem_freq, val);
gen6_set_rps(dev, val); dev_priv->rps.min_delay = val;
valleyview_set_rps(dev, val);
} else {
do_div(val, GT_FREQUENCY_MULTIPLIER);
dev_priv->rps.min_delay = val;
gen6_set_rps(dev, val);
}
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return 0; return 0;
......
...@@ -1445,15 +1445,19 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv) ...@@ -1445,15 +1445,19 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
{ {
const struct intel_device_info *info = dev_priv->info; const struct intel_device_info *info = dev_priv->info;
#define DEV_INFO_FLAG(name) info->name ? #name "," : "" #define PRINT_S(name) "%s"
#define DEV_INFO_SEP , #define SEP_EMPTY
#define PRINT_FLAG(name) info->name ? #name "," : ""
#define SEP_COMMA ,
DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags=" DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
info->gen, info->gen,
dev_priv->dev->pdev->device, dev_priv->dev->pdev->device,
DEV_INFO_FLAGS); DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
#undef DEV_INFO_FLAG #undef PRINT_S
#undef DEV_INFO_SEP #undef SEP_EMPTY
#undef PRINT_FLAG
#undef SEP_COMMA
} }
/** /**
...@@ -1468,7 +1472,7 @@ static void intel_early_sanitize_regs(struct drm_device *dev) ...@@ -1468,7 +1472,7 @@ static void intel_early_sanitize_regs(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_HASWELL(dev)) if (HAS_FPGA_DBG_UNCLAIMED(dev))
I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM); I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
} }
...@@ -1629,6 +1633,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1629,6 +1633,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->gpu_error.lock); spin_lock_init(&dev_priv->gpu_error.lock);
spin_lock_init(&dev_priv->rps.lock); spin_lock_init(&dev_priv->rps.lock);
spin_lock_init(&dev_priv->backlight.lock);
mutex_init(&dev_priv->dpio_lock); mutex_init(&dev_priv->dpio_lock);
mutex_init(&dev_priv->rps.hw_lock); mutex_init(&dev_priv->rps.hw_lock);
...@@ -1737,10 +1742,10 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1737,10 +1742,10 @@ int i915_driver_unload(struct drm_device *dev)
* free the memory space allocated for the child device * free the memory space allocated for the child device
* config parsed from VBT * config parsed from VBT
*/ */
if (dev_priv->child_dev && dev_priv->child_dev_num) { if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
kfree(dev_priv->child_dev); kfree(dev_priv->vbt.child_dev);
dev_priv->child_dev = NULL; dev_priv->vbt.child_dev = NULL;
dev_priv->child_dev_num = 0; dev_priv->vbt.child_dev_num = 0;
} }
vga_switcheroo_unregister_client(dev->pdev); vga_switcheroo_unregister_client(dev->pdev);
......
...@@ -280,6 +280,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { ...@@ -280,6 +280,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
GEN7_FEATURES, GEN7_FEATURES,
.is_ivybridge = 1, .is_ivybridge = 1,
.is_mobile = 1, .is_mobile = 1,
.has_fbc = 1,
}; };
static const struct intel_device_info intel_ivybridge_q_info = { static const struct intel_device_info intel_ivybridge_q_info = {
...@@ -308,12 +309,17 @@ static const struct intel_device_info intel_valleyview_d_info = { ...@@ -308,12 +309,17 @@ static const struct intel_device_info intel_valleyview_d_info = {
static const struct intel_device_info intel_haswell_d_info = { static const struct intel_device_info intel_haswell_d_info = {
GEN7_FEATURES, GEN7_FEATURES,
.is_haswell = 1, .is_haswell = 1,
.has_ddi = 1,
.has_fpga_dbg = 1,
}; };
static const struct intel_device_info intel_haswell_m_info = { static const struct intel_device_info intel_haswell_m_info = {
GEN7_FEATURES, GEN7_FEATURES,
.is_haswell = 1, .is_haswell = 1,
.is_mobile = 1, .is_mobile = 1,
.has_ddi = 1,
.has_fpga_dbg = 1,
.has_fbc = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ static const struct pci_device_id pciidlist[] = { /* aka */
...@@ -549,6 +555,8 @@ static int i915_drm_freeze(struct drm_device *dev) ...@@ -549,6 +555,8 @@ static int i915_drm_freeze(struct drm_device *dev)
*/ */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
dev_priv->display.crtc_disable(crtc); dev_priv->display.crtc_disable(crtc);
intel_modeset_suspend_hw(dev);
} }
i915_save_state(dev); i915_save_state(dev);
...@@ -984,12 +992,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -984,12 +992,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct intel_device_info *intel_info = struct intel_device_info *intel_info =
(struct intel_device_info *) ent->driver_data; (struct intel_device_info *) ent->driver_data;
if (intel_info->is_valleyview)
if(!i915_preliminary_hw_support) {
DRM_ERROR("Preliminary hardware support disabled\n");
return -ENODEV;
}
/* Only bind to function 0 of the device. Early generations /* Only bind to function 0 of the device. Early generations
* used function 1 as a placeholder for multi-head. This causes * used function 1 as a placeholder for multi-head. This causes
* us confusion instead, especially on the systems where both * us confusion instead, especially on the systems where both
...@@ -1218,16 +1220,16 @@ MODULE_LICENSE("GPL and additional rights"); ...@@ -1218,16 +1220,16 @@ MODULE_LICENSE("GPL and additional rights");
static void static void
ilk_dummy_write(struct drm_i915_private *dev_priv) ilk_dummy_write(struct drm_i915_private *dev_priv)
{ {
/* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the /* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
* chip from rc6 before touching it for real. MI_MODE is masked, hence * the chip from rc6 before touching it for real. MI_MODE is masked,
* harmless to write 0 into. */ * hence harmless to write 0 into. */
I915_WRITE_NOTRACE(MI_MODE, 0); I915_WRITE_NOTRACE(MI_MODE, 0);
} }
static void static void
hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg) hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
{ {
if (IS_HASWELL(dev_priv->dev) && if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
(I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
DRM_ERROR("Unknown unclaimed register before writing to %x\n", DRM_ERROR("Unknown unclaimed register before writing to %x\n",
reg); reg);
...@@ -1238,7 +1240,7 @@ hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg) ...@@ -1238,7 +1240,7 @@ hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
static void static void
hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
{ {
if (IS_HASWELL(dev_priv->dev) && if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
(I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
DRM_ERROR("Unclaimed write to %x\n", reg); DRM_ERROR("Unclaimed write to %x\n", reg);
I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM); I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
......
This diff is collapsed.
...@@ -2042,6 +2042,11 @@ i915_add_request(struct intel_ring_buffer *ring, ...@@ -2042,6 +2042,11 @@ i915_add_request(struct intel_ring_buffer *ring,
request->seqno = intel_ring_get_seqno(ring); request->seqno = intel_ring_get_seqno(ring);
request->ring = ring; request->ring = ring;
request->tail = request_ring_position; request->tail = request_ring_position;
request->ctx = ring->last_context;
if (request->ctx)
i915_gem_context_reference(request->ctx);
request->emitted_jiffies = jiffies; request->emitted_jiffies = jiffies;
was_empty = list_empty(&ring->request_list); was_empty = list_empty(&ring->request_list);
list_add_tail(&request->list, &ring->request_list); list_add_tail(&request->list, &ring->request_list);
...@@ -2094,6 +2099,17 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) ...@@ -2094,6 +2099,17 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
spin_unlock(&file_priv->mm.lock); spin_unlock(&file_priv->mm.lock);
} }
static void i915_gem_free_request(struct drm_i915_gem_request *request)
{
list_del(&request->list);
i915_gem_request_remove_from_client(request);
if (request->ctx)
i915_gem_context_unreference(request->ctx);
kfree(request);
}
static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
...@@ -2104,9 +2120,7 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, ...@@ -2104,9 +2120,7 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
struct drm_i915_gem_request, struct drm_i915_gem_request,
list); list);
list_del(&request->list); i915_gem_free_request(request);
i915_gem_request_remove_from_client(request);
kfree(request);
} }
while (!list_empty(&ring->active_list)) { while (!list_empty(&ring->active_list)) {
...@@ -2198,9 +2212,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) ...@@ -2198,9 +2212,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
*/ */
ring->last_retired_head = request->tail; ring->last_retired_head = request->tail;
list_del(&request->list); i915_gem_free_request(request);
i915_gem_request_remove_from_client(request);
kfree(request);
} }
/* Move any buffers on the active list that are no longer referenced /* Move any buffers on the active list that are no longer referenced
......
...@@ -124,10 +124,10 @@ static int get_context_size(struct drm_device *dev) ...@@ -124,10 +124,10 @@ static int get_context_size(struct drm_device *dev)
return ret; return ret;
} }
static void do_destroy(struct i915_hw_context *ctx) void i915_gem_context_free(struct kref *ctx_ref)
{ {
if (ctx->file_priv) struct i915_hw_context *ctx = container_of(ctx_ref,
idr_remove(&ctx->file_priv->context_idr, ctx->id); typeof(*ctx), ref);
drm_gem_object_unreference(&ctx->obj->base); drm_gem_object_unreference(&ctx->obj->base);
kfree(ctx); kfree(ctx);
...@@ -145,6 +145,7 @@ create_hw_context(struct drm_device *dev, ...@@ -145,6 +145,7 @@ create_hw_context(struct drm_device *dev,
if (ctx == NULL) if (ctx == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
kref_init(&ctx->ref);
ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
if (ctx->obj == NULL) { if (ctx->obj == NULL) {
kfree(ctx); kfree(ctx);
...@@ -169,18 +170,18 @@ create_hw_context(struct drm_device *dev, ...@@ -169,18 +170,18 @@ create_hw_context(struct drm_device *dev,
if (file_priv == NULL) if (file_priv == NULL)
return ctx; return ctx;
ctx->file_priv = file_priv;
ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0, ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0,
GFP_KERNEL); GFP_KERNEL);
if (ret < 0) if (ret < 0)
goto err_out; goto err_out;
ctx->file_priv = file_priv;
ctx->id = ret; ctx->id = ret;
return ctx; return ctx;
err_out: err_out:
do_destroy(ctx); i915_gem_context_unreference(ctx);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -226,7 +227,7 @@ static int create_default_context(struct drm_i915_private *dev_priv) ...@@ -226,7 +227,7 @@ static int create_default_context(struct drm_i915_private *dev_priv)
err_unpin: err_unpin:
i915_gem_object_unpin(ctx->obj); i915_gem_object_unpin(ctx->obj);
err_destroy: err_destroy:
do_destroy(ctx); i915_gem_context_unreference(ctx);
return ret; return ret;
} }
...@@ -262,6 +263,7 @@ void i915_gem_context_init(struct drm_device *dev) ...@@ -262,6 +263,7 @@ void i915_gem_context_init(struct drm_device *dev)
void i915_gem_context_fini(struct drm_device *dev) void i915_gem_context_fini(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
if (dev_priv->hw_contexts_disabled) if (dev_priv->hw_contexts_disabled)
return; return;
...@@ -271,9 +273,16 @@ void i915_gem_context_fini(struct drm_device *dev) ...@@ -271,9 +273,16 @@ void i915_gem_context_fini(struct drm_device *dev)
* other code, leading to spurious errors. */ * other code, leading to spurious errors. */
intel_gpu_reset(dev); intel_gpu_reset(dev);
i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); i915_gem_object_unpin(dctx->obj);
do_destroy(dev_priv->ring[RCS].default_context); /* When default context is created and switched to, base object refcount
* will be 2 (+1 from object creation and +1 from do_switch()).
* i915_gem_context_fini() will be called after gpu_idle() has switched
* to default context. So we need to unreference the base object once
* to offset the do_switch part, so that i915_gem_context_unreference()
* can then free the base object correctly. */
drm_gem_object_unreference(&dctx->obj->base);
i915_gem_context_unreference(dctx);
} }
static int context_idr_cleanup(int id, void *p, void *data) static int context_idr_cleanup(int id, void *p, void *data)
...@@ -282,8 +291,7 @@ static int context_idr_cleanup(int id, void *p, void *data) ...@@ -282,8 +291,7 @@ static int context_idr_cleanup(int id, void *p, void *data)
BUG_ON(id == DEFAULT_CONTEXT_ID); BUG_ON(id == DEFAULT_CONTEXT_ID);
do_destroy(ctx); i915_gem_context_unreference(ctx);
return 0; return 0;
} }
...@@ -325,6 +333,7 @@ mi_set_context(struct intel_ring_buffer *ring, ...@@ -325,6 +333,7 @@ mi_set_context(struct intel_ring_buffer *ring,
if (ret) if (ret)
return ret; return ret;
/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw */
if (IS_GEN7(ring->dev)) if (IS_GEN7(ring->dev))
intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
else else
...@@ -353,13 +362,13 @@ mi_set_context(struct intel_ring_buffer *ring, ...@@ -353,13 +362,13 @@ mi_set_context(struct intel_ring_buffer *ring,
static int do_switch(struct i915_hw_context *to) static int do_switch(struct i915_hw_context *to)
{ {
struct intel_ring_buffer *ring = to->ring; struct intel_ring_buffer *ring = to->ring;
struct drm_i915_gem_object *from_obj = ring->last_context_obj; struct i915_hw_context *from = ring->last_context;
u32 hw_flags = 0; u32 hw_flags = 0;
int ret; int ret;
BUG_ON(from_obj != NULL && from_obj->pin_count == 0); BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0);
if (from_obj == to->obj) if (from == to)
return 0; return 0;
ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false); ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false);
...@@ -382,7 +391,7 @@ static int do_switch(struct i915_hw_context *to) ...@@ -382,7 +391,7 @@ static int do_switch(struct i915_hw_context *to)
if (!to->is_initialized || is_default_context(to)) if (!to->is_initialized || is_default_context(to))
hw_flags |= MI_RESTORE_INHIBIT; hw_flags |= MI_RESTORE_INHIBIT;
else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ else if (WARN_ON_ONCE(from == to)) /* not yet expected */
hw_flags |= MI_FORCE_RESTORE; hw_flags |= MI_FORCE_RESTORE;
ret = mi_set_context(ring, to, hw_flags); ret = mi_set_context(ring, to, hw_flags);
...@@ -397,9 +406,9 @@ static int do_switch(struct i915_hw_context *to) ...@@ -397,9 +406,9 @@ static int do_switch(struct i915_hw_context *to)
* is a bit suboptimal because the retiring can occur simply after the * is a bit suboptimal because the retiring can occur simply after the
* MI_SET_CONTEXT instead of when the next seqno has completed. * MI_SET_CONTEXT instead of when the next seqno has completed.
*/ */
if (from_obj != NULL) { if (from != NULL) {
from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
i915_gem_object_move_to_active(from_obj, ring); i915_gem_object_move_to_active(from->obj, ring);
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the * whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be * object dirty. The only exception is that the context must be
...@@ -407,15 +416,26 @@ static int do_switch(struct i915_hw_context *to) ...@@ -407,15 +416,26 @@ static int do_switch(struct i915_hw_context *to)
* able to defer doing this until we know the object would be * able to defer doing this until we know the object would be
* swapped, but there is no way to do that yet. * swapped, but there is no way to do that yet.
*/ */
from_obj->dirty = 1; from->obj->dirty = 1;
BUG_ON(from_obj->ring != ring); BUG_ON(from->obj->ring != ring);
i915_gem_object_unpin(from_obj);
ret = i915_add_request(ring, NULL, NULL);
if (ret) {
/* Too late, we've already scheduled a context switch.
* Try to undo the change so that the hw state is
* consistent with out tracking. In case of emergency,
* scream.
*/
WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT));
return ret;
}
drm_gem_object_unreference(&from_obj->base); i915_gem_object_unpin(from->obj);
i915_gem_context_unreference(from);
} }
drm_gem_object_reference(&to->obj->base); i915_gem_context_reference(to);
ring->last_context_obj = to->obj; ring->last_context = to;
to->is_initialized = true; to->is_initialized = true;
return 0; return 0;
...@@ -444,6 +464,8 @@ int i915_switch_context(struct intel_ring_buffer *ring, ...@@ -444,6 +464,8 @@ int i915_switch_context(struct intel_ring_buffer *ring,
if (dev_priv->hw_contexts_disabled) if (dev_priv->hw_contexts_disabled)
return 0; return 0;
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
if (ring != &dev_priv->ring[RCS]) if (ring != &dev_priv->ring[RCS])
return 0; return 0;
...@@ -512,8 +534,8 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, ...@@ -512,8 +534,8 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
return -ENOENT; return -ENOENT;
} }
do_destroy(ctx); idr_remove(&ctx->file_priv->context_idr, ctx->id);
i915_gem_context_unreference(ctx);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_drv.h" #include "intel_drv.h"
typedef uint32_t gen6_gtt_pte_t;
/* PPGTT stuff */ /* PPGTT stuff */
#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0))
...@@ -44,29 +42,22 @@ typedef uint32_t gen6_gtt_pte_t; ...@@ -44,29 +42,22 @@ typedef uint32_t gen6_gtt_pte_t;
#define GEN6_PTE_CACHE_LLC_MLC (3 << 1) #define GEN6_PTE_CACHE_LLC_MLC (3 << 1)
#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr)
static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev, static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
dma_addr_t addr, dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = GEN6_PTE_VALID;
pte |= GEN6_PTE_ADDR_ENCODE(addr); pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) { switch (level) {
case I915_CACHE_LLC_MLC: case I915_CACHE_LLC_MLC:
/* Haswell doesn't set L3 this way */ pte |= GEN6_PTE_CACHE_LLC_MLC;
if (IS_HASWELL(dev))
pte |= GEN6_PTE_CACHE_LLC;
else
pte |= GEN6_PTE_CACHE_LLC_MLC;
break; break;
case I915_CACHE_LLC: case I915_CACHE_LLC:
pte |= GEN6_PTE_CACHE_LLC; pte |= GEN6_PTE_CACHE_LLC;
break; break;
case I915_CACHE_NONE: case I915_CACHE_NONE:
if (IS_HASWELL(dev)) pte |= GEN6_PTE_UNCACHED;
pte |= HSW_PTE_UNCACHED;
else
pte |= GEN6_PTE_UNCACHED;
break; break;
default: default:
BUG(); BUG();
...@@ -75,16 +66,48 @@ static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev, ...@@ -75,16 +66,48 @@ static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
return pte; return pte;
} }
static int gen6_ppgtt_enable(struct drm_device *dev) #define BYT_PTE_WRITEABLE (1 << 1)
#define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2)
static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
dma_addr_t addr,
enum i915_cache_level level)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; gen6_gtt_pte_t pte = GEN6_PTE_VALID;
uint32_t pd_offset; pte |= GEN6_PTE_ADDR_ENCODE(addr);
struct intel_ring_buffer *ring;
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; /* Mark the page as writeable. Other platforms don't have a
* setting for read-only/writable, so this matches that behavior.
*/
pte |= BYT_PTE_WRITEABLE;
if (level != I915_CACHE_NONE)
pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
return pte;
}
static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
dma_addr_t addr,
enum i915_cache_level level)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
if (level != I915_CACHE_NONE)
pte |= GEN6_PTE_CACHE_LLC;
return pte;
}
static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
{
struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
gen6_gtt_pte_t __iomem *pd_addr; gen6_gtt_pte_t __iomem *pd_addr;
uint32_t pd_entry; uint32_t pd_entry;
int i; int i;
WARN_ON(ppgtt->pd_offset & 0x3f);
pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm + pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
ppgtt->pd_offset / sizeof(gen6_gtt_pte_t); ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
for (i = 0; i < ppgtt->num_pd_entries; i++) { for (i = 0; i < ppgtt->num_pd_entries; i++) {
...@@ -97,6 +120,19 @@ static int gen6_ppgtt_enable(struct drm_device *dev) ...@@ -97,6 +120,19 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
writel(pd_entry, pd_addr + i); writel(pd_entry, pd_addr + i);
} }
readl(pd_addr); readl(pd_addr);
}
static int gen6_ppgtt_enable(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t pd_offset;
struct intel_ring_buffer *ring;
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
int i;
BUG_ON(ppgtt->pd_offset & 0x3f);
gen6_write_pdes(ppgtt);
pd_offset = ppgtt->pd_offset; pd_offset = ppgtt->pd_offset;
pd_offset /= 64; /* in cachelines, */ pd_offset /= 64; /* in cachelines, */
...@@ -154,9 +190,9 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, ...@@ -154,9 +190,9 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
unsigned last_pte, i; unsigned last_pte, i;
scratch_pte = gen6_pte_encode(ppgtt->dev, scratch_pte = ppgtt->pte_encode(ppgtt->dev,
ppgtt->scratch_page_dma_addr, ppgtt->scratch_page_dma_addr,
I915_CACHE_LLC); I915_CACHE_LLC);
while (num_entries) { while (num_entries) {
last_pte = first_pte + num_entries; last_pte = first_pte + num_entries;
...@@ -191,8 +227,8 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, ...@@ -191,8 +227,8 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
dma_addr_t page_addr; dma_addr_t page_addr;
page_addr = sg_page_iter_dma_address(&sg_iter); page_addr = sg_page_iter_dma_address(&sg_iter);
pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr, pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
cache_level); cache_level);
if (++act_pte == I915_PPGTT_PT_ENTRIES) { if (++act_pte == I915_PPGTT_PT_ENTRIES) {
kunmap_atomic(pt_vaddr); kunmap_atomic(pt_vaddr);
act_pt++; act_pt++;
...@@ -233,8 +269,15 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ...@@ -233,8 +269,15 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
* entries. For aliasing ppgtt support we just steal them at the end for * entries. For aliasing ppgtt support we just steal them at the end for
* now. */ * now. */
first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt); first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
if (IS_HASWELL(dev)) {
ppgtt->pte_encode = hsw_pte_encode;
} else if (IS_VALLEYVIEW(dev)) {
ppgtt->pte_encode = byt_pte_encode;
} else {
ppgtt->pte_encode = gen6_pte_encode;
}
ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
ppgtt->enable = gen6_ppgtt_enable; ppgtt->enable = gen6_ppgtt_enable;
ppgtt->clear_range = gen6_ppgtt_clear_range; ppgtt->clear_range = gen6_ppgtt_clear_range;
...@@ -437,7 +480,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev, ...@@ -437,7 +480,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
addr = sg_page_iter_dma_address(&sg_iter); addr = sg_page_iter_dma_address(&sg_iter);
iowrite32(gen6_pte_encode(dev, addr, level), &gtt_entries[i]); iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
&gtt_entries[i]);
i++; i++;
} }
...@@ -449,7 +493,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev, ...@@ -449,7 +493,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
*/ */
if (i != 0) if (i != 0)
WARN_ON(readl(&gtt_entries[i-1]) WARN_ON(readl(&gtt_entries[i-1])
!= gen6_pte_encode(dev, addr, level)); != dev_priv->gtt.pte_encode(dev, addr, level));
/* This next bit makes the above posting read even more important. We /* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates * want to flush the TLBs only after we're certain all the PTE updates
...@@ -474,8 +518,9 @@ static void gen6_ggtt_clear_range(struct drm_device *dev, ...@@ -474,8 +518,9 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
first_entry, num_entries, max_entries)) first_entry, num_entries, max_entries))
num_entries = max_entries; num_entries = max_entries;
scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma, scratch_pte = dev_priv->gtt.pte_encode(dev,
I915_CACHE_LLC); dev_priv->gtt.scratch_page_dma,
I915_CACHE_LLC);
for (i = 0; i < num_entries; i++) for (i = 0; i < num_entries; i++)
iowrite32(scratch_pte, &gtt_base[i]); iowrite32(scratch_pte, &gtt_base[i]);
readl(gtt_base); readl(gtt_base);
...@@ -809,6 +854,13 @@ int i915_gem_gtt_init(struct drm_device *dev) ...@@ -809,6 +854,13 @@ int i915_gem_gtt_init(struct drm_device *dev)
} else { } else {
dev_priv->gtt.gtt_probe = gen6_gmch_probe; dev_priv->gtt.gtt_probe = gen6_gmch_probe;
dev_priv->gtt.gtt_remove = gen6_gmch_remove; dev_priv->gtt.gtt_remove = gen6_gmch_remove;
if (IS_HASWELL(dev)) {
dev_priv->gtt.pte_encode = hsw_pte_encode;
} else if (IS_VALLEYVIEW(dev)) {
dev_priv->gtt.pte_encode = byt_pte_encode;
} else {
dev_priv->gtt.pte_encode = gen6_pte_encode;
}
} }
ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total, ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
......
...@@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) ...@@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
* its value of TOLUD. * its value of TOLUD.
*/ */
base = 0; base = 0;
if (INTEL_INFO(dev)->gen >= 6) { if (IS_VALLEYVIEW(dev)) {
pci_read_config_dword(dev->pdev, 0x5c, &base);
base &= ~((1<<20) - 1);
} else if (INTEL_INFO(dev)->gen >= 6) {
/* Read Base Data of Stolen Memory Register (BDSM) directly. /* Read Base Data of Stolen Memory Register (BDSM) directly.
* Note that there is also a MCHBAR miror at 0x1080c0 or * Note that there is also a MCHBAR miror at 0x1080c0 or
* we could use device 2:0x5c instead. * we could use device 2:0x5c instead.
...@@ -136,6 +139,7 @@ static int i915_setup_compression(struct drm_device *dev, int size) ...@@ -136,6 +139,7 @@ static int i915_setup_compression(struct drm_device *dev, int size)
err_fb: err_fb:
drm_mm_put_block(compressed_fb); drm_mm_put_block(compressed_fb);
err: err:
pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
return -ENOSPC; return -ENOSPC;
} }
...@@ -182,6 +186,7 @@ void i915_gem_cleanup_stolen(struct drm_device *dev) ...@@ -182,6 +186,7 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
int i915_gem_init_stolen(struct drm_device *dev) int i915_gem_init_stolen(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int bios_reserved = 0;
dev_priv->mm.stolen_base = i915_stolen_to_physical(dev); dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
if (dev_priv->mm.stolen_base == 0) if (dev_priv->mm.stolen_base == 0)
...@@ -190,8 +195,12 @@ int i915_gem_init_stolen(struct drm_device *dev) ...@@ -190,8 +195,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n", DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base); dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
if (IS_VALLEYVIEW(dev))
bios_reserved = 1024*1024; /* top 1M on VLV/BYT */
/* Basic memrange allocator for stolen space */ /* Basic memrange allocator for stolen space */
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size); drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
bios_reserved);
return 0; return 0;
} }
...@@ -330,7 +339,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, ...@@ -330,7 +339,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
/* KISS and expect everything to be page-aligned */ /* KISS and expect everything to be page-aligned */
BUG_ON(stolen_offset & 4095); BUG_ON(stolen_offset & 4095);
BUG_ON(gtt_offset & 4095);
BUG_ON(size & 4095); BUG_ON(size & 4095);
if (WARN_ON(size == 0)) if (WARN_ON(size == 0))
...@@ -351,6 +359,10 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, ...@@ -351,6 +359,10 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
return NULL; return NULL;
} }
/* Some objects just need physical mem from stolen space */
if (gtt_offset == -1)
return obj;
/* To simplify the initialisation sequence between KMS and GTT, /* To simplify the initialisation sequence between KMS and GTT,
* we allow construction of the stolen object prior to * we allow construction of the stolen object prior to
* setting up the GTT space. The actual reservation will occur * setting up the GTT space. The actual reservation will occur
......
This diff is collapsed.
This diff is collapsed.
...@@ -192,6 +192,7 @@ static void i915_restore_vga(struct drm_device *dev) ...@@ -192,6 +192,7 @@ static void i915_restore_vga(struct drm_device *dev)
static void i915_save_display(struct drm_device *dev) static void i915_save_display(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long flags;
/* Display arbitration control */ /* Display arbitration control */
if (INTEL_INFO(dev)->gen <= 4) if (INTEL_INFO(dev)->gen <= 4)
...@@ -202,6 +203,8 @@ static void i915_save_display(struct drm_device *dev) ...@@ -202,6 +203,8 @@ static void i915_save_display(struct drm_device *dev)
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_save_display_reg(dev); i915_save_display_reg(dev);
spin_lock_irqsave(&dev_priv->backlight.lock, flags);
/* LVDS state */ /* LVDS state */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL); dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
...@@ -222,6 +225,8 @@ static void i915_save_display(struct drm_device *dev) ...@@ -222,6 +225,8 @@ static void i915_save_display(struct drm_device *dev)
dev_priv->regfile.saveLVDS = I915_READ(LVDS); dev_priv->regfile.saveLVDS = I915_READ(LVDS);
} }
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL); dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
...@@ -257,6 +262,7 @@ static void i915_restore_display(struct drm_device *dev) ...@@ -257,6 +262,7 @@ static void i915_restore_display(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 mask = 0xffffffff; u32 mask = 0xffffffff;
unsigned long flags;
/* Display arbitration */ /* Display arbitration */
if (INTEL_INFO(dev)->gen <= 4) if (INTEL_INFO(dev)->gen <= 4)
...@@ -265,6 +271,8 @@ static void i915_restore_display(struct drm_device *dev) ...@@ -265,6 +271,8 @@ static void i915_restore_display(struct drm_device *dev)
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_restore_display_reg(dev); i915_restore_display_reg(dev);
spin_lock_irqsave(&dev_priv->backlight.lock, flags);
/* LVDS state */ /* LVDS state */
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
...@@ -304,6 +312,8 @@ static void i915_restore_display(struct drm_device *dev) ...@@ -304,6 +312,8 @@ static void i915_restore_display(struct drm_device *dev)
I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL); I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
} }
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
/* only restore FBC info on the platform that supports FBC*/ /* only restore FBC info on the platform that supports FBC*/
intel_disable_fbc(dev); intel_disable_fbc(dev);
if (I915_HAS_FBC(dev)) { if (I915_HAS_FBC(dev)) {
......
...@@ -212,7 +212,13 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, ...@@ -212,7 +212,13 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
int ret; int ret;
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; if (IS_VALLEYVIEW(dev_priv->dev)) {
u32 freq;
valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &freq);
ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
} else {
ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
}
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return snprintf(buf, PAGE_SIZE, "%d\n", ret); return snprintf(buf, PAGE_SIZE, "%d\n", ret);
...@@ -226,7 +232,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute ...@@ -226,7 +232,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
int ret; int ret;
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; if (IS_VALLEYVIEW(dev_priv->dev))
ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
else
ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return snprintf(buf, PAGE_SIZE, "%d\n", ret); return snprintf(buf, PAGE_SIZE, "%d\n", ret);
...@@ -246,16 +255,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, ...@@ -246,16 +255,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
if (ret) if (ret)
return ret; return ret;
val /= GT_FREQUENCY_MULTIPLIER;
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); if (IS_VALLEYVIEW(dev_priv->dev)) {
hw_max = dev_priv->rps.hw_max; val = vlv_freq_opcode(dev_priv->mem_freq, val);
non_oc_max = (rp_state_cap & 0xff);
hw_min = ((rp_state_cap & 0xff0000) >> 16); hw_max = valleyview_rps_max_freq(dev_priv);
hw_min = valleyview_rps_min_freq(dev_priv);
non_oc_max = hw_max;
} else {
val /= GT_FREQUENCY_MULTIPLIER;
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
hw_max = dev_priv->rps.hw_max;
non_oc_max = (rp_state_cap & 0xff);
hw_min = ((rp_state_cap & 0xff0000) >> 16);
}
if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) { if (val < hw_min || val > hw_max ||
val < dev_priv->rps.min_delay) {
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return -EINVAL; return -EINVAL;
} }
...@@ -264,8 +282,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, ...@@ -264,8 +282,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
DRM_DEBUG("User requested overclocking to %d\n", DRM_DEBUG("User requested overclocking to %d\n",
val * GT_FREQUENCY_MULTIPLIER); val * GT_FREQUENCY_MULTIPLIER);
if (dev_priv->rps.cur_delay > val) if (dev_priv->rps.cur_delay > val) {
gen6_set_rps(dev_priv->dev, val); if (IS_VALLEYVIEW(dev_priv->dev))
valleyview_set_rps(dev_priv->dev, val);
else
gen6_set_rps(dev_priv->dev, val);
}
dev_priv->rps.max_delay = val; dev_priv->rps.max_delay = val;
...@@ -282,7 +304,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute ...@@ -282,7 +304,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
int ret; int ret;
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; if (IS_VALLEYVIEW(dev_priv->dev))
ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
else
ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return snprintf(buf, PAGE_SIZE, "%d\n", ret); return snprintf(buf, PAGE_SIZE, "%d\n", ret);
...@@ -302,21 +327,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, ...@@ -302,21 +327,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
if (ret) if (ret)
return ret; return ret;
val /= GT_FREQUENCY_MULTIPLIER;
mutex_lock(&dev_priv->rps.hw_lock); mutex_lock(&dev_priv->rps.hw_lock);
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); if (IS_VALLEYVIEW(dev)) {
hw_max = dev_priv->rps.hw_max; val = vlv_freq_opcode(dev_priv->mem_freq, val);
hw_min = ((rp_state_cap & 0xff0000) >> 16);
hw_max = valleyview_rps_max_freq(dev_priv);
hw_min = valleyview_rps_min_freq(dev_priv);
} else {
val /= GT_FREQUENCY_MULTIPLIER;
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
hw_max = dev_priv->rps.hw_max;
hw_min = ((rp_state_cap & 0xff0000) >> 16);
}
if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) { if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return -EINVAL; return -EINVAL;
} }
if (dev_priv->rps.cur_delay < val) if (dev_priv->rps.cur_delay < val) {
gen6_set_rps(dev_priv->dev, val); if (IS_VALLEYVIEW(dev))
valleyview_set_rps(dev, val);
else
gen6_set_rps(dev_priv->dev, val);
}
dev_priv->rps.min_delay = val; dev_priv->rps.min_delay = val;
......
...@@ -148,13 +148,13 @@ void i915_save_display_reg(struct drm_device *dev) ...@@ -148,13 +148,13 @@ void i915_save_display_reg(struct drm_device *dev)
dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ); dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS); dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
dev_priv->regfile.saveTRANSACONF = I915_READ(_TRANSACONF); dev_priv->regfile.saveTRANSACONF = I915_READ(_PCH_TRANSACONF);
dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A); dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_PCH_TRANS_HTOTAL_A);
dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A); dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_PCH_TRANS_HBLANK_A);
dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A); dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_PCH_TRANS_HSYNC_A);
dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A); dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_PCH_TRANS_VTOTAL_A);
dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A); dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_PCH_TRANS_VBLANK_A);
dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A); dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_PCH_TRANS_VSYNC_A);
} }
dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR); dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR);
...@@ -205,13 +205,13 @@ void i915_save_display_reg(struct drm_device *dev) ...@@ -205,13 +205,13 @@ void i915_save_display_reg(struct drm_device *dev)
dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ); dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS); dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
dev_priv->regfile.saveTRANSBCONF = I915_READ(_TRANSBCONF); dev_priv->regfile.saveTRANSBCONF = I915_READ(_PCH_TRANSBCONF);
dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B); dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_PCH_TRANS_HTOTAL_B);
dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B); dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_PCH_TRANS_HBLANK_B);
dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B); dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_PCH_TRANS_HSYNC_B);
dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B); dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_PCH_TRANS_VTOTAL_B);
dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B); dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_PCH_TRANS_VBLANK_B);
dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B); dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_PCH_TRANS_VSYNC_B);
} }
dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR); dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR);
...@@ -259,14 +259,14 @@ void i915_save_display_reg(struct drm_device *dev) ...@@ -259,14 +259,14 @@ void i915_save_display_reg(struct drm_device *dev)
dev_priv->regfile.saveDP_B = I915_READ(DP_B); dev_priv->regfile.saveDP_B = I915_READ(DP_B);
dev_priv->regfile.saveDP_C = I915_READ(DP_C); dev_priv->regfile.saveDP_C = I915_READ(DP_C);
dev_priv->regfile.saveDP_D = I915_READ(DP_D); dev_priv->regfile.saveDP_D = I915_READ(DP_D);
dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M); dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_DATA_M_G4X);
dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M); dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_DATA_M_G4X);
dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N); dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_DATA_N_G4X);
dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N); dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_DATA_N_G4X);
dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M); dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_LINK_M_G4X);
dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M); dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_LINK_M_G4X);
dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N); dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_LINK_N_G4X);
dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N); dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_LINK_N_G4X);
} }
/* FIXME: regfile.save TV & SDVO state */ /* FIXME: regfile.save TV & SDVO state */
...@@ -282,14 +282,14 @@ void i915_restore_display_reg(struct drm_device *dev) ...@@ -282,14 +282,14 @@ void i915_restore_display_reg(struct drm_device *dev)
/* Display port ratios (must be done before clock is set) */ /* Display port ratios (must be done before clock is set) */
if (SUPPORTS_INTEGRATED_DP(dev)) { if (SUPPORTS_INTEGRATED_DP(dev)) {
I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->regfile.savePIPEA_GMCH_DATA_M); I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->regfile.savePIPEB_GMCH_DATA_M); I915_WRITE(_PIPEB_DATA_M_G4X, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->regfile.savePIPEA_GMCH_DATA_N); I915_WRITE(_PIPEA_DATA_N_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->regfile.savePIPEB_GMCH_DATA_N); I915_WRITE(_PIPEB_DATA_N_G4X, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->regfile.savePIPEA_DP_LINK_M); I915_WRITE(_PIPEA_LINK_M_G4X, dev_priv->regfile.savePIPEA_DP_LINK_M);
I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->regfile.savePIPEB_DP_LINK_M); I915_WRITE(_PIPEB_LINK_M_G4X, dev_priv->regfile.savePIPEB_DP_LINK_M);
I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->regfile.savePIPEA_DP_LINK_N); I915_WRITE(_PIPEA_LINK_N_G4X, dev_priv->regfile.savePIPEA_DP_LINK_N);
I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->regfile.savePIPEB_DP_LINK_N); I915_WRITE(_PIPEB_LINK_N_G4X, dev_priv->regfile.savePIPEB_DP_LINK_N);
} }
/* Fences */ /* Fences */
...@@ -379,13 +379,13 @@ void i915_restore_display_reg(struct drm_device *dev) ...@@ -379,13 +379,13 @@ void i915_restore_display_reg(struct drm_device *dev)
I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ); I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ);
I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS); I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS);
I915_WRITE(_TRANSACONF, dev_priv->regfile.saveTRANSACONF); I915_WRITE(_PCH_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
I915_WRITE(_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A); I915_WRITE(_PCH_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
I915_WRITE(_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A); I915_WRITE(_PCH_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
I915_WRITE(_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A); I915_WRITE(_PCH_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
I915_WRITE(_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A); I915_WRITE(_PCH_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
I915_WRITE(_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A); I915_WRITE(_PCH_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
I915_WRITE(_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A); I915_WRITE(_PCH_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
} }
/* Restore plane info */ /* Restore plane info */
...@@ -448,13 +448,13 @@ void i915_restore_display_reg(struct drm_device *dev) ...@@ -448,13 +448,13 @@ void i915_restore_display_reg(struct drm_device *dev)
I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ); I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ);
I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS); I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS);
I915_WRITE(_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF); I915_WRITE(_PCH_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
I915_WRITE(_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B); I915_WRITE(_PCH_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
I915_WRITE(_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B); I915_WRITE(_PCH_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
I915_WRITE(_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B); I915_WRITE(_PCH_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
I915_WRITE(_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B); I915_WRITE(_PCH_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
I915_WRITE(_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B); I915_WRITE(_PCH_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
I915_WRITE(_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B); I915_WRITE(_PCH_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
} }
/* Restore plane info */ /* Restore plane info */
......
...@@ -212,7 +212,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -212,7 +212,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
if (!lvds_options) if (!lvds_options)
return; return;
dev_priv->lvds_dither = lvds_options->pixel_dither; dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
if (lvds_options->panel_type == 0xff) if (lvds_options->panel_type == 0xff)
return; return;
...@@ -226,7 +226,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -226,7 +226,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
if (!lvds_lfp_data_ptrs) if (!lvds_lfp_data_ptrs)
return; return;
dev_priv->lvds_vbt = 1; dev_priv->vbt.lvds_vbt = 1;
panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
lvds_lfp_data_ptrs, lvds_lfp_data_ptrs,
...@@ -238,7 +238,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -238,7 +238,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing); fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n"); DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode); drm_mode_debug_printmodeline(panel_fixed_mode);
...@@ -274,9 +274,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -274,9 +274,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
/* check the resolution, just to be sure */ /* check the resolution, just to be sure */
if (fp_timing->x_res == panel_fixed_mode->hdisplay && if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
fp_timing->y_res == panel_fixed_mode->vdisplay) { fp_timing->y_res == panel_fixed_mode->vdisplay) {
dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; dev_priv->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
DRM_DEBUG_KMS("VBT initial LVDS value %x\n", DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
dev_priv->bios_lvds_val); dev_priv->vbt.bios_lvds_val);
} }
} }
} }
...@@ -316,7 +316,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, ...@@ -316,7 +316,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
fill_detail_timing_data(panel_fixed_mode, dvo_timing + index); fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; dev_priv->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n"); DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode); drm_mode_debug_printmodeline(panel_fixed_mode);
...@@ -345,20 +345,20 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -345,20 +345,20 @@ parse_general_features(struct drm_i915_private *dev_priv,
general = find_section(bdb, BDB_GENERAL_FEATURES); general = find_section(bdb, BDB_GENERAL_FEATURES);
if (general) { if (general) {
dev_priv->int_tv_support = general->int_tv_support; dev_priv->vbt.int_tv_support = general->int_tv_support;
dev_priv->int_crt_support = general->int_crt_support; dev_priv->vbt.int_crt_support = general->int_crt_support;
dev_priv->lvds_use_ssc = general->enable_ssc; dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
dev_priv->lvds_ssc_freq = dev_priv->vbt.lvds_ssc_freq =
intel_bios_ssc_frequency(dev, general->ssc_freq); intel_bios_ssc_frequency(dev, general->ssc_freq);
dev_priv->display_clock_mode = general->display_clock_mode; dev_priv->vbt.display_clock_mode = general->display_clock_mode;
dev_priv->fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted; dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n", DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
dev_priv->int_tv_support, dev_priv->vbt.int_tv_support,
dev_priv->int_crt_support, dev_priv->vbt.int_crt_support,
dev_priv->lvds_use_ssc, dev_priv->vbt.lvds_use_ssc,
dev_priv->lvds_ssc_freq, dev_priv->vbt.lvds_ssc_freq,
dev_priv->display_clock_mode, dev_priv->vbt.display_clock_mode,
dev_priv->fdi_rx_polarity_inverted); dev_priv->vbt.fdi_rx_polarity_inverted);
} }
} }
...@@ -375,7 +375,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, ...@@ -375,7 +375,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
int bus_pin = general->crt_ddc_gmbus_pin; int bus_pin = general->crt_ddc_gmbus_pin;
DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
if (intel_gmbus_is_port_valid(bus_pin)) if (intel_gmbus_is_port_valid(bus_pin))
dev_priv->crt_ddc_pin = bus_pin; dev_priv->vbt.crt_ddc_pin = bus_pin;
} else { } else {
DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
block_size); block_size);
...@@ -486,7 +486,7 @@ parse_driver_features(struct drm_i915_private *dev_priv, ...@@ -486,7 +486,7 @@ parse_driver_features(struct drm_i915_private *dev_priv,
if (SUPPORTS_EDP(dev) && if (SUPPORTS_EDP(dev) &&
driver->lvds_config == BDB_DRIVER_FEATURE_EDP) driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->edp.support = 1; dev_priv->vbt.edp_support = 1;
if (driver->dual_frequency) if (driver->dual_frequency)
dev_priv->render_reclock_avail = true; dev_priv->render_reclock_avail = true;
...@@ -501,20 +501,20 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) ...@@ -501,20 +501,20 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
edp = find_section(bdb, BDB_EDP); edp = find_section(bdb, BDB_EDP);
if (!edp) { if (!edp) {
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support)
DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
return; return;
} }
switch ((edp->color_depth >> (panel_type * 2)) & 3) { switch ((edp->color_depth >> (panel_type * 2)) & 3) {
case EDP_18BPP: case EDP_18BPP:
dev_priv->edp.bpp = 18; dev_priv->vbt.edp_bpp = 18;
break; break;
case EDP_24BPP: case EDP_24BPP:
dev_priv->edp.bpp = 24; dev_priv->vbt.edp_bpp = 24;
break; break;
case EDP_30BPP: case EDP_30BPP:
dev_priv->edp.bpp = 30; dev_priv->vbt.edp_bpp = 30;
break; break;
} }
...@@ -522,48 +522,48 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) ...@@ -522,48 +522,48 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
edp_pps = &edp->power_seqs[panel_type]; edp_pps = &edp->power_seqs[panel_type];
edp_link_params = &edp->link_params[panel_type]; edp_link_params = &edp->link_params[panel_type];
dev_priv->edp.pps = *edp_pps; dev_priv->vbt.edp_pps = *edp_pps;
dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : dev_priv->vbt.edp_rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
DP_LINK_BW_1_62; DP_LINK_BW_1_62;
switch (edp_link_params->lanes) { switch (edp_link_params->lanes) {
case 0: case 0:
dev_priv->edp.lanes = 1; dev_priv->vbt.edp_lanes = 1;
break; break;
case 1: case 1:
dev_priv->edp.lanes = 2; dev_priv->vbt.edp_lanes = 2;
break; break;
case 3: case 3:
default: default:
dev_priv->edp.lanes = 4; dev_priv->vbt.edp_lanes = 4;
break; break;
} }
switch (edp_link_params->preemphasis) { switch (edp_link_params->preemphasis) {
case 0: case 0:
dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
break; break;
case 1: case 1:
dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
break; break;
case 2: case 2:
dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
break; break;
case 3: case 3:
dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
break; break;
} }
switch (edp_link_params->vswing) { switch (edp_link_params->vswing) {
case 0: case 0:
dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_400;
break; break;
case 1: case 1:
dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_600;
break; break;
case 2: case 2:
dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_800;
break; break;
case 3: case 3:
dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_1200;
break; break;
} }
} }
...@@ -611,13 +611,13 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -611,13 +611,13 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
return; return;
} }
dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); dev_priv->vbt.child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
if (!dev_priv->child_dev) { if (!dev_priv->vbt.child_dev) {
DRM_DEBUG_KMS("No memory space for child device\n"); DRM_DEBUG_KMS("No memory space for child device\n");
return; return;
} }
dev_priv->child_dev_num = count; dev_priv->vbt.child_dev_num = count;
count = 0; count = 0;
for (i = 0; i < child_device_num; i++) { for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]); p_child = &(p_defs->devices[i]);
...@@ -625,7 +625,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -625,7 +625,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
/* skip the device block if device type is invalid */ /* skip the device block if device type is invalid */
continue; continue;
} }
child_dev_ptr = dev_priv->child_dev + count; child_dev_ptr = dev_priv->vbt.child_dev + count;
count++; count++;
memcpy((void *)child_dev_ptr, (void *)p_child, memcpy((void *)child_dev_ptr, (void *)p_child,
sizeof(*p_child)); sizeof(*p_child));
...@@ -638,23 +638,23 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) ...@@ -638,23 +638,23 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
/* LFP panel data */ /* LFP panel data */
dev_priv->lvds_dither = 1; dev_priv->vbt.lvds_dither = 1;
dev_priv->lvds_vbt = 0; dev_priv->vbt.lvds_vbt = 0;
/* SDVO panel data */ /* SDVO panel data */
dev_priv->sdvo_lvds_vbt_mode = NULL; dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
/* general features */ /* general features */
dev_priv->int_tv_support = 1; dev_priv->vbt.int_tv_support = 1;
dev_priv->int_crt_support = 1; dev_priv->vbt.int_crt_support = 1;
/* Default to using SSC */ /* Default to using SSC */
dev_priv->lvds_use_ssc = 1; dev_priv->vbt.lvds_use_ssc = 1;
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
} }
static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
......
...@@ -207,6 +207,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, ...@@ -207,6 +207,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
pipe_config->has_pch_encoder = true; pipe_config->has_pch_encoder = true;
/* LPT FDI RX only supports 8bpc. */
if (HAS_PCH_LPT(dev))
pipe_config->pipe_bpp = 24;
return true; return true;
} }
...@@ -431,7 +435,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) ...@@ -431,7 +435,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG); BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
edid = intel_crt_get_edid(connector, i2c); edid = intel_crt_get_edid(connector, i2c);
if (edid) { if (edid) {
...@@ -637,7 +641,7 @@ static int intel_crt_get_modes(struct drm_connector *connector) ...@@ -637,7 +641,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
int ret; int ret;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
ret = intel_crt_ddc_get_modes(connector, i2c); ret = intel_crt_ddc_get_modes(connector, i2c);
if (ret || !IS_G4X(dev)) if (ret || !IS_G4X(dev))
return ret; return ret;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -120,7 +120,6 @@ struct intel_encoder { ...@@ -120,7 +120,6 @@ struct intel_encoder {
struct intel_crtc *new_crtc; struct intel_crtc *new_crtc;
int type; int type;
bool needs_tv_clock;
/* /*
* Intel hw has only one MUX where encoders could be clone, hence a * Intel hw has only one MUX where encoders could be clone, hence a
* simple flag is enough to compute the possible_clones mask. * simple flag is enough to compute the possible_clones mask.
...@@ -177,6 +176,18 @@ struct intel_connector { ...@@ -177,6 +176,18 @@ struct intel_connector {
u8 polled; u8 polled;
}; };
typedef struct dpll {
/* given values */
int n;
int m1, m2;
int p1, p2;
/* derived values */
int dot;
int vco;
int m;
int p;
} intel_clock_t;
struct intel_crtc_config { struct intel_crtc_config {
struct drm_display_mode requested_mode; struct drm_display_mode requested_mode;
struct drm_display_mode adjusted_mode; struct drm_display_mode adjusted_mode;
...@@ -201,18 +212,30 @@ struct intel_crtc_config { ...@@ -201,18 +212,30 @@ struct intel_crtc_config {
/* DP has a bunch of special case unfortunately, so mark the pipe /* DP has a bunch of special case unfortunately, so mark the pipe
* accordingly. */ * accordingly. */
bool has_dp_encoder; bool has_dp_encoder;
/*
* Enable dithering, used when the selected pipe bpp doesn't match the
* plane bpp.
*/
bool dither; bool dither;
/* Controls for the clock computation, to override various stages. */ /* Controls for the clock computation, to override various stages. */
bool clock_set; bool clock_set;
/* SDVO TV has a bunch of special case. To make multifunction encoders
* work correctly, we need to track this at runtime.*/
bool sdvo_tv_clock;
/*
* crtc bandwidth limit, don't increase pipe bpp or clock if not really
* required. This is set in the 2nd loop of calling encoder's
* ->compute_config if the first pick doesn't work out.
*/
bool bw_constrained;
/* Settings for the intel dpll used on pretty much everything but /* Settings for the intel dpll used on pretty much everything but
* haswell. */ * haswell. */
struct dpll { struct dpll dpll;
unsigned n;
unsigned m1, m2;
unsigned p1, p2;
} dpll;
int pipe_bpp; int pipe_bpp;
struct intel_link_m_n dp_m_n; struct intel_link_m_n dp_m_n;
...@@ -224,6 +247,23 @@ struct intel_crtc_config { ...@@ -224,6 +247,23 @@ struct intel_crtc_config {
int pixel_target_clock; int pixel_target_clock;
/* Used by SDVO (and if we ever fix it, HDMI). */ /* Used by SDVO (and if we ever fix it, HDMI). */
unsigned pixel_multiplier; unsigned pixel_multiplier;
/* Panel fitter controls for gen2-gen4 + VLV */
struct {
u32 control;
u32 pgm_ratios;
u32 lvds_border_bits;
} gmch_pfit;
/* Panel fitter placement and size for Ironlake+ */
struct {
u32 pos;
u32 size;
} pch_pfit;
/* FDI configuration, only valid if has_pch_encoder is set. */
int fdi_lanes;
struct intel_link_m_n fdi_m_n;
}; };
struct intel_crtc { struct intel_crtc {
...@@ -242,7 +282,6 @@ struct intel_crtc { ...@@ -242,7 +282,6 @@ struct intel_crtc {
bool lowfreq_avail; bool lowfreq_avail;
struct intel_overlay *overlay; struct intel_overlay *overlay;
struct intel_unpin_work *unpin_work; struct intel_unpin_work *unpin_work;
int fdi_lanes;
atomic_t unpin_work_count; atomic_t unpin_work_count;
...@@ -265,6 +304,10 @@ struct intel_crtc { ...@@ -265,6 +304,10 @@ struct intel_crtc {
/* reset counter value when the last flip was submitted */ /* reset counter value when the last flip was submitted */
unsigned int reset_counter; unsigned int reset_counter;
/* Access to these should be protected by dev_priv->irq_lock. */
bool cpu_fifo_underrun_disabled;
bool pch_fifo_underrun_disabled;
}; };
struct intel_plane { struct intel_plane {
...@@ -411,7 +454,6 @@ struct intel_dp { ...@@ -411,7 +454,6 @@ struct intel_dp {
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo; struct i2c_algo_dp_aux_data algo;
bool is_pch_edp;
uint8_t train_set[4]; uint8_t train_set[4];
int panel_power_up_delay; int panel_power_up_delay;
int panel_power_down_delay; int panel_power_down_delay;
...@@ -431,6 +473,19 @@ struct intel_digital_port { ...@@ -431,6 +473,19 @@ struct intel_digital_port {
struct intel_hdmi hdmi; struct intel_hdmi hdmi;
}; };
static inline int
vlv_dport_to_channel(struct intel_digital_port *dport)
{
switch (dport->port) {
case PORT_B:
return 0;
case PORT_C:
return 1;
default:
BUG();
}
}
static inline struct drm_crtc * static inline struct drm_crtc *
intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
{ {
...@@ -474,6 +529,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); ...@@ -474,6 +529,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
extern void intel_attach_force_audio_property(struct drm_connector *connector); extern void intel_attach_force_audio_property(struct drm_connector *connector);
extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
extern void intel_crt_init(struct drm_device *dev); extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, extern void intel_hdmi_init(struct drm_device *dev,
int hdmi_reg, enum port port); int hdmi_reg, enum port port);
...@@ -512,7 +568,6 @@ extern void ironlake_edp_panel_on(struct intel_dp *intel_dp); ...@@ -512,7 +568,6 @@ extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
extern void ironlake_edp_panel_off(struct intel_dp *intel_dp); extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp); extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
enum plane plane); enum plane plane);
...@@ -524,12 +579,14 @@ extern void intel_panel_fini(struct intel_panel *panel); ...@@ -524,12 +579,14 @@ extern void intel_panel_fini(struct intel_panel *panel);
extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
extern void intel_pch_panel_fitting(struct drm_device *dev, extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
int fitting_mode, struct intel_crtc_config *pipe_config,
const struct drm_display_mode *mode, int fitting_mode);
struct drm_display_mode *adjusted_mode); extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
extern u32 intel_panel_get_max_backlight(struct drm_device *dev); struct intel_crtc_config *pipe_config,
extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); int fitting_mode);
extern void intel_panel_set_backlight(struct drm_device *dev,
u32 level, u32 max);
extern int intel_panel_setup_backlight(struct drm_connector *connector); extern int intel_panel_setup_backlight(struct drm_connector *connector);
extern void intel_panel_enable_backlight(struct drm_device *dev, extern void intel_panel_enable_backlight(struct drm_device *dev,
enum pipe pipe); enum pipe pipe);
...@@ -565,19 +622,17 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector ...@@ -565,19 +622,17 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
return to_intel_connector(connector)->encoder; return to_intel_connector(connector)->encoder;
} }
static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port =
container_of(encoder, struct intel_digital_port, base.base);
return &intel_dig_port->dp;
}
static inline struct intel_digital_port * static inline struct intel_digital_port *
enc_to_dig_port(struct drm_encoder *encoder) enc_to_dig_port(struct drm_encoder *encoder)
{ {
return container_of(encoder, struct intel_digital_port, base.base); return container_of(encoder, struct intel_digital_port, base.base);
} }
static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{
return &enc_to_dig_port(encoder)->dp;
}
static inline struct intel_digital_port * static inline struct intel_digital_port *
dp_to_dig_port(struct intel_dp *intel_dp) dp_to_dig_port(struct intel_dp *intel_dp)
{ {
...@@ -607,6 +662,7 @@ intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, ...@@ -607,6 +662,7 @@ intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
extern void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
struct intel_load_detect_pipe { struct intel_load_detect_pipe {
struct drm_framebuffer *release_fb; struct drm_framebuffer *release_fb;
...@@ -660,13 +716,9 @@ extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, ...@@ -660,13 +716,9 @@ extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
#define assert_pipe_disabled(d, p) assert_pipe(d, p, false) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
extern void intel_init_clock_gating(struct drm_device *dev); extern void intel_init_clock_gating(struct drm_device *dev);
extern void intel_suspend_hw(struct drm_device *dev);
extern void intel_write_eld(struct drm_encoder *encoder, extern void intel_write_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode); struct drm_display_mode *mode);
extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
extern void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n);
extern void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n);
extern void intel_prepare_ddi(struct drm_device *dev); extern void intel_prepare_ddi(struct drm_device *dev);
extern void hsw_fdi_link_train(struct drm_crtc *crtc); extern void hsw_fdi_link_train(struct drm_crtc *crtc);
extern void intel_ddi_init(struct drm_device *dev, enum port port); extern void intel_ddi_init(struct drm_device *dev, enum port port);
...@@ -690,6 +742,8 @@ extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, ...@@ -690,6 +742,8 @@ extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg); extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
extern void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
u32 val);
/* Power-related functions, located in intel_pm.c */ /* Power-related functions, located in intel_pm.c */
extern void intel_init_pm(struct drm_device *dev); extern void intel_init_pm(struct drm_device *dev);
...@@ -701,7 +755,8 @@ extern void intel_update_fbc(struct drm_device *dev); ...@@ -701,7 +755,8 @@ extern void intel_update_fbc(struct drm_device *dev);
extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
extern void intel_gpu_ips_teardown(void); extern void intel_gpu_ips_teardown(void);
extern bool intel_using_power_well(struct drm_device *dev); extern bool intel_display_power_enabled(struct drm_device *dev,
enum intel_display_power_domain domain);
extern void intel_init_power_well(struct drm_device *dev); extern void intel_init_power_well(struct drm_device *dev);
extern void intel_set_power_well(struct drm_device *dev, bool enable); extern void intel_set_power_well(struct drm_device *dev, bool enable);
extern void intel_enable_gt_powersave(struct drm_device *dev); extern void intel_enable_gt_powersave(struct drm_device *dev);
...@@ -728,5 +783,11 @@ intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); ...@@ -728,5 +783,11 @@ intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
extern void intel_display_handle_reset(struct drm_device *dev); extern void intel_display_handle_reset(struct drm_device *dev);
extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable);
extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable);
#endif /* __INTEL_DRV_H__ */ #endif /* __INTEL_DRV_H__ */
...@@ -53,6 +53,13 @@ static const struct intel_dvo_device intel_dvo_devices[] = { ...@@ -53,6 +53,13 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.slave_addr = CH7xxx_ADDR, .slave_addr = CH7xxx_ADDR,
.dev_ops = &ch7xxx_ops, .dev_ops = &ch7xxx_ops,
}, },
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "ch7xxx",
.dvo_reg = DVOC,
.slave_addr = 0x75, /* For some ch7010 */
.dev_ops = &ch7xxx_ops,
},
{ {
.type = INTEL_DVO_CHIP_LVDS, .type = INTEL_DVO_CHIP_LVDS,
.name = "ivch", .name = "ivch",
......
...@@ -697,6 +697,14 @@ static void intel_enable_hdmi(struct intel_encoder *encoder) ...@@ -697,6 +697,14 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
I915_WRITE(intel_hdmi->hdmi_reg, temp); I915_WRITE(intel_hdmi->hdmi_reg, temp);
POSTING_READ(intel_hdmi->hdmi_reg); POSTING_READ(intel_hdmi->hdmi_reg);
} }
if (IS_VALLEYVIEW(dev)) {
struct intel_digital_port *dport =
enc_to_dig_port(&encoder->base);
int channel = vlv_dport_to_channel(dport);
vlv_wait_port_ready(dev_priv, channel);
}
} }
static void intel_disable_hdmi(struct intel_encoder *encoder) static void intel_disable_hdmi(struct intel_encoder *encoder)
...@@ -775,6 +783,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -775,6 +783,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
int desired_bpp;
if (intel_hdmi->color_range_auto) { if (intel_hdmi->color_range_auto) {
/* See CEA-861-E - 5.1 Default Encoding Parameters */ /* See CEA-861-E - 5.1 Default Encoding Parameters */
...@@ -794,14 +804,31 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -794,14 +804,31 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
/* /*
* HDMI is either 12 or 8, so if the display lets 10bpc sneak * HDMI is either 12 or 8, so if the display lets 10bpc sneak
* through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
* outputs. * outputs. We also need to check that the higher clock still fits
* within limits.
*/ */
if (pipe_config->pipe_bpp > 8*3 && HAS_PCH_SPLIT(dev)) { if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000
DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n"); && HAS_PCH_SPLIT(dev)) {
pipe_config->pipe_bpp = 12*3; DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
desired_bpp = 12*3;
/* Need to adjust the port link by 1.5x for 12bpc. */
adjusted_mode->clock = clock_12bpc;
pipe_config->pixel_target_clock =
pipe_config->requested_mode.clock;
} else { } else {
DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n"); DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n");
pipe_config->pipe_bpp = 8*3; desired_bpp = 8*3;
}
if (!pipe_config->bw_constrained) {
DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI\n", desired_bpp);
pipe_config->pipe_bpp = desired_bpp;
}
if (adjusted_mode->clock > 225000) {
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
return false;
} }
return true; return true;
...@@ -955,6 +982,101 @@ intel_hdmi_set_property(struct drm_connector *connector, ...@@ -955,6 +982,101 @@ intel_hdmi_set_property(struct drm_connector *connector,
return 0; return 0;
} }
static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc =
to_intel_crtc(encoder->base.crtc);
int port = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
u32 val;
if (!IS_VALLEYVIEW(dev))
return;
WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
/* Enable clock channels for this port */
val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
val = 0;
if (pipe)
val |= (1<<21);
else
val &= ~(1<<21);
val |= 0x001000c4;
intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
/* HDMI 1.0V-2dB */
intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0);
intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port),
0x2b245f5f);
intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
0x5578b83a);
intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port),
0x0c782040);
intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port),
0x2b247878);
intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
0x00002000);
intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
DPIO_TX_OCALINIT_EN);
/* Program lane clock */
intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
0x00760018);
intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
0x00400888);
}
static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int port = vlv_dport_to_channel(dport);
if (!IS_VALLEYVIEW(dev))
return;
WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
/* Program Tx lane resets to default */
intel_dpio_write(dev_priv, DPIO_PCS_TX(port),
DPIO_PCS_TX_LANE2_RESET |
DPIO_PCS_TX_LANE1_RESET);
intel_dpio_write(dev_priv, DPIO_PCS_CLK(port),
DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
(1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
DPIO_PCS_CLK_SOFT_RESET);
/* Fix up inter-pair skew failure */
intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
intel_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
intel_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
0x00002000);
intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
DPIO_TX_OCALINIT_EN);
}
static void intel_hdmi_post_disable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
int port = vlv_dport_to_channel(dport);
/* Reset lanes to avoid HDMI flicker (VLV w/a) */
mutex_lock(&dev_priv->dpio_lock);
intel_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000);
intel_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060);
mutex_unlock(&dev_priv->dpio_lock);
}
static void intel_hdmi_destroy(struct drm_connector *connector) static void intel_hdmi_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector); drm_sysfs_connector_remove(connector);
...@@ -1094,6 +1216,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) ...@@ -1094,6 +1216,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
intel_encoder->enable = intel_enable_hdmi; intel_encoder->enable = intel_enable_hdmi;
intel_encoder->disable = intel_disable_hdmi; intel_encoder->disable = intel_disable_hdmi;
intel_encoder->get_hw_state = intel_hdmi_get_hw_state; intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
if (IS_VALLEYVIEW(dev)) {
intel_encoder->pre_enable = intel_hdmi_pre_enable;
intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
intel_encoder->post_disable = intel_hdmi_post_disable;
}
intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->type = INTEL_OUTPUT_HDMI;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -515,6 +515,8 @@ static int init_render_ring(struct intel_ring_buffer *ring) ...@@ -515,6 +515,8 @@ static int init_render_ring(struct intel_ring_buffer *ring)
/* We need to disable the AsyncFlip performance optimisations in order /* We need to disable the AsyncFlip performance optimisations in order
* to use MI_WAIT_FOR_EVENT within the CS. It should already be * to use MI_WAIT_FOR_EVENT within the CS. It should already be
* programmed to '1' on all products. * programmed to '1' on all products.
*
* WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
*/ */
if (INTEL_INFO(dev)->gen >= 6) if (INTEL_INFO(dev)->gen >= 6)
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
......
...@@ -135,7 +135,7 @@ struct intel_ring_buffer { ...@@ -135,7 +135,7 @@ struct intel_ring_buffer {
*/ */
bool itlb_before_ctx_switch; bool itlb_before_ctx_switch;
struct i915_hw_context *default_context; struct i915_hw_context *default_context;
struct drm_i915_gem_object *last_context_obj; struct i915_hw_context *last_context;
void *private; void *private;
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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