Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 7143 → Rev 7144

/drivers/video/drm/i915/intel_pm.c
37,6 → 37,8
void getrawmonotonic(struct timespec *ts);
 
/**
* DOC: RC6
*
* RC6 is a special power stage which allows the GPU to enter an very
* low-voltage mode when idle, using down to 0V while at this stage. This
* stage is entered automatically when the GPU is idle when RC6 support is
551,7 → 553,7
* intel_calculate_wm - calculate watermark level
* @clock_in_khz: pixel clock
* @wm: chip FIFO params
* @pixel_size: display pixel size
* @cpp: bytes per pixel
* @latency_ns: memory latency for the platform
*
* Calculate the watermark level (the level at which the display plane will
567,8 → 569,7
*/
static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
const struct intel_watermark_params *wm,
int fifo_size,
int pixel_size,
int fifo_size, int cpp,
unsigned long latency_ns)
{
long entries_required, wm_size;
579,7 → 580,7
* clocks go from a few thousand to several hundred thousand.
* latency is usually a few thousand
*/
entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
entries_required = ((clock_in_khz / 1000) * cpp * latency_ns) /
1000;
entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size);
 
643,13 → 644,13
crtc = single_enabled_crtc(dev);
if (crtc) {
const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
int clock = adjusted_mode->crtc_clock;
 
/* Display SR */
wm = intel_calculate_wm(clock, &pineview_display_wm,
pineview_display_wm.fifo_size,
pixel_size, latency->display_sr);
cpp, latency->display_sr);
reg = I915_READ(DSPFW1);
reg &= ~DSPFW_SR_MASK;
reg |= FW_WM(wm, SR);
659,7 → 660,7
/* cursor SR */
wm = intel_calculate_wm(clock, &pineview_cursor_wm,
pineview_display_wm.fifo_size,
pixel_size, latency->cursor_sr);
cpp, latency->cursor_sr);
reg = I915_READ(DSPFW3);
reg &= ~DSPFW_CURSOR_SR_MASK;
reg |= FW_WM(wm, CURSOR_SR);
668,7 → 669,7
/* Display HPLL off SR */
wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
pineview_display_hplloff_wm.fifo_size,
pixel_size, latency->display_hpll_disable);
cpp, latency->display_hpll_disable);
reg = I915_READ(DSPFW3);
reg &= ~DSPFW_HPLL_SR_MASK;
reg |= FW_WM(wm, HPLL_SR);
677,7 → 678,7
/* cursor HPLL off SR */
wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
pineview_display_hplloff_wm.fifo_size,
pixel_size, latency->cursor_hpll_disable);
cpp, latency->cursor_hpll_disable);
reg = I915_READ(DSPFW3);
reg &= ~DSPFW_HPLL_CURSOR_MASK;
reg |= FW_WM(wm, HPLL_CURSOR);
701,7 → 702,7
{
struct drm_crtc *crtc;
const struct drm_display_mode *adjusted_mode;
int htotal, hdisplay, clock, pixel_size;
int htotal, hdisplay, clock, cpp;
int line_time_us, line_count;
int entries, tlb_miss;
 
716,10 → 717,10
clock = adjusted_mode->crtc_clock;
htotal = adjusted_mode->crtc_htotal;
hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
 
/* Use the small buffer method to calculate plane watermark */
entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
entries = ((clock * cpp / 1000) * display_latency_ns) / 1000;
tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
if (tlb_miss > 0)
entries += tlb_miss;
731,7 → 732,7
/* Use the large buffer method to calculate cursor watermark */
line_time_us = max(htotal * 1000 / clock, 1);
line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
entries = line_count * crtc->cursor->state->crtc_w * pixel_size;
entries = line_count * crtc->cursor->state->crtc_w * cpp;
tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
if (tlb_miss > 0)
entries += tlb_miss;
787,7 → 788,7
{
struct drm_crtc *crtc;
const struct drm_display_mode *adjusted_mode;
int hdisplay, htotal, pixel_size, clock;
int hdisplay, htotal, cpp, clock;
unsigned long line_time_us;
int line_count, line_size;
int small, large;
803,14 → 804,14
clock = adjusted_mode->crtc_clock;
htotal = adjusted_mode->crtc_htotal;
hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
 
line_time_us = max(htotal * 1000 / clock, 1);
line_count = (latency_ns / line_time_us + 1000) / 1000;
line_size = hdisplay * pixel_size;
line_size = hdisplay * cpp;
 
/* Use the minimum of the small and large buffer method for primary */
small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
small = ((clock * cpp / 1000) * latency_ns) / 1000;
large = line_count * line_size;
 
entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
817,7 → 818,7
*display_wm = entries + display->guard_size;
 
/* calculate the self-refresh watermark for display cursor */
entries = line_count * pixel_size * crtc->cursor->state->crtc_w;
entries = line_count * cpp * crtc->cursor->state->crtc_w;
entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
*cursor_wm = entries + cursor->guard_size;
 
909,13 → 910,13
static unsigned int vlv_wm_method2(unsigned int pixel_rate,
unsigned int pipe_htotal,
unsigned int horiz_pixels,
unsigned int bytes_per_pixel,
unsigned int cpp,
unsigned int latency)
{
unsigned int ret;
 
ret = (latency * pixel_rate) / (pipe_htotal * 10000);
ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
ret = (ret + 1) * horiz_pixels * cpp;
ret = DIV_ROUND_UP(ret, 64);
 
return ret;
944,7 → 945,7
int level)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
int clock, htotal, pixel_size, width, wm;
int clock, htotal, cpp, width, wm;
 
if (dev_priv->wm.pri_latency[level] == 0)
return USHRT_MAX;
952,7 → 953,7
if (!state->visible)
return 0;
 
pixel_size = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
cpp = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
clock = crtc->config->base.adjusted_mode.crtc_clock;
htotal = crtc->config->base.adjusted_mode.crtc_htotal;
width = crtc->config->pipe_src_w;
968,7 → 969,7
*/
wm = 63;
} else {
wm = vlv_wm_method2(clock, htotal, width, pixel_size,
wm = vlv_wm_method2(clock, htotal, width, cpp,
dev_priv->wm.pri_latency[level] * 10);
}
 
1442,7 → 1443,7
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
unsigned long line_time_us;
int entries;
 
1450,7 → 1451,7
 
/* Use ns/us then divide to preserve precision */
entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * hdisplay;
cpp * hdisplay;
entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
srwm = I965_FIFO_SIZE - entries;
if (srwm < 0)
1460,7 → 1461,7
entries, srwm);
 
entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * crtc->cursor->state->crtc_w;
cpp * crtc->cursor->state->crtc_w;
entries = DIV_ROUND_UP(entries,
i965_cursor_wm_info.cacheline_size);
cursor_sr = i965_cursor_wm_info.fifo_size -
1521,7 → 1522,7
crtc = intel_get_crtc_for_plane(dev, 0);
if (intel_crtc_active(crtc)) {
const struct drm_display_mode *adjusted_mode;
int cpp = crtc->primary->state->fb->bits_per_pixel / 8;
int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
if (IS_GEN2(dev))
cpp = 4;
 
1543,7 → 1544,7
crtc = intel_get_crtc_for_plane(dev, 1);
if (intel_crtc_active(crtc)) {
const struct drm_display_mode *adjusted_mode;
int cpp = crtc->primary->state->fb->bits_per_pixel / 8;
int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
if (IS_GEN2(dev))
cpp = 4;
 
1589,7 → 1590,7
int clock = adjusted_mode->crtc_clock;
int htotal = adjusted_mode->crtc_htotal;
int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w;
int pixel_size = enabled->primary->state->fb->bits_per_pixel / 8;
int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0);
unsigned long line_time_us;
int entries;
 
1597,7 → 1598,7
 
/* Use ns/us then divide to preserve precision */
entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
pixel_size * hdisplay;
cpp * hdisplay;
entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
srwm = wm_info->fifo_size - entries;
1677,6 → 1678,9
if (pipe_h < pfit_h)
pipe_h = pfit_h;
 
if (WARN_ON(!pfit_w || !pfit_h))
return pixel_rate;
 
pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
pfit_w * pfit_h);
}
1685,8 → 1689,7
}
 
