Skip to content
Permalink
Browse files
drm/connector: Add a drm_connector privacy-screen helper functions
Add 2 drm_connector privacy-screen helper functions:

1. drm_connector_attach_privacy_screen_provider(), this function creates
and attaches the standard privacy-screen properties and registers a
generic notifier for generating sysfs-connector-status-events on external
changes to the privacy-screen status.

2. drm_connector_update_privacy_screen(), Check if the passed in atomic
state contains a privacy-screen sw_state change for the connector and if
it does, call drm_privacy_screen_set_sw_state() with the new sw_state.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
jwrdegoede authored and intel-lab-lkp committed Apr 14, 2021
1 parent 8dbaa9b commit 8cb16e16d419f6ea9da13b9826a2d1d7ad5a9819
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
@@ -20,13 +20,15 @@
* OF THIS SOFTWARE.
*/

#include <drm/drm_atomic.h>
#include <drm/drm_connector.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_utils.h>
#include <drm/drm_print.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_privacy_screen_consumer.h>
#include <drm/drm_sysfs.h>

#include <linux/uaccess.h>
@@ -451,6 +453,11 @@ void drm_connector_cleanup(struct drm_connector *connector)
DRM_CONNECTOR_REGISTERED))
drm_connector_unregister(connector);

if (connector->privacy_screen) {
drm_privacy_screen_put(connector->privacy_screen);
connector->privacy_screen = NULL;
}

if (connector->tile_group) {
drm_mode_put_tile_group(dev, connector->tile_group);
connector->tile_group = NULL;
@@ -530,6 +537,10 @@ int drm_connector_register(struct drm_connector *connector)
/* Let userspace know we have a new connector */
drm_sysfs_hotplug_event(connector->dev);

if (connector->privacy_screen)
drm_privacy_screen_register_notifier(connector->privacy_screen,
&connector->privacy_screen_notifier);

goto unlock;

err_debugfs:
@@ -558,6 +569,11 @@ void drm_connector_unregister(struct drm_connector *connector)
return;
}

if (connector->privacy_screen)
drm_privacy_screen_unregister_notifier(
connector->privacy_screen,
&connector->privacy_screen_notifier);

if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);

@@ -2353,6 +2369,103 @@ drm_connector_attach_privacy_screen_properties(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_connector_attach_privacy_screen_properties);

static void drm_connector_update_privacy_screen_properties(
struct drm_connector *connector)
{
enum drm_privacy_screen_status sw_state, hw_state;

drm_privacy_screen_get_state(connector->privacy_screen,
&sw_state, &hw_state);

connector->state->privacy_screen_sw_state = sw_state;
drm_object_property_set_value(&connector->base,
connector->privacy_screen_hw_state_property, hw_state);
}

static int drm_connector_privacy_screen_notifier(
struct notifier_block *nb, unsigned long action, void *data)
{
struct drm_connector *connector =
container_of(nb, struct drm_connector, privacy_screen_notifier);
struct drm_device *dev = connector->dev;

drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
drm_connector_update_privacy_screen_properties(connector);
drm_modeset_unlock(&dev->mode_config.connection_mutex);

drm_sysfs_connector_status_event(connector,
connector->privacy_screen_sw_state_property);
drm_sysfs_connector_status_event(connector,
connector->privacy_screen_hw_state_property);

return NOTIFY_DONE;
}

/**
* drm_connector_attach_privacy_screen_provider - attach a privacy-screen to
* the connector
* @connector: connector to attach the privacy-screen to
* @priv: drm_privacy_screen to attach
*
* Create and attach the standard privacy-screen properties and register
* a generic notifier for generating sysfs-connector-status-events
* on external changes to the privacy-screen status.
* This function takes ownership of the passed in drm_privacy_screen and will
* call drm_privacy_screen_put() on it when the connector is destroyed.
*/
void drm_connector_attach_privacy_screen_provider(
struct drm_connector *connector, struct drm_privacy_screen *priv)
{
connector->privacy_screen = priv;
connector->privacy_screen_notifier.notifier_call =
drm_connector_privacy_screen_notifier;

drm_connector_create_privacy_screen_properties(connector);
drm_connector_update_privacy_screen_properties(connector);
drm_connector_attach_privacy_screen_properties(connector);
}
EXPORT_SYMBOL(drm_connector_attach_privacy_screen_provider);

/**
* drm_connector_update_privacy_screen - update connector's privacy-screen
* state (if changed)
* @connector: connector to update the privacy-screen for
* @state: drm_atomic state describing the state change
*
* This function checks if the passed in connector has a privacy-screen
* attached and if it does, it checks if the
* drm_connector_state.privacy_screen_sw_state setting has changed.
* If both conditions are true it calls drm_privacy_screen_set_sw_state() on
* the connector's privacy-screen to update the privacy-screen's state.
*/
void drm_connector_update_privacy_screen(struct drm_connector *connector,
struct drm_atomic_state *state)
{
struct drm_connector_state *new_connector_state, *old_connector_state;
int ret;

if (!connector->privacy_screen)
return;

new_connector_state = drm_atomic_get_new_connector_state(state, connector);
old_connector_state = drm_atomic_get_old_connector_state(state, connector);

if (new_connector_state->privacy_screen_sw_state ==
old_connector_state->privacy_screen_sw_state)
return;

ret = drm_privacy_screen_set_sw_state(connector->privacy_screen,
new_connector_state->privacy_screen_sw_state);
if (ret) {
drm_err(connector->dev, "Error updating privacy-screen sw_state\n");
return;
}

/* The hw_state property value may have changed, update the props. */
drm_connector_update_privacy_screen_properties(connector);
}
EXPORT_SYMBOL(drm_connector_update_privacy_screen);

int drm_connector_set_obj_prop(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t value)
@@ -27,6 +27,7 @@
#include <linux/llist.h>
#include <linux/ctype.h>
#include <linux/hdmi.h>
#include <linux/notifier.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_util.h>

@@ -40,6 +41,7 @@ struct drm_encoder;
struct drm_property;
struct drm_property_blob;
struct drm_printer;
struct drm_privacy_screen;
struct edid;
struct i2c_adapter;

@@ -1410,6 +1412,12 @@ struct drm_connector {
*/
struct drm_property *max_bpc_property;

/** @privacy_screen: drm_privacy_screen for this connector, or NULL. */
struct drm_privacy_screen *privacy_screen;

/** @privacy_screen_notifier: privacy-screen notifier_block */
struct notifier_block privacy_screen_notifier;

/**
* @privacy_screen_sw_state_property: Optional atomic property for the
* connector to control the integrated privacy screen.
@@ -1742,6 +1750,10 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
int min, int max);
void drm_connector_create_privacy_screen_properties(struct drm_connector *conn);
void drm_connector_attach_privacy_screen_properties(struct drm_connector *conn);
void drm_connector_attach_privacy_screen_provider(
struct drm_connector *connector, struct drm_privacy_screen *priv);
void drm_connector_update_privacy_screen(struct drm_connector *connector,
struct drm_atomic_state *state);

/**
* struct drm_tile_group - Tile group metadata

0 comments on commit 8cb16e1

Please sign in to comment.