From a50fb57df23d16825d18434f65c7f86f2f8a21c6 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Fri, 19 Aug 2022 09:01:48 +0000 Subject: [PATCH] media: rockchip: hdmirx: auto identification of hdcp1.4 and hdcp2.3 Signed-off-by: Chen Shunqing Change-Id: Ic7f39acfa903085144c380c9a4415e2cf64380d8 --- .../platform/rockchip/hdmirx/rk_hdmirx.c | 29 ++--- .../platform/rockchip/hdmirx/rk_hdmirx_hdcp.c | 123 ++++++++---------- 2 files changed, 64 insertions(+), 88 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 417eac289583..47a85fa7112f 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -219,9 +219,8 @@ struct rk_hdmirx_dev { bool initialized; bool freq_qos_add; bool get_timing; - u8 hdcp_enable; - u8 hdcp_support; bool cec_enable; + u8 hdcp_enable; u32 num_clks; u32 edid_blocks_written; u32 hpd_trigger_level; @@ -1048,7 +1047,6 @@ static void hdmirx_register_hdcp(struct device *dev, .hpd_config = hdmirx_hpd_config, .tx_5v_power = tx_5v_power_present, .enable = hdcp_enable, - .hdcp_support = hdmirx_dev->hdcp_support, .dev = hdmirx_dev->dev, }; @@ -1299,6 +1297,8 @@ static void hdmirx_format_change(struct rk_hdmirx_dev *hdmirx_dev) } hdmirx_dev->get_timing = true; + if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_start) + hdmirx_dev->hdcp->hdcp_start(hdmirx_dev->hdcp); v4l2_dbg(1, debug, v4l2_dev, "%s: queue res_chg_event\n", __func__); v4l2_event_queue(&stream->vdev, &ev_src_chg); } @@ -1422,10 +1422,6 @@ static void hdmirx_dma_config(struct rk_hdmirx_dev *hdmirx_dev) static void hdmirx_submodule_init(struct rk_hdmirx_dev *hdmirx_dev) { - /* Note: if not config HDCP2_CONFIG, there will be some errors; */ - hdmirx_update_bits(hdmirx_dev, HDCP2_CONFIG, - HDCP2_SWITCH_OVR_EN, - HDCP2_SWITCH_OVR_EN); hdmirx_scdc_init(hdmirx_dev); hdmirx_controller_init(hdmirx_dev); } @@ -2022,9 +2018,11 @@ static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev) HDMIRX_AXI_ERROR_INT_EN, 0); hdmirx_reset_dma(hdmirx_dev); hdmirx_dev->get_timing = false; + if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_stop) + hdmirx_dev->hdcp->hdcp_stop(hdmirx_dev->hdcp); schedule_delayed_work_on(hdmirx_dev->bound_cpu, &hdmirx_dev->delayed_work_res_change, - msecs_to_jiffies(50)); + msecs_to_jiffies(800)); } static void avpunit_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev, @@ -2435,8 +2433,6 @@ static void hdmirx_plugin(struct rk_hdmirx_dev *hdmirx_dev) hdmirx_dma_config(hdmirx_dev); hdmirx_interrupts_setup(hdmirx_dev, true); hdmirx_audio_handle_plugged_change(hdmirx_dev, 1); - if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_start) - hdmirx_dev->hdcp->hdcp_start(hdmirx_dev->hdcp); } static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev) @@ -2946,18 +2942,11 @@ static int hdmirx_parse_dt(struct rk_hdmirx_dev *hdmirx_dev) dev_warn(dev, "failed to get hpd-trigger-level, set high as default\n"); } - if (of_property_read_bool(np, "hdcp1x-enable")) { - hdmirx_dev->hdcp_support |= HDCP_1X_ENABLE; + if (of_property_read_bool(np, "hdcp1x-enable")) hdmirx_dev->hdcp_enable = HDCP_1X_ENABLE; - } - if (of_property_read_bool(np, "hdcp2x-enable")) { - hdmirx_dev->hdcp_support |= HDCP_2X_ENABLE; + + if (of_property_read_bool(np, "hdcp2x-enable")) hdmirx_dev->hdcp_enable = HDCP_2X_ENABLE; - } - if (of_property_read_bool(np, "hdcp1x-default-enable")) { - hdmirx_dev->hdcp_support |= HDCP_1X_ENABLE; - hdmirx_dev->hdcp_enable = HDCP_1X_ENABLE; - } if (of_property_read_bool(np, "cec-enable")) hdmirx_dev->cec_enable = true; diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx_hdcp.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx_hdcp.c index 6cb7232207e1..015889186c74 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx_hdcp.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx_hdcp.c @@ -81,6 +81,7 @@ static int rk_hdmirx_hdcp_load_key(struct rk_hdmirx_hdcp *hdcp) { int ret; + hdcp->status = HDMIRX_HDCP_DISABLED; if (!hdcp->keys_is_load) { ret = hdcp_load_keys_cb(hdcp); if (ret) @@ -95,10 +96,8 @@ static int rk_hdmirx_hdcp_load_key(struct rk_hdmirx_hdcp *hdcp) hdmirx_hdcp_update_bits(hdcp, HDCP2_CONFIG, HDCP2_CONNECTED | - HDCP2_SWITCH_OVR_VALUE | - HDCP2_SWITCH_OVR_EN, - HDCP2_CONNECTED | - HDCP2_SWITCH_OVR_EN); + HDCP2_SWITCH_OVR_VALUE, + HDCP2_CONNECTED); return 0; } @@ -113,6 +112,9 @@ static int rk_hdmirx_hdcp1x_start(struct rk_hdmirx_hdcp *hdcp) static int rk_hdmirx_hdcp1x_stop(struct rk_hdmirx_hdcp *hdcp) { + if (hdcp->status == HDMIRX_HDCP_DISABLED) + return 0; + hdmirx_hdcp_update_bits(hdcp, GLOBAL_SWENABLE, HDCP_ENABLE, 0); hdcp->status = HDMIRX_HDCP_DISABLED; @@ -129,8 +131,8 @@ static int rk_hdmirx_hdcp2x_start(struct rk_hdmirx_hdcp *hdcp) { hdmirx_hdcp_update_bits(hdcp, HDCP2_CONFIG, HDCP2_SWITCH_OVR_VALUE | - HDCP2_SWITCH_LCK, - HDCP2_SWITCH_OVR_VALUE | + HDCP2_SWITCH_LCK | + HDCP2_SWITCH_OVR_EN, HDCP2_SWITCH_LCK); if (hdcp->tx_5v_power(hdcp->hdmirx)) hdmirx_hdcp_write(hdcp, HDCP2_ESM_P0_GPIO_IN, 0x2); @@ -141,13 +143,12 @@ static int rk_hdmirx_hdcp2x_start(struct rk_hdmirx_hdcp *hdcp) static int rk_hdmirx_hdcp2x_stop(struct rk_hdmirx_hdcp *hdcp) { - rk_hdmirx_hdcp2_hpd_config(hdcp, false); hdmirx_hdcp_write(hdcp, HDCP2_ESM_P0_GPIO_IN, 0x0); hdmirx_hdcp_update_bits(hdcp, HDCP2_CONFIG, HDCP2_SWITCH_OVR_VALUE | - HDCP2_SWITCH_LCK, 0); - msleep(300); - rk_hdmirx_hdcp2_hpd_config(hdcp, true); + HDCP2_SWITCH_LCK | + HDCP2_SWITCH_OVR_EN, + HDCP2_SWITCH_OVR_EN); return 0; } @@ -169,13 +170,15 @@ static void rk_hdmirx_hdcp2_connect_ctrl(struct rk_hdmirx_hdcp *hdcp, bool en) static int rk_hdmirx_hdcp_start(struct rk_hdmirx_hdcp *hdcp) { - if ((hdcp->hdcp_support & HDCP_2X_ENABLE) && - hdcp->enable == HDCP_2X_ENABLE) { + if (hdcp->enable == HDCP_2X_ENABLE) { + rk_hdmirx_hdcp1x_start(hdcp); rk_hdmirx_hdcp2x_start(hdcp); return 0; } - if ((hdcp->hdcp_support & HDCP_1X_ENABLE) && - hdcp->enable == HDCP_1X_ENABLE) + hdmirx_hdcp_update_bits(hdcp, HDCP2_CONFIG, + HDCP2_SWITCH_OVR_EN, + HDCP2_SWITCH_OVR_EN); + if (hdcp->enable == HDCP_1X_ENABLE) rk_hdmirx_hdcp1x_start(hdcp); return 0; @@ -183,18 +186,13 @@ static int rk_hdmirx_hdcp_start(struct rk_hdmirx_hdcp *hdcp) static int rk_hdmirx_hdcp_stop(struct rk_hdmirx_hdcp *hdcp) { - if ((hdcp->hdcp_support & HDCP_2X_ENABLE) && - hdcp->enable == HDCP_2X_ENABLE) { - rk_hdmirx_hdcp2x_stop(hdcp); - dev_dbg(hdcp->dev, "hdcp2 stop\n"); - } + if (!hdcp->enable) + return 0; - if ((hdcp->hdcp_support & HDCP_1X_ENABLE) && - hdcp->enable == HDCP_1X_ENABLE) { - rk_hdmirx_hdcp1x_stop(hdcp); - dev_dbg(hdcp->dev, "hdcp1x stop\n"); - } - hdcp->enable = 0; + if (hdcp->enable == HDCP_2X_ENABLE) + rk_hdmirx_hdcp2x_stop(hdcp); + rk_hdmirx_hdcp1x_stop(hdcp); + dev_dbg(hdcp->dev, "hdcp stop\n"); return 0; } @@ -215,7 +213,7 @@ static ssize_t enable_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { - int enable, hdcp_support; + int enable; struct rk_hdmirx_hdcp *hdcp = g_hdmirx_hdcp; if (!hdcp) @@ -224,31 +222,23 @@ static ssize_t enable_store(struct device *device, if (kstrtoint(buf, 10, &enable)) return -EINVAL; - if (hdcp->hdcp_support & HDCP_2X_ENABLE) - hdcp_support = HDCP_2X_ENABLE; - else if (hdcp->hdcp_support & HDCP_1X_ENABLE) - hdcp_support = HDCP_1X_ENABLE; - else - hdcp_support = 0; - - if (enable > hdcp_support) + if (enable > hdcp->hdcp_support) return count; if (hdcp->enable != enable) { + rk_hdmirx_hdcp2_hpd_config(hdcp, false); if (enable == HDCP_2X_ENABLE) { - if (hdcp->enable == HDCP_1X_ENABLE) - rk_hdmirx_hdcp1x_stop(hdcp); + rk_hdmirx_hdcp1x_start(hdcp); rk_hdmirx_hdcp2x_start(hdcp); } else if (enable == HDCP_1X_ENABLE) { if (hdcp->enable == HDCP_2X_ENABLE) rk_hdmirx_hdcp2x_stop(hdcp); rk_hdmirx_hdcp1x_start(hdcp); } else { - if (hdcp->enable == HDCP_2X_ENABLE) - rk_hdmirx_hdcp2x_stop(hdcp); - if (hdcp->enable == HDCP_1X_ENABLE) - rk_hdmirx_hdcp1x_stop(hdcp); + rk_hdmirx_hdcp_stop(hdcp); } + msleep(300); + rk_hdmirx_hdcp2_hpd_config(hdcp, true); hdcp->enable = enable; } @@ -263,31 +253,27 @@ static ssize_t status_show(struct device *device, int status = HDMIRX_HDCP_DISABLED; struct rk_hdmirx_hdcp *hdcp = g_hdmirx_hdcp; u32 val; - int n; + int dectypt, n = 0; if (!hdcp) return 0; + if (!hdcp->enable) + return snprintf(buf, PAGE_SIZE, "HDCP Disable\n"); + if (hdcp->enable == HDCP_2X_ENABLE) { - val = hdmirx_hdcp_read(hdcp, HDCP2_STATUS); - n = snprintf(buf, PAGE_SIZE, "HDCP2:\n%s\n", - (val & BIT(0)) ? "Dectypted" : "No dectypted"); - - val = hdmirx_hdcp_read(hdcp, HDCP2_ESM_P0_GPIO_OUT); - if (val & BIT(0)) - n += snprintf(buf + n, PAGE_SIZE - n, "Capable\n"); - if (val & BIT(1)) - n += snprintf(buf + n, PAGE_SIZE - n, "Not capable\n"); - if (val & BIT(2)) - n += snprintf(buf + n, PAGE_SIZE - n, "Authenticated success\n"); - if (val & BIT(3)) - n += snprintf(buf + n, PAGE_SIZE - n, "Authenticated failed\n"); - if (val & BIT(4)) - n += snprintf(buf + n, PAGE_SIZE - n, "Link Error\n"); - if (val & BIT(7)) - n += snprintf(buf + n, PAGE_SIZE - n, "AKE Init or SKE done\n"); - - return n; + dectypt = hdmirx_hdcp_read(hdcp, HDCP2_STATUS) & BIT(0); + if (dectypt) { + val = hdmirx_hdcp_read(hdcp, HDCP2_ESM_P0_GPIO_OUT); + if (val & BIT(2)) + n += snprintf(buf + n, PAGE_SIZE - n, + "HDCP2.3: Authenticated success\n"); + else + n += snprintf(buf + n, PAGE_SIZE - n, + "HDCP2.3: Authenticated failed\n"); + return n; + } + n += snprintf(buf, PAGE_SIZE, "HDCP2.3: No dectypted\n"); } status = hdcp->status; @@ -302,16 +288,17 @@ static ssize_t status_show(struct device *device, else status = HDMIRX_HDCP_AUTH_FAIL; } - if (status == HDMIRX_HDCP_DISABLED) - return snprintf(buf, PAGE_SIZE, "hdcp disable\n"); - else if (status == HDMIRX_HDCP_AUTH_START) - return snprintf(buf, PAGE_SIZE, "hdcp_auth_start\n"); + + if (status == HDMIRX_HDCP_AUTH_START) + n += snprintf(buf + n, PAGE_SIZE, "HDCP1.4: Authenticated start\n"); else if (status == HDMIRX_HDCP_AUTH_SUCCESS) - return snprintf(buf, PAGE_SIZE, "hdcp_auth_success\n"); + n += snprintf(buf + n, PAGE_SIZE, "HDCP1.4: Authenticated success\n"); else if (status == HDMIRX_HDCP_AUTH_FAIL) - return snprintf(buf, PAGE_SIZE, "hdcp_auth_fail\n"); + n += snprintf(buf + n, PAGE_SIZE, "HDCP1.4: Authenticated failed\n"); else - return snprintf(buf, PAGE_SIZE, "unknown status\n"); + n += snprintf(buf + n, PAGE_SIZE, "HDCP1.4: Unknown status\n"); + + return n; } static DEVICE_ATTR_RO(status); @@ -345,7 +332,7 @@ struct rk_hdmirx_hdcp *rk_hdmirx_hdcp_register(struct rk_hdmirx_hdcp *hdcp_data) hdcp->tx_5v_power = hdcp_data->tx_5v_power; hdcp->hpd_config = hdcp_data->hpd_config; hdcp->enable = hdcp_data->enable; - hdcp->hdcp_support = hdcp_data->hdcp_support; + hdcp->hdcp_support = hdcp_data->enable; hdcp->dev = hdcp_data->dev; g_hdmirx_hdcp = hdcp; hdcp->mdev.minor = MISC_DYNAMIC_MINOR;