/* latency must be in 0.1us units. */
static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
uint32_t latency)
static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency)
{
uint64_t ret;
 
1693,7 → 1696,7
if (WARN(latency == 0, "Latency value missing\n"))
return UINT_MAX;
 
ret = (uint64_t) pixel_rate * bytes_per_pixel * latency;
ret = (uint64_t) pixel_rate * cpp * latency;
ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2;
 
return ret;
1701,7 → 1704,7
 
/* latency must be in 0.1us units. */
static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
uint32_t horiz_pixels, uint8_t bytes_per_pixel,
uint32_t horiz_pixels, uint8_t cpp,
uint32_t latency)
{
uint32_t ret;
1708,17 → 1711,30
 
if (WARN(latency == 0, "Latency value missing\n"))
return UINT_MAX;
if (WARN_ON(!pipe_htotal))
return UINT_MAX;
 
ret = (latency * pixel_rate) / (pipe_htotal * 10000);
ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
ret = (ret + 1) * horiz_pixels * cpp;
ret = DIV_ROUND_UP(ret, 64) + 2;
return ret;
}
 
static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
uint8_t bytes_per_pixel)
uint8_t cpp)
{
return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
/*
* Neither of these should be possible since this function shouldn't be
* called if the CRTC is off or the plane is invisible. But let's be
* extra paranoid to avoid a potential divide-by-zero if we screw up
* elsewhere in the driver.
*/
if (WARN_ON(!cpp))
return 0;
if (WARN_ON(!horiz_pixels))
return 0;
 
return DIV_ROUND_UP(pri_val * 64, horiz_pixels * cpp) + 2;
}
 
