<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 4, 2019 at 11:41 AM Rajat Jain <<a href="mailto:rajatja@google.com">rajatja@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Certain laptops now come with panels that have integrated privacy<br>
screens on them. This patch adds support for such panels by adding<br>
a privacy-screen property to the intel_connector for the panel, that<br>
the userspace can then use to control and check the status.<br>
<br>
Identifying the presence of privacy screen, and controlling it, is done<br>
via ACPI _DSM methods.<br>
<br>
Currently, this is done only for the Intel display ports. But in future,<br>
this can be done for any other ports if the hardware becomes available<br>
(e.g. external monitors supporting integrated privacy screens?).<br>
<br>
Signed-off-by: Rajat Jain <<a href="mailto:rajatja@google.com" target="_blank">rajatja@google.com</a>><br>
Change-Id: Ic9ff07fc4a50797d2d0dfb919f11aa0821a4b548<br>
---<br>
v2: Formed by splitting the original patch into multiple patches.<br>
- All code has been moved into i915 now.<br>
- Privacy screen is a i915 property<br>
- Have a local state variable to store the prvacy screen. Don't read<br>
it from hardware.<br></blockquote><div><br></div><div><br></div><div>Hi Folks,</div><div><br></div><div>I posted a v2 taking care of the comments I received (also split it into 3 patches now, and resused some ACPI code I found in i915 driver). . Wondering if any one got a chance to look at this?</div><div><br></div><div>Thanks,</div><div><br></div><div>Rajat</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
drivers/gpu/drm/i915/Makefile | 3 +-<br>
drivers/gpu/drm/i915/display/intel_atomic.c | 13 +++-<br>
.../gpu/drm/i915/display/intel_connector.c | 35 ++++++++++<br>
.../gpu/drm/i915/display/intel_connector.h | 1 +<br>
.../drm/i915/display/intel_display_types.h | 4 ++<br>
drivers/gpu/drm/i915/display/intel_dp.c | 5 ++<br>
.../drm/i915/display/intel_privacy_screen.c | 70 +++++++++++++++++++<br>
.../drm/i915/display/intel_privacy_screen.h | 25 +++++++<br>
include/uapi/drm/i915_drm.h | 14 ++++<br>
9 files changed, 166 insertions(+), 4 deletions(-)<br>
create mode 100644 drivers/gpu/drm/i915/display/intel_privacy_screen.c<br>
create mode 100644 drivers/gpu/drm/i915/display/intel_privacy_screen.h<br>
<br>
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile<br>
index 2587ea834f06..3589ebcf27bc 100644<br>
--- a/drivers/gpu/drm/i915/Makefile<br>
+++ b/drivers/gpu/drm/i915/Makefile<br>
@@ -185,7 +185,8 @@ i915-y += \<br>
display/intel_tc.o<br>
i915-$(CONFIG_ACPI) += \<br>
display/intel_acpi.o \<br>
- display/intel_opregion.o<br>
+ display/intel_opregion.o \<br>
+ display/intel_privacy_screen.o<br>
i915-$(CONFIG_DRM_FBDEV_EMULATION) += \<br>
display/intel_fbdev.o<br>
<br>
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c<br>
index d3fb75bb9eb1..378772d3449c 100644<br>
--- a/drivers/gpu/drm/i915/display/intel_atomic.c<br>
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c<br>
@@ -37,6 +37,7 @@<br>
#include "intel_atomic.h"<br>
#include "intel_display_types.h"<br>
#include "intel_hdcp.h"<br>
+#include "intel_privacy_screen.h"<br>
#include "intel_sprite.h"<br>
<br>
/**<br>
@@ -57,11 +58,14 @@ int intel_digital_connector_atomic_get_property(struct drm_connector *connector,<br>
struct drm_i915_private *dev_priv = to_i915(dev);<br>
struct intel_digital_connector_state *intel_conn_state =<br>
to_intel_digital_connector_state(state);<br>
+ struct intel_connector *intel_connector = to_intel_connector(connector);<br>
<br>
if (property == dev_priv->force_audio_property)<br>
*val = intel_conn_state->force_audio;<br>
else if (property == dev_priv->broadcast_rgb_property)<br>
*val = intel_conn_state->broadcast_rgb;<br>
+ else if (property == intel_connector->privacy_screen_property)<br>
+ *val = intel_conn_state->privacy_screen_status;<br>
else {<br>
DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",<br>
property-><a href="http://base.id" rel="noreferrer" target="_blank">base.id</a>, property->name);<br>
@@ -89,15 +93,18 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,<br>
struct drm_i915_private *dev_priv = to_i915(dev);<br>
struct intel_digital_connector_state *intel_conn_state =<br>
to_intel_digital_connector_state(state);<br>
+ struct intel_connector *intel_connector = to_intel_connector(connector);<br>
<br>
if (property == dev_priv->force_audio_property) {<br>
intel_conn_state->force_audio = val;<br>
return 0;<br>
- }<br>
-<br>
- if (property == dev_priv->broadcast_rgb_property) {<br>
+ } else if (property == dev_priv->broadcast_rgb_property) {<br>
intel_conn_state->broadcast_rgb = val;<br>
return 0;<br>
+ } else if (property == intel_connector->privacy_screen_property) {<br>
+ intel_privacy_screen_set_val(intel_connector, val);<br>
+ intel_conn_state->privacy_screen_status = val;<br>
+ return 0;<br>
}<br>
<br>
DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",<br>
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c<br>
index 308ec63207ee..3ccbf52aedf9 100644<br>
--- a/drivers/gpu/drm/i915/display/intel_connector.c<br>
+++ b/drivers/gpu/drm/i915/display/intel_connector.c<br>
@@ -281,3 +281,38 @@ intel_attach_colorspace_property(struct drm_connector *connector)<br>
drm_object_attach_property(&connector->base,<br>
connector->colorspace_property, 0);<br>
}<br>
+<br>
+static const struct drm_prop_enum_list privacy_screen_enum[] = {<br>
+ { PRIVACY_SCREEN_DISABLED, "Disabled" },<br>
+ { PRIVACY_SCREEN_ENABLED, "Enabled" },<br>
+};<br>
+<br>
+/**<br>
+ * intel_attach_privacy_screen_property -<br>
+ * create and attach the connecter's privacy-screen property. *<br>
+ * @connector: connector for which to init the privacy-screen property<br>
+ *<br>
+ * This function creates and attaches the "privacy-screen" property to the<br>
+ * connector. Initial state of privacy-screen is set to disabled.<br>
+ */<br>
+void<br>
+intel_attach_privacy_screen_property(struct drm_connector *connector)<br>
+{<br>
+ struct intel_connector *intel_connector = to_intel_connector(connector);<br>
+ struct drm_property *prop;<br>
+<br>
+ if (!intel_connector->privacy_screen_property) {<br>
+ prop = drm_property_create_enum(connector->dev,<br>
+ DRM_MODE_PROP_ENUM,<br>
+ "privacy-screen",<br>
+ privacy_screen_enum,<br>
+ ARRAY_SIZE(privacy_screen_enum));<br>
+ if (!prop)<br>
+ return;<br>
+<br>
+ intel_connector->privacy_screen_property = prop;<br>
+ }<br>
+<br>
+ drm_object_attach_property(&connector->base, prop,<br>
+ PRIVACY_SCREEN_DISABLED);<br>
+}<br>
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h<br>
index 93a7375c8196..61005f37a338 100644<br>
--- a/drivers/gpu/drm/i915/display/intel_connector.h<br>
+++ b/drivers/gpu/drm/i915/display/intel_connector.h<br>
@@ -31,5 +31,6 @@ void intel_attach_force_audio_property(struct drm_connector *connector);<br>
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);<br>
void intel_attach_aspect_ratio_property(struct drm_connector *connector);<br>
void intel_attach_colorspace_property(struct drm_connector *connector);<br>
+void intel_attach_privacy_screen_property(struct drm_connector *connector);<br>
<br>
#endif /* __INTEL_CONNECTOR_H__ */<br>
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h<br>
index c2706afc069b..83b8c98049a7 100644<br>
--- a/drivers/gpu/drm/i915/display/intel_display_types.h<br>
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h<br>
@@ -426,6 +426,9 @@ struct intel_connector {<br>
struct work_struct modeset_retry_work;<br>
<br>
struct intel_hdcp hdcp;<br>
+<br>
+ /* Optional "privacy-screen" property for the connector panel */<br>
+ struct drm_property *privacy_screen_property;<br>
};<br>
<br>
struct intel_digital_connector_state {<br>
@@ -433,6 +436,7 @@ struct intel_digital_connector_state {<br>
<br>
enum hdmi_force_audio force_audio;<br>
int broadcast_rgb;<br>
+ enum intel_privacy_screen_status privacy_screen_status;<br>
};<br>
<br>
#define to_intel_digital_connector_state(x) container_of(x, struct intel_digital_connector_state, base)<br>
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c<br>
index 4fac408a4299..1963e92404ba 100644<br>
--- a/drivers/gpu/drm/i915/display/intel_dp.c<br>
+++ b/drivers/gpu/drm/i915/display/intel_dp.c<br>
@@ -62,6 +62,7 @@<br>
#include "intel_lspcon.h"<br>
#include "intel_lvds.h"<br>
#include "intel_panel.h"<br>
+#include "intel_privacy_screen.h"<br>
#include "intel_psr.h"<br>
#include "intel_sideband.h"<br>
#include "intel_tc.h"<br>
@@ -6358,6 +6359,10 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect<br>
<br>
/* Lookup the ACPI node corresponding to the connector */<br>
intel_connector_lookup_acpi_node(intel_connector);<br>
+<br>
+ /* Check for integrated Privacy screen support */<br>
+ if (intel_privacy_screen_present(intel_connector))<br>
+ intel_attach_privacy_screen_property(connector);<br>
}<br>
}<br>
<br>
diff --git a/drivers/gpu/drm/i915/display/intel_privacy_screen.c b/drivers/gpu/drm/i915/display/intel_privacy_screen.c<br>
new file mode 100644<br>
index 000000000000..4c422e38c51a<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/i915/display/intel_privacy_screen.c<br>
@@ -0,0 +1,70 @@<br>
+// SPDX-License-Identifier: GPL-2.0-or-later<br>
+/*<br>
+ * Intel ACPI privacy screen code<br>
+ *<br>
+ * Copyright © 2019 Google Inc.<br>
+ */<br>
+<br>
+#include <linux/acpi.h><br>
+<br>
+#include "intel_privacy_screen.h"<br>
+<br>
+#define CONNECTOR_DSM_REVID 1<br>
+<br>
+#define CONNECTOR_DSM_FN_PRIVACY_ENABLE 2<br>
+#define CONNECTOR_DSM_FN_PRIVACY_DISABLE 3<br>
+<br>
+static const guid_t drm_conn_dsm_guid =<br>
+ GUID_INIT(0xC7033113, 0x8720, 0x4CEB,<br>
+ 0x90, 0x90, 0x9D, 0x52, 0xB3, 0xE5, 0x2D, 0x73);<br>
+<br>
+/* Makes _DSM call to set privacy screen status */<br>
+static void acpi_privacy_screen_call_dsm(acpi_handle conn_handle, u64 func)<br>
+{<br>
+ union acpi_object *obj;<br>
+<br>
+ obj = acpi_evaluate_dsm(conn_handle, &drm_conn_dsm_guid,<br>
+ CONNECTOR_DSM_REVID, func, NULL);<br>
+ if (!obj) {<br>
+ DRM_DEBUG_DRIVER("failed to evaluate _DSM for fn %llx\n", func);<br>
+ return;<br>
+ }<br>
+<br>
+ ACPI_FREE(obj);<br>
+}<br>
+<br>
+void intel_privacy_screen_set_val(struct intel_connector *intel_connector,<br>
+ enum intel_privacy_screen_status val)<br>
+{<br>
+ acpi_handle acpi_handle = intel_connector->acpi_handle;<br>
+<br>
+ if (!acpi_handle)<br>
+ return;<br>
+<br>
+ if (val == PRIVACY_SCREEN_DISABLED)<br>
+ acpi_privacy_screen_call_dsm(acpi_handle,<br>
+ CONNECTOR_DSM_FN_PRIVACY_DISABLE);<br>
+ else if (val == PRIVACY_SCREEN_ENABLED)<br>
+ acpi_privacy_screen_call_dsm(acpi_handle,<br>
+ CONNECTOR_DSM_FN_PRIVACY_ENABLE);<br>
+}<br>
+<br>
+bool intel_privacy_screen_present(struct intel_connector *intel_connector)<br>
+{<br>
+ acpi_handle handle = intel_connector->acpi_handle;<br>
+<br>
+ if (!handle)<br>
+ return false;<br>
+<br>
+ if (!acpi_check_dsm(handle, &drm_conn_dsm_guid,<br>
+ CONNECTOR_DSM_REVID,<br>
+ 1 << CONNECTOR_DSM_FN_PRIVACY_ENABLE |<br>
+ 1 << CONNECTOR_DSM_FN_PRIVACY_DISABLE)) {<br>
+ DRM_WARN("%s: Odd, connector ACPI node but no privacy scrn?\n",<br>
+ dev_name(intel_connector->base.dev->dev));<br>
+ return false;<br>
+ }<br>
+ DRM_DEV_INFO(intel_connector->base.dev->dev,<br>
+ "supports privacy screen\n");<br>
+ return true;<br>
+}<br>
diff --git a/drivers/gpu/drm/i915/display/intel_privacy_screen.h b/drivers/gpu/drm/i915/display/intel_privacy_screen.h<br>
new file mode 100644<br>
index 000000000000..212f73349a00<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/i915/display/intel_privacy_screen.h<br>
@@ -0,0 +1,25 @@<br>
+/* SPDX-License-Identifier: GPL-2.0-or-later */<br>
+/*<br>
+ * Copyright © 2019 Google Inc.<br>
+ */<br>
+<br>
+#ifndef __DRM_PRIVACY_SCREEN_H__<br>
+#define __DRM_PRIVACY_SCREEN_H__<br>
+<br>
+#include "intel_display_types.h"<br>
+<br>
+#ifdef CONFIG_ACPI<br>
+bool intel_privacy_screen_present(struct intel_connector *intel_connector);<br>
+void intel_privacy_screen_set_val(struct intel_connector *intel_connector,<br>
+ enum intel_privacy_screen_status val);<br>
+#else<br>
+bool intel_privacy_screen_present(struct intel_connector *intel_connector);<br>
+{<br>
+ return false;<br>
+}<br>
+void intel_privacy_screen_set_val(struct intel_connector *intel_connector,<br>
+ enum intel_privacy_screen_status val)<br>
+{ }<br>
+#endif /* CONFIG_ACPI */<br>
+<br>
+#endif /* __DRM_PRIVACY_SCREEN_H__ */<br>
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h<br>
index 469dc512cca3..cf08d5636363 100644<br>
--- a/include/uapi/drm/i915_drm.h<br>
+++ b/include/uapi/drm/i915_drm.h<br>
@@ -2123,6 +2123,20 @@ struct drm_i915_query_engine_info {<br>
struct drm_i915_engine_info engines[];<br>
};<br>
<br>
+/**<br>
+ * enum intel_privacy_screen_status - privacy_screen status<br>
+ *<br>
+ * This enum is used to track and control the state of the integrated privacy<br>
+ * screen present on some display panels, via the "privacy-screen" property.<br>
+ *<br>
+ * @PRIVACY_SCREEN_DISABLED: The privacy-screen on the panel is disabled<br>
+ * @PRIVACY_SCREEN_ENABLED: The privacy-screen on the panel is enabled<br>
+ **/<br>
+enum intel_privacy_screen_status {<br>
+ PRIVACY_SCREEN_DISABLED = 0,<br>
+ PRIVACY_SCREEN_ENABLED = 1,<br>
+};<br>
+<br>
#if defined(__cplusplus)<br>
}<br>
#endif<br>
-- <br>
2.24.0.rc1.363.gb1bccd3e3d-goog<br>
<br>
</blockquote></div></div>