Skip to content

Commit

Permalink
drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
Browse files Browse the repository at this point in the history
This patch adds HDCP 1.x support to msm DP connectors using the new HDCP
helpers.

Cc: Stephen Boyd <swboyd@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-sean@poorly.run #v1

Changes in v2:
-Squash [1] into this patch with the following changes (Stephen)
  -Update the sc7180 dtsi file
  -Remove resource names and just use index (Stephen)

[1] https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-14-sean@poorly.run
  • Loading branch information
atseanpaul authored and intel-lab-lkp committed Sep 15, 2021
1 parent 9db9bd7 commit 2fc7bb1
Show file tree
Hide file tree
Showing 14 changed files with 709 additions and 19 deletions.
4 changes: 3 additions & 1 deletion arch/arm64/boot/dts/qcom/sc7180.dtsi
Expand Up @@ -3088,7 +3088,9 @@
compatible = "qcom,sc7180-dp";
status = "disabled";

reg = <0 0x0ae90000 0 0x1400>;
reg = <0 0x0ae90000 0 0x1400>,
<0 0x0aed1000 0 0x174>,
<0 0x0aee1000 0 0x2c>;

interrupt-parent = <&mdss>;
interrupts = <12>;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/msm/Makefile
Expand Up @@ -109,6 +109,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
dp/dp_ctrl.o \
dp/dp_display.o \
dp/dp_drm.o \
dp/dp_hdcp.o \
dp/dp_hpd.o \
dp/dp_link.o \
dp/dp_panel.o \
Expand Down
49 changes: 48 additions & 1 deletion drivers/gpu/drm/msm/dp/dp_debug.c
Expand Up @@ -8,13 +8,15 @@
#include <linux/debugfs.h>
#include <drm/drm_connector.h>
#include <drm/drm_file.h>
#include <drm/drm_hdcp.h>

#include "dp_parser.h"
#include "dp_catalog.h"
#include "dp_aux.h"
#include "dp_ctrl.h"
#include "dp_debug.h"
#include "dp_display.h"
#include "dp_hdcp.h"

#define DEBUG_NAME "msm_dp"

Expand All @@ -24,6 +26,7 @@ struct dp_debug_private {
struct dp_usbpd *usbpd;
struct dp_link *link;
struct dp_panel *panel;
struct dp_hdcp *hdcp;
struct drm_connector **connector;
struct device *dev;
struct drm_device *drm_dev;
Expand Down Expand Up @@ -349,6 +352,38 @@ static int dp_test_active_open(struct inode *inode,
inode->i_private);
}

static ssize_t dp_hdcp_key_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
char *input_buffer;
int ret = 0;
struct dp_debug_private *debug = file->private_data;
struct drm_device *dev;

dev = debug->drm_dev;

if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN))
return -EINVAL;

if (!debug->hdcp)
return -ENOENT;

input_buffer = memdup_user_nul(ubuf, len);
if (IS_ERR(input_buffer))
return PTR_ERR(input_buffer);

ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len);

kfree(input_buffer);
if (ret < 0) {
DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret);
return ret;
}

*offp += len;
return len;
}

static const struct file_operations dp_debug_fops = {
.open = simple_open,
.read = dp_debug_read_info,
Expand All @@ -363,6 +398,12 @@ static const struct file_operations test_active_fops = {
.write = dp_test_active_write
};

static const struct file_operations dp_hdcp_key_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.write = dp_hdcp_key_write,
};

static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)
{
int rc = 0;
Expand All @@ -384,14 +425,19 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)
minor->debugfs_root,
debug, &dp_test_type_fops);

debugfs_create_file("msm_dp_hdcp_key", 0222,
minor->debugfs_root,
debug, &dp_hdcp_key_fops);

debug->root = minor->debugfs_root;

return rc;
}

struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
struct drm_connector **connector, struct drm_minor *minor)
struct dp_hdcp *hdcp, struct drm_connector **connector,
struct drm_minor *minor)
{
int rc = 0;
struct dp_debug_private *debug;
Expand All @@ -413,6 +459,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
debug->usbpd = usbpd;
debug->link = link;
debug->panel = panel;
debug->hdcp = hdcp;
debug->dev = dev;
debug->drm_dev = minor->dev;
debug->connector = connector;
Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/msm/dp/dp_debug.h
Expand Up @@ -6,6 +6,7 @@
#ifndef _DP_DEBUG_H_
#define _DP_DEBUG_H_

#include "dp_hdcp.h"
#include "dp_panel.h"
#include "dp_link.h"

Expand Down Expand Up @@ -43,7 +44,7 @@ struct dp_debug {
*/
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
struct drm_connector **connector,
struct dp_hdcp *hdcp, struct drm_connector **connector,
struct drm_minor *minor);

/**
Expand All @@ -60,7 +61,8 @@ void dp_debug_put(struct dp_debug *dp_debug);
static inline
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
struct drm_connector **connector, struct drm_minor *minor)
struct dp_hdcp *hdcp, struct drm_connector **connector,
struct drm_minor *minor)
{
return ERR_PTR(-EINVAL);
}
Expand Down
45 changes: 43 additions & 2 deletions drivers/gpu/drm/msm/dp/dp_display.c
Expand Up @@ -26,6 +26,7 @@
#include "dp_drm.h"
#include "dp_audio.h"
#include "dp_debug.h"
#include "dp_hdcp.h"

static struct msm_dp *g_dp_display;
#define HPD_STRING_SIZE 30
Expand Down Expand Up @@ -96,6 +97,7 @@ struct dp_display_private {
struct dp_panel *panel;
struct dp_ctrl *ctrl;
struct dp_debug *debug;
struct dp_hdcp *hdcp;

struct dp_usbpd_cb usbpd_cb;
struct dp_display_mode dp_mode;
Expand All @@ -121,6 +123,15 @@ static const struct of_device_id dp_dt_match[] = {
{}
};

struct dp_hdcp *dp_display_connector_to_hdcp(struct drm_connector *connector)
{
struct msm_dp *dp_display = msm_dp_from_connector(connector);
struct dp_display_private *dp;

dp = container_of(dp_display, struct dp_display_private, dp_display);
return dp->hdcp;
}

static int dp_add_event(struct dp_display_private *dp_priv, u32 event,
u32 data, u32 delay)
{
Expand Down Expand Up @@ -714,6 +725,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
static void dp_display_deinit_sub_modules(struct dp_display_private *dp)
{
dp_debug_put(dp->debug);
dp_hdcp_put(dp->hdcp);
dp_audio_put(dp->audio);
dp_panel_put(dp->panel);
dp_aux_put(dp->aux);
Expand Down Expand Up @@ -810,8 +822,18 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error_ctrl;
}

dp->hdcp = dp_hdcp_get(dp->parser, dp->aux);
if (IS_ERR(dp->hdcp)) {
rc = PTR_ERR(dp->hdcp);
DRM_ERROR("failed to initialize hdcp, rc = %d\n", rc);
dp->hdcp = NULL;
goto error_hdcp;
}

return rc;

error_hdcp:
dp_audio_put(dp->audio);
error_ctrl:
dp_panel_put(dp->panel);
error_link:
Expand Down Expand Up @@ -930,6 +952,15 @@ int dp_display_set_plugged_cb(struct msm_dp *dp_display,
return 0;
}

void dp_display_hdcp_commit(struct msm_dp *dp, struct drm_atomic_state *state)
{
struct dp_display_private *dp_display;

dp_display = container_of(dp, struct dp_display_private, dp_display);

dp_hdcp_commit(dp_display->hdcp, state);
}

int dp_display_validate_mode(struct msm_dp *dp, u32 mode_pclk_khz)
{
const u32 num_components = 3, default_bpp = 24;
Expand Down Expand Up @@ -1429,8 +1460,8 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
dev = &dp->pdev->dev;

dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
dp->link, &dp->dp_display.connector,
minor);
dp->link, dp->hdcp,
&dp->dp_display.connector, minor);
if (IS_ERR(dp->debug)) {
rc = PTR_ERR(dp->debug);
DRM_ERROR("failed to initialize debug, rc = %d\n", rc);
Expand All @@ -1441,12 +1472,16 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder)
{
struct dp_display_private *dp_display_priv;
struct msm_drm_private *priv;
int ret;

if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
return -EINVAL;

dp_display_priv = container_of(dp_display, struct dp_display_private,
dp_display);

priv = dev->dev_private;
dp_display->drm_dev = dev;

Expand All @@ -1467,6 +1502,12 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
return ret;
}

ret = dp_hdcp_attach(dp_display_priv->hdcp, dp_display->connector);
if (ret) {
DRM_ERROR("Failed to attach hdcp, ret=%d\n", ret);
return ret;
}

priv->connectors[priv->num_connectors++] = dp_display->connector;
return 0;
}
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/msm/dp/dp_display.h
Expand Up @@ -27,8 +27,13 @@ struct msm_dp {
struct dp_audio *dp_audio;
};

struct drm_atomic_state;

int dp_display_set_plugged_cb(struct msm_dp *dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev);
struct dp_hdcp *dp_display_connector_to_hdcp(struct drm_connector *connector);
void dp_display_hdcp_commit(struct msm_dp *dp_display,
struct drm_atomic_state *state);
int dp_display_validate_mode(struct msm_dp *dp_display, u32 mode_pclk_khz);
int dp_display_get_modes(struct msm_dp *dp_display,
struct dp_display_mode *dp_mode);
Expand Down
68 changes: 67 additions & 1 deletion drivers/gpu/drm/msm/dp/dp_drm.c
Expand Up @@ -5,18 +5,32 @@

#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_hdcp.h>

#include "msm_drv.h"
#include "msm_kms.h"
#include "dp_drm.h"
#include "dp_hdcp.h"

struct dp_connector_state {
struct drm_connector_state base;
bool hdcp_transition;
};
#define to_dp_connector_state(x) container_of(x, struct dp_connector_state, base)

struct dp_connector {
struct drm_connector base;
struct msm_dp *dp_display;
};
#define to_dp_connector(x) container_of(x, struct dp_connector, base)

struct msm_dp *msm_dp_from_connector(struct drm_connector *connector)
{
return to_dp_connector(connector)->dp_display;
}

/**
* dp_connector_detect - callback to determine if connector is connected
* @conn: Pointer to drm connector structure
Expand Down Expand Up @@ -114,20 +128,72 @@ static enum drm_mode_status dp_connector_mode_valid(
return dp_display_validate_mode(dp_disp, mode->clock);
}

static int dp_connector_atomic_check(struct drm_connector *connector,
struct drm_atomic_state *state)
{
struct drm_connector_state *conn_state;
struct dp_connector_state *dp_state;

conn_state = drm_atomic_get_new_connector_state(state, connector);
dp_state = to_dp_connector_state(conn_state);

dp_state->hdcp_transition = drm_hdcp_atomic_check(connector, state);

return 0;
}

static struct drm_connector_state *
dp_connector_atomic_duplicate_state(struct drm_connector *connector)
{
struct dp_connector_state *state;

state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return NULL;

state->hdcp_transition = false;

__drm_atomic_helper_connector_duplicate_state(connector, &state->base);
return &state->base;
}

static const struct drm_connector_funcs dp_connector_funcs = {
.detect = dp_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_duplicate_state = dp_connector_atomic_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

static const struct drm_connector_helper_funcs dp_connector_helper_funcs = {
.get_modes = dp_connector_get_modes,
.mode_valid = dp_connector_mode_valid,
.atomic_check = dp_connector_atomic_check,
};

bool dp_drm_is_connector_msm_dp(struct drm_connector *connector)
{
return connector->funcs == &dp_connector_funcs;
}

void dp_drm_atomic_commit(struct drm_connector *connector,
struct drm_connector_state *conn_state,
struct drm_atomic_state *state)
{
struct dp_connector_state *dp_state;
struct msm_dp *dp_disp;

dp_state = to_dp_connector_state(conn_state);

if (!dp_state->hdcp_transition)
return;

dp_disp = msm_dp_from_connector(connector);

dp_display_hdcp_commit(dp_disp, state);
}

/* connector initialization */
struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
{
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/msm/dp/dp_drm.h
Expand Up @@ -14,5 +14,10 @@
#include "dp_display.h"

struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display);
struct msm_dp *msm_dp_from_connector(struct drm_connector *connector);
bool dp_drm_is_connector_msm_dp(struct drm_connector *connector);
void dp_drm_atomic_commit(struct drm_connector *connector,
struct drm_connector_state *conn_state,
struct drm_atomic_state *state);

#endif /* _DP_DRM_H_ */

0 comments on commit 2fc7bb1

Please sign in to comment.