core, i915, amdgpu, imx, sun4i, ast, tegra, vmwgfx fixes.

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJatEGeAAoJEAx081l5xIa+I48P/1hikZ9+JzL3paYkknLVsBCg
 TkVxOLFDk+1vd4MtmEhiDgwR1VxETgQJv/Y6wRqBALGu/kYcyRq5S1j6B65ZLFMx
 sKVSmp2quGE2myJeFVQj3mi2N2duVbaNk1hbZDXDh/tvvlAfnpX2XkjR2gtKGjOM
 LfY4AFYggoBeMEFWBk287b/O/qk1BvVNZxyxnvpsm6HboCwOB6QFt5Du8MFafxbp
 lqqfXEHFVUQ8ukqphoYcrRzr3d6AGtR6HBHDC8ooVIe2QAyZftsWaxHgbyZnBExG
 obH/e9ssrIQBQsOky2VVxS1QesWarUwV+m3j/u4N2OvNZ7uSTKt4meHHdpihujLf
 H8xErUbkMMGYCgatqHCSCAFz8TNRDWutecMxSoAmpsF+6rKr4T+oKvbHiubN6rPa
 s4m1BA2SjSmeowNcUNeTfcKeyRFKYrCepRtlTCibLB+1Nco5oArVEXEMqti3VMvk
 cJW1qLpdQVyQHk7EA5lZHB5iFtPsxhOpyzjIWScdyFjTx0JcmnVxraUbnqFU8J5X
 aNhBz6tbfxTn1r2bTZgkW+zKpVJd6LCWleUNsKHTNcyHffz2ny4kiK8TdcUJBTkC
 sK26IPIY8X5lM1p3/Lytrki7+Ul+ChfyDaUcXC3VEqseznaRxzzlDhKpLohOmuAt
 z5VQUFYxZR6EYQ6oOo1W
 =4caQ
 -----END PGP SIGNATURE-----

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

Pull drm fixes from Dave Airlie:
 "A bunch of fixes all over the place (core, i915, amdgpu, imx, sun4i,
  ast, tegra, vmwgfx), nothing too serious or worrying at this stage.

   - one uapi fix to stop multi-planar images with getfb

   - Sun4i error path and clock fixes

   - udl driver mmap offset fix

   - i915 DP MST and GPU reset fixes

   - vmwgfx mutex and black screen fixes

   - imx array underflow fix and vblank fix

   - amdgpu: display fixes

   - exynos devicetree fix

   - ast mode fix"

* tag 'drm-fixes-for-v4.16-rc7' of git://people.freedesktop.org/~airlied/linux: (29 commits)
  drm/ast: Fixed 1280x800 Display Issue
  drm: udl: Properly check framebuffer mmap offsets
  drm/i915: Specify which engines to reset following semaphore/event lockups
  drm/vmwgfx: Fix a destoy-while-held mutex problem.
  drm/vmwgfx: Fix black screen and device errors when running without fbdev
  drm: Reject getfb for multi-plane framebuffers
  drm/amd/display: Add one to EDID's audio channel count when passing to DC
  drm/amd/display: We shouldn't set format_default on plane as atomic driver
  drm/amd/display: Fix FMT truncation programming
  drm/amd/display: Allow truncation to 10 bits
  drm/sun4i: hdmi: Fix another error handling path in 'sun4i_hdmi_bind()'
  drm/sun4i: hdmi: Fix an error handling path in 'sun4i_hdmi_bind()'
  drm/i915/dp: Write to SET_POWER dpcd to enable MST hub.
  drm/amd/display: fix dereferencing possible ERR_PTR()
  drm/amd/display: Refine disable VGA
  drm/tegra: Shutdown on driver unbind
  drm/tegra: dsi: Don't disable regulator on ->exit()
  drm/tegra: dc: Detach IOMMU group from domain only once
  dt-bindings: exynos: Document #sound-dai-cells property of the HDMI node
  drm/imx: move arming of the vblank event to atomic_flush
  ...
This commit is contained in:
Linus Torvalds 2018-03-22 17:37:44 -07:00
commit 9ec7ccc8f4
29 changed files with 173 additions and 81 deletions

View File

@ -16,6 +16,7 @@ Required properties:
- ddc: phandle to the hdmi ddc node - ddc: phandle to the hdmi ddc node
- phy: phandle to the hdmi phy node - phy: phandle to the hdmi phy node
- samsung,syscon-phandle: phandle for system controller node for PMU. - samsung,syscon-phandle: phandle for system controller node for PMU.
- #sound-dai-cells: should be 0.
Required properties for Exynos 4210, 4212, 5420 and 5433: Required properties for Exynos 4210, 4212, 5420 and 5433:
- clocks: list of clock IDs from SoC clock driver. - clocks: list of clock IDs from SoC clock driver.

View File

@ -2063,9 +2063,12 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
DRM_INFO("amdgpu: finishing device.\n"); DRM_INFO("amdgpu: finishing device.\n");
adev->shutdown = true; adev->shutdown = true;
if (adev->mode_info.mode_config_initialized) if (adev->mode_info.mode_config_initialized){
drm_crtc_force_disable_all(adev->ddev); if (!amdgpu_device_has_dc_support(adev))
drm_crtc_force_disable_all(adev->ddev);
else
drm_atomic_helper_shutdown(adev->ddev);
}
amdgpu_ib_pool_fini(adev); amdgpu_ib_pool_fini(adev);
amdgpu_fence_driver_fini(adev); amdgpu_fence_driver_fini(adev);
amdgpu_fbdev_fini(adev); amdgpu_fbdev_fini(adev);

View File

