diff options
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r-- | drivers/gpu/drm/vc4/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 62 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 188 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_bo.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_dsi.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 183 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 133 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_txp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_validate.c | 11 |
13 files changed, 338 insertions, 361 deletions
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 6cc7b7e6294a..123ab0ce1781 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -14,6 +14,7 @@ config DRM_VC4 select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HDMI_STATE_HELPER select DRM_DISPLAY_HELPER + select DRM_EXEC select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c index e70d7c3076ac..577d9a956369 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c @@ -61,6 +61,19 @@ static const struct drm_display_mode default_mode = { DRM_SIMPLE_MODE(640, 480, 64, 48) }; +/** + * vc4_mock_atomic_add_output() - Enables an output in a state + * @test: The test context object + * @state: Atomic state to enable the output in. + * @type: Type of the output encoder + * + * Adds an output CRTC and connector to a state, and enables them. + * + * Returns: + * 0 on success, a negative error code on failure. If the error is + * EDEADLK, the entire atomic sequence must be restarted. All other + * errors are fatal. + */ int vc4_mock_atomic_add_output(struct kunit *test, struct drm_atomic_state *state, enum vc4_encoder_type type) @@ -75,30 +88,49 @@ int vc4_mock_atomic_add_output(struct kunit *test, int ret; encoder = vc4_find_encoder_by_type(drm, type); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + if (!encoder) + return -ENODEV; crtc = vc4_find_crtc_for_encoder(test, drm, encoder); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + if (!crtc) + return -ENODEV; output = encoder_to_vc4_dummy_output(encoder); conn = &output->connector; conn_state = drm_atomic_get_connector_state(state, conn); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); - KUNIT_EXPECT_EQ(test, ret, 0); + if (ret) + return ret; crtc_state = drm_atomic_get_crtc_state(state, crtc); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); ret = drm_atomic_set_mode_for_crtc(crtc_state, &default_mode); - KUNIT_EXPECT_EQ(test, ret, 0); + if (ret) + return ret; crtc_state->active = true; return 0; } +/** + * vc4_mock_atomic_del_output() - Disables an output in a state + * @test: The test context object + * @state: Atomic state to disable the output in. + * @type: Type of the output encoder + * + * Adds an output CRTC and connector to a state, and disables them. + * + * Returns: + * 0 on success, a negative error code on failure. If the error is + * EDEADLK, the entire atomic sequence must be restarted. All other + * errors are fatal. + */ int vc4_mock_atomic_del_output(struct kunit *test, struct drm_atomic_state *state, enum vc4_encoder_type type) @@ -113,26 +145,32 @@ int vc4_mock_atomic_del_output(struct kunit *test, int ret; encoder = vc4_find_encoder_by_type(drm, type); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + if (!encoder) + return -ENODEV; crtc = vc4_find_crtc_for_encoder(test, drm, encoder); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + if (!crtc) + return -ENODEV; crtc_state = drm_atomic_get_crtc_state(state, crtc); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); crtc_state->active = false; ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); - KUNIT_ASSERT_EQ(test, ret, 0); + if (ret) + return ret; output = encoder_to_vc4_dummy_output(encoder); conn = &output->connector; conn_state = drm_atomic_get_connector_state(state, conn); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); - KUNIT_ASSERT_EQ(test, ret, 0); + if (ret) + return ret; return 0; } diff --git a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c index 40a05869a50e..d1f694029169 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c @@ -20,7 +20,6 @@ struct pv_muxing_priv { struct vc4_dev *vc4; - struct drm_atomic_state *state; }; static bool check_fifo_conflict(struct kunit *test, @@ -677,18 +676,41 @@ static void drm_vc4_test_pv_muxing(struct kunit *test) { const struct pv_muxing_param *params = test->param_value; const struct pv_muxing_priv *priv = test->priv; - struct drm_atomic_state *state = priv->state; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_device *drm; + struct vc4_dev *vc4; unsigned int i; int ret; + drm_modeset_acquire_init(&ctx, 0); + + vc4 = priv->vc4; + drm = &vc4->base; + +retry: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); for (i = 0; i < params->nencoders; i++) { enum vc4_encoder_type enc_type = params->encoders[i]; ret = vc4_mock_atomic_add_output(test, state, enc_type); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } KUNIT_ASSERT_EQ(test, ret, 0); } ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } KUNIT_EXPECT_EQ(test, ret, 0); KUNIT_EXPECT_TRUE(test, @@ -700,33 +722,61 @@ static void drm_vc4_test_pv_muxing(struct kunit *test) KUNIT_EXPECT_TRUE(test, check_channel_for_encoder(test, state, enc_type, params->check_fn)); } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); } static void drm_vc4_test_pv_muxing_invalid(struct kunit *test) { const struct pv_muxing_param *params = test->param_value; const struct pv_muxing_priv *priv = test->priv; - struct drm_atomic_state *state = priv->state; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_device *drm; + struct vc4_dev *vc4; unsigned int i; int ret; + drm_modeset_acquire_init(&ctx, 0); + + vc4 = priv->vc4; + drm = &vc4->base; + +retry: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + for (i = 0; i < params->nencoders; i++) { enum vc4_encoder_type enc_type = params->encoders[i]; ret = vc4_mock_atomic_add_output(test, state, enc_type); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } KUNIT_ASSERT_EQ(test, ret, 0); } ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } KUNIT_EXPECT_LT(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); } static int vc4_pv_muxing_test_init(struct kunit *test) { const struct pv_muxing_param *params = test->param_value; - struct drm_modeset_acquire_ctx *ctx; struct pv_muxing_priv *priv; - struct drm_device *drm; struct vc4_dev *vc4; priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); @@ -737,13 +787,6 @@ static int vc4_pv_muxing_test_init(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); priv->vc4 = vc4; - ctx = drm_kunit_helper_acquire_ctx_alloc(test); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - - drm = &vc4->base; - priv->state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->state); - return 0; } @@ -782,7 +825,7 @@ static struct kunit_suite vc5_pv_muxing_test_suite = { */ static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test) { - struct drm_modeset_acquire_ctx *ctx; + struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; struct vc4_crtc_state *new_vc4_crtc_state; struct vc4_hvs_state *new_hvs_state; @@ -795,17 +838,29 @@ static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *tes vc4 = vc5_mock_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); - ctx = drm_kunit_helper_acquire_ctx_alloc(test); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + drm_modeset_acquire_init(&ctx, 0); drm = &vc4->base; - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_first: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); new_hvs_state = vc4_hvs_get_new_global_state(state); @@ -822,13 +877,26 @@ static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *tes ret = drm_atomic_helper_swap_state(state, false); KUNIT_ASSERT_EQ(test, ret, 0); - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_second: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); new_hvs_state = vc4_hvs_get_new_global_state(state); @@ -843,6 +911,9 @@ static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *tes KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use); KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); } /* @@ -854,7 +925,7 @@ static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *tes */ static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) { - struct drm_modeset_acquire_ctx *ctx; + struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; struct vc4_crtc_state *new_vc4_crtc_state; struct vc4_hvs_state *new_hvs_state; @@ -867,20 +938,38 @@ static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) vc4 = vc5_mock_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); - ctx = drm_kunit_helper_acquire_ctx_alloc(test); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + drm_modeset_acquire_init(&ctx, 0); drm = &vc4->base; - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_first: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); new_hvs_state = vc4_hvs_get_new_global_state(state); @@ -905,13 +994,26 @@ static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) ret = drm_atomic_helper_swap_state(state, false); KUNIT_ASSERT_EQ(test, ret, 0); - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_second: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_del_output(test, state, VC4_ENCODER_TYPE_HDMI0); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); new_hvs_state = vc4_hvs_get_new_global_state(state); @@ -929,6 +1031,9 @@ static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel); } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); } /* @@ -949,7 +1054,7 @@ static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test) { - struct drm_modeset_acquire_ctx *ctx; + struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; struct vc4_crtc_state *new_vc4_crtc_state; struct drm_device *drm; @@ -959,34 +1064,61 @@ drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct ku vc4 = vc5_mock_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); - ctx = drm_kunit_helper_acquire_ctx_alloc(test); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + drm_modeset_acquire_init(&ctx, 0); drm = &vc4->base; - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_first: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_first; + } KUNIT_ASSERT_EQ(test, ret, 0); - ret = drm_atomic_helper_swap_state(state, false); KUNIT_ASSERT_EQ(test, ret, 0); - state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); +retry_second: + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_second; + } KUNIT_ASSERT_EQ(test, ret, 0); new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, VC4_ENCODER_TYPE_HDMI0); KUNIT_EXPECT_NULL(test, new_vc4_crtc_state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); } static struct kunit_case vc5_pv_muxing_bugs_tests[] = { diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index fb450b6a4d44..7125773889f1 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -1043,7 +1043,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused) struct vc4_dev *vc4 = to_vc4_dev(dev); int i; - del_timer(&vc4->bo_cache.time_timer); + timer_delete(&vc4->bo_cache.time_timer); cancel_work_sync(&vc4->bo_cache.time_work); vc4_bo_cache_purge(dev); diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index cf40a53ad42e..2a48038abe7a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -884,11 +884,7 @@ struct vc4_async_flip_state { struct drm_framebuffer *fb; struct drm_framebuffer *old_fb; struct drm_pending_vblank_event *event; - - union { - struct dma_fence_cb fence; - struct vc4_seqno_cb seqno; - } cb; + struct dma_fence_cb cb; }; /* Called when the V3D execution for the BO being flipped to is done, so that @@ -919,10 +915,11 @@ vc4_async_page_flip_complete(struct vc4_async_flip_state *flip_state) kfree(flip_state); } -static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) +static void vc4_async_page_flip_complete_with_cleanup(struct dma_fence *fence, + struct dma_fence_cb *cb) { struct vc4_async_flip_state *flip_state = - container_of(cb, struct vc4_async_flip_state, cb.seqno); + container_of(cb, struct vc4_async_flip_state, cb); struct vc4_bo *bo = NULL; if (flip_state->old_fb) { @@ -932,6 +929,7 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) } vc4_async_page_flip_complete(flip_state); + dma_fence_put(fence); /* * Decrement the BO usecnt in order to keep the inc/dec @@ -950,7 +948,7 @@ static void vc4_async_page_flip_fence_complete(struct dma_fence *fence, struct dma_fence_cb *cb) { struct vc4_async_flip_state *flip_state = - container_of(cb, struct vc4_async_flip_state, cb.fence); + container_of(cb, struct vc4_async_flip_state, cb); vc4_async_page_flip_complete(flip_state); dma_fence_put(fence); @@ -961,16 +959,15 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, { struct drm_framebuffer *fb = flip_state->fb; struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); + dma_fence_func_t async_page_flip_complete_function; struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; - if (vc4->gen == VC4_GEN_4) { - 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); - } + if (vc4->gen == VC4_GEN_4) + async_page_flip_complete_function = vc4_async_page_flip_complete_with_cleanup; + else + async_page_flip_complete_function = vc4_async_page_flip_fence_complete; ret = dma_resv_get_singleton(dma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); if (ret) @@ -978,14 +975,14 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, /* If there's no fence, complete the page flip immediately */ if (!fence) { - vc4_async_page_flip_fence_complete(fence, &flip_state->cb.fence); + async_page_flip_complete_function(fence, &flip_state->cb); return 0; } /* If the fence has already been completed, complete the page flip */ - if (dma_fence_add_callback(fence, &flip_state->cb.fence, - vc4_async_page_flip_fence_complete)) - vc4_async_page_flip_fence_complete(fence, &flip_state->cb.fence); + if (dma_fence_add_callback(fence, &flip_state->cb, + async_page_flip_complete_function)) + async_page_flip_complete_function(fence, &flip_state->cb); return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 4a078ffd9f82..221d8e01d539 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -186,11 +186,6 @@ struct vc4_dev { */ struct vc4_perfmon *active_perfmon; - /* List of struct vc4_seqno_cb for callbacks to be made from a - * workqueue when the given seqno is passed. - */ - struct list_head seqno_cb_list; - /* The memory used for storing binner tile alloc, tile state, * and overflow memory allocations. This is freed when V3D * powers down. @@ -247,16 +242,6 @@ struct vc4_dev { struct vc4_bo { struct drm_gem_dma_object base; - /* seqno of the last job to render using this BO. */ - uint64_t seqno; - - /* seqno of the last job to use the RCL to write to this BO. - * - * Note that this doesn't include binner overflow memory - * writes. - */ - uint64_t write_seqno; - bool t_format; /* List entry for the BO's position in either @@ -304,12 +289,6 @@ struct vc4_fence { #define to_vc4_fence(_fence) \ container_of_const(_fence, struct vc4_fence, base) -struct vc4_seqno_cb { - struct work_struct work; - uint64_t seqno; - void (*func)(struct vc4_seqno_cb *cb); -}; - struct vc4_v3d { struct vc4_dev *vc4; struct platform_device *pdev; @@ -695,9 +674,6 @@ struct vc4_exec_info { /* Sequence number for this bin/render job. */ uint64_t seqno; - /* Latest write_seqno of any BO that binning depends on. */ - uint64_t bin_dep_seqno; - struct dma_fence *fence; /* Last current addresses the hardware was processing when the @@ -1025,9 +1001,6 @@ void vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec); int vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, bool interruptible); void vc4_job_handle_completed(struct vc4_dev *vc4); -int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)); int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 5eb293bdb363..458e5d987964 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -552,8 +552,6 @@ struct vc4_dsi { struct vc4_encoder encoder; struct mipi_dsi_host dsi_host; - struct kref kref; - struct platform_device *pdev; struct drm_bridge *out_bridge; @@ -800,7 +798,7 @@ dsi_esc_timing(u32 ns) } static void vc4_dsi_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); u32 disp0_ctrl; @@ -811,7 +809,7 @@ static void vc4_dsi_bridge_disable(struct drm_bridge *bridge, } static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); struct device *dev = &dsi->pdev->dev; @@ -873,9 +871,8 @@ static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge, } static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_state->base.state; struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); const struct drm_crtc_state *crtc_state; struct device *dev = &dsi->pdev->dev; @@ -1143,7 +1140,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge, } static void vc4_dsi_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); bool debug_dump_regs = false; @@ -1161,12 +1158,13 @@ static void vc4_dsi_bridge_enable(struct drm_bridge *bridge, } static int vc4_dsi_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, enum drm_bridge_attach_flags flags) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); /* Attach the panel or bridge to the dsi bridge */ - return drm_bridge_attach(bridge->encoder, dsi->out_bridge, + return drm_bridge_attach(encoder, dsi->out_bridge, &dsi->bridge, flags); } @@ -1622,29 +1620,11 @@ static void vc4_dsi_dma_chan_release(void *ptr) dsi->reg_dma_chan = NULL; } -static void vc4_dsi_release(struct kref *kref) -{ - struct vc4_dsi *dsi = - container_of(kref, struct vc4_dsi, kref); - - kfree(dsi); -} - -static void vc4_dsi_get(struct vc4_dsi *dsi) -{ - kref_get(&dsi->kref); -} - -static void vc4_dsi_put(struct vc4_dsi *dsi) -{ - kref_put(&dsi->kref, &vc4_dsi_release); -} - static void vc4_dsi_release_action(struct drm_device *drm, void *ptr) { struct vc4_dsi *dsi = ptr; - vc4_dsi_put(dsi); + drm_bridge_put(&dsi->bridge); } static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) @@ -1655,7 +1635,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) struct drm_encoder *encoder = &dsi->encoder.base; int ret; - vc4_dsi_get(dsi); + drm_bridge_get(&dsi->bridge); ret = drmm_add_action_or_reset(drm, vc4_dsi_release_action, dsi); if (ret) @@ -1810,15 +1790,12 @@ static int vc4_dsi_dev_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct vc4_dsi *dsi; - dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(&pdev->dev, struct vc4_dsi, bridge, &vc4_dsi_bridge_funcs); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); dev_set_drvdata(dev, dsi); - kref_init(&dsi->kref); - dsi->pdev = pdev; - dsi->bridge.funcs = &vc4_dsi_bridge_funcs; #ifdef CONFIG_OF dsi->bridge.of_node = dev->of_node; #endif @@ -1836,7 +1813,6 @@ static void vc4_dsi_dev_remove(struct platform_device *pdev) struct vc4_dsi *dsi = dev_get_drvdata(dev); mipi_dsi_host_unregister(&dsi->dsi_host); - vc4_dsi_put(dsi); } struct platform_driver vc4_dsi_driver = { diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 22bccd69eb62..8125f87edc60 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -29,6 +29,7 @@ #include <linux/sched/signal.h> #include <linux/dma-fence-array.h> +#include <drm/drm_exec.h> #include <drm/drm_syncobj.h> #include "uapi/drm/vc4_drm.h" @@ -552,45 +553,24 @@ vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec) } static void -vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) +vc4_attach_fences(struct vc4_exec_info *exec) { struct vc4_bo *bo; unsigned i; for (i = 0; i < exec->bo_count; i++) { bo = to_vc4_bo(exec->bo[i]); - bo->seqno = seqno; - dma_resv_add_fence(bo->base.base.resv, exec->fence, DMA_RESV_USAGE_READ); } - list_for_each_entry(bo, &exec->unref_list, unref_head) { - bo->seqno = seqno; - } - for (i = 0; i < exec->rcl_write_bo_count; i++) { bo = to_vc4_bo(&exec->rcl_write_bo[i]->base); - bo->write_seqno = seqno; - dma_resv_add_fence(bo->base.base.resv, exec->fence, DMA_RESV_USAGE_WRITE); } } -static void -vc4_unlock_bo_reservations(struct drm_device *dev, - struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx) -{ - int i; - - for (i = 0; i < exec->bo_count; i++) - dma_resv_unlock(exec->bo[i]->resv); - - ww_acquire_fini(acquire_ctx); -} - /* Takes the reservation lock on all the BOs being referenced, so that * at queue submit time we can update the reservations. * @@ -599,70 +579,23 @@ vc4_unlock_bo_reservations(struct drm_device *dev, * to vc4, so we don't attach dma-buf fences to them. */ static int -vc4_lock_bo_reservations(struct drm_device *dev, - struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx) +vc4_lock_bo_reservations(struct vc4_exec_info *exec, + struct drm_exec *exec_ctx) { - int contended_lock = -1; - int i, ret; - struct drm_gem_object *bo; - - ww_acquire_init(acquire_ctx, &reservation_ww_class); - -retry: - if (contended_lock != -1) { - bo = exec->bo[contended_lock]; - ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); - if (ret) { - ww_acquire_done(acquire_ctx); - return ret; - } - } - - for (i = 0; i < exec->bo_count; i++) { - if (i == contended_lock) - continue; - - bo = exec->bo[i]; - - ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); - if (ret) { - int j; - - for (j = 0; j < i; j++) { - bo = exec->bo[j]; - dma_resv_unlock(bo->resv); - } - - if (contended_lock != -1 && contended_lock >= i) { - bo = exec->bo[contended_lock]; - - dma_resv_unlock(bo->resv); - } - - if (ret == -EDEADLK) { - contended_lock = i; - goto retry; - } - - ww_acquire_done(acquire_ctx); - return ret; - } - } - - ww_acquire_done(acquire_ctx); + int ret; /* Reserve space for our shared (read-only) fence references, * before we commit the CL to the hardware. */ - for (i = 0; i < exec->bo_count; i++) { - bo = exec->bo[i]; + drm_exec_init(exec_ctx, DRM_EXEC_INTERRUPTIBLE_WAIT, exec->bo_count); + drm_exec_until_all_locked(exec_ctx) { + ret = drm_exec_prepare_array(exec_ctx, exec->bo, + exec->bo_count, 1); + } - ret = dma_resv_reserve_fences(bo->resv, 1); - if (ret) { - vc4_unlock_bo_reservations(dev, exec, acquire_ctx); - return ret; - } + if (ret) { + drm_exec_fini(exec_ctx); + return ret; } return 0; @@ -679,7 +612,7 @@ retry: */ static int vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx, + struct drm_exec *exec_ctx, struct drm_syncobj *out_sync) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -706,9 +639,9 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, if (out_sync) drm_syncobj_replace_fence(out_sync, exec->fence); - vc4_update_bo_seqnos(exec, seqno); + vc4_attach_fences(exec); - vc4_unlock_bo_reservations(dev, exec, acquire_ctx); + drm_exec_fini(exec_ctx); list_add_tail(&exec->head, &vc4->bin_job_list); @@ -904,12 +837,6 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) goto fail; } - /* Block waiting on any previous rendering into the CS's VBO, - * IB, or textures, so that pixels are actually written by the - * time we try to read them. - */ - ret = vc4_wait_for_seqno(dev, exec->bin_dep_seqno, ~0ull, true); - fail: kvfree(temp); return ret; @@ -968,7 +895,6 @@ void vc4_job_handle_completed(struct vc4_dev *vc4) { unsigned long irqflags; - struct vc4_seqno_cb *cb, *cb_temp; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return; @@ -985,46 +911,7 @@ vc4_job_handle_completed(struct vc4_dev *vc4) spin_lock_irqsave(&vc4->job_lock, irqflags); } - list_for_each_entry_safe(cb, cb_temp, &vc4->seqno_cb_list, work.entry) { - if (cb->seqno <= vc4->finished_seqno) { - list_del_init(&cb->work.entry); - schedule_work(&cb->work); - } - } - - spin_unlock_irqrestore(&vc4->job_lock, irqflags); -} - -static void vc4_seqno_cb_work(struct work_struct *work) -{ - struct vc4_seqno_cb *cb = container_of(work, struct vc4_seqno_cb, work); - - cb->func(cb); -} - -int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)) -{ - struct vc4_dev *vc4 = to_vc4_dev(dev); - unsigned long irqflags; - - if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) - return -ENODEV; - - cb->func = func; - INIT_WORK(&cb->work, vc4_seqno_cb_work); - - spin_lock_irqsave(&vc4->job_lock, irqflags); - if (seqno > vc4->finished_seqno) { - cb->seqno = seqno; - list_add_tail(&cb->work.entry, &vc4->seqno_cb_list); - } else { - schedule_work(&cb->work); - } spin_unlock_irqrestore(&vc4->job_lock, irqflags); - - return 0; } /* Scheduled when any job has been completed, this walks the list of @@ -1079,8 +966,10 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, struct vc4_dev *vc4 = to_vc4_dev(dev); int ret; struct drm_vc4_wait_bo *args = data; - struct drm_gem_object *gem_obj; - struct vc4_bo *bo; + unsigned long timeout_jiffies = + usecs_to_jiffies(div_u64(args->timeout_ns, 1000)); + ktime_t start = ktime_get(); + u64 delta_ns; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return -ENODEV; @@ -1088,17 +977,18 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, if (args->pad != 0) return -EINVAL; - gem_obj = drm_gem_object_lookup(file_priv, args->handle); - if (!gem_obj) { - DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle); - return -EINVAL; - } - bo = to_vc4_bo(gem_obj); + ret = drm_gem_dma_resv_wait(file_priv, args->handle, + true, timeout_jiffies); - ret = vc4_wait_for_seqno_ioctl_helper(dev, bo->seqno, - &args->timeout_ns); + /* Decrement the user's timeout, in case we got interrupted + * such that the ioctl will be restarted. + */ + delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start)); + if (delta_ns < args->timeout_ns) + args->timeout_ns -= delta_ns; + else + args->timeout_ns = 0; - drm_gem_object_put(gem_obj); return ret; } @@ -1123,7 +1013,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct drm_vc4_submit_cl *args = data; struct drm_syncobj *out_sync = NULL; struct vc4_exec_info *exec; - struct ww_acquire_ctx acquire_ctx; + struct drm_exec exec_ctx; struct dma_fence *in_fence; int ret = 0; @@ -1216,7 +1106,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, if (ret) goto fail; - ret = vc4_lock_bo_reservations(dev, exec, &acquire_ctx); + ret = vc4_lock_bo_reservations(exec, &exec_ctx); if (ret) goto fail; @@ -1224,7 +1114,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, out_sync = drm_syncobj_find(file_priv, args->out_sync); if (!out_sync) { ret = -EINVAL; - goto fail; + goto fail_unreserve; } /* We replace the fence in out_sync in vc4_queue_submit since @@ -1239,7 +1129,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, */ exec->args = NULL; - ret = vc4_queue_submit(dev, exec, &acquire_ctx, out_sync); + ret = vc4_queue_submit(dev, exec, &exec_ctx, out_sync); /* The syncobj isn't part of the exec data and we need to free our * reference even if job submission failed. @@ -1248,13 +1138,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, drm_syncobj_put(out_sync); if (ret) - goto fail; + goto fail_unreserve; /* Return the seqno for our job. */ args->seqno = vc4->emit_seqno; return 0; +fail_unreserve: + drm_exec_fini(&exec_ctx); fail: vc4_complete_exec(&vc4->base, exec); @@ -1275,7 +1167,6 @@ int vc4_gem_init(struct drm_device *dev) INIT_LIST_HEAD(&vc4->bin_job_list); INIT_LIST_HEAD(&vc4->render_job_list); INIT_LIST_HEAD(&vc4->job_done_list); - INIT_LIST_HEAD(&vc4->seqno_cb_list); spin_lock_init(&vc4->job_lock); INIT_WORK(&vc4->hangcheck.reset_work, vc4_reset_work); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 47d9ada98430..a29a6ef266f9 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -51,6 +51,7 @@ #include <linux/reset.h> #include <sound/dmaengine_pcm.h> #include <sound/hdmi-codec.h> +#include <sound/jack.h> #include <sound/pcm_drm_eld.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -270,34 +271,6 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} #endif -static int reset_pipe(struct drm_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_atomic_state *state; - struct drm_crtc_state *crtc_state; - int ret; - - state = drm_atomic_state_alloc(crtc->dev); - if (!state) - return -ENOMEM; - - state->acquire_ctx = ctx; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - goto out; - } - - crtc_state->connectors_changed = true; - - ret = drm_atomic_commit(state); -out: - drm_atomic_state_put(state); - - return ret; -} - static int vc4_hdmi_reset_link(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx) { @@ -376,7 +349,7 @@ static int vc4_hdmi_reset_link(struct drm_connector *connector, * would be perfectly happy if were to just reconfigure * the SCDC settings on the fly. */ - return reset_pipe(crtc, ctx); + return drm_atomic_helper_reset_crtc(crtc, ctx); } static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, @@ -400,13 +373,13 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, * the lock for now. */ + drm_atomic_helper_connector_hdmi_hotplug(connector, status); + if (status == connector_status_disconnected) { cec_phys_addr_invalidate(vc4_hdmi->cec_adap); return; } - drm_atomic_helper_connector_hdmi_hotplug(connector, status); - cec_s_phys_addr(vc4_hdmi->cec_adap, connector->display_info.source_physical_address, false); @@ -2203,6 +2176,22 @@ static const struct drm_connector_hdmi_audio_funcs vc4_hdmi_audio_funcs = { .shutdown = vc4_hdmi_audio_shutdown, }; +static int vc4_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct vc4_hdmi *vc4_hdmi = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &vc4_hdmi->hdmi_jack); + if (ret) { + dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); + return ret; + } + + return snd_soc_component_set_jack(component, &vc4_hdmi->hdmi_jack, NULL); +} + static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) { const struct vc4_hdmi_register *mai_data = @@ -2316,6 +2305,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = dev_name(&vc4_hdmi->connector.hdmi_audio.codec_pdev->dev); dai_link->platforms->name = dev_name(dev); + dai_link->init = vc4_hdmi_codec_init; card->dai_link = dai_link; card->num_links = 1; @@ -2954,15 +2944,16 @@ static int vc5_hdmi_init_resources(struct drm_device *drm, struct resource *res; int ret; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); - if (!res) - return -ENODEV; - - vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, - resource_size(res)); - if (!vc4_hdmi->hdmicore_regs) - return -ENOMEM; + vc4_hdmi->hdmicore_regs = devm_platform_ioremap_resource_byname(pdev, + "hdmi"); + if (IS_ERR(vc4_hdmi->hdmicore_regs)) + return PTR_ERR(vc4_hdmi->hdmicore_regs); + /* This is shared between both HDMI controllers. Cannot + * claim for both instances. Lets not convert to using + * devm_platform_ioremap_resource_byname() like + * the rest + */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd"); if (!res) return -ENODEV; @@ -2971,53 +2962,35 @@ static int vc5_hdmi_init_resources(struct drm_device *drm, if (!vc4_hdmi->hd_regs) return -ENOMEM; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec"); - if (!res) - return -ENODEV; + vc4_hdmi->cec_regs = devm_platform_ioremap_resource_byname(pdev, + "cec"); + if (IS_ERR(vc4_hdmi->cec_regs)) + return PTR_ERR(vc4_hdmi->cec_regs); - vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->cec_regs) - return -ENOMEM; + vc4_hdmi->csc_regs = devm_platform_ioremap_resource_byname(pdev, + "csc"); + if (IS_ERR(vc4_hdmi->csc_regs)) + return PTR_ERR(vc4_hdmi->csc_regs); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc"); - if (!res) - return -ENODEV; + vc4_hdmi->dvp_regs = devm_platform_ioremap_resource_byname(pdev, + "dvp"); + if (IS_ERR(vc4_hdmi->dvp_regs)) + return PTR_ERR(vc4_hdmi->dvp_regs); - vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->csc_regs) - return -ENOMEM; + vc4_hdmi->phy_regs = devm_platform_ioremap_resource_byname(pdev, + "phy"); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp"); - if (!res) - return -ENODEV; + if (IS_ERR(vc4_hdmi->phy_regs)) + return PTR_ERR(vc4_hdmi->phy_regs); - vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->dvp_regs) - return -ENOMEM; + vc4_hdmi->ram_regs = devm_platform_ioremap_resource_byname(pdev, + "packet"); + if (IS_ERR(vc4_hdmi->ram_regs)) + return PTR_ERR(vc4_hdmi->ram_regs); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); - if (!res) - return -ENODEV; - - vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->phy_regs) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet"); - if (!res) - return -ENODEV; - - vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->ram_regs) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm"); - if (!res) - return -ENODEV; - - vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->rm_regs) - return -ENOMEM; + vc4_hdmi->rm_regs = devm_platform_ioremap_resource_byname(pdev, "rm"); + if (IS_ERR(vc4_hdmi->rm_regs)) + return PTR_ERR(vc4_hdmi->rm_regs); vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); if (IS_ERR(vc4_hdmi->hsm_clock)) { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index e3d989ca302b..a31157c99bee 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -4,6 +4,7 @@ #include <drm/drm_connector.h> #include <media/cec.h> #include <sound/dmaengine_pcm.h> +#include <sound/hdmi-codec.h> #include <sound/soc.h> #include "vc4_drv.h" @@ -211,6 +212,12 @@ struct vc4_hdmi { * KMS hooks. Protected by @mutex. */ enum hdmi_colorspace output_format; + + /** + * @hdmi_jack: Represents the connection state of the HDMI plug, for + * ALSA jack detection. + */ + struct snd_soc_jack hdmi_jack; }; #define connector_to_vc4_hdmi(_connector) \ diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index d608860d525f..056d344c5411 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -2080,7 +2080,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane, /* HPPF plane 1 */ vc4_dlist_write(vc4_state, kernel); /* VPPF plane 1 */ - vc4_dlist_write(vc4_state, kernel); + vc4_dlist_write(vc4_state, kernel); } } @@ -2338,7 +2338,7 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, } static int vc4_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct vc4_dev *vc4 = to_vc4_dev(plane->dev); struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 4eab069cda75..42acac05fe47 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -196,7 +196,7 @@ static int vc4_txp_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status vc4_txp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_mode_config *mode_config = &dev->mode_config; diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 5bf134968ade..1e7bdda55698 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -284,9 +284,6 @@ validate_indexed_prim_list(VALIDATE_ARGS) if (!ib) return -EINVAL; - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&ib->base)->write_seqno); - if (offset > ib->base.size || (ib->base.size - offset) / index_size < length) { DRM_DEBUG("IB access overflow (%d + %d*%d > %zd)\n", @@ -738,11 +735,6 @@ reloc_tex(struct vc4_exec_info *exec, *validated_p0 = tex->dma_addr + p0; - if (is_cs) { - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&tex->base)->write_seqno); - } - return true; fail: DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0); @@ -904,9 +896,6 @@ validate_gl_shader_rec(struct drm_device *dev, uint32_t stride = *(uint8_t *)(pkt_u + o + 5); uint32_t max_index; - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&vbo->base)->write_seqno); - if (state->addr & 0x8) stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff; |