diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_crtc.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 108 |
1 files changed, 57 insertions, 51 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 029be98660b3..2def6e2ad6f0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -37,7 +37,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -206,11 +206,6 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, return ret; } -void vc4_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); -} - static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) { const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); @@ -544,6 +539,20 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) return 0; } +void vc4_crtc_send_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + unsigned long flags; + + if (!crtc->state || !crtc->state->event) + return; + + 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 void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -567,14 +576,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, * 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); - } + vc4_crtc_send_vblank(crtc); } static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, @@ -821,9 +823,9 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) struct vc4_bo *bo = NULL; if (flip_state->old_fb) { - struct drm_gem_cma_object *cma_bo = - drm_fb_cma_get_gem_obj(flip_state->old_fb, 0); - bo = to_vc4_bo(&cma_bo->base); + struct drm_gem_dma_object *dma_bo = + drm_fb_dma_get_gem_obj(flip_state->old_fb, 0); + bo = to_vc4_bo(&dma_bo->base); } vc4_async_page_flip_complete(flip_state); @@ -855,19 +857,19 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, struct vc4_async_flip_state *flip_state) { struct drm_framebuffer *fb = flip_state->fb; - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; if (!vc4->is_vc5) { - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno, vc4_async_page_flip_seqno_complete); } - ret = dma_resv_get_singleton(cma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); + ret = dma_resv_get_singleton(dma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); if (ret) return ret; @@ -943,8 +945,8 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); + struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); int ret; if (WARN_ON_ONCE(vc4->is_vc5)) @@ -1050,9 +1052,23 @@ void vc4_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base); } +int vc4_crtc_late_register(struct drm_crtc *crtc) +{ + struct drm_device *drm = crtc->dev; + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); + int ret; + + ret = vc4_debugfs_add_regset32(drm->primary, crtc_data->debugfs_name, + &vc4_crtc->regset); + if (ret) + return ret; + + return 0; +} + static const struct drm_crtc_funcs vc4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = vc4_crtc_destroy, .page_flip = vc4_page_flip, .set_property = NULL, .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ @@ -1063,6 +1079,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, + .late_register = vc4_crtc_late_register, }; static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { @@ -1077,10 +1094,10 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { static const struct vc4_pv_data bcm2835_pv0_data = { .base = { + .debugfs_name = "crtc0_regs", .hvs_available_channels = BIT(0), .hvs_output = 0, }, - .debugfs_name = "crtc0_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1091,10 +1108,10 @@ static const struct vc4_pv_data bcm2835_pv0_data = { static const struct vc4_pv_data bcm2835_pv1_data = { .base = { + .debugfs_name = "crtc1_regs", .hvs_available_channels = BIT(2), .hvs_output = 2, }, - .debugfs_name = "crtc1_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1105,10 +1122,10 @@ static const struct vc4_pv_data bcm2835_pv1_data = { static const struct vc4_pv_data bcm2835_pv2_data = { .base = { + .debugfs_name = "crtc2_regs", .hvs_available_channels = BIT(1), .hvs_output = 1, }, - .debugfs_name = "crtc2_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1119,10 +1136,10 @@ static const struct vc4_pv_data bcm2835_pv2_data = { static const struct vc4_pv_data bcm2711_pv0_data = { .base = { + .debugfs_name = "crtc0_regs", .hvs_available_channels = BIT(0), .hvs_output = 0, }, - .debugfs_name = "crtc0_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1133,10 +1150,10 @@ static const struct vc4_pv_data bcm2711_pv0_data = { static const struct vc4_pv_data bcm2711_pv1_data = { .base = { + .debugfs_name = "crtc1_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 3, }, - .debugfs_name = "crtc1_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1147,10 +1164,10 @@ static const struct vc4_pv_data bcm2711_pv1_data = { static const struct vc4_pv_data bcm2711_pv2_data = { .base = { + .debugfs_name = "crtc2_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 4, }, - .debugfs_name = "crtc2_regs", .fifo_depth = 256, .pixels_per_clock = 2, .encoder_types = { @@ -1160,10 +1177,10 @@ static const struct vc4_pv_data bcm2711_pv2_data = { static const struct vc4_pv_data bcm2711_pv3_data = { .base = { + .debugfs_name = "crtc3_regs", .hvs_available_channels = BIT(1), .hvs_output = 1, }, - .debugfs_name = "crtc3_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1173,10 +1190,10 @@ static const struct vc4_pv_data bcm2711_pv3_data = { static const struct vc4_pv_data bcm2711_pv4_data = { .base = { + .debugfs_name = "crtc4_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 5, }, - .debugfs_name = "crtc4_regs", .fifo_depth = 64, .pixels_per_clock = 2, .encoder_types = { @@ -1230,6 +1247,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, struct drm_crtc *crtc = &vc4_crtc->base; struct drm_plane *primary_plane; unsigned int i; + int ret; /* For now, we create just the primary and the legacy cursor * planes. We should be able to stack more planes on easily, @@ -1237,15 +1255,18 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, * requirement of the plane configuration, and reject ones * that will take too much. */ - primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); + primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0); if (IS_ERR(primary_plane)) { dev_err(drm->dev, "failed to construct primary plane\n"); return PTR_ERR(primary_plane); } spin_lock_init(&vc4_crtc->irq_lock); - drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, - crtc_funcs, NULL); + ret = drmm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, + crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, crtc_helper_funcs); if (!vc4->is_vc5) { @@ -1275,10 +1296,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) const struct vc4_pv_data *pv_data; struct vc4_crtc *vc4_crtc; struct drm_crtc *crtc; - struct drm_plane *destroy_plane, *temp; int ret; - vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); + vc4_crtc = drmm_kzalloc(drm, sizeof(*vc4_crtc), GFP_KERNEL); if (!vc4_crtc) return -ENOMEM; crtc = &vc4_crtc->base; @@ -1310,23 +1330,11 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) IRQF_SHARED, "vc4 crtc", vc4_crtc); if (ret) - goto err_destroy_planes; + return ret; platform_set_drvdata(pdev, vc4_crtc); - vc4_debugfs_add_regset32(drm, pv_data->debugfs_name, - &vc4_crtc->regset); - return 0; - -err_destroy_planes: - list_for_each_entry_safe(destroy_plane, temp, - &drm->mode_config.plane_list, head) { - if (destroy_plane->possible_crtcs == drm_crtc_mask(crtc)) - destroy_plane->funcs->destroy(destroy_plane); - } - - return ret; } static void vc4_crtc_unbind(struct device *dev, struct device *master, @@ -1335,8 +1343,6 @@ static void vc4_crtc_unbind(struct device *dev, struct device *master, struct platform_device *pdev = to_platform_device(dev); struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev); - vc4_crtc_destroy(&vc4_crtc->base); - CRTC_WRITE(PV_INTEN, 0); platform_set_drvdata(pdev, NULL); |