Commit 0f940fac authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-for-v4.17-rc3' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Pretty run of the mill for this stage in the cycle: msm, i915, amdgpu,
  qxl, virtio-gpu, sun4i fixes.

  i915:
   - Black screen fixes
   - Display w/a fix
   - HDA codec interop fix

  sun4i:
   - tbsa711 tablet regression fix

  qxl:
   - Regression fixes due to changes in TTM

  virtio:
   - Fix wait event condition

  msm:
   - DSI display fixes

  amdgpu:
   - fix hang on Carrizo
   - DP MST hang fixes
   - irq handling deadlock in DC.

  amdkfd:
   - Fix Kconfig issue
   - Clock retrieval fix
   - Sparse fixes"

* tag 'drm-fixes-for-v4.17-rc3' of git://people.freedesktop.org/~airlied/linux: (27 commits)
  drm/edid: Reset more of the display info
  drm/virtio: fix vq wait_event condition
  qxl: keep separate release_bo pointer
  qxl: fix qxl_release_{map,unmap}
  Revert "drm/sun4i: add lvds mode_valid function"
  drm/amd/display: Check dc_sink every time in MST hotplug
  drm/amd/display: Update MST edid property every time
  drm/amd/display: Don't read EDID in atomic_check
  drm/amd/display: Disallow enabling CRTC without primary plane with FB
  drm/amd/display: Fix deadlock when flushing irq
  drm/i915/fbdev: Enable late fbdev initial configuration
  drm/i915: Use ktime on wait_for
  drm/amdgpu: set COMPUTE_PGM_RSRC1 for SGPR/VGPR clearing shaders
  drm/amdkfd: fix build, select MMU_NOTIFIER
  drm/amdkfd: fix clock counter retrieval for node without GPU
  drm/amdkfd: Fix the error return code in kfd_ioctl_unmap_memory_from_gpu()
  drm/amdkfd: kfd_dev_is_large_bar() can be static
  drm/i915: Enable display WA#1183 from its correct spot
  drm/i915/audio: set minimum CD clock to twice the BCLK
  drm/msm: don't deref error pointer in the msm_fbdev_create error path
  ...
