mirror of
https://github.com/torvalds/linux.git
synced 2026-06-09 15:12:59 +02:00
UPSTREAM: drm: Add callbacks for late registering
Like what has been done for connectors add callbacks on encoder,
crtc and plane to let driver do actions after drm device registration.
Correspondingly, add callbacks called before unregister drm device.
version 2:
add drm_modeset_register_all() and drm_modeset_unregister_all()
to centralize all calls
version 3:
in error case unwind registers in drm_modeset_register_all
fix uninitialed return value
inverse order of unregistration in drm_modeset_unregister_all
version 4:
move function definitions in drm_crtc_internal.h
remove not needed documentation
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1466519829-4000-1-git-send-email-benjamin.gaignard@linaro.org
(cherry picked from commit 79190ea265)
Change-Id: I836e8ea62b46c0eae89cf8c70bcf3ea4e10068f5
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
parent
c79741d5d5
commit
bb866327e3
|
|
@ -649,6 +649,31 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
|
|||
|
||||
DEFINE_WW_CLASS(crtc_ww_class);
|
||||
|
||||
static int drm_crtc_register_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (crtc->funcs->late_register)
|
||||
ret = crtc->funcs->late_register(crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_crtc_unregister_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (crtc->funcs->early_unregister)
|
||||
crtc->funcs->early_unregister(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_init_with_planes - Initialise a new CRTC object with
|
||||
* specified primary and cursor planes.
|
||||
|
|
@ -1125,6 +1150,31 @@ void drm_connector_unregister_all(struct drm_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_connector_unregister_all);
|
||||
|
||||
static int drm_encoder_register_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
int ret = 0;
|
||||
|
||||
drm_for_each_encoder(encoder, dev) {
|
||||
if (encoder->funcs->late_register)
|
||||
ret = encoder->funcs->late_register(encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_encoder_unregister_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
drm_for_each_encoder(encoder, dev) {
|
||||
if (encoder->funcs->early_unregister)
|
||||
encoder->funcs->early_unregister(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_encoder_init - Init a preallocated encoder
|
||||
* @dev: drm device
|
||||
|
|
@ -1272,6 +1322,31 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_universal_plane_init);
|
||||
|
||||
static int drm_plane_register_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
int ret = 0;
|
||||
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (plane->funcs->late_register)
|
||||
ret = plane->funcs->late_register(plane);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_plane_unregister_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (plane->funcs->early_unregister)
|
||||
plane->funcs->early_unregister(plane);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_init - Initialize a legacy plane
|
||||
* @dev: DRM device
|
||||
|
|
@ -1507,6 +1582,46 @@ void drm_plane_force_disable(struct drm_plane *plane)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_plane_force_disable);
|
||||
|
||||
int drm_modeset_register_all(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_plane_register_all(dev);
|
||||
if (ret)
|
||||
goto err_plane;
|
||||
|
||||
ret = drm_crtc_register_all(dev);
|
||||
if (ret)
|
||||
goto err_crtc;
|
||||
|
||||
ret = drm_encoder_register_all(dev);
|
||||
if (ret)
|
||||
goto err_encoder;
|
||||
|
||||
ret = drm_connector_register_all(dev);
|
||||
if (ret)
|
||||
goto err_connector;
|
||||
|
||||
return 0;
|
||||
|
||||
err_connector:
|
||||
drm_encoder_unregister_all(dev);
|
||||
err_encoder:
|
||||
drm_crtc_unregister_all(dev);
|
||||
err_crtc:
|
||||
drm_plane_unregister_all(dev);
|
||||
err_plane:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drm_modeset_unregister_all(struct drm_device *dev)
|
||||
{
|
||||
drm_connector_unregister_all(dev);
|
||||
drm_encoder_unregister_all(dev);
|
||||
drm_crtc_unregister_all(dev);
|
||||
drm_plane_unregister_all(dev);
|
||||
}
|
||||
|
||||
static int drm_mode_create_standard_properties(struct drm_device *dev)
|
||||
{
|
||||
struct drm_property *prop;
|
||||
|
|
|
|||
|
|
@ -42,3 +42,5 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
|
|||
int drm_mode_atomic_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
int drm_modeset_register_all(struct drm_device *dev);
|
||||
void drm_modeset_unregister_all(struct drm_device *dev);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_core.h>
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_internal.h"
|
||||
|
||||
|
|
@ -759,7 +760,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
|||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_connector_register_all(dev);
|
||||
drm_modeset_register_all(dev);
|
||||
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
|
|
@ -792,7 +793,7 @@ void drm_dev_unregister(struct drm_device *dev)
|
|||
drm_lastclose(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_connector_unregister_all(dev);
|
||||
drm_modeset_unregister_all(dev);
|
||||
|
||||
if (dev->driver->unload)
|
||||
dev->driver->unload(dev);
|
||||
|
|
|
|||
|
|
@ -391,6 +391,32 @@ struct drm_crtc_funcs {
|
|||
const struct drm_crtc_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t *val);
|
||||
|
||||
/**
|
||||
* @late_register:
|
||||
*
|
||||
* This optional hook can be used to register additional userspace
|
||||
* interfaces attached to the crtc like debugfs interfaces.
|
||||
* It is called late in the driver load sequence from drm_dev_register().
|
||||
* Everything added from this callback should be unregistered in
|
||||
* the early_unregister callback.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int (*late_register)(struct drm_crtc *crtc);
|
||||
|
||||
/**
|
||||
* @early_unregister:
|
||||
*
|
||||
* This optional hook should be used to unregister the additional
|
||||
* userspace interfaces attached to the crtc from
|
||||
* late_unregister(). It is called from drm_dev_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_crtc *crtc);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -587,6 +613,32 @@ struct drm_connector_funcs {
|
|||
struct drm_encoder_funcs {
|
||||
void (*reset)(struct drm_encoder *encoder);
|
||||
void (*destroy)(struct drm_encoder *encoder);
|
||||
|
||||
/**
|
||||
* @late_register:
|
||||
*
|
||||
* This optional hook can be used to register additional userspace
|
||||
* interfaces attached to the encoder like debugfs interfaces.
|
||||
* It is called late in the driver load sequence from drm_dev_register().
|
||||
* Everything added from this callback should be unregistered in
|
||||
* the early_unregister callback.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int (*late_register)(struct drm_encoder *encoder);
|
||||
|
||||
/**
|
||||
* @early_unregister:
|
||||
*
|
||||
* This optional hook should be used to unregister the additional
|
||||
* userspace interfaces attached to the encoder from
|
||||
* late_unregister(). It is called from drm_dev_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_encoder *encoder);
|
||||
};
|
||||
|
||||
#define DRM_CONNECTOR_MAX_ENCODER 3
|
||||
|
|
@ -847,6 +899,31 @@ struct drm_plane_funcs {
|
|||
const struct drm_plane_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t *val);
|
||||
/**
|
||||
* @late_register:
|
||||
*
|
||||
* This optional hook can be used to register additional userspace
|
||||
* interfaces attached to the plane like debugfs interfaces.
|
||||
* It is called late in the driver load sequence from drm_dev_register().
|
||||
* Everything added from this callback should be unregistered in
|
||||
* the early_unregister callback.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int (*late_register)(struct drm_plane *plane);
|
||||
|
||||
/**
|
||||
* @early_unregister:
|
||||
*
|
||||
* This optional hook should be used to unregister the additional
|
||||
* userspace interfaces attached to the plane from
|
||||
* late_unregister(). It is called from drm_dev_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_plane *plane);
|
||||
};
|
||||
|
||||
enum drm_plane_type {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user