This pull request brings in interlaced vblank timing and a 3D

rendering memory/CPU overhead reduction.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCgAGBQJXxKfYAAoJELXWKTbR/J7ob4QP/ipAXOUilPlhtOgLALgYJAMh
 IHeJVpa9CJuXt72A+L2KUZ/5iaZ1ALTFjne/1QjaGX/oN92R7uBO8aj9B43Mi7Qu
 C6GlxAJ8MQWWbytw2ez52dDt2mR5FcuazbdAcL32loCwYq6C5mrvJk7lNKImj+4/
 uoOCg1gsmBLRO1iZGzlLRFGQ8FwXaRviotKlpCiiQyLFlNsLRIalxYQgD3I3uF7l
 BkvF3uimUQVIbYFd6lwwftv2/pvointiSMOQk5MYeRsWf4od/SofeB82LvYEZG6w
 nybhuNzFj0ifAIw4klqJyHCZdst0cO0AwnxO9GVL29r8DB7fEUPoM+gB/fr9sejx
 d+gzrO2LnjrIWxwTvNlvrxpf+vkrlynYAOWIBwvX7ZehsMA3U4yoGZ49JOLSoOvM
 KTj9uMS0RFqJV5t2GpAaGtkQk896xm7UaETy6hyD8srafUcgaqj1EEkbJnIEYLoh
 ThjowDqp/AbqXyM8lefSMi4jn9NdksDo+vTC+W3npo2YkWDX4G9fbMxKoJaXMJba
 D22DCdUUS/DxcKuFiWkgUY3rbzEJcClubYEVBCDvaYtlNsG0eTKMpG4Zj9yzfR5j
 mc8PDlfLRNI+6oHZYaz22E0bcgb2G2rrxBl4IbctCv7jef8h8u+uFQVlR0rU4AFb
 U/xE4XI2yHkefZidlyAr
 =rUTW
 -----END PGP SIGNATURE-----

Merge tag 'drm-vc4-next-2016-08-29' of https://github.com/anholt/linux into drm-next

This pull request brings in interlaced vblank timing and a 3D
rendering memory/CPU overhead reduction.

* tag 'drm-vc4-next-2016-08-29' of https://github.com/anholt/linux:
  drm/vc4: Don't force new binner overflow allocation per draw.
  drm/vc4: Enable/Disable vblanks properly in crtc en/disable.
  drm/vc4: Enable precise vblank timestamping for interlaced modes.
  drm/vc4: Reject doublescan modes.
  drm/vc4: Fix handling of interlaced video modes.
  drm/vc4: Disallow interlaced modes on DPI.
This commit is contained in:
Dave Airlie 2016-09-02 15:50:19 +10:00
commit 2c07d5a8b8
4 changed files with 77 additions and 19 deletions

View File

