summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeizhung Ding <weizhungding@google.com>2023-09-21 08:27:54 +0000
committerJi Soo Shin <jisshin@google.com>2023-10-18 17:32:26 +0000
commita41c9219ba1ac53591b28d4f7ada1b10c9463f14 (patch)
tree8194bc6ba0b7911e2300ab7a61e4bc07171079e6
parent47212ce550245a8d89380905d5dfb1e4aa2996f2 (diff)
downloadsamsung-a41c9219ba1ac53591b28d4f7ada1b10c9463f14.tar.gz
hdcp: Add DisplayPort statistics for max and current HDCP version.
Bug: 266898132 Test: cat /sys/devices/platform/hdcp/hdcp1_success_count Change-Id: I9c604c3a37b848b64970c4a325b40d2d4c06e8d9 Signed-off-by: Weizhung Ding <weizhungding@google.com>
-rw-r--r--Documentation/ABI/testing/sysfs-devices-platform-hdcp47
-rw-r--r--auth-control.c56
-rw-r--r--auth-control.h6
-rw-r--r--auth13.c4
-rw-r--r--auth22.c1
-rw-r--r--hdcp.h23
-rw-r--r--main.c91
7 files changed, 208 insertions, 20 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-hdcp b/Documentation/ABI/testing/sysfs-devices-platform-hdcp
new file mode 100644
index 0000000..d424eef
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-platform-hdcp
@@ -0,0 +1,47 @@
+What: /sys/devices/platform/hdcp/hdcp2_success_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ successful HDCP2 connection.
+
+What: /sys/devices/platform/hdcp/hdcp2_fallback_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ HDCP2 connection attempt that resorted to HDCP1 instead.
+
+What: /sys/devices/platform/hdcp/hdcp2_fail_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ HDCP2 connection attempt that failed.
+
+What: /sys/devices/platform/hdcp/hdcp1_success_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ successful HDCP1 connection.
+
+What: /sys/devices/platform/hdcp/hdcp1_fail_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ HDCP1 connection attempt that failed.
+
+What: /sys/devices/platform/hdcp/hdcp0_count
+Date: October 2023
+KernelVersion: 5.15
+Contact: "Ji Soo Shin" <jisshin@google.com>
+Description:
+ DisplayPort stats uses this interface to count the number of
+ connections that is incapable of HDCP.
diff --git a/auth-control.c b/auth-control.c
index bcd2d2d..00df17b 100644
--- a/auth-control.c
+++ b/auth-control.c
@@ -17,12 +17,13 @@
#include "auth-control.h"
#include "auth13.h"
#include "auth22.h"
+#include "hdcp.h"
#include "hdcp-log.h"
#include "teeif.h"
#define HDCP_SCHEDULE_DELAY_MSEC (5000)
-static struct delayed_work hdcp_work;
+static struct hdcp_device *hdcp_dev;
static enum auth_state state;
@@ -49,7 +50,7 @@ static int run_hdcp2_auth(void) {
hdcp_tee_enable_enc_22();
return 0;
} else if (ret != -EAGAIN) {
- return -EIO;
+ return ret;
}
hdcp_info("HDCP22 Retry...\n");
}
@@ -58,12 +59,22 @@ static int run_hdcp2_auth(void) {
}
static void hdcp_worker(struct work_struct *work) {
+ int ret;
+ bool hdcp2_capable = false;
+ bool hdcp1_capable = false;
+
+ struct hdcp_device *hdcp_dev =
+ container_of(work, struct hdcp_device, hdcp_work.work);
+
if (max_ver >= 2) {
hdcp_info("Trying HDCP22...\n");
- if (run_hdcp2_auth() == 0) {
+ ret = run_hdcp2_auth();
+ if (ret == 0) {
hdcp_info("HDCP22 Authentication Success\n");
+ hdcp_dev->hdcp2_success_count++;
return;
}
+ hdcp2_capable = (ret != -EOPNOTSUPP);
hdcp_info("HDCP22 Authentication Failed.\n");
} else {
hdcp_info("Not trying HDCP22. max_ver is %lu\n", max_ver);
@@ -72,29 +83,37 @@ static void hdcp_worker(struct work_struct *work) {
if (max_ver >= 1) {
hdcp_info("Trying HDCP13...\n");
state = HDCP1_AUTH_PROGRESS;
- if (hdcp13_dplink_authenticate() == 0) {
+ ret = hdcp13_dplink_authenticate();
+ if (ret == 0) {
hdcp_info("HDCP13 Authentication Success\n");
state = HDCP1_AUTH_DONE;
+ hdcp_dev->hdcp2_fallback_count += hdcp2_capable;
+ hdcp_dev->hdcp1_success_count += !hdcp2_capable;
return;
}
state = HDCP_AUTH_IDLE;
+ hdcp1_capable = (ret != -EOPNOTSUPP);
hdcp_info("HDCP13 Authentication Failed.\n");
} else {
hdcp_info("Not trying HDCP13. max_ver is %lu\n", max_ver);
}
+
+ hdcp_dev->hdcp2_fail_count += (hdcp2_capable);
+ hdcp_dev->hdcp1_fail_count += (!hdcp2_capable && hdcp1_capable);
+ hdcp_dev->hdcp0_count += (!hdcp2_capable && !hdcp1_capable);
}
void hdcp_dplink_handle_irq(void) {
if (state == HDCP2_AUTH_PROGRESS || state == HDCP2_AUTH_DONE) {
if (hdcp22_dplink_handle_irq() == -EAGAIN)
- schedule_delayed_work(&hdcp_work, 0);
+ schedule_delayed_work(&hdcp_dev->hdcp_work, 0);
return;
}
if (state == HDCP1_AUTH_DONE) {
if (hdcp13_dplink_handle_irq() == -EAGAIN)
- schedule_delayed_work(&hdcp_work, 0);
+ schedule_delayed_work(&hdcp_dev->hdcp_work, 0);
return;
}
}
@@ -109,20 +128,31 @@ void hdcp_dplink_connect_state(enum dp_state dp_hdcp_state) {
hdcp22_dplink_abort();
hdcp_tee_disable_enc();
state = HDCP_AUTH_IDLE;
- if (delayed_work_pending(&hdcp_work))
- cancel_delayed_work(&hdcp_work);
+ if (delayed_work_pending(&hdcp_dev->hdcp_work))
+ cancel_delayed_work(&hdcp_dev->hdcp_work);
return;
}
- schedule_delayed_work(&hdcp_work, msecs_to_jiffies(HDCP_SCHEDULE_DELAY_MSEC));
+ schedule_delayed_work(&hdcp_dev->hdcp_work,
+ msecs_to_jiffies(HDCP_SCHEDULE_DELAY_MSEC));
return;
}
EXPORT_SYMBOL_GPL(hdcp_dplink_connect_state);
-void hdcp_auth_worker_init(void) {
- INIT_DELAYED_WORK(&hdcp_work, hdcp_worker);
+int hdcp_auth_worker_init(struct hdcp_device *dev) {
+ if (hdcp_dev)
+ return -EACCES;
+
+ hdcp_dev = dev;
+ INIT_DELAYED_WORK(&hdcp_dev->hdcp_work, hdcp_worker);
+ return 0;
}
-void hdcp_auth_worker_deinit(void) {
- cancel_delayed_work_sync(&hdcp_work);
+int hdcp_auth_worker_deinit(struct hdcp_device *dev) {
+ if (hdcp_dev != dev)
+ return -EACCES;
+
+ cancel_delayed_work_sync(&hdcp_dev->hdcp_work);
+ hdcp_dev = NULL;
+ return 0;
}
diff --git a/auth-control.h b/auth-control.h
index 340a778..6bd753e 100644
--- a/auth-control.h
+++ b/auth-control.h
@@ -11,6 +11,8 @@
#ifndef __EXYNOS_HDCP_AUTH_CONTROL_H__
#define __EXYNOS_HDCP_AUTH_CONTROL_H__
+struct hdcp_device;
+
enum auth_state {
HDCP_AUTH_IDLE,
HDCP1_AUTH_PROGRESS,
@@ -21,7 +23,7 @@ enum auth_state {
int hdcp_get_auth_state(void);
-void hdcp_auth_worker_init(void);
-void hdcp_auth_worker_deinit(void);
+int hdcp_auth_worker_init(struct hdcp_device *dev);
+int hdcp_auth_worker_deinit(struct hdcp_device *dev);
#endif
diff --git a/auth13.c b/auth13.c
index 6bebb21..ac41a96 100644
--- a/auth13.c
+++ b/auth13.c
@@ -188,12 +188,12 @@ int hdcp13_dplink_authenticate(void)
ret = hdcp_dplink_recv(DP_AUX_HDCP_BCAPS, &bcaps, sizeof(bcaps));
if (ret) {
hdcp_err("BCaps Read failure (%d)\n", ret);
- return -EIO;
+ return -EOPNOTSUPP;
}
if (!(bcaps & DP_BCAPS_HDCP_CAPABLE)) {
hdcp_err("HDCP13 is not supported\n");
- return -EIO;
+ return -EOPNOTSUPP;
}
ret = hdcp_dplink_recv(DP_AUX_HDCP_BKSV, (uint8_t*)&bksv, HDCP_BKSV_SIZE);
diff --git a/auth22.c b/auth22.c
index 0b54ed9..ae800ac 100644
--- a/auth22.c
+++ b/auth22.c
@@ -82,6 +82,7 @@ int hdcp22_dplink_authenticate(void)
UPDATE_LINK_STATE(lk_data, LINK_ST_A1_EXCHANGE_MASTER_KEY);
} else {
UPDATE_LINK_STATE(lk_data, LINK_ST_H1_TX_LOW_VALUE_CONTENT);
+ return -EOPNOTSUPP;
}
break;
case LINK_ST_A1_EXCHANGE_MASTER_KEY:
diff --git a/hdcp.h b/hdcp.h
new file mode 100644
index 0000000..c9edf06
--- /dev/null
+++ b/hdcp.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * HDCP platform device headerpanel common utility header
+ *
+ * Copyright (c) 2022 Google LLC
+ */
+#ifndef __EXYNOS_HDCP_H__
+#define __EXYNOS_HDCP_H__
+
+struct hdcp_device {
+ struct device *dev;
+ struct delayed_work hdcp_work;
+
+ /* HDCP Telemetry */
+ uint32_t hdcp2_success_count;
+ uint32_t hdcp2_fallback_count;
+ uint32_t hdcp2_fail_count;
+ uint32_t hdcp1_success_count;
+ uint32_t hdcp1_fail_count;
+ uint32_t hdcp0_count;
+};
+
+#endif
diff --git a/main.c b/main.c
index 9420087..c2f0a4b 100644
--- a/main.c
+++ b/main.c
@@ -26,6 +26,7 @@
#include "exynos-hdcp-interface.h"
#include "auth-control.h"
+#include "hdcp.h"
#include "hdcp-log.h"
#include "selftest.h"
#include "teeif.h"
@@ -48,8 +49,94 @@ static ssize_t hdcp_read(struct file *filp, char __user *buf,
return 0;
}
+static ssize_t hdcp2_success_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp2_success_count);
+}
+static DEVICE_ATTR_RO(hdcp2_success_count);
+
+static ssize_t hdcp2_fallback_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp2_fallback_count);
+}
+static DEVICE_ATTR_RO(hdcp2_fallback_count);
+
+static ssize_t hdcp2_fail_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp2_fail_count);
+}
+static DEVICE_ATTR_RO(hdcp2_fail_count);
+
+static ssize_t hdcp1_success_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp1_success_count);
+}
+static DEVICE_ATTR_RO(hdcp1_success_count);
+
+static ssize_t hdcp1_fail_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp1_fail_count);
+}
+static DEVICE_ATTR_RO(hdcp1_fail_count);
+
+static ssize_t hdcp0_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdcp_device *hdcp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hdcp->hdcp0_count);
+}
+static DEVICE_ATTR_RO(hdcp0_count);
+
+static const struct attribute *hdcp_attrs[] = {
+ &dev_attr_hdcp2_success_count.attr,
+ &dev_attr_hdcp2_fallback_count.attr,
+ &dev_attr_hdcp2_fail_count.attr,
+ &dev_attr_hdcp1_success_count.attr,
+ &dev_attr_hdcp1_fail_count.attr,
+ &dev_attr_hdcp0_count.attr,
+ NULL };
+
static int exynos_hdcp_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct hdcp_device *hdcp_dev = NULL;
+ int ret = 0;
+
+ hdcp_dev = devm_kzalloc(dev, sizeof(struct hdcp_device), GFP_KERNEL);
+ if (!hdcp_dev) {
+ return -ENOMEM;
+ }
+ hdcp_dev->dev = dev;
+ platform_set_drvdata(pdev, hdcp_dev);
+ hdcp_auth_worker_init(hdcp_dev);
+
+ ret = sysfs_create_files(&dev->kobj, hdcp_attrs);
+ if (ret)
+ dev_err(dev, "failed to create hdcp sysfs files\n");
+
+ return 0;
+}
+
+static int exynos_hdcp_remove(struct platform_device *pdev)
+{
+ struct hdcp_device *hdcp_dev = platform_get_drvdata(pdev);
+ hdcp_auth_worker_deinit(hdcp_dev);
return 0;
}
@@ -60,6 +147,7 @@ static const struct of_device_id exynos_hdcp_of_match_table[] = {
static struct platform_driver exynos_hdcp_driver = {
.probe = exynos_hdcp_probe,
+ .remove = exynos_hdcp_remove,
.driver = {
.name = "exynos-hdcp",
.owner = THIS_MODULE,
@@ -81,8 +169,6 @@ static int __init hdcp_init(void)
}
hdcp_tee_init();
- hdcp_auth_worker_init();
-
return platform_driver_register(&exynos_hdcp_driver);
}
@@ -90,7 +176,6 @@ static void __exit hdcp_exit(void)
{
misc_deregister(&hdcp);
hdcp_tee_close();
- hdcp_auth_worker_deinit();
platform_driver_unregister(&exynos_hdcp_driver);
}