parents 0644f186 24d9092c
...@@ -1459,10 +1459,11 @@ static const u32 sgpr_init_compute_shader[] = ...@@ -1459,10 +1459,11 @@ static const u32 sgpr_init_compute_shader[] =
static const u32 vgpr_init_regs[] = static const u32 vgpr_init_regs[] =
{ {
mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xffffffff, mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xffffffff,
mmCOMPUTE_RESOURCE_LIMITS, 0, mmCOMPUTE_RESOURCE_LIMITS, 0x1000000, /* CU_GROUP_COUNT=1 */
mmCOMPUTE_NUM_THREAD_X, 256*4, mmCOMPUTE_NUM_THREAD_X, 256*4,
mmCOMPUTE_NUM_THREAD_Y, 1, mmCOMPUTE_NUM_THREAD_Y, 1,
mmCOMPUTE_NUM_THREAD_Z, 1, mmCOMPUTE_NUM_THREAD_Z, 1,
mmCOMPUTE_PGM_RSRC1, 0x100004f, /* VGPRS=15 (64 logical VGPRs), SGPRS=1 (16 SGPRs), BULKY=1 */
mmCOMPUTE_PGM_RSRC2, 20, mmCOMPUTE_PGM_RSRC2, 20,
mmCOMPUTE_USER_DATA_0, 0xedcedc00, mmCOMPUTE_USER_DATA_0, 0xedcedc00,
mmCOMPUTE_USER_DATA_1, 0xedcedc01, mmCOMPUTE_USER_DATA_1, 0xedcedc01,
...@@ -1479,10 +1480,11 @@ static const u32 vgpr_init_regs[] = ...@@ -1479,10 +1480,11 @@ static const u32 vgpr_init_regs[] =
static const u32 sgpr1_init_regs[] = static const u32 sgpr1_init_regs[] =
{ {
mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0x0f, mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0x0f,
mmCOMPUTE_RESOURCE_LIMITS, 0x1000000, mmCOMPUTE_RESOURCE_LIMITS, 0x1000000, /* CU_GROUP_COUNT=1 */
mmCOMPUTE_NUM_THREAD_X, 256*5, mmCOMPUTE_NUM_THREAD_X, 256*5,
mmCOMPUTE_NUM_THREAD_Y, 1, mmCOMPUTE_NUM_THREAD_Y, 1,
mmCOMPUTE_NUM_THREAD_Z, 1, mmCOMPUTE_NUM_THREAD_Z, 1,
mmCOMPUTE_PGM_RSRC1, 0x240, /* SGPRS=9 (80 GPRS) */
mmCOMPUTE_PGM_RSRC2, 20, mmCOMPUTE_PGM_RSRC2, 20,
mmCOMPUTE_USER_DATA_0, 0xedcedc00, mmCOMPUTE_USER_DATA_0, 0xedcedc00,
mmCOMPUTE_USER_DATA_1, 0xedcedc01, mmCOMPUTE_USER_DATA_1, 0xedcedc01,
...@@ -1503,6 +1505,7 @@ static const u32 sgpr2_init_regs[] = ...@@ -1503,6 +1505,7 @@ static const u32 sgpr2_init_regs[] =
mmCOMPUTE_NUM_THREAD_X, 256*5, mmCOMPUTE_NUM_THREAD_X, 256*5,
mmCOMPUTE_NUM_THREAD_Y, 1, mmCOMPUTE_NUM_THREAD_Y, 1,
mmCOMPUTE_NUM_THREAD_Z, 1, mmCOMPUTE_NUM_THREAD_Z, 1,
mmCOMPUTE_PGM_RSRC1, 0x240, /* SGPRS=9 (80 GPRS) */
mmCOMPUTE_PGM_RSRC2, 20, mmCOMPUTE_PGM_RSRC2, 20,
mmCOMPUTE_USER_DATA_0, 0xedcedc00, mmCOMPUTE_USER_DATA_0, 0xedcedc00,
mmCOMPUTE_USER_DATA_1, 0xedcedc01, mmCOMPUTE_USER_DATA_1, 0xedcedc01,
......
...@@ -6,5 +6,6 @@ config HSA_AMD ...@@ -6,5 +6,6 @@ config HSA_AMD
tristate "HSA kernel driver for AMD GPU devices" tristate "HSA kernel driver for AMD GPU devices"
depends on DRM_AMDGPU && X86_64 depends on DRM_AMDGPU && X86_64
imply AMD_IOMMU_V2 imply AMD_IOMMU_V2
select MMU_NOTIFIER
help help
Enable this if you want to use HSA features on AMD GPU devices. Enable this if you want to use HSA features on AMD GPU devices.
...@@ -749,12 +749,13 @@ static int kfd_ioctl_get_clock_counters(struct file *filep, ...@@ -749,12 +749,13 @@ static int kfd_ioctl_get_clock_counters(struct file *filep,
struct timespec64 time; struct timespec64 time;
dev = kfd_device_by_id(args->gpu_id); dev = kfd_device_by_id(args->gpu_id);
if (dev == NULL) if (dev)
return -EINVAL; /* Reading GPU clock counter from KGD */
args->gpu_clock_counter =
/* Reading GPU clock counter from KGD */ dev->kfd2kgd->get_gpu_clock_counter(dev->kgd);
args->gpu_clock_counter = else
dev->kfd2kgd->get_gpu_clock_counter(dev->kgd); /* Node without GPU resource */
args->gpu_clock_counter = 0;
/* No access to rdtsc. Using raw monotonic time */ /* No access to rdtsc. Using raw monotonic time */
getrawmonotonic64(&time); getrawmonotonic64(&time);
...@@ -1147,7 +1148,7 @@ static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p, ...@@ -1147,7 +1148,7 @@ static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p,
return ret; return ret;
} }
bool kfd_dev_is_large_bar(struct kfd_dev *dev) static bool kfd_dev_is_large_bar(struct kfd_dev *dev)
{ {
struct kfd_local_mem_info mem_info; struct kfd_local_mem_info mem_info;
...@@ -1421,7 +1422,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, ...@@ -1421,7 +1422,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
pdd = kfd_get_process_device_data(dev, p); pdd = kfd_get_process_device_data(dev, p);
if (!pdd) { if (!pdd) {
err = PTR_ERR(pdd); err = -EINVAL;
goto bind_process_to_device_failed; goto bind_process_to_device_failed;
} }
......
...@@ -4557,6 +4557,7 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4557,6 +4557,7 @@ static int dm_update_crtcs_state(struct dc *dc,
struct amdgpu_dm_connector *aconnector = NULL; struct amdgpu_dm_connector *aconnector = NULL;
struct drm_connector_state *new_con_state = NULL; struct drm_connector_state *new_con_state = NULL;
struct dm_connector_state *dm_conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL;
struct drm_plane_state *new_plane_state = NULL;
new_stream = NULL; new_stream = NULL;
...@@ -4564,6 +4565,13 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4564,6 +4565,13 @@ static int dm_update_crtcs_state(struct dc *dc,
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
acrtc = to_amdgpu_crtc(crtc); acrtc = to_amdgpu_crtc(crtc);
new_plane_state = drm_atomic_get_new_plane_state(state, new_crtc_state->crtc->primary);
if (new_crtc_state->enable && new_plane_state && !new_plane_state->fb) {
ret = -EINVAL;
goto fail;
}
aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
/* TODO This hack should go away */ /* TODO This hack should go away */
...@@ -4760,7 +4768,7 @@ static int dm_update_planes_state(struct dc *dc, ...@@ -4760,7 +4768,7 @@ static int dm_update_planes_state(struct dc *dc,
if (!dm_old_crtc_state->stream) if (!dm_old_crtc_state->stream)
continue; continue;
DRM_DEBUG_DRIVER("Disabling DRM plane: %d on DRM crtc %d\n", DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n",
plane->base.id, old_plane_crtc->base.id); plane->base.id, old_plane_crtc->base.id);
if (!dc_remove_plane_from_context( if (!dc_remove_plane_from_context(
......
...@@ -329,14 +329,15 @@ void amdgpu_dm_irq_fini(struct amdgpu_device *adev) ...@@ -329,14 +329,15 @@ void amdgpu_dm_irq_fini(struct amdgpu_device *adev)
{ {
int src; int src;
struct irq_list_head *lh; struct irq_list_head *lh;
unsigned long irq_table_flags;
DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n"); DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n");
for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
/* The handler was removed from the table, /* The handler was removed from the table,
* it means it is safe to flush all the 'work' * it means it is safe to flush all the 'work'
* (because no code can schedule a new one). */ * (because no code can schedule a new one). */
lh = &adev->dm.irq_handler_list_low_tab[src]; lh = &adev->dm.irq_handler_list_low_tab[src];
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
flush_work(&lh->work); flush_work(&lh->work);
} }
} }
......
...@@ -161,6 +161,11 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) ...@@ -161,6 +161,11 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder; struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder;
if (amdgpu_dm_connector->edid) {
kfree(amdgpu_dm_connector->edid);
amdgpu_dm_connector->edid = NULL;
}
drm_encoder_cleanup(&amdgpu_encoder->base); drm_encoder_cleanup(&amdgpu_encoder->base);
kfree(amdgpu_encoder); kfree(amdgpu_encoder);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
...@@ -181,28 +186,22 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { ...@@ -181,28 +186,22 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
void dm_dp_mst_dc_sink_create(struct drm_connector *connector) void dm_dp_mst_dc_sink_create(struct drm_connector *connector)
{ {
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
struct edid *edid;
struct dc_sink *dc_sink; struct dc_sink *dc_sink;
struct dc_sink_init_data init_params = { struct dc_sink_init_data init_params = {
.link = aconnector->dc_link, .link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
/* FIXME none of this is safe. we shouldn't touch aconnector here in
* atomic_check
*/
/* /*
* TODO: Need to further figure out why ddc.algo is NULL while MST port exists * TODO: Need to further figure out why ddc.algo is NULL while MST port exists
*/ */
if (!aconnector->port || !aconnector->port->aux.ddc.algo) if (!aconnector->port || !aconnector->port->aux.ddc.algo)
return; return;
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); ASSERT(aconnector->edid);
if (!edid) {
drm_mode_connector_update_edid_property(
&aconnector->base,
NULL);
return;
}
aconnector->edid = edid;
dc_sink = dc_link_add_remote_sink( dc_sink = dc_link_add_remote_sink(
aconnector->dc_link, aconnector->dc_link,
...@@ -215,9 +214,6 @@ void dm_dp_mst_dc_sink_create(struct drm_connector *connector) ...@@ -215,9 +214,6 @@ void dm_dp_mst_dc_sink_create(struct drm_connector *connector)
amdgpu_dm_add_sink_to_freesync_module( amdgpu_dm_add_sink_to_freesync_module(
connector, aconnector->edid); connector, aconnector->edid);
drm_mode_connector_update_edid_property(
&aconnector->base, aconnector->edid);
} }
static int dm_dp_mst_get_modes(struct drm_connector *connector) static int dm_dp_mst_get_modes(struct drm_connector *connector)
...@@ -230,10 +226,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) ...@@ -230,10 +226,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
if (!aconnector->edid) { if (!aconnector->edid) {
struct edid *edid; struct edid *edid;
struct dc_sink *dc_sink;
struct dc_sink_init_data init_params = {
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
if (!edid) { if (!edid) {
...@@ -244,11 +236,17 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) ...@@ -244,11 +236,17 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
} }
aconnector->edid = edid; aconnector->edid = edid;
}
if (!aconnector->dc_sink) {
struct dc_sink *dc_sink;
struct dc_sink_init_data init_params = {
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
dc_sink = dc_link_add_remote_sink( dc_sink = dc_link_add_remote_sink(
aconnector->dc_link, aconnector->dc_link,
(uint8_t *)edid, (uint8_t *)aconnector->edid,
(edid->extensions + 1) * EDID_LENGTH, (aconnector->edid->extensions + 1) * EDID_LENGTH,
&init_params); &init_params);
dc_sink->priv = aconnector; dc_sink->priv = aconnector;
...@@ -256,12 +254,12 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) ...@@ -256,12 +254,12 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
if (aconnector->dc_sink) if (aconnector->dc_sink)
amdgpu_dm_add_sink_to_freesync_module( amdgpu_dm_add_sink_to_freesync_module(
connector, edid); connector, aconnector->edid);
drm_mode_connector_update_edid_property(
&aconnector->base, edid);
} }
drm_mode_connector_update_edid_property(
&aconnector->base, aconnector->edid);
ret = drm_add_edid_modes(connector, aconnector->edid); ret = drm_add_edid_modes(connector, aconnector->edid);
return ret; return ret;
...@@ -424,14 +422,6 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, ...@@ -424,14 +422,6 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
dc_sink_release(aconnector->dc_sink); dc_sink_release(aconnector->dc_sink);
aconnector->dc_sink = NULL; aconnector->dc_sink = NULL;
} }
if (aconnector->edid) {
kfree(aconnector->edid);
aconnector->edid = NULL;
}
drm_mode_connector_update_edid_property(
&aconnector->base,
NULL);
aconnector->mst_connected = false; aconnector->mst_connected = false;
} }
......
...@@ -4451,6 +4451,7 @@ drm_reset_display_info(struct drm_connector *connector) ...@@ -4451,6 +4451,7 @@ drm_reset_display_info(struct drm_connector *connector)
info->max_tmds_clock = 0; info->max_tmds_clock = 0;
info->dvi_dual = false; info->dvi_dual = false;
info->has_hdmi_infoframe = false; info->has_hdmi_infoframe = false;
memset(&info->hdmi, 0, sizeof(info->hdmi));
info->non_desktop = 0; info->non_desktop = 0;
} }
...@@ -4462,17 +4463,11 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi ...@@ -4462,17 +4463,11 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
u32 quirks = edid_get_quirks(edid); u32 quirks = edid_get_quirks(edid);
drm_reset_display_info(connector);
info->width_mm = edid->width_cm * 10; info->width_mm = edid->width_cm * 10;
info->height_mm = edid->height_cm * 10; info->height_mm = edid->height_cm * 10;
/* driver figures it out in this case */
info->bpc = 0;
info->color_formats = 0;
info->cea_rev = 0;
info->max_tmds_clock = 0;
info->dvi_dual = false;
info->has_hdmi_infoframe = false;
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop); DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
......
...@@ -2140,10 +2140,22 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) ...@@ -2140,10 +2140,22 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
} }
} }
/* According to BSpec, "The CD clock frequency must be at least twice /*
* According to BSpec, "The CD clock frequency must be at least twice
* the frequency of the Azalia BCLK." and BCLK is 96 MHz by default. * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*
* FIXME: Check the actual, not default, BCLK being used.
*
* FIXME: This does not depend on ->has_audio because the higher CDCLK
* is required for audio probe, also when there are no audio capable
* displays connected at probe time. This leads to unnecessarily high
* CDCLK when audio is not required.
*
* FIXME: This limit is only applied when there are displays connected
* at probe time. If we probe without displays, we'll still end up using
* the platform minimum CDCLK, failing audio probe.
*/ */
if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) if (INTEL_GEN(dev_priv) >= 9)
min_cdclk = max(2 * 96000, min_cdclk); min_cdclk = max(2 * 96000, min_cdclk);
/* /*
......
...@@ -49,12 +49,12 @@ ...@@ -49,12 +49,12 @@
* check the condition before the timeout. * check the condition before the timeout.
*/ */
#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ #define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
int ret__; \ int ret__; \
might_sleep(); \ might_sleep(); \
for (;;) { \ for (;;) { \
bool expired__ = time_after(jiffies, timeout__); \ const bool expired__ = ktime_after(ktime_get_raw(), end__); \
OP; \ OP; \
if (COND) { \ if (COND) { \
ret__ = 0; \ ret__ = 0; \
......
...@@ -806,7 +806,7 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev) ...@@ -806,7 +806,7 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev)
return; return;
intel_fbdev_sync(ifbdev); intel_fbdev_sync(ifbdev);
if (ifbdev->vma) if (ifbdev->vma || ifbdev->helper.deferred_setup)
drm_fb_helper_hotplug_event(&ifbdev->helper); drm_fb_helper_hotplug_event(&ifbdev->helper);
} }
......
...@@ -641,19 +641,18 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv) ...@@ -641,19 +641,18 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv)
DRM_DEBUG_KMS("Enabling DC6\n"); DRM_DEBUG_KMS("Enabling DC6\n");
gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); /* Wa Display #1183: skl,kbl,cfl */
if (IS_GEN9_BC(dev_priv))
I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) |
SKL_SELECT_ALTERNATE_DC_EXIT);
gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
} }
void skl_disable_dc6(struct drm_i915_private *dev_priv) void skl_disable_dc6(struct drm_i915_private *dev_priv)
{ {
DRM_DEBUG_KMS("Disabling DC6\n"); DRM_DEBUG_KMS("Disabling DC6\n");
/* Wa Display #1183: skl,kbl,cfl */
if (IS_GEN9_BC(dev_priv))
I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) |
SKL_SELECT_ALTERNATE_DC_EXIT);
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
} }
......
...@@ -351,6 +351,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc, ...@@ -351,6 +351,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc,
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
mdp4_crtc->event = crtc->state->event; mdp4_crtc->event = crtc->state->event;
crtc->state->event = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
blend_setup(crtc); blend_setup(crtc);
......
...@@ -708,6 +708,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc, ...@@ -708,6 +708,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
mdp5_crtc->event = crtc->state->event; mdp5_crtc->event = crtc->state->event;
crtc->state->event = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
/* /*
......
...@@ -171,7 +171,8 @@ uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats, ...@@ -171,7 +171,8 @@ uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats,
return i; return i;
} }
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format) const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format,
uint64_t modifier)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(formats); i++) { for (i = 0; i < ARRAY_SIZE(formats); i++) {
......
...@@ -98,7 +98,7 @@ struct mdp_format { ...@@ -98,7 +98,7 @@ struct mdp_format {
#define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->is_yuv) #define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->is_yuv)
uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only); uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format); const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier);
/* MDP capabilities */ /* MDP capabilities */
#define MDP_CAP_SMP BIT(0) /* Shared Memory Pool */ #define MDP_CAP_SMP BIT(0) /* Shared Memory Pool */
......
...@@ -173,6 +173,7 @@ struct msm_dsi_host { ...@@ -173,6 +173,7 @@ struct msm_dsi_host {
bool registered; bool registered;
bool power_on; bool power_on;
bool enabled;
int irq; int irq;
}; };
...@@ -775,7 +776,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( ...@@ -775,7 +776,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt(
switch (mipi_fmt) { switch (mipi_fmt) {
case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888; case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888;
case MIPI_DSI_FMT_RGB666_PACKED: case MIPI_DSI_FMT_RGB666_PACKED:
case MIPI_DSI_FMT_RGB666: return VID_DST_FORMAT_RGB666; case MIPI_DSI_FMT_RGB666: return CMD_DST_FORMAT_RGB666;
case MIPI_DSI_FMT_RGB565: return CMD_DST_FORMAT_RGB565; case MIPI_DSI_FMT_RGB565: return CMD_DST_FORMAT_RGB565;
default: return CMD_DST_FORMAT_RGB888; default: return CMD_DST_FORMAT_RGB888;
} }
...@@ -986,13 +987,19 @@ static void dsi_set_tx_power_mode(int mode, struct msm_dsi_host *msm_host) ...@@ -986,13 +987,19 @@ static void dsi_set_tx_power_mode(int mode, struct msm_dsi_host *msm_host)
static void dsi_wait4video_done(struct msm_dsi_host *msm_host) static void dsi_wait4video_done(struct msm_dsi_host *msm_host)
{ {
u32 ret = 0;
struct device *dev = &msm_host->pdev->dev;
dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 1); dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 1);
reinit_completion(&msm_host->video_comp); reinit_completion(&msm_host->video_comp);
wait_for_completion_timeout(&msm_host->video_comp, ret = wait_for_completion_timeout(&msm_host->video_comp,
msecs_to_jiffies(70)); msecs_to_jiffies(70));
if (ret <= 0)
dev_err(dev, "wait for video done timed out\n");
dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 0); dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 0);
} }
...@@ -1001,7 +1008,7 @@ static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host) ...@@ -1001,7 +1008,7 @@ static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host)
if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO))
return; return;
if (msm_host->power_on) { if (msm_host->power_on && msm_host->enabled) {
dsi_wait4video_done(msm_host); dsi_wait4video_done(msm_host);
/* delay 4 ms to skip BLLP */ /* delay 4 ms to skip BLLP */
usleep_range(2000, 4000); usleep_range(2000, 4000);
...@@ -2203,7 +2210,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host) ...@@ -2203,7 +2210,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host)
* pm_runtime_put_autosuspend(&msm_host->pdev->dev); * pm_runtime_put_autosuspend(&msm_host->pdev->dev);
* } * }
*/ */
msm_host->enabled = true;
return 0; return 0;
} }
...@@ -2211,6 +2218,7 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host) ...@@ -2211,6 +2218,7 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host)
{ {
struct msm_dsi_host *msm_host = to_msm_dsi_host(host); struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
msm_host->enabled = false;
dsi_op_mode_config(msm_host, dsi_op_mode_config(msm_host,
!!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO), false); !!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO), false);
......
...@@ -265,6 +265,115 @@ int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing, ...@@ -265,6 +265,115 @@ int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
return 0; return 0;
} }
int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req)
{
const unsigned long bit_rate = clk_req->bitclk_rate;
const unsigned long esc_rate = clk_req->escclk_rate;
s32 ui, ui_x8, lpx;
s32 tmax, tmin;
s32 pcnt0 = 50;
s32 pcnt1 = 50;
s32 pcnt2 = 10;
s32 pcnt3 = 30;
s32 pcnt4 = 10;
s32 pcnt5 = 2;
s32 coeff = 1000; /* Precision, should avoid overflow */
s32 hb_en, hb_en_ckln;
s32 temp;
if (!bit_rate || !esc_rate)
return -EINVAL;
timing->hs_halfbyte_en = 0;
hb_en = 0;
timing->hs_halfbyte_en_ckln = 0;
hb_en_ckln = 0;
ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
ui_x8 = ui << 3;
lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000);
temp = S_DIV_ROUND_UP(38 * coeff, ui_x8);
tmin = max_t(s32, temp, 0);
temp = (95 * coeff) / ui_x8;
tmax = max_t(s32, temp, 0);
timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
temp = 300 * coeff - (timing->clk_prepare << 3) * ui;
tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
tmax = (tmin > 255) ? 511 : 255;
timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
temp = 105 * coeff + 12 * ui - 20 * coeff;
tmax = (temp + 3 * ui) / ui_x8;
timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8);
tmin = max_t(s32, temp, 0);
temp = (85 * coeff + 6 * ui) / ui_x8;
tmax = max_t(s32, temp, 0);
timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui;
tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
tmax = 255;
timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1;
temp = 105 * coeff + 12 * ui - 20 * coeff;
tmax = (temp / ui_x8) - 1;
timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
tmax = 255;
timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8);
temp = 60 * coeff + 52 * ui - 43 * ui;
tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
tmax = 63;
timing->shared_timings.clk_post =
linear_inter(tmax, tmin, pcnt2, 0, false);
temp = 8 * ui + (timing->clk_prepare << 3) * ui;
temp += (((timing->clk_zero + 3) << 3) + 11) * ui;
temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) :
(((timing->hs_rqst_ckln << 3) + 8) * ui);
tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
tmax = 63;
if (tmin > tmax) {
temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
timing->shared_timings.clk_pre = temp >> 1;
timing->shared_timings.clk_pre_inc_by_2 = 1;
} else {
timing->shared_timings.clk_pre =
linear_inter(tmax, tmin, pcnt2, 0, false);
timing->shared_timings.clk_pre_inc_by_2 = 0;
}
timing->ta_go = 3;
timing->ta_sure = 0;
timing->ta_get = 4;
DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
timing->clk_trail, timing->clk_prepare, timing->hs_exit,
timing->hs_zero, timing->hs_prepare, timing->hs_trail,
timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en,
timing->hs_halfbyte_en_ckln, timing->hs_prep_dly,
timing->hs_prep_dly_ckln);
return 0;
}
void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
u32 bit_mask) u32 bit_mask)
{ {
......
...@@ -101,6 +101,8 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing, ...@@ -101,6 +101,8 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req); struct msm_dsi_phy_clk_request *clk_req);
int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing, int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req); struct msm_dsi_phy_clk_request *clk_req);
int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req);
void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
u32 bit_mask); u32 bit_mask);
int msm_dsi_phy_init_common(struct msm_dsi_phy *phy); int msm_dsi_phy_init_common(struct msm_dsi_phy *phy);
......
...@@ -79,34 +79,6 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy) ...@@ -79,34 +79,6 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04); dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
} }
static int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req)
{
/*
* TODO: These params need to be computed, they're currently hardcoded
* for a 1440x2560@60Hz panel with a byteclk of 100.618 Mhz, and a
* default escape clock of 19.2 Mhz.
*/
timing->hs_halfbyte_en = 0;
timing->clk_zero = 0x1c;
timing->clk_prepare = 0x07;
timing->clk_trail = 0x07;
timing->hs_exit = 0x23;
timing->hs_zero = 0x21;
timing->hs_prepare = 0x07;
timing->hs_trail = 0x07;
timing->hs_rqst = 0x05;
timing->ta_sure = 0x00;
timing->ta_go = 0x03;
timing->ta_get = 0x04;
timing->shared_timings.clk_pre = 0x2d;
timing->shared_timings.clk_post = 0x0d;
return 0;
}
static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
struct msm_dsi_phy_clk_request *clk_req) struct msm_dsi_phy_clk_request *clk_req)
{ {
......
...@@ -183,7 +183,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, ...@@ -183,7 +183,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
format = kms->funcs->get_format(kms, mode_cmd->pixel_format); format = kms->funcs->get_format(kms, mode_cmd->pixel_format,
mode_cmd->modifier[0]);
if (!format) { if (!format) {
dev_err(dev->dev, "unsupported pixel format: %4.4s\n", dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
(char *)&mode_cmd->pixel_format); (char *)&mode_cmd->pixel_format);
......
...@@ -92,8 +92,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, ...@@ -92,8 +92,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
if (IS_ERR(fb)) { if (IS_ERR(fb)) {
dev_err(dev->dev, "failed to allocate fb\n"); dev_err(dev->dev, "failed to allocate fb\n");
ret = PTR_ERR(fb); return PTR_ERR(fb);
goto fail;
} }
bo = msm_framebuffer_bo(fb, 0); bo = msm_framebuffer_bo(fb, 0);
...@@ -151,13 +150,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, ...@@ -151,13 +150,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
fail_unlock: fail_unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
fail: drm_framebuffer_remove(fb);
if (ret) {
if (fb)
drm_framebuffer_remove(fb);
}
return ret; return ret;
} }
......
...@@ -132,17 +132,19 @@ static void put_pages(struct drm_gem_object *obj) ...@@ -132,17 +132,19 @@ static void put_pages(struct drm_gem_object *obj)
struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_object *msm_obj = to_msm_bo(obj);
if (msm_obj->pages) { if (msm_obj->pages) {
/* For non-cached buffers, ensure the new pages are clean if (msm_obj->sgt) {
* because display controller, GPU, etc. are not coherent: /* For non-cached buffers, ensure the new
*/ * pages are clean because display controller,
if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) * GPU, etc. are not coherent:
dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, */
msm_obj->sgt->nents, DMA_BIDIRECTIONAL); if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl,
msm_obj->sgt->nents,
DMA_BIDIRECTIONAL);
if (msm_obj->sgt)
sg_free_table(msm_obj->sgt); sg_free_table(msm_obj->sgt);
kfree(msm_obj->sgt);
kfree(msm_obj->sgt); }
if (use_pages(obj)) if (use_pages(obj))
drm_gem_put_pages(obj, msm_obj->pages, true, false); drm_gem_put_pages(obj, msm_obj->pages, true, false);
......
...@@ -48,8 +48,11 @@ struct msm_kms_funcs { ...@@ -48,8 +48,11 @@ struct msm_kms_funcs {
/* functions to wait for atomic commit completed on each CRTC */ /* functions to wait for atomic commit completed on each CRTC */
void (*wait_for_crtc_commit_done)(struct msm_kms *kms, void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
struct drm_crtc *crtc); struct drm_crtc *crtc);
/* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */
const struct msm_format *(*get_format)(struct msm_kms *kms,
const uint32_t format,
const uint64_t modifiers);
/* misc: */ /* misc: */
const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder); struct drm_encoder *encoder);
int (*set_split_display)(struct msm_kms *kms, int (*set_split_display)(struct msm_kms *kms,
......
...@@ -179,10 +179,9 @@ qxl_push_command_ring_release(struct qxl_device *qdev, struct qxl_release *relea ...@@ -179,10 +179,9 @@ qxl_push_command_ring_release(struct qxl_device *qdev, struct qxl_release *relea
uint32_t type, bool interruptible) uint32_t type, bool interruptible)
{ {
struct qxl_command cmd; struct qxl_command cmd;
struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
cmd.type = type; cmd.type = type;
cmd.data = qxl_bo_physical_address(qdev, to_qxl_bo(entry->tv.bo), release->release_offset); cmd.data = qxl_bo_physical_address(qdev, release->release_bo, release->release_offset);
return qxl_ring_push(qdev->command_ring, &cmd, interruptible); return qxl_ring_push(qdev->command_ring, &cmd, interruptible);
} }
...@@ -192,10 +191,9 @@ qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *releas ...@@ -192,10 +191,9 @@ qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *releas
uint32_t type, bool interruptible) uint32_t type, bool interruptible)
{ {
struct qxl_command cmd; struct qxl_command cmd;
struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
cmd.type = type; cmd.type = type;
cmd.data = qxl_bo_physical_address(qdev, to_qxl_bo(entry->tv.bo), release->release_offset); cmd.data = qxl_bo_physical_address(qdev, release->release_bo, release->release_offset);
return qxl_ring_push(qdev->cursor_ring, &cmd, interruptible); return qxl_ring_push(qdev->cursor_ring, &cmd, interruptible);
} }
......
...@@ -167,6 +167,7 @@ struct qxl_release { ...@@ -167,6 +167,7 @@ struct qxl_release {
int id; int id;
int type; int type;
struct qxl_bo *release_bo;
uint32_t release_offset; uint32_t release_offset;
uint32_t surface_release_id; uint32_t surface_release_id;
struct ww_acquire_ctx ticket; struct ww_acquire_ctx ticket;
......
...@@ -182,9 +182,9 @@ static int qxl_process_single_command(struct qxl_device *qdev, ...@@ -182,9 +182,9 @@ static int qxl_process_single_command(struct qxl_device *qdev,
goto out_free_reloc; goto out_free_reloc;
/* TODO copy slow path code from i915 */ /* TODO copy slow path code from i915 */
fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_SIZE)); fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_MASK));
unwritten = __copy_from_user_inatomic_nocache unwritten = __copy_from_user_inatomic_nocache
(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_MASK),
u64_to_user_ptr(cmd->command), cmd->command_size); u64_to_user_ptr(cmd->command), cmd->command_size);
{ {
......
...@@ -173,6 +173,7 @@ qxl_release_free_list(struct qxl_release *release) ...@@ -173,6 +173,7 @@ qxl_release_free_list(struct qxl_release *release)
list_del(&entry->tv.head); list_del(&entry->tv.head);
kfree(entry); kfree(entry);
} }
release->release_bo = NULL;
} }
void void
...@@ -296,7 +297,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, ...@@ -296,7 +297,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
{ {
if (surface_cmd_type == QXL_SURFACE_CMD_DESTROY && create_rel) { if (surface_cmd_type == QXL_SURFACE_CMD_DESTROY && create_rel) {
int idr_ret; int idr_ret;
struct qxl_bo_list *entry = list_first_entry(&create_rel->bos, struct qxl_bo_list, tv.head);
struct qxl_bo *bo; struct qxl_bo *bo;
union qxl_release_info *info; union qxl_release_info *info;
...@@ -304,8 +304,9 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, ...@@ -304,8 +304,9 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release); idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
if (idr_ret < 0) if (idr_ret < 0)
return idr_ret; return idr_ret;
bo = to_qxl_bo(entry->tv.bo); bo = create_rel->release_bo;
(*release)->release_bo = bo;
(*release)->release_offset = create_rel->release_offset + 64; (*release)->release_offset = create_rel->release_offset + 64;
qxl_release_list_add(*release, bo); qxl_release_list_add(*release, bo);
...@@ -365,6 +366,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, ...@@ -365,6 +366,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
bo = qxl_bo_ref(qdev->current_release_bo[cur_idx]); bo = qxl_bo_ref(qdev->current_release_bo[cur_idx]);
(*release)->release_bo = bo;
(*release)->release_offset = qdev->current_release_bo_offset[cur_idx] * release_size_per_bo[cur_idx]; (*release)->release_offset = qdev->current_release_bo_offset[cur_idx] * release_size_per_bo[cur_idx];
qdev->current_release_bo_offset[cur_idx]++; qdev->current_release_bo_offset[cur_idx]++;
...@@ -408,13 +410,12 @@ union qxl_release_info *qxl_release_map(struct qxl_device *qdev, ...@@ -408,13 +410,12 @@ union qxl_release_info *qxl_release_map(struct qxl_device *qdev,
{ {
void *ptr; void *ptr;
union qxl_release_info *info; union qxl_release_info *info;
struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head); struct qxl_bo *bo = release->release_bo;
struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
ptr = qxl_bo_kmap_atomic_page(qdev, bo, release->release_offset & PAGE_SIZE); ptr = qxl_bo_kmap_atomic_page(qdev, bo, release->release_offset & PAGE_MASK);
if (!ptr) if (!ptr)
return NULL; return NULL;
info = ptr + (release->release_offset & ~PAGE_SIZE); info = ptr + (release->release_offset & ~PAGE_MASK);
return info; return info;
} }
...@@ -422,11 +423,10 @@ void qxl_release_unmap(struct qxl_device *qdev, ...@@ -422,11 +423,10 @@ void qxl_release_unmap(struct qxl_device *qdev,
struct qxl_release *release, struct qxl_release *release,
union qxl_release_info *info) union qxl_release_info *info)
{ {
struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head); struct qxl_bo *bo = release->release_bo;
struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
void *ptr; void *ptr;
ptr = ((void *)info) - (release->release_offset & ~PAGE_SIZE); ptr = ((void *)info) - (release->release_offset & ~PAGE_MASK);
qxl_bo_kunmap_atomic_page(qdev, bo, ptr); qxl_bo_kunmap_atomic_page(qdev, bo, ptr);
} }
......
...@@ -94,64 +94,9 @@ static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder) ...@@ -94,64 +94,9 @@ static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
} }
} }
static enum drm_mode_status sun4i_lvds_encoder_mode_valid(struct drm_encoder *crtc,
const struct drm_display_mode *mode)
{
struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(crtc);
struct sun4i_tcon *tcon = lvds->tcon;
u32 hsync = mode->hsync_end - mode->hsync_start;
u32 vsync = mode->vsync_end - mode->vsync_start;
unsigned long rate = mode->clock * 1000;
long rounded_rate;
DRM_DEBUG_DRIVER("Validating modes...\n");
if (hsync < 1)
return MODE_HSYNC_NARROW;
if (hsync > 0x3ff)
return MODE_HSYNC_WIDE;
if ((mode->hdisplay < 1) || (mode->htotal < 1))
return MODE_H_ILLEGAL;
if ((mode->hdisplay > 0x7ff) || (mode->htotal > 0xfff))
return MODE_BAD_HVALUE;
DRM_DEBUG_DRIVER("Horizontal parameters OK\n");
if (vsync < 1)
return MODE_VSYNC_NARROW;
if (vsync > 0x3ff)
return MODE_VSYNC_WIDE;
if ((mode->vdisplay < 1) || (mode->vtotal < 1))
return MODE_V_ILLEGAL;
if ((mode->vdisplay > 0x7ff) || (mode->vtotal > 0xfff))
return MODE_BAD_VVALUE;
DRM_DEBUG_DRIVER("Vertical parameters OK\n");
tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
rounded_rate = clk_round_rate(tcon->dclk, rate);
if (rounded_rate < rate)
return MODE_CLOCK_LOW;
if (rounded_rate > rate)
return MODE_CLOCK_HIGH;
DRM_DEBUG_DRIVER("Clock rate OK\n");
return MODE_OK;
}
static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = { static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
.disable = sun4i_lvds_encoder_disable, .disable = sun4i_lvds_encoder_disable,
.enable = sun4i_lvds_encoder_enable, .enable = sun4i_lvds_encoder_enable,
.mode_valid = sun4i_lvds_encoder_mode_valid,
}; };
static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = { static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
......
...@@ -293,7 +293,7 @@ static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev, ...@@ -293,7 +293,7 @@ static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC); ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC);
if (ret == -ENOSPC) { if (ret == -ENOSPC) {
spin_unlock(&vgdev->ctrlq.qlock); spin_unlock(&vgdev->ctrlq.qlock);
wait_event(vgdev->ctrlq.ack_queue, vq->num_free); wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= outcnt + incnt);
spin_lock(&vgdev->ctrlq.qlock); spin_lock(&vgdev->ctrlq.qlock);
goto retry; goto retry;
} else { } else {
...@@ -368,7 +368,7 @@ static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev, ...@@ -368,7 +368,7 @@ static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
ret = virtqueue_add_sgs(vq, sgs, outcnt, 0, vbuf, GFP_ATOMIC); ret = virtqueue_add_sgs(vq, sgs, outcnt, 0, vbuf, GFP_ATOMIC);
if (ret == -ENOSPC) { if (ret == -ENOSPC) {
spin_unlock(&vgdev->cursorq.qlock); spin_unlock(&vgdev->cursorq.qlock);
wait_event(vgdev->cursorq.ack_queue, vq->num_free); wait_event(vgdev->cursorq.ack_queue, vq->num_free >= outcnt);
spin_lock(&vgdev->cursorq.qlock); spin_lock(&vgdev->cursorq.qlock);
goto retry; goto retry;
} 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