struct ilk_wm_maximums {
1737,13 → 1753,14
uint32_t mem_value,
bool is_lp)
{
int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
int cpp = pstate->base.fb ?
drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
uint32_t method1, method2;
 
if (!cstate->base.active || !pstate->visible)
return 0;
 
method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
 
if (!is_lp)
return method1;
1751,8 → 1768,7
method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
cstate->base.adjusted_mode.crtc_htotal,
drm_rect_width(&pstate->dst),
bpp,
mem_value);
cpp, mem_value);
 
return min(method1, method2);
}
1765,18 → 1781,18
const struct intel_plane_state *pstate,
uint32_t mem_value)
{
int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
int cpp = pstate->base.fb ?
drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
uint32_t method1, method2;
 
if (!cstate->base.active || !pstate->visible)
return 0;
 
method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
cstate->base.adjusted_mode.crtc_htotal,
drm_rect_width(&pstate->dst),
bpp,
mem_value);
cpp, mem_value);
return min(method1, method2);
}
 
1809,12 → 1825,13
const struct intel_plane_state *pstate,
uint32_t pri_val)
{
int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
int cpp = pstate->base.fb ?
drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
 
if (!cstate->base.active || !pstate->visible)
return 0;
 
return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), bpp);
return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), cpp);
}
 
static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
2007,15 → 2024,20
}
 
static uint32_t
hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
hsw_compute_linetime_wm(struct drm_device *dev,
struct intel_crtc_state *cstate)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
const struct drm_display_mode *adjusted_mode =
&cstate->base.adjusted_mode;
u32 linetime, ips_linetime;
 
if (!intel_crtc->active)
if (!cstate->base.active)
return 0;
if (WARN_ON(adjusted_mode->crtc_clock == 0))
return 0;
if (WARN_ON(dev_priv->cdclk_freq == 0))
return 0;
 
/* The WM are computed with base on how long it takes to fill a single
* row at the given clock rate, multiplied by 8.
2323,8 → 2345,7
pristate, sprstate, curstate, &pipe_wm->wm[0]);
 
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
pipe_wm->linetime = hsw_compute_linetime_wm(dev,
&intel_crtc->base);
pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate);
 
/* LP0 watermarks always use 1/2 DDB partitioning */
ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
2860,25 → 2881,28
const struct drm_plane_state *pstate,
int y)
{
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
struct drm_framebuffer *fb = pstate->fb;
uint32_t width = 0, height = 0;
 
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
 
if (intel_rotation_90_or_270(pstate->rotation))
swap(width, height);
 
/* for planar format */
if (fb->pixel_format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
return intel_crtc->config->pipe_src_w *
intel_crtc->config->pipe_src_h *
return width * height *
drm_format_plane_cpp(fb->pixel_format, 0);
else /* uv-plane data rate */
return (intel_crtc->config->pipe_src_w/2) *
(intel_crtc->config->pipe_src_h/2) *
return (width / 2) * (height / 2) *
drm_format_plane_cpp(fb->pixel_format, 1);
}
 
/* for packed formats */
return intel_crtc->config->pipe_src_w *
intel_crtc->config->pipe_src_h *
drm_format_plane_cpp(fb->pixel_format, 0);
return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
}
 
