static void hdcp_wq_authentication_failure(void) { if (hdcp.hdmi_state == HDMI_STOPPED) { hdcp.auth_state = HDCP_STATE_AUTH_FAILURE; return; } hdcp_lib_auto_ri_check(false); hdcp_lib_auto_bcaps_rdy_check(false); hdcp_lib_set_av_mute(AV_MUTE_SET); hdcp_lib_set_encryption(HDCP_ENC_OFF); hdcp_wq_disable(); if (hdcp.retry_cnt && (hdcp.hdmi_state != HDMI_STOPPED)) { if (hdcp.retry_cnt < HDCP_INFINITE_REAUTH) { hdcp.retry_cnt--; printk(KERN_INFO "HDCP: authentication failed - " "retrying, attempts=%d\n", hdcp.retry_cnt); } else printk(KERN_INFO "HDCP: authentication failed - " "retrying\n"); hdcp.hdcp_state = HDCP_AUTHENTICATION_START; hdcp.auth_state = HDCP_STATE_AUTH_FAIL_RESTARTING; hdcp.pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT, HDCP_REAUTH_DELAY); } else { printk(KERN_INFO "HDCP: authentication failed - " "HDCP disabled\n"); hdcp.hdcp_state = HDCP_ENABLE_PENDING; hdcp.auth_state = HDCP_STATE_AUTH_FAILURE; } }
static void omap4_hdcp_irq_cb(int status) { HDCP_DBG("hdcp_irq_cb() status=%x", status); if (!hdcp.hdcp_keys_loaded) { HDCP_DBG("%s: hdcp_keys not loaded = %d", __func__, hdcp.hdcp_keys_loaded); return; } /* Disable auto Ri/BCAPS immediately */ if (((status & HDMI_RI_ERR) || (status & HDMI_BCAP) || (status & HDMI_HPD_LOW)) && (hdcp.hdcp_state != HDCP_ENABLE_PENDING)) { hdcp_lib_auto_ri_check(false); hdcp_lib_auto_bcaps_rdy_check(false); } /* Work queue execution not required if HDCP is disabled */ /* TODO: ignore interrupts if they are masked (cannnot access UMASK * here so should use global variable */ if ((hdcp.hdcp_state != HDCP_DISABLED) && (hdcp.hdcp_state != HDCP_ENABLE_PENDING)) { if (status & HDMI_HPD_LOW) { hdcp_lib_set_encryption(HDCP_ENC_OFF); hdcp_ddc_abort(); } if (status & HDMI_RI_ERR) { hdcp_lib_set_av_mute(AV_MUTE_SET); hdcp_lib_set_encryption(HDCP_ENC_OFF); hdcp_submit_work(HDCP_RI_FAIL_EVENT, 0); } /* RI error takes precedence over BCAP */ else if (status & HDMI_BCAP) hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0); } if (status & HDMI_HPD_LOW) { hdcp.pending_disable = 1; /* Used to exit on-going HDCP * work */ hdcp.hpd_low = 0; /* Used to cancel HDCP works */ if (hdcp.pending_start) { pr_err("cancelling work for pending start\n"); hdcp_cancel_work(&hdcp.pending_start); } hdcp_wq_disable(); /* In case of HDCP_STOP_FRAME_EVENT, HDCP stop * frame callback is blocked and waiting for * HDCP driver to finish accessing the HW * before returning * Reason is to avoid HDMI driver to shutdown * DSS/HDMI power before HDCP work is finished */ hdcp.hdmi_state = HDMI_STOPPED; hdcp.hdcp_state = HDCP_ENABLE_PENDING; hdcp.auth_state = HDCP_STATE_DISABLED; } }
/*----------------------------------------------------------------------------- * Function: hdcp_work_queue *----------------------------------------------------------------------------- */ static void hdcp_work_queue(struct work_struct *work) { struct hdcp_delayed_work *hdcp_w = container_of(work, struct hdcp_delayed_work, work.work); int event = hdcp_w->event; mutex_lock(&hdcp->lock); DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d", jiffies_to_msecs(jiffies), hdcp->hdmi_state, hdcp->hdcp_state, (event & 0xFF00) >> 8, event & 0xFF); if(event == HDCP_STOP_FRAME_EVENT) { hdcp->hdmi_state = HDMI_STOPPED; } if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) { hdcp_wq_disable(event); } if (event & HDCP_WORKQUEUE_SRC) hdcp->pending_wq_event = 0; /* First handle HDMI state */ if (event == HDCP_START_FRAME_EVENT) { hdcp->pending_start = 0; hdcp->hdmi_state = HDMI_STARTED; } /**********************/ /* HDCP state machine */ /**********************/ switch (hdcp->hdcp_state) { case HDCP_DISABLED: /* HDCP enable control or re-authentication event */ if (event == HDCP_ENABLE_CTL) { if(hdcp->retry_times == 0) hdcp->retry_cnt = HDCP_INFINITE_REAUTH; else hdcp->retry_cnt = hdcp->retry_times; if (hdcp->hdmi_state == HDMI_STARTED) hdcp_wq_start_authentication(); else hdcp->hdcp_state = HDCP_ENABLE_PENDING; } break; case HDCP_ENABLE_PENDING: /* HDMI start frame event */ if (event == HDCP_START_FRAME_EVENT) hdcp_wq_start_authentication(); break; case HDCP_AUTHENTICATION_START: /* Re-authentication */ if (event == HDCP_AUTH_REATT_EVENT) hdcp_wq_start_authentication(); break; case HDCP_WAIT_KSV_LIST: /* KSV failure */ if (event == HDCP_FAIL_EVENT) { printk(KERN_INFO "HDCP: KSV switch failure\n"); hdcp_wq_authentication_failure(); } /* KSV list ready event */ else if (event == HDCP_KSV_LIST_RDY_EVENT) hdcp_wq_check_bksv(); break; case HDCP_LINK_INTEGRITY_CHECK: /* Ri failure */ if (event == HDCP_FAIL_EVENT) { printk(KERN_INFO "HDCP: Ri check failure\n"); hdcp_wq_authentication_failure(); } else if(event == HDCP_AUTH_PASS_EVENT) hdcp_wq_authentication_sucess(); break; default: printk(KERN_WARNING "HDCP: error - unknow HDCP state\n"); break; } kfree(hdcp_w); if(event == HDCP_STOP_FRAME_EVENT) complete(&hdcp->complete); mutex_unlock(&hdcp->lock); }