video: tegra: dc: Expose HDCP through DT
Aly Hirani [Mon, 26 Oct 2015 21:02:15 +0000 (14:02 -0700)]
This change exposes the ability to set the HDCP policy through the
device-tree. It moves the HDCP policy into a new device-tree node for
easier maintainace rather than overloading more DC flags. It also adds
a new policy to keep the HDCP always disabled. This is needed for the
recovery kernel where doing HDCP is not possible.

Bug 1694996

Change-Id: Ifd96d2b1bdb3f3f0e963681efd3134719b15e350
Signed-off-by: Aly Hirani <ahirani@nvidia.com>
Reviewed-on: http://git-master/r/821655
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>

Documentation/devicetree/bindings/video/nvidia,tegra210-dp.txt
Documentation/devicetree/bindings/video/nvidia,tegra210-hdmi.txt
arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/hdmihdcp.c
drivers/video/tegra/dc/of_dc.c
include/dt-bindings/display/tegra-dc.h
include/video/nvhdcp.h

index 550d3fd..26b534f 100644 (file)
@@ -31,6 +31,8 @@ NVIDIA TEGRA210 DisplayPort
    TEGRA_DC_OUT_N_SHOT_MODE, TEGRA_DC_OUT_ONE_SHOT_LP_MODE,
    TEGRA_DC_OUT_INITIALIZED_MODE and TEGRA_DC_OUT_HOTPLUG_WAKE_LP0.
    If several items are written, bitwise OR is operated for them, internally.
+ - nvidia,out-hdcp-policy: One of TEGRA_DC_OUT_HDCP_POLICY_ALWAYS_ON,
+   TEGRA_DC_OUT_HDCP_POLICY_ALWAYS_OFF
  - nvidia,out-parent-clk: Parent clk for display controller.
  - nvidia,out-max-pixclk: Maximum pixel clock in pico-seconds.
  - nvidia,dither: Dither option. Should be TEGRA_DC_UNDEFINED_DITHER or
index 1995824..e33924d 100644 (file)
@@ -74,6 +74,8 @@ NVIDIA TEGRA210 High Definition Multimedia Interface
    TEGRA_DC_OUT_N_SHOT_MODE, TEGRA_DC_OUT_ONE_SHOT_LP_MODE,
    TEGRA_DC_OUT_INITIALIZED_MODE and TEGRA_DC_OUT_HOTPLUG_WAKE_LP0.
    If several items are written, bitwise OR is operated for them, internally.
+ - nvidia,out-hdcp-policy: One of TEGRA_DC_OUT_HDCP_POLICY_ALWAYS_ON,
+   TEGRA_DC_OUT_HDCP_POLICY_ALWAYS_OFF
  - nvidia,out-parent-clk: Parent clk for display controller.
  - nvidia,out-max-pixclk: Maximum pixel clock in pico-seconds.
  - nvidia,dither: Dither option. Should be TEGRA_DC_UNDEFINED_DITHER or
