static ssize_t hdcp_enable_write(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { int enable; if(hdcp == NULL) return -EINVAL; sscanf(buf, "%d", &enable); if(hdcp->enable != enable) { /* Post event to workqueue */ if(enable) { if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0) return -EFAULT; } else { hdcp_cancel_work(&hdcp->pending_start); hdcp_cancel_work(&hdcp->pending_wq_event); /* Post event to workqueue */ if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0) return -EFAULT; } hdcp->enable = enable; } return count; }
/*----------------------------------------------------------------------------- * Function: hdcp_start_frame_cb *----------------------------------------------------------------------------- */ static void hdcp_start_frame_cb(void) { DBG("hdcp_start_frame_cb()"); /* Cancel any pending work */ if (hdcp->pending_start) hdcp_cancel_work(&hdcp->pending_start); if (hdcp->pending_wq_event) hdcp_cancel_work(&hdcp->pending_wq_event); hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT, HDCP_ENABLE_DELAY); }
/*----------------------------------------------------------------------------- * Function: hdcp_disable_ctl *----------------------------------------------------------------------------- */ static long hdcp_disable_ctl(void) { DBG("hdcp_ioctl() - DISABLE %u", jiffies_to_msecs(jiffies)); hdcp_cancel_work(&hdcp.pending_start); hdcp_cancel_work(&hdcp.pending_wq_event); hdcp.pending_disable = 1; /* Post event to workqueue */ if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0) return -EFAULT; return 0; }
/*----------------------------------------------------------------------------- * Function: hdcp_power_off_cb *----------------------------------------------------------------------------- */ static void hdcp_power_off_cb(void) { DBG("%s", __FUNCTION__); if(!hdcp->enable) return; hdcp_cancel_work(&hdcp->pending_start); hdcp_cancel_work(&hdcp->pending_wq_event); init_completion(&hdcp->complete); /* Post event to workqueue */ if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0)) wait_for_completion_interruptible_timeout(&hdcp->complete, msecs_to_jiffies(2000)); }
/*----------------------------------------------------------------------------- * Function: hdcp_wq_step2_authentication *----------------------------------------------------------------------------- */ static void hdcp_wq_step2_authentication(void) { int status = HDCP_OK; /* KSV list timeout is running and should be canceled */ hdcp_cancel_work(&hdcp.pending_wq_event); status = hdcp_lib_step2(); if (status == -HDCP_CANCELLED_AUTH) { DBG("Authentication step 2 cancelled."); return; } else if (status < 0) hdcp_wq_authentication_failure(); else { printk(KERN_INFO "HDCP: (Repeater) authentication step 2 " "successful\n"); hdcp.hdcp_state = HDCP_LINK_INTEGRITY_CHECK; hdcp.auth_state = HDCP_STATE_AUTH_3RD_STEP; /* Restore retry counter */ if (hdcp.en_ctrl->nb_retry == 0) hdcp.retry_cnt = HDCP_INFINITE_REAUTH; else hdcp.retry_cnt = hdcp.en_ctrl->nb_retry; } }
/*----------------------------------------------------------------------------- * Function: hdcp_wq_authentication_failure *----------------------------------------------------------------------------- */ static void hdcp_wq_authentication_failure(void) { if (hdcp->hdmi_state == HDMI_STOPPED) { return; } rk30_hdcp_disable(hdcp); rk30_hdmi_control_output(hdcp->hdmi, HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE); hdcp_cancel_work(&hdcp->pending_wq_event); 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->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; } }
static void hdcp_wq_disable(void) { printk(KERN_INFO "HDCP: disabled\n"); hdcp_cancel_work(&hdcp.pending_wq_event); hdcp_lib_disable(); hdcp.pending_disable = 0; }
/*----------------------------------------------------------------------------- * Function: hdcp_start_frame_cb *----------------------------------------------------------------------------- */ static void hdcp_start_frame_cb(void) { DBG("hdcp_start_frame_cb() %u", jiffies_to_msecs(jiffies)); if (!hdcp.hdcp_keys_loaded) { DBG("%s: hdcp_keys not loaded = %d", __func__, hdcp.hdcp_keys_loaded); return; } /* Cancel any pending work */ if (hdcp.pending_start) hdcp_cancel_work(&hdcp.pending_start); if (hdcp.pending_wq_event) hdcp_cancel_work(&hdcp.pending_wq_event); hdcp.hpd_low = 0; hdcp.pending_disable = 0; hdcp.retry_cnt = HDCP_INFINITE_REAUTH; hdcp.pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT, HDCP_ENABLE_DELAY); }
/*----------------------------------------------------------------------------- * Function: hdcp_wq_disable *----------------------------------------------------------------------------- */ static void hdcp_wq_disable(int event) { printk(KERN_INFO "HDCP: disabled"); hdcp_cancel_work(&hdcp->pending_wq_event); rk30_hdcp_disable(hdcp); if(event == HDCP_DISABLE_CTL) { hdcp->hdcp_state = HDCP_DISABLED; if(hdcp->hdmi_state == HDMI_STARTED) rk30_hdmi_control_output(hdcp->hdmi, HDMI_AV_UNMUTE); } else if(event == HDCP_STOP_FRAME_EVENT) hdcp->hdcp_state = HDCP_ENABLE_PENDING; }
/*----------------------------------------------------------------------------- * Function: hdcp_wq_authentication_failure *----------------------------------------------------------------------------- */ 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_cancel_work(&hdcp.pending_wq_event); hdcp_lib_disable(); hdcp.pending_disable = 0; 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; } }