Commit a1a98689 authored by Hans de Goede's avatar Hans de Goede

drm: Add privacy-screen class (v4)

On some new laptops the LCD panel has a builtin electronic privacy-screen.
We want to export this functionality as a property on the drm connector
object. But often this functionality is not exposed on the GPU but on some
other (ACPI) device.

This commit adds a privacy-screen class allowing the driver for these
other devices to register themselves as a privacy-screen provider; and
allowing the drm/kms code to get a privacy-screen provider associated
with a specific GPU/connector combo.

Changes in v2:
- Make CONFIG_DRM_PRIVACY_SCREEN a bool which controls if the drm_privacy
  code gets built as part of the main drm module rather then making it
  a tristate which builds its own module.
- Add a #if IS_ENABLED(CONFIG_DRM_PRIVACY_SCREEN) check to
  drm_privacy_screen_consumer.h and define stubs when the check fails.
  Together these 2 changes fix several dependency issues.
- Remove module related code now that this is part of the main drm.ko
- Use drm_class as class for the privacy-screen devices instead of
  adding a separate class for this

Changes in v3:
- Make the static inline drm_privacy_screen_get_state() stub set sw_state
  and hw_state to PRIVACY_SCREEN_DISABLED to squelch an uninitialized
  variable warning when CONFIG_DRM_PRIVICAY_SCREEN is not set

Changes in v4:
- Make drm_privacy_screen_set_sw_state() skip calling out to the hw if
  hw_state == new_sw_state
