Commit 20325e8a authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2018-11-15' of...

Merge tag 'drm-intel-fixes-2018-11-15' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

- Fix Bugzilla #108712: Fix incorrect EU count report from kernel
- Fix to account for scale factor when calculating initial phase on scaled output
- Avoid too trigger-happy HPD storm detection and fix a race and an OOPS for MST systems.
- Relocation race fix for Gen4/5
- A couple ICL fixes and dependencies for above Fixes:.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181115164709.GA13430@jlahtine-desk.ger.corp.intel.com
parents 9826b113 6e8adf6f
...@@ -474,7 +474,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) ...@@ -474,7 +474,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
u8 eu_disabled_mask; u8 eu_disabled_mask;
u32 n_disabled; u32 n_disabled;
if (!(sseu->subslice_mask[ss] & BIT(ss))) if (!(sseu->subslice_mask[s] & BIT(ss)))
/* skip disabled subslice */ /* skip disabled subslice */
continue; continue;
......
...@@ -4850,8 +4850,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) ...@@ -4850,8 +4850,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
* chroma samples for both of the luma samples, and thus we don't * chroma samples for both of the luma samples, and thus we don't
* actually get the expected MPEG2 chroma siting convention :( * actually get the expected MPEG2 chroma siting convention :(
* The same behaviour is observed on pre-SKL platforms as well. * The same behaviour is observed on pre-SKL platforms as well.
*
* Theory behind the formula (note that we ignore sub-pixel
* source coordinates):
* s = source sample position
* d = destination sample position
*
* Downscaling 4:1:
* -0.5
* | 0.0
* | | 1.5 (initial phase)
* | | |
* v v v
* | s | s | s | s |
* | d |
*
* Upscaling 1:4:
* -0.5
* | -0.375 (initial phase)
* | | 0.0
* | | |
* v v v
* | s |
* | d | d | d | d |
*/ */
u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
{ {
int phase = -0x8000; int phase = -0x8000;
u16 trip = 0; u16 trip = 0;
...@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) ...@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
if (chroma_cosited) if (chroma_cosited)
phase += (sub - 1) * 0x8000 / sub; phase += (sub - 1) * 0x8000 / sub;
phase += scale / (2 * sub);
/*
* Hardware initial phase limited to [-0.5:1.5].
* Since the max hardware scale factor is 3.0, we
* should never actually excdeed 1.0 here.
*/
WARN_ON(phase < -0x8000 || phase > 0x18000);
if (phase < 0) if (phase < 0)
phase = 0x10000 + phase; phase = 0x10000 + phase;
else else
...@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc) ...@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
if (crtc->config->pch_pfit.enabled) { if (crtc->config->pch_pfit.enabled) {
u16 uv_rgb_hphase, uv_rgb_vphase; u16 uv_rgb_hphase, uv_rgb_vphase;
int pfit_w, pfit_h, hscale, vscale;
int id; int id;
if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
return; return;
uv_rgb_hphase = skl_scaler_calc_phase(1, false); pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
uv_rgb_vphase = skl_scaler_calc_phase(1, false); pfit_h = crtc->config->pch_pfit.size & 0xFFFF;
hscale = (crtc->config->pipe_src_w << 16) / pfit_w;
vscale = (crtc->config->pipe_src_h << 16) / pfit_h;
uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
id = scaler_state->scaler_id; id = scaler_state->scaler_id;
I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN | I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
......
...@@ -452,6 +452,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo ...@@ -452,6 +452,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (!intel_connector) if (!intel_connector)
return NULL; return NULL;
intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
intel_connector->mst_port = intel_dp;
intel_connector->port = port;
connector = &intel_connector->base; connector = &intel_connector->base;
ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
DRM_MODE_CONNECTOR_DisplayPort); DRM_MODE_CONNECTOR_DisplayPort);
...@@ -462,10 +466,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo ...@@ -462,10 +466,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
intel_connector->mst_port = intel_dp;
intel_connector->port = port;
for_each_pipe(dev_priv, pipe) { for_each_pipe(dev_priv, pipe) {
struct drm_encoder *enc = struct drm_encoder *enc =
&intel_dp->mst_encoders[pipe]->base.base; &intel_dp->mst_encoders[pipe]->base.base;
......
...@@ -1646,7 +1646,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -1646,7 +1646,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state); struct intel_crtc_state *crtc_state);
u16 skl_scaler_calc_phase(int sub, bool chroma_center); u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(const struct intel_crtc_state *crtc_state, int skl_max_scale(const struct intel_crtc_state *crtc_state,
u32 pixel_format); u32 pixel_format);
......
...@@ -228,7 +228,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) ...@@ -228,7 +228,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
drm_for_each_connector_iter(connector, &conn_iter) { drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_connector *intel_connector = to_intel_connector(connector);
if (intel_connector->encoder->hpd_pin == pin) { /* Don't check MST ports, they don't have pins */
if (!intel_connector->mst_port &&
intel_connector->encoder->hpd_pin == pin) {
if (connector->polled != intel_connector->polled) if (connector->polled != intel_connector->polled)
DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n", DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
connector->name); connector->name);
...@@ -395,38 +397,55 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, ...@@ -395,38 +397,55 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
struct intel_encoder *encoder; struct intel_encoder *encoder;
bool storm_detected = false; bool storm_detected = false;
bool queue_dig = false, queue_hp = false; bool queue_dig = false, queue_hp = false;
u32 long_hpd_pulse_mask = 0;
u32 short_hpd_pulse_mask = 0;
enum hpd_pin pin;
if (!pin_mask) if (!pin_mask)
return; return;
spin_lock(&dev_priv->irq_lock); spin_lock(&dev_priv->irq_lock);
/*
* Determine whether ->hpd_pulse() exists for each pin, and
* whether we have a short or a long pulse. This is needed
* as each pin may have up to two encoders (HDMI and DP) and
* only the one of them (DP) will have ->hpd_pulse().
*/
for_each_intel_encoder(&dev_priv->drm, encoder) { for_each_intel_encoder(&dev_priv->drm, encoder) {
enum hpd_pin pin = encoder->hpd_pin;
bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder); bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
enum port port = encoder->port;
bool long_hpd;
pin = encoder->hpd_pin;
if (!(BIT(pin) & pin_mask)) if (!(BIT(pin) & pin_mask))
continue; continue;
if (has_hpd_pulse) { if (!has_hpd_pulse)
bool long_hpd = long_mask & BIT(pin); continue;
enum port port = encoder->port;
long_hpd = long_mask & BIT(pin);
DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port), DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
long_hpd ? "long" : "short"); long_hpd ? "long" : "short");
/*
* For long HPD pulses we want to have the digital queue happen,
* but we still want HPD storm detection to function.
*/
queue_dig = true; queue_dig = true;
if (long_hpd) { if (long_hpd) {
dev_priv->hotplug.long_port_mask |= (1 << port); long_hpd_pulse_mask |= BIT(pin);
dev_priv->hotplug.long_port_mask |= BIT(port);
} else { } else {
/* for short HPD just trigger the digital queue */ short_hpd_pulse_mask |= BIT(pin);
dev_priv->hotplug.short_port_mask |= (1 << port); dev_priv->hotplug.short_port_mask |= BIT(port);
continue;
} }
} }
/* Now process each pin just once */
for_each_hpd_pin(pin) {
bool long_hpd;
if (!(BIT(pin) & pin_mask))
continue;
if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) { if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
/* /*
* On GMCH platforms the interrupt mask bits only * On GMCH platforms the interrupt mask bits only
...@@ -442,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, ...@@ -442,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED) if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
continue; continue;
if (!has_hpd_pulse) { /*
* Delegate to ->hpd_pulse() if one of the encoders for this
* pin has it, otherwise let the hotplug_work deal with this
* pin directly.
*/
if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) {
long_hpd = long_hpd_pulse_mask & BIT(pin);
} else {
dev_priv->hotplug.event_bits |= BIT(pin); dev_priv->hotplug.event_bits |= BIT(pin);
long_hpd = true;
queue_hp = true; queue_hp = true;
} }
if (!long_hpd)
continue;
if (intel_hpd_irq_storm_detect(dev_priv, pin)) { if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
dev_priv->hotplug.event_bits &= ~BIT(pin); dev_priv->hotplug.event_bits &= ~BIT(pin);
storm_detected = true; storm_detected = true;
......
...@@ -424,7 +424,8 @@ static u64 execlists_update_context(struct i915_request *rq) ...@@ -424,7 +424,8 @@ static u64 execlists_update_context(struct i915_request *rq)
reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail); reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
/* True 32b PPGTT with dynamic page allocation: update PDP /*
* True 32b PPGTT with dynamic page allocation: update PDP
* registers and point the unallocated PDPs to scratch page. * registers and point the unallocated PDPs to scratch page.
* PML4 is allocated during ppgtt init, so this is not needed * PML4 is allocated during ppgtt init, so this is not needed
* in 48-bit mode. * in 48-bit mode.
...@@ -432,6 +433,17 @@ static u64 execlists_update_context(struct i915_request *rq) ...@@ -432,6 +433,17 @@ static u64 execlists_update_context(struct i915_request *rq)
if (ppgtt && !i915_vm_is_48bit(&ppgtt->vm)) if (ppgtt && !i915_vm_is_48bit(&ppgtt->vm))
execlists_update_context_pdps(ppgtt, reg_state); execlists_update_context_pdps(ppgtt, reg_state);
/*
* Make sure the context image is complete before we submit it to HW.
*
* Ostensibly, writes (including the WCB) should be flushed prior to
* an uncached write such as our mmio register access, the empirical
* evidence (esp. on Braswell) suggests that the WC write into memory
* may not be visible to the HW prior to the completion of the UC
* register write and that we may begin execution from the context
* before its image is complete leading to invalid PD chasing.
*/
wmb();
return ce->lrc_desc; return ce->lrc_desc;
} }
......
...@@ -91,6 +91,7 @@ static int ...@@ -91,6 +91,7 @@ static int
gen4_render_ring_flush(struct i915_request *rq, u32 mode) gen4_render_ring_flush(struct i915_request *rq, u32 mode)
{ {
u32 cmd, *cs; u32 cmd, *cs;
int i;
/* /*
* read/write caches: * read/write caches:
...@@ -127,12 +128,45 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode) ...@@ -127,12 +128,45 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
cmd |= MI_INVALIDATE_ISP; cmd |= MI_INVALIDATE_ISP;
} }
cs = intel_ring_begin(rq, 2); i = 2;
if (mode & EMIT_INVALIDATE)
i += 20;
cs = intel_ring_begin(rq, i);
if (IS_ERR(cs)) if (IS_ERR(cs))
return PTR_ERR(cs); return PTR_ERR(cs);
*cs++ = cmd; *cs++ = cmd;
*cs++ = MI_NOOP;
/*
* A random delay to let the CS invalidate take effect? Without this
* delay, the GPU relocation path fails as the CS does not see
* the updated contents. Just as important, if we apply the flushes
* to the EMIT_FLUSH branch (i.e. immediately after the relocation
* write and before the invalidate on the next batch), the relocations
* still fail. This implies that is a delay following invalidation
* that is required to reset the caches as opposed to a delay to
* ensure the memory is written.
*/
if (mode & EMIT_INVALIDATE) {
*cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
*cs++ = i915_ggtt_offset(rq->engine->scratch) |
PIPE_CONTROL_GLOBAL_GTT;
*cs++ = 0;
*cs++ = 0;
for (i = 0; i < 12; i++)
*cs++ = MI_FLUSH;
*cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
*cs++ = i915_ggtt_offset(rq->engine->scratch) |
PIPE_CONTROL_GLOBAL_GTT;
*cs++ = 0;
*cs++ = 0;
}
*cs++ = cmd;
intel_ring_advance(rq, cs); intel_ring_advance(rq, cs);
return 0; return 0;
......
...@@ -2748,6 +2748,12 @@ static const struct i915_power_well_desc icl_power_wells[] = { ...@@ -2748,6 +2748,12 @@ static const struct i915_power_well_desc icl_power_wells[] = {
.hsw.has_fuses = true, .hsw.has_fuses = true,
}, },
}, },
{
.name = "DC off",
.domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
.ops = &gen9_dc_off_power_well_ops,
.id = DISP_PW_ID_NONE,
},
{ {
.name = "power well 2", .name = "power well 2",
.domains = ICL_PW_2_POWER_DOMAINS, .domains = ICL_PW_2_POWER_DOMAINS,
...@@ -2759,12 +2765,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { ...@@ -2759,12 +2765,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
.hsw.has_fuses = true, .hsw.has_fuses = true,
}, },
}, },
{
.name = "DC off",
.domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
.ops = &gen9_dc_off_power_well_ops,
.id = DISP_PW_ID_NONE,
},
{ {
.name = "power well 3", .name = "power well 3",
.domains = ICL_PW_3_POWER_DOMAINS, .domains = ICL_PW_3_POWER_DOMAINS,
...@@ -3176,8 +3176,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv) ...@@ -3176,8 +3176,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
u8 req_slices) u8 req_slices)
{ {
u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices; const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
u32 val;
bool ret; bool ret;
if (req_slices > intel_dbuf_max_slices(dev_priv)) { if (req_slices > intel_dbuf_max_slices(dev_priv)) {
...@@ -3188,7 +3187,6 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, ...@@ -3188,7 +3187,6 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
if (req_slices == hw_enabled_slices || req_slices == 0) if (req_slices == hw_enabled_slices || req_slices == 0)
return; return;
val = I915_READ(DBUF_CTL_S2);
if (req_slices > hw_enabled_slices) if (req_slices > hw_enabled_slices)
ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true); ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
else else
......
...@@ -302,13 +302,65 @@ skl_plane_max_stride(struct intel_plane *plane, ...@@ -302,13 +302,65 @@ skl_plane_max_stride(struct intel_plane *plane,
return min(8192 * cpp, 32768); return min(8192 * cpp, 32768);
} }
static void
skl_program_scaler(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
int scaler_id = plane_state->scaler_id;
const struct intel_scaler *scaler =
&crtc_state->scaler_state.scalers[scaler_id];
int crtc_x = plane_state->base.dst.x1;
int crtc_y = plane_state->base.dst.y1;
uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
u16 y_hphase, uv_rgb_hphase;
u16 y_vphase, uv_rgb_vphase;
int hscale, vscale;
hscale = drm_rect_calc_hscale(&plane_state->base.src,
&plane_state->base.dst,
0, INT_MAX);
vscale = drm_rect_calc_vscale(&plane_state->base.src,
&plane_state->base.dst,
0, INT_MAX);
/* TODO: handle sub-pixel coordinates */
if (plane_state->base.fb->format->format == DRM_FORMAT_NV12) {
y_hphase = skl_scaler_calc_phase(1, hscale, false);
y_vphase = skl_scaler_calc_phase(1, vscale, false);
/* MPEG2 chroma siting convention */
uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
} else {
/* not used */
y_hphase = 0;
y_vphase = 0;
uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
}
I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
}
void void
skl_update_plane(struct intel_plane *plane, skl_update_plane(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state, const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state) const struct intel_plane_state *plane_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->base.fb;
enum plane_id plane_id = plane->id; enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe; enum pipe pipe = plane->pipe;
u32 plane_ctl = plane_state->ctl; u32 plane_ctl = plane_state->ctl;
...@@ -318,8 +370,6 @@ skl_update_plane(struct intel_plane *plane, ...@@ -318,8 +370,6 @@ skl_update_plane(struct intel_plane *plane,
u32 aux_stride = skl_plane_stride(plane_state, 1); u32 aux_stride = skl_plane_stride(plane_state, 1);
int crtc_x = plane_state->base.dst.x1; int crtc_x = plane_state->base.dst.x1;
int crtc_y = plane_state->base.dst.y1; int crtc_y = plane_state->base.dst.y1;
uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
uint32_t x = plane_state->color_plane[0].x; uint32_t x = plane_state->color_plane[0].x;
uint32_t y = plane_state->color_plane[0].y; uint32_t y = plane_state->color_plane[0].y;
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
...@@ -329,8 +379,6 @@ skl_update_plane(struct intel_plane *plane, ...@@ -329,8 +379,6 @@ skl_update_plane(struct intel_plane *plane,
/* Sizes are 0 based */ /* Sizes are 0 based */
src_w--; src_w--;
src_h--; src_h--;
crtc_w--;
crtc_h--;
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
...@@ -353,41 +401,8 @@ skl_update_plane(struct intel_plane *plane, ...@@ -353,41 +401,8 @@ skl_update_plane(struct intel_plane *plane,
(plane_state->color_plane[1].y << 16) | (plane_state->color_plane[1].y << 16) |
plane_state->color_plane[1].x); plane_state->color_plane[1].x);
/* program plane scaler */
if (plane_state->scaler_id >= 0) { if (plane_state->scaler_id >= 0) {
int scaler_id = plane_state->scaler_id; skl_program_scaler(plane, crtc_state, plane_state);
const struct intel_scaler *scaler =
&crtc_state->scaler_state.scalers[scaler_id];
u16 y_hphase, uv_rgb_hphase;
u16 y_vphase, uv_rgb_vphase;
/* TODO: handle sub-pixel coordinates */
if (fb->format->format == DRM_FORMAT_NV12) {
y_hphase = skl_scaler_calc_phase(1, false);
y_vphase = skl_scaler_calc_phase(1, false);
/* MPEG2 chroma siting convention */
uv_rgb_hphase = skl_scaler_calc_phase(2, true);
uv_rgb_vphase = skl_scaler_calc_phase(2, false);
} else {
/* not used */
y_hphase = 0;
y_vphase = 0;
uv_rgb_hphase = skl_scaler_calc_phase(1, false);
uv_rgb_vphase = skl_scaler_calc_phase(1, false);
}
I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
((crtc_w + 1) << 16)|(crtc_h + 1));
I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
} else { } else {
......
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