diff options
Diffstat (limited to 'drivers/video/omap2/hdcp/hdcp.h')
-rw-r--r-- | drivers/video/omap2/hdcp/hdcp.h | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/drivers/video/omap2/hdcp/hdcp.h b/drivers/video/omap2/hdcp/hdcp.h new file mode 100644 index 0000000..e22a588 --- /dev/null +++ b/drivers/video/omap2/hdcp/hdcp.h @@ -0,0 +1,394 @@ +/* + * hdcp.h + * + * HDCP interface DSS driver setting for TI's OMAP4 family of processor. + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Fabrice Olivero + * Fabrice Olivero <f-olivero@ti.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _HDCP_H_ +#define _HDCP_H_ + + +/********************************/ +/* Structures related to ioctl */ +/********************************/ + +/* HDCP key size in 32-bit words */ +#define DESHDCP_KEY_SIZE 160 + +/* HDCP ioctl */ +#include <linux/ioctl.h> +#include <linux/types.h> + +struct hdcp_encrypt_control { + uint32_t in_key[DESHDCP_KEY_SIZE]; + uint32_t *out_key; +}; + +struct hdcp_enable_control { + uint32_t key[DESHDCP_KEY_SIZE]; + int nb_retry; +}; + +#define MAX_SHA_DATA_SIZE 645 +#define MAX_SHA_VPRIME_SIZE 20 + +struct hdcp_sha_in { + uint8_t data[MAX_SHA_DATA_SIZE]; + uint32_t byte_counter; + uint8_t vprime[MAX_SHA_VPRIME_SIZE]; +}; + +struct hdcp_wait_control { + uint32_t event; + struct hdcp_sha_in *data; +}; + +/* HDCP ioctl */ +#define HDCP_IOCTL_MAGIC 'h' +#define HDCP_ENABLE _IOW(HDCP_IOCTL_MAGIC, 0, \ + struct hdcp_enable_control) +#define HDCP_DISABLE _IO(HDCP_IOCTL_MAGIC, 1) +#define HDCP_ENCRYPT_KEY _IOWR(HDCP_IOCTL_MAGIC, 2, \ + struct hdcp_encrypt_control) +#define HDCP_QUERY_STATUS _IOWR(HDCP_IOCTL_MAGIC, 3, uint32_t) +#define HDCP_WAIT_EVENT _IOWR(HDCP_IOCTL_MAGIC, 4, \ + struct hdcp_wait_control) +#define HDCP_DONE _IOW(HDCP_IOCTL_MAGIC, 5, uint32_t) + +/* HDCP state */ +#define HDCP_STATE_DISABLED 0 +#define HDCP_STATE_INIT 1 +#define HDCP_STATE_AUTH_1ST_STEP 2 +#define HDCP_STATE_AUTH_2ND_STEP 3 +#define HDCP_STATE_AUTH_3RD_STEP 4 +#define HDCP_STATE_AUTH_FAIL_RESTARTING 5 +#define HDCP_STATE_AUTH_FAILURE 6 + +/* HDCP events */ +#define HDCP_EVENT_STEP1 (1 << 0x0) +#define HDCP_EVENT_STEP2 (1 << 0x1) +#define HDCP_EVENT_EXIT (1 << 0x2) + +/* HDCP user space status */ +#define HDCP_US_NO_ERR (0 << 8) +#define HDCP_US_FAILURE (1 << 8) + +#ifdef __KERNEL__ + +#include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/fs.h> + +#define _9032_AUTO_RI_ /* Auto Ri mode */ +#define _9032_BCAP_ /* BCAP polling */ +#undef _9032_AN_STOP_FIX_ + +#ifdef DEBUG +#define DDC_DBG /* Log DDC data */ +#undef POWER_TRANSITION_DBG /* Add wait loops to allow testing DSS power + * transition during HDCP */ +#endif + +/***************************/ +/* HW specific definitions */ +/***************************/ + +/* DESHDCP base address */ +/*----------------------*/ + +#define DSS_SS_FROM_L3__DESHDCP 0x58007000 + +/* DESHDCP registers */ +#define DESHDCP__DHDCP_CTRL 0x020 +#define DESHDCP__DHDCP_DATA_L 0x024 +#define DESHDCP__DHDCP_DATA_H 0x028 + +/* DESHDCP CTRL bits */ +#define DESHDCP__DHDCP_CTRL__DIRECTION_POS_F 2 +#define DESHDCP__DHDCP_CTRL__DIRECTION_POS_L 2 + +#define DESHDCP__DHDCP_CTRL__OUTPUT_READY_POS_F 0 +#define DESHDCP__DHDCP_CTRL__OUTPUT_READY_POS_L 0 + +/* HDMI WP base address */ +/*----------------------*/ +#define HDMI_WP 0x58006000 + +/* HDMI CORE SYSTEM base address */ +/*-------------------------------*/ + +#define HDMI_IP_CORE_SYSTEM 0x400 + +/* HDMI CORE registers */ +#define HDMI_IP_CORE_SYSTEM__DCTL 0x034 + +#define HDMI_IP_CORE_SYSTEM__HDCP_CTRL 0x03C + +#define HDMI_IP_CORE_SYSTEM__BKSV0 0x040 + +#define HDMI_IP_CORE_SYSTEM__AN0 0x054 + +#define HDMI_IP_CORE_SYSTEM__AKSV0 0x074 + +#define HDMI_IP_CORE_SYSTEM__R1 0x088 +#define HDMI_IP_CORE_SYSTEM__R2 0x08C + +#define HDMI_IP_CORE_SYSTEM__RI_CMD 0x09C +#define HDMI_IP_CORE_SYSTEM__RI_STAT 0x098 + +#define HDMI_IP_CORE_SYSTEM__INTR2 0x1C8 +#define HDMI_IP_CORE_SYSTEM__INTR3 0x1CC + +#define HDMI_IP_CORE_SYSTEM__INT_UNMASK2 0x1D8 +#define HDMI_IP_CORE_SYSTEM__INT_UNMASK3 0x1DC + +#define HDMI_IP_CORE_SYSTEM__SHA_CTRL 0x330 + +#define HDMI_IP_CORE_SYSTEM__INTR2__BCAP 0x80 +#define HDMI_IP_CORE_SYSTEM__INTR3__RI_ERR 0xF0 + +enum hdcp_repeater { + HDCP_RECEIVER = 0, + HDCP_REPEATER = 1 +}; + +enum encryption_state { + HDCP_ENC_OFF = 0x0, + HDCP_ENC_ON = 0x1 +}; + +/* HDMI CORE AV base address */ +/*---------------------------*/ + +#define HDMI_CORE_AV_BASE 0x900 +#ifndef HDMI_CORE_AV_HDMI_CTRL +#define HDMI_CORE_AV_HDMI_CTRL 0x0BC +#define HDMI_CORE_AV_PB_CTRL2 0x0FC +#define HDMI_CORE_AV_CP_BYTE1 0x37C +#endif + +#define HDMI_CORE_AV_HDMI_CTRL__HDMI_MODE 0x01 + +enum av_mute { + AV_MUTE_SET = 0x01, + AV_MUTE_CLEAR = 0x10 +}; +/***********************/ +/* HDCP DDC addresses */ +/***********************/ + +#define DDC_BKSV_ADDR 0x00 +#define DDC_Ri_ADDR 0x08 +#define DDC_AKSV_ADDR 0x10 +#define DDC_AN_ADDR 0x18 +#define DDC_V_ADDR 0x20 +#define DDC_BCAPS_ADDR 0x40 +#define DDC_BSTATUS_ADDR 0x41 +#define DDC_KSV_FIFO_ADDR 0x43 + +#define DDC_BKSV_LEN 5 +#define DDC_Ri_LEN 2 +#define DDC_AKSV_LEN 5 +#define DDC_AN_LEN 8 +#define DDC_V_LEN 20 +#define DDC_BCAPS_LEN 1 +#define DDC_BSTATUS_LEN 2 + +#define DDC_BIT_REPEATER 6 + +#define DDC_BSTATUS0_MAX_DEVS 0x80 +#define DDC_BSTATUS0_DEV_COUNT 0x7F +#define DDC_BSTATUS1_MAX_CASC 0x08 + +/***************************/ +/* Definitions */ +/***************************/ + +/* Status / error codes */ +#define HDCP_OK 0 +#define HDCP_DDC_ERROR 1 +#define HDCP_AUTH_FAILURE 2 +#define HDCP_AKSV_ERROR 3 +#define HDCP_3DES_ERROR 4 +#define HDCP_SHA1_ERROR 5 +#define HDCP_DRIVER_ERROR 6 +#define HDCP_CANCELLED_AUTH 7 + +#define HDCP_INFINITE_REAUTH 0x100 +#define HDCP_MAX_DDC_ERR 5 + +/* FIXME: should be 300ms delay between HDMI start frame event and HDCP enable + * (to respect 7 VSYNC delay in 24 Hz) + */ +#define HDCP_ENABLE_DELAY 300 +#define HDCP_R0_DELAY 110 +#define HDCP_KSV_TIMEOUT_DELAY 5000 +#define HDCP_REAUTH_DELAY 100 + +/* DDC access timeout in ms */ +#define HDCP_DDC_TIMEOUT 500 +#define HDCP_STOP_FRAME_BLOCKING_TIMEOUT (2*HDCP_DDC_TIMEOUT) + +/* Event source */ +#define HDCP_SRC_SHIFT 8 +#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT) +#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT) +#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT) +#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT) + +/* Workqueue events */ +/* Note: HDCP_ENABLE_CTL, HDCP_R0_EXP_EVENT, HDCP_KSV_TIMEOUT_EVENT and + * HDCP_AUTH_REATT_EVENT can be cancelled by HDCP disabling + */ +#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0) +#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1) +#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2) +#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3) +#define HDCP_HPD_LOW_EVENT (HDCP_IRQ_SRC | 4) +#define HDCP_RI_FAIL_EVENT (HDCP_IRQ_SRC | 5) +#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 6) +#define HDCP_R0_EXP_EVENT (HDCP_WORKQUEUE_SRC | 7) +#define HDCP_KSV_TIMEOUT_EVENT (HDCP_WORKQUEUE_SRC | 8) +#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 9) + +/* IRQ status */ +#define HDCP_IRQ_RI_FAIL 0x01 +#define HDCP_IRQ_KSV_RDY 0x02 + +enum hdcp_states { + HDCP_DISABLED, + HDCP_ENABLE_PENDING, + HDCP_AUTHENTICATION_START, + HDCP_WAIT_R0_DELAY, + HDCP_WAIT_KSV_LIST, + HDCP_LINK_INTEGRITY_CHECK, + HDCP_KEY_ENCRYPTION_ONGOING +}; + +enum hdmi_states { + HDMI_STOPPED, + HDMI_STARTED +}; + +struct hdcp_delayed_work { + struct delayed_work work; + int event; +}; + +struct hdcp { + void __iomem *hdmi_wp_base_addr; + void __iomem *deshdcp_base_addr; + struct mutex lock; + struct hdcp_enable_control *en_ctrl; + dev_t dev_id; + struct class *hdcp_class; + enum hdmi_states hdmi_state; + enum hdcp_states hdcp_state; + int auth_state; + struct delayed_work *pending_start; + /* Following variable should store works submitted from workqueue + * context + * WARNING: only ONE work at a time can be stored (no conflict + * should happen). It is used to allow cancelled pending works when + * disabling HDCP + */ + struct delayed_work *pending_wq_event; + int retry_cnt; + int dss_state; + int pending_disable; + int hdmi_restart; + int hpd_low; + spinlock_t spinlock; + struct workqueue_struct *workqueue; + int hdcp_up_event; + int hdcp_down_event; + bool hdcp_keys_loaded; +}; + +extern struct hdcp hdcp; +extern struct hdcp_sha_in sha_input; + + +/***************************/ +/* Macros for accessing HW */ +/***************************/ + +#define WR_REG_32(base, offset, val) __raw_writel(val, base + offset) +#define RD_REG_32(base, offset) __raw_readl(base + offset) + + +#undef FLD_MASK +#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end)) +#undef FLD_VAL +#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end)) +#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) +#define FLD_MOD(orig, val, start, end) \ + (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) + +#define WR_FIELD_32(base, offset, start, end, val) \ + WR_REG_32(base, offset, FLD_MOD(RD_REG_32(base, offset), val, \ + start, end)) + +#define RD_FIELD_32(base, offset, start, end) \ + ((RD_REG_32(base, offset) & FLD_MASK(start, end)) >> (end)) + + +#undef DBG + +#ifdef HDCP_DEBUG +#define DBG(format, ...) \ + printk(KERN_DEBUG "HDCP: " format "\n", ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +/***************************/ +/* Function prototypes */ +/***************************/ + +int hdcp_user_space_task(int flags); + +/* 3DES */ +int hdcp_3des_load_key(uint32_t *deshdcp_encrypted_key); +void hdcp_3des_encrypt_key(struct hdcp_encrypt_control *enc_ctrl, + uint32_t out_key[DESHDCP_KEY_SIZE]); + +/* IP control */ +int hdcp_lib_disable(void); +int hdcp_lib_step1_start(void); +int hdcp_lib_step1_r0_check(void); +int hdcp_lib_step2(void); +int hdcp_lib_irq(void); +void hdcp_lib_auto_ri_check(bool state); +void hdcp_lib_auto_bcaps_rdy_check(bool state); +void hdcp_lib_set_av_mute(enum av_mute av_mute_state); +void hdcp_lib_set_encryption(enum encryption_state enc_state); +u8 hdcp_lib_check_repeater_bit_in_tx(void); + +/* DDC */ +int hdcp_ddc_read(u16 no_bytes, u8 addr, u8 *pdata); +int hdcp_ddc_write(u16 no_bytes, u8 addr, u8 *pdata); +void hdcp_ddc_abort(void); + +#endif /* __KERNEL__ */ + +#endif /* _HDCP_H_ */ |