/*-----------------------------------------------------------------------------
 * Function: hdcp_suspend_resume_auto_ri
 *-----------------------------------------------------------------------------
 */
static int hdcp_suspend_resume_auto_ri(enum ri_suspend_resume state)
{
    static u8 OldRiStat, OldRiCommand;
    u8 TimeOut = 10;

    /* Suspend Auto Ri in order to allow FW access MDDC bus.
     * Poll 0x72:0x26[0] for MDDC bus availability or timeout
     */

    DBG("hdcp_suspend_resume_auto_ri() state=%s",
        state == AUTO_RI_SUSPEND ? "SUSPEND" : "RESUME");

    if (state == AUTO_RI_SUSPEND) {
        /* Save original Auto Ri state */
        OldRiCommand = RD_FIELD_32(hdcp.hdmi_wp_base_addr +
                                   HDMI_IP_CORE_SYSTEM,
                                   HDMI_IP_CORE_SYSTEM__RI_CMD, 0, 0);

        /* Disable Auto Ri */
        hdcp_lib_auto_ri_check(false);

        /* Wait for HW to release MDDC bus */
        /* TODO: while loop / timeout to be enhanced */
        while (--TimeOut) {
            if (!RD_FIELD_32(hdcp.hdmi_wp_base_addr +
                             HDMI_IP_CORE_SYSTEM,
                             HDMI_IP_CORE_SYSTEM__RI_STAT, 0, 0))
                break;
        }

        /* MDDC bus not relinquished */
        if (!TimeOut) {
            printk(KERN_ERR "HDCP: Suspending Auto Ri failed !\n");
            return -HDCP_DDC_ERROR;
        }

        OldRiStat = RD_FIELD_32(hdcp.hdmi_wp_base_addr +
                                HDMI_IP_CORE_SYSTEM,
                                HDMI_IP_CORE_SYSTEM__RI_STAT, 0, 0);
    } else {
        /* If Auto Ri was enabled before it was suspended */
        if ((OldRiStat) && (OldRiCommand))
            /* Re-enable Auto Ri */
            hdcp_lib_auto_ri_check(false);
    }

    return HDCP_OK;
}
Beispiel #2
0
/*-----------------------------------------------------------------------------
 * Function: hdcp_irq_cb
 *-----------------------------------------------------------------------------
 */
static void hdcp_irq_cb(int status)
{
	DBG("hdcp_irq_cb() status=%x", status);

	if (!hdcp.hdcp_keys_loaded) {
		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 */
		hdcp_lib_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;
	}
}
Beispiel #3
0
/*-----------------------------------------------------------------------------
 * 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;
	}

}
Beispiel #4
0
/*-----------------------------------------------------------------------------
 * Function: hdcp_lib_step2
 *-----------------------------------------------------------------------------
 */