@ -3134,8 +3134,6 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
switch (aplane->base.type) { switch (aplane->base.type) {
case DRM_PLANE_TYPE_PRIMARY: case DRM_PLANE_TYPE_PRIMARY:
aplane->base.format_default = true;
res = drm_universal_plane_init( res = drm_universal_plane_init(
dm->adev->ddev, dm->adev->ddev,
&aplane->base, &aplane->base,
@ -4794,6 +4792,9 @@ static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state,
return -EDEADLK; return -EDEADLK;
crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc); crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
if (crtc->primary == plane && crtc_state->active) { if (crtc->primary == plane && crtc_state->active) {
if (!plane_state->fb) if (!plane_state->fb)
return -EINVAL; return -EINVAL;

View File

@ -109,7 +109,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
struct cea_sad *sad = &sads[i]; struct cea_sad *sad = &sads[i];
edid_caps->audio_modes[i].format_code = sad->format; edid_caps->audio_modes[i].format_code = sad->format;
edid_caps->audio_modes[i].channel_count = sad->channels; edid_caps->audio_modes[i].channel_count = sad->channels + 1;
edid_caps->audio_modes[i].sample_rate = sad->freq; edid_caps->audio_modes[i].sample_rate = sad->freq;
edid_caps->audio_modes[i].sample_size = sad->byte2; edid_caps->audio_modes[i].sample_size = sad->byte2;
} }

View File

@ -496,6 +496,9 @@ struct dce_hwseq_registers {
HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
HWS_SF(, D1VGA_CONTROL, D1VGA_MODE_ENABLE, mask_sh),\ HWS_SF(, D1VGA_CONTROL, D1VGA_MODE_ENABLE, mask_sh),\
HWS_SF(, D2VGA_CONTROL, D2VGA_MODE_ENABLE, mask_sh),\
HWS_SF(, D3VGA_CONTROL, D3VGA_MODE_ENABLE, mask_sh),\
HWS_SF(, D4VGA_CONTROL, D4VGA_MODE_ENABLE, mask_sh),\
HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_ENABLE, mask_sh),\ HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_ENABLE, mask_sh),\
HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_RENDER_START, mask_sh),\ HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_RENDER_START, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
@ -591,7 +594,10 @@ struct dce_hwseq_registers {
type DENTIST_DISPCLK_WDIVIDER; \ type DENTIST_DISPCLK_WDIVIDER; \
type VGA_TEST_ENABLE; \ type VGA_TEST_ENABLE; \
type VGA_TEST_RENDER_START; \ type VGA_TEST_RENDER_START; \
type D1VGA_MODE_ENABLE; type D1VGA_MODE_ENABLE; \
type D2VGA_MODE_ENABLE; \
type D3VGA_MODE_ENABLE; \
type D4VGA_MODE_ENABLE;
struct dce_hwseq_shift { struct dce_hwseq_shift {
HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_REG_FIELD_LIST(uint8_t)

View File

@ -128,23 +128,22 @@ static void set_truncation(
return; return;
} }
/* on other format-to do */ /* on other format-to do */
if (params->flags.TRUNCATE_ENABLED == 0 || if (params->flags.TRUNCATE_ENABLED == 0)
params->flags.TRUNCATE_DEPTH == 2)
return; return;
/*Set truncation depth and Enable truncation*/ /*Set truncation depth and Enable truncation*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1, FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, FMT_TRUNCATE_DEPTH,
params->flags.TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH,
FMT_TRUNCATE_MODE, FMT_TRUNCATE_MODE,
params->flags.TRUNCATE_DEPTH); params->flags.TRUNCATE_MODE);
} }
/** /**
* set_spatial_dither * set_spatial_dither
* 1) set spatial dithering mode: pattern of seed * 1) set spatial dithering mode: pattern of seed
* 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp * 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
* 3) set random seed * 3) set random seed
* 4) set random mode * 4) set random mode
* lfsr is reset every frame or not reset * lfsr is reset every frame or not reset

View File

@ -238,14 +238,24 @@ static void enable_power_gating_plane(
static void disable_vga( static void disable_vga(
struct dce_hwseq *hws) struct dce_hwseq *hws)
{ {
unsigned int in_vga_mode = 0; unsigned int in_vga1_mode = 0;
unsigned int in_vga2_mode = 0;
unsigned int in_vga3_mode = 0;
unsigned int in_vga4_mode = 0;
REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga_mode); REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
if (in_vga_mode == 0) if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
in_vga3_mode == 0 && in_vga4_mode == 0)
return; return;
REG_WRITE(D1VGA_CONTROL, 0); REG_WRITE(D1VGA_CONTROL, 0);
REG_WRITE(D2VGA_CONTROL, 0);
REG_WRITE(D3VGA_CONTROL, 0);
REG_WRITE(D4VGA_CONTROL, 0);
/* HW Engineer's Notes: /* HW Engineer's Notes:
* During switch from vga->extended, if we set the VGA_TEST_ENABLE and * During switch from vga->extended, if we set the VGA_TEST_ENABLE and

View File

@ -97,7 +97,7 @@ static const struct ast_vbios_dclk_info dclk_table[] = {
{0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */
{0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */
{0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */
{0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */ {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */
{0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */
{0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */
{0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */
@ -127,7 +127,7 @@ static const struct ast_vbios_dclk_info dclk_table_ast2500[] = {
{0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */
{0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */
{0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */
{0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */ {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */
{0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */
{0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */
{0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */

View File

@ -461,6 +461,12 @@ int drm_mode_getfb(struct drm_device *dev,
if (!fb) if (!fb)
return -ENOENT; return -ENOENT;
/* Multi-planar framebuffers need getfb2. */
if (fb->format->num_planes > 1) {
ret = -EINVAL;
goto out;
}
r->height = fb->height; r->height = fb->height;
r->width = fb->width; r->width = fb->width;
r->depth = fb->format->depth; r->depth = fb->format->depth;
@ -484,6 +490,7 @@ int drm_mode_getfb(struct drm_device *dev,
ret = -ENODEV; ret = -ENODEV;
} }
out:
drm_framebuffer_put(fb); drm_framebuffer_put(fb);
return ret; return ret;

View File

@ -2175,8 +2175,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
intel_prepare_dp_ddi_buffers(encoder, crtc_state); intel_prepare_dp_ddi_buffers(encoder, crtc_state);
intel_ddi_init_dp_buf_reg(encoder); intel_ddi_init_dp_buf_reg(encoder);
if (!is_mst) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
intel_dp_stop_link_train(intel_dp); intel_dp_stop_link_train(intel_dp);
@ -2274,14 +2273,12 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
struct intel_dp *intel_dp = &dig_port->dp; struct intel_dp *intel_dp = &dig_port->dp;
bool is_mst = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST);
/* /*
* Power down sink before disabling the port, otherwise we end * Power down sink before disabling the port, otherwise we end
* up getting interrupts from the sink on detecting link loss. * up getting interrupts from the sink on detecting link loss.
*/ */
if (!is_mst) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
intel_disable_ddi_buf(encoder); intel_disable_ddi_buf(encoder);

View File

@ -246,7 +246,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd)
*/ */
tmp = I915_READ_CTL(engine); tmp = I915_READ_CTL(engine);
if (tmp & RING_WAIT) { if (tmp & RING_WAIT) {
i915_handle_error(dev_priv, 0, i915_handle_error(dev_priv, BIT(engine->id),
"Kicking stuck wait on %s", "Kicking stuck wait on %s",
engine->name); engine->name);
I915_WRITE_CTL(engine, tmp); I915_WRITE_CTL(engine, tmp);
@ -258,7 +258,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd)
default: default:
return ENGINE_DEAD; return ENGINE_DEAD;
case 1: case 1:
i915_handle_error(dev_priv, 0, i915_handle_error(dev_priv, ALL_ENGINES,
"Kicking stuck semaphore on %s", "Kicking stuck semaphore on %s",
engine->name); engine->name);
I915_WRITE_CTL(engine, tmp); I915_WRITE_CTL(engine, tmp);

View File

@ -225,7 +225,11 @@ static void ipu_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state) struct drm_crtc_state *old_crtc_state)
{ {
drm_crtc_vblank_on(crtc); drm_crtc_vblank_on(crtc);
}
static void ipu_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
spin_lock_irq(&crtc->dev->event_lock); spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event) { if (crtc->state->event) {
WARN_ON(drm_crtc_vblank_get(crtc)); WARN_ON(drm_crtc_vblank_get(crtc));
@ -293,6 +297,7 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
.mode_set_nofb = ipu_crtc_mode_set_nofb, .mode_set_nofb = ipu_crtc_mode_set_nofb,
.atomic_check = ipu_crtc_atomic_check, .atomic_check = ipu_crtc_atomic_check,
.atomic_begin = ipu_crtc_atomic_begin, .atomic_begin = ipu_crtc_atomic_begin,
.atomic_flush = ipu_crtc_atomic_flush,
.atomic_disable = ipu_crtc_atomic_disable, .atomic_disable = ipu_crtc_atomic_disable,
.atomic_enable = ipu_crtc_atomic_enable, .atomic_enable = ipu_crtc_atomic_enable,
}; };

View File

@ -22,6 +22,7 @@
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include "video/imx-ipu-v3.h" #include "video/imx-ipu-v3.h"
#include "imx-drm.h"
#include "ipuv3-plane.h" #include "ipuv3-plane.h"
struct ipu_plane_state { struct ipu_plane_state {
@ -272,7 +273,7 @@ static void ipu_plane_destroy(struct drm_plane *plane)
kfree(ipu_plane); kfree(ipu_plane);
} }
void ipu_plane_state_reset(struct drm_plane *plane) static void ipu_plane_state_reset(struct drm_plane *plane)
{ {
struct ipu_plane_state *ipu_state; struct ipu_plane_state *ipu_state;
@ -292,7 +293,8 @@ void ipu_plane_state_reset(struct drm_plane *plane)
plane->state = &ipu_state->base; plane->state = &ipu_state->base;
} }
struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane) static struct drm_plane_state *
ipu_plane_duplicate_state(struct drm_plane *plane)
{ {
struct ipu_plane_state *state; struct ipu_plane_state *state;
@ -306,8 +308,8 @@ struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane)
return &state->base; return &state->base;
} }
void ipu_plane_destroy_state(struct drm_plane *plane, static void ipu_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);

View File

@ -90,25 +90,18 @@ void radeon_connector_hotplug(struct drm_connector *connector)
/* don't do anything if sink is not display port, i.e., /* don't do anything if sink is not display port, i.e.,
* passive dp->(dvi|hdmi) adaptor * passive dp->(dvi|hdmi) adaptor
*/ */
if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT &&
int saved_dpms = connector->dpms; radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
/* Only turn off the display if it's physically disconnected */ radeon_dp_needs_link_train(radeon_connector)) {
if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { /* Don't start link training before we have the DPCD */
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); if (!radeon_dp_getdpcd(radeon_connector))
} else if (radeon_dp_needs_link_train(radeon_connector)) { return;
/* Don't try to start link training before we
* have the dpcd */
if (!radeon_dp_getdpcd(radeon_connector))
return;
/* set it to OFF so that drm_helper_connector_dpms() /* Turn the connector off and back on immediately, which
* won't return immediately since the current state * will trigger link training
* is ON at this point. */
*/ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
connector->dpms = DRM_MODE_DPMS_OFF; drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}
connector->dpms = saved_dpms;
} }
} }
} }

View File

@ -111,7 +111,7 @@ static int sun4i_drv_bind(struct device *dev)
/* drm_vblank_init calls kcalloc, which can fail */ /* drm_vblank_init calls kcalloc, which can fail */
ret = drm_vblank_init(drm, drm->mode_config.num_crtc); ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret) if (ret)
goto free_mem_region; goto cleanup_mode_config;
drm->irq_enabled = true; drm->irq_enabled = true;
@ -139,7 +139,6 @@ finish_poll:
sun4i_framebuffer_free(drm); sun4i_framebuffer_free(drm);
cleanup_mode_config: cleanup_mode_config:
drm_mode_config_cleanup(drm); drm_mode_config_cleanup(drm);
free_mem_region:
of_reserved_mem_device_release(dev); of_reserved_mem_device_release(dev);
free_drm: free_drm:
drm_dev_unref(drm); drm_dev_unref(drm);

View File

@ -538,7 +538,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
&sun4i_hdmi_regmap_config); &sun4i_hdmi_regmap_config);
if (IS_ERR(hdmi->regmap)) { if (IS_ERR(hdmi->regmap)) {
dev_err(dev, "Couldn't create HDMI encoder regmap\n"); dev_err(dev, "Couldn't create HDMI encoder regmap\n");
return PTR_ERR(hdmi->regmap); ret = PTR_ERR(hdmi->regmap);
goto err_disable_mod_clk;
} }
ret = sun4i_tmds_create(hdmi); ret = sun4i_tmds_create(hdmi);
@ -551,7 +552,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc");
if (IS_ERR(hdmi->ddc_parent_clk)) { if (IS_ERR(hdmi->ddc_parent_clk)) {
dev_err(dev, "Couldn't get the HDMI DDC clock\n"); dev_err(dev, "Couldn't get the HDMI DDC clock\n");
return PTR_ERR(hdmi->ddc_parent_clk); ret = PTR_ERR(hdmi->ddc_parent_clk);
goto err_disable_mod_clk;
} }
} else { } else {
hdmi->ddc_parent_clk = hdmi->tmds_clk; hdmi->ddc_parent_clk = hdmi->tmds_clk;

View File

@ -103,6 +103,7 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
if (enabled) { if (enabled) {
clk_prepare_enable(clk); clk_prepare_enable(clk);
clk_rate_exclusive_get(clk);
} else { } else {
clk_rate_exclusive_put(clk); clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
@ -262,7 +263,7 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
{ {
/* Configure the dot clock */ /* Configure the dot clock */
clk_set_rate_exclusive(tcon->dclk, mode->crtc_clock * 1000); clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
/* Set the resolution */ /* Set the resolution */
regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
@ -423,7 +424,7 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
WARN_ON(!tcon->quirks->has_channel_1); WARN_ON(!tcon->quirks->has_channel_1);
/* Configure the dot clock */ /* Configure the dot clock */
clk_set_rate_exclusive(tcon->sclk1, mode->crtc_clock * 1000); clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
/* Adjust clock delay */ /* Adjust clock delay */
clk_delay = sun4i_tcon_get_clk_delay(mode, 1); clk_delay = sun4i_tcon_get_clk_delay(mode, 1);

View File

@ -1903,8 +1903,12 @@ cleanup:
if (!IS_ERR(primary)) if (!IS_ERR(primary))
drm_plane_cleanup(primary); drm_plane_cleanup(primary);
if (group && tegra->domain) { if (group && dc->domain) {
iommu_detach_group(tegra->domain, group); if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
}
dc->domain = NULL; dc->domain = NULL;
} }
@ -1913,8 +1917,10 @@ cleanup:
static int tegra_dc_exit(struct host1x_client *client) static int tegra_dc_exit(struct host1x_client *client)
{ {
struct drm_device *drm = dev_get_drvdata(client->parent);
struct iommu_group *group = iommu_group_get(client->dev); struct iommu_group *group = iommu_group_get(client->dev);
struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_dc *dc = host1x_client_to_dc(client);
struct tegra_drm *tegra = drm->dev_private;
int err; int err;
devm_free_irq(dc->dev, dc->irq, dc); devm_free_irq(dc->dev, dc->irq, dc);
@ -1926,7 +1932,11 @@ static int tegra_dc_exit(struct host1x_client *client)
} }
if (group && dc->domain) { if (group && dc->domain) {
iommu_detach_group(dc->domain, group); if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
}
dc->domain = NULL; dc->domain = NULL;
} }

View File

@ -250,6 +250,7 @@ static void tegra_drm_unload(struct drm_device *drm)
drm_kms_helper_poll_fini(drm); drm_kms_helper_poll_fini(drm);
tegra_drm_fb_exit(drm); tegra_drm_fb_exit(drm);
drm_atomic_helper_shutdown(drm);
drm_mode_config_cleanup(drm); drm_mode_config_cleanup(drm);
err = host1x_device_exit(device); err = host1x_device_exit(device);

View File

@ -1072,7 +1072,6 @@ static int tegra_dsi_exit(struct host1x_client *client)
struct tegra_dsi *dsi = host1x_client_to_dsi(client); struct tegra_dsi *dsi = host1x_client_to_dsi(client);
tegra_output_exit(&dsi->output); tegra_output_exit(&dsi->output);
regulator_disable(dsi->vdd);
return 0; return 0;
} }

View File

@ -297,6 +297,10 @@ int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha)
case WIN_COLOR_DEPTH_B8G8R8X8: case WIN_COLOR_DEPTH_B8G8R8X8:
*alpha = WIN_COLOR_DEPTH_B8G8R8A8; *alpha = WIN_COLOR_DEPTH_B8G8R8A8;
return 0; return 0;
case WIN_COLOR_DEPTH_B5G6R5:
*alpha = opaque;
return 0;
} }
return -EINVAL; return -EINVAL;
@ -330,9 +334,6 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra,
unsigned int zpos[2]; unsigned int zpos[2];
unsigned int i; unsigned int i;
for (i = 0; i < 3; i++)
state->dependent[i] = false;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
zpos[i] = 0; zpos[i] = 0;
@ -346,6 +347,8 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra,
index = tegra_plane_get_overlap_index(tegra, p); index = tegra_plane_get_overlap_index(tegra, p);
state->dependent[index] = false;
/* /*
* If any of the other planes is on top of this plane and uses * If any of the other planes is on top of this plane and uses
* a format with an alpha component, mark this plane as being * a format with an alpha component, mark this plane as being

View File

@ -159,10 +159,15 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{ {
unsigned long start = vma->vm_start; unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long offset;
unsigned long page, pos; unsigned long page, pos;
if (offset + size > info->fix.smem_len) if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
offset = vma->vm_pgoff << PAGE_SHIFT;
if (offset > info->fix.smem_len || size > info->fix.smem_len - offset)
return -EINVAL; return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset; pos = (unsigned long)info->fix.smem_start + offset;

View File

@ -1337,6 +1337,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv)
*/ */
void vmw_svga_disable(struct vmw_private *dev_priv) void vmw_svga_disable(struct vmw_private *dev_priv)
{ {
/*
* Disabling SVGA will turn off device modesetting capabilities, so
* notify KMS about that so that it doesn't cache atomic state that
* isn't valid anymore, for example crtcs turned on.
* Strictly we'd want to do this under the SVGA lock (or an SVGA mutex),
* but vmw_kms_lost_device() takes the reservation sem and thus we'll
* end up with lock order reversal. Thus, a master may actually perform
* a new modeset just after we call vmw_kms_lost_device() and race with
* vmw_svga_disable(), but that should at worst cause atomic KMS state
* to be inconsistent with the device, causing modesetting problems.
*
*/
vmw_kms_lost_device(dev_priv->dev);
ttm_write_lock(&dev_priv->reservation_sem, false); ttm_write_lock(&dev_priv->reservation_sem, false);
spin_lock(&dev_priv->svga_lock); spin_lock(&dev_priv->svga_lock);
if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {

View File

@ -938,6 +938,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv); void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
void vmw_kms_lost_device(struct drm_device *dev);
int vmw_dumb_create(struct drm_file *file_priv, int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,

View File

@ -31,7 +31,6 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
/* Might need a hrtimer here? */ /* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
@ -2517,9 +2516,12 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
* Helper to be used if an error forces the caller to undo the actions of * Helper to be used if an error forces the caller to undo the actions of
* vmw_kms_helper_resource_prepare. * vmw_kms_helper_resource_prepare.
*/ */
void vmw_kms_helper_resource_revert(struct vmw_resource *res) void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx)
{ {
vmw_kms_helper_buffer_revert(res->backup); struct vmw_resource *res = ctx->res;
vmw_kms_helper_buffer_revert(ctx->buf);
vmw_dmabuf_unreference(&ctx->buf);
vmw_resource_unreserve(res, false, NULL, 0); vmw_resource_unreserve(res, false, NULL, 0);
mutex_unlock(&res->dev_priv->cmdbuf_mutex); mutex_unlock(&res->dev_priv->cmdbuf_mutex);
} }
@ -2536,10 +2538,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res)
* interrupted by a signal. * interrupted by a signal.
*/ */
int vmw_kms_helper_resource_prepare(struct vmw_resource *res, int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible) bool interruptible,
struct vmw_validation_ctx *ctx)
{ {
int ret = 0; int ret = 0;
ctx->buf = NULL;
ctx->res = res;
if (interruptible) if (interruptible)
ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex);
else else
@ -2558,6 +2564,8 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
res->dev_priv->has_mob); res->dev_priv->has_mob);
if (ret) if (ret)
goto out_unreserve; goto out_unreserve;
ctx->buf = vmw_dmabuf_reference(res->backup);
} }
ret = vmw_resource_validate(res); ret = vmw_resource_validate(res);
if (ret) if (ret)
@ -2565,7 +2573,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
return 0; return 0;
out_revert: out_revert:
vmw_kms_helper_buffer_revert(res->backup); vmw_kms_helper_buffer_revert(ctx->buf);
out_unreserve: out_unreserve:
vmw_resource_unreserve(res, false, NULL, 0); vmw_resource_unreserve(res, false, NULL, 0);
out_unlock: out_unlock:
@ -2581,11 +2589,13 @@ out_unlock:
* @out_fence: Optional pointer to a fence pointer. If non-NULL, a * @out_fence: Optional pointer to a fence pointer. If non-NULL, a
* ref-counted fence pointer is returned here. * ref-counted fence pointer is returned here.
*/ */
void vmw_kms_helper_resource_finish(struct vmw_resource *res, void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
struct vmw_fence_obj **out_fence) struct vmw_fence_obj **out_fence)
{ {
if (res->backup || out_fence) struct vmw_resource *res = ctx->res;
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, res->backup,
if (ctx->buf || out_fence)
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf,
out_fence, NULL); out_fence, NULL);
vmw_resource_unreserve(res, false, NULL, 0); vmw_resource_unreserve(res, false, NULL, 0);
@ -2851,3 +2861,14 @@ int vmw_kms_set_config(struct drm_mode_set *set,
return drm_atomic_helper_set_config(set, ctx); return drm_atomic_helper_set_config(set, ctx);
} }
/**
* vmw_kms_lost_device - Notify kms that modesetting capabilities will be lost
*
* @dev: Pointer to the drm device
*/
void vmw_kms_lost_device(struct drm_device *dev)
{
drm_atomic_helper_shutdown(dev);
}

