hdmitx: add hdcp topo information [3/5]

PD#165815: hdmitx: add hdcp topo information

1. add SYSFS 'hdcp_topo_info' to represent HDCP22 Topology
2. rewrite SYSFS 'hdcp22_type', should be controlled by Daemon

Change-Id: Ie9f748c5592a32b8658b63186429794e877fd41c
Signed-off-by: Zongdong Jiao <zongdong.jiao@amlogic.com>
This commit is contained in:
Zongdong Jiao
2018-05-24 16:16:11 +08:00
parent 25d1c8cd56
commit 715a75cd69
4 changed files with 180 additions and 3 deletions

View File

@@ -928,6 +928,94 @@ static ssize_t store_hdcp_repeater(struct device *dev,
return count;
}
/*
* hdcp_topo_info attr
* For hdcp 22, hdcp_tx22 will write to store_hdcp_topo_info
* For hdcp 14, directly get from HW
*/
static ssize_t show_hdcp_topo_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
int pos = 0;
struct hdmitx_dev *hdev = &hdmitx_device;
struct hdcprp_topo *topoinfo = hdev->topo_info;
if (!hdev->hdcp_mode) {
pos += snprintf(buf+pos, PAGE_SIZE, "hdcp mode: 0\n");
return pos;
}
if (!topoinfo)
return pos;
if (hdev->hdcp_mode == 1) {
memset(topoinfo, 0, sizeof(struct hdcprp_topo));
hdev->HWOp.CntlDDC(hdev, DDC_HDCP14_GET_TOPO_INFO,
(unsigned long)&topoinfo->topo.topo14);
}
pos += snprintf(buf+pos, PAGE_SIZE, "hdcp mode: %s\n",
hdev->hdcp_mode == 1 ? "14" : "22");
if (hdev->hdcp_mode == 2) {
topoinfo->hdcp_ver = HDCPVER_22;
pos += snprintf(buf+pos, PAGE_SIZE, "max_devs_exceeded: %d\n",
topoinfo->topo.topo22.max_devs_exceeded);
pos += snprintf(buf+pos, PAGE_SIZE,
"max_cascade_exceeded: %d\n",
topoinfo->topo.topo22.max_cascade_exceeded);
pos += snprintf(buf+pos, PAGE_SIZE, "v2_0_repeater_down: %d\n",
topoinfo->topo.topo22.v2_0_repeater_down);
pos += snprintf(buf+pos, PAGE_SIZE, "v1_X_device_down: %d\n",
topoinfo->topo.topo22.v1_X_device_down);
pos += snprintf(buf+pos, PAGE_SIZE, "device_count: %d\n",
topoinfo->topo.topo22.device_count);
pos += snprintf(buf+pos, PAGE_SIZE, "depth: %d\n",
topoinfo->topo.topo22.depth);
return pos;
}
if (hdev->hdcp_mode == 1) {
topoinfo->hdcp_ver = HDCPVER_14;
pos += snprintf(buf+pos, PAGE_SIZE, "max_devs_exceeded: %d\n",
topoinfo->topo.topo14.max_devs_exceeded);
pos += snprintf(buf+pos, PAGE_SIZE,
"max_cascade_exceeded: %d\n",
topoinfo->topo.topo14.max_cascade_exceeded);
pos += snprintf(buf+pos, PAGE_SIZE, "device_count: %d\n",
topoinfo->topo.topo14.device_count);
pos += snprintf(buf+pos, PAGE_SIZE, "depth: %d\n",
topoinfo->topo.topo14.depth);
return pos;
}
return pos;
}
static ssize_t store_hdcp_topo_info(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct hdmitx_dev *hdev = &hdmitx_device;
struct hdcprp_topo *topoinfo = hdev->topo_info;
int cnt;
if (!topoinfo)
return count;
if (hdev->hdcp_mode == 2) {
memset(topoinfo, 0, sizeof(struct hdcprp_topo));
cnt = sscanf(buf, "%x %x %x %x %x %x",
(int *)&topoinfo->topo.topo22.max_devs_exceeded,
(int *)&topoinfo->topo.topo22.max_cascade_exceeded,
(int *)&topoinfo->topo.topo22.v2_0_repeater_down,
(int *)&topoinfo->topo.topo22.v1_X_device_down,
(int *)&topoinfo->topo.topo22.device_count,
(int *)&topoinfo->topo.topo22.depth);
if (cnt < 0)
return count;
}
return count;
}
static ssize_t show_hdcp22_type(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -941,10 +1029,17 @@ static ssize_t show_hdcp22_type(struct device *dev,
static ssize_t store_hdcp22_type(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
if (buf[0] == '0')
hdmitx_device.hdcp22_type = 0;
int type = 0;
struct hdmitx_dev *hdev = &hdmitx_device;
if (buf[0] == '1')
hdmitx_device.hdcp22_type = 1;
type = 1;
else
type = 0;
hdev->hdcp22_type = type;
pr_info("hdmitx: set hdcp22 content type %d\n", type);
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_SET_TOPO_INFO, type);
return count;
}
@@ -2658,6 +2753,8 @@ static DEVICE_ATTR(hdcp_mode, 0664, show_hdcp_mode, store_hdcp_mode);
static DEVICE_ATTR(hdcp_lstore, 0664, show_hdcp_lstore, store_hdcp_lstore);
static DEVICE_ATTR(hdcp_repeater, 0644, show_hdcp_repeater,
store_hdcp_repeater);
static DEVICE_ATTR(hdcp_topo_info, 0644, show_hdcp_topo_info,
store_hdcp_topo_info);
static DEVICE_ATTR(hdcp22_type, 0644, show_hdcp22_type, store_hdcp22_type);
static DEVICE_ATTR(hdcp22_base, 0444, show_hdcp22_base, NULL);
static DEVICE_ATTR(div40, 0664, show_div40, store_div40);
@@ -3068,6 +3165,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
hdev->HWOp.CntlConfig(hdev, CONF_CLR_AVI_PACKET, 0);
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1);
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF);
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_SET_TOPO_INFO, 0);
hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE);
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT;
hdev->HWOp.CntlMisc(hdev, MISC_ESM_RESET, 0);
@@ -3467,6 +3565,10 @@ static int amhdmitx_device_init(struct hdmitx_dev *hdmi_dev)
hdmitx_device.audio_param_update_flag = 0;
/* 1: 2ch */
hdmitx_device.hdmi_ch = 1;
hdmitx_device.topo_info =
kmalloc(sizeof(struct hdcprp_topo), GFP_KERNEL);
if (!hdmitx_device.topo_info)
pr_info("failed to alloc hdcp topo info\n");
hdmitx_init_parameters(&hdmitx_device.hdmi_info);
return 0;
@@ -3717,6 +3819,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
ret = device_create_file(dev, &dev_attr_hdcp_byp);
ret = device_create_file(dev, &dev_attr_hdcp_mode);
ret = device_create_file(dev, &dev_attr_hdcp_repeater);
ret = device_create_file(dev, &dev_attr_hdcp_topo_info);
ret = device_create_file(dev, &dev_attr_hdcp22_type);
ret = device_create_file(dev, &dev_attr_hdcp22_base);
ret = device_create_file(dev, &dev_attr_hdcp_lstore);
@@ -3809,6 +3912,7 @@ static int amhdmitx_remove(struct platform_device *pdev)
device_remove_file(dev, &dev_attr_hdcp_pwr);
device_remove_file(dev, &dev_attr_div40);
device_remove_file(dev, &dev_attr_hdcp_repeater);
device_remove_file(dev, &dev_attr_hdcp_topo_info);
device_remove_file(dev, &dev_attr_hdcp22_type);
device_remove_file(dev, &dev_attr_hdcp22_base);

