drm: writeback: Create an helper for drm_writeback_connector initialization

As the old drm and the new drmm variants of drm_writeback_connector
requires almost the same initialization, create an internal helper to do
most of the initialization work.

Currently there is no cleanup function for writeback connectors. To allows
implementation of drmm variant of writeback connector, create a cleanup
function that can be used to properly remove all the writeback-specific
properties and allocations.

This also introduce an helper to cleanup only the drm_writeback_connector
properties, so it can be used during initialization to cleanup in case of
failure.

Reviewed-by: Maxime Ripard <mripard@kernel.org>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-5-3e4ae1bd05a0@bootlin.com
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
This commit is contained in:
Louis Chauvet 2025-01-16 18:47:17 +01:00
parent 8dd92e6eee
commit 135d8fc7af
No known key found for this signature in database
GPG Key ID: 20AD2EC65B102CE2

View File

@ -15,6 +15,7 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_property.h>
#include <drm/drm_writeback.h>
@ -195,6 +196,77 @@ int drm_writeback_connector_init(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_writeback_connector_init);
/**
* drm_writeback_connector_init_with_encoder - Initialize a writeback connector with
* a custom encoder
*
* @dev: DRM device
* @wb_connector: Writeback connector to initialize
* @enc: handle to the already initialized drm encoder
* @formats: Array of supported pixel formats for the writeback engine
* @n_formats: Length of the formats array
*
* This function creates the writeback-connector-specific properties if they
* have not been already created, initializes the connector as
* type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
* values.
*
* This function assumes that the drm_writeback_connector's encoder has already been
* created and initialized before invoking this function.
*
* In addition, this function also assumes that callers of this API will manage
* assigning the encoder helper functions, possible_crtcs and any other encoder
* specific operation.
*
* Returns: 0 on success, or a negative error code
*/
static int __drm_writeback_connector_init(struct drm_device *dev,
struct drm_writeback_connector *wb_connector,
struct drm_encoder *enc, const u32 *formats,
int n_formats)
{
struct drm_connector *connector = &wb_connector->base;
struct drm_mode_config *config = &dev->mode_config;
struct drm_property_blob *blob;
int ret = create_writeback_properties(dev);
if (ret != 0)
return ret;
connector->interlace_allowed = 0;
ret = drm_connector_attach_encoder(connector, enc);
if (ret)
return ret;
blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
formats);
if (IS_ERR(blob))
return PTR_ERR(blob);
INIT_LIST_HEAD(&wb_connector->job_queue);
spin_lock_init(&wb_connector->job_lock);
wb_connector->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&wb_connector->fence_lock);
snprintf(wb_connector->timeline_name,
sizeof(wb_connector->timeline_name),
"CONNECTOR:%d-%s", connector->base.id, connector->name);
drm_object_attach_property(&connector->base,
config->writeback_out_fence_ptr_property, 0);
drm_object_attach_property(&connector->base,
config->writeback_fb_id_property, 0);
drm_object_attach_property(&connector->base,
config->writeback_pixel_formats_property,
blob->base.id);
wb_connector->pixel_formats_blob_ptr = blob;
return 0;
}
/**
* drm_writeback_connector_init_with_encoder - Initialize a writeback connector with
* a custom encoder
@ -225,61 +297,24 @@ EXPORT_SYMBOL(drm_writeback_connector_init);
* Returns: 0 on success, or a negative error code
*/
int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
struct drm_writeback_connector *wb_connector, struct drm_encoder *enc,
const struct drm_connector_funcs *con_funcs, const u32 *formats,
int n_formats)
struct drm_writeback_connector *wb_connector,
struct drm_encoder *enc,
const struct drm_connector_funcs *con_funcs,
const u32 *formats, int n_formats)
{
struct drm_property_blob *blob;
struct drm_connector *connector = &wb_connector->base;
struct drm_mode_config *config = &dev->mode_config;
int ret = create_writeback_properties(dev);
if (ret != 0)
return ret;
blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
formats);
if (IS_ERR(blob))
return PTR_ERR(blob);
connector->interlace_allowed = 0;
int ret;
ret = drm_connector_init(dev, connector, con_funcs,
DRM_MODE_CONNECTOR_WRITEBACK);
if (ret)
goto connector_fail;
return ret;
ret = drm_connector_attach_encoder(connector, enc);
ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats,
n_formats);
if (ret)
goto attach_fail;
drm_connector_cleanup(connector);
INIT_LIST_HEAD(&wb_connector->job_queue);
spin_lock_init(&wb_connector->job_lock);
wb_connector->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&wb_connector->fence_lock);
snprintf(wb_connector->timeline_name,
sizeof(wb_connector->timeline_name),
"CONNECTOR:%d-%s", connector->base.id, connector->name);
drm_object_attach_property(&connector->base,
config->writeback_out_fence_ptr_property, 0);
drm_object_attach_property(&connector->base,
config->writeback_fb_id_property, 0);
drm_object_attach_property(&connector->base,
config->writeback_pixel_formats_property,
blob->base.id);
wb_connector->pixel_formats_blob_ptr = blob;
return 0;
attach_fail:
drm_connector_cleanup(connector);
connector_fail:
drm_property_blob_put(blob);
return ret;
}
EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder);