mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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---------------------------------- */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user