View File

@ -240,6 +240,11 @@ struct vmw_display_unit {
int set_gui_y; int set_gui_y;
}; };
struct vmw_validation_ctx {
struct vmw_resource *res;
struct vmw_dma_buffer *buf;
};
#define vmw_crtc_to_du(x) \ #define vmw_crtc_to_du(x) \
container_of(x, struct vmw_display_unit, crtc) container_of(x, struct vmw_display_unit, crtc)
#define vmw_connector_to_du(x) \ #define vmw_connector_to_du(x) \
@ -296,9 +301,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
struct drm_vmw_fence_rep __user * struct drm_vmw_fence_rep __user *
user_fence_rep); user_fence_rep);
int vmw_kms_helper_resource_prepare(struct vmw_resource *res, int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible); bool interruptible,
void vmw_kms_helper_resource_revert(struct vmw_resource *res); struct vmw_validation_ctx *ctx);
void vmw_kms_helper_resource_finish(struct vmw_resource *res, void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx);
void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
struct vmw_fence_obj **out_fence); struct vmw_fence_obj **out_fence);
int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_file *file_priv, struct drm_file *file_priv,
@ -439,5 +445,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
int vmw_kms_set_config(struct drm_mode_set *set, int vmw_kms_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
#endif #endif

View File

@ -909,12 +909,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs = struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base); container_of(framebuffer, typeof(*vfbs), base);
struct vmw_kms_sou_surface_dirty sdirty; struct vmw_kms_sou_surface_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret; int ret;
if (!srf) if (!srf)
srf = &vfbs->surface->res; srf = &vfbs->surface->res;
ret = vmw_kms_helper_resource_prepare(srf, true); ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret) if (ret)
return ret; return ret;
@ -933,7 +934,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
dest_x, dest_y, num_clips, inc, dest_x, dest_y, num_clips, inc,
&sdirty.base); &sdirty.base);
vmw_kms_helper_resource_finish(srf, out_fence); vmw_kms_helper_resource_finish(&ctx, out_fence);
return ret; return ret;
} }