@ -163,14 +163,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
int vblank_lines; int vblank_lines;
int ret = 0; int ret = 0;
/*
* XXX Doesn't work well in interlaced mode yet, partially due
* to problems in vc4 kms or drm core interlaced mode handling,
* so disable for now in interlaced mode.
*/
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
return ret;
/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
/* Get optional system timestamp before query. */ /* Get optional system timestamp before query. */
@ -191,10 +183,15 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
/* Vertical position of hvs composed scanline. */ /* Vertical position of hvs composed scanline. */
*vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE);
*hpos = 0;
/* No hpos info available. */ if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
if (hpos) *vpos /= 2;
*hpos = 0;
/* Use hpos to correct for field offset in interlaced mode. */
if (VC4_GET_FIELD(val, SCALER_DISPSTATX_FRAME_COUNT) % 2)
*hpos += mode->crtc_htotal / 2;
}
/* This is the offset we need for translating hvs -> pv scanout pos. */ /* This is the offset we need for translating hvs -> pv scanout pos. */
fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
@ -217,8 +214,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
* position of the PV. * position of the PV.
*/ */
*vpos -= fifo_lines + 1; *vpos -= fifo_lines + 1;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
*vpos /= 2;
ret |= DRM_SCANOUTPOS_ACCURATE; ret |= DRM_SCANOUTPOS_ACCURATE;
return ret; return ret;
@ -480,6 +475,9 @@ static void vc4_crtc_disable(struct drm_crtc *crtc)
int ret; int ret;
require_hvs_enabled(dev); require_hvs_enabled(dev);
/* Disable vblank irq handling before crtc is disabled. */
drm_crtc_vblank_off(crtc);
CRTC_WRITE(PV_V_CONTROL, CRTC_WRITE(PV_V_CONTROL,
CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN); CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
@ -530,6 +528,33 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
/* Turn on the pixel valve, which will emit the vstart signal. */ /* Turn on the pixel valve, which will emit the vstart signal. */
CRTC_WRITE(PV_V_CONTROL, CRTC_WRITE(PV_V_CONTROL,
CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
/* Enable vblank irq handling after crtc is started. */
drm_crtc_vblank_on(crtc);
}
static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
/* Do not allow doublescan modes from user space */
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) {
DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
crtc->base.id);
return false;
}
/*
* Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
* coming from user space. We don't want this, as it screws up
* vblank timestamping, so fix it up.
*/
drm_mode_set_crtcinfo(adjusted_mode, 0);
DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
drm_mode_debug_printmodeline(adjusted_mode);
return true;
} }
static int vc4_crtc_atomic_check(struct drm_crtc *crtc, static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
@ -819,6 +844,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
.mode_set_nofb = vc4_crtc_mode_set_nofb, .mode_set_nofb = vc4_crtc_mode_set_nofb,
.disable = vc4_crtc_disable, .disable = vc4_crtc_disable,
.enable = vc4_crtc_enable, .enable = vc4_crtc_enable,
.mode_fixup = vc4_crtc_mode_fixup,
.atomic_check = vc4_crtc_atomic_check, .atomic_check = vc4_crtc_atomic_check,
.atomic_flush = vc4_crtc_atomic_flush, .atomic_flush = vc4_crtc_atomic_flush,
}; };

View File

@ -340,9 +340,20 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
} }
} }
static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return false;
return true;
}
static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = {
.disable = vc4_dpi_encoder_disable, .disable = vc4_dpi_encoder_disable,
.enable = vc4_dpi_encoder_enable, .enable = vc4_dpi_encoder_enable,
.mode_fixup = vc4_dpi_encoder_mode_fixup,
}; };
static const struct of_device_id vc4_dpi_dt_match[] = { static const struct of_device_id vc4_dpi_dt_match[] = {

View File

@ -419,10 +419,6 @@ vc4_submit_next_bin_job(struct drm_device *dev)
vc4_flush_caches(dev); vc4_flush_caches(dev);
/* Disable the binner's pre-loaded overflow memory address */
V3D_WRITE(V3D_BPOA, 0);
V3D_WRITE(V3D_BPOS, 0);
/* Either put the job in the binner if it uses the binner, or /* Either put the job in the binner if it uses the binner, or
* immediately move it to the to-be-rendered queue. * immediately move it to the to-be-rendered queue.
*/ */

View File

@ -208,10 +208,35 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
return ret; return ret;
} }
/*
* drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to
* all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it
* screws up vblank timestamping for interlaced modes, so fix it up.
*/
static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector,
uint32_t maxX, uint32_t maxY)
{
struct drm_display_mode *mode;
int count;
count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
if (count == 0)
return 0;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n",
connector->base.id, connector->name);
list_for_each_entry(mode, &connector->modes, head) {
drm_mode_set_crtcinfo(mode, 0);
drm_mode_debug_printmodeline(mode);
}
return count;
}
static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.detect = vc4_hdmi_connector_detect, .detect = vc4_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = vc4_hdmi_connector_probe_modes,
.destroy = vc4_hdmi_connector_destroy, .destroy = vc4_hdmi_connector_destroy,
.reset = drm_atomic_helper_connector_reset, .reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@ -246,7 +271,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
connector->polled = (DRM_CONNECTOR_POLL_CONNECT | connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT); DRM_CONNECTOR_POLL_DISCONNECT);
connector->interlace_allowed = 0; connector->interlace_allowed = 1;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
drm_mode_connector_attach_encoder(connector, encoder); drm_mode_connector_attach_encoder(connector, encoder);