Reviewed-by: default avatarEmil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211005202322.700909-3-hdegoede@redhat.com
parent 107fe904
......@@ -435,3 +435,18 @@ Legacy CRTC/Modeset Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
:export:
Privacy-screen class
====================
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
:doc: overview
.. kernel-doc:: include/drm/drm_privacy_screen_driver.h
:internal:
.. kernel-doc:: include/drm/drm_privacy_screen_machine.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
:export:
......@@ -6422,6 +6422,14 @@ F: drivers/gpu/drm/drm_panel.c
F: drivers/gpu/drm/panel/
F: include/drm/drm_panel.h
DRM PRIVACY-SCREEN CLASS
M: Hans de Goede <hdegoede@redhat.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/drm_privacy_screen*
F: include/drm/drm_privacy_screen*
DRM TTM SUBSYSTEM
M: Christian Koenig <christian.koenig@amd.com>
M: Huang Rui <ray.huang@amd.com>
......
......@@ -496,3 +496,7 @@ config DRM_PANEL_ORIENTATION_QUIRKS
config DRM_LIB_RANDOM
bool
default n
config DRM_PRIVACY_SCREEN
bool
default n
......@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.o
drm-$(CONFIG_PCI) += drm_pci.o
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
......
......@@ -43,6 +43,7 @@
#include <drm/drm_managed.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_print.h>
#include <drm/drm_privacy_screen_machine.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
......@@ -1029,6 +1030,7 @@ static const struct file_operations drm_stub_fops = {
static void drm_core_exit(void)
{
drm_privacy_screen_lookup_exit();
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
......@@ -1056,6 +1058,8 @@ static int __init drm_core_init(void)
if (ret < 0)
goto error;
drm_privacy_screen_lookup_init();
drm_core_init_complete = true;
DRM_DEBUG("Initialized\n");
......
This diff is collapsed.
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2020 Red Hat, Inc.
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef __DRM_PRIVACY_SCREEN_CONSUMER_H__
#define __DRM_PRIVACY_SCREEN_CONSUMER_H__
#include <linux/device.h>
#include <drm/drm_connector.h>
struct drm_privacy_screen;
#if IS_ENABLED(CONFIG_DRM_PRIVACY_SCREEN)
struct drm_privacy_screen *drm_privacy_screen_get(struct device *dev,
const char *con_id);
void drm_privacy_screen_put(struct drm_privacy_screen *priv);
int drm_privacy_screen_set_sw_state(struct drm_privacy_screen *priv,
enum drm_privacy_screen_status sw_state);
void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
enum drm_privacy_screen_status *sw_state_ret,
enum drm_privacy_screen_status *hw_state_ret);
#else
static inline struct drm_privacy_screen *drm_privacy_screen_get(struct device *dev,
const char *con_id)
{
return ERR_PTR(-ENODEV);
}
static inline void drm_privacy_screen_put(struct drm_privacy_screen *priv)
{
}
static inline int drm_privacy_screen_set_sw_state(struct drm_privacy_screen *priv,
enum drm_privacy_screen_status sw_state)
{
return -ENODEV;
}
static inline void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
enum drm_privacy_screen_status *sw_state_ret,
enum drm_privacy_screen_status *hw_state_ret)
{
*sw_state_ret = PRIVACY_SCREEN_DISABLED;
*hw_state_ret = PRIVACY_SCREEN_DISABLED;
}
#endif
#endif
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2020 Red Hat, Inc.
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef __DRM_PRIVACY_SCREEN_DRIVER_H__
#define __DRM_PRIVACY_SCREEN_DRIVER_H__
#include <linux/device.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <drm/drm_connector.h>
struct drm_privacy_screen;
/**
* struct drm_privacy_screen_ops - drm_privacy_screen operations
*
* Defines the operations which the privacy-screen class code may call.
* These functions should be implemented by the privacy-screen driver.
*/
struct drm_privacy_screen_ops {
/**
* @set_sw_state: Called to request a change of the privacy-screen
* state. The privacy-screen class code contains a check to avoid this
* getting called when the hw_state reports the state is locked.
* It is the driver's responsibility to update sw_state and hw_state.
* This is always called with the drm_privacy_screen's lock held.
*/
int (*set_sw_state)(struct drm_privacy_screen *priv,
enum drm_privacy_screen_status sw_state);
/**
* @get_hw_state: Called to request that the driver gets the current
* privacy-screen state from the hardware and then updates sw_state and
* hw_state accordingly. This will be called by the core just before
* the privacy-screen is registered in sysfs.
*/
void (*get_hw_state)(struct drm_privacy_screen *priv);
};
/**
* struct drm_privacy_screen - central privacy-screen structure
*
* Central privacy-screen structure, this contains the struct device used
* to register the screen in sysfs, the screen's state, ops, etc.
*/
struct drm_privacy_screen {
/** @dev: device used to register the privacy-screen in sysfs. */
struct device dev;
/** @lock: mutex protection all fields in this struct. */
struct mutex lock;
/** @list: privacy-screen devices list list-entry. */
struct list_head list;
/**
* @ops: &struct drm_privacy_screen_ops for this privacy-screen.
* This is NULL if the driver has unregistered the privacy-screen.
*/
const struct drm_privacy_screen_ops *ops;
/**
* @sw_state: The privacy-screen's software state, see
* :ref:`Standard Connector Properties<standard_connector_properties>`
* for more info.
*/
enum drm_privacy_screen_status sw_state;
/**
* @hw_state: The privacy-screen's hardware state, see
* :ref:`Standard Connector Properties<standard_connector_properties>`
* for more info.
*/
enum drm_privacy_screen_status hw_state;
};
struct drm_privacy_screen *drm_privacy_screen_register(
struct device *parent, const struct drm_privacy_screen_ops *ops);
void drm_privacy_screen_unregister(struct drm_privacy_screen *priv);
#endif
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2020 Red Hat, Inc.
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef __DRM_PRIVACY_SCREEN_MACHINE_H__
#define __DRM_PRIVACY_SCREEN_MACHINE_H__
#include <linux/list.h>
/**
* struct drm_privacy_screen_lookup - static privacy-screen lookup list entry
*
* Used for the static lookup-list for mapping privacy-screen consumer
* dev-connector pairs to a privacy-screen provider.
*/
struct drm_privacy_screen_lookup {
/** @list: Lookup list list-entry. */
struct list_head list;
/** @dev_id: Consumer device name or NULL to match all devices. */
const char *dev_id;
/** @con_id: Consumer connector name or NULL to match all connectors. */
const char *con_id;
/** @provider: dev_name() of the privacy_screen provider. */
const char *provider;
};
void drm_privacy_screen_lookup_add(struct drm_privacy_screen_lookup *lookup);
void drm_privacy_screen_lookup_remove(struct drm_privacy_screen_lookup *lookup);
static inline void drm_privacy_screen_lookup_init(void)
{
}
static inline void drm_privacy_screen_lookup_exit(void)
{
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment