diff options
Diffstat (limited to 'drivers/gpu/drm/vc4')
25 files changed, 744 insertions, 672 deletions
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 6cc7b7e6294a..bb8c40be3250 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 @@ -34,6 +35,7 @@ config DRM_VC4_HDMI_CEC bool "Broadcom VC4 HDMI CEC Support" depends on DRM_VC4 select CEC_CORE + select DRM_DISPLAY_HDMI_CEC_HELPER help Choose this option if you have a Broadcom VC4 GPU and want to use CEC. diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h index 002b6218960c..3cc4b4a0feed 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock.h +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h @@ -52,10 +52,10 @@ struct vc4_dev *vc4_mock_device(struct kunit *test); struct vc4_dev *vc5_mock_device(struct kunit *test); int vc4_mock_atomic_add_output(struct kunit *test, - struct drm_atomic_state *state, + struct drm_atomic_commit *state, enum vc4_encoder_type type); int vc4_mock_atomic_del_output(struct kunit *test, - struct drm_atomic_state *state, + struct drm_atomic_commit *state, enum vc4_encoder_type type); #endif // VC4_MOCK_H_ diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c index e70d7c3076ac..b53c3635ce67 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c @@ -61,8 +61,21 @@ 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, + struct drm_atomic_commit *state, enum vc4_encoder_type type) { struct drm_device *drm = state->dev; @@ -75,32 +88,51 @@ 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, + struct drm_atomic_commit *state, enum vc4_encoder_type type) { struct drm_device *drm = state->dev; @@ -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..7a54f46acff9 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c @@ -20,11 +20,10 @@ struct pv_muxing_priv { struct vc4_dev *vc4; - struct drm_atomic_state *state; }; static bool check_fifo_conflict(struct kunit *test, - const struct drm_atomic_state *state) + const struct drm_atomic_commit *state) { struct vc4_hvs_state *hvs_state; unsigned int used_fifos = 0; @@ -120,7 +119,7 @@ static bool check_vc5_encoder_constraints(enum vc4_encoder_type type, unsigned i static struct vc4_crtc_state * get_vc4_crtc_state_for_encoder(struct kunit *test, - const struct drm_atomic_state *state, + const struct drm_atomic_commit *state, enum vc4_encoder_type type) { struct drm_device *drm = state->dev; @@ -142,7 +141,7 @@ get_vc4_crtc_state_for_encoder(struct kunit *test, } static bool check_channel_for_encoder(struct kunit *test, - const struct drm_atomic_state *state, + const struct drm_atomic_commit *state, enum vc4_encoder_type type, bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel)) { @@ -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_commit *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_commit_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_commit_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_commit *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_commit_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_commit_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,8 +825,8 @@ 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_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_commit *state; struct vc4_crtc_state *new_vc4_crtc_state; struct vc4_hvs_state *new_hvs_state; unsigned int hdmi0_channel; @@ -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_commit_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_commit_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_commit_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_commit_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,8 +925,8 @@ 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_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_commit *state; struct vc4_crtc_state *new_vc4_crtc_state; struct vc4_hvs_state *new_hvs_state; unsigned int old_hdmi0_channel; @@ -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_commit_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_commit_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_commit_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_commit_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_commit_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,8 +1054,8 @@ 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_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_commit *state; struct vc4_crtc_state *new_vc4_crtc_state; struct drm_device *drm; struct vc4_dev *vc4; @@ -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_commit_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_commit_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_commit_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_commit_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..2161761b1f22 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -19,9 +19,9 @@ #include <linux/dma-buf.h> #include <drm/drm_fourcc.h> +#include <drm/drm_print.h> #include "vc4_drv.h" -#include "uapi/drm/vc4_drm.h" static const struct drm_gem_object_funcs vc4_gem_object_funcs; @@ -204,8 +204,7 @@ static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev, struct list_head *new_list; uint32_t i; - new_list = kmalloc_array(new_size, sizeof(struct list_head), - GFP_KERNEL); + new_list = kmalloc_objs(struct list_head, new_size); if (!new_list) return NULL; @@ -399,7 +398,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return ERR_PTR(-ENODEV); - bo = kzalloc(sizeof(*bo), GFP_KERNEL); + bo = kzalloc_obj(*bo); if (!bo) return ERR_PTR(-ENOMEM); @@ -556,7 +555,7 @@ static void vc4_free_object(struct drm_gem_object *gem_bo) mutex_lock(&vc4->bo_lock); /* If the object references someone else's memory, we can't cache it. */ - if (gem_bo->import_attach) { + if (drm_gem_is_imported(gem_bo)) { vc4_bo_destroy(bo); goto out; } @@ -679,7 +678,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo) static void vc4_bo_cache_time_timer(struct timer_list *t) { - struct vc4_dev *vc4 = from_timer(vc4, t, bo_cache.time_timer); + struct vc4_dev *vc4 = timer_container_of(vc4, t, bo_cache.time_timer); schedule_work(&vc4->bo_cache.time_work); } @@ -738,12 +737,15 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct return -EINVAL; } + mutex_lock(&bo->madv_lock); if (bo->madv != VC4_MADV_WILLNEED) { DRM_DEBUG("mmapping of %s BO not allowed\n", bo->madv == VC4_MADV_DONTNEED ? "purgeable" : "purged"); + mutex_unlock(&bo->madv_lock); return -EINVAL; } + mutex_unlock(&bo->madv_lock); return drm_gem_dma_mmap(&bo->base, vma); } @@ -1014,8 +1016,7 @@ int vc4_bo_cache_init(struct drm_device *dev) * use. This lets us avoid a bunch of string reallocation in * the kernel's draw and BO allocation paths. */ - vc4->bo_labels = kcalloc(VC4_BO_TYPE_COUNT, sizeof(*vc4->bo_labels), - GFP_KERNEL); + vc4->bo_labels = kzalloc_objs(*vc4->bo_labels, VC4_BO_TYPE_COUNT); if (!vc4->bo_labels) return -ENOMEM; vc4->num_labels = VC4_BO_TYPE_COUNT; @@ -1043,7 +1044,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..4572b0b9bae1 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -343,7 +343,7 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) } static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -497,7 +497,7 @@ static void require_hvs_enabled(struct drm_device *dev) static int vc4_crtc_disable(struct drm_crtc *crtc, struct drm_encoder *encoder, - struct drm_atomic_state *state, + struct drm_atomic_commit *state, unsigned int channel) { struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); @@ -622,7 +622,7 @@ void vc4_crtc_send_vblank(struct drm_crtc *crtc) } static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc); @@ -648,7 +648,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, } static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc); @@ -740,7 +740,7 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state, } int vc4_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); @@ -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; } @@ -1000,7 +997,7 @@ vc4_async_page_flip_common(struct drm_crtc *crtc, struct drm_plane *plane = crtc->primary; struct vc4_async_flip_state *flip_state; - flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL); + flip_state = kzalloc_obj(*flip_state); if (!flip_state) return -ENOMEM; @@ -1108,7 +1105,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) { struct vc4_crtc_state *vc4_state, *old_vc4_state; - vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); + vc4_state = kzalloc_obj(*vc4_state); if (!vc4_state) return NULL; @@ -1145,7 +1142,7 @@ void vc4_crtc_reset(struct drm_crtc *crtc) if (crtc->state) vc4_crtc_destroy_state(crtc, crtc->state); - vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL); + vc4_crtc_state = kzalloc_obj(*vc4_crtc_state); if (!vc4_crtc_state) { crtc->state = NULL; return; diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index fac624a663ea..e765904e13f3 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -4,6 +4,7 @@ */ #include <drm/drm_drv.h> +#include <drm/drm_print.h> #include <linux/seq_file.h> #include <linux/circ_buf.h> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 960550c166d9..53f36626a50d 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -17,12 +17,12 @@ #include <drm/drm_edid.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/media-bus-format.h> -#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index c7cb1e3a6434..616caf9d9915 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -36,12 +36,11 @@ #include <drm/drm_drv.h> #include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> +#include <drm/drm_print.h> #include <drm/drm_vblank.h> #include <soc/bcm2835/raspberrypi-firmware.h> -#include "uapi/drm/vc4_drm.h" - #include "vc4_drv.h" #include "vc4_regs.h" @@ -151,7 +150,7 @@ static int vc4_open(struct drm_device *dev, struct drm_file *file) if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return -ENODEV; - vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); + vc4file = kzalloc_obj(*vc4file); if (!vc4file) return -ENOMEM; vc4file->dev = vc4; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 4a078ffd9f82..0f5958c1e6b6 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; @@ -396,9 +375,9 @@ struct vc4_hvs_state { #define to_vc4_hvs_state(_state) \ container_of_const(_state, struct vc4_hvs_state, base) -struct vc4_hvs_state *vc4_hvs_get_global_state(struct drm_atomic_state *state); -struct vc4_hvs_state *vc4_hvs_get_old_global_state(const struct drm_atomic_state *state); -struct vc4_hvs_state *vc4_hvs_get_new_global_state(const struct drm_atomic_state *state); +struct vc4_hvs_state *vc4_hvs_get_global_state(struct drm_atomic_commit *state); +struct vc4_hvs_state *vc4_hvs_get_old_global_state(const struct drm_atomic_commit *state); +struct vc4_hvs_state *vc4_hvs_get_new_global_state(const struct drm_atomic_commit *state); struct vc4_plane { struct drm_plane base; @@ -499,12 +478,12 @@ struct vc4_encoder { enum vc4_encoder_type type; u32 clock_select; - void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state); - void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state); - void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state); + void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_commit *state); + void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_commit *state); + void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_commit *state); - void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state); - void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state); + void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_commit *state); + void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_commit *state); }; #define to_vc4_encoder(_encoder) \ @@ -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 @@ -815,10 +791,7 @@ struct vc4_exec_info { struct vc4_file { struct vc4_dev *dev; - struct { - struct idr idr; - struct mutex lock; - } perfmon; + struct xarray perfmons; bool bin_bo_used; }; @@ -972,7 +945,7 @@ int vc4_page_flip(struct drm_crtc *crtc, uint32_t flags, struct drm_modeset_acquire_ctx *ctx); int vc4_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_atomic_state *state); + struct drm_atomic_commit *state); struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc); void vc4_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); @@ -1025,9 +998,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); @@ -1055,11 +1025,11 @@ struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output); int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output); u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo); -int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); -void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); -void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); -void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); -void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); +int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state); +void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_commit *state); +void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_commit *state); +void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_commit *state); +void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_commit *state); void vc4_hvs_dump_state(struct vc4_hvs *hvs); void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel); void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 5eb293bdb363..fc76018b044c 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -36,6 +36,7 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> @@ -552,8 +553,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 +799,7 @@ dsi_esc_timing(u32 ns) } static void vc4_dsi_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_commit *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); u32 disp0_ctrl; @@ -811,7 +810,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_commit *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); struct device *dev = &dsi->pdev->dev; @@ -873,9 +872,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_commit *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 +1141,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_commit *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); bool debug_dump_regs = false; @@ -1161,12 +1159,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 +1621,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 +1636,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 +1791,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 +1814,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..e231c906709c 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -29,9 +29,10 @@ #include <linux/sched/signal.h> #include <linux/dma-fence-array.h> +#include <drm/drm_exec.h> +#include <drm/drm_print.h> #include <drm/drm_syncobj.h> -#include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" #include "vc4_regs.h" #include "vc4_trace.h" @@ -60,6 +61,7 @@ vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state) for (i = 0; i < state->user_state.bo_count; i++) drm_gem_object_put(state->bo[i]); + kfree(state->bo); kfree(state); } @@ -108,7 +110,7 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, state->bo = get_state->bo; memcpy(get_state, state, sizeof(*state)); - bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL); + bo_state = kzalloc_objs(*bo_state, state->bo_count); if (!bo_state) { ret = -ENOMEM; goto err_free; @@ -159,7 +161,7 @@ vc4_save_hang_state(struct drm_device *dev) unsigned long irqflags; unsigned int i, j, k, unref_list_count; - kernel_state = kcalloc(1, sizeof(*kernel_state), GFP_KERNEL); + kernel_state = kzalloc_objs(*kernel_state, 1); if (!kernel_state) return; @@ -168,10 +170,8 @@ vc4_save_hang_state(struct drm_device *dev) spin_lock_irqsave(&vc4->job_lock, irqflags); exec[0] = vc4_first_bin_job(vc4); exec[1] = vc4_first_render_job(vc4); - if (!exec[0] && !exec[1]) { - spin_unlock_irqrestore(&vc4->job_lock, irqflags); - return; - } + if (!exec[0] && !exec[1]) + goto err_free_state; /* Get the bos from both binner and renderer into hang state. */ state->bo_count = 0; @@ -185,13 +185,11 @@ vc4_save_hang_state(struct drm_device *dev) state->bo_count += exec[i]->bo_count + unref_list_count; } - kernel_state->bo = kcalloc(state->bo_count, - sizeof(*kernel_state->bo), GFP_ATOMIC); + kernel_state->bo = kzalloc_objs(*kernel_state->bo, state->bo_count, + GFP_ATOMIC); - if (!kernel_state->bo) { - spin_unlock_irqrestore(&vc4->job_lock, irqflags); - return; - } + if (!kernel_state->bo) + goto err_free_state; k = 0; for (i = 0; i < 2; i++) { @@ -283,6 +281,12 @@ vc4_save_hang_state(struct drm_device *dev) vc4->hang_state = kernel_state; spin_unlock_irqrestore(&vc4->job_lock, irqflags); } + + return; + +err_free_state: + spin_unlock_irqrestore(&vc4->job_lock, irqflags); + kfree(kernel_state); } static void @@ -325,7 +329,7 @@ vc4_reset_work(struct work_struct *work) static void vc4_hangcheck_elapsed(struct timer_list *t) { - struct vc4_dev *vc4 = from_timer(vc4, t, hangcheck.timer); + struct vc4_dev *vc4 = timer_container_of(vc4, t, hangcheck.timer); struct drm_device *dev = &vc4->base; uint32_t ct0ca, ct1ca; unsigned long irqflags; @@ -552,45 +556,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 +582,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 +615,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); @@ -688,7 +624,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, unsigned long irqflags; struct vc4_fence *fence; - fence = kzalloc(sizeof(*fence), GFP_KERNEL); + fence = kzalloc_obj(*fence); if (!fence) return -ENOMEM; fence->dev = dev; @@ -706,9 +642,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 +840,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 +898,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,48 +914,9 @@ 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 * jobs that had completed and unrefs their BOs and frees their exec * structs. @@ -1079,8 +969,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 +980,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 +1016,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; @@ -1152,7 +1045,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - exec = kcalloc(1, sizeof(*exec), GFP_KERNEL); + exec = kzalloc_objs(*exec, 1); if (!exec) return -ENOMEM; @@ -1216,7 +1109,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 +1117,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 +1132,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 +1141,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 +1170,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); @@ -1358,7 +1252,7 @@ int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data, /* Not sure it's safe to purge imported BOs. Let's just assume it's * not until proven otherwise. */ - if (gem_obj->import_attach) { + if (drm_gem_is_imported(gem_obj)) { DRM_DEBUG("madvise not supported on imported BOs\n"); ret = -EINVAL; goto out_put_gem; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 47d9ada98430..a161d3b00a25 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -32,12 +32,14 @@ */ #include <drm/display/drm_hdmi_audio_helper.h> +#include <drm/display/drm_hdmi_cec_helper.h> #include <drm/display/drm_hdmi_helper.h> #include <drm/display/drm_hdmi_state_helper.h> #include <drm/display/drm_scdc_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <linux/clk.h> @@ -51,6 +53,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> @@ -130,7 +133,7 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi) static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, unsigned int bpc, - enum hdmi_colorspace fmt) + enum drm_output_color_format fmt) { unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); @@ -270,34 +273,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 +351,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,16 +375,8 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, * the lock for now. */ - 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); - if (status != connector_status_connected) return; @@ -477,7 +444,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) const struct drm_display_mode *mode; list_for_each_entry(mode, &connector->probed_modes, head) { - if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) { + if (vc4_hdmi_mode_needs_scrambling(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444)) { drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); } @@ -488,7 +455,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) } static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(state, connector); @@ -580,16 +547,16 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, &vc4_hdmi_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA, vc4_hdmi->ddc, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), max_bpc); if (ret) return ret; ret = drm_connector_hdmi_audio_init(connector, dev->dev, &vc4_hdmi_audio_funcs, - 8, false, -1); + 8, 0, false, -1); if (ret) return ret; @@ -657,6 +624,30 @@ static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi, return ret; } +static int vc4_hdmi_clear_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type) +{ + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + struct drm_device *drm = connector->dev; + int ret; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return 0; + + WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & + VC4_HDMI_RAM_PACKET_ENABLE), + "Packet RAM has to be on to store the packet."); + + ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true); + if (ret) + drm_err(drm, "Failed to wait for infoframe to go idle: %d\n", ret); + + drm_dev_exit(idx); + + return ret; +} + static int vc4_hdmi_write_infoframe(struct drm_connector *connector, enum hdmi_infoframe_type type, const u8 *infoframe, size_t len) @@ -736,6 +727,66 @@ out: return ret; } +static int vc4_hdmi_clear_avi_infoframe(struct drm_connector *connector) +{ + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI); +} + +static int vc4_hdmi_clear_hdmi_infoframe(struct drm_connector *connector) +{ + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR); +} + +static int vc4_hdmi_clear_audio_infoframe(struct drm_connector *connector) +{ + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO); +} + +static int vc4_hdmi_clear_hdr_drm_infoframe(struct drm_connector *connector) +{ + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM); +} + +static int vc4_hdmi_clear_spd_infoframe(struct drm_connector *connector) +{ + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD); +} + +static int vc4_hdmi_write_avi_infoframe(struct drm_connector *connector, + const u8 *buffer, size_t len) +{ + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI, + buffer, len); +} + +static int vc4_hdmi_write_hdmi_infoframe(struct drm_connector *connector, + const u8 *buffer, size_t len) +{ + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR, + buffer, len); +} + +static int vc4_hdmi_write_audio_infoframe(struct drm_connector *connector, + const u8 *buffer, size_t len) +{ + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO, + buffer, len); +} + +static int vc4_hdmi_write_hdr_drm_infoframe(struct drm_connector *connector, + const u8 *buffer, size_t len) +{ + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM, + buffer, len); +} + +static int vc4_hdmi_write_spd_infoframe(struct drm_connector *connector, + const u8 *buffer, size_t len) +{ + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD, + buffer, len); +} + #define SCRAMBLING_POLLING_DELAY_MS 1000 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) @@ -772,7 +823,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) vc4_hdmi->scdc_enabled = true; - queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, + queue_delayed_work(system_percpu_wq, &vc4_hdmi->scrambling_work, msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); } @@ -821,12 +872,12 @@ static void vc4_hdmi_scrambling_wq(struct work_struct *work) drm_scdc_set_high_tmds_clock_ratio(connector, true); drm_scdc_set_scrambling(connector, true); - queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, + queue_delayed_work(system_percpu_wq, &vc4_hdmi->scrambling_work, msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); } static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; @@ -876,12 +927,11 @@ out: } static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; - int ret; int idx; mutex_lock(&vc4_hdmi->mutex); @@ -900,9 +950,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); - ret = pm_runtime_put(&vc4_hdmi->pdev->dev); - if (ret < 0) - drm_err(drm, "Failed to release power domain: %d\n", ret); + pm_runtime_put(&vc4_hdmi->pdev->dev); drm_dev_exit(idx); @@ -1166,13 +1214,13 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); switch (state->hdmi.output_format) { - case HDMI_COLORSPACE_YUV444: + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); break; - case HDMI_COLORSPACE_YUV422: + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, @@ -1189,7 +1237,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); break; - case HDMI_COLORSPACE_RGB: + case DRM_OUTPUT_COLOR_FORMAT_RGB444: if_xbar = 0x354021; vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); @@ -1346,7 +1394,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, * YCC422 is always 36-bit and not considered deep colour so * doesn't signal in GCP. */ - if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) { + if (state->hdmi.output_format == DRM_OUTPUT_COLOR_FORMAT_YCBCR422) { gcp = 0; } @@ -1423,7 +1471,7 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) } static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; @@ -1539,7 +1587,7 @@ out: } static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; @@ -1569,7 +1617,7 @@ out: } static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_connector *connector = &vc4_hdmi->connector; @@ -1693,7 +1741,26 @@ vc4_hdmi_connector_clock_valid(const struct drm_connector *connector, static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = { .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid, - .write_infoframe = vc4_hdmi_write_infoframe, + .avi = { + .clear_infoframe = vc4_hdmi_clear_avi_infoframe, + .write_infoframe = vc4_hdmi_write_avi_infoframe, + }, + .hdmi = { + .clear_infoframe = vc4_hdmi_clear_hdmi_infoframe, + .write_infoframe = vc4_hdmi_write_hdmi_infoframe, + }, + .audio = { + .clear_infoframe = vc4_hdmi_clear_audio_infoframe, + .write_infoframe = vc4_hdmi_write_audio_infoframe, + }, + .hdr_drm = { + .clear_infoframe = vc4_hdmi_clear_hdr_drm_infoframe, + .write_infoframe = vc4_hdmi_write_hdr_drm_infoframe, + }, + .spd = { + .clear_infoframe = vc4_hdmi_clear_spd_infoframe, + .write_infoframe = vc4_hdmi_write_spd_infoframe, + }, }; #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL @@ -2203,6 +2270,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 = @@ -2302,6 +2385,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) return ret; } + ret = drm_connector_hdmi_audio_init(&vc4_hdmi->connector, dev, + &vc4_hdmi_audio_funcs, 8, 0, false, + -1); + if (ret) + return ret; + dai_link->cpus = &vc4_hdmi->audio.cpu; dai_link->codecs = &vc4_hdmi->audio.codec; dai_link->platforms = &vc4_hdmi->audio.platform; @@ -2316,6 +2405,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; @@ -2359,17 +2449,23 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi) int ret; if (vc4_hdmi->variant->external_irq_controller) { - unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); - unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); + int hpd = platform_get_irq_byname(pdev, "hpd-connected"); + + if (hpd < 0) + return hpd; - ret = devm_request_threaded_irq(&pdev->dev, hpd_con, + ret = devm_request_threaded_irq(&pdev->dev, hpd, NULL, vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, "vc4 hdmi hpd connected", vc4_hdmi); if (ret) return ret; - ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, + hpd = platform_get_irq_byname(pdev, "hpd-removed"); + if (hpd < 0) + return hpd; + + ret = devm_request_threaded_irq(&pdev->dev, hpd, NULL, vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, "vc4 hdmi hpd disconnected", vc4_hdmi); @@ -2388,8 +2484,8 @@ static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv) struct vc4_hdmi *vc4_hdmi = priv; if (vc4_hdmi->cec_rx_msg.len) - cec_received_msg(vc4_hdmi->cec_adap, - &vc4_hdmi->cec_rx_msg); + drm_connector_hdmi_cec_received_msg(&vc4_hdmi->connector, + &vc4_hdmi->cec_rx_msg); return IRQ_HANDLED; } @@ -2399,15 +2495,17 @@ static irqreturn_t vc4_cec_irq_handler_tx_thread(int irq, void *priv) struct vc4_hdmi *vc4_hdmi = priv; if (vc4_hdmi->cec_tx_ok) { - cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, - 0, 0, 0, 0); + drm_connector_hdmi_cec_transmit_done(&vc4_hdmi->connector, + CEC_TX_STATUS_OK, + 0, 0, 0, 0); } else { /* * This CEC implementation makes 1 retry, so if we * get a NACK, then that means it made 2 attempts. */ - cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, - 0, 2, 0, 0); + drm_connector_hdmi_cec_transmit_done(&vc4_hdmi->connector, + CEC_TX_STATUS_NACK, + 0, 2, 0, 0); } return IRQ_HANDLED; } @@ -2564,9 +2662,9 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) return ret; } -static int vc4_hdmi_cec_enable(struct cec_adapter *adap) +static int vc4_hdmi_cec_enable(struct drm_connector *connector) { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct drm_device *drm = vc4_hdmi->connector.dev; /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; @@ -2631,9 +2729,9 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) return 0; } -static int vc4_hdmi_cec_disable(struct cec_adapter *adap) +static int vc4_hdmi_cec_disable(struct drm_connector *connector) { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; int idx; @@ -2667,17 +2765,17 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) return 0; } -static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) +static int vc4_hdmi_cec_adap_enable(struct drm_connector *connector, bool enable) { if (enable) - return vc4_hdmi_cec_enable(adap); + return vc4_hdmi_cec_enable(connector); else - return vc4_hdmi_cec_disable(adap); + return vc4_hdmi_cec_disable(connector); } -static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +static int vc4_hdmi_cec_adap_log_addr(struct drm_connector *connector, u8 log_addr) { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; int idx; @@ -2703,10 +2801,10 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) return 0; } -static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, +static int vc4_hdmi_cec_adap_transmit(struct drm_connector *connector, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct drm_device *dev = vc4_hdmi->connector.dev; unsigned long flags; u32 val; @@ -2749,84 +2847,65 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, return 0; } -static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { - .adap_enable = vc4_hdmi_cec_adap_enable, - .adap_log_addr = vc4_hdmi_cec_adap_log_addr, - .adap_transmit = vc4_hdmi_cec_adap_transmit, -}; - -static void vc4_hdmi_cec_release(void *ptr) -{ - struct vc4_hdmi *vc4_hdmi = ptr; - - cec_unregister_adapter(vc4_hdmi->cec_adap); - vc4_hdmi->cec_adap = NULL; -} - -static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +static int vc4_hdmi_cec_init(struct drm_connector *connector) { - struct cec_connector_info conn_info; + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct platform_device *pdev = vc4_hdmi->pdev; struct device *dev = &pdev->dev; int ret; - if (!of_property_present(dev->of_node, "interrupts")) { - dev_warn(dev, "'interrupts' DT property is missing, no CEC\n"); - return 0; - } - - vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, - vc4_hdmi, - vc4_hdmi->variant->card_name, - CEC_CAP_DEFAULTS | - CEC_CAP_CONNECTOR_INFO, 1); - ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); - if (ret < 0) - return ret; - - cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); - cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); - if (vc4_hdmi->variant->external_irq_controller) { ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"), vc4_cec_irq_handler_rx_bare, vc4_cec_irq_handler_rx_thread, 0, "vc4 hdmi cec rx", vc4_hdmi); if (ret) - goto err_delete_cec_adap; + return ret; ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"), vc4_cec_irq_handler_tx_bare, vc4_cec_irq_handler_tx_thread, 0, "vc4 hdmi cec tx", vc4_hdmi); if (ret) - goto err_delete_cec_adap; + return ret; } else { ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), vc4_cec_irq_handler, vc4_cec_irq_handler_thread, 0, "vc4 hdmi cec", vc4_hdmi); if (ret) - goto err_delete_cec_adap; + return ret; } - ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); - if (ret < 0) - goto err_delete_cec_adap; + return 0; +} + +static const struct drm_connector_hdmi_cec_funcs vc4_hdmi_cec_funcs = { + .init = vc4_hdmi_cec_init, + .enable = vc4_hdmi_cec_adap_enable, + .log_addr = vc4_hdmi_cec_adap_log_addr, + .transmit = vc4_hdmi_cec_adap_transmit, +}; + +static int vc4_hdmi_cec_register(struct vc4_hdmi *vc4_hdmi) +{ + struct platform_device *pdev = vc4_hdmi->pdev; + struct device *dev = &pdev->dev; + + if (!of_property_present(dev->of_node, "interrupts")) { + dev_warn(dev, "'interrupts' DT property is missing, no CEC\n"); + return 0; + } /* - * NOTE: Strictly speaking, we should probably use a DRM-managed - * registration there to avoid removing the CEC adapter by the - * time the DRM driver doesn't have any user anymore. + * NOTE: the CEC adapter will be unregistered by drmm cleanup from + * drm_managed_release(), which is called from drm_dev_release() + * during device unbind. * * However, the CEC framework already cleans up the CEC adapter * only when the last user has closed its file descriptor, so we * don't need to handle it in DRM. * - * By the time the device-managed hook is executed, we will give - * up our reference to the CEC adapter and therefore don't - * really care when it's actually freed. - * * There's still a problematic sequence: if we unregister our * CEC adapter, but the userspace keeps a handle on the CEC * adapter but not the DRM device for some reason. In such a @@ -2837,19 +2916,14 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) * the CEC framework already handles this too, by calling * cec_is_registered() in cec_ioctl() and cec_poll(). */ - ret = devm_add_action_or_reset(dev, vc4_hdmi_cec_release, vc4_hdmi); - if (ret) - return ret; - - return 0; - -err_delete_cec_adap: - cec_delete_adapter(vc4_hdmi->cec_adap); - - return ret; + return drmm_connector_hdmi_cec_register(&vc4_hdmi->connector, + &vc4_hdmi_cec_funcs, + vc4_hdmi->variant->card_name, + 1, + &pdev->dev); } #else -static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +static int vc4_hdmi_cec_register(struct vc4_hdmi *vc4_hdmi) { return 0; } @@ -2873,8 +2947,7 @@ static int vc4_hdmi_build_regset(struct drm_device *drm, unsigned int i; int ret; - regs = kcalloc(variant->num_registers, sizeof(*regs), - GFP_KERNEL); + regs = kzalloc_objs(*regs, variant->num_registers); if (!regs) return -ENOMEM; @@ -2954,15 +3027,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 +3045,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_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->cec_regs) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc"); - 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->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->csc_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, "dvp"); - 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->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (!vc4_hdmi->dvp_regs) - return -ENOMEM; + vc4_hdmi->phy_regs = devm_platform_ioremap_resource_byname(pdev, + "phy"); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); - if (!res) - return -ENODEV; + if (IS_ERR(vc4_hdmi->phy_regs)) + return PTR_ERR(vc4_hdmi->phy_regs); - 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; + 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, "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)) { @@ -3271,7 +3327,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_put_runtime_pm; - ret = vc4_hdmi_cec_init(vc4_hdmi); + ret = vc4_hdmi_cec_register(vc4_hdmi); if (ret) goto err_put_runtime_pm; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index e3d989ca302b..29d461d4ee49 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" @@ -146,7 +147,6 @@ struct vc4_hdmi { */ bool disable_wifi_frequencies; - struct cec_adapter *cec_adap; struct cec_msg cec_rx_msg; bool cec_tx_ok; bool cec_irq_was_rx; @@ -210,7 +210,13 @@ struct vc4_hdmi { * @drm_connector_state.hdmi.output_format for use outside of * KMS hooks. Protected by @mutex. */ - enum hdmi_colorspace output_format; + enum drm_output_color_format 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_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 4811d794001f..184d51ea3fa5 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -26,6 +26,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_print.h> #include <drm/drm_vblank.h> #include <soc/bcm2835/raspberrypi-firmware.h> @@ -786,7 +787,7 @@ void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) __vc4_hvs_stop_channel(hvs, chan); } -int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) +int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); @@ -881,7 +882,7 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) } void vc4_hvs_atomic_begin(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); @@ -893,7 +894,7 @@ void vc4_hvs_atomic_begin(struct drm_crtc *crtc, } void vc4_hvs_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -911,7 +912,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, } void vc4_hvs_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -923,7 +924,7 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc, } void vc4_hvs_atomic_flush(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc); diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index 69b399f3b802..8e5141bb5075 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -47,7 +47,7 @@ #include <linux/platform_device.h> -#include <drm/drm_drv.h> +#include <drm/drm_print.h> #include "vc4_drv.h" #include "vc4_regs.h" @@ -241,23 +241,6 @@ vc4_irq(int irq, void *arg) return status; } -static void -vc4_irq_prepare(struct drm_device *dev) -{ - struct vc4_dev *vc4 = to_vc4_dev(dev); - - if (!vc4->v3d) - return; - - init_waitqueue_head(&vc4->job_wait_queue); - INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work); - - /* Clear any pending interrupts someone might have left around - * for us. - */ - V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); -} - void vc4_irq_enable(struct drm_device *dev) { @@ -306,12 +289,22 @@ int vc4_irq_install(struct drm_device *dev, int irq) if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return -ENODEV; + if (!vc4->v3d) + return -ENODEV; + if (irq == IRQ_NOTCONNECTED) return -ENOTCONN; - vc4_irq_prepare(dev); + init_waitqueue_head(&vc4->job_wait_queue); + INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work); + + /* Clear any pending interrupts someone might have left around + * for us. + */ + V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); - ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev); + ret = devm_request_irq(dev->dev, irq, vc4_irq, 0, + dev_name(dev->dev), dev); if (ret) return ret; @@ -328,7 +321,6 @@ void vc4_irq_uninstall(struct drm_device *dev) return; vc4_irq_disable(dev); - free_irq(vc4->irq, dev); } /** Reinitializes interrupt registers when a GPU reset is performed. */ diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index f5b167417428..b17e73bce384 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -19,6 +19,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> @@ -43,7 +44,7 @@ struct vc4_load_tracker_state { #define to_vc4_load_tracker_state(_state) \ container_of_const(_state, struct vc4_load_tracker_state, base) -static struct vc4_ctm_state *vc4_get_ctm_state(struct drm_atomic_state *state, +static struct vc4_ctm_state *vc4_get_ctm_state(struct drm_atomic_commit *state, struct drm_private_obj *manager) { struct drm_device *dev = state->dev; @@ -84,7 +85,22 @@ static void vc4_ctm_destroy_state(struct drm_private_obj *obj, kfree(ctm_state); } +static struct drm_private_state * +vc4_ctm_create_state(struct drm_private_obj *obj) +{ + struct vc4_ctm_state *ctm_state; + + ctm_state = kzalloc_obj(*ctm_state); + if (!ctm_state) + return ERR_PTR(-ENOMEM); + + __drm_atomic_helper_private_obj_create_state(obj, &ctm_state->base); + + return &ctm_state->base; +} + static const struct drm_private_state_funcs vc4_ctm_state_funcs = { + .atomic_create_state = vc4_ctm_create_state, .atomic_duplicate_state = vc4_ctm_duplicate_state, .atomic_destroy_state = vc4_ctm_destroy_state, }; @@ -98,15 +114,9 @@ static void vc4_ctm_obj_fini(struct drm_device *dev, void *unused) static int vc4_ctm_obj_init(struct vc4_dev *vc4) { - struct vc4_ctm_state *ctm_state; - drm_modeset_lock_init(&vc4->ctm_state_lock); - ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL); - if (!ctm_state) - return -ENOMEM; - - drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, &ctm_state->base, + drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, &vc4_ctm_state_funcs); return drmm_add_action_or_reset(&vc4->base, vc4_ctm_obj_fini, NULL); @@ -132,7 +142,7 @@ static u16 vc4_ctm_s31_32_to_s0_9(u64 in) } static void -vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) +vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_commit *state) { struct vc4_hvs *hvs = vc4->hvs; struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state); @@ -169,7 +179,7 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) } struct vc4_hvs_state * -vc4_hvs_get_new_global_state(const struct drm_atomic_state *state) +vc4_hvs_get_new_global_state(const struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_private_state *priv_state; @@ -182,7 +192,7 @@ vc4_hvs_get_new_global_state(const struct drm_atomic_state *state) } struct vc4_hvs_state * -vc4_hvs_get_old_global_state(const struct drm_atomic_state *state) +vc4_hvs_get_old_global_state(const struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_private_state *priv_state; @@ -195,7 +205,7 @@ vc4_hvs_get_old_global_state(const struct drm_atomic_state *state) } struct vc4_hvs_state * -vc4_hvs_get_global_state(struct drm_atomic_state *state) +vc4_hvs_get_global_state(struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_private_state *priv_state; @@ -208,7 +218,7 @@ vc4_hvs_get_global_state(struct drm_atomic_state *state) } static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hvs *hvs = vc4->hvs; struct drm_crtc_state *crtc_state; @@ -251,7 +261,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, } static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hvs *hvs = vc4->hvs; struct drm_crtc_state *crtc_state; @@ -327,7 +337,7 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, } static void vc6_hvs_pv_muxing_commit(struct vc4_dev *vc4, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hvs *hvs = vc4->hvs; struct drm_crtc_state *crtc_state; @@ -374,7 +384,7 @@ static void vc6_hvs_pv_muxing_commit(struct vc4_dev *vc4, } } -static void vc4_atomic_commit_tail(struct drm_atomic_state *state) +static void vc4_atomic_commit_tail(struct drm_atomic_commit *state) { struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -498,7 +508,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) } } -static int vc4_atomic_commit_setup(struct drm_atomic_state *state) +static int vc4_atomic_commit_setup(struct drm_atomic_commit *state) { struct drm_crtc_state *crtc_state; struct vc4_hvs_state *hvs_state; @@ -530,6 +540,7 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, struct drm_file *file_priv, + const struct drm_format_info *info, const struct drm_mode_fb_cmd2 *mode_cmd) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -568,7 +579,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, mode_cmd = &mode_cmd_local; } - return drm_gem_fb_create(dev, file_priv, mode_cmd); + return drm_gem_fb_create(dev, file_priv, info, mode_cmd); } /* Our CTM has some peculiar limitations: we can only enable it for one CRTC @@ -576,7 +587,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, * we don't allow userland to set a CTM that we have no hope of approximating. */ static int -vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) +vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_ctm_state *ctm_state = NULL; @@ -642,7 +653,7 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) return 0; } -static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state) +static int vc4_load_tracker_atomic_check(struct drm_atomic_commit *state) { struct drm_plane_state *old_plane_state, *new_plane_state; struct vc4_dev *vc4 = to_vc4_dev(state->dev); @@ -716,7 +727,22 @@ static void vc4_load_tracker_destroy_state(struct drm_private_obj *obj, kfree(load_state); } +static struct drm_private_state * +vc4_load_tracker_create_state(struct drm_private_obj *obj) +{ + struct vc4_load_tracker_state *load_state; + + load_state = kzalloc_obj(*load_state); + if (!load_state) + return ERR_PTR(-ENOMEM); + + __drm_atomic_helper_private_obj_create_state(obj, &load_state->base); + + return &load_state->base; +} + static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { + .atomic_create_state = vc4_load_tracker_create_state, .atomic_duplicate_state = vc4_load_tracker_duplicate_state, .atomic_destroy_state = vc4_load_tracker_destroy_state, }; @@ -730,14 +756,7 @@ static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused) static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) { - struct vc4_load_tracker_state *load_state; - - load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); - if (!load_state) - return -ENOMEM; - drm_atomic_private_obj_init(&vc4->base, &vc4->load_tracker, - &load_state->base, &vc4_load_tracker_state_funcs); return drmm_add_action_or_reset(&vc4->base, vc4_load_tracker_obj_fini, NULL); @@ -750,7 +769,7 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) struct vc4_hvs_state *state; unsigned int i; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = kzalloc_obj(*state); if (!state) return NULL; @@ -798,7 +817,22 @@ static void vc4_hvs_channels_print_state(struct drm_printer *p, } } +static struct drm_private_state * +vc4_hvs_channels_create_state(struct drm_private_obj *obj) +{ + struct vc4_hvs_state *hvs_state; + + hvs_state = kzalloc_obj(*hvs_state); + if (!hvs_state) + return ERR_PTR(-ENOMEM); + + __drm_atomic_helper_private_obj_create_state(obj, &hvs_state->base); + + return &hvs_state->base; +} + static const struct drm_private_state_funcs vc4_hvs_state_funcs = { + .atomic_create_state = vc4_hvs_channels_create_state, .atomic_duplicate_state = vc4_hvs_channels_duplicate_state, .atomic_destroy_state = vc4_hvs_channels_destroy_state, .atomic_print_state = vc4_hvs_channels_print_state, @@ -813,14 +847,7 @@ static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused) static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) { - struct vc4_hvs_state *state; - - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - drm_atomic_private_obj_init(&vc4->base, &vc4->hvs_channels, - &state->base, &vc4_hvs_state_funcs); return drmm_add_action_or_reset(&vc4->base, vc4_hvs_channels_obj_fini, NULL); @@ -871,7 +898,7 @@ static int cmp_vc4_crtc_hvs_output(const void *a, const void *b) * single display, and changing the resolution down and then back up. */ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_hvs_state *hvs_new_state; struct drm_crtc **sorted_crtcs; @@ -909,7 +936,7 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, * If the layout changes and doesn't give us that in the future, * we will need to have something smarter, but it works so far. */ - sorted_crtcs = kmalloc_array(dev->num_crtcs, sizeof(*sorted_crtcs), GFP_KERNEL); + sorted_crtcs = kmalloc_objs(*sorted_crtcs, dev->num_crtcs); if (!sorted_crtcs) return -ENOMEM; @@ -992,7 +1019,7 @@ err_free_crtc_array: } static int -vc4_core_clock_atomic_check(struct drm_atomic_state *state) +vc4_core_clock_atomic_check(struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_private_state *priv_state; @@ -1064,7 +1091,7 @@ vc4_core_clock_atomic_check(struct drm_atomic_state *state) static int -vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) +vc4_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state) { int ret; diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c index f1342f917cf7..f75dfd156756 100644 --- a/drivers/gpu/drm/vc4/vc4_perfmon.c +++ b/drivers/gpu/drm/vc4/vc4_perfmon.c @@ -9,12 +9,11 @@ * The V3D block provides 16 hardware counters which can count various events. */ +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_regs.h" -#define VC4_PERFMONID_MIN 1 -#define VC4_PERFMONID_MAX U32_MAX - void vc4_perfmon_get(struct vc4_perfmon *perfmon) { struct vc4_dev *vc4; @@ -93,10 +92,10 @@ struct vc4_perfmon *vc4_perfmon_find(struct vc4_file *vc4file, int id) if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return NULL; - mutex_lock(&vc4file->perfmon.lock); - perfmon = idr_find(&vc4file->perfmon.idr, id); + xa_lock(&vc4file->perfmons); + perfmon = xa_load(&vc4file->perfmons, id); vc4_perfmon_get(perfmon); - mutex_unlock(&vc4file->perfmon.lock); + xa_unlock(&vc4file->perfmons); return perfmon; } @@ -108,37 +107,34 @@ void vc4_perfmon_open_file(struct vc4_file *vc4file) if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return; - mutex_init(&vc4file->perfmon.lock); - idr_init_base(&vc4file->perfmon.idr, VC4_PERFMONID_MIN); - vc4file->dev = vc4; + xa_init_flags(&vc4file->perfmons, XA_FLAGS_ALLOC1); } -static int vc4_perfmon_idr_del(int id, void *elem, void *data) +static void vc4_perfmon_delete(struct vc4_file *vc4file, + struct vc4_perfmon *perfmon) { - struct vc4_perfmon *perfmon = elem; - struct vc4_dev *vc4 = (struct vc4_dev *)data; + struct vc4_dev *vc4 = vc4file->dev; /* If the active perfmon is being destroyed, stop it first */ if (perfmon == vc4->active_perfmon) vc4_perfmon_stop(vc4, perfmon, false); vc4_perfmon_put(perfmon); - - return 0; } void vc4_perfmon_close_file(struct vc4_file *vc4file) { struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + unsigned long id; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return; - mutex_lock(&vc4file->perfmon.lock); - idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, vc4); - idr_destroy(&vc4file->perfmon.idr); - mutex_unlock(&vc4file->perfmon.lock); - mutex_destroy(&vc4file->perfmon.lock); + xa_for_each(&vc4file->perfmons, id, perfmon) + vc4_perfmon_delete(vc4file, perfmon); + + xa_destroy(&vc4file->perfmons); } int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, @@ -150,6 +146,7 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, struct vc4_perfmon *perfmon; unsigned int i; int ret; + u32 id; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return -ENODEV; @@ -170,8 +167,7 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - perfmon = kzalloc(struct_size(perfmon, counters, req->ncounters), - GFP_KERNEL); + perfmon = kzalloc_flex(*perfmon, counters, req->ncounters); if (!perfmon) return -ENOMEM; perfmon->dev = vc4; @@ -183,17 +179,15 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, refcount_set(&perfmon->refcnt, 1); - mutex_lock(&vc4file->perfmon.lock); - ret = idr_alloc(&vc4file->perfmon.idr, perfmon, VC4_PERFMONID_MIN, - VC4_PERFMONID_MAX, GFP_KERNEL); - mutex_unlock(&vc4file->perfmon.lock); - + ret = xa_alloc(&vc4file->perfmons, &id, perfmon, xa_limit_32b, + GFP_KERNEL); if (ret < 0) { kfree(perfmon); return ret; } - req->id = ret; + req->id = id; + return 0; } @@ -213,14 +207,12 @@ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data, return -ENODEV; } - mutex_lock(&vc4file->perfmon.lock); - perfmon = idr_remove(&vc4file->perfmon.idr, req->id); - mutex_unlock(&vc4file->perfmon.lock); - + perfmon = xa_erase(&vc4file->perfmons, req->id); if (!perfmon) return -EINVAL; - vc4_perfmon_put(perfmon); + vc4_perfmon_delete(vc4file, perfmon); + return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index d608860d525f..6c433270214d 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -24,8 +24,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> - -#include "uapi/drm/vc4_drm.h" +#include <drm/drm_print.h> #include "vc4_drv.h" #include "vc4_regs.h" @@ -373,7 +372,7 @@ static void vc4_plane_reset(struct drm_plane *plane) kfree(plane->state); - vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); + vc4_state = kzalloc_obj(*vc4_state); if (!vc4_state) return; @@ -497,8 +496,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) u32 v_subsample = fb->format->vsub; int ret; - crtc_state = drm_atomic_get_existing_crtc_state(state->state, - state->crtc); + crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); if (!crtc_state) { DRM_DEBUG_KMS("Invalid crtc state\n"); return -EINVAL; @@ -875,8 +873,7 @@ static void vc4_plane_calc_load(struct drm_plane_state *state) unsigned int vscale_factor; vc4_state = to_vc4_plane_state(state); - crtc_state = drm_atomic_get_existing_crtc_state(state->state, - state->crtc); + crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); vrefresh = drm_mode_vrefresh(&crtc_state->adjusted_mode); /* The HVS is able to process 2 pixels/cycle when scaling the source, @@ -2080,7 +2077,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); } } @@ -2126,7 +2123,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane, * in the CRTC's flush. */ static int vc4_plane_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct vc4_dev *vc4 = to_vc4_dev(plane->dev); struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, @@ -2172,7 +2169,7 @@ static int vc4_plane_atomic_check(struct drm_plane *plane, } static void vc4_plane_atomic_update(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { /* No contents here. Since we don't know where in the CRTC's * dlist we should be stored, our dlist is uploaded to the @@ -2264,7 +2261,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) } static void vc4_plane_atomic_async_update(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); @@ -2338,7 +2335,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_commit *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_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index 14079853338e..c264d21bc3fe 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -35,7 +35,8 @@ * actually fairly low. */ -#include "uapi/drm/vc4_drm.h" +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_packet.h" diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 4eab069cda75..bc3f366fc3e6 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -9,7 +9,6 @@ #include <linux/clk.h> #include <linux/component.h> -#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -21,6 +20,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include <drm/drm_writeback.h> @@ -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; @@ -245,7 +245,7 @@ static void vc4_txp_armed(struct drm_crtc_state *state) } static int vc4_txp_connector_atomic_check(struct drm_connector *conn, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; @@ -284,7 +284,7 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn, } static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *drm = conn->dev; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, @@ -434,7 +434,7 @@ static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { }; static int vc4_txp_atomic_check(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); @@ -450,14 +450,14 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc, } static void vc4_txp_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { drm_crtc_vblank_on(crtc); vc4_hvs_atomic_enable(crtc, state); } static void vc4_txp_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index bb09df5000bd..d31b906cb8e7 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -10,6 +10,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_regs.h" @@ -479,6 +481,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ + pm_runtime_put_autosuspend(dev); return 0; diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 5bf134968ade..7f2fadfde7a8 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -43,7 +43,8 @@ * to use) happens. */ -#include "uapi/drm/vc4_drm.h" +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_packet.h" @@ -284,9 +285,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 +736,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 +897,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; diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c index 2d74e786914c..66502a6a4a8e 100644 --- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c +++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c @@ -41,6 +41,8 @@ * this validation is only performed at BO creation time. */ +#include <drm/drm_print.h> + #include "vc4_drv.h" #include "vc4_qpu_defines.h" @@ -288,15 +290,16 @@ static bool require_uniform_address_uniform(struct vc4_validated_shader_info *va { uint32_t o = validated_shader->num_uniform_addr_offsets; uint32_t num_uniforms = validated_shader->uniforms_size / 4; + u32 *offsets; - validated_shader->uniform_addr_offsets = - krealloc(validated_shader->uniform_addr_offsets, - (o + 1) * - sizeof(*validated_shader->uniform_addr_offsets), - GFP_KERNEL); - if (!validated_shader->uniform_addr_offsets) + offsets = krealloc_array(validated_shader->uniform_addr_offsets, + o + 1, + sizeof(*validated_shader->uniform_addr_offsets), + GFP_KERNEL); + if (!offsets) return false; + validated_shader->uniform_addr_offsets = offsets; validated_shader->uniform_addr_offsets[o] = num_uniforms; validated_shader->num_uniform_addr_offsets++; @@ -801,7 +804,7 @@ vc4_validate_shader(struct drm_gem_dma_object *shader_obj) if (!validation_state.branch_targets) goto fail; - validated_shader = kcalloc(1, sizeof(*validated_shader), GFP_KERNEL); + validated_shader = kzalloc_objs(*validated_shader, 1); if (!validated_shader) goto fail; diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 06d702e879b0..792b7b39be59 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -17,6 +17,7 @@ #include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <linux/clk.h> @@ -537,11 +538,11 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) } static void vc4_vec_encoder_disable(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); - int idx, ret; + int idx; if (!drm_dev_enter(drm, &idx)) return; @@ -555,21 +556,13 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder, clk_disable_unprepare(vec->clock); - ret = pm_runtime_put(&vec->pdev->dev); - if (ret < 0) { - drm_err(drm, "Failed to release power domain: %d\n", ret); - goto err_dev_exit; - } - - drm_dev_exit(idx); - return; + pm_runtime_put(&vec->pdev->dev); -err_dev_exit: drm_dev_exit(idx); } static void vc4_vec_encoder_enable(struct drm_encoder *encoder, - struct drm_atomic_state *state) + struct drm_atomic_commit *state) { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); |
