From nobody Thu Dec 18 21:13:39 2025 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20C1E2405E8 for ; Tue, 18 Feb 2025 10:12:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; cv=none; b=lRiwryidI8P/jZTQ+5W890jQ26GRsS9JO8s/UuSUFkveuhjZn2/D6Dtm0qemOBqaxev9TS7rfBZ/lVJaiEm3kK3EcY67cIFNJ9oB3u/CNoOvy+Rp1CAYd2f3xfy/AnVSQZDrgHLOV/oYbYcZqLTOqkRP/2uvrqoXUqEw90CopPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; c=relaxed/simple; bh=VKouC1yHam4PYKIdm1UgvOuWvAtAfkCSnSnCSuP8yEU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VqGQohIEa5BxssqWMZuMkv69/JKCrS+nQdCPdvSjo4zqAOv76vpi8Xq/mPXmp50FRXlKJigUy5cNR9C1dQr3rC02u46qyVImSU96pxufVyMcZIKJiHOBRtIV8/q4DpTTLnTwlnjEGpd+MhVEhLtUfwkRtQ8Zey7SXRwXktyOYVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=K22OEZol; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K22OEZol" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-38f22fe8762so2649237f8f.2 for ; Tue, 18 Feb 2025 02:12:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873554; x=1740478354; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CnYiK1+icpg3ZrEtfUK020G2fBOmYV0BKtEcQQYSHs0=; b=K22OEZolVd5s0IlEHJWZO7tIt6TBRHMrz6hP+Nip5qzQ9cU/kYV+4UFHBvpXQ24TzR /sYNTAyCDk/qiBVF76wVWMZIrSErw12FkDu7/sX1tji9FjnxBV3PMLMzCEjX62GRNhR+ LM3zlXLhvP//4qb7m7kiyOxQp3PPd1adYPfYKXkVaps7VBf6kSDU/9cqA1M4vGvazQtG ZNqLlJ/iKKq2YRwSMD5PL8aFnmUWZBe9FihPrntOhE7DNW4ORUIvAIlF7VXTBPcYdZct O7vjiARDt5shvDup9a1csqvjoDja6hJ9wMLODGAts/sLSDqylI2cyOIdVYXRwVbDBMfb PlPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873554; x=1740478354; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CnYiK1+icpg3ZrEtfUK020G2fBOmYV0BKtEcQQYSHs0=; b=IoY+nlkXlPp8XOwUvEzJwoE569zbDNDMKdOPwLg4gRyrUxfkkuHfYnsNGjspewjfgN D6dhpNDj9RoXgvnzesiXoFTLyL1GGvVyy6r0RmNgMZRiTP+JUc/01zIWOapezPIL+J9k QgtGS0to5EnzVjTEbK2x0G1aL9xuc3HJv8Vs/2ZAvfWt1ur8S2ytvph8RUmW1+RFwsDu hBZuufOrRqWElAkQLTZFIpbwk97ZE/2E9zmnRvC3r5zG+Fk4NMgh62EqdeqLT7WgPZoo 9JVQX5q6VjVy81+BawGKQxOJKO9ntwNZR2LuL1VxlB6vq9EK7jgc5oUOM9RZWvXOMdJH PCNQ== X-Forwarded-Encrypted: i=1; AJvYcCVaqes+wAGLNYDY/jl+bNCVJJhGq9ag8xjE0k1czyqB6qQYaaPexmjUxc1jlBZMQJE7gmD71M7nYvAh1eA=@vger.kernel.org X-Gm-Message-State: AOJu0YwVa+lNOOTYHR9smVsyiRMJnGZJ5dpQw63fS/Iu4MmxcaD7yyN4 d54uQy5wehOEOJ3d4MqxOm4aemkuZGH4jLVGVzUWpMeqHbY+8V+4 X-Gm-Gg: ASbGncv/cvwRQSwdNkFPlf4RilRKoOe+N8o4oEArCWOI4wtH2T7d4BsYp63huhMyjZa Wm6tgBZ/aDl/T8ufS/XljontvUI/Lfyn7IK0t3+gXZnnPzak/ntgVCLdweiobwtgiitlJprua6E QJW7flsTRK79ZHLRi7hTnxiQbAowAzu0a1MYJdYOMXSpPjeD9nGdnqsLWc8BB+dXIzbc4nN2g+8 TmXhfnChV0MtTysr2rgwvC9E2icYdz7iUL/zT60vioT60oluzTqejJaN546eJmiYUmWfv2RNtg5 ie/gBR9MKrCIoSQo3A== X-Google-Smtp-Source: AGHT+IG1ZmDjPTVP9m7Ze/D8DKfeL8z6cLrGwEJyuKNK1w3jBVvYy5CX24KspIt6i8rcja5vkrkxLw== X-Received: by 2002:a05:6000:400f:b0:38f:3ee5:fd36 with SMTP id ffacd0b85a97d-38f3ee5ff31mr7979577f8f.53.1739873554174; Tue, 18 Feb 2025 02:12:34 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:33 -0800 (PST) From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= To: louis.chauvet@bootlin.com Cc: hamohammed.sa@gmail.com, simona@ffwll.ch, melissa.srw@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Subject: [PATCH v4 12/14] drm/vkms: Allow to attach encoders and CRTCs Date: Tue, 18 Feb 2025 11:12:12 +0100 Message-ID: <20250218101214.5790-13-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-1-jose.exposito89@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a list of possible CRTCs to the encoder configuration and helpers to attach and detach them. Now that the default configuration has its encoder and CRTC correctly attached, configure the output following the configuration. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 125 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 82 ++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 29 ++++ drivers/gpu/drm/vkms/vkms_output.c | 49 ++++--- 5 files changed, 266 insertions(+), 20 deletions(-) diff --git a/.clang-format b/.clang-format index c355a2f58eed..5d21c0e4edbd 100644 --- a/.clang-format +++ b/.clang-format @@ -693,6 +693,7 @@ ForEachMacros: - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_encoder' - 'vkms_config_for_each_plane' + - 'vkms_config_encoder_for_each_possible_crtc' - 'vkms_config_plane_for_each_possible_crtc' - 'while_for_each_ftrace_op' - 'xa_for_each' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index fa8b4f23cb49..600f563dd0a8 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -312,6 +312,7 @@ static void vkms_config_test_valid_plane_type(struct ku= nit *test) struct vkms_config *config; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; int err; =20 config =3D vkms_config_default_create(false, false, false); @@ -365,6 +366,9 @@ static void vkms_config_test_valid_plane_type(struct ku= nit *test) =20 /* Invalid: Second CRTC without primary plane */ crtc_cfg =3D vkms_config_create_crtc(config); + encoder_cfg =3D vkms_config_create_encoder(config); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 /* Valid: Second CRTC with a primary plane */ @@ -442,11 +446,57 @@ static void vkms_config_test_invalid_encoder_number(s= truct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *te= st) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_encoder *encoder_cfg; + int err; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + crtc_cfg1 =3D get_first_crtc(config); + + /* Invalid: Encoder without a possible CRTC */ + encoder_cfg =3D vkms_config_create_encoder(config); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: Second CRTC with shared encoder */ + crtc_cfg2 =3D vkms_config_create_crtc(config); + + plane_cfg =3D vkms_config_create_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg1); + KUNIT_EXPECT_EQ(test, err, 0); + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Invalid: Second CRTC without encoders */ + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg2); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: First CRTC with 2 possible encoder */ + vkms_config_destroy_plane(plane_cfg); + vkms_config_destroy_crtc(config, crtc_cfg2); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_attach_different_configs(struct kunit *test) { struct vkms_config *config1, *config2; struct vkms_config_plane *plane_cfg1, *plane_cfg2; struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; int err; =20 config1 =3D vkms_config_create("test1"); @@ -457,20 +507,29 @@ static void vkms_config_test_attach_different_configs= (struct kunit *test) =20 plane_cfg1 =3D vkms_config_create_plane(config1); crtc_cfg1 =3D vkms_config_create_crtc(config1); + encoder_cfg1 =3D vkms_config_create_encoder(config1); =20 plane_cfg2 =3D vkms_config_create_plane(config2); crtc_cfg2 =3D vkms_config_create_crtc(config2); + encoder_cfg2 =3D vkms_config_create_encoder(config2); =20 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2); =20 err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2); KUNIT_EXPECT_NE(test, err, 0); err =3D vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg1); KUNIT_EXPECT_NE(test, err, 0); =20 + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2); + KUNIT_EXPECT_NE(test, err, 0); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg1); + KUNIT_EXPECT_NE(test, err, 0); + vkms_config_destroy(config1); vkms_config_destroy(config2); } @@ -600,6 +659,70 @@ static void vkms_config_test_plane_get_possible_crtcs(= struct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + int n_crtcs =3D 0; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + encoder_cfg1 =3D vkms_config_create_encoder(config); + encoder_cfg2 =3D vkms_config_create_encoder(config); + crtc_cfg1 =3D vkms_config_create_crtc(config); + crtc_cfg2 =3D vkms_config_create_crtc(config); + + /* No possible CRTCs */ + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* Encoder 1 attached to CRTC 1 and 2 */ + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg1); + KUNIT_EXPECT_EQ(test, err, 0); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1 && possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 2); + n_crtcs =3D 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* Encoder 1 attached to CRTC 1 and encoder 2 to CRTC 2 */ + vkms_config_encoder_detach_crtc(encoder_cfg1, crtc_cfg2); + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + n_crtcs =3D 0; + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + + vkms_config_destroy(config); +} + static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_empty_config), KUNIT_CASE_PARAM(vkms_config_test_default_config, @@ -612,9 +735,11 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_crtc_number), KUNIT_CASE(vkms_config_test_invalid_encoder_number), + KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), KUNIT_CASE(vkms_config_test_attach_different_configs), KUNIT_CASE(vkms_config_test_plane_attach_crtc), KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs), + KUNIT_CASE(vkms_config_test_encoder_get_possible_crtcs), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index db8be054f6f4..17262a9c2567 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -86,6 +86,9 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, if (IS_ERR(encoder_cfg)) goto err_alloc; =20 + if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -216,6 +219,42 @@ static bool valid_encoder_number(const struct vkms_con= fig *config) return true; } =20 +static bool valid_encoder_possible_crtcs(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; + + vkms_config_for_each_encoder(config, encoder_cfg) { + if (xa_empty(&encoder_cfg->possible_crtcs)) { + drm_info(dev, "All encoders must have at least one possible CRTC\n"); + return false; + } + } + + vkms_config_for_each_crtc(config, crtc_cfg) { + bool crtc_has_encoder =3D false; + + vkms_config_for_each_encoder(config, encoder_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, + idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + crtc_has_encoder =3D true; + } + } + + if (!crtc_has_encoder) { + drm_info(dev, "All CRTCs must have at least one possible encoder\n"); + return false; + } + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -237,6 +276,9 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig) return false; } =20 + if (!valid_encoder_possible_crtcs(config)) + return false; + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -362,10 +404,14 @@ void vkms_config_destroy_crtc(struct vkms_config *con= fig, struct vkms_config_crtc *crtc_cfg) { struct vkms_config_plane *plane_cfg; + struct vkms_config_encoder *encoder_cfg; =20 vkms_config_for_each_plane(config, plane_cfg) vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); =20 + vkms_config_for_each_encoder(config, encoder_cfg) + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } @@ -425,6 +471,8 @@ struct vkms_config_encoder *vkms_config_create_encoder(= struct vkms_config *confi return ERR_PTR(-ENOMEM); =20 encoder_cfg->config =3D config; + xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); + list_add_tail(&encoder_cfg->link, &config->encoders); =20 return encoder_cfg; @@ -434,7 +482,41 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); void vkms_config_destroy_encoder(struct vkms_config *config, struct vkms_config_encoder *encoder_cfg) { + xa_destroy(&encoder_cfg->possible_crtcs); list_del(&encoder_cfg->link); kfree(encoder_cfg); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); + +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *encoder_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + u32 crtc_idx =3D 0; + + if (encoder_cfg->config !=3D crtc_cfg->config) + return -EINVAL; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crt= c) { + if (possible_crtc =3D=3D crtc_cfg) + return -EEXIST; + } + + return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc); + +void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_c= fg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crt= c) { + if (possible_crtc =3D=3D crtc_cfg) + xa_erase(&encoder_cfg->possible_crtcs, idx); + } +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 024cbed0e439..3e5b2e407378 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -76,6 +76,7 @@ struct vkms_config_crtc { * * @link: Link to the others encoders in vkms_config * @config: The vkms_config this CRTC belongs to + * @possible_crtcs: Array of CRTCs that can be used with this encoder * @encoder: Internal usage. This pointer should never be considered as va= lid. * It can be used to store a temporary reference to a VKMS encod= er * during device creation. This pointer is not managed by the @@ -85,6 +86,8 @@ struct vkms_config_encoder { struct list_head link; struct vkms_config *config; =20 + struct xarray possible_crtcs; + /* Internal usage */ struct drm_encoder *encoder; }; @@ -123,6 +126,16 @@ struct vkms_config_encoder { #define vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_= crtc) \ xa_for_each(&(plane_cfg)->possible_crtcs, idx, (possible_crtc)) =20 +/** + * vkms_config_encoder_for_each_possible_crtc - Iterate over the + * vkms_config_encoder possible CRTCs + * @encoder_cfg: &struct vkms_config_encoder pointer + * @idx: Index of the cursor + * @possible_crtc: &struct vkms_config_crtc pointer used as cursor + */ +#define vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possi= ble_crtc) \ + xa_for_each(&(encoder_cfg)->possible_crtcs, idx, (possible_crtc)) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -332,4 +345,20 @@ struct vkms_config_encoder *vkms_config_create_encoder= (struct vkms_config *confi void vkms_config_destroy_encoder(struct vkms_config *config, struct vkms_config_encoder *encoder_cfg); =20 +/** + * vkms_config_encoder_attach_crtc - Attach a encoder to a CRTC + * @encoder_cfg: Encoder to attach + * @crtc_cfg: CRTC to attach @encoder_cfg to + */ +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *encoder_cfg, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_encoder_detach_crtc - Detach a encoder from a CRTC + * @encoder_cfg: Encoder to detach + * @crtc_cfg: CRTC to detach @encoder_cfg from + */ +void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_c= fg, + struct vkms_config_crtc *crtc_cfg); + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index f63bc8e3014b..8920d6b5d105 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -9,9 +9,9 @@ int vkms_output_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; struct vkms_connector *connector; - struct drm_encoder *encoder; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; int ret; int writeback; =20 @@ -61,32 +61,41 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } =20 + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + encoder_cfg->encoder =3D drmm_kzalloc(dev, sizeof(*encoder_cfg->encoder)= , GFP_KERNEL); + if (!encoder_cfg->encoder) { + DRM_ERROR("Failed to allocate encoder\n"); + return -ENOMEM; + } + ret =3D drmm_encoder_init(dev, encoder_cfg->encoder, NULL, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) { + DRM_ERROR("Failed to init encoder\n"); + return ret; + } + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_cr= tc) { + encoder_cfg->encoder->possible_crtcs |=3D + drm_crtc_mask(&possible_crtc->crtc->crtc); + } + } + connector =3D vkms_connector_init(vkmsdev); if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); return PTR_ERR(connector); } =20 - encoder =3D drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); - if (!encoder) { - DRM_ERROR("Failed to allocate encoder\n"); - return -ENOMEM; - } - ret =3D drmm_encoder_init(dev, encoder, NULL, - DRM_MODE_ENCODER_VIRTUAL, NULL); - if (ret) { - DRM_ERROR("Failed to init encoder\n"); - return ret; - } - - vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) - encoder->possible_crtcs =3D drm_crtc_mask(&crtc_cfg->crtc->crtc); - /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(&connector->base, encoder); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - return ret; + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { + ret =3D drm_connector_attach_encoder(&connector->base, encoder_cfg->enco= der); + if (ret) { + DRM_ERROR("Failed to attach connector to encoder\n"); + return ret; + } } =20 drm_mode_config_reset(dev); --=20 2.48.1