View File

@ -980,12 +980,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs = struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base); container_of(framebuffer, typeof(*vfbs), base);
struct vmw_stdu_dirty sdirty; struct vmw_stdu_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret; int ret;
if (!srf) if (!srf)
srf = &vfbs->surface->res; srf = &vfbs->surface->res;
ret = vmw_kms_helper_resource_prepare(srf, true); ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret) if (ret)
return ret; return ret;
@ -1008,7 +1009,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
dest_x, dest_y, num_clips, inc, dest_x, dest_y, num_clips, inc,
&sdirty.base); &sdirty.base);
out_finish: out_finish:
vmw_kms_helper_resource_finish(srf, out_fence); vmw_kms_helper_resource_finish(&ctx, out_fence);
return ret; return ret;
} }

View File

@ -250,10 +250,14 @@ void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
{ {
int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
struct ipu_prg *prg = ipu_chan->ipu->prg_priv; struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
struct ipu_prg_channel *chan = &prg->chan[prg_chan]; struct ipu_prg_channel *chan;
u32 val; u32 val;
if (!chan->enabled || prg_chan < 0) if (prg_chan < 0)
return;
chan = &prg->chan[prg_chan];
if (!chan->enabled)
return; return;
pm_runtime_get_sync(prg->dev); pm_runtime_get_sync(prg->dev);
@ -280,13 +284,15 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
{ {
int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
struct ipu_prg *prg = ipu_chan->ipu->prg_priv; struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
struct ipu_prg_channel *chan = &prg->chan[prg_chan]; struct ipu_prg_channel *chan;
u32 val; u32 val;
int ret; int ret;
if (prg_chan < 0) if (prg_chan < 0)
return prg_chan; return prg_chan;
chan = &prg->chan[prg_chan];
if (chan->enabled) { if (chan->enabled) {
ipu_pre_update(prg->pres[chan->used_pre], *eba); ipu_pre_update(prg->pres[chan->used_pre], *eba);
return 0; return 0;