mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
hdmitx: add init code for repeater [2/6]
PD#SWPL-323 Problem: For TXLX/T962E, it has both HDMI Rx and TX, and lacks of HDMI repeater functions, including HDCP repeater function. Solution: Add the init code for hdmi repeater Verify: TXLX/T962E/R321 Change-Id: Iaf17ae62c590ff4f8478dd5556f3ed24b9ff3bb1 Signed-off-by: Zongdong Jiao <zongdong.jiao@amlogic.com>
This commit is contained in:
committed by
Dongjin Kim
parent
80b8564f35
commit
15e30c1693
@@ -13539,8 +13539,8 @@ F: arch/arm/mach-meson/Makefile.boot
|
||||
|
||||
HDMITX OUTPUT DRIVER
|
||||
M: Yi Zhou <yi.zhou@amlogic.com>
|
||||
M: Kaifu Hu <kaifu.hu@amlogic.com>
|
||||
M: Zongdong Jiao <zongdong.jiao@amlogic.com>
|
||||
M: Kaifu Hu <kaifu.hu@amlogic.com>
|
||||
S: Maintained
|
||||
F: drivers/amlogic/media/vout/hdmitx/*
|
||||
F: drivers/amlogic/media/vout/hdmitx/hdcp/*
|
||||
|
||||
@@ -305,14 +305,16 @@ int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev,
|
||||
}
|
||||
|
||||
set_vsdb_phy_addr(hdev, &info->vsdb_phy_addr, &buff[BlockAddr]);
|
||||
if ((check_fbc_special(&hdev->EDID_buf[0])) ||
|
||||
(check_fbc_special(&hdev->EDID_buf1[0])))
|
||||
rx_edid_physical_addr(0, 0, 0, 0);
|
||||
else
|
||||
rx_edid_physical_addr(info->vsdb_phy_addr.a,
|
||||
info->vsdb_phy_addr.b,
|
||||
info->vsdb_phy_addr.c,
|
||||
info->vsdb_phy_addr.d);
|
||||
if (hdev->repeater_tx) {
|
||||
if ((check_fbc_special(&hdev->EDID_buf[0])) ||
|
||||
(check_fbc_special(&hdev->EDID_buf1[0])))
|
||||
rx_edid_physical_addr(0, 0, 0, 0);
|
||||
else
|
||||
rx_edid_physical_addr(info->vsdb_phy_addr.a,
|
||||
info->vsdb_phy_addr.b,
|
||||
info->vsdb_phy_addr.c,
|
||||
info->vsdb_phy_addr.d);
|
||||
}
|
||||
|
||||
if (temp_addr >= VSpecificBoundary)
|
||||
ret = -1;
|
||||
@@ -1203,18 +1205,15 @@ static void Edid_Y420CMDB_Reset(struct hdmitx_info *info)
|
||||
memset(info->y420cmdb_bitmap, 0x00, Y420CMDB_MAX);
|
||||
}
|
||||
|
||||
static char *rptx_edid_aud;
|
||||
static char rptx_edid_buf[512];
|
||||
MODULE_PARM_DESC(rptx_edid_aud, "\n receive_edid\n");
|
||||
module_param(rptx_edid_aud, charp, 0444);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
int Edid_ParsingCEADataBlockCollection(struct hdmitx_dev *hdmitx_device,
|
||||
unsigned char *buff)
|
||||
{
|
||||
unsigned char AddrTag, D, Addr, Data;
|
||||
int temp_addr, i, len, pos;
|
||||
int temp_addr;
|
||||
int len;
|
||||
struct hdmitx_info *info = &(hdmitx_device->hdmi_info);
|
||||
struct rx_cap *pRXCap = &hdmitx_device->RXCap;
|
||||
|
||||
/* Byte number offset d where Detailed Timing data begins */
|
||||
D = buff[2];
|
||||
@@ -1225,22 +1224,29 @@ int Edid_ParsingCEADataBlockCollection(struct hdmitx_dev *hdmitx_device,
|
||||
Data = buff[AddrTag];
|
||||
switch (Data&0xE0) {
|
||||
case VIDEO_TAG:
|
||||
if ((Addr + (Data&0x1f)) < D)
|
||||
if ((Addr + (Data&0x1f)) < D) {
|
||||
Edid_ParsingVideoDATABlock(info, buff,
|
||||
Addr + 1, (Data & 0x1F));
|
||||
len = (Data & 0x1f) + 1;
|
||||
if ((pRXCap->vsd.len + len) > MAX_RAW_LEN)
|
||||
break;
|
||||
memcpy(&pRXCap->vsd.raw[pRXCap->vsd.len],
|
||||
&buff[AddrTag], len);
|
||||
pRXCap->vsd.len += len;
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_TAG:
|
||||
len = (Data & 0x1f) + 1;
|
||||
if (hdmitx_device->repeater_tx)
|
||||
rx_set_receiver_edid(&buff[AddrTag], len);
|
||||
for (pos = 0, i = 0; i < len; i++)
|
||||
pos += sprintf(rptx_edid_buf+pos, "%02x",
|
||||
buff[AddrTag + i]);
|
||||
rptx_edid_buf[pos + 1] = 0;
|
||||
/* rx_set_receiver_edid(&buff[AddrTag], len); */
|
||||
if ((Addr + (Data&0x1f)) < D)
|
||||
Edid_ParsingAudioDATABlock(info, buff,
|
||||
Addr + 1, (Data & 0x1F));
|
||||
len = (Data & 0x1f) + 1;
|
||||
if ((pRXCap->asd.len + len) > MAX_RAW_LEN)
|
||||
break;
|
||||
memcpy(&pRXCap->asd.raw[pRXCap->asd.len],
|
||||
&buff[AddrTag], len);
|
||||
pRXCap->asd.len += len;
|
||||
break;
|
||||
|
||||
case SPEAKER_TAG:
|
||||
@@ -1965,10 +1971,12 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device)
|
||||
EDID_MAX_BLOCK * 128);
|
||||
} else
|
||||
EDID_buf = hdmitx_device->EDID_buf1;
|
||||
|
||||
if (check_dvi_hdmi_edid_valid(hdmitx_device->EDID_buf1))
|
||||
hdmitx_device->edid_parsing = 1;
|
||||
|
||||
hdmitx_device->edid_ptr = EDID_buf;
|
||||
pr_info(EDID "EDID Parser:\n");
|
||||
memset(rptx_edid_buf, 0, sizeof(rptx_edid_buf));
|
||||
rptx_edid_aud = &rptx_edid_buf[0];
|
||||
/* Calculate the EDID hash for special use */
|
||||
memset(hdmitx_device->EDID_hash, 0,
|
||||
ARRAY_SIZE(hdmitx_device->EDID_hash));
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
* other devices
|
||||
*/
|
||||
extern int hdcp_ksv_valid(unsigned char *dat);
|
||||
extern unsigned int hdcp_get_downstream_ver(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ static void hdmitx_early_suspend(struct early_suspend *h)
|
||||
|| strncmp(info->name, "null", 4) == 0))
|
||||
return;
|
||||
|
||||
phdmi->ready = 0;
|
||||
phdmi->hpd_lock = 1;
|
||||
msleep(20);
|
||||
phdmi->HWOp.CntlMisc(phdmi, MISC_AVMUTE_OP, SET_AVMUTE);
|
||||
@@ -184,7 +185,7 @@ static void hdmitx_late_resume(struct early_suspend *h)
|
||||
|
||||
/* update status for hpd and switch/state */
|
||||
hdmitx_device.hpd_state =
|
||||
!!(hdmitx_device.HWOp.CntlMisc(&hdmitx_device,
|
||||
!!(hdmitx_device.HWOp.CntlMisc(&hdmitx_device,
|
||||
MISC_HPD_GPI_ST, 0));
|
||||
|
||||
pr_info("hdmitx hpd state: %d\n", hdmitx_device.hpd_state);
|
||||
@@ -218,6 +219,7 @@ static int hdmitx_reboot_notifier(struct notifier_block *nb,
|
||||
{
|
||||
struct hdmitx_dev *hdev = container_of(nb, struct hdmitx_dev, nb);
|
||||
|
||||
hdev->ready = 0;
|
||||
hdev->HWOp.CntlMisc(hdev, MISC_AVMUTE_OP, SET_AVMUTE);
|
||||
mdelay(100);
|
||||
hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE);
|
||||
@@ -447,6 +449,7 @@ static int set_disp_mode_auto(void)
|
||||
hdev, STAT_VIDEO_VIC, 0);
|
||||
|
||||
memset(mode, 0, sizeof(mode));
|
||||
hdev->ready = 0;
|
||||
|
||||
/* get current vinfo */
|
||||
info = hdmitx_get_current_vinfo();
|
||||
@@ -633,6 +636,83 @@ void setup_attr(const char *buf)
|
||||
}
|
||||
EXPORT_SYMBOL(setup_attr);
|
||||
|
||||
|
||||
/* for android application data exchange / swap */
|
||||
static char *tmp_swap;
|
||||
static DEFINE_MUTEX(mutex_swap);
|
||||
|
||||
static ssize_t store_swap(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
pr_info("store_swap: %s\n", buf);
|
||||
mutex_lock(&mutex_swap);
|
||||
|
||||
kfree(tmp_swap);
|
||||
tmp_swap = kzalloc(count + 1, GFP_KERNEL);
|
||||
if (!tmp_swap) {
|
||||
mutex_unlock(&mutex_swap);
|
||||
return count;
|
||||
}
|
||||
memcpy(tmp_swap, buf, count);
|
||||
tmp_swap[count] = '\0'; /* padding end string */
|
||||
mutex_unlock(&mutex_swap);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_swap(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
struct rx_cap *pRXCap = &hdev->RXCap;
|
||||
struct hdcprp14_topo *topo14 = &hdev->topo_info->topo.topo14;
|
||||
|
||||
mutex_lock(&mutex_swap);
|
||||
|
||||
if (!tmp_swap ||
|
||||
(!hdev->edid_parsing && !strstr(tmp_swap, "hdcp.topo"))) {
|
||||
mutex_unlock(&mutex_swap);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* VSD: Video Short Descriptor */
|
||||
if (strstr(tmp_swap, "edid.vsd"))
|
||||
for (i = 0; i < pRXCap->vsd.len; i++)
|
||||
n += snprintf(buf + n, PAGE_SIZE - n, "%02x",
|
||||
pRXCap->vsd.raw[i]);
|
||||
/* ASD: Audio Short Descriptor */
|
||||
if (strstr(tmp_swap, "edid.asd"))
|
||||
for (i = 0; i < pRXCap->asd.len; i++)
|
||||
n += snprintf(buf + n, PAGE_SIZE - n, "%02x",
|
||||
pRXCap->asd.raw[i]);
|
||||
/* CEC: Physical Address */
|
||||
if (strstr(tmp_swap, "edid.cec"))
|
||||
n += snprintf(buf + n, PAGE_SIZE - n, "%x%x%x%x",
|
||||
hdev->hdmi_info.vsdb_phy_addr.a,
|
||||
hdev->hdmi_info.vsdb_phy_addr.b,
|
||||
hdev->hdmi_info.vsdb_phy_addr.c,
|
||||
hdev->hdmi_info.vsdb_phy_addr.d);
|
||||
/* HDCP TOPO */
|
||||
if (strstr(tmp_swap, "hdcp.topo")) {
|
||||
char *tmp = (char *)topo14;
|
||||
|
||||
pr_info("max_cascade_exceeded %d\n",
|
||||
topo14->max_cascade_exceeded);
|
||||
pr_info("depth %d\n", topo14->depth);
|
||||
pr_info("max_devs_exceeded %d\n", topo14->max_devs_exceeded);
|
||||
pr_info("device_count %d\n", topo14->device_count);
|
||||
for (i = 0; i < sizeof(struct hdcprp14_topo); i++)
|
||||
n += snprintf(buf + n, PAGE_SIZE - n, "%02x", tmp[i]);
|
||||
}
|
||||
|
||||
kfree(tmp_swap);
|
||||
tmp_swap = NULL;
|
||||
|
||||
mutex_unlock(&mutex_swap);
|
||||
return n;
|
||||
}
|
||||
|
||||
static ssize_t show_aud_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -2596,24 +2676,53 @@ static ssize_t store_avmute(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int cmd = OFF_AVMUTE;
|
||||
static int mask0;
|
||||
static int mask1;
|
||||
static DEFINE_MUTEX(avmute_mutex);
|
||||
|
||||
if (strncmp(buf, "-1", 2) == 0)
|
||||
pr_info("store_avmute %s\n", buf);
|
||||
mutex_lock(&avmute_mutex);
|
||||
if (strncmp(buf, "-1", 2) == 0) {
|
||||
cmd = CLR_AVMUTE;
|
||||
else if (strncmp(buf, "0", 1) == 0)
|
||||
mask0 = -1;
|
||||
} else if (strncmp(buf, "0", 1) == 0) {
|
||||
cmd = OFF_AVMUTE;
|
||||
else if (strncmp(buf, "1", 1) == 0)
|
||||
mask0 = 0;
|
||||
} else if (strncmp(buf, "1", 1) == 0) {
|
||||
cmd = SET_AVMUTE;
|
||||
else
|
||||
pr_info(SYS "set avmute wrong: %s\n", buf);
|
||||
|
||||
mask0 = 1;
|
||||
}
|
||||
if (strncmp(buf, "r-1", 3) == 0) {
|
||||
cmd = CLR_AVMUTE;
|
||||
mask1 = -1;
|
||||
} else if (strncmp(buf, "r0", 2) == 0) {
|
||||
cmd = OFF_AVMUTE;
|
||||
mask1 = 0;
|
||||
} else if (strncmp(buf, "r1", 2) == 0) {
|
||||
cmd = SET_AVMUTE;
|
||||
mask1 = 1;
|
||||
}
|
||||
if ((mask0 == 1) || (mask1 == 1))
|
||||
cmd = SET_AVMUTE;
|
||||
else if ((mask0 == -1) && (mask1 == -1))
|
||||
cmd = CLR_AVMUTE;
|
||||
hdmitx_device.HWOp.CntlMisc(&hdmitx_device, MISC_AVMUTE_OP, cmd);
|
||||
mutex_unlock(&avmute_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_avmute(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return 0;
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
int ret = 0;
|
||||
int pos = 0;
|
||||
|
||||
ret = hdev->HWOp.CntlMisc(hdev, MISC_READ_AVMUTE_OP, 0);
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "%d", ret);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2819,6 +2928,13 @@ static ssize_t show_hdcp_lstore(struct device *dev,
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
/* if current TX is RP-TX, then return lstore as 00 */
|
||||
/* hdcp_lstore is used under only TX */
|
||||
if (hdmitx_device.repeater_tx == 1) {
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "00\n");
|
||||
return pos;
|
||||
}
|
||||
|
||||
if (hdmitx_device.lstore < 0x10) {
|
||||
hdmitx_device.lstore = 0;
|
||||
if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
@@ -2853,6 +2969,53 @@ static ssize_t store_hdcp_lstore(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
static int rptxlstore;
|
||||
static ssize_t show_hdcp_rptxlstore(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
/* if current TX is not RP-TX, then return rptxlstore as 00 */
|
||||
/* hdcp_rptxlstore is used under only RP-TX */
|
||||
if (hdmitx_device.repeater_tx == 0) {
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "00\n");
|
||||
return pos;
|
||||
}
|
||||
|
||||
if (rptxlstore < 0x10) {
|
||||
rptxlstore = 0;
|
||||
if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_14_LSTORE, 0))
|
||||
rptxlstore += 1;
|
||||
if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_22_LSTORE, 0))
|
||||
rptxlstore += 2;
|
||||
}
|
||||
if (rptxlstore & 0x1)
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "14\n");
|
||||
if (rptxlstore & 0x2)
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "22\n");
|
||||
if ((rptxlstore & 0xf) == 0)
|
||||
pos += snprintf(buf + pos, PAGE_SIZE, "00\n");
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t store_hdcp_rptxlstore(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
pr_info("hdcp: set lstore as %s\n", buf);
|
||||
if (strncmp(buf, "0", 1) == 0)
|
||||
rptxlstore = 0x10;
|
||||
if (strncmp(buf, "11", 2) == 0)
|
||||
rptxlstore = 0x11;
|
||||
if (strncmp(buf, "12", 2) == 0)
|
||||
rptxlstore = 0x12;
|
||||
if (strncmp(buf, "13", 2) == 0)
|
||||
rptxlstore = 0x13;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_div40(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -2931,39 +3094,119 @@ static ssize_t store_hdcp_mode(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
void direct_hdcptx14_start(void)
|
||||
static bool hdcp_sticky_mode;
|
||||
static ssize_t show_hdcp_stickmode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
pr_info("%s[%d]", __func__, __LINE__);
|
||||
hdmitx_device.hdcp_mode = 1;
|
||||
hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_OP, HDCP14_ON);
|
||||
}
|
||||
EXPORT_SYMBOL(direct_hdcptx14_start);
|
||||
int pos = 0;
|
||||
|
||||
void direct_hdcptx14_stop(void)
|
||||
{
|
||||
pr_info("%s[%d]", __func__, __LINE__);
|
||||
hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_OP, HDCP14_OFF);
|
||||
pos += snprintf(buf+pos, PAGE_SIZE, "%d\n", hdcp_sticky_mode);
|
||||
|
||||
return pos;
|
||||
}
|
||||
EXPORT_SYMBOL(direct_hdcptx14_stop);
|
||||
|
||||
static ssize_t store_hdcp_stickmode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
if (buf[0] == '0')
|
||||
hdcp_sticky_mode = 0;
|
||||
if (buf[0] == '1')
|
||||
hdcp_sticky_mode = 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned char hdcp_sticky_step;
|
||||
static ssize_t show_hdcp_stickstep(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
pos += snprintf(buf+pos, PAGE_SIZE, "%x\n", hdcp_sticky_step);
|
||||
if (hdcp_sticky_step)
|
||||
hdcp_sticky_step = 0;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t store_hdcp_stickstep(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
if (isdigit(buf[0]))
|
||||
hdcp_sticky_step = buf[0] - '0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Indicate whether a rptx under repeater */
|
||||
static ssize_t show_repeater_tx(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
pos += snprintf(buf+pos, PAGE_SIZE, "%d\n",
|
||||
!!hdmitx_device.repeater_tx);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_rptx.h>
|
||||
|
||||
void direct_hdcptx14_opr(enum rptx_hdcp14_cmd cmd, void *args)
|
||||
{
|
||||
int rst;
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
|
||||
pr_info("%s[%d] cmd: %d\n", __func__, __LINE__, cmd);
|
||||
switch (cmd) {
|
||||
case RPTX_HDCP14_OFF:
|
||||
hdev->hdcp_mode = 0;
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF);
|
||||
break;
|
||||
case RPTX_HDCP14_ON:
|
||||
hdev->hdcp_mode = 1;
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_ON);
|
||||
break;
|
||||
case RPTX_HDCP14_GET_AUTHST:
|
||||
rst = hdev->HWOp.CntlDDC(hdev, DDC_HDCP_GET_AUTH, 0);
|
||||
*(int *)args = rst;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(direct_hdcptx14_opr);
|
||||
|
||||
static ssize_t store_hdcp_ctrl(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
if (hdmitx_device.HWOp.CntlDDC(&hdmitx_device, DDC_HDCP_14_LSTORE,
|
||||
0) == 0)
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
|
||||
if (hdev->HWOp.CntlDDC(hdev, DDC_HDCP_14_LSTORE, 0) == 0)
|
||||
return count;
|
||||
dev_warn(dev, "hdmitx20: %s\n", buf);
|
||||
|
||||
/* for repeater */
|
||||
if (hdev->repeater_tx) {
|
||||
dev_warn(dev, "hdmitx20: %s\n", buf);
|
||||
if (strncmp(buf, "rstop", 5) == 0) {
|
||||
if (strncmp(buf+5, "14", 2) == 0)
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP,
|
||||
HDCP14_OFF);
|
||||
if (strncmp(buf+5, "22", 2) == 0)
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP,
|
||||
HDCP22_OFF);
|
||||
hdev->hdcp_mode = 0;
|
||||
hdmitx_hdcp_do_work(hdev);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/* for non repeater */
|
||||
if (strncmp(buf, "stop", 4) == 0) {
|
||||
dev_warn(dev, "hdmitx20: %s\n", buf);
|
||||
if (strncmp(buf+4, "14", 2) == 0)
|
||||
hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_OP, HDCP14_OFF);
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF);
|
||||
if (strncmp(buf+4, "22", 2) == 0)
|
||||
hdmitx_device.HWOp.CntlDDC(&hdmitx_device,
|
||||
DDC_HDCP_OP, HDCP22_OFF);
|
||||
hdmitx_device.hdcp_mode = 0;
|
||||
hdmitx_hdcp_do_work(&hdmitx_device);
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP22_OFF);
|
||||
hdev->hdcp_mode = 0;
|
||||
hdmitx_hdcp_do_work(hdev);
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -3047,6 +3290,26 @@ static ssize_t show_hpd_state(struct device *dev,
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_rhpd_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
int st;
|
||||
|
||||
st = hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d", hdev->rhpd_state);
|
||||
}
|
||||
|
||||
static ssize_t show_max_exceed_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hdmitx_dev *hdev = &hdmitx_device;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d", hdev->hdcp_max_exceed_state);
|
||||
}
|
||||
|
||||
static ssize_t show_hdmi_init(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -3105,6 +3368,7 @@ static DEVICE_ATTR(dc_cap, 0444, show_dc_cap, NULL);
|
||||
static DEVICE_ATTR(valid_mode, 0664, show_valid_mode, store_valid_mode);
|
||||
static DEVICE_ATTR(aud_ch, 0664, show_aud_ch, store_aud_ch);
|
||||
static DEVICE_ATTR(avmute, 0664, show_avmute, store_avmute);
|
||||
static DEVICE_ATTR(swap, 0644, show_swap, store_swap);
|
||||
static DEVICE_ATTR(vic, 0664, show_vic, store_vic);
|
||||
static DEVICE_ATTR(phy, 0664, show_phy, store_phy);
|
||||
static DEVICE_ATTR(sspll, 0664, show_sspll, store_sspll);
|
||||
@@ -3116,11 +3380,18 @@ static DEVICE_ATTR(hdcp_pwr, 0664, show_hdcp_pwr, store_hdcp_pwr);
|
||||
static DEVICE_ATTR(hdcp_byp, 0200, NULL, store_hdcp_byp);
|
||||
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_rptxlstore, 0664, show_hdcp_rptxlstore,
|
||||
store_hdcp_rptxlstore);
|
||||
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(hdcp_stickmode, 0664, show_hdcp_stickmode,
|
||||
store_hdcp_stickmode);
|
||||
static DEVICE_ATTR(hdcp_stickstep, 0664, show_hdcp_stickstep,
|
||||
store_hdcp_stickstep);
|
||||
static DEVICE_ATTR(hdmi_repeater_tx, 0444, show_repeater_tx, NULL);
|
||||
static DEVICE_ATTR(hdcp22_base, 0444, show_hdcp22_base, NULL);
|
||||
static DEVICE_ATTR(div40, 0664, show_div40, store_div40);
|
||||
static DEVICE_ATTR(hdcp_ctrl, 0664, show_hdcp_ctrl, store_hdcp_ctrl);
|
||||
@@ -3128,6 +3399,8 @@ static DEVICE_ATTR(disp_cap_3d, 0444, show_disp_cap_3d, NULL);
|
||||
static DEVICE_ATTR(hdcp_ksv_info, 0444, show_hdcp_ksv_info, NULL);
|
||||
static DEVICE_ATTR(hdcp_ver, 0444, show_hdcp_ver, NULL);
|
||||
static DEVICE_ATTR(hpd_state, 0444, show_hpd_state, NULL);
|
||||
static DEVICE_ATTR(rhpd_state, 0444, show_rhpd_state, NULL);
|
||||
static DEVICE_ATTR(max_exceed, 0444, show_max_exceed_state, NULL);
|
||||
static DEVICE_ATTR(hdmi_init, 0444, show_hdmi_init, NULL);
|
||||
static DEVICE_ATTR(ready, 0664, show_ready, store_ready);
|
||||
static DEVICE_ATTR(support_3d, 0444, show_support_3d, NULL);
|
||||
@@ -3451,9 +3724,11 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
|
||||
}
|
||||
mutex_lock(&setclk_mutex);
|
||||
pr_info(SYS "plugin\n");
|
||||
hdev->HWOp.CntlMisc(hdev, MISC_I2C_REACTIVE, 0);
|
||||
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN;
|
||||
/* start reading E-EDID */
|
||||
rx_repeat_hpd_state(1);
|
||||
if (hdev->repeater_tx)
|
||||
rx_repeat_hpd_state(1);
|
||||
hdmitx_get_edid(hdev);
|
||||
hdmi_physcial_size_update(hdev);
|
||||
|
||||
@@ -3478,7 +3753,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
|
||||
}
|
||||
|
||||
mutex_lock(&getedid_mutex);
|
||||
hdev->HWOp.CntlMisc(hdev, MISC_I2C_REACTIVE, 0);
|
||||
mutex_unlock(&getedid_mutex);
|
||||
if (hdev->repeater_tx) {
|
||||
if (check_fbc_special(&hdev->EDID_buf[0])
|
||||
@@ -3486,7 +3760,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
|
||||
rx_set_repeater_support(0);
|
||||
else
|
||||
rx_set_repeater_support(1);
|
||||
rx_repeat_hdcp_ver(hdcp_get_downstream_ver());
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_GET_BKSV,
|
||||
(unsigned long int)bksv_buf);
|
||||
rx_set_receive_hdcp(bksv_buf, 1, 1, 0, 0);
|
||||
@@ -3539,7 +3812,8 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
|
||||
return;
|
||||
hdev->hdcp_mode = 0;
|
||||
hdev->hdcp_bcaps_repeater = 0;
|
||||
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1);
|
||||
hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF);
|
||||
mutex_lock(&setclk_mutex);
|
||||
pr_info(SYS "plugout\n");
|
||||
if (!!(hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0))) {
|
||||
@@ -4011,6 +4285,14 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev)
|
||||
pr_info(SYS "hdmitx_device.chip_type : %d\n",
|
||||
hdmitx_device.chip_type);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"repeater_tx", &val);
|
||||
if (!ret)
|
||||
hdmitx_device.repeater_tx = val;
|
||||
if (hdmitx_device.repeater_tx == 1)
|
||||
hdmitx_device.topo_info = kzalloc(
|
||||
sizeof(*hdmitx_device.topo_info), GFP_KERNEL);
|
||||
|
||||
/* Get vendor information */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"vend-data", &val);
|
||||
@@ -4202,6 +4484,7 @@ static int amhdmitx_probe(struct platform_device *pdev)
|
||||
ret = device_create_file(dev, &dev_attr_dv_cap);
|
||||
ret = device_create_file(dev, &dev_attr_aud_ch);
|
||||
ret = device_create_file(dev, &dev_attr_avmute);
|
||||
ret = device_create_file(dev, &dev_attr_swap);
|
||||
ret = device_create_file(dev, &dev_attr_vic);
|
||||
ret = device_create_file(dev, &dev_attr_phy);
|
||||
ret = device_create_file(dev, &dev_attr_frac_rate_policy);
|
||||
@@ -4216,11 +4499,17 @@ static int amhdmitx_probe(struct platform_device *pdev)
|
||||
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_hdcp_stickmode);
|
||||
ret = device_create_file(dev, &dev_attr_hdcp_stickstep);
|
||||
ret = device_create_file(dev, &dev_attr_hdmi_repeater_tx);
|
||||
ret = device_create_file(dev, &dev_attr_hdcp22_base);
|
||||
ret = device_create_file(dev, &dev_attr_hdcp_lstore);
|
||||
ret = device_create_file(dev, &dev_attr_hdcp_rptxlstore);
|
||||
ret = device_create_file(dev, &dev_attr_div40);
|
||||
ret = device_create_file(dev, &dev_attr_hdcp_ctrl);
|
||||
ret = device_create_file(dev, &dev_attr_hpd_state);
|
||||
ret = device_create_file(dev, &dev_attr_rhpd_state);
|
||||
ret = device_create_file(dev, &dev_attr_max_exceed);
|
||||
ret = device_create_file(dev, &dev_attr_hdmi_init);
|
||||
ret = device_create_file(dev, &dev_attr_ready);
|
||||
ret = device_create_file(dev, &dev_attr_support_3d);
|
||||
@@ -4296,6 +4585,8 @@ static int amhdmitx_remove(struct platform_device *pdev)
|
||||
device_remove_file(dev, &dev_attr_dc_cap);
|
||||
device_remove_file(dev, &dev_attr_valid_mode);
|
||||
device_remove_file(dev, &dev_attr_hpd_state);
|
||||
device_remove_file(dev, &dev_attr_rhpd_state);
|
||||
device_remove_file(dev, &dev_attr_max_exceed);
|
||||
device_remove_file(dev, &dev_attr_hdmi_init);
|
||||
device_remove_file(dev, &dev_attr_ready);
|
||||
device_remove_file(dev, &dev_attr_support_3d);
|
||||
@@ -4309,7 +4600,11 @@ static int amhdmitx_remove(struct platform_device *pdev)
|
||||
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_hdcp_stickmode);
|
||||
device_remove_file(dev, &dev_attr_hdcp_stickstep);
|
||||
device_remove_file(dev, &dev_attr_hdmi_repeater_tx);
|
||||
device_remove_file(dev, &dev_attr_hdcp22_base);
|
||||
device_remove_file(dev, &dev_attr_swap);
|
||||
|
||||
cdev_del(&hdmitx_device.cdev);
|
||||
|
||||
|
||||
@@ -59,6 +59,14 @@ static void hdmitx_csc_config(unsigned char input_color_format,
|
||||
static int hdmitx_hdmi_dvi_config(struct hdmitx_dev *hdev,
|
||||
unsigned int dvi_mode);
|
||||
static void hdmitx_set_avi_colorimetry(struct hdmi_format_para *para);
|
||||
|
||||
struct ksv_lists_ {
|
||||
unsigned char valid;
|
||||
unsigned int no;
|
||||
unsigned char lists[MAX_KSV_LISTS * 5];
|
||||
};
|
||||
static struct ksv_lists_ tmp_ksv_lists;
|
||||
|
||||
static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB);
|
||||
static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB,
|
||||
unsigned char *CHAN_STAT_BUF);
|
||||
@@ -269,6 +277,31 @@ static void config_avmute(unsigned int val)
|
||||
}
|
||||
}
|
||||
|
||||
static int read_avmute(void)
|
||||
{
|
||||
int val;
|
||||
int ret = 0;
|
||||
|
||||
val = hdmitx_rd_reg(HDMITX_DWC_FC_GCP) & 0x3;
|
||||
|
||||
switch (val) {
|
||||
case 2:
|
||||
ret = 1;
|
||||
break;
|
||||
case 1:
|
||||
ret = -1;
|
||||
break;
|
||||
case 0:
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void config_video_mapping(enum hdmi_color_space cs,
|
||||
enum hdmi_color_depth cd)
|
||||
{
|
||||
@@ -463,6 +496,8 @@ static void hdmi_hwp_init(struct hdmitx_dev *hdev)
|
||||
/* assign phy_clk_en = control[1]; */
|
||||
/* Bring HDMITX MEM output of power down */
|
||||
hd_set_reg_bits(P_HHI_MEM_PD_REG0, 0, 8, 8);
|
||||
/* enable CLK_TO_DIG */
|
||||
hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL3, 0x3, 0, 2);
|
||||
if (hdmitx_uboot_already_display()) {
|
||||
hdev->ready = 1;
|
||||
/* Get uboot output color space from AVI */
|
||||
@@ -580,6 +615,10 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev)
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_0, 0xcf);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_LCNT_1, 0);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_LCNT_0, 0xff);
|
||||
if (hdev->repeater_tx == 1) {
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_0, 0x67);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_LCNT_0, 0x78);
|
||||
}
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_HCNT_1, 0);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_HCNT_0, 0x0f);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_FS_SCL_LCNT_1, 0);
|
||||
@@ -612,60 +651,63 @@ void HDMITX_Meson_Init(struct hdmitx_dev *hdev)
|
||||
hdmi_hwp_init(hdev);
|
||||
hdmi_hwi_init(hdev);
|
||||
hdev->HWOp.CntlMisc(hdev, MISC_AVMUTE_OP, CLR_AVMUTE);
|
||||
rptx_ksvs = &rptx_ksv_prbuf[0];
|
||||
}
|
||||
|
||||
static irqreturn_t intr_handler(int irq, void *dev)
|
||||
{
|
||||
unsigned int data32 = 0;
|
||||
/* get interrupt status */
|
||||
unsigned int dat_top = hdmitx_rd_reg(HDMITX_TOP_INTR_STAT);
|
||||
unsigned int dat_dwc = hdmitx_rd_reg(HDMITX_DWC_HDCP22REG_STAT);
|
||||
struct hdmitx_dev *hdev = (struct hdmitx_dev *)dev;
|
||||
|
||||
/* get interrupt status */
|
||||
data32 = hdmitx_rd_reg(HDMITX_TOP_INTR_STAT);
|
||||
pr_info(HW "irq %x\n", data32);
|
||||
/* ack INTERNAL_INTR or else we stuck with no interrupts at all */
|
||||
hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, ~0);
|
||||
hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff);
|
||||
|
||||
pr_info(SYS "irq %x\n", dat_top);
|
||||
if (dat_dwc)
|
||||
pr_info(SYS "irq %x\n", dat_dwc);
|
||||
if (hdev->hpd_lock == 1) {
|
||||
hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0xf);
|
||||
pr_info(HW "HDMI hpd locked\n");
|
||||
goto next;
|
||||
}
|
||||
/* check HPD status */
|
||||
if ((data32 & (1 << 1)) && (data32 & (1 << 2))) {
|
||||
if ((dat_top & (1 << 1)) && (dat_top & (1 << 2))) {
|
||||
if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO))
|
||||
data32 &= ~(1 << 2);
|
||||
dat_top &= ~(1 << 2);
|
||||
else
|
||||
data32 &= ~(1 << 1);
|
||||
dat_top &= ~(1 << 1);
|
||||
}
|
||||
/* HPD rising */
|
||||
if (data32 & (1 << 1)) {
|
||||
if (dat_top & (1 << 1)) {
|
||||
hdev->hdmitx_event |= HDMI_TX_HPD_PLUGIN;
|
||||
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT;
|
||||
hdev->rhpd_state = 1;
|
||||
queue_delayed_work(hdev->hdmi_wq,
|
||||
&hdev->work_hpd_plugin, HZ / 2);
|
||||
}
|
||||
/* HPD falling */
|
||||
if (data32 & (1 << 2)) {
|
||||
if (dat_top & (1 << 2)) {
|
||||
queue_delayed_work(hdev->hdmi_wq,
|
||||
&hdev->work_aud_hpd_plug, 2 * HZ);
|
||||
hdev->hdmitx_event |= HDMI_TX_HPD_PLUGOUT;
|
||||
hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN;
|
||||
hdev->rhpd_state = 0;
|
||||
queue_delayed_work(hdev->hdmi_wq,
|
||||
&hdev->work_hpd_plugout, HZ / 20);
|
||||
}
|
||||
next:
|
||||
/* internal interrupt */
|
||||
if (data32 & (1 << 0)) {
|
||||
if (dat_top & (1 << 0)) {
|
||||
hdev->hdmitx_event |= HDMI_TX_INTERNAL_INTR;
|
||||
queue_work(hdev->hdmi_wq, &hdev->work_internal_intr);
|
||||
}
|
||||
if (data32 & (1 << 3)) {
|
||||
if (dat_top & (1 << 3)) {
|
||||
unsigned int rd_nonce_mode =
|
||||
hdmitx_rd_reg(HDMITX_TOP_SKP_CNTL_STAT) & 0x1;
|
||||
pr_info(HW "hdcp22: Nonce %s Vld: %d\n",
|
||||
rd_nonce_mode ? "HW" : "SW",
|
||||
((hdmitx_rd_reg(HDMITX_TOP_SKP_CNTL_STAT) >> 31) & 1));
|
||||
if (rd_nonce_mode)
|
||||
hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, (1 << 3));
|
||||
else {
|
||||
if (!rd_nonce_mode) {
|
||||
hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x32107654);
|
||||
hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xba98fedc);
|
||||
hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0xcdef89ab);
|
||||
@@ -676,13 +718,10 @@ next:
|
||||
hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x01234567);
|
||||
}
|
||||
}
|
||||
if (data32 & (1 << 30)) {
|
||||
pr_info(HW "hdcp22: reg stat: 0x%x\n",
|
||||
hdmitx_rd_reg(HDMITX_DWC_HDCP22REG_STAT));
|
||||
hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff);
|
||||
}
|
||||
/* ack INTERNAL_INTR or else we stuck with no interrupts at all */
|
||||
hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, data32 | 0x7);
|
||||
if (dat_top & (1 << 30))
|
||||
pr_info("hdcp22: reg stat: 0x%x\n", dat_dwc);
|
||||
|
||||
next:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -2628,8 +2667,14 @@ static void set_aud_samp_pkt(struct hdmitx_dev *hdev,
|
||||
}
|
||||
}
|
||||
|
||||
static int amute_flag = -1;
|
||||
static void audio_mute_op(bool flag)
|
||||
{
|
||||
if (amute_flag != flag)
|
||||
amute_flag = flag;
|
||||
else
|
||||
return;
|
||||
|
||||
if (flag == 0) {
|
||||
hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 0, 2, 2);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 0, 0, 1);
|
||||
@@ -4403,8 +4448,6 @@ static void hdmitx_read_edid(unsigned char *rx_edid)
|
||||
}
|
||||
} /* hdmi20_tx_read_edid */
|
||||
|
||||
#define HDCP_NMOOFDEVICES 127
|
||||
|
||||
static int get_hdcp_depth(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -4453,68 +4496,54 @@ static int get_hdcp_device_count(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void get_hdcp_bstatus(void)
|
||||
static void get_hdcp_bstatus(int *ret1, int *ret2)
|
||||
{
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1);
|
||||
hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
|
||||
ret1 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0);
|
||||
ret2 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1);
|
||||
*ret1 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0);
|
||||
*ret2 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
|
||||
pr_info("BSTATUS0 = 0x%x BSTATUS1 = 0x%x\n", ret1, ret2);
|
||||
}
|
||||
|
||||
static void hdcp_ksv_store(unsigned char *dat, int no)
|
||||
static void hdcp_ksv_store(struct hdcprp_topo *topo,
|
||||
unsigned char *dat, int no)
|
||||
{
|
||||
int i;
|
||||
int pos;
|
||||
|
||||
for (i = 0; i < no; i++) {
|
||||
rptx_ksv_buf[rptx_ksv_no] = dat[i];
|
||||
rptx_ksv_no++;
|
||||
}
|
||||
}
|
||||
|
||||
static void hdcp_ksv_print(void)
|
||||
{
|
||||
unsigned int i, pos;
|
||||
unsigned char *tmp_buf = NULL;
|
||||
|
||||
tmp_buf = kmalloc(2000, GFP_ATOMIC);
|
||||
if (!tmp_buf)
|
||||
if (!topo)
|
||||
return;
|
||||
if (topo->hdcp_ver != 1)
|
||||
return;
|
||||
/* must check ksv num to prevent leak */
|
||||
if (topo->topo.topo14.device_count >= MAX_KSV_LISTS)
|
||||
return;
|
||||
|
||||
pos = 0;
|
||||
memset(tmp_buf, 0, sizeof(2000));
|
||||
pos += sprintf(tmp_buf + pos, "Dump ksv test START\n");
|
||||
for (i = 0; (i < rptx_ksv_no) && (i < 635); i++) {
|
||||
pos += sprintf(tmp_buf + pos, "%02x", rptx_ksv_buf[i]);
|
||||
if (((i+1) % 40) == 0) /* print 40bytes a line */
|
||||
pos += sprintf(tmp_buf + pos, "\n");
|
||||
}
|
||||
pos += sprintf(tmp_buf + pos, "\n");
|
||||
pos += sprintf(tmp_buf + pos, "Dump ksv test END\n");
|
||||
pr_info("%s\n", tmp_buf);
|
||||
kfree(tmp_buf);
|
||||
pos = topo->topo.topo14.device_count * 5;
|
||||
for (i = 0; (i < no) && (i < MAX_KSV_LISTS * 5); i++)
|
||||
topo->topo.topo14.ksv_list[pos++] = dat[i];
|
||||
topo->topo.topo14.device_count += no / 5;
|
||||
}
|
||||
|
||||
static uint8_t *hdcp_mKsvListBuf;
|
||||
static int ksv_sha_matched;
|
||||
static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev)
|
||||
{
|
||||
size_t list = 0;
|
||||
size_t size = 0;
|
||||
size_t i = 0;
|
||||
int valid = HDCP_NULL;
|
||||
unsigned char ksvs[635] = {0}; /* Max 127 * 5 */
|
||||
char temp[MAX_KSV_LISTS * 5];
|
||||
int j = 0;
|
||||
|
||||
/* 0x165e: Page 95 */
|
||||
memset(&tmp_ksv_lists, 0, sizeof(tmp_ksv_lists));
|
||||
memset(&temp[0], 0, sizeof(temp));
|
||||
hdcp_mKsvListBuf = kmalloc(0x1660, GFP_ATOMIC);
|
||||
if (hdcp_mKsvListBuf) {
|
||||
/* KSV_SIZE; */
|
||||
list = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0) & KSV_MASK;
|
||||
if (list <= HDCP_NMOOFDEVICES) {
|
||||
if (list <= MAX_KSV_LISTS) {
|
||||
size = (list * KSV_SIZE) + HDCP_HEAD + SHA_MAX_SIZE;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i < HDCP_HEAD) { /* BSTATUS & M0 */
|
||||
@@ -4527,9 +4556,11 @@ static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev)
|
||||
hdcp_mKsvListBuf[i - HDCP_HEAD] =
|
||||
hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCP_BSTATUS_0 + i);
|
||||
ksvs[j] =
|
||||
tmp_ksv_lists.lists[tmp_ksv_lists.no++]
|
||||
= hdcp_mKsvListBuf[i -
|
||||
HDCP_HEAD];
|
||||
temp[j++] =
|
||||
hdcp_mKsvListBuf[i - HDCP_HEAD];
|
||||
j++;
|
||||
} else { /* SHA */
|
||||
hdcp_mKsvListBuf[i] = hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCP_BSTATUS_0 + i);
|
||||
@@ -4539,12 +4570,18 @@ static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev)
|
||||
valid = HDCP_KSVLIST_VALID;
|
||||
else
|
||||
valid = HDCP_KSVLIST_INVALID;
|
||||
ksv_sha_matched = valid;
|
||||
}
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL,
|
||||
(valid == HDCP_KSVLIST_VALID) ? 0 : 1, 3, 1);
|
||||
if (valid == HDCP_KSVLIST_VALID)
|
||||
hdcp_ksv_store(ksvs, j);
|
||||
if (valid == HDCP_KSVLIST_VALID) {
|
||||
tmp_ksv_lists.valid = 1;
|
||||
for (i = 0; (i < j) &&
|
||||
(tmp_ksv_lists.no < MAX_KSV_LISTS * 5); i++)
|
||||
tmp_ksv_lists.lists[tmp_ksv_lists.no++]
|
||||
= temp[i];
|
||||
}
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 2, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 2, 1);
|
||||
kfree(hdcp_mKsvListBuf);
|
||||
@@ -4552,15 +4589,50 @@ static void hdcp_ksv_sha1_calc(struct hdmitx_dev *hdev)
|
||||
pr_info("hdcptx14: KSV List memory not valid\n");
|
||||
}
|
||||
|
||||
static int max_exceed = 200;
|
||||
MODULE_PARM_DESC(max_exceed, "\nmax_exceed\n");
|
||||
module_param(max_exceed, int, 0664);
|
||||
|
||||
static void hdcptx_events_handle(unsigned long arg)
|
||||
{
|
||||
struct hdmitx_dev *hdev = (struct hdmitx_dev *)arg;
|
||||
unsigned char ksv[5] = {0};
|
||||
int pos, i;
|
||||
int i;
|
||||
unsigned int bcaps_6_rp;
|
||||
static unsigned int bcaps_5_ksvfifoready;
|
||||
static unsigned int st_flag = -1;
|
||||
static unsigned int hdcpobs3_1;
|
||||
unsigned int hdcpobs3_2;
|
||||
struct hdcprp14_topo *topo14 = &hdev->topo_info->topo.topo14;
|
||||
int bstatus0 = 0;
|
||||
int bstatus1 = 0;
|
||||
|
||||
if (hdev->hdcp_max_exceed_cnt == 0) {
|
||||
hdcpobs3_1 = 0;
|
||||
bcaps_5_ksvfifoready = 0;
|
||||
}
|
||||
|
||||
hdcpobs3_2 = hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3);
|
||||
if (hdcpobs3_1 != hdcpobs3_2)
|
||||
hdcpobs3_1 = hdcpobs3_2;
|
||||
|
||||
bcaps_6_rp = !!(hdcpobs3_1 & (1 << 6));
|
||||
bcaps_5_ksvfifoready = !!(hdcpobs3_1 & (1 << 5));
|
||||
|
||||
if (bcaps_6_rp && bcaps_5_ksvfifoready
|
||||
&& (hdev->hdcp_max_exceed_cnt == 0))
|
||||
hdev->hdcp_max_exceed_cnt++;
|
||||
if (hdev->hdcp_max_exceed_cnt)
|
||||
hdev->hdcp_max_exceed_cnt++;
|
||||
if (bcaps_6_rp && bcaps_5_ksvfifoready) {
|
||||
if ((hdev->hdcp_max_exceed_cnt > max_exceed)
|
||||
&& !ksv_sha_matched) {
|
||||
topo14->max_devs_exceeded = 1;
|
||||
topo14->max_cascade_exceeded = 1;
|
||||
hdev->hdcp_max_exceed_state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bcaps_6_rp = !!(hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3) & (1 << 6));
|
||||
if (st_flag != hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT)) {
|
||||
st_flag = hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT);
|
||||
pr_info("hdcp14: instat: 0x%x\n", st_flag);
|
||||
@@ -4568,27 +4640,43 @@ static void hdcptx_events_handle(unsigned long arg)
|
||||
if (st_flag & (1 << 7)) {
|
||||
hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 1 << 7);
|
||||
hdmitx_hdcp_opr(3);
|
||||
if (bcaps_6_rp)
|
||||
get_hdcp_bstatus(&bstatus0, &bstatus1);
|
||||
for (i = 0; i < 5; i++)
|
||||
ksv[i] = (unsigned char)
|
||||
hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + i);
|
||||
hdcp_ksv_store(ksv, 5);
|
||||
get_hdcp_bstatus();
|
||||
if (hdev->repeater_tx) {
|
||||
rx_set_receive_hdcp(rptx_ksv_buf, (rptx_ksv_no + 1) / 5,
|
||||
(bcaps_6_rp ? get_hdcp_depth() : 0) + 1,
|
||||
bcaps_6_rp ? get_hdcp_max_cascade() : 0,
|
||||
bcaps_6_rp ? get_hdcp_max_devs() : 0);
|
||||
pr_info("%s[%d] ksvs Num = %d device_count = %d\n",
|
||||
__func__, __LINE__,
|
||||
(rptx_ksv_no + 1) / 5,
|
||||
bcaps_6_rp ? get_hdcp_device_count() : 0);
|
||||
memset(rptx_ksv_prbuf, 0, sizeof(rptx_ksv_prbuf));
|
||||
for (pos = 0, i = 0; i < rptx_ksv_no; i++)
|
||||
pos += sprintf(rptx_ksv_prbuf + pos,
|
||||
"%02x", rptx_ksv_buf[i]);
|
||||
rptx_ksv_prbuf[pos + 1] = '\0';
|
||||
if (1)
|
||||
hdcp_ksv_print();
|
||||
/* if downstream is only RX */
|
||||
if ((hdev->repeater_tx == 1) && hdev->topo_info) {
|
||||
hdcp_ksv_store(hdev->topo_info, ksv, 5);
|
||||
if (tmp_ksv_lists.valid) {
|
||||
int cnt = get_hdcp_device_count();
|
||||
int devs = get_hdcp_max_devs();
|
||||
int cascade = get_hdcp_max_cascade();
|
||||
int depth = get_hdcp_depth();
|
||||
|
||||
hdcp_ksv_store(hdev->topo_info,
|
||||
tmp_ksv_lists.lists, tmp_ksv_lists.no);
|
||||
if (cnt >= 127) {
|
||||
topo14->device_count = 127;
|
||||
topo14->max_devs_exceeded = 1;
|
||||
} else {
|
||||
topo14->device_count = cnt + 1;
|
||||
topo14->max_devs_exceeded = devs;
|
||||
}
|
||||
|
||||
if (depth >= 7) {
|
||||
topo14->depth = 7;
|
||||
topo14->max_cascade_exceeded = 1;
|
||||
} else {
|
||||
topo14->depth = depth + 1;
|
||||
topo14->max_cascade_exceeded = cascade;
|
||||
}
|
||||
} else {
|
||||
topo14->device_count = 1;
|
||||
topo14->max_devs_exceeded = 0;
|
||||
topo14->max_cascade_exceeded = 0;
|
||||
topo14->depth = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st_flag & (1 << 1)) {
|
||||
@@ -4602,30 +4690,8 @@ static void hdcptx_events_handle(unsigned long arg)
|
||||
return;
|
||||
}
|
||||
hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x4);
|
||||
if (hdev->repeater_tx) {
|
||||
rptx_ksvlist_retry++;
|
||||
if (rptx_ksvlist_retry % 4 == 0) {
|
||||
for (i = 0; i < 5; i++)
|
||||
ksv[i] = (unsigned char) hdmitx_rd_reg(
|
||||
HDMITX_DWC_HDCPREG_BKSV0 + i);
|
||||
hdcp_ksv_store(ksv, 5);
|
||||
rx_set_receive_hdcp(&ksv[0], 1, 127, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hdev->repeater_tx && bcaps_6_rp && (get_hdcp_max_devs() ||
|
||||
get_hdcp_max_cascade())) {
|
||||
for (i = 0; i < 5; i++)
|
||||
ksv[i] = (unsigned char)
|
||||
hdmitx_rd_reg(HDMITX_DWC_HDCPREG_BKSV0 + i);
|
||||
hdcp_ksv_store(ksv, 5);
|
||||
rx_set_receive_hdcp(&ksv[0], 1, 127, 1, 1);
|
||||
}
|
||||
if (hdev->hdcp_try_times)
|
||||
mod_timer(&hdev->hdcp_timer, jiffies + HZ / 100);
|
||||
else
|
||||
return;
|
||||
hdev->hdcp_try_times--;
|
||||
mod_timer(&hdev->hdcp_timer, jiffies + HZ / 100);
|
||||
}
|
||||
|
||||
static void hdcp_start_timer(struct hdmitx_dev *hdev)
|
||||
@@ -4639,10 +4705,8 @@ static void hdcp_start_timer(struct hdmitx_dev *hdev)
|
||||
hdev->hdcp_timer.function = hdcptx_events_handle;
|
||||
hdev->hdcp_timer.expires = jiffies + HZ / 100;
|
||||
add_timer(&hdev->hdcp_timer);
|
||||
hdev->hdcp_try_times = 500;
|
||||
return;
|
||||
}
|
||||
hdev->hdcp_try_times = 500;
|
||||
hdev->hdcp_timer.expires = jiffies + HZ / 100;
|
||||
mod_timer(&hdev->hdcp_timer, jiffies + HZ / 100);
|
||||
}
|
||||
@@ -4672,6 +4736,20 @@ static void set_pkf_duk_nonce(void)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void check_read_ksv_list_st(void)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
for (cnt = 0; cnt < 5; cnt++) {
|
||||
if (((hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS1) & 0x7) == 5) ||
|
||||
((hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS1) & 0x7) == 6))
|
||||
msleep(20);
|
||||
else
|
||||
return;
|
||||
}
|
||||
pr_info("hdcp14: FSM: A9 read ksv list\n");
|
||||
}
|
||||
|
||||
static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
unsigned long argv)
|
||||
{
|
||||
@@ -4731,22 +4809,33 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
}
|
||||
if (argv == 1)
|
||||
hdmitx_hdcp_opr(6);
|
||||
if (argv == 3)
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_HDCP22REG_CTRL, 1, 2, 1);
|
||||
break;
|
||||
case DDC_HDCP_OP:
|
||||
hdev->hdcp_max_exceed_state = 0;
|
||||
hdev->hdcp_max_exceed_cnt = 0;
|
||||
ksv_sha_matched = 0;
|
||||
del_timer(&hdev->hdcp_timer);
|
||||
if (hdev->topo_info)
|
||||
memset(hdev->topo_info, 0, sizeof(*hdev->topo_info));
|
||||
|
||||
if (argv == HDCP14_ON) {
|
||||
rptx_ksvlist_retry = 0;
|
||||
rptx_ksv_no = 0;
|
||||
memset(rptx_ksv_buf, 0, sizeof(rptx_ksv_buf));
|
||||
check_read_ksv_list_st();
|
||||
if (hdev->topo_info)
|
||||
hdev->topo_info->hdcp_ver = HDCPVER_14;
|
||||
hdmitx_ddc_hw_op(DDC_MUX_DDC);
|
||||
hdmitx_set_reg_bits(HDMITX_TOP_SKP_CNTL_STAT, 0, 3, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 31, 1);
|
||||
hdmitx_hdcp_opr(6);
|
||||
hdmitx_hdcp_opr(1);
|
||||
hdcp_start_timer(hdev);
|
||||
}
|
||||
if (argv == HDCP14_OFF) {
|
||||
rptx_ksvlist_retry = 0;
|
||||
if (argv == HDCP14_OFF)
|
||||
hdmitx_hdcp_opr(4);
|
||||
}
|
||||
if (argv == HDCP22_ON) {
|
||||
if (hdev->topo_info)
|
||||
hdev->topo_info->hdcp_ver = 2;
|
||||
hdmitx_ddc_hw_op(DDC_MUX_DDC);
|
||||
hdmitx_hdcp_opr(5);
|
||||
/* wait for start hdcp22app */
|
||||
@@ -4754,6 +4843,9 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
if (argv == HDCP22_OFF)
|
||||
hdmitx_hdcp_opr(6);
|
||||
break;
|
||||
case DDC_IS_HDCP_ON:
|
||||
/* argv = !!((hdmitx_rd_reg(TX_HDCP_MODE)) & (1 << 7)); */
|
||||
break;
|
||||
case DDC_HDCP_GET_BKSV:
|
||||
tmp_char = (unsigned char *) argv;
|
||||
for (i = 0; i < 5; i++)
|
||||
@@ -4962,6 +5054,8 @@ static int hdmitx_tmds_rxsense(void)
|
||||
static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
unsigned int argv)
|
||||
{
|
||||
static int st;
|
||||
|
||||
if ((cmd & CMD_MISC_OFFSET) != CMD_MISC_OFFSET) {
|
||||
pr_err(HW "misc: w: invalid cmd 0x%x\n", cmd);
|
||||
return -1;
|
||||
@@ -5002,16 +5096,24 @@ static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
case MISC_AVMUTE_OP:
|
||||
config_avmute(argv);
|
||||
break;
|
||||
case MISC_READ_AVMUTE_OP:
|
||||
return read_avmute();
|
||||
case MISC_HDCP_CLKDIS:
|
||||
if (st != !!argv) {
|
||||
st = !!argv;
|
||||
pr_info("set hdcp clkdis: %d\n", !!argv);
|
||||
}
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, !!argv, 6, 1);
|
||||
break;
|
||||
case MISC_I2C_REACTIVE:
|
||||
hdmitx_hdcp_opr(4);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_A_HDCPCFG1, 0, 0, 1);
|
||||
hdmitx_set_reg_bits(HDMITX_DWC_HDCP22REG_CTRL, 0, 2, 1);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_1, 0xff);
|
||||
hdmitx_wr_reg(HDMITX_DWC_I2CM_SS_SCL_HCNT_0, 0xf6);
|
||||
edid_read_head_8bytes();
|
||||
hdmi_hwi_init(hdev);
|
||||
mdelay(5);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -5087,7 +5189,10 @@ static int hdmitx_get_state(struct hdmitx_dev *hdev, unsigned int cmd,
|
||||
static void hdmi_phy_suspend(void)
|
||||
{
|
||||
hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x0);
|
||||
hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x0);
|
||||
/* keep PHY_CNTL3 bit[1:0] as 0b11,
|
||||
* otherwise may cause HDCP22 boot failed
|
||||
*/
|
||||
hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x3);
|
||||
hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x800);
|
||||
}
|
||||
|
||||
@@ -5504,7 +5609,8 @@ static void config_hdmi20_tx(enum hdmi_vic vic,
|
||||
data32 |= (default_phase << 2);
|
||||
data32 |= (0 << 1);
|
||||
data32 |= (0 << 0);
|
||||
hdmitx_wr_reg(HDMITX_DWC_FC_GCP, data32);
|
||||
if (!hdev->repeater_tx)
|
||||
hdmitx_wr_reg(HDMITX_DWC_FC_GCP, data32);
|
||||
|
||||
/* write AVI Infoframe packet configuration */
|
||||
data32 = 0;
|
||||
|
||||
@@ -131,42 +131,6 @@ 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---------------------------------- */
|
||||
|
||||
29
include/linux/amlogic/media/vout/hdmi_tx/hdmi_rptx.h
Normal file
29
include/linux/amlogic/media/vout/hdmi_tx/hdmi_rptx.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* include/linux/amlogic/media/vout/hdmi_tx/hdmi_rptx.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HDMI_RPTX_H_
|
||||
#define _HDMI_RPTX_H_
|
||||
|
||||
enum rptx_hdcp14_cmd {
|
||||
RPTX_HDCP14_OFF,
|
||||
RPTX_HDCP14_ON,
|
||||
RPTX_HDCP14_GET_AUTHST,
|
||||
};
|
||||
|
||||
extern void direct_hdcptx14_opr(enum rptx_hdcp14_cmd cmd, void *args);
|
||||
|
||||
#endif
|
||||
@@ -65,6 +65,12 @@ struct rx_audiocap {
|
||||
unsigned char cc3;
|
||||
};
|
||||
|
||||
#define MAX_RAW_LEN 64
|
||||
struct raw_block {
|
||||
int len;
|
||||
char raw[MAX_RAW_LEN];
|
||||
};
|
||||
|
||||
enum hd_ctrl {
|
||||
VID_EN, VID_DIS, AUD_EN, AUD_DIS, EDID_EN, EDID_DIS, HDCP_EN, HDCP_DIS,
|
||||
};
|
||||
@@ -145,6 +151,8 @@ struct rx_cap {
|
||||
unsigned char dtd_idx;
|
||||
unsigned char flag_vfpdb;
|
||||
unsigned char number_of_dtd;
|
||||
struct raw_block asd;
|
||||
struct raw_block vsd;
|
||||
/*blk0 check sum*/
|
||||
unsigned char blk0_chksum;
|
||||
};
|
||||
@@ -232,6 +240,48 @@ struct hdmitx_clk_tree_s {
|
||||
struct clk *venci_1_gate;
|
||||
};
|
||||
|
||||
/* 2kB should be enough to record */
|
||||
#define HDCP_LOG_SIZE (1024 * 2)
|
||||
struct hdcplog_buf {
|
||||
int idx;
|
||||
unsigned char buf[HDCP_LOG_SIZE + 64]; /* padding 8 bytes */
|
||||
};
|
||||
|
||||
enum hdcp_ver_e {
|
||||
HDCPVER_NONE = 0,
|
||||
HDCPVER_14,
|
||||
HDCPVER_22,
|
||||
};
|
||||
|
||||
#define 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[MAX_KSV_LISTS * 5];
|
||||
};
|
||||
|
||||
struct hdcprp22_topo {
|
||||
unsigned int depth;
|
||||
unsigned int device_count;
|
||||
unsigned int v1_X_device_down;
|
||||
unsigned int v2_0_repeater_down;
|
||||
unsigned int max_devs_exceeded;
|
||||
unsigned int max_cascade_exceeded;
|
||||
unsigned char id_num;
|
||||
unsigned char id_lists[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;
|
||||
};
|
||||
|
||||
#define EDID_MAX_BLOCK 4
|
||||
#define HDMI_TMP_BUF_SIZE 1024
|
||||
struct hdmitx_dev {
|
||||
@@ -259,7 +309,6 @@ struct hdmitx_dev {
|
||||
struct delayed_work cec_work;
|
||||
#endif
|
||||
struct timer_list hdcp_timer;
|
||||
int hdcp_try_times;
|
||||
int chip_type;
|
||||
int hdmi_init;
|
||||
int hpdmode;
|
||||
@@ -269,7 +318,6 @@ struct hdmitx_dev {
|
||||
int ready; /* 1, hdmi stable output, others are 0 */
|
||||
int hdcp_hpd_stick; /* 1 not init & reset at plugout */
|
||||
int hdcp_tst_sig;
|
||||
bool hdcp22_type;
|
||||
unsigned int div40;
|
||||
unsigned int lstore;
|
||||
struct {
|
||||
@@ -335,6 +383,9 @@ struct hdmitx_dev {
|
||||
/**/
|
||||
unsigned char hpd_event; /* 1, plugin; 2, plugout */
|
||||
unsigned char hpd_state; /* 1, connect; 0, disconnect */
|
||||
unsigned char rhpd_state; /* For repeater use only, no delay */
|
||||
unsigned char hdcp_max_exceed_state;
|
||||
unsigned int hdcp_max_exceed_cnt;
|
||||
unsigned char force_audio_flag;
|
||||
unsigned char mux_hpd_if_pin_high_flag;
|
||||
int auth_process_timer;
|
||||
@@ -352,6 +403,7 @@ struct hdmitx_dev {
|
||||
unsigned int output_blank_flag;
|
||||
unsigned int audio_notify_flag;
|
||||
unsigned int audio_step;
|
||||
bool hdcp22_type;
|
||||
unsigned int repeater_tx;
|
||||
struct hdcprp_topo *topo_info;
|
||||
/* 0.1% clock shift, 1080p60hz->59.94hz */
|
||||
@@ -401,6 +453,7 @@ struct hdmitx_dev {
|
||||
#define HDCP14_OFF 0x2
|
||||
#define HDCP22_ON 0x3
|
||||
#define HDCP22_OFF 0x4
|
||||
#define DDC_IS_HDCP_ON (CMD_DDC_OFFSET + 0x04)
|
||||
#define DDC_HDCP_GET_AKSV (CMD_DDC_OFFSET + 0x05)
|
||||
#define DDC_HDCP_GET_BKSV (CMD_DDC_OFFSET + 0x06)
|
||||
#define DDC_HDCP_GET_AUTH (CMD_DDC_OFFSET + 0x07)
|
||||
@@ -408,6 +461,7 @@ struct hdmitx_dev {
|
||||
#define PIN_MUX 0x1
|
||||
#define PIN_UNMUX 0x2
|
||||
#define DDC_EDID_READ_DATA (CMD_DDC_OFFSET + 0x0a)
|
||||
#define DDC_IS_EDID_DATA_READY (CMD_DDC_OFFSET + 0x0b)
|
||||
#define DDC_EDID_GET_DATA (CMD_DDC_OFFSET + 0x0c)
|
||||
#define DDC_EDID_CLEAR_RAM (CMD_DDC_OFFSET + 0x0d)
|
||||
#define DDC_HDCP_MUX_INIT (CMD_DDC_OFFSET + 0x0e)
|
||||
@@ -417,6 +471,7 @@ struct hdmitx_dev {
|
||||
#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)
|
||||
#define DDC_HDCP14_SAVE_OBS (CMD_DDC_OFFSET + 0x40)
|
||||
|
||||
/***********************************************************************
|
||||
* CONFIG CONTROL //CntlConfig
|
||||
@@ -487,6 +542,7 @@ struct hdmitx_dev {
|
||||
#define MISC_HDCP_CLKDIS (CMD_MISC_OFFSET + 0x0e)
|
||||
#define MISC_TMDS_RXSENSE (CMD_MISC_OFFSET + 0x0f)
|
||||
#define MISC_I2C_REACTIVE (CMD_MISC_OFFSET + 0x10)
|
||||
#define MISC_READ_AVMUTE_OP (CMD_MISC_OFFSET + 0x11)
|
||||
|
||||
/***********************************************************************
|
||||
* Get State //GetState
|
||||
@@ -574,16 +630,6 @@ void __attribute__((weak))rx_set_receiver_edid(unsigned char *data, int len)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* ver = 22 means downstream supports HDCP22
|
||||
* ver = 14 means support HDCP14
|
||||
* ver = 0 means support NO HDCP
|
||||
*/
|
||||
extern void rx_repeat_hdcp_ver(unsigned int ver);
|
||||
void __attribute__((weak))rx_repeat_hdcp_ver(unsigned int ver)
|
||||
{
|
||||
}
|
||||
|
||||
extern void rx_set_receive_hdcp(unsigned char *data, int len, int depth,
|
||||
bool max_cascade, bool max_devs);
|
||||
void __attribute__((weak))rx_set_receive_hdcp(unsigned char *data, int len,
|
||||
|
||||
Reference in New Issue
Block a user