index c0ef09b..393f7de 100644 (file)
@@ -674,6 +674,7 @@ struct tegra_vrr {
 struct tegra_dc_out {
        int                             type;
        unsigned                        flags;
+       unsigned                        hdcp_policy;
 
        /* size in mm */
        unsigned                        h_size;
@@ -742,6 +743,10 @@ struct tegra_dc_out {
 #define TEGRA_DC_OUT_HOTPLUG_WAKE_LP0          (1 << 7)
 #define TEGRA_DC_OUT_NVSR_MODE                 (1 << 8)
 
+#define TEGRA_DC_HDCP_POLICY_ALWAYS_ON 0
+#define TEGRA_DC_HDCP_POLICY_ON_DEMAND 1
+#define TEGRA_DC_HDCP_POLICY_ALWAYS_OFF        2
+
 #define TEGRA_DC_ALIGN_MSB             0
 #define TEGRA_DC_ALIGN_LSB             1
 
index 891de10..07568d5 100644 (file)
@@ -1677,7 +1677,9 @@ static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp)
        u8 hdcp2version = 0;
        int e;
        nvhdcp->state = STATE_UNAUTHENTICATED;
-       if (nvhdcp_is_plugged(nvhdcp)) {
+       if (nvhdcp_is_plugged(nvhdcp) &&
+               atomic_read(&nvhdcp->policy) !=
+               TEGRA_DC_HDCP_POLICY_ALWAYS_OFF) {
                nvhdcp->fail_count = 0;
                e = nvhdcp_i2c_read8(nvhdcp, HDCP_HDCP2_VERSION, &hdcp2version);
                if (e)
@@ -1730,12 +1732,18 @@ void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd)
 
 int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol)
 {
-       if (pol == TEGRA_NVHDCP_POLICY_ALWAYS_ON) {
+       if (pol == TEGRA_DC_HDCP_POLICY_ALWAYS_ON) {
                nvhdcp_info("using \"always on\" policy.\n");
                if (atomic_xchg(&nvhdcp->policy, pol) != pol) {
                        /* policy changed, start working */
                        tegra_nvhdcp_on(nvhdcp);
                }
+       } else if (pol == TEGRA_DC_HDCP_POLICY_ALWAYS_OFF) {
+               nvhdcp_info("using \"always off\" policy.\n");
+               if (atomic_xchg(&nvhdcp->policy, pol) != pol) {
+                       /* policy changed, stop working */
+                       tegra_nvhdcp_off(nvhdcp);
+               }
        } else {
                /* unsupported policy */
                return -EINVAL;
@@ -1923,6 +1931,7 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_hdmi *hdmi,
        nvhdcp->info.platform_data = nvhdcp;
        nvhdcp->fail_count = 0;
        nvhdcp->max_retries = HDCP_MAX_RETRIES;
+       atomic_set(&nvhdcp->policy, hdmi->dc->pdata->default_out->hdcp_policy);
 
        adapter = i2c_get_adapter(bus);
        if (!adapter) {
index 433b951..47dec70 100644 (file)
@@ -367,6 +367,13 @@ static int parse_disp_default_out(struct platform_device *ndev,
                default_out->flags |= (unsigned) u;
        }
 
+       if (!of_property_read_u32(np, "nvidia,out-hdcp-policy", &temp)) {
+               default_out->hdcp_policy = (unsigned)temp;
+               OF_DC_LOG("hdcp_policy = %u\n", default_out->hdcp_policy);
+       } else {
+               default_out->hdcp_policy = TEGRA_DC_HDCP_POLICY_ALWAYS_ON;
+       }
+
        if (tegra_platform_is_linsim())
                default_out->hotplug_gpio = -1;
 
index 29bf179..2c350f1 100644 (file)
 /* Makes hotplug GPIO a LP0 wakeup source */
 #define TEGRA_DC_OUT_HOTPLUG_WAKE_LP0          (1 << 7)
 
+/* bots for tegra_dc_out.hdcp_policy */
+#define TEGRA_DC_HDCP_POLICY_ALWAYS_ON 0
+#define TEGRA_DC_HDCP_POLICY_ON_DEMAND 1
+#define TEGRA_DC_HDCP_POLICY_ALWAYS_OFF        2
+
 /* tegra_dc_out.align */
 #define TEGRA_DC_ALIGN_MSB             0
 #define TEGRA_DC_ALIGN_LSB             1
index 499b4f2..fad6716 100644 (file)
@@ -84,6 +84,7 @@ struct tegra_nvhdcp_packet {
 /* parameters to TEGRAIO_NVHDCP_SET_POLICY */
 #define TEGRA_NVHDCP_POLICY_ON_DEMAND  0
 #define TEGRA_NVHDCP_POLICY_ALWAYS_ON  1
+#define TEGRA_NVHDCP_POLICY_ALWAYS_OFF 2
 
 /* ioctls */
 #define TEGRAIO_NVHDCP_ON              _IO('F', 0x70)