pipe_size = ddb_size / config->num_pipes_active;
alloc->start = nth_active_pipe * ddb_size / config->num_pipes_active;
- alloc->end = alloc->start + pipe_size - 1;
+ alloc->end = alloc->start + pipe_size;
}
static unsigned int skl_cursor_allocation(const struct intel_wm_config *config)
return 8;
}
+static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg)
+{
+ entry->start = reg & 0x3ff;
+ entry->end = (reg >> 16) & 0x3ff;
+ if (entry->end)
+ entry->end += 1;
+}
+
+void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
+ struct skl_ddb_allocation *ddb /* out */)
+{
+ struct drm_device *dev = dev_priv->dev;
+ enum pipe pipe;
+ int plane;
+ u32 val;
+
+ for_each_pipe(dev_priv, pipe) {
+ for_each_plane(pipe, plane) {
+ val = I915_READ(PLANE_BUF_CFG(pipe, plane));
+ skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane],
+ val);
+ }
+
+ val = I915_READ(CUR_BUF_CFG(pipe));
+ skl_ddb_entry_init_from_hw(&ddb->cursor[pipe], val);
+ }
+}
+
static unsigned int
skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p)
{
}
cursor_blocks = skl_cursor_allocation(config);
- ddb->cursor[pipe].start = alloc.end - cursor_blocks + 1;
+ ddb->cursor[pipe].start = alloc.end - cursor_blocks;
ddb->cursor[pipe].end = alloc.end;
alloc_size -= cursor_blocks;
total_data_rate);
ddb->plane[pipe][plane].start = start;
- ddb->plane[pipe][plane].end = start + plane_blocks - 1;
+ ddb->plane[pipe][plane].end = start + plane_blocks;
start += plane_blocks;
}
return ret;
}
-static void skl_compute_transition_wm(struct drm_crtc *crtc,
- struct skl_pipe_wm_parameters *params,
- struct skl_pipe_wm *pipe_wm)
-{
- /*
- * For now it is suggested to use the LP0 wm val of corresponding
- * plane as transition wm val. This is done while computing results.
- */
- if (!params->active)
- return;
-}
-
-static uint32_t
-skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p)
-{
- if (!intel_crtc_active(crtc))
- return 0;
-
- return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate);
-
-}
-
static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
const struct intel_crtc *intel_crtc)
{
}
static bool skl_compute_plane_wm(struct skl_pipe_wm_parameters *p,
- struct intel_plane_wm_parameters *p_params,
- uint16_t max_page_buff_alloc,
- uint32_t mem_value,
- uint16_t *res_blocks, /* out */
- uint8_t *res_lines /* out */)
+ struct intel_plane_wm_parameters *p_params,
+ uint16_t ddb_allocation,
+ uint32_t mem_value,
+ uint16_t *out_blocks, /* out */
+ uint8_t *out_lines /* out */)
{
- uint32_t method1, method2, plane_bytes_per_line;
+ uint32_t method1, method2, plane_bytes_per_line, res_blocks, res_lines;
uint32_t result_bytes;
if (mem_value == 0 || !p->active || !p_params->enabled)
p_params->bytes_per_pixel;
/* For now xtile and linear */
- if (((max_page_buff_alloc * 512) / plane_bytes_per_line) >= 1)
+ if (((ddb_allocation * 512) / plane_bytes_per_line) >= 1)
result_bytes = min(method1, method2);
else
result_bytes = method1;
- *res_blocks = DIV_ROUND_UP(result_bytes, 512) + 1;
- *res_lines = DIV_ROUND_UP(result_bytes, plane_bytes_per_line);
+ res_blocks = DIV_ROUND_UP(result_bytes, 512) + 1;
+ res_lines = DIV_ROUND_UP(result_bytes, plane_bytes_per_line);
+
+ if (res_blocks > ddb_allocation || res_lines > 31)
+ return false;
+
+ *out_blocks = res_blocks;
+ *out_lines = res_lines;
return true;
}
&result->cursor_res_l);
}
+static uint32_t
+skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p)
+{
+ if (!intel_crtc_active(crtc))
+ return 0;
+
+ return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate);
+
+}
+
+static void skl_compute_transition_wm(struct drm_crtc *crtc,
+ struct skl_pipe_wm_parameters *params,
+ struct skl_wm_level *trans_wm /* out */)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int i;
+
+ if (!params->active)
+ return;
+
+ /* Until we know more, just disable transition WMs */
+ for (i = 0; i < intel_num_planes(intel_crtc); i++)
+ trans_wm->plane_en[i] = false;
+ trans_wm->cursor_en = false;
+}
+
static void skl_compute_pipe_wm(struct drm_crtc *crtc,
struct skl_ddb_allocation *ddb,
struct skl_pipe_wm_parameters *params,
}
pipe_wm->linetime = skl_compute_linetime_wm(crtc, params);
- skl_compute_transition_wm(crtc, params, pipe_wm);
+ skl_compute_transition_wm(crtc, params, &pipe_wm->trans_wm);
}
static void skl_compute_wm_results(struct drm_device *dev,
{
int level, max_level = ilk_wm_max_level(dev);
enum pipe pipe = intel_crtc->pipe;
+ uint32_t temp;
+ int i;
for (level = 0; level <= max_level; level++) {
- uint16_t ddb_blocks;
- uint32_t temp;
- int i;
-
for (i = 0; i < intel_num_planes(intel_crtc); i++) {
temp = 0;
- ddb_blocks = skl_ddb_entry_size(&r->ddb.plane[pipe][i]);
-
- if ((p_wm->wm[level].plane_res_b[i] > ddb_blocks) ||
- (p_wm->wm[level].plane_res_l[i] > 31))
- p_wm->wm[level].plane_en[i] = false;
temp |= p_wm->wm[level].plane_res_l[i] <<
PLANE_WM_LINES_SHIFT;
temp |= PLANE_WM_EN;
r->plane[pipe][i][level] = temp;
- /* Use the LP0 WM value for transition WM for now. */
- if (level == 0)
- r->plane_trans[pipe][i] = temp;
}
temp = 0;
- ddb_blocks = skl_ddb_entry_size(&r->ddb.cursor[pipe]);
-
- if ((p_wm->wm[level].cursor_res_b > ddb_blocks) ||
- (p_wm->wm[level].cursor_res_l > 31))
- p_wm->wm[level].cursor_en = false;
temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT;
temp |= p_wm->wm[level].cursor_res_b;
temp |= PLANE_WM_EN;
r->cursor[pipe][level] = temp;
- /* Use the LP0 WM value for transition WM for now. */
- if (level == 0)
- r->cursor_trans[pipe] = temp;
}
+ /* transition WMs */
+ for (i = 0; i < intel_num_planes(intel_crtc); i++) {
+ temp = 0;
+ temp |= p_wm->trans_wm.plane_res_l[i] << PLANE_WM_LINES_SHIFT;
+ temp |= p_wm->trans_wm.plane_res_b[i];
+ if (p_wm->trans_wm.plane_en[i])
+ temp |= PLANE_WM_EN;
+
+ r->plane_trans[pipe][i] = temp;
+ }
+
+ temp = 0;
+ temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT;
+ temp |= p_wm->trans_wm.cursor_res_b;
+ if (p_wm->trans_wm.cursor_en)
+ temp |= PLANE_WM_EN;
+
+ r->cursor_trans[pipe] = temp;
+
r->wm_linetime[pipe] = p_wm->linetime;
}
+static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, uint32_t reg,
+ const struct skl_ddb_entry *entry)
+{
+ if (entry->end)
+ I915_WRITE(reg, (entry->end - 1) << 16 | entry->start);
+ else
+ I915_WRITE(reg, 0);
+}
+
static void skl_write_wm_values(struct drm_i915_private *dev_priv,
const struct skl_wm_values *new)
{
I915_WRITE(CUR_WM_TRANS(pipe), new->cursor_trans[pipe]);
for (i = 0; i < intel_num_planes(crtc); i++)
- I915_WRITE(PLANE_BUF_CFG(pipe, i),
- new->ddb.plane[pipe][i].end << 16 |
- new->ddb.plane[pipe][i].start);
+ skl_ddb_entry_write(dev_priv,
+ PLANE_BUF_CFG(pipe, i),
+ &new->ddb.plane[pipe][i]);
- I915_WRITE(CUR_BUF_CFG(pipe),
- new->ddb.cursor[pipe].end << 16 |
- new->ddb.cursor[pipe].start);
+ skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe),
+ &new->ddb.cursor[pipe]);
}
}
}
void skl_wm_get_hw_state(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
struct drm_crtc *crtc;
+ skl_ddb_get_hw_state(dev_priv, ddb);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
skl_pipe_wm_get_hw_state(crtc);
}