diff options
author | Dave Airlie <airlied@redhat.com> | 2020-07-20 17:29:49 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-07-20 17:30:23 +1000 |
commit | 3ffff3c6855bda1b39eae88f3730d2baddce3bfd (patch) | |
tree | e3cb9de81d26cae157dd9d39118529d2753755c7 /drivers/gpu/drm/vc4/vc4_txp.c | |
parent | 1cc4af412f40bfe33f4b7e2b014a8d4b140bd8d3 (diff) | |
parent | 947fcfeac3295ff0961bb50803e0c4ae63cff65b (diff) |
Merge tag 'drm-misc-next-2020-07-16' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.9:
UAPI Changes:
Cross-subsystem Changes:
- Add ckoenig as dma-buf maintainer.
- Revert invalid fix for dma-fence-chain, and fix selftest.
- Add fixmes to amifb about APUS support.
- Use array3_size in fbcon_prepare_logo, and struct_size() in alloc_apertures.
- Fix leaks in neofb, fb/savage and omapfb.
- Other small fixes to fb code.
- Convert some dt bindings to schema for some panels, and fix simple-framebuffer dt example.
Core Changes:
- Add DRM_FORMAT_MOD_GENERIC_16_16_TILE as alias to DRM_FORMAT_MOD_SAMSUNG_16_16_TILE,
as it can be used more generic.
- Add support for multiple DispID extension blocks in edid.
- Use https instead of http for some of the urls.
- Use drm_* macros for logging in mipi-dsi and fb-helper.
- Further cleanup ttm_mem_reg handling.
- Remove duplicated words in comments.
Driver Changes:
- Use __drm_atomic_helper_crtc_reset in all atomic drivers.
- Add Amlogic Video FBC support to meson and fourcc to core.
- Refactor hisilicon's hibmc_drv_vdac.
- Create a TXP CRTC for vc4.
- Rework cursor support in ast.
- Fix runtime PM in STM.
- Allow bigger cursors in vkms.
- Cleanup sg handling in radeon and amdgpu, and stop creating dummy
gtt nodes with ttm fixed.
- Rework crtc handling in mgag200.
- Miscellaneous small fixes to meson, vgem, bridge/dw-hdmi,
panel/auo,b116xw03, panel/LG LB070WV8, lima, bridge/sil_sii8620,
virtio, tilcdc.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/8b360d65-f228-9286-d247-3004156a5254@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_txp.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_txp.c | 109 |
1 files changed, 107 insertions, 2 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index bf720206727f..a7c3af0005a0 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -19,6 +19,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include <drm/drm_writeback.h> #include "vc4_drv.h" @@ -145,6 +146,8 @@ #define TXP_WRITE(offset, val) writel(val, txp->regs + (offset)) struct vc4_txp { + struct vc4_crtc base; + struct platform_device *pdev; struct drm_writeback_connector connector; @@ -222,6 +225,13 @@ static const u32 txp_fmts[] = { TXP_FORMAT_BGRA8888, }; +static void vc4_txp_armed(struct drm_crtc_state *state) +{ + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + + vc4_state->txp_armed = true; +} + static int vc4_txp_connector_atomic_check(struct drm_connector *conn, struct drm_atomic_state *state) { @@ -256,7 +266,7 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn, if (fb->pitches[0] & GENMASK(3, 0)) return -EINVAL; - vc4_crtc_txp_armed(crtc_state); + vc4_txp_armed(crtc_state); return 0; } @@ -355,23 +365,105 @@ static const struct drm_encoder_helper_funcs vc4_txp_encoder_helper_funcs = { .disable = vc4_txp_encoder_disable, }; +static int vc4_txp_enable_vblank(struct drm_crtc *crtc) +{ + return 0; +} + +static void vc4_txp_disable_vblank(struct drm_crtc *crtc) {} + +static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .destroy = vc4_crtc_destroy, + .page_flip = vc4_page_flip, + .reset = vc4_crtc_reset, + .atomic_duplicate_state = vc4_crtc_duplicate_state, + .atomic_destroy_state = vc4_crtc_destroy_state, + .gamma_set = drm_atomic_helper_legacy_gamma_set, + .enable_vblank = vc4_txp_enable_vblank, + .disable_vblank = vc4_txp_disable_vblank, +}; + +static int vc4_txp_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + int ret; + + ret = vc4_hvs_atomic_check(crtc, state); + if (ret) + return ret; + + state->no_vblank = true; + vc4_state->feed_txp = true; + + return 0; +} + +static void vc4_txp_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + drm_crtc_vblank_on(crtc); + vc4_hvs_atomic_enable(crtc, old_state); +} + +static void vc4_txp_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct drm_device *dev = crtc->dev; + + /* Disable vblank irq handling before crtc is disabled. */ + drm_crtc_vblank_off(crtc); + + vc4_hvs_atomic_disable(crtc, old_state); + + /* + * Make sure we issue a vblank event after disabling the CRTC if + * someone was waiting it. + */ + if (crtc->state->event) { + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + } +} + +static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = { + .atomic_check = vc4_txp_atomic_check, + .atomic_flush = vc4_hvs_atomic_flush, + .atomic_enable = vc4_txp_atomic_enable, + .atomic_disable = vc4_txp_atomic_disable, + .mode_set_nofb = vc4_hvs_mode_set_nofb, +}; + static irqreturn_t vc4_txp_interrupt(int irq, void *data) { struct vc4_txp *txp = data; + struct vc4_crtc *vc4_crtc = &txp->base; TXP_WRITE(TXP_DST_CTRL, TXP_READ(TXP_DST_CTRL) & ~TXP_EI); - vc4_crtc_handle_vblank(to_vc4_crtc(txp->connector.base.state->crtc)); + vc4_crtc_handle_vblank(vc4_crtc); drm_writeback_signal_completion(&txp->connector, 0); return IRQ_HANDLED; } +static const struct vc4_crtc_data vc4_txp_crtc_data = { + .hvs_channel = 2, +}; + static int vc4_txp_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_crtc *vc4_crtc; struct vc4_txp *txp; + struct drm_crtc *crtc; + struct drm_encoder *encoder; int ret, irq; irq = platform_get_irq(pdev, 0); @@ -381,6 +473,11 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) txp = devm_kzalloc(dev, sizeof(*txp), GFP_KERNEL); if (!txp) return -ENOMEM; + vc4_crtc = &txp->base; + crtc = &vc4_crtc->base; + + vc4_crtc->pdev = pdev; + vc4_crtc->data = &vc4_txp_crtc_data; txp->pdev = pdev; @@ -400,6 +497,14 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; + ret = vc4_crtc_init(drm, vc4_crtc, + &vc4_txp_crtc_funcs, &vc4_txp_crtc_helper_funcs); + if (ret) + return ret; + + encoder = &txp->connector.encoder; + encoder->possible_crtcs |= drm_crtc_mask(crtc); + ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0, dev_name(dev), txp); if (ret) |