diff options
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_dpi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_dsi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 2 |
7 files changed, 54 insertions, 37 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index b00e20f5ce05..1208258ad3b2 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -84,13 +84,14 @@ static const struct debugfs_reg32 crtc_regs[] = { VC4_REG32(PV_HACT_ACT), }; -bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - bool in_vblank_irq, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) +static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, + bool in_vblank_irq, + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { + struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); u32 val; int fifo_lines; @@ -1030,6 +1031,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { .gamma_set = drm_atomic_helper_legacy_gamma_set, .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, + .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, }; static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { @@ -1039,6 +1041,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .atomic_flush = vc4_crtc_atomic_flush, .atomic_enable = vc4_crtc_atomic_enable, .atomic_disable = vc4_crtc_atomic_disable, + .get_scanout_position = vc4_crtc_get_scanout_position, }; static const struct vc4_crtc_data pv0_data = { diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index c586325de2a5..6dfede03396e 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -252,7 +252,7 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) bridge = drm_panel_bridge_add_typed(panel, DRM_MODE_CONNECTOR_DPI); - return drm_bridge_attach(dpi->encoder, bridge, NULL); + return drm_bridge_attach(dpi->encoder, bridge, NULL, 0); } static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 5e6fb6c2307f..76f93b662766 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -190,9 +190,6 @@ static struct drm_driver vc4_drm_driver = { .irq_postinstall = vc4_irq_postinstall, .irq_uninstall = vc4_irq_uninstall, - .get_scanout_position = vc4_crtc_get_scanoutpos, - .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos, - #if defined(CONFIG_DEBUG_FS) .debugfs_init = vc4_debugfs_init, #endif diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 6627b20c99e9..139d25a8328e 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -65,7 +65,7 @@ struct vc4_perfmon { * Note that counter values can't be reset, but you can fake a reset by * destroying the perfmon and creating a new one. */ - u64 counters[0]; + u64 counters[]; }; struct vc4_dev { @@ -677,32 +677,41 @@ struct vc4_validated_shader_info { }; /** - * _wait_for - magic (register) wait macro + * __wait_for - magic wait macro * - * Does the right thing for modeset paths when run under kdgb or similar atomic - * contexts. Note that it's important that we check the condition again after - * having timed out, since the timeout could be due to preemption or similar and - * we've never had a chance to check the condition before the timeout. + * Macro to help avoid open coding check/wait/timeout patterns. Note that it's + * important that we check the condition again after having timed out, since the + * timeout could be due to preemption or similar and we've never had a chance to + * check the condition before the timeout. */ -#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \ - int ret__ = 0; \ - while (!(COND)) { \ - if (time_after(jiffies, timeout__)) { \ - if (!(COND)) \ - ret__ = -ETIMEDOUT; \ +#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ + const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \ + long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ + int ret__; \ + might_sleep(); \ + for (;;) { \ + const bool expired__ = ktime_after(ktime_get_raw(), end__); \ + OP; \ + /* Guarantee COND check prior to timeout */ \ + barrier(); \ + if (COND) { \ + ret__ = 0; \ break; \ } \ - if (W && drm_can_sleep()) { \ - msleep(W); \ - } else { \ - cpu_relax(); \ + if (expired__) { \ + ret__ = -ETIMEDOUT; \ + break; \ } \ + usleep_range(wait__, wait__ * 2); \ + if (wait__ < (Wmax)) \ + wait__ <<= 1; \ } \ ret__; \ }) -#define wait_for(COND, MS) _wait_for(COND, MS, 1) +#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \ + (Wmax)) +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) /* vc4_bo.c */ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size); @@ -743,10 +752,6 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; -bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - bool in_vblank_irq, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_txp_armed(struct drm_crtc_state *state); void vc4_crtc_get_margins(struct drm_crtc_state *state, diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index fd8a2eb60505..d99b1d526651 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1619,7 +1619,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) DRM_MODE_ENCODER_DSI, NULL); drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); - ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); + ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); if (ret) { dev_err(dev, "bridge attach failed: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index cea18dc15f77..340719238753 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -681,11 +681,23 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc, const struct drm_display_mode *mode) { - /* HSM clock must be 108% of the pixel clock. Additionally, - * the AXI clock needs to be at least 25% of pixel clock, but - * HSM ends up being the limiting factor. + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * pixel clock, but HSM ends up being the limiting factor. */ - if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100)) + if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100)) return MODE_CLOCK_HIGH; return MODE_OK; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 4934127f0d76..91e408f7a56e 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -139,7 +139,7 @@ static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst) static bool plane_enabled(struct drm_plane_state *state) { - return state->fb && state->crtc; + return state->fb && !WARN_ON(!state->crtc); } static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) |