int hdcp_lib_step2(void)
{
	/* HDCP authentication steps:
	 *   1) Disable auto Ri check
	 *   2) DDC: read BStatus (nb of devices, MAX_DEV
	 */

	u8 bstatus[2];
	int status = HDCP_OK;

	DBG("hdcp_lib_step2() %u", jiffies_to_msecs(jiffies));

#ifdef _9032_AUTO_RI_
	/* Disable Auto Ri */
	hdcp_lib_auto_ri_check(false);
#endif

	/* DDC: Read Bstatus (1st byte) from Rx */
	if (hdcp_ddc_read(DDC_BSTATUS_LEN, DDC_BSTATUS_ADDR, bstatus))
		return -HDCP_DDC_ERROR;

	/* Get KSV list size */
	DBG("KSV list size: %d", bstatus[0] & DDC_BSTATUS0_DEV_COUNT);
	sha_input.byte_counter = (bstatus[0] & DDC_BSTATUS0_DEV_COUNT) * 5;

	/* Check BStatus topology errors */
	if (bstatus[0] & DDC_BSTATUS0_MAX_DEVS) {
		DBG("MAX_DEV_EXCEEDED set");
		return -HDCP_AUTH_FAILURE;
	}

	if (bstatus[1] & DDC_BSTATUS1_MAX_CASC) {
		DBG("MAX_CASCADE_EXCEEDED set");
		return -HDCP_AUTH_FAILURE;
	}

	DBG("Retrieving KSV list...");

	/* Clear all SHA input data */
	/* TODO: should be done earlier at HDCP init */
	memset(sha_input.data, 0, MAX_SHA_DATA_SIZE);

	if (hdcp.pending_disable)
		return -HDCP_CANCELLED_AUTH;

	/* DDC: read KSV list */
	if (sha_input.byte_counter) {
		if (hdcp_ddc_read(sha_input.byte_counter, DDC_KSV_FIFO_ADDR,
				  (u8 *)&sha_input.data))
			return -HDCP_DDC_ERROR;
	}

	/* Read and add Bstatus */
	if (hdcp_lib_sha_bstatus(&sha_input))
		return -HDCP_DDC_ERROR;

	if (hdcp.pending_disable)
		return -HDCP_CANCELLED_AUTH;

	/* Read V' */
	if (hdcp_ddc_read(DDC_V_LEN, DDC_V_ADDR, sha_input.vprime))
		return -HDCP_DDC_ERROR;

	if (hdcp.pending_disable)
		return -HDCP_CANCELLED_AUTH;

	/* clear sha_input values in cache*/
	dma_sync_single_for_device(NULL,
				   __pa((u32)(&sha_input)),
				   sizeof(struct hdcp_sha_in),
				   DMA_TO_DEVICE);

	status = omap4_secure_dispatcher(PPA_SERVICE_HDCP_CHECK_V,
					FLAG_START_CRITICAL,
					1, __pa((u32)&sha_input), 0, 0, 0);
	/* Wait for user space */
	if (status) {
		printk(KERN_ERR "HDCP: omap4_secure_dispatcher CHECH_V error "
				"%d\n", status);
		return -HDCP_AUTH_FAILURE;
	}

	if (status == HDCP_OK) {
		/* Re-enable Ri check */
#ifdef _9032_AUTO_RI_
		hdcp_lib_auto_ri_check(true);
#endif
	}

	return status;
}
Beispiel #5
0
/*-----------------------------------------------------------------------------
 * Function: hdcp_lib_step1_r0_check
 *-----------------------------------------------------------------------------
 */
int hdcp_lib_step1_r0_check(void)
{
	int status = HDCP_OK;

	/* HDCP authentication steps:
	 *   1) DDC: Read M0'
	 *   2) Compare M0 and M0'
	 *   if Rx is a receiver: switch to authentication step 3
	 *   3) Enable encryption / auto Ri check / disable AV mute
	 *   if Rx is a repeater: switch to authentication step 2
	 *   3) Get M0 from HDMI IP and store it for further processing (V)
	 *   4) Enable encryption / auto Ri check / auto BCAPS RDY polling
	 *      Disable AV mute
	 */

	DBG("hdcp_lib_step1_r0_check() %u", jiffies_to_msecs(jiffies));

	status = hdcp_lib_r0_check();
	if (status < 0)
		return status;

	/* Authentication 1st step done */

	/* Now prepare 2nd step authentication in case of RX repeater and
	 * enable encryption / Ri check
	 */

	if (hdcp.pending_disable)
		return -HDCP_CANCELLED_AUTH;

	if (hdcp_lib_check_repeater_bit_in_tx()) {
		status = omap4_secure_dispatcher(PPA_SERVICE_HDCP_READ_M0,
						FLAG_START_CRITICAL,
						0, 0, 0, 0, 0);
		/* Wait for user space */
		if (status) {
			printk(KERN_ERR "HDCP: omap4_secure_dispatcher M0 error "
					"%d\n", status);
			return -HDCP_AUTH_FAILURE;
		}

		DBG("hdcp_lib_set_encryption() %u", jiffies_to_msecs(jiffies));

		/* Enable encryption */
		hdcp_lib_set_encryption(HDCP_ENC_ON);

#ifdef _9032_AUTO_RI_
		/* Enable Auto Ri */
		hdcp_lib_auto_ri_check(true);
#endif

#ifdef _9032_BCAP_
		/* Enable automatic BCAPS polling */
		hdcp_lib_auto_bcaps_rdy_check(true);
#endif

		/* Now, IP waiting for BCAPS ready bit */
	} else {
		/* Receiver: enable encryption and auto Ri check */
		hdcp_lib_set_encryption(HDCP_ENC_ON);

#ifdef _9032_AUTO_RI_
		/* Enable Auto Ri */
		hdcp_lib_auto_ri_check(true);
#endif

	}

	/* Clear AV mute */
	hdcp_lib_set_av_mute(AV_MUTE_CLEAR);

	return HDCP_OK;
}