From patchwork Thu Jun 6 22:40:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Siqueira X-Patchwork-Id: 10980561 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 293C776 for ; Thu, 6 Jun 2019 22:40:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 11F1428AAF for ; Thu, 6 Jun 2019 22:40:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 017B128AB7; Thu, 6 Jun 2019 22:40:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 99B3D28AAF for ; Thu, 6 Jun 2019 22:40:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CEC2189823; Thu, 6 Jun 2019 22:40:48 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ed1-x544.google.com (mail-ed1-x544.google.com [IPv6:2a00:1450:4864:20::544]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3323D89823 for ; Thu, 6 Jun 2019 22:40:47 +0000 (UTC) Received: by mail-ed1-x544.google.com with SMTP id w13so10882eds.4 for ; Thu, 06 Jun 2019 15:40:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=phnCWAxvmUCyTW6c5t2uUP0p/ctzFwDLw8hDVCeBb+I=; b=Pe6ydPqHd/cIuo4x1CN8V8GelxZk9XMOSAQq90dG1GC+4WfhFQA8TxSrRdrOZoqb0Y /xYFC38SUVQaWsrUkozK+4XZh2E7Md9NLldQfW4sNxlHxfYmQ026hYJmpHAFPo6I4bze X5iJflmrkOYPE4su12JsudRsJdqrEN5x+OlcWv28Qg9yT9TmWP24VSTSEe8ztN4740/u BMlbOxP9MEsx7XRrjP47T7Zl/DsGpsdPq79WEOwtNQke/bj3wYmn8tYc8gSG4F9o3cIw 7o0XgaM766Z8wvORe0tLZhwnKrhb+a0cuvuK4esPW5BdifMqSaeEVI79LrRU6A5usUSP Bhmw== X-Gm-Message-State: APjAAAWM/xlCpUqjbn1BRVNh4DJ/gQy79aQhE29XSkpP+Go9Es8Wwmed AMuDMke3QuTxhNC8LP/Hkh0= X-Google-Smtp-Source: APXvYqwd34GV/ljRusChb3NlKnkx4KXjGhPS4IEWP75EI54kblA3z2OYq/LyXOQnMuR/LmkDu7L3MQ== X-Received: by 2002:a17:906:2890:: with SMTP id o16mr18236138ejd.80.1559860845759; Thu, 06 Jun 2019 15:40:45 -0700 (PDT) Received: from smtp.gmail.com ([187.121.151.146]) by smtp.gmail.com with ESMTPSA id f13sm60065ejj.7.2019.06.06.15.40.41 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 06 Jun 2019 15:40:45 -0700 (PDT) Date: Thu, 6 Jun 2019 19:40:38 -0300 From: Rodrigo Siqueira To: Brian Starkey , Liviu Dudau , Daniel Vetter , Haneen Mohammed , Simon Ser Subject: [PATCH 1/2] drm/vkms: Use index instead of 0 in possible crtc Message-ID: References: MIME-Version: 1.0 In-Reply-To: User-Agent: NeoMutt/20180716 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=phnCWAxvmUCyTW6c5t2uUP0p/ctzFwDLw8hDVCeBb+I=; b=U+UmNgMJ383xno5xjEYhVlJgAAsmxRbAfZpqQ619BoqL7fIbXRBOjRPTaw0/j8CKKX VKG1i/PbbbMLuIO29fXI494Fa/qc5/KlqfV9WDEenibnqqsRUDl9J7mPNUb0K9+cC91/ 0Q8SgwIgOzNGElWxZSyyaxlBUbB4KYl9mfWXg2QU2kBqbaKN1XzKfq/G2DC0deWmyFSa 7N1V1D6hL876838zbl30hfQ3Yy9A2sI+OfZgWKPGn222hvPhSC3A9VHujtwFDWOYIIEB 0CM2sfEDQ4MVtWlAoI/L9oT6CJPZbXkhZK0JXQfCueZdvRlJhQ55bwcUxJ1iPcx9Bt7K NOew== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP When vkms calls drm_universal_plane_init(), it sets 0 for the possible_crtcs parameter which works well for a single encoder and connector; however, this approach is not flexible and does not fit well for vkms. This commit adds an index parameter for vkms_plane_init() which makes code flexible and enables vkms to support other DRM features. Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/vkms/vkms_drv.c | 2 +- drivers/gpu/drm/vkms/vkms_drv.h | 4 ++-- drivers/gpu/drm/vkms/vkms_output.c | 6 +++--- drivers/gpu/drm/vkms/vkms_plane.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 738dd6206d85..92296bd8f623 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -92,7 +92,7 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.max_height = YRES_MAX; dev->mode_config.preferred_depth = 24; - return vkms_output_init(vkmsdev); + return vkms_output_init(vkmsdev, 0); } static int __init vkms_init(void) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 81f1cfbeb936..e81073dea154 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -113,10 +113,10 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, int *max_error, ktime_t *vblank_time, bool in_vblank_irq); -int vkms_output_init(struct vkms_device *vkmsdev); +int vkms_output_init(struct vkms_device *vkmsdev, int index); struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type); + enum drm_plane_type type, int index); /* Gem stuff */ struct drm_gem_object *vkms_gem_create(struct drm_device *dev, diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 3b162b25312e..1442b447c707 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -36,7 +36,7 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = { .get_modes = vkms_conn_get_modes, }; -int vkms_output_init(struct vkms_device *vkmsdev) +int vkms_output_init(struct vkms_device *vkmsdev, int index) { struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; @@ -46,12 +46,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) struct drm_plane *primary, *cursor = NULL; int ret; - primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY); + primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index); if (IS_ERR(primary)) return PTR_ERR(primary); if (enable_cursor) { - cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR); + cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index); if (IS_ERR(cursor)) { ret = PTR_ERR(cursor); goto err_cursor; diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 0e67d2d42f0c..20ffc52f9194 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -168,7 +168,7 @@ static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = { }; struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type) + enum drm_plane_type type, int index) { struct drm_device *dev = &vkmsdev->drm; const struct drm_plane_helper_funcs *funcs; @@ -190,7 +190,7 @@ struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, funcs = &vkms_primary_helper_funcs; } - ret = drm_universal_plane_init(dev, plane, 0, + ret = drm_universal_plane_init(dev, plane, 1 << index, &vkms_plane_funcs, formats, nformats, NULL, type, NULL); From patchwork Thu Jun 6 22:41:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rodrigo Siqueira X-Patchwork-Id: 10980563 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE3E176 for ; Thu, 6 Jun 2019 22:41:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C6F3928AAF for ; Thu, 6 Jun 2019 22:41:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA90B28AB7; Thu, 6 Jun 2019 22:41:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 206F728AAF for ; Thu, 6 Jun 2019 22:41:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 50C9789A62; Thu, 6 Jun 2019 22:41:11 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ed1-x543.google.com (mail-ed1-x543.google.com [IPv6:2a00:1450:4864:20::543]) by gabe.freedesktop.org (Postfix) with ESMTPS id 847C289A62 for ; Thu, 6 Jun 2019 22:41:09 +0000 (UTC) Received: by mail-ed1-x543.google.com with SMTP id z25so5555624edq.9 for ; Thu, 06 Jun 2019 15:41:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=JhgexSOQCk69aVM20s4eSvr2Wf1I3NzyL+87Su9CLwA=; b=SrbT9P8kZZDaOowObpX/REV6Z4KE8AXP3stM5K3btOE+w1DPgmMDDoyPB2w2C0frXZ Cv+6tdTQ3ra8bFYvOkU3Vvl0aLTDAB82GX9c+DnDJRpKoLiVsCrJvNrN7RcPXqoEiQ2U i8yyugOQkJwPuXZvLgdm1G9ZZ64wquRThzAp99q/KwJmWHfu2lunZb2q6xgxuCQppvPI rhG+nRnqb3aPs3fPkVGGrI+GQN15ckdlasyqJls2OzzSu26bh4Ma9WRy8Ph3xMR7tPhp BeNEk3qx9zeKnGQQcA5EkOpMHWb60ctoIjni2U8I7M0CdRTUdxtOGfFdEZ///FthcMXd rjbw== X-Gm-Message-State: APjAAAVuRJAzxlXDe6HnkCfb+4ZgioQWedsBfGUnKmkhYbuBXvRcDNlK DTf7jY7lRWvJEVOgMVCkxCk= X-Google-Smtp-Source: APXvYqxerrRP5WRy+rml8eMGfURU7CFX2ih4mnTm2wD+X3V2ToEbFqcEecsAb4P/596kEGg6E9fFWw== X-Received: by 2002:a17:906:4cc3:: with SMTP id q3mr19346590ejt.27.1559860868078; Thu, 06 Jun 2019 15:41:08 -0700 (PDT) Received: from smtp.gmail.com ([187.121.151.146]) by smtp.gmail.com with ESMTPSA id j2sm56764ejc.43.2019.06.06.15.41.04 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 06 Jun 2019 15:41:07 -0700 (PDT) Date: Thu, 6 Jun 2019 19:41:01 -0300 From: Rodrigo Siqueira To: Brian Starkey , Liviu Dudau , Daniel Vetter , Haneen Mohammed , Simon Ser Subject: [PATCH 2/2] drm/vkms: Add support for writeback Message-ID: <0acd74232d988970668298be0111c485bc68ec87.1559860606.git.rodrigosiqueiramelo@gmail.com> References: MIME-Version: 1.0 In-Reply-To: User-Agent: NeoMutt/20180716 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=JhgexSOQCk69aVM20s4eSvr2Wf1I3NzyL+87Su9CLwA=; b=Gu2p9ICSRNK3e7zFb7NBBVp4Ff1fWLEZnTnzBaOxFQiL8kAo84Tc1N3CPv/kKiyJS3 EWITAf0/4yF/XIeuKimpj8+sxz7CpJiLiK6WUcEnu0EIBjRyn4fYENf6SsnTXIM9ZhNw 03G+rVbSNoh52i31iN1c0/aUPFQ//NJRo3v959iCh90eFxqnB6H+EUcNvuA6DHHCQeOu UvAFLYHSS0eOMN+mpC+QTUCmd7T0tLzDBtj7jUGsAitK/aqbJs19L2xHt9gaDuPf4zvo Xgvjq5xPpZPbuS5AxtCUO5ZhV0I3eEy4Gxt8BZrwgbPz4eAktdaShWJk5NRkD3ihPqlu ML0A== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch implements the necessary functions to add writeback support for vkms. This feature is useful for testing compositors if you don’t have hardware with writeback support. Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/vkms/Makefile | 9 +- drivers/gpu/drm/vkms/vkms_crtc.c | 5 + drivers/gpu/drm/vkms/vkms_drv.c | 10 ++ drivers/gpu/drm/vkms/vkms_drv.h | 12 ++ drivers/gpu/drm/vkms/vkms_output.c | 6 + drivers/gpu/drm/vkms/vkms_writeback.c | 165 ++++++++++++++++++++++++++ 6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 89f09bec7b23..90eb7acd618d 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,4 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only -vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_crc.o +vkms-y := \ + vkms_drv.o \ + vkms_plane.o \ + vkms_output.o \ + vkms_crtc.o \ + vkms_gem.o \ + vkms_crc.o \ + vkms_writeback.o obj-$(CONFIG_DRM_VKMS) += vkms.o diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 1bbe099b7db8..ce797e265b1b 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -23,6 +23,11 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) if (!ret) DRM_ERROR("vkms failure on handling vblank"); + if (output->writeback_status == WB_START) { + drm_writeback_signal_completion(&output->wb_connector, 0); + output->writeback_status = WB_STOP; + } + if (state && output->crc_enabled) { u64 frame = drm_crtc_accurate_vblank_count(crtc); diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 92296bd8f623..d5917d5a45e3 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -29,6 +29,10 @@ bool enable_cursor; module_param_named(enable_cursor, enable_cursor, bool, 0444); MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); +int enable_writeback; +module_param_named(enable_writeback, enable_writeback, int, 0444); +MODULE_PARM_DESC(enable_writeback, "Enable/Disable writeback connector"); + static const struct file_operations vkms_driver_fops = { .owner = THIS_MODULE, .open = drm_open, @@ -123,6 +127,12 @@ static int __init vkms_init(void) goto out_fini; } + vkms_device->output.writeback_status = WB_DISABLED; + if (enable_writeback) { + vkms_device->output.writeback_status = WB_STOP; + DRM_INFO("Writeback connector enabled"); + } + ret = vkms_modeset_init(vkms_device); if (ret) goto out_fini; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index e81073dea154..ca1f9ee63ec8 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #define XRES_MIN 20 @@ -60,14 +61,22 @@ struct vkms_crtc_state { u64 frame_end; }; +enum wb_status { + WB_DISABLED, + WB_START, + WB_STOP, +}; + struct vkms_output { struct drm_crtc crtc; struct drm_encoder encoder; struct drm_connector connector; + struct drm_writeback_connector wb_connector; struct hrtimer vblank_hrtimer; ktime_t period_ns; struct drm_pending_vblank_event *event; bool crc_enabled; + enum wb_status writeback_status; /* ordered wq for crc_work */ struct workqueue_struct *crc_workq; /* protects concurrent access to crc_data */ @@ -141,4 +150,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt); void vkms_crc_work_handle(struct work_struct *work); +/* Writeback */ +int enable_writeback_connector(struct vkms_device *vkmsdev); + #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 1442b447c707..1fc1d4e9585c 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -91,6 +91,12 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) goto err_attach; } + if (vkmsdev->output.writeback_status != WB_DISABLED) { + ret = enable_writeback_connector(vkmsdev); + if (ret) + DRM_ERROR("Failed to init writeback connector\n"); + } + drm_mode_config_reset(dev); return 0; diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c new file mode 100644 index 000000000000..f7b962ae5646 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "vkms_drv.h" +#include +#include +#include +#include + +static const struct drm_connector_funcs vkms_wb_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_framebuffer *fb; + const struct drm_display_mode *mode = &crtc_state->mode; + + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) + return 0; + + fb = conn_state->writeback_job->fb; + if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) { + DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n", + fb->width, fb->height); + return -EINVAL; + } + + if (fb->format->format != DRM_FORMAT_XRGB8888) { + struct drm_format_name_buf format_name; + + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(fb->format->format, + &format_name)); + return -EINVAL; + } + + return 0; +} + +static const struct drm_encoder_helper_funcs vkms_wb_encoder_helper_funcs = { + .atomic_check = vkms_wb_encoder_atomic_check, +}; + +static int vkms_wb_connector_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + + return drm_add_modes_noedid(connector, dev->mode_config.max_width, + dev->mode_config.max_height); +} + +static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector, + struct drm_writeback_job *job) +{ + struct vkms_gem_object *vkms_obj; + struct drm_gem_object *gem_obj; + int ret; + + if (!job->fb) + return 0; + + gem_obj = drm_gem_fb_get_obj(job->fb, 0); + ret = vkms_gem_vmap(gem_obj); + if (ret) { + DRM_ERROR("vmap failed: %d\n", ret); + return ret; + } + + vkms_obj = drm_gem_to_vkms_gem(gem_obj); + job->priv = vkms_obj->vaddr; + + return 0; +} + +static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector, + struct drm_writeback_job *job) +{ + struct drm_gem_object *gem_obj; + + if (!job->fb) + return; + + gem_obj = drm_gem_fb_get_obj(job->fb, 0); + vkms_gem_vunmap(gem_obj); +} + +static void vkms_wb_atomic_commit(struct drm_connector *conn, + struct drm_connector_state *state) +{ + struct vkms_device *vkmsdev = drm_device_to_vkms_device(conn->dev); + struct vkms_output *output = &vkmsdev->output; + struct drm_writeback_connector *wb_conn = &output->wb_connector; + struct drm_connector_state *conn_state = wb_conn->base.state; + void *priv_data = conn_state->writeback_job->priv; + struct vkms_crc_data *primary_data = NULL; + struct drm_framebuffer *fb = NULL; + struct vkms_gem_object *vkms_obj; + struct drm_gem_object *gem_obj; + struct drm_plane *plane; + + if (!conn_state) + return; + + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) { + output->writeback_status = WB_STOP; + DRM_DEBUG_DRIVER("Disable writeback\n"); + return; + } + + drm_for_each_plane(plane, &vkmsdev->drm) { + struct vkms_plane_state *vplane_state; + struct vkms_crc_data *plane_data; + + vplane_state = to_vkms_plane_state(plane->state); + plane_data = vplane_state->crc_data; + + if (drm_framebuffer_read_refcount(&plane_data->fb) == 0) + continue; + + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + primary_data = plane_data; + } + + if (!primary_data) + return; + + fb = &primary_data->fb; + gem_obj = drm_gem_fb_get_obj(fb, 0); + vkms_obj = drm_gem_to_vkms_gem(gem_obj); + + if (!vkms_obj->vaddr || !priv_data) + return; + + memcpy(priv_data, vkms_obj->vaddr, vkms_obj->gem.size); + drm_writeback_queue_job(wb_conn, state); + output->writeback_status = WB_START; +} + +static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { + .get_modes = vkms_wb_connector_get_modes, + .prepare_writeback_job = vkms_wb_prepare_job, + .cleanup_writeback_job = vkms_wb_cleanup_job, + .atomic_commit = vkms_wb_atomic_commit, +}; + +int enable_writeback_connector(struct vkms_device *vkmsdev) +{ + struct drm_writeback_connector *wb = &vkmsdev->output.wb_connector; + + vkmsdev->output.wb_connector.encoder.possible_crtcs = 1; + drm_connector_helper_add(&wb->base, &vkms_wb_conn_helper_funcs); + + return drm_writeback_connector_init(&vkmsdev->drm, wb, + &vkms_wb_connector_funcs, + &vkms_wb_encoder_helper_funcs, + vkms_formats, + ARRAY_SIZE(vkms_formats)); +} +