From nobody Sun Dec 14 22:11:52 2025 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFAC11B5831 for ; Wed, 14 Aug 2024 14:36:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723646205; cv=none; b=ZGVFyAoZvQTmdeuEco0mM+unQysYCLu0SeL0dWH2fvd9e5EyBaNqsUSbzvVQMBXlNcnRxfrJI/qWMmVNKO/FKIhBZ18LcVx1ZIxhrjLg1XkNuwqtVBLqvVmRc3roeoN42tS+Pr0dFhjCTVKLbz5deEUiGi0oZnu46Q0tjon9QKs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723646205; c=relaxed/simple; bh=46j34JKKy712RzuP5JY2IZ6oP0Ml2QvEJ9sWjcs6B+Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DxF27m0dyDXkaZKTkzPUBb7CHrJP1mvceYcpACk1fFb+TPbatg5GUYsuiASI9v/+i6A0/kjguJ7MwNqrJMdd1Fz9Hx35owS8ddTEmmILhlO1rhDXKRG813tMp96XWT2aKhPiY+Ibe7NHXMP4wBLgdEwj+lMbVlBEfsQkZckHNo4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=HgqOgMPN; arc=none smtp.client-ip=217.70.183.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="HgqOgMPN" Received: by mail.gandi.net (Postfix) with ESMTPSA id 7468D1C0002; Wed, 14 Aug 2024 14:36:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1723646201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hi1TEW7eGWLARBXasnPACvRwfa310YzOI/mLeLTA3eY=; b=HgqOgMPN2QYNm/a9KHW28iVFp0/evBz1pU97MyT9JHeE7AbAnHZdswcL7fHjzIGjz2YqCV qSvIRFZ2aCjXilvd1LKQLemFIIPwCkgOgmds7PZWodSzYk2HusLfB5tUNBZCk25DA5/fGp diFMcyGcEh2XLYvBbQNsAQCTyZnXlHOLpMNgE3mGA8I5ZNMXvyRHaddnekBmfCKvRp02vm Lq0rNxLX2VJSZD5kSndmZomyXYmUKaUAlLSUjxxLuacbKML0b5SnmGM+J0MOZYdJvOIERq uWjlRiVqsP2H3XVz2R/B/566qmEYqwafGZ99Mbcga+P4EoRQJvSf5xpJwFPdJA== From: Louis Chauvet Date: Wed, 14 Aug 2024 16:36:34 +0200 Subject: [PATCH RFC 12/15] drm/vkms: Add configuration for CRTCs and encoders 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 Message-Id: <20240814-google-remove-crtc-index-from-parameter-v1-12-6e179abf9fd4@bootlin.com> References: <20240814-google-remove-crtc-index-from-parameter-v1-0-6e179abf9fd4@bootlin.com> In-Reply-To: <20240814-google-remove-crtc-index-from-parameter-v1-0-6e179abf9fd4@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie Cc: dri-devel@lists.freedesktop.org, arthurgrillo@riseup.net, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=23979; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=46j34JKKy712RzuP5JY2IZ6oP0Ml2QvEJ9sWjcs6B+Y=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBmvMDr8ZdUaO0h2dEAzSwdtgIh/pJFagSx51udc tqOsworcY2JAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZrzA6wAKCRAgrS7GWxAs 4l71EADORjvvKFvJ8IVvxSpM5ZJbfDegj+kmCq8vCDyynUQzHwYb4Y/KJjtz7ok4wCoTUvofz9s h3kuyWUh8tBQGZsLSCH24iVnNb2PLplUcJ/JKuOXTd+zCAi25UdRlpU9f+cik3tlYlanD2lSPBo OaWEE+GvODUAx15qXqRhiS6VWRllzXyay8q8s0AFq2hiAAnYNGas6I7wplm8+g+2kmOFl1Vj/LI Sk5UzmQrVC/v8tLww7TO24LNOU9rBAoXCMmxKBHxoJgRePnd7xSgr2pppT1oyHF10KnYL9l+PZH d2aKojUfVSzHxnc3d3gmIjEu9woGWInHwo2mFLhP65YnVJs//Ukhm6isWnaARhTvy8Zsr2VuhnI Zy39S5QdOHXP3WXLR4eUdeXic5JS0MSDYIJAvIBDhj7aU0UondyPsh0jvd7HutcGOi0bVayTDUv ifk1rGyPVQuZzVx4Wi7giiOTPKAPv8Y//VOOD5f7KYvZfYHPNfq4D5jYEJEJNpgQ0+e7KEkuDq5 HxOTXSeP8PO57moZa8O6TpaX+wCbNozJGkJcVRZF6PCu9aWFKTnrXP4n4qFgkg4TJ7N69fucjwS RHy1ZOAb85PNhCKuY1wf713nx1V2aHKE5lgKbfFwDP7On6J3cphECRrMakDH0e6NCZC1nOw1BHc AGeK1ygFOX8ZFoQ== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com The current VKMS driver can only uses one CRTC and one encoder. This patch introduce in the same time CRTC and encoders as they are tighly linked. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_config.c | 266 +++++++++++++++++++++++++++++++++= ---- drivers/gpu/drm/vkms/vkms_config.h | 102 +++++++++++++- drivers/gpu/drm/vkms/vkms_crtc.c | 20 ++- drivers/gpu/drm/vkms/vkms_crtc.h | 3 +- drivers/gpu/drm/vkms/vkms_drv.c | 87 ++++++------ 5 files changed, 405 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index e9e30974523a..fcd4a128c21b 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -14,6 +14,8 @@ struct vkms_config *vkms_config_create(void) return ERR_PTR(-ENOMEM); =20 INIT_LIST_HEAD(&config->planes); + INIT_LIST_HEAD(&config->crtcs); + INIT_LIST_HEAD(&config->encoders); =20 return config; } @@ -22,12 +24,24 @@ struct vkms_config *vkms_config_alloc_default(bool enab= le_writeback, bool enable bool enable_cursor) { struct vkms_config_plane *plane; + struct vkms_config_encoder *encoder; + struct vkms_config_crtc *crtc; struct vkms_config *vkms_config =3D vkms_config_create(); =20 if (IS_ERR(vkms_config)) return vkms_config; =20 - vkms_config->writeback =3D enable_writeback; + crtc =3D vkms_config_create_crtc(vkms_config); + if (!crtc) + goto err_alloc; + crtc->writeback =3D enable_writeback; + + encoder =3D vkms_config_create_encoder(vkms_config); + if (!encoder) + goto err_alloc; + + if (vkms_config_encoder_attach_crtc(encoder, crtc)) + goto err_alloc; =20 plane =3D vkms_config_create_plane(vkms_config); if (!plane) @@ -39,6 +53,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable= _writeback, bool enable goto err_alloc; sprintf(plane->name, "primary"); =20 + if (vkms_config_plane_attach_crtc(plane, crtc)) + goto err_alloc; + if (enable_overlay) { for (int i =3D 0; i < NUM_OVERLAY_PLANES; i++) { plane =3D vkms_config_create_plane(vkms_config); @@ -49,6 +66,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable= _writeback, bool enable if (!plane->name) goto err_alloc; snprintf(plane->name, 10, "plane-%d", i); + + if (vkms_config_plane_attach_crtc(plane, crtc)) + goto err_alloc; } } if (enable_cursor) { @@ -60,6 +80,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable= _writeback, bool enable if (!plane->name) goto err_alloc; sprintf(plane->name, "cursor"); + + if (vkms_config_plane_attach_crtc(plane, crtc)) + goto err_alloc; } =20 return vkms_config; @@ -89,38 +112,196 @@ struct vkms_config_plane *vkms_config_create_plane(st= ruct vkms_config *vkms_conf vkms_config_overlay->supported_color_range =3D BIT(DRM_COLOR_YCBCR_LIMITE= D_RANGE) | BIT(DRM_COLOR_YCBCR_FULL_RANGE); vkms_config_overlay->default_color_range =3D DRM_COLOR_YCBCR_FULL_RANGE; + xa_init_flags(&vkms_config_overlay->possible_crtcs, XA_FLAGS_ALLOC); =20 list_add(&vkms_config_overlay->link, &vkms_config->planes); =20 return vkms_config_overlay; } =20 -void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_overla= y) +struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *vkms_= config) { - if (!vkms_config_overlay) + if (!vkms_config) + return NULL; + + struct vkms_config_crtc *vkms_config_crtc =3D kzalloc(sizeof(*vkms_config= _crtc), + GFP_KERNEL); + + if (!vkms_config_crtc) + return NULL; + + list_add(&vkms_config_crtc->link, &vkms_config->crtcs); + xa_init_flags(&vkms_config_crtc->possible_planes, XA_FLAGS_ALLOC); + xa_init_flags(&vkms_config_crtc->possible_encoders, XA_FLAGS_ALLOC); + + return vkms_config_crtc; +} + +struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config = *vkms_config) +{ + if (!vkms_config) + return NULL; + + struct vkms_config_encoder *vkms_config_encoder =3D kzalloc(sizeof(*vkms_= config_encoder), + GFP_KERNEL); + + if (!vkms_config_encoder) + return NULL; + + list_add(&vkms_config_encoder->link, &vkms_config->encoders); + xa_init_flags(&vkms_config_encoder->possible_crtcs, XA_FLAGS_ALLOC); + + return vkms_config_encoder; +} + +void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane, + struct vkms_config *vkms_config) +{ + struct vkms_config_crtc *crtc_config; + struct vkms_config_plane *plane; + + if (!vkms_config_plane) + return; + list_del(&vkms_config_plane->link); + xa_destroy(&vkms_config_plane->possible_crtcs); + + list_for_each_entry(crtc_config, &vkms_config->crtcs, link) { + unsigned long idx =3D 0; + + xa_for_each(&crtc_config->possible_planes, idx, plane) { + if (plane =3D=3D vkms_config_plane) + xa_erase(&crtc_config->possible_planes, idx); + } + } + + kfree(vkms_config_plane->name); + kfree(vkms_config_plane); +} + +void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc, + struct vkms_config *vkms_config) +{ + struct vkms_config_crtc *crtc_config; + struct vkms_config_plane *plane_config; + struct vkms_config_encoder *encoder_config; + + if (!vkms_config_crtc) + return; + list_del(&vkms_config_crtc->link); + xa_destroy(&vkms_config_crtc->possible_planes); + xa_destroy(&vkms_config_crtc->possible_encoders); + + list_for_each_entry(plane_config, &vkms_config->planes, link) { + unsigned long idx =3D 0; + + xa_for_each(&plane_config->possible_crtcs, idx, crtc_config) { + if (crtc_config =3D=3D vkms_config_crtc) + xa_erase(&plane_config->possible_crtcs, idx); + } + } + + list_for_each_entry(encoder_config, &vkms_config->encoders, link) { + unsigned long idx =3D 0; + + xa_for_each(&encoder_config->possible_crtcs, idx, crtc_config) { + if (crtc_config =3D=3D vkms_config_crtc) + xa_erase(&encoder_config->possible_crtcs, idx); + } + } + + kfree(vkms_config_crtc); +} + +void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_en= coder, + struct vkms_config *vkms_config) +{ + if (!vkms_config_encoder) return; - list_del(&vkms_config_overlay->link); - kfree(vkms_config_overlay->name); - kfree(vkms_config_overlay); + list_del(&vkms_config_encoder->link); + xa_destroy(&vkms_config_encoder->possible_crtcs); + + struct vkms_config_crtc *crtc_config; + struct vkms_config_encoder *encoder; + + list_for_each_entry(crtc_config, &vkms_config->crtcs, link) { + unsigned long idx =3D 0; + + xa_for_each(&crtc_config->possible_encoders, idx, encoder) { + if (encoder =3D=3D vkms_config_encoder) + xa_erase(&crtc_config->possible_encoders, idx); + } + } + + kfree(vkms_config_encoder); } =20 void vkms_config_destroy(struct vkms_config *config) { struct vkms_config_plane *vkms_config_plane, *tmp_plane; + struct vkms_config_encoder *vkms_config_encoder, *tmp_encoder; + struct vkms_config_crtc *vkms_config_crtc, *tmp_crtc; + =20 list_for_each_entry_safe(vkms_config_plane, tmp_plane, &config->planes, l= ink) { - vkms_config_delete_plane(vkms_config_plane); + vkms_config_delete_plane(vkms_config_plane, config); + } + list_for_each_entry_safe(vkms_config_encoder, tmp_encoder, &config->encod= ers, link) { + vkms_config_delete_encoder(vkms_config_encoder, config); + } + list_for_each_entry_safe(vkms_config_crtc, tmp_crtc, &config->crtcs, link= ) { + vkms_config_delete_crtc(vkms_config_crtc, config); } =20 kfree(config); } =20 +int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *v= kms_config_plane, + struct vkms_config_crtc *vkms_config_crtc) +{ + u32 crtc_idx, encoder_idx; + int ret; + + ret =3D xa_alloc(&vkms_config_plane->possible_crtcs, &crtc_idx, vkms_conf= ig_crtc, + xa_limit_32b, GFP_KERNEL); + if (ret) + return ret; + + ret =3D xa_alloc(&vkms_config_crtc->possible_planes, &encoder_idx, vkms_c= onfig_plane, + xa_limit_32b, GFP_KERNEL); + if (ret) { + xa_erase(&vkms_config_plane->possible_crtcs, crtc_idx); + return ret; + } + + return ret; +} + +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *vkms_config_encoder, + struct vkms_config_crtc *vkms_config_crtc) +{ + u32 crtc_idx, encoder_idx; + int ret; + + ret =3D xa_alloc(&vkms_config_encoder->possible_crtcs, &crtc_idx, vkms_co= nfig_crtc, + xa_limit_32b, GFP_KERNEL); + if (ret) + return ret; + + ret =3D xa_alloc(&vkms_config_crtc->possible_encoders, &encoder_idx, vkms= _config_encoder, + xa_limit_32b, GFP_KERNEL); + if (ret) { + xa_erase(&vkms_config_encoder->possible_crtcs, crtc_idx); + return ret; + } + + return ret; +} + bool vkms_config_is_valid(struct vkms_config *config) { struct vkms_config_plane *config_plane; - - bool has_cursor =3D false; - bool has_primary =3D false; + struct vkms_config_crtc *config_crtc; + struct vkms_config_encoder *config_encoder; =20 list_for_each_entry(config_plane, &config->planes, link) { // Default rotation not in supported rotations @@ -141,22 +322,47 @@ bool vkms_config_is_valid(struct vkms_config *config) BIT(config_plane->default_color_range)) return false; =20 - if (config_plane->type =3D=3D DRM_PLANE_TYPE_PRIMARY) { - // Multiple primary planes for only one CRTC - if (has_primary) - return false; - has_primary =3D true; - } - if (config_plane->type =3D=3D DRM_PLANE_TYPE_CURSOR) { - // Multiple cursor planes for only one CRTC - if (has_cursor) - return false; - has_cursor =3D true; - } + // No CRTC linked to this plane + if (xa_empty(&config_plane->possible_crtcs)) + return false; + } + + list_for_each_entry(config_encoder, &config->encoders, link) { + // No CRTC linked to this encoder + if (xa_empty(&config_encoder->possible_crtcs)) + return false; } =20 - if (!has_primary) - return false; + list_for_each_entry(config_crtc, &config->crtcs, link) { + bool has_primary =3D false; + bool has_cursor =3D false; + unsigned long idx =3D 0; + + // No encoder attached to this CRTC + if (xa_empty(&config_crtc->possible_encoders)) + return false; + + xa_for_each(&config_crtc->possible_planes, idx, config_plane) { + if (config_plane->type =3D=3D DRM_PLANE_TYPE_PRIMARY) { + // Multiple primary planes for only one CRTC + if (has_primary) + return false; + + has_primary =3D true; + } + if (config_plane->type =3D=3D DRM_PLANE_TYPE_CURSOR) { + // Multiple cursor planes for only one CRTC + if (has_cursor) + return false; + + has_cursor =3D true; + } + } + + // No primary plane for this CRTC + if (!has_primary) + return false; + } =20 return true; } @@ -167,8 +373,9 @@ static int vkms_config_show(struct seq_file *m, void *d= ata) struct drm_device *dev =3D entry->dev; struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); struct vkms_config_plane *config_plane; + struct vkms_config_crtc *config_crtc; + struct vkms_config_encoder *config_encoder; =20 - seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); list_for_each_entry(config_plane, &vkmsdev->config->planes, link) { seq_puts(m, "plane:\n"); seq_printf(m, "\tname: %s\n", config_plane->name); @@ -185,6 +392,15 @@ static int vkms_config_show(struct seq_file *m, void *= data) config_plane->default_color_range); } =20 + list_for_each_entry(config_encoder, &vkmsdev->config->encoders, link) { + seq_puts(m, "encoder:\n"); + } + + list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) { + seq_puts(m, "crtc:\n"); + seq_printf(m, "\twriteback: %d\n", config_crtc->writeback); + } + return 0; } =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index d668aeab9d26..8f247fc09373 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -9,16 +9,59 @@ /** * struct vkms_config - General configuration for VKMS driver * - * @writeback: If true, a writeback buffer can be attached to the CRTC * @planes: List of planes configured for this device. They are created by= the function * vkms_config_create_plane(). + * @crtcs: List of crtcs configured for this device. They are created by t= he function + * vkms_config_create_crtc(). + * @encoders: List of encoders configured for this device. They are create= d by the function + * vkms_config_create_encoder(). * @dev: Used to store the current vkms device. Only set when the device i= s instancied. */ struct vkms_config { - bool writeback; struct vkms_device *dev; =20 struct list_head planes; + struct list_head crtcs; + struct list_head encoders; +}; + +/** + * struct vkms_config_crtc + * + * @link: Link to the others CRTCs + * @possible_planes: List of planes that can be used with this CRTC + * @possible_encoders: List of encoders that can be used with this CRTC + * @crtc: Internal usage. This pointer should never be considered as valid= . It can be used to + * store a temporary reference to a vkms crtc during device creati= on. This pointer is + * not managed by the configuration and must be managed by other m= eans. + */ +struct vkms_config_crtc { + struct list_head link; + + bool writeback; + struct xarray possible_planes; + struct xarray possible_encoders; + + /* Internal usage */ + struct vkms_crtc *crtc; +}; + +/** + * struct vkms_config_encoder + * + * @link: Link to the others encoders + * @possible_crtcs: List of CRTC 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 encoder during device cre= ation. This pointer is + * not managed by the configuration and must be managed by other m= eans. + */ +struct vkms_config_encoder { + struct list_head link; + + struct xarray possible_crtcs; + + /* Internal usage */ + struct drm_encoder *encoder; }; =20 /** @@ -34,6 +77,7 @@ struct vkms_config { * @supported_color_encoding: Color encoding that this plane will support * @default_color_range: Default color range that should be used by this p= lane * @supported_color_range: Color range that this plane will support + * @possible_crtcs: List of CRTC that can be used with this plane. * @plane: Internal usage. This pointer should never be considered as vali= d. It can be used to * store a temporary reference to a vkms plane during device creat= ion. This pointer is * not managed by the configuration and must be managed by other m= eans. @@ -50,6 +94,7 @@ struct vkms_config_plane { enum drm_color_range default_color_range; unsigned int supported_color_range; =20 + struct xarray possible_crtcs; /* Internal usage */ struct vkms_plane *plane; }; @@ -84,14 +129,63 @@ bool vkms_config_is_valid(struct vkms_config *vkms_con= fig); */ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkm= s_config); =20 +/** + * vkms_config_create_crtc() - Create a crtc configuration + * + * This will allocate and add a new crtc configuration to @vkms_config. + * @vkms_config: Configuration where to insert new crtc configuration + */ +struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *vkms_= config); + +/** + * vkms_config_create_encoder() - Create an encoder configuration + * + * This will allocate and add a new encoder configuration to @vkms_config. + * @vkms_config: Configuration where to insert new encoder configuration + */ +struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config = *vkms_config); + +int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *v= kms_config_plane, + struct vkms_config_crtc *vkms_config_crtc); +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *vkms_config_encoder, + struct vkms_config_crtc *vkms_config_crtc); + /** * vkms_config_delete_plane() - Remove a plane configuration and frees its= memory * * This will delete a plane configuration from the parent configuration. T= his will NOT - * cleanup and frees the vkms_plane that can be stored in @vkms_config_pla= ne. + * cleanup and frees the vkms_plane that can be stored in @vkms_config_pla= ne. It will also remove + * any reference to this plane in @vkms_config. + * * @vkms_config_plane: Plane configuration to cleanup + * @vkms_config: Parent configuration + */ +void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane, + struct vkms_config *vkms_config); +/** + * vkms_config_delete_crtc() - Remove a CRTC configuration and frees its m= emory + * + * This will delete a CRTC configuration from the parent configuration. Th= is will NOT + * cleanup and frees the vkms_crtc that can be stored in @vkms_config_crtc= . It will also remove + * any reference to this CRTC in @vkms_config. + * + * @vkms_config_crtc: Plane configuration to cleanup + * @vkms_config: Parent configuration + */ +void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc, + struct vkms_config *vkms_config); +/** + * vkms_config_delete_encoder() - Remove an encoder configuration and free= s its memory + * + * This will delete an encoder configuration from the parent configuration= . This will NOT + * cleanup and frees the vkms_encoder that can be stored in @vkms_config_e= ncoder. It will also + * remove any reference to this CRTC in @vkms_config. + * + * @vkms_config_encoder: Plane configuration to cleanup + * @vkms_config: Parent configuration */ -void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane); +void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_en= coder, + struct vkms_config *vkms_config); =20 /** * vkms_config_alloc_default() - Allocate the configuration for the defaul= t device diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_c= rtc.c index 6f6d3118b2f2..654238dbba7f 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -281,9 +281,17 @@ static void vkms_crtc_destroy_workqueue(struct drm_dev= ice *dev, void *raw_vkms_c destroy_workqueue(vkms_crtc->composer_workq); } =20 +static void vkms_crtc_cleanup_writeback_connector(struct drm_device *dev, = void *data) +{ + struct vkms_crtc *vkms_crtc =3D data; + + drm_writeback_connector_cleanup(&vkms_crtc->wb_connector); +} + struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, - struct drm_plane *cursor) + struct drm_plane *cursor, + struct vkms_config_crtc *config) { struct drm_device *dev =3D &vkmsdev->drm; struct vkms_crtc *vkms_crtc; @@ -317,5 +325,15 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *v= kmsdev, if (ret) return ERR_PTR(ret); =20 + if (config->writeback) { + ret =3D vkms_enable_writeback_connector(vkmsdev, vkms_crtc); + if (ret) + return ERR_PTR(ret); + ret =3D drmm_add_action_or_reset(&vkmsdev->drm, vkms_crtc_cleanup_writeb= ack_connector, + vkms_crtc); + if (ret) + return ERR_PTR(ret); + } + return vkms_crtc; } diff --git a/drivers/gpu/drm/vkms/vkms_crtc.h b/drivers/gpu/drm/vkms/vkms_c= rtc.h index dde28884a0a5..a271e95f1cfe 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.h +++ b/drivers/gpu/drm/vkms/vkms_crtc.h @@ -86,5 +86,6 @@ struct vkms_crtc { */ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, - struct drm_plane *cursor); + struct drm_plane *cursor, + struct vkms_config_crtc *config); #endif //_VKMS_CRTC_H diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index 403006a0bb61..6deff5099322 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -153,13 +153,12 @@ static const struct drm_connector_helper_funcs vkms_c= onn_helper_funcs =3D { =20 static int vkms_output_init(struct vkms_device *vkmsdev) { - struct vkms_config_plane *config_plane; + struct vkms_config_encoder *config_encoder; struct drm_device *dev =3D &vkmsdev->drm; + struct vkms_config_plane *config_plane; + struct vkms_config_crtc *config_crtc; struct drm_connector *connector; - struct drm_encoder *encoder; - struct vkms_crtc *crtc; - struct drm_plane *plane; - struct vkms_plane *primary, *cursor =3D NULL; + unsigned long idx; int ret; int writeback; =20 @@ -169,22 +168,30 @@ static int vkms_output_init(struct vkms_device *vkmsd= ev) ret =3D PTR_ERR(config_plane->plane); return ret; } - - if (config_plane->type =3D=3D DRM_PLANE_TYPE_PRIMARY) - primary =3D config_plane->plane; - else if (config_plane->type =3D=3D DRM_PLANE_TYPE_CURSOR) - cursor =3D config_plane->plane; } =20 - /* [1]: Initialize the crtc component */ - crtc =3D vkms_crtc_init(vkmsdev, &primary->base, - cursor ? &cursor->base : NULL); - if (IS_ERR(crtc)) - return PTR_ERR(crtc); + list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) { + struct drm_plane *primary =3D NULL, *cursor =3D NULL; + + xa_for_each(&config_crtc->possible_planes, idx, config_plane) { + if (config_plane->type =3D=3D DRM_PLANE_TYPE_PRIMARY) + primary =3D &config_plane->plane->base; + else if (config_plane->type =3D=3D DRM_PLANE_TYPE_CURSOR) + cursor =3D &config_plane->plane->base; + } + + config_crtc->crtc =3D vkms_crtc_init(vkmsdev, primary, cursor, config_cr= tc); =20 - /* Enable the output's CRTC for all the planes */ - drm_for_each_plane(plane, &vkmsdev->drm) { - plane->possible_crtcs |=3D drm_crtc_mask(&crtc->base); + if (IS_ERR(config_crtc->crtc)) { + ret =3D PTR_ERR(config_crtc->crtc); + return ret; + } + } + + list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) { + xa_for_each(&config_crtc->possible_planes, idx, config_plane) { + config_plane->plane->base.possible_crtcs |=3D drm_crtc_mask(&config_crt= c->crtc->base); + } } =20 /* Initialize the connector component */ @@ -201,32 +208,28 @@ static int vkms_output_init(struct vkms_device *vkmsd= ev) =20 drm_connector_helper_add(connector, &vkms_conn_helper_funcs); =20 - /* Initialize the encoder component */ - encoder =3D drmm_kzalloc(&vkmsdev->drm, sizeof(*encoder), GFP_KERNEL); - if (!encoder) - return -ENOMEM; - - ret =3D drmm_encoder_init(dev, encoder, &vkms_encoder_funcs, - DRM_MODE_ENCODER_VIRTUAL, NULL); - if (ret) { - DRM_ERROR("Failed to init encoder\n"); - return ret; - } - - encoder->possible_crtcs =3D drm_crtc_mask(&crtc->base); =20 - /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(connector, encoder); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - return ret; - } + list_for_each_entry(config_encoder, &vkmsdev->config->encoders, link) { + config_encoder->encoder =3D drmm_kzalloc(&vkmsdev->drm, + sizeof(*config_encoder->encoder), + GFP_KERNEL); + if (!config_encoder->encoder) + return -ENOMEM; + ret =3D drmm_encoder_init(dev, config_encoder->encoder, &vkms_encoder_fu= ncs, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) { + DRM_ERROR("Failed to init encoder\n"); + return ret; + } =20 - /* Initialize the writeback component */ - if (vkmsdev->config->writeback) { - writeback =3D vkms_enable_writeback_connector(vkmsdev, crtc); - if (writeback) - DRM_ERROR("Failed to init writeback connector\n"); + xa_for_each(&config_encoder->possible_crtcs, idx, config_crtc) { + config_encoder->encoder->possible_crtcs |=3D drm_crtc_mask(&config_crtc= ->crtc->base); + } + if (IS_ERR(config_encoder->encoder)) + return PTR_ERR(config_encoder->encoder); + ret =3D drm_connector_attach_encoder(connector, config_encoder->encoder); + if (ret) + return ret; } =20 drm_mode_config_reset(dev); --=20 2.44.2