/*
2957,8 → 2981,9
struct drm_framebuffer *fb = plane->state->fb;
int id = skl_wm_plane_id(intel_plane);
 
if (fb == NULL)
if (!to_intel_plane_state(plane->state)->visible)
continue;
 
if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
 
2984,7 → 3009,7
uint16_t plane_blocks, y_plane_blocks = 0;
int id = skl_wm_plane_id(intel_plane);
 
if (pstate->fb == NULL)
if (!to_intel_plane_state(pstate)->visible)
continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
3034,12 → 3059,11
 
/*
* The max latency should be 257 (max the punit can code is 255 and we add 2us
* for the read latency) and bytes_per_pixel should always be <= 8, so that
* for the read latency) and cpp should always be <= 8, so that
* should allow pixel_rate up to ~2 GHz which seems sufficient since max
* 2xcdclk is 1350 MHz and the pixel rate should never exceed that.
*/
static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
uint32_t latency)
static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency)
{
uint32_t wm_intermediate_val, ret;
 
3046,7 → 3070,7
if (latency == 0)
return UINT_MAX;
 
wm_intermediate_val = latency * pixel_rate * bytes_per_pixel / 512;
wm_intermediate_val = latency * pixel_rate * cpp / 512;
ret = DIV_ROUND_UP(wm_intermediate_val, 1000);
 
return ret;
3053,7 → 3077,7
}
 
static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
uint32_t horiz_pixels, uint8_t bytes_per_pixel,
uint32_t horiz_pixels, uint8_t cpp,
uint64_t tiling, uint32_t latency)
{
uint32_t ret;
3063,7 → 3087,7
if (latency == 0)
return UINT_MAX;
 
plane_bytes_per_line = horiz_pixels * bytes_per_pixel;
plane_bytes_per_line = horiz_pixels * cpp;
 
if (tiling == I915_FORMAT_MOD_Y_TILED ||
tiling == I915_FORMAT_MOD_Yf_TILED) {
3108,28 → 3132,36
{
struct drm_plane *plane = &intel_plane->base;
struct drm_framebuffer *fb = plane->state->fb;
struct intel_plane_state *intel_pstate =
to_intel_plane_state(plane->state);
uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line;
uint32_t res_blocks, res_lines;
uint32_t selected_result;
uint8_t bytes_per_pixel;
uint8_t cpp;
uint32_t width = 0, height = 0;
 
if (latency == 0 || !cstate->base.active || !fb)
if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
return false;
 
bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0);
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
 
if (intel_rotation_90_or_270(plane->state->rotation))
swap(width, height);
 
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
bytes_per_pixel,
latency);
cpp, latency);
method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
cstate->base.adjusted_mode.crtc_htotal,
cstate->pipe_src_w,
bytes_per_pixel,
width,
cpp,
fb->modifier[0],
latency);
 
plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel;
plane_bytes_per_line = width * cpp;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
 
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
3137,11 → 3169,11
uint32_t min_scanlines = 4;
uint32_t y_tile_minimum;
if (intel_rotation_90_or_270(plane->state->rotation)) {
int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
drm_format_plane_cpp(fb->pixel_format, 1) :
drm_format_plane_cpp(fb->pixel_format, 0);
 
switch (bpp) {
switch (cpp) {
case 1:
min_scanlines = 16;
break;
3630,9 → 3662,11
}
}
 
static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
static void ilk_program_watermarks(struct intel_crtc_state *cstate)
{
struct drm_device *dev = dev_priv->dev;
struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
struct ilk_wm_maximums max;
struct intel_wm_config config = {};
3665,7 → 3699,6
 
static void ilk_update_wm(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
 
3685,7 → 3718,7
 
intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
 
ilk_program_watermarks(dev_priv);
ilk_program_watermarks(cstate);
}
 
static void skl_pipe_wm_active_state(uint32_t val,
4073,7 → 4106,7
dev_priv->display.update_wm(crtc);
}
 
/**
/*
* Lock protecting IPS related data structures
*/
DEFINE_SPINLOCK(mchdev_lock);
4109,11 → 4142,13
static void ironlake_enable_drps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 rgvmodectl = I915_READ(MEMMODECTL);
u32 rgvmodectl;
u8 fmax, fmin, fstart, vstart;
 
spin_lock_irq(&mchdev_lock);
 
rgvmodectl = I915_READ(MEMMODECTL);
 
/* Enable temp reporting */
I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
4546,21 → 4581,71
}
if (HAS_RC6p(dev))
DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s RC6p %s RC6pp %s\n",
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
(mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
onoff(mode & GEN6_RC_CTL_RC6_ENABLE),
onoff(mode & GEN6_RC_CTL_RC6p_ENABLE),
onoff(mode & GEN6_RC_CTL_RC6pp_ENABLE));
 
else
DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s\n",
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
onoff(mode & GEN6_RC_CTL_RC6_ENABLE));
}
 
static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
bool enable_rc6 = true;
unsigned long rc6_ctx_base;
 
if (!(I915_READ(RC6_LOCATION) & RC6_CTX_IN_DRAM)) {
DRM_DEBUG_KMS("RC6 Base location not set properly.\n");
enable_rc6 = false;
}
 