View File

@@ -168,6 +168,7 @@ int hdmitx_ddc_hw_op(enum ddc_op cmd)
}
EXPORT_SYMBOL(hdmitx_ddc_hw_op);
static int hdcp_topo_st = -1;
int hdmitx_hdcp_opr(unsigned int val)
{
struct arm_smccc_res res;
@@ -210,6 +211,13 @@ int hdmitx_hdcp_opr(unsigned int val)
arm_smccc_smc(0x8200001c, 0, 0, 0, 0, 0, 0, 0, &res);
return (unsigned int)((res.a0)&0xffffffff);
}
if (val == 0xd) { /* HDCP22_SET_TOPO */
arm_smccc_smc(0x82000083, hdcp_topo_st, 0, 0, 0, 0, 0, 0, &res);
}
if (val == 0xe) { /* HDCP22_GET_TOPO */
arm_smccc_smc(0x82000084, 0, 0, 0, 0, 0, 0, 0, &res);
return (unsigned int)((res.a0)&0xffffffff);
}
return -1;
}
@@ -2864,6 +2872,9 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf)
pr_info(HW "set hdmi vic count = %d\n",
hdev->vic_count);
}
} else if (strncmp(tmpbuf, "topo", 4) == 0) {
pr_info("topo: %d\n", hdmitx_hdcp_opr(0xe));
return;
} else if (strncmp(tmpbuf, "dumphdmireg", 11) == 0) {
unsigned char reg_val = 0;
unsigned int reg_adr = 0;
@@ -3361,6 +3372,8 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd,
{
int i = 0;
unsigned char *tmp_char = NULL;
struct hdcprp14_topo *topo14 = NULL;
unsigned int val;
if ((cmd & CMD_DDC_OFFSET) != CMD_DDC_OFFSET) {
pr_err(HW "ddc: invalid cmd 0x%x\n", cmd);
@@ -3454,6 +3467,27 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd,
return hdmitx_hdcp_opr(0xa);
case DDC_HDCP_22_LSTORE:
return hdmitx_hdcp_opr(0xb);
case DDC_HDCP14_GET_TOPO_INFO:
topo14 = (struct hdcprp14_topo *)argv;
/* if rx is not repeater, directly return */
if (!(hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3) & (1 << 6)))
return 0;
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1);
hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
val = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0);
topo14->device_count = val & 0x7f;
topo14->max_devs_exceeded = !!(val & 0x80);
val = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1);
topo14->depth = val & 0x7;
topo14->max_cascade_exceeded = !!(val & 0x8);
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
return 1;
case DDC_HDCP_SET_TOPO_INFO:
if (hdcp_topo_st != argv) {
hdcp_topo_st = argv;
hdmitx_hdcp_opr(0xd);
}
break;
case DDC_SCDC_DIV40_SCRAMB:
if (argv == 1) {
scdc_wr_sink(TMDS_CFG, 0x3); /* TMDS 1/40 & Scramble */

View File

@@ -131,6 +131,42 @@ enum hdcp_authstate {
HDCP_MAX
};
enum hdcp_ver_e {
HDCPVER_NONE = 0,
HDCPVER_14,
HDCPVER_22,
};
#define HDCP14_MAX_KSV_LISTS 127
struct hdcprp14_topo {
unsigned char max_cascade_exceeded:1;
unsigned char depth:3;
unsigned char max_devs_exceeded:1;
unsigned char device_count:7; /* 1 ~ 127 */
unsigned char ksv_list[HDCP14_MAX_KSV_LISTS * 5];
};
#define HDCP22_MAX_KSV_LISTS 31
struct hdcprp22_topo {
int depth;
int device_count;
int v1_X_device_down;
int v2_0_repeater_down;
int max_devs_exceeded;
int max_cascade_exceeded;
unsigned char id_num;
unsigned char id_lists[HDCP22_MAX_KSV_LISTS * 5];
};
struct hdcprp_topo {
/* hdcp_ver currently used */
enum hdcp_ver_e hdcp_ver;
union {
struct hdcprp14_topo topo14;
struct hdcprp22_topo topo22;
} topo;
};
/* -----------------------HDCP END---------------------------------------- */
/* -----------------------HDMI TX---------------------------------- */

View File

@@ -342,6 +342,7 @@ struct hdmitx_dev {
unsigned int audio_notify_flag;
unsigned int audio_step;
unsigned int repeater_tx;
struct hdcprp_topo *topo_info;
/* 0.1% clock shift, 1080p60hz->59.94hz */
unsigned int frac_rate_policy;
unsigned int rxsense_policy;
@@ -402,6 +403,8 @@ struct hdmitx_dev {
#define DDC_HDCP_22_LSTORE (CMD_DDC_OFFSET + 0x10)
#define DDC_SCDC_DIV40_SCRAMB (CMD_DDC_OFFSET + 0x20)
#define DDC_HDCP14_GET_BCAPS_RP (CMD_DDC_OFFSET + 0x30)
#define DDC_HDCP14_GET_TOPO_INFO (CMD_DDC_OFFSET + 0x31)
#define DDC_HDCP_SET_TOPO_INFO (CMD_DDC_OFFSET + 0x32)
/***********************************************************************
* CONFIG CONTROL //CntlConfig