Loading drivers/video/fbdev/msm/mdss_dp.c +40 −19 Original line number Diff line number Diff line Loading @@ -1286,12 +1286,8 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) link_training: dp_drv->power_on = true; if (-EAGAIN == mdss_dp_train_main_link(dp_drv)) { mutex_unlock(&dp_drv->train_mutex); mdss_dp_link_retraining(dp_drv); return 0; } while (-EAGAIN == mdss_dp_train_main_link(dp_drv)) pr_debug("MAIN LINK TRAINING RETRY\n"); dp_drv->cont_splash = 0; Loading Loading @@ -1622,13 +1618,27 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work) struct mdss_dp_drv_pdata *dp; struct delayed_work *dw = to_delayed_work(work); struct hdcp_ops *ops; unsigned char *base; int rc = 0; u32 hdcp_auth_state; dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work); base = dp->base; hdcp_auth_state = (dp_read(base + DP_HDCP_STATUS) >> 20) & 0x3; pr_debug("hdcp auth state %d\n", hdcp_auth_state); ops = dp->hdcp.ops; switch (dp->hdcp_status) { case HDCP_STATE_AUTHENTICATING: pr_debug("start authenticaton\n"); if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); break; case HDCP_STATE_AUTHENTICATED: pr_debug("hdcp authenticated\n"); dp->hdcp.auth_state = true; Loading @@ -1636,7 +1646,7 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work) case HDCP_STATE_AUTH_FAIL: dp->hdcp.auth_state = false; if (dp->power_on) { if (dp->alt_mode.dp_status.hpd_high && dp->power_on) { pr_debug("Reauthenticating\n"); if (ops && ops->reauthenticate) { rc = ops->reauthenticate(dp->hdcp.data); Loading Loading @@ -1664,6 +1674,7 @@ static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status) dp->hdcp_status = status; if (dp->alt_mode.dp_status.hpd_high) queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4); } Loading Loading @@ -1927,19 +1938,27 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, rc = mdss_dp_on(pdata); break; case MDSS_EVENT_PANEL_ON: mdss_dp_ack_state(dp, true); mdss_dp_update_hdcp_info(dp); if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); if (dp_is_hdcp_enabled(dp)) { cancel_delayed_work(&dp->hdcp_cb_work); mdss_dp_ack_state(dp, true); dp->hdcp_status = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ / 2); } break; case MDSS_EVENT_PANEL_OFF: rc = mdss_dp_off(pdata); break; case MDSS_EVENT_BLANK: if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) { flush_delayed_work(&dp->hdcp_cb_work); if (dp_is_hdcp_enabled(dp)) { dp->hdcp_status = HDCP_STATE_INACTIVE; cancel_delayed_work(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); } Loading Loading @@ -2189,9 +2208,6 @@ irqreturn_t dp_isr(int irq, void *ptr) isr1 &= ~mask1; /* remove masks bit */ pr_debug("isr=%x mask=%x isr2=%x\n", isr1, mask1, isr2); ack = isr1 & EDP_INTR_STATUS1; ack <<= 1; /* ack bits */ ack |= mask1; Loading Loading @@ -2601,8 +2617,7 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) if (dp_drv->alt_mode.dp_status.hpd_irq) { pr_debug("Attention: hpd_irq high\n"); if (dp_drv->power_on && dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) { if (dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) { if (!dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data)) return; } Loading @@ -2616,6 +2631,12 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) if (!dp_drv->alt_mode.dp_status.hpd_high) { pr_debug("Attention: HPD low\n"); if (dp_is_hdcp_enabled(dp_drv) && dp_drv->hdcp.ops->off) { cancel_delayed_work(&dp_drv->hdcp_cb_work); dp_drv->hdcp.ops->off(dp_drv->hdcp.data); } mdss_dp_update_cable_status(dp_drv, false); mdss_dp_notify_clients(dp_drv, false); pr_debug("Attention: Notified clients\n"); Loading drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c +114 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "mdss_hdcp.h" #include "mdss_dp_util.h" struct dp_hdcp2p2_ctrl; enum dp_hdcp2p2_sink_status { SINK_DISCONNECTED, SINK_CONNECTED Loading @@ -33,9 +35,21 @@ enum dp_auth_status { DP_HDCP_AUTH_STATUS_SUCCESS }; struct dp_hdcp2p2_int_set { u32 interrupt; char *name; void (*func)(struct dp_hdcp2p2_ctrl *ctrl); }; struct dp_hdcp2p2_interrupts { u32 reg; struct dp_hdcp2p2_int_set *int_set; }; struct dp_hdcp2p2_ctrl { atomic_t auth_state; enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */ struct dp_hdcp2p2_interrupts *intr; struct hdcp_init_data init_data; struct mutex mutex; /* mutex to protect access to ctrl */ struct mutex msg_lock; /* mutex to protect access to msg buffer */ Loading Loading @@ -172,6 +186,9 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_LINK_POLL: if (ctrl->cp_irq_done) queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: Loading Loading @@ -211,6 +228,31 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); } static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable) { unsigned char *base = ctrl->init_data.core_io->base; struct dp_hdcp2p2_interrupts *intr = ctrl->intr; while (intr && intr->reg) { struct dp_hdcp2p2_int_set *int_set = intr->int_set; u32 interrupts = 0; while (int_set && int_set->interrupt) { interrupts |= int_set->interrupt; int_set++; } if (enable) dp_write(base + intr->reg, dp_read(base + intr->reg) | interrupts); else dp_write(base + intr->reg, dp_read(base + intr->reg) & ~interrupts); intr++; } } static void dp_hdcp2p2_off(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading @@ -221,6 +263,13 @@ static void dp_hdcp2p2_off(void *input) return; } if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); return; } dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_reset(ctrl); flush_kthread_worker(&ctrl->worker); Loading @@ -237,6 +286,8 @@ static int dp_hdcp2p2_authenticate(void *input) flush_kthread_worker(&ctrl->worker); dp_hdcp2p2_set_interrupts(ctrl, true); ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); Loading Loading @@ -317,6 +368,8 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl) return; } dp_hdcp2p2_set_interrupts(ctrl, false); /* notify DP about HDCP failure */ ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTH_FAIL); Loading Loading @@ -640,6 +693,8 @@ static int dp_hdcp2p2_cp_irq(void *input) goto error; } pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status); if (!ctrl->sink_rx_status) { pr_debug("not a hdcp 2.2 irq\n"); rc = -EINVAL; Loading @@ -653,6 +708,46 @@ error: return rc; } static int dp_hdcp2p2_isr(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; int rc = 0; struct dss_io_data *io; struct dp_hdcp2p2_interrupts *intr; u32 hdcp_int_val; if (!ctrl || !ctrl->init_data.core_io) { pr_err("invalid input\n"); rc = -EINVAL; goto end; } io = ctrl->init_data.core_io; intr = ctrl->intr; while (intr && intr->reg) { struct dp_hdcp2p2_int_set *int_set = intr->int_set; hdcp_int_val = dp_read(io->base + intr->reg); while (int_set && int_set->interrupt) { if (hdcp_int_val & (int_set->interrupt >> 2)) { pr_debug("%s\n", int_set->name); if (int_set->func) int_set->func(ctrl); dp_write(io->base + intr->reg, hdcp_int_val | (int_set->interrupt >> 1)); } int_set++; } intr++; } end: return rc; } void dp_hdcp2p2_deinit(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading Loading @@ -684,6 +779,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) int rc; struct dp_hdcp2p2_ctrl *ctrl; static struct hdcp_ops ops = { .isr = dp_hdcp2p2_isr, .reauthenticate = dp_hdcp2p2_reauthenticate, .authenticate = dp_hdcp2p2_authenticate, .feature_supported = dp_hdcp2p2_feature_supported, Loading @@ -694,7 +790,22 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) static struct hdcp_client_ops client_ops = { .wakeup = dp_hdcp2p2_wakeup, }; static struct dp_hdcp2p2_int_set int_set1[] = { {BIT(17), "authentication successful", 0}, {BIT(20), "authentication failed", 0}, {BIT(24), "encryption enabled", 0}, {BIT(27), "encryption disabled", 0}, {0}, }; static struct dp_hdcp2p2_int_set int_set2[] = { {BIT(2), "key fifo underflow", 0}, {0}, }; static struct dp_hdcp2p2_interrupts intr[] = { {DP_INTR_STATUS2, int_set1}, {DP_INTR_STATUS3, int_set2}, {0} }; static struct hdcp_txmtr_ops txmtr_ops; struct hdcp_register_data register_data = {0}; Loading @@ -719,6 +830,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) } ctrl->sink_status = SINK_DISCONNECTED; ctrl->intr = intr; atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); Loading Loading
drivers/video/fbdev/msm/mdss_dp.c +40 −19 Original line number Diff line number Diff line Loading @@ -1286,12 +1286,8 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) link_training: dp_drv->power_on = true; if (-EAGAIN == mdss_dp_train_main_link(dp_drv)) { mutex_unlock(&dp_drv->train_mutex); mdss_dp_link_retraining(dp_drv); return 0; } while (-EAGAIN == mdss_dp_train_main_link(dp_drv)) pr_debug("MAIN LINK TRAINING RETRY\n"); dp_drv->cont_splash = 0; Loading Loading @@ -1622,13 +1618,27 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work) struct mdss_dp_drv_pdata *dp; struct delayed_work *dw = to_delayed_work(work); struct hdcp_ops *ops; unsigned char *base; int rc = 0; u32 hdcp_auth_state; dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work); base = dp->base; hdcp_auth_state = (dp_read(base + DP_HDCP_STATUS) >> 20) & 0x3; pr_debug("hdcp auth state %d\n", hdcp_auth_state); ops = dp->hdcp.ops; switch (dp->hdcp_status) { case HDCP_STATE_AUTHENTICATING: pr_debug("start authenticaton\n"); if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); break; case HDCP_STATE_AUTHENTICATED: pr_debug("hdcp authenticated\n"); dp->hdcp.auth_state = true; Loading @@ -1636,7 +1646,7 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work) case HDCP_STATE_AUTH_FAIL: dp->hdcp.auth_state = false; if (dp->power_on) { if (dp->alt_mode.dp_status.hpd_high && dp->power_on) { pr_debug("Reauthenticating\n"); if (ops && ops->reauthenticate) { rc = ops->reauthenticate(dp->hdcp.data); Loading Loading @@ -1664,6 +1674,7 @@ static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status) dp->hdcp_status = status; if (dp->alt_mode.dp_status.hpd_high) queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4); } Loading Loading @@ -1927,19 +1938,27 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, rc = mdss_dp_on(pdata); break; case MDSS_EVENT_PANEL_ON: mdss_dp_ack_state(dp, true); mdss_dp_update_hdcp_info(dp); if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); if (dp_is_hdcp_enabled(dp)) { cancel_delayed_work(&dp->hdcp_cb_work); mdss_dp_ack_state(dp, true); dp->hdcp_status = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ / 2); } break; case MDSS_EVENT_PANEL_OFF: rc = mdss_dp_off(pdata); break; case MDSS_EVENT_BLANK: if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) { flush_delayed_work(&dp->hdcp_cb_work); if (dp_is_hdcp_enabled(dp)) { dp->hdcp_status = HDCP_STATE_INACTIVE; cancel_delayed_work(&dp->hdcp_cb_work); if (dp->hdcp.ops->off) dp->hdcp.ops->off(dp->hdcp.data); } Loading Loading @@ -2189,9 +2208,6 @@ irqreturn_t dp_isr(int irq, void *ptr) isr1 &= ~mask1; /* remove masks bit */ pr_debug("isr=%x mask=%x isr2=%x\n", isr1, mask1, isr2); ack = isr1 & EDP_INTR_STATUS1; ack <<= 1; /* ack bits */ ack |= mask1; Loading Loading @@ -2601,8 +2617,7 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) if (dp_drv->alt_mode.dp_status.hpd_irq) { pr_debug("Attention: hpd_irq high\n"); if (dp_drv->power_on && dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) { if (dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) { if (!dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data)) return; } Loading @@ -2616,6 +2631,12 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) if (!dp_drv->alt_mode.dp_status.hpd_high) { pr_debug("Attention: HPD low\n"); if (dp_is_hdcp_enabled(dp_drv) && dp_drv->hdcp.ops->off) { cancel_delayed_work(&dp_drv->hdcp_cb_work); dp_drv->hdcp.ops->off(dp_drv->hdcp.data); } mdss_dp_update_cable_status(dp_drv, false); mdss_dp_notify_clients(dp_drv, false); pr_debug("Attention: Notified clients\n"); Loading
drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c +114 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "mdss_hdcp.h" #include "mdss_dp_util.h" struct dp_hdcp2p2_ctrl; enum dp_hdcp2p2_sink_status { SINK_DISCONNECTED, SINK_CONNECTED Loading @@ -33,9 +35,21 @@ enum dp_auth_status { DP_HDCP_AUTH_STATUS_SUCCESS }; struct dp_hdcp2p2_int_set { u32 interrupt; char *name; void (*func)(struct dp_hdcp2p2_ctrl *ctrl); }; struct dp_hdcp2p2_interrupts { u32 reg; struct dp_hdcp2p2_int_set *int_set; }; struct dp_hdcp2p2_ctrl { atomic_t auth_state; enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */ struct dp_hdcp2p2_interrupts *intr; struct hdcp_init_data init_data; struct mutex mutex; /* mutex to protect access to ctrl */ struct mutex msg_lock; /* mutex to protect access to msg buffer */ Loading Loading @@ -172,6 +186,9 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_LINK_POLL: if (ctrl->cp_irq_done) queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: Loading Loading @@ -211,6 +228,31 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); } static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable) { unsigned char *base = ctrl->init_data.core_io->base; struct dp_hdcp2p2_interrupts *intr = ctrl->intr; while (intr && intr->reg) { struct dp_hdcp2p2_int_set *int_set = intr->int_set; u32 interrupts = 0; while (int_set && int_set->interrupt) { interrupts |= int_set->interrupt; int_set++; } if (enable) dp_write(base + intr->reg, dp_read(base + intr->reg) | interrupts); else dp_write(base + intr->reg, dp_read(base + intr->reg) & ~interrupts); intr++; } } static void dp_hdcp2p2_off(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading @@ -221,6 +263,13 @@ static void dp_hdcp2p2_off(void *input) return; } if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); return; } dp_hdcp2p2_set_interrupts(ctrl, false); dp_hdcp2p2_reset(ctrl); flush_kthread_worker(&ctrl->worker); Loading @@ -237,6 +286,8 @@ static int dp_hdcp2p2_authenticate(void *input) flush_kthread_worker(&ctrl->worker); dp_hdcp2p2_set_interrupts(ctrl, true); ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); Loading Loading @@ -317,6 +368,8 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl) return; } dp_hdcp2p2_set_interrupts(ctrl, false); /* notify DP about HDCP failure */ ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTH_FAIL); Loading Loading @@ -640,6 +693,8 @@ static int dp_hdcp2p2_cp_irq(void *input) goto error; } pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status); if (!ctrl->sink_rx_status) { pr_debug("not a hdcp 2.2 irq\n"); rc = -EINVAL; Loading @@ -653,6 +708,46 @@ error: return rc; } static int dp_hdcp2p2_isr(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; int rc = 0; struct dss_io_data *io; struct dp_hdcp2p2_interrupts *intr; u32 hdcp_int_val; if (!ctrl || !ctrl->init_data.core_io) { pr_err("invalid input\n"); rc = -EINVAL; goto end; } io = ctrl->init_data.core_io; intr = ctrl->intr; while (intr && intr->reg) { struct dp_hdcp2p2_int_set *int_set = intr->int_set; hdcp_int_val = dp_read(io->base + intr->reg); while (int_set && int_set->interrupt) { if (hdcp_int_val & (int_set->interrupt >> 2)) { pr_debug("%s\n", int_set->name); if (int_set->func) int_set->func(ctrl); dp_write(io->base + intr->reg, hdcp_int_val | (int_set->interrupt >> 1)); } int_set++; } intr++; } end: return rc; } void dp_hdcp2p2_deinit(void *input) { struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; Loading Loading @@ -684,6 +779,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) int rc; struct dp_hdcp2p2_ctrl *ctrl; static struct hdcp_ops ops = { .isr = dp_hdcp2p2_isr, .reauthenticate = dp_hdcp2p2_reauthenticate, .authenticate = dp_hdcp2p2_authenticate, .feature_supported = dp_hdcp2p2_feature_supported, Loading @@ -694,7 +790,22 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) static struct hdcp_client_ops client_ops = { .wakeup = dp_hdcp2p2_wakeup, }; static struct dp_hdcp2p2_int_set int_set1[] = { {BIT(17), "authentication successful", 0}, {BIT(20), "authentication failed", 0}, {BIT(24), "encryption enabled", 0}, {BIT(27), "encryption disabled", 0}, {0}, }; static struct dp_hdcp2p2_int_set int_set2[] = { {BIT(2), "key fifo underflow", 0}, {0}, }; static struct dp_hdcp2p2_interrupts intr[] = { {DP_INTR_STATUS2, int_set1}, {DP_INTR_STATUS3, int_set2}, {0} }; static struct hdcp_txmtr_ops txmtr_ops; struct hdcp_register_data register_data = {0}; Loading @@ -719,6 +830,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) } ctrl->sink_status = SINK_DISCONNECTED; ctrl->intr = intr; atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); Loading