Loading drivers/gpu/drm/msm/dp/dp_debug.c +0 −65 Original line number Diff line number Diff line Loading @@ -598,56 +598,6 @@ static ssize_t dp_debug_read_connected(struct file *file, return len; } static ssize_t dp_debug_write_hdcp(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int hdcp = 0; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &hdcp) != 0) goto end; debug->dp_debug.hdcp_disabled = !hdcp; end: return len; } static ssize_t dp_debug_read_hdcp(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; u32 len = 0; if (!debug) return -ENODEV; if (*ppos) return 0; len = sizeof(debug->dp_debug.hdcp_status); if (copy_to_user(user_buff, debug->dp_debug.hdcp_status, len)) return -EFAULT; *ppos += len; return len; } static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len) { if (rc >= *max_size) { Loading Loading @@ -1287,12 +1237,6 @@ static const struct file_operations max_pclk_khz_fops = { .read = dp_debug_max_pclk_khz_read, }; static const struct file_operations hdcp_fops = { .open = simple_open, .write = dp_debug_write_hdcp, .read = dp_debug_read_hdcp, }; static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -1468,15 +1412,6 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } file = debugfs_create_file("hdcp", 0644, dir, debug, &hdcp_fops); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); pr_err("[%s] debugfs hdcp failed, rc=%d\n", DEBUG_NAME, rc); goto error_remove_dir; } return 0; error_remove_dir: Loading drivers/gpu/drm/msm/dp/dp_debug.h +0 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ struct dp_debug { bool debug_en; bool sim_mode; bool psm_enabled; bool hdcp_disabled; int aspect_ratio; int vdisplay; int hdisplay; Loading @@ -42,7 +41,6 @@ struct dp_debug { bool tpg_state; u32 max_pclk_khz; bool force_encryption; char hdcp_status[SZ_128]; u8 *(*get_edid)(struct dp_debug *dp_debug); }; Loading drivers/gpu/drm/msm/dp/dp_display.c +76 −124 Original line number Diff line number Diff line Loading @@ -43,19 +43,14 @@ static struct dp_display *g_dp_display; #define HPD_STRING_SIZE 30 struct dp_hdcp_dev { void *fd; struct sde_hdcp_ops *ops; enum sde_hdcp_version ver; }; struct dp_hdcp { void *data; struct sde_hdcp_ops *ops; u32 source_cap; void *hdcp1; void *hdcp2; struct dp_hdcp_dev dev[HDCP_VERSION_MAX]; bool feature_enabled; }; struct dp_mst { Loading Loading @@ -121,7 +116,8 @@ static bool dp_display_framework_ready(struct dp_display_private *dp) static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) { return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; return dp->hdcp.feature_enabled && dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; } static irqreturn_t dp_display_irq(int irq, void *dev_id) Loading Loading @@ -166,83 +162,16 @@ static bool dp_display_is_ready(struct dp_display_private *dp) dp->hpd->alt_mode_cfg_done; } static void dp_display_update_hdcp_status(struct dp_display_private *dp, bool reset) { if (reset) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE; } memset(dp->debug->hdcp_status, 0, sizeof(dp->debug->hdcp_status)); snprintf(dp->debug->hdcp_status, sizeof(dp->debug->hdcp_status), "%s: %s\ncaps: %d\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version), sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state), dp->hdcp.source_cap); } static void dp_display_update_hdcp_info(struct dp_display_private *dp) { void *fd = NULL; struct dp_hdcp_dev *dev = NULL; struct sde_hdcp_ops *ops = NULL; int i = HDCP_VERSION_2P2; dp_display_update_hdcp_status(dp, true); dp->hdcp.data = NULL; dp->hdcp.ops = NULL; if (dp->debug->hdcp_disabled || dp->debug->sim_mode) return; while (i) { dev = &dp->hdcp.dev[i]; ops = dev->ops; fd = dev->fd; i >>= 1; if (!(dp->hdcp.source_cap & dev->ver)) continue; if (ops->sink_support(fd)) { dp->hdcp.data = fd; dp->hdcp.ops = ops; dp->link->hdcp_status.hdcp_version = dev->ver; break; } } pr_debug("HDCP version supported: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version)); } static void dp_display_hdcp_cb_work(struct work_struct *work) { struct dp_display_private *dp; struct delayed_work *dw = to_delayed_work(work); struct sde_hdcp_ops *ops; struct dp_link_hdcp_status *status; void *data; int rc = 0; u32 hdcp_auth_state; dp = container_of(dw, struct dp_display_private, hdcp_cb_work); status = &dp->link->hdcp_status; if (status->hdcp_state == HDCP_STATE_INACTIVE) { dp_display_update_hdcp_info(dp); if (dp_display_is_hdcp_enabled(dp)) { status->hdcp_state = HDCP_STATE_AUTHENTICATING; } else { dp_display_update_hdcp_status(dp, true); return; } } rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl); if (rc >= 0) { Loading @@ -253,15 +182,14 @@ static void dp_display_hdcp_cb_work(struct work_struct *work) ops = dp->hdcp.ops; data = dp->hdcp.data; pr_debug("%s: %s\n", sde_hdcp_version(status->hdcp_version), sde_hdcp_state_name(status->hdcp_state)); dp_display_update_hdcp_status(dp, false); pr_debug("%s: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version), sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state)); if (dp->debug->force_encryption && ops && ops->force_encryption) ops->force_encryption(data, dp->debug->force_encryption); switch (status->hdcp_state) { switch (dp->link->hdcp_status.hdcp_state) { case HDCP_STATE_AUTHENTICATING: if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(data); Loading Loading @@ -298,35 +226,62 @@ static void dp_display_notify_hdcp_status_cb(void *ptr, queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ/4); } static void dp_display_check_source_hdcp_caps(struct dp_display_private *dp) static void dp_display_update_hdcp_info(struct dp_display_private *dp) { int i; struct dp_hdcp_dev *hdcp_dev = dp->hdcp.dev; void *fd = NULL; struct sde_hdcp_ops *ops = NULL; bool hdcp2_present = false, hdcp1_present = false; if (dp->debug->hdcp_disabled) { pr_debug("hdcp disabled\n"); if (!dp) { pr_err("invalid input\n"); return; } for (i = 0; i < HDCP_VERSION_MAX; i++) { struct dp_hdcp_dev *dev = &hdcp_dev[i]; struct sde_hdcp_ops *ops = dev->ops; void *fd = dev->fd; dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE; if (!fd || !ops) continue; if (!dp->hdcp.feature_enabled) { pr_debug("feature not enabled\n"); return; } if (ops->feature_supported(fd)) dp->hdcp.source_cap |= dev->ver; else pr_warn("This device doesn't support %s\n", sde_hdcp_version(dev->ver)); if (dp->debug->sim_mode) { pr_debug("skip HDCP version checks for simulation mode\n"); return; } if (!dp->hdcp.source_cap) dp->debug->hdcp_disabled = true; fd = dp->hdcp.hdcp2; if (fd) ops = sde_dp_hdcp2p2_start(fd); if (ops && ops->feature_supported) hdcp2_present = ops->feature_supported(fd); if (hdcp2_present) dp->link->hdcp_status.hdcp_version = HDCP_VERSION_2P2; dp_display_update_hdcp_status(dp, false); if (!hdcp2_present) { fd = dp->hdcp.hdcp1; if (fd) ops = sde_hdcp_1x_start(fd); if (ops && ops->feature_supported) hdcp1_present = ops->feature_supported(fd); if (hdcp1_present) dp->link->hdcp_status.hdcp_version = HDCP_VERSION_1X; } if (hdcp2_present || hdcp1_present) { dp->hdcp.data = fd; dp->hdcp.ops = ops; } else { dp->hdcp.data = NULL; dp->hdcp.ops = NULL; } pr_debug("HDCP version supported: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version)); } static void dp_display_deinitialize_hdcp(struct dp_display_private *dp) Loading @@ -343,7 +298,6 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp) { struct sde_hdcp_init_data hdcp_init_data; struct dp_parser *parser; void *fd; int rc = 0; if (!dp) { Loading @@ -370,35 +324,29 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp) hdcp_init_data.revision = &dp->panel->link_info.revision; hdcp_init_data.msm_hdcp_dev = dp->parser->msm_hdcp_dev; fd = sde_hdcp_1x_init(&hdcp_init_data); if (IS_ERR_OR_NULL(fd)) { dp->hdcp.hdcp1 = sde_hdcp_1x_init(&hdcp_init_data); if (IS_ERR_OR_NULL(dp->hdcp.hdcp1)) { pr_err("Error initializing HDCP 1.x\n"); rc = -EINVAL; goto error; } dp->hdcp.dev[HDCP_VERSION_1X].fd = fd; dp->hdcp.dev[HDCP_VERSION_1X].ops = sde_hdcp_1x_get(fd); dp->hdcp.dev[HDCP_VERSION_1X].ver = HDCP_VERSION_1X; pr_debug("HDCP 1.3 initialized\n"); fd = sde_dp_hdcp2p2_init(&hdcp_init_data); if (IS_ERR_OR_NULL(fd)) { dp->hdcp.hdcp2 = sde_dp_hdcp2p2_init(&hdcp_init_data); if (IS_ERR_OR_NULL(dp->hdcp.hdcp2)) { pr_err("Error initializing HDCP 2.x\n"); rc = -EINVAL; goto error; } dp->hdcp.dev[HDCP_VERSION_2P2].fd = fd; dp->hdcp.dev[HDCP_VERSION_2P2].ops = sde_dp_hdcp2p2_get(fd); dp->hdcp.dev[HDCP_VERSION_2P2].ver = HDCP_VERSION_2P2; pr_debug("HDCP 2.2 initialized\n"); dp->hdcp.feature_enabled = true; return 0; error: dp_display_deinitialize_hdcp(dp); dp->debug->hdcp_disabled = true; return rc; } Loading Loading @@ -527,9 +475,6 @@ static void dp_display_post_open(struct dp_display *dp_display) return; } dp_display_update_hdcp_status(dp, true); dp_display_check_source_hdcp_caps(dp); /* if cable is already connected, send notification */ if (dp->hpd->hpd_high) queue_delayed_work(dp->wq, &dp->connect_work, HZ * 10); Loading Loading @@ -775,11 +720,11 @@ static void dp_display_clean(struct dp_display_private *dp) struct dp_panel *dp_panel; if (dp_display_is_hdcp_enabled(dp)) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; cancel_delayed_work_sync(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); dp_display_update_hdcp_status(dp, true); } for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { Loading Loading @@ -918,7 +863,7 @@ static void dp_display_attention_work(struct work_struct *work) struct dp_display_private, attention_work); if (dp->link->process_request(dp->link)) goto cp_irq; goto mst_attention; if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { if (dp_display_is_sink_count_zero(dp)) { Loading Loading @@ -954,7 +899,7 @@ static void dp_display_attention_work(struct work_struct *work) if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) dp->ctrl->link_maintenance(dp->ctrl); cp_irq: if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) dp->hdcp.ops->cp_irq(dp->hdcp.data); mst_attention: Loading Loading @@ -1456,8 +1401,15 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) dp_panel->audio->on(dp_panel->audio); } dp_display_update_hdcp_info(dp); if (dp_display_is_hdcp_enabled(dp)) { cancel_delayed_work_sync(&dp->hdcp_cb_work); queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ); dp->link->hdcp_status.hdcp_state = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading Loading @@ -1497,11 +1449,11 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) } if (dp_display_is_hdcp_enabled(dp)) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; cancel_delayed_work_sync(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); dp_display_update_hdcp_status(dp, true); } if (dp_panel->audio_supported) Loading drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +31 −28 Original line number Diff line number Diff line Loading @@ -777,31 +777,6 @@ static int dp_hdcp2p2_isr(void *input) return rc; } static bool dp_hdcp2p2_supported(void *input) { struct dp_hdcp2p2_ctrl *ctrl = input; u32 const rxcaps_dpcd_offset = 0x6921d; ssize_t bytes_read = 0; u8 buf[DP_HDCP_RXCAPS_LENGTH]; pr_debug("Checking sink capability\n"); bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH); if (bytes_read != DP_HDCP_RXCAPS_LENGTH) { pr_err("RxCaps read failed\n"); goto error; } pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1); pr_debug("VERSION=%d\n", buf[0]); if ((buf[2] & BIT(1)) && (buf[0] == 0x2)) return true; error: return false; } void sde_dp_hdcp2p2_deinit(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading Loading @@ -834,7 +809,6 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) .authenticate = dp_hdcp2p2_authenticate, .feature_supported = dp_hdcp2p2_feature_supported, .force_encryption = dp_hdcp2p2_force_encryption, .sink_support = dp_hdcp2p2_supported, .off = dp_hdcp2p2_off, .cp_irq = dp_hdcp2p2_cp_irq, }; Loading Loading @@ -926,8 +900,37 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) return ERR_PTR(rc); } struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input) static bool dp_hdcp2p2_supported(struct dp_hdcp2p2_ctrl *ctrl) { u32 const rxcaps_dpcd_offset = 0x6921d; ssize_t bytes_read = 0; u8 buf[DP_HDCP_RXCAPS_LENGTH]; bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH); if (bytes_read != DP_HDCP_RXCAPS_LENGTH) { pr_err("RxCaps read failed\n"); goto error; } pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1); pr_debug("VERSION=%d\n", buf[0]); if ((buf[2] & BIT(1)) && (buf[0] == 0x2)) return true; error: return false; } struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input) { return ((struct dp_hdcp2p2_ctrl *)input)->ops; struct dp_hdcp2p2_ctrl *ctrl = input; pr_debug("Checking sink capability\n"); if (dp_hdcp2p2_supported(ctrl)) return ctrl->ops; else return NULL; } drivers/gpu/drm/msm/sde_hdcp.h +4 −6 Original line number Diff line number Diff line Loading @@ -40,9 +40,8 @@ enum sde_hdcp_state { enum sde_hdcp_version { HDCP_VERSION_NONE, HDCP_VERSION_1X = BIT(0), HDCP_VERSION_2P2 = BIT(1), HDCP_VERSION_MAX = BIT(2), HDCP_VERSION_1X, HDCP_VERSION_2P2 }; struct sde_hdcp_init_data { Loading Loading @@ -73,7 +72,6 @@ struct sde_hdcp_ops { int (*authenticate)(void *hdcp_ctrl); bool (*feature_supported)(void *input); void (*force_encryption)(void *input, bool enable); bool (*sink_support)(void *input); void (*off)(void *hdcp_ctrl); }; Loading @@ -100,8 +98,8 @@ static inline const char *sde_hdcp_version(enum sde_hdcp_version hdcp_version) void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data); void sde_hdcp_1x_deinit(void *input); struct sde_hdcp_ops *sde_hdcp_1x_get(void *input); struct sde_hdcp_ops *sde_hdcp_1x_start(void *input); void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data); void sde_dp_hdcp2p2_deinit(void *input); struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input); struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input); #endif /* __SDE_HDCP_H__ */ Loading
drivers/gpu/drm/msm/dp/dp_debug.c +0 −65 Original line number Diff line number Diff line Loading @@ -598,56 +598,6 @@ static ssize_t dp_debug_read_connected(struct file *file, return len; } static ssize_t dp_debug_write_hdcp(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int hdcp = 0; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &hdcp) != 0) goto end; debug->dp_debug.hdcp_disabled = !hdcp; end: return len; } static ssize_t dp_debug_read_hdcp(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; u32 len = 0; if (!debug) return -ENODEV; if (*ppos) return 0; len = sizeof(debug->dp_debug.hdcp_status); if (copy_to_user(user_buff, debug->dp_debug.hdcp_status, len)) return -EFAULT; *ppos += len; return len; } static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len) { if (rc >= *max_size) { Loading Loading @@ -1287,12 +1237,6 @@ static const struct file_operations max_pclk_khz_fops = { .read = dp_debug_max_pclk_khz_read, }; static const struct file_operations hdcp_fops = { .open = simple_open, .write = dp_debug_write_hdcp, .read = dp_debug_read_hdcp, }; static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -1468,15 +1412,6 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } file = debugfs_create_file("hdcp", 0644, dir, debug, &hdcp_fops); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); pr_err("[%s] debugfs hdcp failed, rc=%d\n", DEBUG_NAME, rc); goto error_remove_dir; } return 0; error_remove_dir: Loading
drivers/gpu/drm/msm/dp/dp_debug.h +0 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ struct dp_debug { bool debug_en; bool sim_mode; bool psm_enabled; bool hdcp_disabled; int aspect_ratio; int vdisplay; int hdisplay; Loading @@ -42,7 +41,6 @@ struct dp_debug { bool tpg_state; u32 max_pclk_khz; bool force_encryption; char hdcp_status[SZ_128]; u8 *(*get_edid)(struct dp_debug *dp_debug); }; Loading
drivers/gpu/drm/msm/dp/dp_display.c +76 −124 Original line number Diff line number Diff line Loading @@ -43,19 +43,14 @@ static struct dp_display *g_dp_display; #define HPD_STRING_SIZE 30 struct dp_hdcp_dev { void *fd; struct sde_hdcp_ops *ops; enum sde_hdcp_version ver; }; struct dp_hdcp { void *data; struct sde_hdcp_ops *ops; u32 source_cap; void *hdcp1; void *hdcp2; struct dp_hdcp_dev dev[HDCP_VERSION_MAX]; bool feature_enabled; }; struct dp_mst { Loading Loading @@ -121,7 +116,8 @@ static bool dp_display_framework_ready(struct dp_display_private *dp) static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) { return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; return dp->hdcp.feature_enabled && dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; } static irqreturn_t dp_display_irq(int irq, void *dev_id) Loading Loading @@ -166,83 +162,16 @@ static bool dp_display_is_ready(struct dp_display_private *dp) dp->hpd->alt_mode_cfg_done; } static void dp_display_update_hdcp_status(struct dp_display_private *dp, bool reset) { if (reset) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE; } memset(dp->debug->hdcp_status, 0, sizeof(dp->debug->hdcp_status)); snprintf(dp->debug->hdcp_status, sizeof(dp->debug->hdcp_status), "%s: %s\ncaps: %d\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version), sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state), dp->hdcp.source_cap); } static void dp_display_update_hdcp_info(struct dp_display_private *dp) { void *fd = NULL; struct dp_hdcp_dev *dev = NULL; struct sde_hdcp_ops *ops = NULL; int i = HDCP_VERSION_2P2; dp_display_update_hdcp_status(dp, true); dp->hdcp.data = NULL; dp->hdcp.ops = NULL; if (dp->debug->hdcp_disabled || dp->debug->sim_mode) return; while (i) { dev = &dp->hdcp.dev[i]; ops = dev->ops; fd = dev->fd; i >>= 1; if (!(dp->hdcp.source_cap & dev->ver)) continue; if (ops->sink_support(fd)) { dp->hdcp.data = fd; dp->hdcp.ops = ops; dp->link->hdcp_status.hdcp_version = dev->ver; break; } } pr_debug("HDCP version supported: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version)); } static void dp_display_hdcp_cb_work(struct work_struct *work) { struct dp_display_private *dp; struct delayed_work *dw = to_delayed_work(work); struct sde_hdcp_ops *ops; struct dp_link_hdcp_status *status; void *data; int rc = 0; u32 hdcp_auth_state; dp = container_of(dw, struct dp_display_private, hdcp_cb_work); status = &dp->link->hdcp_status; if (status->hdcp_state == HDCP_STATE_INACTIVE) { dp_display_update_hdcp_info(dp); if (dp_display_is_hdcp_enabled(dp)) { status->hdcp_state = HDCP_STATE_AUTHENTICATING; } else { dp_display_update_hdcp_status(dp, true); return; } } rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl); if (rc >= 0) { Loading @@ -253,15 +182,14 @@ static void dp_display_hdcp_cb_work(struct work_struct *work) ops = dp->hdcp.ops; data = dp->hdcp.data; pr_debug("%s: %s\n", sde_hdcp_version(status->hdcp_version), sde_hdcp_state_name(status->hdcp_state)); dp_display_update_hdcp_status(dp, false); pr_debug("%s: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version), sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state)); if (dp->debug->force_encryption && ops && ops->force_encryption) ops->force_encryption(data, dp->debug->force_encryption); switch (status->hdcp_state) { switch (dp->link->hdcp_status.hdcp_state) { case HDCP_STATE_AUTHENTICATING: if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(data); Loading Loading @@ -298,35 +226,62 @@ static void dp_display_notify_hdcp_status_cb(void *ptr, queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ/4); } static void dp_display_check_source_hdcp_caps(struct dp_display_private *dp) static void dp_display_update_hdcp_info(struct dp_display_private *dp) { int i; struct dp_hdcp_dev *hdcp_dev = dp->hdcp.dev; void *fd = NULL; struct sde_hdcp_ops *ops = NULL; bool hdcp2_present = false, hdcp1_present = false; if (dp->debug->hdcp_disabled) { pr_debug("hdcp disabled\n"); if (!dp) { pr_err("invalid input\n"); return; } for (i = 0; i < HDCP_VERSION_MAX; i++) { struct dp_hdcp_dev *dev = &hdcp_dev[i]; struct sde_hdcp_ops *ops = dev->ops; void *fd = dev->fd; dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE; if (!fd || !ops) continue; if (!dp->hdcp.feature_enabled) { pr_debug("feature not enabled\n"); return; } if (ops->feature_supported(fd)) dp->hdcp.source_cap |= dev->ver; else pr_warn("This device doesn't support %s\n", sde_hdcp_version(dev->ver)); if (dp->debug->sim_mode) { pr_debug("skip HDCP version checks for simulation mode\n"); return; } if (!dp->hdcp.source_cap) dp->debug->hdcp_disabled = true; fd = dp->hdcp.hdcp2; if (fd) ops = sde_dp_hdcp2p2_start(fd); if (ops && ops->feature_supported) hdcp2_present = ops->feature_supported(fd); if (hdcp2_present) dp->link->hdcp_status.hdcp_version = HDCP_VERSION_2P2; dp_display_update_hdcp_status(dp, false); if (!hdcp2_present) { fd = dp->hdcp.hdcp1; if (fd) ops = sde_hdcp_1x_start(fd); if (ops && ops->feature_supported) hdcp1_present = ops->feature_supported(fd); if (hdcp1_present) dp->link->hdcp_status.hdcp_version = HDCP_VERSION_1X; } if (hdcp2_present || hdcp1_present) { dp->hdcp.data = fd; dp->hdcp.ops = ops; } else { dp->hdcp.data = NULL; dp->hdcp.ops = NULL; } pr_debug("HDCP version supported: %s\n", sde_hdcp_version(dp->link->hdcp_status.hdcp_version)); } static void dp_display_deinitialize_hdcp(struct dp_display_private *dp) Loading @@ -343,7 +298,6 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp) { struct sde_hdcp_init_data hdcp_init_data; struct dp_parser *parser; void *fd; int rc = 0; if (!dp) { Loading @@ -370,35 +324,29 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp) hdcp_init_data.revision = &dp->panel->link_info.revision; hdcp_init_data.msm_hdcp_dev = dp->parser->msm_hdcp_dev; fd = sde_hdcp_1x_init(&hdcp_init_data); if (IS_ERR_OR_NULL(fd)) { dp->hdcp.hdcp1 = sde_hdcp_1x_init(&hdcp_init_data); if (IS_ERR_OR_NULL(dp->hdcp.hdcp1)) { pr_err("Error initializing HDCP 1.x\n"); rc = -EINVAL; goto error; } dp->hdcp.dev[HDCP_VERSION_1X].fd = fd; dp->hdcp.dev[HDCP_VERSION_1X].ops = sde_hdcp_1x_get(fd); dp->hdcp.dev[HDCP_VERSION_1X].ver = HDCP_VERSION_1X; pr_debug("HDCP 1.3 initialized\n"); fd = sde_dp_hdcp2p2_init(&hdcp_init_data); if (IS_ERR_OR_NULL(fd)) { dp->hdcp.hdcp2 = sde_dp_hdcp2p2_init(&hdcp_init_data); if (IS_ERR_OR_NULL(dp->hdcp.hdcp2)) { pr_err("Error initializing HDCP 2.x\n"); rc = -EINVAL; goto error; } dp->hdcp.dev[HDCP_VERSION_2P2].fd = fd; dp->hdcp.dev[HDCP_VERSION_2P2].ops = sde_dp_hdcp2p2_get(fd); dp->hdcp.dev[HDCP_VERSION_2P2].ver = HDCP_VERSION_2P2; pr_debug("HDCP 2.2 initialized\n"); dp->hdcp.feature_enabled = true; return 0; error: dp_display_deinitialize_hdcp(dp); dp->debug->hdcp_disabled = true; return rc; } Loading Loading @@ -527,9 +475,6 @@ static void dp_display_post_open(struct dp_display *dp_display) return; } dp_display_update_hdcp_status(dp, true); dp_display_check_source_hdcp_caps(dp); /* if cable is already connected, send notification */ if (dp->hpd->hpd_high) queue_delayed_work(dp->wq, &dp->connect_work, HZ * 10); Loading Loading @@ -775,11 +720,11 @@ static void dp_display_clean(struct dp_display_private *dp) struct dp_panel *dp_panel; if (dp_display_is_hdcp_enabled(dp)) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; cancel_delayed_work_sync(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); dp_display_update_hdcp_status(dp, true); } for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { Loading Loading @@ -918,7 +863,7 @@ static void dp_display_attention_work(struct work_struct *work) struct dp_display_private, attention_work); if (dp->link->process_request(dp->link)) goto cp_irq; goto mst_attention; if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { if (dp_display_is_sink_count_zero(dp)) { Loading Loading @@ -954,7 +899,7 @@ static void dp_display_attention_work(struct work_struct *work) if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) dp->ctrl->link_maintenance(dp->ctrl); cp_irq: if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) dp->hdcp.ops->cp_irq(dp->hdcp.data); mst_attention: Loading Loading @@ -1456,8 +1401,15 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) dp_panel->audio->on(dp_panel->audio); } dp_display_update_hdcp_info(dp); if (dp_display_is_hdcp_enabled(dp)) { cancel_delayed_work_sync(&dp->hdcp_cb_work); queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ); dp->link->hdcp_status.hdcp_state = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading Loading @@ -1497,11 +1449,11 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) } if (dp_display_is_hdcp_enabled(dp)) { dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; cancel_delayed_work_sync(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); dp_display_update_hdcp_status(dp, true); } if (dp_panel->audio_supported) Loading
drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +31 −28 Original line number Diff line number Diff line Loading @@ -777,31 +777,6 @@ static int dp_hdcp2p2_isr(void *input) return rc; } static bool dp_hdcp2p2_supported(void *input) { struct dp_hdcp2p2_ctrl *ctrl = input; u32 const rxcaps_dpcd_offset = 0x6921d; ssize_t bytes_read = 0; u8 buf[DP_HDCP_RXCAPS_LENGTH]; pr_debug("Checking sink capability\n"); bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH); if (bytes_read != DP_HDCP_RXCAPS_LENGTH) { pr_err("RxCaps read failed\n"); goto error; } pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1); pr_debug("VERSION=%d\n", buf[0]); if ((buf[2] & BIT(1)) && (buf[0] == 0x2)) return true; error: return false; } void sde_dp_hdcp2p2_deinit(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading Loading @@ -834,7 +809,6 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) .authenticate = dp_hdcp2p2_authenticate, .feature_supported = dp_hdcp2p2_feature_supported, .force_encryption = dp_hdcp2p2_force_encryption, .sink_support = dp_hdcp2p2_supported, .off = dp_hdcp2p2_off, .cp_irq = dp_hdcp2p2_cp_irq, }; Loading Loading @@ -926,8 +900,37 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) return ERR_PTR(rc); } struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input) static bool dp_hdcp2p2_supported(struct dp_hdcp2p2_ctrl *ctrl) { u32 const rxcaps_dpcd_offset = 0x6921d; ssize_t bytes_read = 0; u8 buf[DP_HDCP_RXCAPS_LENGTH]; bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH); if (bytes_read != DP_HDCP_RXCAPS_LENGTH) { pr_err("RxCaps read failed\n"); goto error; } pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1); pr_debug("VERSION=%d\n", buf[0]); if ((buf[2] & BIT(1)) && (buf[0] == 0x2)) return true; error: return false; } struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input) { return ((struct dp_hdcp2p2_ctrl *)input)->ops; struct dp_hdcp2p2_ctrl *ctrl = input; pr_debug("Checking sink capability\n"); if (dp_hdcp2p2_supported(ctrl)) return ctrl->ops; else return NULL; }
drivers/gpu/drm/msm/sde_hdcp.h +4 −6 Original line number Diff line number Diff line Loading @@ -40,9 +40,8 @@ enum sde_hdcp_state { enum sde_hdcp_version { HDCP_VERSION_NONE, HDCP_VERSION_1X = BIT(0), HDCP_VERSION_2P2 = BIT(1), HDCP_VERSION_MAX = BIT(2), HDCP_VERSION_1X, HDCP_VERSION_2P2 }; struct sde_hdcp_init_data { Loading Loading @@ -73,7 +72,6 @@ struct sde_hdcp_ops { int (*authenticate)(void *hdcp_ctrl); bool (*feature_supported)(void *input); void (*force_encryption)(void *input, bool enable); bool (*sink_support)(void *input); void (*off)(void *hdcp_ctrl); }; Loading @@ -100,8 +98,8 @@ static inline const char *sde_hdcp_version(enum sde_hdcp_version hdcp_version) void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data); void sde_hdcp_1x_deinit(void *input); struct sde_hdcp_ops *sde_hdcp_1x_get(void *input); struct sde_hdcp_ops *sde_hdcp_1x_start(void *input); void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data); void sde_dp_hdcp2p2_deinit(void *input); struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input); struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input); #endif /* __SDE_HDCP_H__ */