mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
intel, nouveau, rockchip, vmwgfx, imx, meson, mediatek and core fixes
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZOjW6AAoJEAx081l5xIa+6/EQAKYhMnfStw9lhIReP1hoa5bV PuP81uZ4GX5hQSWHbpQ9KyoQb9IrdzvCjZsHLpfnVRaDHFqLmpTDHAl+qpu0gOrf j18Y4B9JjE/rYKd7g6opdsT5DYO/uPgnSxaiAfIEPidg8dXxUxCAXcjwx8RbaQYb Bj0t3avcvYlIhkOejkrpT9E4yWFhZJhdvKl+KdBpzxgFefc7s9upnGYYvCstjxGZ fFBw5GqlILo1amuUmAJJK4RWhsAibzCybz4fDSOa8Ylbelp5HeZA1ewUUJaiwpeh iKO6r85Jg94Rst6CVgkKYvBsZR2g4dDJtnZOOhl7qxe00IsSlJsG91fwQw9agpyz xW7NT1ihMmPc4qKs4cyMYiaMXu07y+XzcDhnN/EvuEqjhnz1gNmDIqb+feJhP9VG B/eytSpqYd+JZpxrmqizJeWoCc0IJPFkYPp8AnVnpF1fiifo0y2CAsKS6ElPimki xInVoC72xJxDlXV+CDJvU5vlgoXC0k0WgGgykoWwQQMnxzars/SynSgCyRr9hebG mbRS0LQtoHqqhHGJqSg4GqHe/cFvZpCLIPbKWZJ8BFbkA3prumI8Qtp+UcSU2x5u 6t9MTPZhKTjcyXh+KrUt4N1W4SR/gdS9DDDi4pBMAQJbQMF8A1vMu6P3xsTx6kA6 R1XC2DfXr+1KfeeV7H5y =2hnW -----END PGP SIGNATURE----- Merge tag 'drm-fixes-for-v4.12-rc5' of git://people.freedesktop.org/~airlied/linux Pull drm fixes from Dave Airlie: "Intel, nouveau, rockchip, vmwgfx, imx, meson, mediatek and core fixes. Bit more spread out fixes this time, fixes for 7 drivers + a couple of core fixes. i915 and vmwgfx are the main ones. The vmwgfx ones fix a bunch of regressions in their atomic rework, and a few fixes destined for stable. i915 has some 4.12 regressions and older things that need to be fixed in stable as well. nouveau also has some runtime pm fixes and a timer list handling fix, otherwise a couple of core and small driver regression fixes" * tag 'drm-fixes-for-v4.12-rc5' of git://people.freedesktop.org/~airlied/linux: (37 commits) drm/i915: fix warning for unused variable drm/meson: Fix driver bind when only CVBS is available drm/i915: Fix 90/270 rotated coordinates for FBC drm/i915: Restore has_fbc=1 for ILK-M drm/i915: Workaround VLV/CHV DSI scanline counter hardware fail drm/i915: Fix logical inversion for gen4 quirking drm/i915: Guard against i915_ggtt_disable_guc() being invoked unconditionally drm/i915: Always recompute watermarks when distrust_bios_wm is set, v2. drm/i915: Prevent the system suspend complete optimization drm/i915/psr: disable psr2 for resolution greater than 32X20 drm/i915: Hold a wakeref for probing the ring registers drm/i915: Short-circuit i915_gem_wait_for_idle() if already idle drm/i915: Disable decoupled MMIO drm/i915/guc: Remove stale comment for q_fail drm/vmwgfx: Bump driver minor and date drm/vmwgfx: Remove unused legacy cursor functions drm/vmwgfx: fix spelling mistake "exeeds" -> "exceeds" drm/vmwgfx: Fix large topology crash drm/vmwgfx: Make sure to update STDU when FB is updated drm/vmwgfx: Make sure backup_handle is always valid ...
This commit is contained in:
commit
6107cc58f3
@ -508,6 +508,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
bool has_connectors =
|
||||
!!new_crtc_state->connector_mask;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
|
||||
|
||||
if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",
|
||||
crtc->base.id, crtc->name);
|
||||
@ -551,6 +553,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
|
||||
const struct drm_connector_helper_funcs *funcs = connector->helper_private;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
||||
|
||||
/*
|
||||
* This only sets crtc->connectors_changed for routing changes,
|
||||
* drivers must set crtc->connectors_changed themselves when
|
||||
@ -650,6 +654,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
|
||||
const struct drm_plane_helper_funcs *funcs;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&plane->mutex));
|
||||
|
||||
funcs = plane->helper_private;
|
||||
|
||||
drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
|
||||
@ -2663,7 +2669,12 @@ int drm_atomic_helper_resume(struct drm_device *dev,
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
while (1) {
|
||||
err = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = drm_atomic_helper_commit_duplicated_state(state, &ctx);
|
||||
out:
|
||||
if (err != -EDEADLK)
|
||||
break;
|
||||
|
||||
|
@ -358,7 +358,12 @@ EXPORT_SYMBOL(drm_put_dev);
|
||||
void drm_unplug_dev(struct drm_device *dev)
|
||||
{
|
||||
/* for a USB device */
|
||||
drm_dev_unregister(dev);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_modeset_unregister_all(dev);
|
||||
|
||||
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
|
||||
drm_minor_unregister(dev, DRM_MINOR_RENDER);
|
||||
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
|
||||
|
||||
mutex_lock(&drm_global_mutex);
|
||||
|
||||
|
@ -760,7 +760,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
|
||||
* Get the endpoint node. In our case, dsi has one output port1
|
||||
* to which the external HDMI bridge is connected.
|
||||
*/
|
||||
ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
|
||||
ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1235,6 +1235,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto out_fini;
|
||||
|
||||
pci_set_drvdata(pdev, &dev_priv->drm);
|
||||
/*
|
||||
* Disable the system suspend direct complete optimization, which can
|
||||
* leave the device suspended skipping the driver's suspend handlers
|
||||
* if the device was already runtime suspended. This is needed due to
|
||||
* the difference in our runtime and system suspend sequence and
|
||||
* becaue the HDA driver may require us to enable the audio power
|
||||
* domain during system suspend.
|
||||
*/
|
||||
pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
|
||||
|
||||
ret = i915_driver_init_early(dev_priv, ent);
|
||||
if (ret < 0)
|
||||
|
@ -2991,6 +2991,16 @@ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
if (IS_BROXTON(dev_priv) && intel_iommu_gfx_mapped)
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
|
||||
int enable_ppgtt);
|
||||
|
||||
|
@ -3298,6 +3298,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* If the device is asleep, we have no requests outstanding */
|
||||
if (!READ_ONCE(i915->gt.awake))
|
||||
return 0;
|
||||
|
||||
if (flags & I915_WAIT_LOCKED) {
|
||||
struct i915_gem_timeline *tl;
|
||||
|
||||
|
@ -2191,6 +2191,101 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
gen8_set_pte(>t_base[i], scratch_pte);
|
||||
}
|
||||
|
||||
static void bxt_vtd_ggtt_wa(struct i915_address_space *vm)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vm->i915;
|
||||
|
||||
/*
|
||||
* Make sure the internal GAM fifo has been cleared of all GTT
|
||||
* writes before exiting stop_machine(). This guarantees that
|
||||
* any aperture accesses waiting to start in another process
|
||||
* cannot back up behind the GTT writes causing a hang.
|
||||
* The register can be any arbitrary GAM register.
|
||||
*/
|
||||
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
||||
}
|
||||
|
||||
struct insert_page {
|
||||
struct i915_address_space *vm;
|
||||
dma_addr_t addr;
|
||||
u64 offset;
|
||||
enum i915_cache_level level;
|
||||
};
|
||||
|
||||
static int bxt_vtd_ggtt_insert_page__cb(void *_arg)
|
||||
{
|
||||
struct insert_page *arg = _arg;
|
||||
|
||||
gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0);
|
||||
bxt_vtd_ggtt_wa(arg->vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm,
|
||||
dma_addr_t addr,
|
||||
u64 offset,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
{
|
||||
struct insert_page arg = { vm, addr, offset, level };
|
||||
|
||||
stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL);
|
||||
}
|
||||
|
||||
struct insert_entries {
|
||||
struct i915_address_space *vm;
|
||||
struct sg_table *st;
|
||||
u64 start;
|
||||
enum i915_cache_level level;
|
||||
};
|
||||
|
||||
static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
|
||||
{
|
||||
struct insert_entries *arg = _arg;
|
||||
|
||||
gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0);
|
||||
bxt_vtd_ggtt_wa(arg->vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm,
|
||||
struct sg_table *st,
|
||||
u64 start,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
{
|
||||
struct insert_entries arg = { vm, st, start, level };
|
||||
|
||||
stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL);
|
||||
}
|
||||
|
||||
struct clear_range {
|
||||
struct i915_address_space *vm;
|
||||
u64 start;
|
||||
u64 length;
|
||||
};
|
||||
|
||||
static int bxt_vtd_ggtt_clear_range__cb(void *_arg)
|
||||
{
|
||||
struct clear_range *arg = _arg;
|
||||
|
||||
gen8_ggtt_clear_range(arg->vm, arg->start, arg->length);
|
||||
bxt_vtd_ggtt_wa(arg->vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bxt_vtd_ggtt_clear_range__BKL(struct i915_address_space *vm,
|
||||
u64 start,
|
||||
u64 length)
|
||||
{
|
||||
struct clear_range arg = { vm, start, length };
|
||||
|
||||
stop_machine(bxt_vtd_ggtt_clear_range__cb, &arg, NULL);
|
||||
}
|
||||
|
||||
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
u64 start, u64 length)
|
||||
{
|
||||
@ -2785,6 +2880,14 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
|
||||
|
||||
ggtt->base.insert_entries = gen8_ggtt_insert_entries;
|
||||
|
||||
/* Serialize GTT updates with aperture access on BXT if VT-d is on. */
|
||||
if (intel_ggtt_update_needs_vtd_wa(dev_priv)) {
|
||||
ggtt->base.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;
|
||||
ggtt->base.insert_page = bxt_vtd_ggtt_insert_page__BKL;
|
||||
if (ggtt->base.clear_range != nop_clear_range)
|
||||
ggtt->base.clear_range = bxt_vtd_ggtt_clear_range__BKL;
|
||||
}
|
||||
|
||||
ggtt->invalidate = gen6_ggtt_invalidate;
|
||||
|
||||
return ggtt_probe_common(ggtt, size);
|
||||
@ -2997,7 +3100,8 @@ void i915_ggtt_enable_guc(struct drm_i915_private *i915)
|
||||
|
||||
void i915_ggtt_disable_guc(struct drm_i915_private *i915)
|
||||
{
|
||||
i915->ggtt.invalidate = gen6_ggtt_invalidate;
|
||||
if (i915->ggtt.invalidate == guc_ggtt_invalidate)
|
||||
i915->ggtt.invalidate = gen6_ggtt_invalidate;
|
||||
}
|
||||
|
||||
void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
|
||||
|
@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
|
||||
obj->mm.quirked = false;
|
||||
}
|
||||
if (!i915_gem_object_is_tiled(obj)) {
|
||||
GEM_BUG_ON(!obj->mm.quirked);
|
||||
GEM_BUG_ON(obj->mm.quirked);
|
||||
__i915_gem_object_pin_pages(obj);
|
||||
obj->mm.quirked = true;
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
|
||||
static const struct intel_device_info intel_ironlake_m_info = {
|
||||
GEN5_FEATURES,
|
||||
.platform = INTEL_IRONLAKE,
|
||||
.is_mobile = 1,
|
||||
.is_mobile = 1, .has_fbc = 1,
|
||||
};
|
||||
|
||||
#define GEN6_FEATURES \
|
||||
@ -390,7 +390,6 @@ static const struct intel_device_info intel_skylake_gt3_info = {
|
||||
.has_hw_contexts = 1, \
|
||||
.has_logical_ring_contexts = 1, \
|
||||
.has_guc = 1, \
|
||||
.has_decoupled_mmio = 1, \
|
||||
.has_aliasing_ppgtt = 1, \
|
||||
.has_full_ppgtt = 1, \
|
||||
.has_full_48bit_ppgtt = 1, \
|
||||
|
@ -12203,6 +12203,15 @@ static void update_scanline_offset(struct intel_crtc *crtc)
|
||||
* type. For DP ports it behaves like most other platforms, but on HDMI
|
||||
* there's an extra 1 line difference. So we need to add two instead of
|
||||
* one to the value.
|
||||
*
|
||||
* On VLV/CHV DSI the scanline counter would appear to increment
|
||||
* approx. 1/3 of a scanline before start of vblank. Unfortunately
|
||||
* that means we can't tell whether we're in vblank or not while
|
||||
* we're on that particular line. We must still set scanline_offset
|
||||
* to 1 so that the vblank timestamps come out correct when we query
|
||||
* the scanline counter from within the vblank interrupt handler.
|
||||
* However if queried just before the start of vblank we'll get an
|
||||
* answer that's slightly in the future.
|
||||
*/
|
||||
if (IS_GEN2(dev_priv)) {
|
||||
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
||||
|
@ -1075,6 +1075,22 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ring_is_idle(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = engine->i915;
|
||||
bool idle = true;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* No bit for gen2, so assume the CS parser is idle */
|
||||
if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
|
||||
idle = false;
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return idle;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_engine_is_idle() - Report if the engine has finished process all work
|
||||
* @engine: the intel_engine_cs
|
||||
@ -1084,8 +1100,6 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
|
||||
*/
|
||||
bool intel_engine_is_idle(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = engine->i915;
|
||||
|
||||
/* Any inflight/incomplete requests? */
|
||||
if (!i915_seqno_passed(intel_engine_get_seqno(engine),
|
||||
intel_engine_last_submit(engine)))
|
||||
@ -1100,7 +1114,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
|
||||
return false;
|
||||
|
||||
/* Ring stopped? */
|
||||
if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
|
||||
if (!ring_is_idle(engine))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -82,20 +82,10 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
|
||||
static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,
|
||||
int *width, int *height)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
if (drm_rotation_90_or_270(cache->plane.rotation)) {
|
||||
w = cache->plane.src_h;
|
||||
h = cache->plane.src_w;
|
||||
} else {
|
||||
w = cache->plane.src_w;
|
||||
h = cache->plane.src_h;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = w;
|
||||
*width = cache->plane.src_w;
|
||||
if (height)
|
||||
*height = h;
|
||||
*height = cache->plane.src_h;
|
||||
}
|
||||
|
||||
static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
|
||||
@ -746,6 +736,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
|
||||
cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate;
|
||||
|
||||
cache->plane.rotation = plane_state->base.rotation;
|
||||
/*
|
||||
* Src coordinates are already rotated by 270 degrees for
|
||||
* the 90/270 degree plane rotation cases (to match the
|
||||
* GTT mapping), hence no need to account for rotation here.
|
||||
*/
|
||||
cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
|
||||
cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;
|
||||
cache->plane.visible = plane_state->base.visible;
|
||||
|
@ -4335,10 +4335,18 @@ skl_compute_wm(struct drm_atomic_state *state)
|
||||
struct drm_crtc_state *cstate;
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct skl_wm_values *results = &intel_state->wm_results;
|
||||
struct drm_device *dev = state->dev;
|
||||
struct skl_pipe_wm *pipe_wm;
|
||||
bool changed = false;
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* When we distrust bios wm we always need to recompute to set the
|
||||
* expected DDB allocations for each CRTC.
|
||||
*/
|
||||
if (to_i915(dev)->wm.distrust_bios_wm)
|
||||
changed = true;
|
||||
|
||||
/*
|
||||
* If this transaction isn't actually touching any CRTC's, don't
|
||||
* bother with watermark calculation. Note that if we pass this
|
||||
@ -4349,6 +4357,7 @@ skl_compute_wm(struct drm_atomic_state *state)
|
||||
*/
|
||||
for_each_new_crtc_in_state(state, crtc, cstate, i)
|
||||
changed = true;
|
||||
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
|
@ -435,8 +435,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
|
||||
}
|
||||
|
||||
/* PSR2 is restricted to work with panel resolutions upto 3200x2000 */
|
||||
if (intel_crtc->config->pipe_src_w > 3200 ||
|
||||
intel_crtc->config->pipe_src_h > 2000) {
|
||||
if (dev_priv->psr.psr2_support &&
|
||||
(intel_crtc->config->pipe_src_w > 3200 ||
|
||||
intel_crtc->config->pipe_src_h > 2000)) {
|
||||
dev_priv->psr.psr2_support = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -83,10 +83,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
*/
|
||||
void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
||||
long timeout = msecs_to_jiffies_timeout(1);
|
||||
int scanline, min, max, vblank_start;
|
||||
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
|
||||
bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
|
||||
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
vblank_start = adjusted_mode->crtc_vblank_start;
|
||||
@ -139,6 +142,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||
|
||||
drm_crtc_vblank_put(&crtc->base);
|
||||
|
||||
/*
|
||||
* On VLV/CHV DSI the scanline counter would appear to
|
||||
* increment approx. 1/3 of a scanline before start of vblank.
|
||||
* The registers still get latched at start of vblank however.
|
||||
* This means we must not write any registers on the first
|
||||
* line of vblank (since not the whole line is actually in
|
||||
* vblank). And unfortunately we can't use the interrupt to
|
||||
* wait here since it will fire too soon. We could use the
|
||||
* frame start interrupt instead since it will fire after the
|
||||
* critical scanline, but that would require more changes
|
||||
* in the interrupt code. So for now we'll just do the nasty
|
||||
* thing and poll for the bad scanline to pass us by.
|
||||
*
|
||||
* FIXME figure out if BXT+ DSI suffers from this as well
|
||||
*/
|
||||
while (need_vlv_dsi_wa && scanline == vblank_start)
|
||||
scanline = intel_get_crtc_scanline(crtc);
|
||||
|
||||
crtc->debug.scanline_start = scanline;
|
||||
crtc->debug.start_vbl_time = ktime_get();
|
||||
crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
|
||||
|
@ -59,8 +59,6 @@ struct drm_i915_gem_request;
|
||||
* available in the work queue (note, the queue is shared,
|
||||
* not per-engine). It is OK for this to be nonzero, but
|
||||
* it should not be huge!
|
||||
* q_fail: failed to enqueue a work item. This should never happen,
|
||||
* because we check for space beforehand.
|
||||
* b_fail: failed to ring the doorbell. This should never happen, unless
|
||||
* somehow the hardware misbehaves, or maybe if the GuC firmware
|
||||
* crashes? We probably need to reset the GPU to recover.
|
||||
|
@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
||||
ret = drm_of_find_panel_or_bridge(child,
|
||||
imx_ldb->lvds_mux ? 4 : 2, 0,
|
||||
&channel->panel, &channel->bridge);
|
||||
if (ret)
|
||||
if (ret && ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
/* panel ddc only if there is no bridge */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <drm/drm_of.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
@ -900,16 +901,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
|
||||
|
||||
static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
|
||||
{
|
||||
u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
while (timeout_ms--) {
|
||||
if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
|
||||
break;
|
||||
|
||||
usleep_range(2, 4);
|
||||
}
|
||||
|
||||
if (timeout_ms == 0) {
|
||||
ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
|
||||
4, 2000000);
|
||||
if (ret) {
|
||||
DRM_WARN("polling dsi wait not busy timeout!\n");
|
||||
|
||||
mtk_dsi_enable(dsi);
|
||||
|
@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
|
||||
}
|
||||
|
||||
err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
|
||||
err);
|
||||
return err;
|
||||
|
@ -152,7 +152,7 @@ static struct regmap_config meson_regmap_config = {
|
||||
.max_register = 0x1000,
|
||||
};
|
||||
|
||||
static int meson_drv_bind(struct device *dev)
|
||||
static int meson_drv_bind_master(struct device *dev, bool has_components)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct meson_drm *priv;
|
||||
@ -233,10 +233,12 @@ static int meson_drv_bind(struct device *dev)
|
||||
if (ret)
|
||||
goto free_drm;
|
||||
|
||||
ret = component_bind_all(drm->dev, drm);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't bind all components\n");
|
||||
goto free_drm;
|
||||
if (has_components) {
|
||||
ret = component_bind_all(drm->dev, drm);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't bind all components\n");
|
||||
goto free_drm;
|
||||
}
|
||||
}
|
||||
|
||||
ret = meson_plane_create(priv);
|
||||
@ -276,6 +278,11 @@ free_drm:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int meson_drv_bind(struct device *dev)
|
||||
{
|
||||
return meson_drv_bind_master(dev, true);
|
||||
}
|
||||
|
||||
static void meson_drv_unbind(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
@ -357,6 +364,9 @@ static int meson_drv_probe(struct platform_device *pdev)
|
||||
count += meson_probe_remote(pdev, &match, np, remote);
|
||||
}
|
||||
|
||||
if (count && !match)
|
||||
return meson_drv_bind_master(&pdev->dev, false);
|
||||
|
||||
/* If some endpoints were found, initialize the nodes */
|
||||
if (count) {
|
||||
dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
struct nvkm_alarm {
|
||||
struct list_head head;
|
||||
struct list_head exec;
|
||||
u64 timestamp;
|
||||
void (*func)(struct nvkm_alarm *);
|
||||
};
|
||||
|
@ -80,7 +80,7 @@ int nouveau_modeset = -1;
|
||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
|
||||
int nouveau_runtime_pm = -1;
|
||||
static int nouveau_runtime_pm = -1;
|
||||
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
|
||||
|
||||
static struct drm_driver driver_stub;
|
||||
@ -495,7 +495,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
nouveau_fbcon_init(dev);
|
||||
nouveau_led_init(dev);
|
||||
|
||||
if (nouveau_runtime_pm != 0) {
|
||||
if (nouveau_pmops_runtime()) {
|
||||
pm_runtime_use_autosuspend(dev->dev);
|
||||
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
|
||||
pm_runtime_set_active(dev->dev);
|
||||
@ -527,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
|
||||
if (nouveau_runtime_pm != 0) {
|
||||
if (nouveau_pmops_runtime()) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
}
|
||||
@ -726,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev)
|
||||
return nouveau_do_resume(drm_dev, false);
|
||||
}
|
||||
|
||||
bool
|
||||
nouveau_pmops_runtime()
|
||||
{
|
||||
if (nouveau_runtime_pm == -1)
|
||||
return nouveau_is_optimus() || nouveau_is_v1_dsm();
|
||||
return nouveau_runtime_pm == 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_pmops_runtime_suspend(struct device *dev)
|
||||
{
|
||||
@ -733,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (nouveau_runtime_pm == 0) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* are we optimus enabled? */
|
||||
if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
|
||||
DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -765,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
||||
struct nvif_device *device = &nouveau_drm(drm_dev)->client.device;
|
||||
int ret;
|
||||
|
||||
if (nouveau_runtime_pm == 0)
|
||||
return -EINVAL;
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev)
|
||||
struct nouveau_drm *drm = nouveau_drm(drm_dev);
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (nouveau_runtime_pm == 0) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* are we optimus enabled? */
|
||||
if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
|
||||
DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv)
|
||||
#include <nvif/object.h>
|
||||
#include <nvif/device.h>
|
||||
|
||||
extern int nouveau_runtime_pm;
|
||||
|
||||
struct nouveau_drm {
|
||||
struct nouveau_cli client;
|
||||
struct drm_device *dev;
|
||||
@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev)
|
||||
|
||||
int nouveau_pmops_suspend(struct device *);
|
||||
int nouveau_pmops_resume(struct device *);
|
||||
bool nouveau_pmops_runtime(void);
|
||||
|
||||
#include <nvkm/core/tegra.h>
|
||||
|
||||
|
@ -87,7 +87,7 @@ void
|
||||
nouveau_vga_init(struct nouveau_drm *drm)
|
||||
{
|
||||
struct drm_device *dev = drm->dev;
|
||||
bool runtime = false;
|
||||
bool runtime = nouveau_pmops_runtime();
|
||||
|
||||
/* only relevant for PCI devices */
|
||||
if (!dev->pdev)
|
||||
@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm)
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);
|
||||
|
||||
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
|
||||
@ -113,18 +109,13 @@ void
|
||||
nouveau_vga_fini(struct nouveau_drm *drm)
|
||||
{
|
||||
struct drm_device *dev = drm->dev;
|
||||
bool runtime = false;
|
||||
bool runtime = nouveau_pmops_runtime();
|
||||
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
runtime = true;
|
||||
|
||||
vga_switcheroo_unregister_client(dev->pdev);
|
||||
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
|
||||
vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
|
||||
|
@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
|
||||
asyc->set.dither = true;
|
||||
}
|
||||
} else {
|
||||
asyc->set.mask = ~0;
|
||||
if (asyc)
|
||||
asyc->set.mask = ~0;
|
||||
asyh->set.mask = ~0;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
/* Move to completed list. We'll drop the lock before
|
||||
* executing the callback so it can reschedule itself.
|
||||
*/
|
||||
list_move_tail(&alarm->head, &exec);
|
||||
list_del_init(&alarm->head);
|
||||
list_add(&alarm->exec, &exec);
|
||||
}
|
||||
|
||||
/* Shut down interrupt if no more pending alarms. */
|
||||
@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
|
||||
/* Execute completed callbacks. */
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, head) {
|
||||
list_del_init(&alarm->head);
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, exec) {
|
||||
list_del(&alarm->exec);
|
||||
alarm->func(alarm);
|
||||
}
|
||||
}
|
||||
|
@ -245,8 +245,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
|
||||
struct rockchip_dp_device *dp = to_dp(encoder);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The hardware IC designed that VOP must output the RGB10 video
|
||||
@ -258,16 +256,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
|
||||
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
|
||||
s->output_type = DRM_MODE_CONNECTOR_eDP;
|
||||
if (dp->data->chip_type == RK3399_EDP) {
|
||||
/*
|
||||
* For RK3399, VOP Lit must code the out mode to RGB888,
|
||||
* VOP Big must code the out mode to RGB10.
|
||||
*/
|
||||
ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
|
||||
encoder);
|
||||
if (ret > 0)
|
||||
s->output_mode = ROCKCHIP_OUT_MODE_P888;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct cdn_dp_device *dp = encoder_to_dp(encoder);
|
||||
int ret, val;
|
||||
struct rockchip_crtc_state *state;
|
||||
|
||||
ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
|
||||
if (ret < 0) {
|
||||
@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
|
||||
|
||||
DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n",
|
||||
(ret) ? "LIT" : "BIG");
|
||||
state = to_rockchip_crtc_state(encoder->crtc->state);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
|
||||
state->output_mode = ROCKCHIP_OUT_MODE_P888;
|
||||
} else {
|
||||
else
|
||||
val = DP_SEL_VOP_LIT << 16;
|
||||
state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
|
||||
}
|
||||
|
||||
ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val);
|
||||
if (ret)
|
||||
|
@ -875,6 +875,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
static void vop_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
const struct vop_data *vop_data = vop->data;
|
||||
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
|
||||
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
|
||||
u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
|
||||
@ -967,6 +968,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
||||
DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
|
||||
s->output_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* if vop is not support RGB10 output, need force RGB10 to RGB888.
|
||||
*/
|
||||
if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
|
||||
!(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
|
||||
s->output_mode = ROCKCHIP_OUT_MODE_P888;
|
||||
VOP_CTRL_SET(vop, out_mode, s->output_mode);
|
||||
|
||||
VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
|
||||
|
@ -142,6 +142,9 @@ struct vop_data {
|
||||
const struct vop_intr *intr;
|
||||
const struct vop_win_data *win;
|
||||
unsigned int win_size;
|
||||
|
||||
#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
|
||||
u64 feature;
|
||||
};
|
||||
|
||||
/* interrupt define */
|
||||
|
@ -275,6 +275,7 @@ static const struct vop_intr rk3288_vop_intr = {
|
||||
static const struct vop_data rk3288_vop = {
|
||||
.init_table = rk3288_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3288_init_reg_table),
|
||||
.feature = VOP_FEATURE_OUTPUT_RGB10,
|
||||
.intr = &rk3288_vop_intr,
|
||||
.ctrl = &rk3288_ctrl_data,
|
||||
.win = rk3288_vop_win_data,
|
||||
@ -343,6 +344,7 @@ static const struct vop_reg_data rk3399_init_reg_table[] = {
|
||||
static const struct vop_data rk3399_vop_big = {
|
||||
.init_table = rk3399_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3399_init_reg_table),
|
||||
.feature = VOP_FEATURE_OUTPUT_RGB10,
|
||||
.intr = &rk3399_vop_intr,
|
||||
.ctrl = &rk3399_ctrl_data,
|
||||
/*
|
||||
|
@ -41,9 +41,9 @@
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
#include "vmwgfx_fence.h"
|
||||
|
||||
#define VMWGFX_DRIVER_DATE "20170221"
|
||||
#define VMWGFX_DRIVER_DATE "20170607"
|
||||
#define VMWGFX_DRIVER_MAJOR 2
|
||||
#define VMWGFX_DRIVER_MINOR 12
|
||||
#define VMWGFX_DRIVER_MINOR 13
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
|
@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
|
||||
return fifo_state->static_buffer;
|
||||
else {
|
||||
fifo_state->dynamic_buffer = vmalloc(bytes);
|
||||
if (!fifo_state->dynamic_buffer)
|
||||
goto out_err;
|
||||
return fifo_state->dynamic_buffer;
|
||||
}
|
||||
}
|
||||
|
@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* vmw_du_cursor_plane_update() - Update cursor image and location
|
||||
*
|
||||
* @plane: plane object to update
|
||||
* @crtc: owning CRTC of @plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @crtc_x: x offset of plane on crtc
|
||||
* @crtc_y: y offset of plane on crtc
|
||||
* @crtc_w: width of plane rectangle on crtc
|
||||
* @crtc_h: height of plane rectangle on crtc
|
||||
* @src_x: Not used
|
||||
* @src_y: Not used
|
||||
* @src_w: Not used
|
||||
* @src_h: Not used
|
||||
*
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
int vmw_du_cursor_plane_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w,
|
||||
unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
{
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
|
||||
struct vmw_surface *surface = NULL;
|
||||
struct vmw_dma_buffer *dmabuf = NULL;
|
||||
s32 hotspot_x, hotspot_y;
|
||||
int ret;
|
||||
|
||||
hotspot_x = du->hotspot_x + fb->hot_x;
|
||||
hotspot_y = du->hotspot_y + fb->hot_y;
|
||||
|
||||
/* A lot of the code assumes this */
|
||||
if (crtc_w != 64 || crtc_h != 64) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vmw_framebuffer_to_vfb(fb)->dmabuf)
|
||||
dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
|
||||
else
|
||||
surface = vmw_framebuffer_to_vfbs(fb)->surface;
|
||||
|
||||
if (surface && !surface->snooper.image) {
|
||||
DRM_ERROR("surface not suitable for cursor\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* setup new image */
|
||||
ret = 0;
|
||||
if (surface) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_surface = surface;
|
||||
|
||||
du->cursor_age = du->cursor_surface->snooper.age;
|
||||
|
||||
ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
|
||||
64, 64, hotspot_x, hotspot_y);
|
||||
} else if (dmabuf) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_dmabuf = dmabuf;
|
||||
|
||||
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
|
||||
hotspot_x, hotspot_y);
|
||||
} else {
|
||||
vmw_cursor_update_position(dev_priv, false, 0, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
du->cursor_x = crtc_x + du->set_gui_x;
|
||||
du->cursor_y = crtc_y + du->set_gui_y;
|
||||
|
||||
vmw_cursor_update_position(dev_priv, true,
|
||||
du->cursor_x + hotspot_x,
|
||||
du->cursor_y + hotspot_y);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vmw_du_cursor_plane_disable(struct drm_plane *plane)
|
||||
{
|
||||
if (plane->fb) {
|
||||
drm_framebuffer_unreference(plane->fb);
|
||||
plane->fb = NULL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
|
||||
@ -472,18 +370,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
|
||||
drm_atomic_set_fb_for_plane(plane->state, NULL);
|
||||
vmw_cursor_update_position(dev_priv, false, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
@ -1498,6 +1384,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
|
||||
*/
|
||||
if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) &&
|
||||
dmabuf && only_2d &&
|
||||
mode_cmd->width > 64 && /* Don't create a proxy for cursor */
|
||||
dev_priv->active_display_unit == vmw_du_screen_target) {
|
||||
ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,
|
||||
dmabuf, &surface);
|
||||
|
@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *r, u16 *g, u16 *b,
|
||||
uint32_t size,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
|
||||
uint32_t handle, uint32_t width, uint32_t height,
|
||||
int32_t hot_x, int32_t hot_y);
|
||||
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
|
||||
int vmw_du_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
|
||||
/* Universal Plane Helpers */
|
||||
void vmw_du_primary_plane_destroy(struct drm_plane *plane);
|
||||
void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
|
||||
int vmw_du_cursor_plane_disable(struct drm_plane *plane);
|
||||
int vmw_du_cursor_plane_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w,
|
||||
unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
|
||||
/* Atomic Helpers */
|
||||
int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
|
||||
@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state);
|
||||
void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state);
|
||||
int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state);
|
||||
void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
|
||||
|
@ -56,6 +56,8 @@ enum stdu_content_type {
|
||||
* @right: Right side of bounding box.
|
||||
* @top: Top side of bounding box.
|
||||
* @bottom: Bottom side of bounding box.
|
||||
* @fb_left: Left side of the framebuffer/content bounding box
|
||||
* @fb_top: Top of the framebuffer/content bounding box
|
||||
* @buf: DMA buffer when DMA-ing between buffer and screen targets.
|
||||
* @sid: Surface ID when copying between surface and screen targets.
|
||||
*/
|
||||
@ -63,6 +65,7 @@ struct vmw_stdu_dirty {
|
||||
struct vmw_kms_dirty base;
|
||||
SVGA3dTransferType transfer;
|
||||
s32 left, right, top, bottom;
|
||||
s32 fb_left, fb_top;
|
||||
u32 pitch;
|
||||
union {
|
||||
struct vmw_dma_buffer *buf;
|
||||
@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
|
||||
*
|
||||
* @dirty: The closure structure.
|
||||
*
|
||||
* This function calculates the bounding box for all the incoming clips
|
||||
* This function calculates the bounding box for all the incoming clips.
|
||||
*/
|
||||
static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
|
||||
{
|
||||
@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
|
||||
|
||||
dirty->num_hits = 1;
|
||||
|
||||
/* Calculate bounding box */
|
||||
/* Calculate destination bounding box */
|
||||
ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
|
||||
ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
|
||||
ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
|
||||
ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
|
||||
|
||||
/*
|
||||
* Calculate content bounding box. We only need the top-left
|
||||
* coordinate because width and height will be the same as the
|
||||
* destination bounding box above
|
||||
*/
|
||||
ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
|
||||
ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y);
|
||||
}
|
||||
|
||||
|
||||
@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
|
||||
/* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */
|
||||
src_pitch = stdu->display_srf->base_size.width * stdu->cpp;
|
||||
src = ttm_kmap_obj_virtual(&stdu->host_map, ¬_used);
|
||||
src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp;
|
||||
src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;
|
||||
|
||||
dst_pitch = ddirty->pitch;
|
||||
dst = ttm_kmap_obj_virtual(&stdu->guest_map, ¬_used);
|
||||
dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp;
|
||||
dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
|
||||
|
||||
|
||||
/* Figure out the real direction */
|
||||
@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
|
||||
}
|
||||
|
||||
out_cleanup:
|
||||
ddirty->left = ddirty->top = S32_MAX;
|
||||
ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
|
||||
ddirty->right = ddirty->bottom = S32_MIN;
|
||||
}
|
||||
|
||||
@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
|
||||
SVGA3D_READ_HOST_VRAM;
|
||||
ddirty.left = ddirty.top = S32_MAX;
|
||||
ddirty.right = ddirty.bottom = S32_MIN;
|
||||
ddirty.fb_left = ddirty.fb_top = S32_MAX;
|
||||
ddirty.pitch = vfb->base.pitches[0];
|
||||
ddirty.buf = buf;
|
||||
ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit;
|
||||
@ -1355,6 +1367,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
|
||||
DRM_ERROR("Failed to bind surface to STDU.\n");
|
||||
else
|
||||
crtc->primary->fb = plane->state->fb;
|
||||
|
||||
ret = vmw_stdu_update_st(dev_priv, stdu);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to update STDU.\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1274,11 +1274,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
int ret;
|
||||
uint32_t size;
|
||||
uint32_t backup_handle;
|
||||
uint32_t backup_handle = 0;
|
||||
|
||||
if (req->multisample_count != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(vmw_user_surface_size == 0))
|
||||
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
|
||||
128;
|
||||
@ -1314,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
|
||||
&res->backup,
|
||||
&user_srf->backup_base);
|
||||
if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
if (ret == 0) {
|
||||
if (res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
} else {
|
||||
backup_handle = req->buffer_handle;
|
||||
}
|
||||
}
|
||||
} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
|
||||
ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
|
||||
@ -1491,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
|
||||
dev_priv->stdu_max_height);
|
||||
|
||||
if (size.width > max_width || size.height > max_height) {
|
||||
DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u",
|
||||
DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",
|
||||
size.width, size.height,
|
||||
max_width, max_height);
|
||||
return -EINVAL;
|
||||
|
@ -725,15 +725,16 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
|
||||
spin_lock_irqsave(&ipu->lock, flags);
|
||||
|
||||
val = ipu_cm_read(ipu, IPU_CONF);
|
||||
if (vdi) {
|
||||
if (vdi)
|
||||
val |= IPU_CONF_IC_INPUT;
|
||||
} else {
|
||||
else
|
||||
val &= ~IPU_CONF_IC_INPUT;
|
||||
if (csi_id == 1)
|
||||
val |= IPU_CONF_CSI_SEL;
|
||||
else
|
||||
val &= ~IPU_CONF_CSI_SEL;
|
||||
}
|
||||
|
||||
if (csi_id == 1)
|
||||
val |= IPU_CONF_CSI_SEL;
|
||||
else
|
||||
val &= ~IPU_CONF_CSI_SEL;
|
||||
|
||||
ipu_cm_write(ipu, val, IPU_CONF);
|
||||
|
||||
spin_unlock_irqrestore(&ipu->lock, flags);
|
||||
|
@ -131,8 +131,6 @@ int ipu_pre_get(struct ipu_pre *pre)
|
||||
if (pre->in_use)
|
||||
return -EBUSY;
|
||||
|
||||
clk_prepare_enable(pre->clk_axi);
|
||||
|
||||
/* first get the engine out of reset and remove clock gating */
|
||||
writel(0, pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
@ -149,12 +147,7 @@ int ipu_pre_get(struct ipu_pre *pre)
|
||||
|
||||
void ipu_pre_put(struct ipu_pre *pre)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE;
|
||||
writel(val, pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
clk_disable_unprepare(pre->clk_axi);
|
||||
writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
pre->in_use = false;
|
||||
}
|
||||
@ -249,6 +242,8 @@ static int ipu_pre_probe(struct platform_device *pdev)
|
||||
if (!pre->buffer_virt)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_prepare_enable(pre->clk_axi);
|
||||
|
||||
pre->dev = dev;
|
||||
platform_set_drvdata(pdev, pre);
|
||||
mutex_lock(&ipu_pre_list_mutex);
|
||||
@ -268,6 +263,8 @@ static int ipu_pre_remove(struct platform_device *pdev)
|
||||
available_pres--;
|
||||
mutex_unlock(&ipu_pre_list_mutex);
|
||||
|
||||
clk_disable_unprepare(pre->clk_axi);
|
||||
|
||||
if (pre->buffer_virt)
|
||||
gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
|
||||
IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
|
||||
|
Loading…
Reference in New Issue
Block a user