/*
* The exact context size is not known for BXT, so assume a page size
* for this check.
*/
rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) &&
(rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base +
dev_priv->gtt.stolen_reserved_size))) {
DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
enable_rc6 = false;
}
 
if (!(((I915_READ(PWRCTX_MAXCNT_RCSUNIT) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_VCSUNIT0) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_BCSUNIT) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_VECSUNIT) & IDLE_TIME_MASK) > 1))) {
DRM_DEBUG_KMS("Engine Idle wait time not set properly.\n");
enable_rc6 = false;
}
 
if (!(I915_READ(GEN6_RC_CONTROL) & (GEN6_RC_CTL_RC6_ENABLE |
GEN6_RC_CTL_HW_ENABLE)) &&
((I915_READ(GEN6_RC_CONTROL) & GEN6_RC_CTL_HW_ENABLE) ||
!(I915_READ(GEN6_RC_STATE) & RC6_STATE))) {
DRM_DEBUG_KMS("HW/SW RC6 is not enabled by BIOS.\n");
enable_rc6 = false;
}
 
return enable_rc6;
}
 
int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
{
/* No RC6 before Ironlake and code is gone for ilk. */
if (INTEL_INFO(dev)->gen < 6)
return 0;
 
if (!enable_rc6)
return 0;
 
if (IS_BROXTON(dev) && !bxt_check_bios_rc6_setup(dev)) {
DRM_INFO("RC6 disabled by BIOS\n");
return 0;
}
 
/* Respect the kernel parameter if it is set */
if (enable_rc6 >= 0) {
int mask;
4730,8 → 4815,7
/* 3a: Enable RC6 */
if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
"on" : "off");
DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE));
/* WaRsUseTimeoutMode */
if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
4750,8 → 4834,7
* 3b: Enable Coarse Power Gating only when RC6 is enabled.
* WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6.
*/
if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_F0)))
if (NEEDS_WaRsDisableCoarsePowerGating(dev))
I915_WRITE(GEN9_PG_ENABLE, 0);
else
I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
5169,8 → 5252,6
u32 pcbr;
int pctx_size = 32*1024;
 
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
pcbr = I915_READ(VLV_PCBR);
if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n");
5192,7 → 5273,7
u32 pcbr;
int pctx_size = 24*1024;
 
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
mutex_lock(&dev->struct_mutex);
 
pcbr = I915_READ(VLV_PCBR);
if (pcbr) {
5220,7 → 5301,7
pctx = i915_gem_object_create_stolen(dev, pctx_size);
if (!pctx) {
DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
return;
goto out;
}
 
pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start;
5229,6 → 5310,7
out:
DRM_DEBUG_DRIVER("PCBR: 0x%08x\n", I915_READ(VLV_PCBR));
dev_priv->vlv_pctx = pctx;
mutex_unlock(&dev->struct_mutex);
}
 
static void valleyview_cleanup_pctx(struct drm_device *dev)
5238,7 → 5320,7
if (WARN_ON(!dev_priv->vlv_pctx))
return;
 
drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
drm_gem_object_unreference_unlocked(&dev_priv->vlv_pctx->base);
dev_priv->vlv_pctx = NULL;
}
 
6047,7 → 6129,6
{
struct drm_i915_private *dev_priv = dev->dev_private;
 
i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
/*
* RPM depends on RC6 to save restore the GT HW context, so make RC6 a
* requirement.
6182,8 → 6263,8
return;
 
if (IS_IRONLAKE_M(dev)) {
ironlake_enable_drps(dev);
mutex_lock(&dev->struct_mutex);
ironlake_enable_drps(dev);
intel_init_emon(dev);
mutex_unlock(&dev->struct_mutex);
} else if (INTEL_INFO(dev)->gen >= 6) {
7019,6 → 7100,7
dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
dev_priv->display.update_wm = ilk_update_wm;
dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
dev_priv->display.program_watermarks = ilk_program_watermarks;
} else {
DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n");
7184,9 → 7266,10
{
int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
 
div = vlv_gpu_freq_div(czclk_freq) / 2;
div = vlv_gpu_freq_div(czclk_freq);
if (div < 0)
return div;
div /= 2;
 
return DIV_ROUND_CLOSEST(czclk_freq * val, 2 * div) / 2;
}
7195,9 → 7278,10
{
int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
 
mul = vlv_gpu_freq_div(czclk_freq) / 2;
mul = vlv_gpu_freq_div(czclk_freq);
if (mul < 0)
return mul;
mul /= 2;
 
/* CHV needs even values */
return DIV_ROUND_CLOSEST(val * 2 * mul, czclk_freq) * 2;