msm: mdss: hdmi: cleanup ddc usage
Check for all possible DDC errors and clear the corresponding acknowledge bit. Properly enable or disable the DDC interrupts based on the requirements. Optimize DDC data structure by removing unnecessary variables and keeping different DDC related data under common structure. Move all DDC implementations to one place. Change-Id: If63479d5bc263db63e62d1846ab13a2659a83a68 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
This commit is contained in:
parent
126b239dd6
commit
a715804225
6 changed files with 438 additions and 345 deletions
|
@ -333,6 +333,7 @@ struct hdcp_lib_handle {
|
||||||
uint32_t tz_ctxhandle;
|
uint32_t tz_ctxhandle;
|
||||||
uint32_t hdcp_timeout;
|
uint32_t hdcp_timeout;
|
||||||
bool no_stored_km_flag;
|
bool no_stored_km_flag;
|
||||||
|
bool feature_supported;
|
||||||
void *client_ctx;
|
void *client_ctx;
|
||||||
struct hdcp_client_ops *client_ops;
|
struct hdcp_client_ops *client_ops;
|
||||||
struct mutex hdcp_lock;
|
struct mutex hdcp_lock;
|
||||||
|
@ -745,9 +746,15 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handle->feature_supported) {
|
||||||
|
supported = true;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
rc = hdcp_lib_library_load(handle);
|
rc = hdcp_lib_library_load(handle);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
pr_debug("HDCP2p2 supported\n");
|
pr_debug("HDCP2p2 supported\n");
|
||||||
|
handle->feature_supported = true;
|
||||||
hdcp_lib_library_unload(handle);
|
hdcp_lib_library_unload(handle);
|
||||||
supported = true;
|
supported = true;
|
||||||
}
|
}
|
||||||
|
@ -769,7 +776,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
||||||
|
|
||||||
handle->wakeup_cmd = data->cmd;
|
handle->wakeup_cmd = data->cmd;
|
||||||
|
|
||||||
pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
|
pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
|
||||||
|
|
||||||
if (data->recvd_msg_len) {
|
if (data->recvd_msg_len) {
|
||||||
handle->last_msg_recvd_len = data->recvd_msg_len;
|
handle->last_msg_recvd_len = data->recvd_msg_len;
|
||||||
|
|
|
@ -366,7 +366,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "Bcaps";
|
ddc_data.what = "Bcaps";
|
||||||
ddc_data.no_align = true;
|
ddc_data.no_align = true;
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
|
DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
@ -529,7 +532,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.data_buf = an;
|
ddc_data.data_buf = an;
|
||||||
ddc_data.data_len = 8;
|
ddc_data.data_len = 8;
|
||||||
ddc_data.what = "An";
|
ddc_data.what = "An";
|
||||||
rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME);
|
DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -542,7 +547,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.data_buf = aksv;
|
ddc_data.data_buf = aksv;
|
||||||
ddc_data.data_len = 5;
|
ddc_data.data_len = 5;
|
||||||
ddc_data.what = "Aksv";
|
ddc_data.what = "Aksv";
|
||||||
rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: AKSV write failed\n", __func__,
|
DEV_ERR("%s: %s: AKSV write failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
@ -561,7 +568,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "Bksv";
|
ddc_data.what = "Bksv";
|
||||||
ddc_data.no_align = true;
|
ddc_data.no_align = true;
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: BKSV read failed\n", __func__,
|
DEV_ERR("%s: %s: BKSV read failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
@ -633,7 +643,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "R0'";
|
ddc_data.what = "R0'";
|
||||||
ddc_data.no_align = true;
|
ddc_data.no_align = true;
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME);
|
DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -684,7 +697,8 @@ do { \
|
||||||
ddc_data.offset = (off); \
|
ddc_data.offset = (off); \
|
||||||
memset(what, 0, sizeof(what)); \
|
memset(what, 0, sizeof(what)); \
|
||||||
snprintf(what, sizeof(what), (name)); \
|
snprintf(what, sizeof(what), (name)); \
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); \
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; \
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); \
|
||||||
if (rc) { \
|
if (rc) { \
|
||||||
DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \
|
DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \
|
||||||
what); \
|
what); \
|
||||||
|
@ -868,7 +882,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "Bcaps";
|
ddc_data.what = "Bcaps";
|
||||||
ddc_data.no_align = false;
|
ddc_data.no_align = false;
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
|
DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
@ -887,7 +904,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "Bstatuss";
|
ddc_data.what = "Bstatuss";
|
||||||
ddc_data.no_align = false;
|
ddc_data.no_align = false;
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: BSTATUS read failed\n", __func__,
|
DEV_ERR("%s: %s: BSTATUS read failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
@ -979,9 +999,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
|
||||||
ddc_data.retry = 5;
|
ddc_data.retry = 5;
|
||||||
ddc_data.what = "KSV FIFO";
|
ddc_data.what = "KSV FIFO";
|
||||||
ddc_data.no_align = true;
|
ddc_data.no_align = true;
|
||||||
|
|
||||||
|
hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
do {
|
do {
|
||||||
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data);
|
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__,
|
DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__,
|
||||||
HDCP_STATE_NAME);
|
HDCP_STATE_NAME);
|
||||||
|
|
|
@ -86,7 +86,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
|
||||||
|
|
||||||
mutex_lock(&ctrl->wakeup_mutex);
|
mutex_lock(&ctrl->wakeup_mutex);
|
||||||
|
|
||||||
pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
|
pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
|
||||||
|
|
||||||
ctrl->wakeup_cmd = data->cmd;
|
ctrl->wakeup_cmd = data->cmd;
|
||||||
ctrl->timeout = data->timeout;
|
ctrl->timeout = data->timeout;
|
||||||
|
@ -310,6 +310,10 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
struct hdmi_tx_ddc_data ddc_data;
|
struct hdmi_tx_ddc_data ddc_data;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
|
||||||
|
pr_err("hdcp is off\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
memset(&ddc_data, 0, sizeof(ddc_data));
|
memset(&ddc_data, 0, sizeof(ddc_data));
|
||||||
ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR;
|
ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR;
|
||||||
ddc_data.offset = HDCP_SINK_DDC_HDCP2_READ_MESSAGE;
|
ddc_data.offset = HDCP_SINK_DDC_HDCP2_READ_MESSAGE;
|
||||||
|
@ -320,7 +324,9 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
ddc_data.hard_timeout = timeout;
|
ddc_data.hard_timeout = timeout;
|
||||||
ddc_data.what = "HDCP2ReadMessage";
|
ddc_data.what = "HDCP2ReadMessage";
|
||||||
|
|
||||||
rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data);
|
ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("Cannot read HDCP message register\n");
|
pr_err("Cannot read HDCP message register\n");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -340,24 +346,14 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
ddc_data.retry = 1;
|
ddc_data.retry = 1;
|
||||||
ddc_data.what = "HDCP2WriteMessage";
|
ddc_data.what = "HDCP2WriteMessage";
|
||||||
|
|
||||||
rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl, &ddc_data);
|
ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("Cannot write HDCP message register");
|
pr_err("Cannot write HDCP message register");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_ddc_abort(struct hdmi_hdcp2p2_ctrl *ctrl)
|
|
||||||
{
|
|
||||||
/* Abort any ongoing DDC transactions */
|
|
||||||
struct hdmi_tx_ddc_data ddc_data;
|
|
||||||
|
|
||||||
memset(&ddc_data, 0, sizeof(ddc_data));
|
|
||||||
ddc_data.retry = 1;
|
|
||||||
ddc_data.what = "HDCPAbortTransaction";
|
|
||||||
hdmi_ddc_abort_transaction(ctrl->init_data.ddc_ctrl,
|
|
||||||
&ddc_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl,
|
static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
u8 *hdcp2version)
|
u8 *hdcp2version)
|
||||||
{
|
{
|
||||||
|
@ -373,7 +369,9 @@ static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
ddc_data.retry = 1;
|
ddc_data.retry = 1;
|
||||||
ddc_data.what = "HDCP2Version";
|
ddc_data.what = "HDCP2Version";
|
||||||
|
|
||||||
rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data);
|
ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Cannot read HDCP2Version register");
|
pr_err("Cannot read HDCP2Version register");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -424,44 +422,6 @@ static struct attribute_group hdmi_hdcp2p2_fs_attr_group = {
|
||||||
.attrs = hdmi_hdcp2p2_fs_attrs,
|
.attrs = hdmi_hdcp2p2_fs_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hdmi_hdcp2p2_isr(void *input)
|
|
||||||
{
|
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl = input;
|
|
||||||
u32 reg_val;
|
|
||||||
|
|
||||||
if (!ctrl) {
|
|
||||||
pr_err("invalid input\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("INT_CTRL0 is 0x%x\n",
|
|
||||||
DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0));
|
|
||||||
reg_val = DSS_REG_R(ctrl->init_data.core_io,
|
|
||||||
HDMI_HDCP_INT_CTRL2);
|
|
||||||
if (reg_val & BIT(0)) {
|
|
||||||
pr_debug("HDCP 2.2 Encryption is enabled\n");
|
|
||||||
reg_val |= BIT(1);
|
|
||||||
DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2,
|
|
||||||
reg_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_val = DSS_REG_R(ctrl->init_data.core_io,
|
|
||||||
HDMI_DDC_INT_CTRL0);
|
|
||||||
if (reg_val & HDCP2P2_RXSTATUS_MESSAGE_SIZE_MASK) {
|
|
||||||
DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0,
|
|
||||||
reg_val & ~(BIT(31)));
|
|
||||||
if (!completion_done(&ctrl->rxstatus_completion))
|
|
||||||
complete_all(&ctrl->rxstatus_completion);
|
|
||||||
} else if (reg_val & BIT(8)) {
|
|
||||||
DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0,
|
|
||||||
reg_val & ~(BIT(9) | BIT(10)));
|
|
||||||
if (!completion_done(&ctrl->rxstatus_completion))
|
|
||||||
complete_all(&ctrl->rxstatus_completion);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hdmi_hdcp2p2_feature_supported(void *input)
|
static bool hdmi_hdcp2p2_feature_supported(void *input)
|
||||||
{
|
{
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl = input;
|
struct hdmi_hdcp2p2_ctrl *ctrl = input;
|
||||||
|
@ -525,12 +485,12 @@ exit:
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
|
static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
|
||||||
{
|
{
|
||||||
int rc = 0, msg_size = 0, retries = 5;
|
int rc = 0;
|
||||||
u64 mult;
|
u64 mult;
|
||||||
char *recvd_msg_buf = NULL;
|
char *recvd_msg_buf = NULL;
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
|
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
|
||||||
struct hdmi_hdcp2p2_ctrl, recv_msg);
|
struct hdmi_hdcp2p2_ctrl, recv_msg);
|
||||||
struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data;
|
struct hdmi_tx_hdcp2p2_ddc_data *ddc_data;
|
||||||
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
|
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
|
||||||
struct msm_hdmi_mode_timing_info *timing;
|
struct msm_hdmi_mode_timing_info *timing;
|
||||||
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
|
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
|
||||||
|
@ -550,59 +510,47 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
ddc_ctrl = ctrl->init_data.ddc_ctrl;
|
ddc_ctrl = ctrl->init_data.ddc_ctrl;
|
||||||
|
if (!ddc_ctrl)
|
||||||
do {
|
goto exit;
|
||||||
timing = ctrl->init_data.timing;
|
|
||||||
|
|
||||||
mult = hdmi_tx_get_v_total(timing) / 20;
|
|
||||||
memset(&hdcp2p2_ddc_data, 0, sizeof(hdcp2p2_ddc_data));
|
|
||||||
hdcp2p2_ddc_data.ddc_data.what = "HDCP2RxStatus";
|
|
||||||
hdcp2p2_ddc_data.ddc_data.data_buf = (u8 *)&msg_size;
|
|
||||||
hdcp2p2_ddc_data.ddc_data.data_len = sizeof(msg_size);
|
|
||||||
hdcp2p2_ddc_data.rxstatus_field = RXSTATUS_MESSAGE_SIZE;
|
|
||||||
hdcp2p2_ddc_data.timer_delay_lines = (u32)mult;
|
|
||||||
hdcp2p2_ddc_data.irq_wait_count = 100;
|
|
||||||
hdcp2p2_ddc_data.poll_sink = false;
|
|
||||||
|
|
||||||
hdmi_ddc_config(ddc_ctrl);
|
hdmi_ddc_config(ddc_ctrl);
|
||||||
pr_debug("Reading rxstatus, timer delay %u\n", (u32)mult);
|
|
||||||
|
|
||||||
rc = hdmi_hdcp2p2_ddc_read_rxstatus(
|
ddc_data = &ddc_ctrl->hdcp2p2_ddc_data;
|
||||||
ddc_ctrl, &hdcp2p2_ddc_data,
|
|
||||||
&ctrl->rxstatus_completion);
|
memset(ddc_data, 0, sizeof(*ddc_data));
|
||||||
|
|
||||||
|
timing = ctrl->init_data.timing;
|
||||||
|
mult = hdmi_tx_get_v_total(timing) / 20;
|
||||||
|
ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE;
|
||||||
|
ddc_data->timer_delay_lines = (u32)mult;
|
||||||
|
ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
||||||
|
|
||||||
|
rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Could not read rxstatus from sink\n");
|
pr_err("error reading rxstatus %d\n", rc);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!msg_size) {
|
|
||||||
pr_err("recvd invalid message size\n");
|
|
||||||
rc = -EINVAL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} while (rc && (retries-- > 0));
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
pr_err("error reading valid rxstatus data\n");
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
recvd_msg_buf = kzalloc(msg_size, GFP_KERNEL);
|
if (!ddc_data->message_size) {
|
||||||
|
pr_err("recvd invalid message size\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("rxstatus msg size %d\n", ddc_data->message_size);
|
||||||
|
|
||||||
|
recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL);
|
||||||
if (!recvd_msg_buf)
|
if (!recvd_msg_buf)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf,
|
rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf,
|
||||||
msg_size, ctrl->timeout);
|
ddc_data->message_size, ctrl->timeout);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("ERROR reading message from sink\n");
|
pr_err("error reading message %d\n", rc);
|
||||||
|
|
||||||
hdmi_hdcp2p2_ddc_abort(ctrl);
|
|
||||||
hdmi_hdcp2p2_ddc_reset(ddc_ctrl);
|
|
||||||
hdmi_hdcp2p2_ddc_disable(ddc_ctrl);
|
|
||||||
|
|
||||||
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
|
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
|
||||||
cdata.recvd_msg_buf = recvd_msg_buf;
|
cdata.recvd_msg_buf = recvd_msg_buf;
|
||||||
cdata.recvd_msg_len = msg_size;
|
cdata.recvd_msg_len = ddc_data->message_size;
|
||||||
exit:
|
exit:
|
||||||
if (rc == -ETIMEDOUT)
|
if (rc == -ETIMEDOUT)
|
||||||
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
|
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
|
||||||
|
@ -707,7 +655,6 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl;
|
struct hdmi_hdcp2p2_ctrl *ctrl;
|
||||||
int rc;
|
int rc;
|
||||||
static struct hdmi_hdcp_ops ops = {
|
static struct hdmi_hdcp_ops ops = {
|
||||||
.hdmi_hdcp_isr = hdmi_hdcp2p2_isr,
|
|
||||||
.hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate,
|
.hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate,
|
||||||
.hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate,
|
.hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate,
|
||||||
.feature_supported = hdmi_hdcp2p2_feature_supported,
|
.feature_supported = hdmi_hdcp2p2_feature_supported,
|
||||||
|
|
|
@ -1291,11 +1291,13 @@ static u32 hdmi_tx_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
||||||
ddc_data.what = "EDID";
|
ddc_data.what = "EDID";
|
||||||
ddc_data.no_align = false;
|
ddc_data.no_align = false;
|
||||||
|
|
||||||
|
ddc_ctrl->ddc_data = ddc_data;
|
||||||
|
|
||||||
/* Read EDID twice with 32bit alighnment too */
|
/* Read EDID twice with 32bit alighnment too */
|
||||||
if (block < 2)
|
if (block < 2)
|
||||||
status = hdmi_ddc_read(ddc_ctrl, &ddc_data);
|
status = hdmi_ddc_read(ddc_ctrl);
|
||||||
else
|
else
|
||||||
status = hdmi_ddc_read_seg(ddc_ctrl, &ddc_data);
|
status = hdmi_ddc_read_seg(ddc_ctrl);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
|
@ -3777,10 +3779,14 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data)
|
||||||
if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]))
|
if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]))
|
||||||
DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);
|
DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);
|
||||||
|
|
||||||
if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data)
|
if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) {
|
||||||
|
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) {
|
||||||
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr(
|
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr(
|
||||||
hdmi_ctrl->hdcp_feature_data))
|
hdmi_ctrl->hdcp_feature_data))
|
||||||
DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__);
|
DEV_ERR("%s: hdmi_hdcp_isr failed\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
end:
|
end:
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
} /* hdmi_tx_isr */
|
} /* hdmi_tx_isr */
|
||||||
|
@ -3865,6 +3871,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||||
|
|
||||||
hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO];
|
hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO];
|
||||||
init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
|
init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
|
||||||
|
init_completion(&hdmi_ctrl->ddc_ctrl.rxstatus_completion);
|
||||||
|
|
||||||
hdmi_ctrl->panel_power_on = false;
|
hdmi_ctrl->panel_power_on = false;
|
||||||
hdmi_ctrl->panel_suspend = false;
|
hdmi_ctrl->panel_suspend = false;
|
||||||
|
@ -4080,6 +4087,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
|
||||||
hdmi_ctrl->hdcp_ops->hdmi_hdcp_off(
|
hdmi_ctrl->hdcp_ops->hdmi_hdcp_off(
|
||||||
hdmi_ctrl->hdcp_feature_data);
|
hdmi_ctrl->hdcp_feature_data);
|
||||||
|
|
||||||
|
hdmi_ctrl->hdcp_ops = NULL;
|
||||||
|
|
||||||
rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM,
|
rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM,
|
||||||
false);
|
false);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||||
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include "mdss_hdmi_util.h"
|
#include "mdss_hdmi_util.h"
|
||||||
|
@ -119,7 +121,7 @@ bool hdmi_is_valid_resv_timing(int mode)
|
||||||
struct msm_hdmi_mode_timing_info *info;
|
struct msm_hdmi_mode_timing_info *info;
|
||||||
|
|
||||||
if (mode < HDMI_VFRMT_RESERVE1 || mode > RESERVE_VFRMT_END) {
|
if (mode < HDMI_VFRMT_RESERVE1 || mode > RESERVE_VFRMT_END) {
|
||||||
DEV_ERR("%s: invalid mode %d\n", __func__, mode);
|
pr_err("invalid mode %d\n", mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +380,7 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in,
|
||||||
u32 ret;
|
u32 ret;
|
||||||
|
|
||||||
if (!timing_in) {
|
if (!timing_in) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,12 +431,12 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vic < 0) {
|
if (vic < 0) {
|
||||||
DEV_ERR("%s: timing is not supported h=%d v=%d\n",
|
pr_err("timing is not supported h=%d v=%d\n",
|
||||||
__func__, timing_in->active_h, timing_in->active_v);
|
timing_in->active_h, timing_in->active_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
DEV_DBG("%s: vic = %d timing = %s\n", __func__, vic,
|
pr_debug("vic = %d timing = %s\n", vic,
|
||||||
msm_hdmi_mode_2string((u32)vic));
|
msm_hdmi_mode_2string((u32)vic));
|
||||||
|
|
||||||
return vic;
|
return vic;
|
||||||
|
@ -481,19 +483,18 @@ ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size)
|
||||||
return len;
|
return len;
|
||||||
} /* hdmi_get_video_3d_fmt_2string */
|
} /* hdmi_get_video_3d_fmt_2string */
|
||||||
|
|
||||||
static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data,
|
static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data)
|
||||||
const char *caller)
|
|
||||||
{
|
{
|
||||||
if (!ddc_data) {
|
if (!ddc_data) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s: buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n",
|
pr_debug("what: %s, buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n",
|
||||||
caller, ddc_data->data_buf, ddc_data->data_len,
|
ddc_data->what, ddc_data->data_buf, ddc_data->data_len,
|
||||||
ddc_data->dev_addr, ddc_data->no_align);
|
ddc_data->dev_addr, ddc_data->no_align);
|
||||||
DEV_DBG("%s: offset=0x%x, req_len=0x%x, retry=%d, what=%s\n",
|
pr_debug("what: %s, offset=0x%x, req_len=0x%x, retry=%d, what=%s\n",
|
||||||
caller, ddc_data->offset, ddc_data->request_len,
|
ddc_data->what, ddc_data->offset, ddc_data->request_len,
|
||||||
ddc_data->retry, ddc_data->what);
|
ddc_data->retry, ddc_data->what);
|
||||||
} /* hdmi_ddc_print_data */
|
} /* hdmi_ddc_print_data */
|
||||||
|
|
||||||
|
@ -503,7 +504,7 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
||||||
u32 reg_val, time_out_count;
|
u32 reg_val, time_out_count;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,32 +519,34 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
||||||
} while ((reg_val & BIT(0)) && time_out_count);
|
} while ((reg_val & BIT(0)) && time_out_count);
|
||||||
|
|
||||||
if (!time_out_count) {
|
if (!time_out_count) {
|
||||||
DEV_ERR("%s[%s]: timedout\n", __func__, what);
|
pr_err("%s: timedout\n", what);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} /*hdmi_ddc_clear_irq */
|
} /*hdmi_ddc_clear_irq */
|
||||||
|
|
||||||
static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_ddc_data *ddc_data)
|
|
||||||
{
|
{
|
||||||
u32 reg_val, ndx, time_out_count, wait_time;
|
u32 reg_val, ndx, time_out_count, wait_time;
|
||||||
|
struct hdmi_tx_ddc_data *ddc_data;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int log_retry_fail;
|
int log_retry_fail;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddc_data = &ddc_ctrl->ddc_data;
|
||||||
|
|
||||||
if (!ddc_data->data_buf) {
|
if (!ddc_data->data_buf) {
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
|
pr_err("%s: invalid buf\n", ddc_data->what);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdmi_ddc_print_data(ddc_data, __func__);
|
hdmi_ddc_print_data(ddc_data);
|
||||||
|
|
||||||
log_retry_fail = ddc_data->retry != 1;
|
log_retry_fail = ddc_data->retry != 1;
|
||||||
again:
|
again:
|
||||||
|
@ -624,8 +627,7 @@ again:
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
|
||||||
|
|
||||||
if (ddc_data->hard_timeout) {
|
if (ddc_data->hard_timeout) {
|
||||||
DEV_DBG("%s: using hard_timeout %dms\n", __func__,
|
pr_debug("using hard_timeout %dms\n", ddc_data->hard_timeout);
|
||||||
ddc_data->hard_timeout);
|
|
||||||
wait_time = msecs_to_jiffies(ddc_data->hard_timeout);
|
wait_time = msecs_to_jiffies(ddc_data->hard_timeout);
|
||||||
} else {
|
} else {
|
||||||
wait_time = HZ/2;
|
wait_time = HZ/2;
|
||||||
|
@ -633,20 +635,18 @@ again:
|
||||||
|
|
||||||
time_out_count = wait_for_completion_timeout(
|
time_out_count = wait_for_completion_timeout(
|
||||||
&ddc_ctrl->ddc_sw_done, wait_time);
|
&ddc_ctrl->ddc_sw_done, wait_time);
|
||||||
DEV_DBG("ddc read done at %dms\n", jiffies_to_msecs(jiffies));
|
pr_debug("ddc read done at %dms\n", jiffies_to_msecs(jiffies));
|
||||||
|
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
|
||||||
if (!time_out_count) {
|
if (!time_out_count) {
|
||||||
if (ddc_data->retry-- > 0) {
|
if (ddc_data->retry-- > 0) {
|
||||||
DEV_INFO("%s: failed timout, retry=%d\n", __func__,
|
pr_debug("failed timout, retry=%d\n", ddc_data->retry);
|
||||||
ddc_data->retry);
|
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -ETIMEDOUT;
|
status = -ETIMEDOUT;
|
||||||
DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
|
pr_err("timedout(7), Int Ctrl=%08x\n",
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
||||||
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
|
pr_err("DDC SW Status=%08x, HW Status=%08x\n",
|
||||||
__func__,
|
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -666,20 +666,20 @@ again:
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
||||||
|
|
||||||
if (ddc_data->retry-- > 0) {
|
if (ddc_data->retry-- > 0) {
|
||||||
DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
|
pr_debug("%s: failed NACK=0x%08x, retry=%d\n",
|
||||||
__func__, ddc_data->what, reg_val,
|
ddc_data->what, reg_val,
|
||||||
ddc_data->retry);
|
ddc_data->retry);
|
||||||
DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
|
pr_debug("daddr=0x%02x,off=0x%02x,len=%d\n",
|
||||||
__func__, ddc_data->dev_addr,
|
ddc_data->dev_addr,
|
||||||
ddc_data->offset, ddc_data->data_len);
|
ddc_data->offset, ddc_data->data_len);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
if (log_retry_fail) {
|
if (log_retry_fail) {
|
||||||
DEV_ERR("%s(%s): failed NACK=0x%08x\n",
|
pr_err("%s: failed NACK=0x%08x\n",
|
||||||
__func__, ddc_data->what, reg_val);
|
ddc_data->what, reg_val);
|
||||||
DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
|
pr_err("daddr=0x%02x,off=0x%02x,len=%d\n",
|
||||||
__func__, ddc_data->dev_addr,
|
ddc_data->dev_addr,
|
||||||
ddc_data->offset, ddc_data->data_len);
|
ddc_data->offset, ddc_data->data_len);
|
||||||
}
|
}
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -704,7 +704,7 @@ again:
|
||||||
ddc_data->data_buf[ndx] = (u8)((reg_val & 0x0000FF00) >> 8);
|
ddc_data->data_buf[ndx] = (u8)((reg_val & 0x0000FF00) >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
|
pr_debug("%s: success\n", ddc_data->what);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
return status;
|
return status;
|
||||||
|
@ -713,7 +713,7 @@ error:
|
||||||
void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
{
|
{
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,6 +730,139 @@ void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (19 << 0));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (19 << 0));
|
||||||
} /* hdmi_ddc_config */
|
} /* hdmi_ddc_config */
|
||||||
|
|
||||||
|
static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
|
{
|
||||||
|
struct dss_io_data *io = NULL;
|
||||||
|
struct hdmi_tx_hdcp2p2_ddc_data *data;
|
||||||
|
u32 intr0, intr2;
|
||||||
|
|
||||||
|
if (!ddc_ctrl) {
|
||||||
|
pr_err("invalid input\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
io = ddc_ctrl->io;
|
||||||
|
if (!io) {
|
||||||
|
pr_err("invalid io data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = &ddc_ctrl->hdcp2p2_ddc_data;
|
||||||
|
|
||||||
|
intr2 = DSS_REG_R(io, HDMI_HDCP_INT_CTRL2);
|
||||||
|
intr0 = DSS_REG_R(io, HDMI_DDC_INT_CTRL0);
|
||||||
|
|
||||||
|
pr_debug("INT_CTRL0 :0x%x\n", intr0);
|
||||||
|
pr_debug("INT_CTRL2 :0x%x\n", intr2);
|
||||||
|
|
||||||
|
/* check for encryption ready interrupt */
|
||||||
|
if (intr2 & BIT(2)) {
|
||||||
|
/* check if encryption is enabled */
|
||||||
|
if (intr2 & BIT(0)) {
|
||||||
|
/*
|
||||||
|
* ack encryption ready interrupt.
|
||||||
|
* disable encryption ready interrupt.
|
||||||
|
* enable encryption not ready interrupt.
|
||||||
|
*/
|
||||||
|
intr2 &= ~BIT(2);
|
||||||
|
intr2 |= BIT(1) | BIT(6);
|
||||||
|
|
||||||
|
pr_debug("HDCP 2.2 Encryption enabled\n");
|
||||||
|
data->encryption_ready = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for encryption not ready interrupt */
|
||||||
|
if (intr2 & BIT(6)) {
|
||||||
|
/* check if encryption is disabled */
|
||||||
|
if (intr2 & BIT(4)) {
|
||||||
|
/*
|
||||||
|
* ack encryption not ready interrupt.
|
||||||
|
* disable encryption not ready interrupt.
|
||||||
|
* enable encryption ready interrupt.
|
||||||
|
*/
|
||||||
|
intr2 |= BIT(5) | BIT(2);
|
||||||
|
intr2 &= ~BIT(6);
|
||||||
|
|
||||||
|
pr_debug("HDCP 2.2 Encryption disabled\n");
|
||||||
|
data->encryption_ready = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_HDCP_INT_CTRL2, intr2);
|
||||||
|
|
||||||
|
/* check for message size interrupt */
|
||||||
|
if (intr0 & BIT(31)) {
|
||||||
|
/* ack and disable message size interrupt */
|
||||||
|
intr0 |= BIT(30);
|
||||||
|
intr0 &= ~BIT(31);
|
||||||
|
|
||||||
|
/* get the message size bits 29:20 */
|
||||||
|
data->message_size = (intr0 & (0x3FF << 20)) >> 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for ready/not ready interrupt */
|
||||||
|
if (intr0 & (BIT(18) | BIT(19))) {
|
||||||
|
/* check and disable ready interrupt */
|
||||||
|
if (intr0 & BIT(16)) {
|
||||||
|
intr0 &= ~BIT(18);
|
||||||
|
data->ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check and disable not ready interrupt */
|
||||||
|
if (intr0 & BIT(15)) {
|
||||||
|
intr0 &= ~BIT(19);
|
||||||
|
data->ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ack ready/not ready interrupt */
|
||||||
|
intr0 |= BIT(17);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for reauth req interrupt */
|
||||||
|
if (intr0 & BIT(14)) {
|
||||||
|
/* ack and disable reauth req interrupt */
|
||||||
|
intr0 |= BIT(13);
|
||||||
|
intr0 &= ~BIT(14);
|
||||||
|
|
||||||
|
data->reauth_req = (intr0 & BIT(12)) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for ddc fail interrupt */
|
||||||
|
if (intr0 & BIT(10)) {
|
||||||
|
/* ack and disable ddc fail interrupt */
|
||||||
|
intr0 |= BIT(9);
|
||||||
|
intr0 &= ~BIT(10);
|
||||||
|
|
||||||
|
data->ddc_max_retries_fail = (intr0 & BIT(8)) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for ddc done interrupt */
|
||||||
|
if (intr0 & BIT(6)) {
|
||||||
|
/* ack and disable ddc done interrupt */
|
||||||
|
intr0 |= BIT(5);
|
||||||
|
intr0 &= ~BIT(6);
|
||||||
|
|
||||||
|
data->ddc_done = (intr0 & BIT(4)) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for ddc read req interrupt */
|
||||||
|
if (intr0 & BIT(2)) {
|
||||||
|
/* ack and disable read req interrupt */
|
||||||
|
intr0 |= BIT(1);
|
||||||
|
intr0 &= ~BIT(2);
|
||||||
|
|
||||||
|
data->ddc_read_req = (intr0 & BIT(0)) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL0, intr0);
|
||||||
|
|
||||||
|
if (!completion_done(&ddc_ctrl->rxstatus_completion))
|
||||||
|
complete_all(&ddc_ctrl->rxstatus_completion);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
||||||
{
|
{
|
||||||
u32 ddc_int_ctrl;
|
u32 ddc_int_ctrl;
|
||||||
|
@ -737,7 +870,7 @@ int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
||||||
bool scrambler_timer_off = false;
|
bool scrambler_timer_off = false;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,15 +882,14 @@ int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
||||||
complete(&ddc_ctrl->ddc_sw_done);
|
complete(&ddc_ctrl->ddc_sw_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s: ddc_int_ctrl=%04x\n", __func__, ddc_int_ctrl);
|
pr_debug("ddc_int_ctrl=%04x\n", ddc_int_ctrl);
|
||||||
if (version < HDMI_TX_SCRAMBLER_MIN_TX_VERSION)
|
if (version < HDMI_TX_SCRAMBLER_MIN_TX_VERSION)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
ddc_timer_int = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2);
|
ddc_timer_int = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2);
|
||||||
if (ddc_timer_int & BIT(12)) {
|
if (ddc_timer_int & BIT(12)) {
|
||||||
/* DDC_INT_CTRL2.SCRAMBLER_STATUS_NOT is set */
|
/* DDC_INT_CTRL2.SCRAMBLER_STATUS_NOT is set */
|
||||||
DEV_ERR("%s: Sink cannot descramble the signal\n",
|
pr_err("Sink cannot descramble the signal\n");
|
||||||
__func__);
|
|
||||||
/* Clear interrupt */
|
/* Clear interrupt */
|
||||||
ddc_timer_int |= BIT(14);
|
ddc_timer_int |= BIT(14);
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2,
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2,
|
||||||
|
@ -771,9 +903,7 @@ int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
||||||
* DDC_INT_CTRL5.SCRAMBLER_STATUS_DDC_REQ_TIMEOUT
|
* DDC_INT_CTRL5.SCRAMBLER_STATUS_DDC_REQ_TIMEOUT
|
||||||
* is set
|
* is set
|
||||||
*/
|
*/
|
||||||
DEV_ERR(
|
pr_err("DDC timeout while reading SCRAMBLER STATUS\n");
|
||||||
"%s: DDC timeout while reading SCRAMBLER STATUS\n",
|
|
||||||
__func__);
|
|
||||||
ddc_timer_int |= BIT(13);
|
ddc_timer_int |= BIT(13);
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL5,
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL5,
|
||||||
ddc_timer_int);
|
ddc_timer_int);
|
||||||
|
@ -788,49 +918,54 @@ int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 version)
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_HW_DDC_CTRL, regval);
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_HW_DDC_CTRL, regval);
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
|
hdmi_ddc_hdcp2p2_isr(ddc_ctrl);
|
||||||
return 0;
|
return 0;
|
||||||
} /* hdmi_ddc_isr */
|
} /* hdmi_ddc_isr */
|
||||||
|
|
||||||
int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_ddc_data *ddc_data)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
struct hdmi_tx_ddc_data *ddc_data;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_data) {
|
if (!ddc_ctrl) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid ddc ctrl\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
|
ddc_data = &ddc_ctrl->ddc_data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read_retry(ddc_ctrl);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (ddc_data->no_align) {
|
if (ddc_data->no_align) {
|
||||||
rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
|
rc = hdmi_ddc_read_retry(ddc_ctrl);
|
||||||
} else {
|
} else {
|
||||||
ddc_data->request_len = 32 * ((ddc_data->data_len + 31) / 32);
|
ddc_data->request_len = 32 * ((ddc_data->data_len + 31) / 32);
|
||||||
rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
|
rc = hdmi_ddc_read_retry(ddc_ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
} /* hdmi_ddc_read */
|
} /* hdmi_ddc_read */
|
||||||
|
|
||||||
int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_ddc_data *ddc_data)
|
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
u32 reg_val, ndx, time_out_count;
|
u32 reg_val, ndx, time_out_count;
|
||||||
int log_retry_fail;
|
int log_retry_fail;
|
||||||
int seg_addr = 0x60, seg_num = 0x01;
|
int seg_addr = 0x60, seg_num = 0x01;
|
||||||
|
struct hdmi_tx_ddc_data *ddc_data;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddc_data = &ddc_ctrl->ddc_data;
|
||||||
|
|
||||||
if (!ddc_data->data_buf) {
|
if (!ddc_data->data_buf) {
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
|
pr_err("%s: invalid buf\n", ddc_data->what);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,15 +1065,13 @@ again:
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
|
||||||
if (!time_out_count) {
|
if (!time_out_count) {
|
||||||
if (ddc_data->retry-- > 0) {
|
if (ddc_data->retry-- > 0) {
|
||||||
DEV_INFO("%s: failed timout, retry=%d\n", __func__,
|
pr_debug("failed timout, retry=%d\n", ddc_data->retry);
|
||||||
ddc_data->retry);
|
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -ETIMEDOUT;
|
status = -ETIMEDOUT;
|
||||||
DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
|
pr_err("timedout(7), Int Ctrl=%08x\n",
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
||||||
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
|
pr_err("DDC SW Status=%08x, HW Status=%08x\n",
|
||||||
__func__,
|
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -956,20 +1089,20 @@ again:
|
||||||
/* SOFT_RESET */
|
/* SOFT_RESET */
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
||||||
if (ddc_data->retry-- > 0) {
|
if (ddc_data->retry-- > 0) {
|
||||||
DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
|
pr_debug("%s: failed NACK=0x%08x, retry=%d\n",
|
||||||
__func__, ddc_data->what, reg_val,
|
ddc_data->what, reg_val,
|
||||||
ddc_data->retry);
|
ddc_data->retry);
|
||||||
DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
|
pr_debug("daddr=0x%02x,off=0x%02x,len=%d\n",
|
||||||
__func__, ddc_data->dev_addr,
|
ddc_data->dev_addr,
|
||||||
ddc_data->offset, ddc_data->data_len);
|
ddc_data->offset, ddc_data->data_len);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
if (log_retry_fail) {
|
if (log_retry_fail) {
|
||||||
DEV_ERR("%s(%s): failed NACK=0x%08x\n",
|
pr_err("%s: failed NACK=0x%08x\n",
|
||||||
__func__, ddc_data->what, reg_val);
|
ddc_data->what, reg_val);
|
||||||
DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
|
pr_err("daddr=0x%02x,off=0x%02x,len=%d\n",
|
||||||
__func__, ddc_data->dev_addr,
|
ddc_data->dev_addr,
|
||||||
ddc_data->offset, ddc_data->data_len);
|
ddc_data->offset, ddc_data->data_len);
|
||||||
}
|
}
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -995,27 +1128,29 @@ again:
|
||||||
ddc_data->data_buf[ndx] = (u8) ((reg_val & 0x0000FF00) >> 8);
|
ddc_data->data_buf[ndx] = (u8) ((reg_val & 0x0000FF00) >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
|
pr_debug("%s: success\n", ddc_data->what);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
return status;
|
return status;
|
||||||
} /* hdmi_ddc_read_seg */
|
} /* hdmi_ddc_read_seg */
|
||||||
|
|
||||||
int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_ddc_data *ddc_data)
|
|
||||||
{
|
{
|
||||||
u32 reg_val, ndx;
|
u32 reg_val, ndx;
|
||||||
int status = 0, retry = 10;
|
int status = 0, retry = 10;
|
||||||
u32 time_out_count;
|
u32 time_out_count;
|
||||||
|
struct hdmi_tx_ddc_data *ddc_data;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddc_data = &ddc_ctrl->ddc_data;
|
||||||
|
|
||||||
if (!ddc_data->data_buf) {
|
if (!ddc_data->data_buf) {
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
|
pr_err("%s: invalid buf\n", ddc_data->what);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,22 +1225,21 @@ again:
|
||||||
time_out_count = wait_for_completion_timeout(
|
time_out_count = wait_for_completion_timeout(
|
||||||
&ddc_ctrl->ddc_sw_done, HZ/2);
|
&ddc_ctrl->ddc_sw_done, HZ/2);
|
||||||
|
|
||||||
DEV_DBG("DDC write done at %dms\n", jiffies_to_msecs(jiffies));
|
pr_debug("DDC write done at %dms\n", jiffies_to_msecs(jiffies));
|
||||||
|
|
||||||
reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
|
reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
|
||||||
if (!time_out_count) {
|
if (!time_out_count) {
|
||||||
if (retry-- > 0) {
|
if (retry-- > 0) {
|
||||||
DEV_INFO("%s[%s]: failed timout, retry=%d\n", __func__,
|
pr_debug("%s: failed timout, retry=%d\n",
|
||||||
ddc_data->what, retry);
|
ddc_data->what, retry);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -ETIMEDOUT;
|
status = -ETIMEDOUT;
|
||||||
DEV_ERR("%s[%s]: timedout, Int Ctrl=%08x\n",
|
pr_err("%s: timedout, Int Ctrl=%08x\n",
|
||||||
__func__, ddc_data->what,
|
ddc_data->what,
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
|
||||||
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
|
pr_err("DDC SW Status=%08x, HW Status=%08x\n",
|
||||||
__func__,
|
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
|
||||||
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1125,34 +1259,35 @@ again:
|
||||||
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
|
||||||
|
|
||||||
if (retry-- > 0) {
|
if (retry-- > 0) {
|
||||||
DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n",
|
pr_debug("%s: failed NACK=%08x, retry=%d\n",
|
||||||
__func__, ddc_data->what, reg_val, retry);
|
ddc_data->what, reg_val, retry);
|
||||||
msleep(100);
|
msleep(100);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
DEV_ERR("%s[%s]: failed NACK: %08x\n", __func__,
|
pr_err("%s: failed NACK: %08x\n", ddc_data->what, reg_val);
|
||||||
ddc_data->what, reg_val);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
|
pr_debug("%s: success\n", ddc_data->what);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
return status;
|
return status;
|
||||||
} /* hdmi_ddc_write */
|
} /* hdmi_ddc_write */
|
||||||
|
|
||||||
|
|
||||||
int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_ddc_data *ddc_data)
|
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
struct hdmi_tx_ddc_data *ddc_data;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
DEV_ERR("%s: invalid input\n", __func__);
|
pr_err("invalid input\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddc_data = &ddc_ctrl->ddc_data;
|
||||||
|
|
||||||
status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what);
|
status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what);
|
||||||
if (status)
|
if (status)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1171,12 +1306,12 @@ int hdmi_scdc_read(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 *val)
|
||||||
u8 data_buf[2] = {0};
|
u8 data_buf[2] = {0};
|
||||||
|
|
||||||
if (!ctrl || !ctrl->io || !val) {
|
if (!ctrl || !ctrl->io || !val) {
|
||||||
DEV_ERR("%s: Bad Parameters\n", __func__);
|
pr_err("Bad Parameters\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_type >= HDMI_TX_SCDC_MAX) {
|
if (data_type >= HDMI_TX_SCDC_MAX) {
|
||||||
DEV_ERR("%s: Unsupported data type\n", __func__);
|
pr_err("Unsupported data type\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,9 +1365,11 @@ int hdmi_scdc_read(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 *val)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = hdmi_ddc_read(ctrl, &data);
|
ctrl->ddc_data = data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_read(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: DDC Read failed for %s\n", __func__, data.what);
|
pr_err("DDC Read failed for %s\n", data.what);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1285,12 +1422,12 @@ int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val)
|
||||||
u8 read_val = 0;
|
u8 read_val = 0;
|
||||||
|
|
||||||
if (!ctrl || !ctrl->io) {
|
if (!ctrl || !ctrl->io) {
|
||||||
DEV_ERR("%s: Bad Parameters\n", __func__);
|
pr_err("Bad Parameters\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_type >= HDMI_TX_SCDC_MAX) {
|
if (data_type >= HDMI_TX_SCDC_MAX) {
|
||||||
DEV_ERR("%s: Unsupported data type\n", __func__);
|
pr_err("Unsupported data type\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1311,9 +1448,10 @@ int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val)
|
||||||
rdata.data_len = 1;
|
rdata.data_len = 1;
|
||||||
rdata.offset = HDMI_SCDC_TMDS_CONFIG;
|
rdata.offset = HDMI_SCDC_TMDS_CONFIG;
|
||||||
rdata.request_len = 1;
|
rdata.request_len = 1;
|
||||||
rc = hdmi_ddc_read(ctrl, &rdata);
|
ctrl->ddc_data = rdata;
|
||||||
|
rc = hdmi_ddc_read(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: scdc read failed\n", __func__);
|
pr_err("scdc read failed\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (data_type == HDMI_TX_SCDC_SCRAMBLING_ENABLE) {
|
if (data_type == HDMI_TX_SCDC_SCRAMBLING_ENABLE) {
|
||||||
|
@ -1334,14 +1472,16 @@ int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val)
|
||||||
data_buf[0] = (u8)(val & 0x1);
|
data_buf[0] = (u8)(val & 0x1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEV_ERR("%s Cannot write to read only reg (%d)\n", __func__,
|
pr_err("Cannot write to read only reg (%d)\n",
|
||||||
data_type);
|
data_type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = hdmi_ddc_write(ctrl, &data);
|
ctrl->ddc_data = data;
|
||||||
|
|
||||||
|
rc = hdmi_ddc_write(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DEV_ERR("%s: DDC Read failed for %s\n", __func__, data.what);
|
pr_err("DDC Read failed for %s\n", data.what);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,12 +1492,12 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl,
|
||||||
u32 type, u32 to_in_num_lines)
|
u32 type, u32 to_in_num_lines)
|
||||||
{
|
{
|
||||||
if (!ctrl) {
|
if (!ctrl) {
|
||||||
DEV_ERR("%s: Invalid parameters\n", __func__);
|
pr_err("Invalid parameters\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type >= HDMI_TX_DDC_TIMER_MAX) {
|
if (type >= HDMI_TX_DDC_TIMER_MAX) {
|
||||||
DEV_ERR("%s: Invalid timer type %d\n", __func__, type);
|
pr_err("Invalid timer type %d\n", type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1366,7 +1506,7 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl,
|
||||||
hdmi_scrambler_status_timer_setup(ctrl, to_in_num_lines);
|
hdmi_scrambler_status_timer_setup(ctrl, to_in_num_lines);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEV_ERR("%s: %d type not supported\n", __func__, type);
|
pr_err("%d type not supported\n", type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1378,7 +1518,7 @@ void hdmi_hdcp2p2_ddc_reset(struct hdmi_tx_ddc_ctrl *ctrl)
|
||||||
u32 reg_val;
|
u32 reg_val;
|
||||||
|
|
||||||
if (!ctrl) {
|
if (!ctrl) {
|
||||||
DEV_ERR("%s: Invalid parameters\n", __func__);
|
pr_err("Invalid parameters\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1404,7 +1544,7 @@ void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl)
|
||||||
bool ddc_hw_not_ready;
|
bool ddc_hw_not_ready;
|
||||||
|
|
||||||
if (!ctrl) {
|
if (!ctrl) {
|
||||||
DEV_ERR("%s: Invalid parameters\n", __func__);
|
pr_err("Invalid parameters\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,75 +1566,38 @@ void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl)
|
||||||
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl,
|
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl)
|
||||||
struct hdmi_tx_hdcp2p2_ddc_data *hdcp2p2_ddc_data,
|
|
||||||
struct completion *rxstatus_completion)
|
|
||||||
{
|
{
|
||||||
u32 reg_val;
|
u32 reg_val;
|
||||||
u32 reg_field_shift;
|
u32 intr_en_mask;
|
||||||
u32 reg_field_mask;
|
|
||||||
u32 reg_intr_ack_shift;
|
|
||||||
u32 reg_intr_mask_shift;
|
|
||||||
u32 timeout;
|
u32 timeout;
|
||||||
u32 rxstatus_read_method;
|
int rc = 0;
|
||||||
u32 rxstatus_bytes;
|
struct hdmi_tx_hdcp2p2_ddc_data *data;
|
||||||
bool poll_sink;
|
|
||||||
|
|
||||||
if (!hdcp2p2_ddc_data)
|
if (!ctrl) {
|
||||||
return -EINVAL;
|
pr_err("Invalid ctrl data\n");
|
||||||
|
|
||||||
/* We return a u32 for all RxStatus bits being read */
|
|
||||||
if (hdcp2p2_ddc_data->ddc_data.data_len < sizeof(u32))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
poll_sink = hdcp2p2_ddc_data->poll_sink;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup shifts and masks based on which RxStatus bits we are dealing
|
|
||||||
* with in this call
|
|
||||||
*/
|
|
||||||
switch (hdcp2p2_ddc_data->rxstatus_field) {
|
|
||||||
case RXSTATUS_MESSAGE_SIZE:
|
|
||||||
reg_field_shift = HDCP2P2_RXSTATUS_MESSAGE_SIZE_SHIFT;
|
|
||||||
reg_field_mask = HDCP2P2_RXSTATUS_MESSAGE_SIZE_MASK;
|
|
||||||
reg_intr_ack_shift =
|
|
||||||
HDCP2P2_RXSTATUS_MESSAGE_SIZE_ACK_SHIFT;
|
|
||||||
reg_intr_mask_shift =
|
|
||||||
HDCP2P2_RXSTATUS_MESSAGE_SIZE_INTR_SHIFT;
|
|
||||||
break;
|
|
||||||
case RXSTATUS_REAUTH_REQ:
|
|
||||||
reg_field_shift = HDCP2P2_RXSTATUS_REAUTH_REQ_SHIFT;
|
|
||||||
reg_field_mask = HDCP2P2_RXSTATUS_REAUTH_REQ_MASK;
|
|
||||||
reg_intr_ack_shift =
|
|
||||||
HDCP2P2_RXSTATUS_REAUTH_REQ_ACK_SHIFT;
|
|
||||||
reg_intr_mask_shift =
|
|
||||||
HDCP2P2_RXSTATUS_REAUTH_REQ_INTR_SHIFT;
|
|
||||||
break;
|
|
||||||
case RXSTATUS_READY:
|
|
||||||
reg_field_shift = HDCP2P2_RXSTATUS_READY_SHIFT;
|
|
||||||
reg_field_mask = HDCP2P2_RXSTATUS_READY_MASK;
|
|
||||||
reg_intr_ack_shift =
|
|
||||||
HDCP2P2_RXSTATUS_READY_ACK_SHIFT;
|
|
||||||
reg_intr_mask_shift =
|
|
||||||
HDCP2P2_RXSTATUS_READY_INTR_SHIFT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_DBG("%s: Requested msg size, shift %u mask %u ack %u mask %u\n",
|
data = &ctrl->hdcp2p2_ddc_data;
|
||||||
__func__, reg_field_shift, reg_field_mask,
|
if (!data) {
|
||||||
reg_intr_ack_shift, reg_intr_mask_shift);
|
pr_err("Invalid ddc data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = hdmi_ddc_clear_irq(ctrl, "rxstatus");
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
intr_en_mask = data->intr_mask;
|
||||||
|
intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK);
|
||||||
|
intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_DONE);
|
||||||
|
|
||||||
/* Disable short read for now, sinks don't support it */
|
/* Disable short read for now, sinks don't support it */
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_CTRL);
|
reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_CTRL);
|
||||||
reg_val |= BIT(4);
|
reg_val |= BIT(4);
|
||||||
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_CTRL, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_CTRL, reg_val);
|
||||||
|
|
||||||
/* Clear interrupt status bits */
|
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0);
|
|
||||||
reg_val &= ~BIT(reg_intr_ack_shift);
|
|
||||||
DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the DDC timers for HDMI_HDCP2P2_DDC_TIMER_CTRL1 and
|
* Setup the DDC timers for HDMI_HDCP2P2_DDC_TIMER_CTRL1 and
|
||||||
* HDMI_HDCP2P2_DDC_TIMER_CTRL2.
|
* HDMI_HDCP2P2_DDC_TIMER_CTRL2.
|
||||||
|
@ -1507,17 +1610,20 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl,
|
||||||
* 3. DDC_TIMEOUT_TIMER: Timeout in hsyncs which starts counting when
|
* 3. DDC_TIMEOUT_TIMER: Timeout in hsyncs which starts counting when
|
||||||
* a request is made and stops when it is accepted by DDC arbiter
|
* a request is made and stops when it is accepted by DDC arbiter
|
||||||
*/
|
*/
|
||||||
timeout = hdcp2p2_ddc_data->timer_delay_lines & 0xffff;
|
timeout = data->timer_delay_lines & 0xffff;
|
||||||
|
pr_debug("timeout: %d\n", timeout);
|
||||||
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timeout);
|
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timeout);
|
||||||
|
|
||||||
/* Set both urgent and hw-timeout fields to the same value */
|
/* Set both urgent and hw-timeout fields to the same value */
|
||||||
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL2,
|
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL2,
|
||||||
(timeout << 16 | timeout));
|
(timeout << 16 | timeout));
|
||||||
|
|
||||||
/* Enable the interrupt for the requested field, and enable timeouts */
|
/* enable interrupts */
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0);
|
reg_val = intr_en_mask;
|
||||||
reg_val |= BIT(reg_intr_mask_shift);
|
/* Clear interrupt status bits */
|
||||||
reg_val |= BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK);
|
reg_val |= intr_en_mask >> 1;
|
||||||
DEV_DBG("%s: Enabling interrupts for req field\n", __func__);
|
|
||||||
|
pr_debug("writng HDMI_DDC_INT_CTRL0 0x%x\n", reg_val);
|
||||||
DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1541,68 +1647,62 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl,
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL);
|
reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL);
|
||||||
reg_val &= ~(BIT(1) | BIT(0));
|
reg_val &= ~(BIT(1) | BIT(0));
|
||||||
|
|
||||||
rxstatus_read_method =
|
pr_debug("data->read_method %d\n", data->read_method);
|
||||||
poll_sink ? HDCP2P2_RXSTATUS_HW_DDC_AUTOMATIC_LOOP
|
|
||||||
: HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
|
||||||
|
|
||||||
if (poll_sink)
|
if (data->read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER)
|
||||||
reg_val |= BIT(0);
|
reg_val |= BIT(1) | BIT(0);
|
||||||
else
|
else
|
||||||
reg_val |= (BIT(1) | BIT(0));
|
reg_val |= BIT(0);
|
||||||
|
|
||||||
DEV_DBG("%s: Enabling hardware access to rxstatus\n", __func__);
|
|
||||||
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
||||||
|
|
||||||
if (rxstatus_read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER) {
|
if (data->read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER) {
|
||||||
/* If we are using SW_TRIGGER, then go ahead and trigger it */
|
/* If we are using SW_TRIGGER, then go ahead and trigger it */
|
||||||
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1);
|
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1);
|
||||||
|
|
||||||
/*
|
reinit_completion(&ctrl->rxstatus_completion);
|
||||||
* Now wait for interrupt bits to be set to indicate that the
|
timeout = wait_for_completion_timeout(
|
||||||
* register is available to read
|
&ctrl->rxstatus_completion,
|
||||||
*/
|
|
||||||
DEV_DBG("%s: HDMI_DDC_INT_CTRL0 is 0x%x, waiting for ISR\n",
|
|
||||||
__func__, DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0));
|
|
||||||
reinit_completion(rxstatus_completion);
|
|
||||||
wait_for_completion_timeout(rxstatus_completion,
|
|
||||||
msecs_to_jiffies(200));
|
msecs_to_jiffies(200));
|
||||||
|
if (!timeout) {
|
||||||
|
pr_err("sw ddc rxstatus timeout\n");
|
||||||
|
rc = -ETIMEDOUT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure no errors occurred during DDC transaction */
|
/* check for errors and clear status */
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_STATUS);
|
reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_STATUS);
|
||||||
|
if (reg_val & BIT(0))
|
||||||
|
pr_debug("ddc busy\n");
|
||||||
|
|
||||||
/* Check for NACK0, NACK1, TIMEOUT, ABORT bits */
|
if (reg_val & BIT(4)) {
|
||||||
reg_val &= (BIT(12) | BIT(14) | BIT(4) | BIT(8));
|
pr_err("ddc aborted\n");
|
||||||
|
reg_val |= BIT(5);
|
||||||
if (reg_val) {
|
rc = -ECONNABORTED;
|
||||||
DEV_ERR("%s: DDC transaction error, hdcp2p2_ddc_status 0x%x\n",
|
|
||||||
__func__, reg_val);
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the RxStatus field that was requested */
|
if (reg_val & BIT(8)) {
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0);
|
pr_err("timed out\n");
|
||||||
rxstatus_bytes = reg_val;
|
reg_val |= BIT(9);
|
||||||
rxstatus_bytes &= reg_field_mask;
|
rc = -ETIMEDOUT;
|
||||||
rxstatus_bytes >>= reg_field_shift;
|
}
|
||||||
memcpy(hdcp2p2_ddc_data->ddc_data.data_buf,
|
|
||||||
&rxstatus_bytes, sizeof(rxstatus_bytes));
|
|
||||||
|
|
||||||
/* Read the RxStatus field that was requested */
|
if (reg_val & BIT(12)) {
|
||||||
/* Write the interrupt ack back */
|
pr_err("NACK0\n");
|
||||||
reg_val |= BIT(reg_intr_ack_shift);
|
reg_val |= BIT(13);
|
||||||
DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val);
|
rc = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear the ack bits and the DDC_FAILED bit next */
|
if (reg_val & BIT(14)) {
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0);
|
pr_err("NACK1\n");
|
||||||
reg_val &= ~BIT(reg_intr_ack_shift);
|
reg_val |= BIT(15);
|
||||||
reg_val &= ~BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK);
|
rc = -EIO;
|
||||||
DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val);
|
}
|
||||||
|
|
||||||
/* Disable hardware access to RxStatus register */
|
|
||||||
reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL);
|
|
||||||
reg_val &= ~(BIT(1) | BIT(0));
|
|
||||||
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
||||||
|
|
||||||
return 0;
|
/* Disable hardware access to RxStatus register */
|
||||||
|
hdmi_hdcp2p2_ddc_disable(ctrl);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,6 +353,7 @@
|
||||||
#define HDCP2P2_RXSTATUS_DDC_FAILED_SHIFT 8
|
#define HDCP2P2_RXSTATUS_DDC_FAILED_SHIFT 8
|
||||||
#define HDCP2P2_RXSTATUS_DDC_FAILED_ACKSHIFT 9
|
#define HDCP2P2_RXSTATUS_DDC_FAILED_ACKSHIFT 9
|
||||||
#define HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK 10
|
#define HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK 10
|
||||||
|
#define HDCP2P2_RXSTATUS_DDC_DONE 6
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be
|
* Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be
|
||||||
|
@ -395,11 +396,6 @@ enum hdmi_tx_ddc_timer_type {
|
||||||
HDMI_TX_DDC_TIMER_MAX,
|
HDMI_TX_DDC_TIMER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hdmi_tx_ddc_ctrl {
|
|
||||||
struct dss_io_data *io;
|
|
||||||
struct completion ddc_sw_done;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hdmi_tx_ddc_data {
|
struct hdmi_tx_ddc_data {
|
||||||
char *what;
|
char *what;
|
||||||
u8 *data_buf;
|
u8 *data_buf;
|
||||||
|
@ -412,20 +408,34 @@ struct hdmi_tx_ddc_data {
|
||||||
int retry;
|
int retry;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hdmi_tx_hdcp2p2_rxstatus_field {
|
enum hdmi_tx_hdcp2p2_rxstatus_intr_mask {
|
||||||
RXSTATUS_MESSAGE_SIZE,
|
RXSTATUS_MESSAGE_SIZE = BIT(31),
|
||||||
RXSTATUS_REAUTH_REQ,
|
RXSTATUS_READY = BIT(18),
|
||||||
RXSTATUS_READY,
|
RXSTATUS_REAUTH_REQ = BIT(14),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hdmi_tx_hdcp2p2_ddc_data {
|
struct hdmi_tx_hdcp2p2_ddc_data {
|
||||||
struct hdmi_tx_ddc_data ddc_data;
|
enum hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask;
|
||||||
enum hdmi_tx_hdcp2p2_rxstatus_field rxstatus_field;
|
|
||||||
u32 timer_delay_lines;
|
u32 timer_delay_lines;
|
||||||
bool poll_sink;
|
u32 read_method;
|
||||||
|
u32 message_size;
|
||||||
|
bool encryption_ready;
|
||||||
|
bool ready;
|
||||||
|
bool reauth_req;
|
||||||
|
bool ddc_max_retries_fail;
|
||||||
|
bool ddc_done;
|
||||||
|
bool ddc_read_req;
|
||||||
int irq_wait_count;
|
int irq_wait_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hdmi_tx_ddc_ctrl {
|
||||||
|
struct dss_io_data *io;
|
||||||
|
struct completion ddc_sw_done;
|
||||||
|
struct completion rxstatus_completion;
|
||||||
|
struct hdmi_tx_ddc_data ddc_data;
|
||||||
|
struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct hdmi_util_ds_data {
|
struct hdmi_util_ds_data {
|
||||||
bool ds_registered;
|
bool ds_registered;
|
||||||
|
@ -469,11 +479,10 @@ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type);
|
||||||
/* DDC */
|
/* DDC */
|
||||||
void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *);
|
void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *);
|
||||||
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *, u32 version);
|
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *, u32 version);
|
||||||
int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
|
int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *);
|
||||||
int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
|
int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *);
|
||||||
int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
|
int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *);
|
||||||
int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *,
|
int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *);
|
||||||
struct hdmi_tx_ddc_data *);
|
|
||||||
|
|
||||||
int hdmi_scdc_read(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 *val);
|
int hdmi_scdc_read(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 *val);
|
||||||
int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val);
|
int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val);
|
||||||
|
@ -481,8 +490,6 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl,
|
||||||
u32 type, u32 to_in_num_lines);
|
u32 type, u32 to_in_num_lines);
|
||||||
void hdmi_hdcp2p2_ddc_reset(struct hdmi_tx_ddc_ctrl *ctrl);
|
void hdmi_hdcp2p2_ddc_reset(struct hdmi_tx_ddc_ctrl *ctrl);
|
||||||
void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl);
|
void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl);
|
||||||
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl,
|
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl);
|
||||||
struct hdmi_tx_hdcp2p2_ddc_data *hdcp2p2_ddc_data,
|
|
||||||
struct completion *rxstatus_completion);
|
|
||||||
|
|
||||||
#endif /* __HDMI_UTIL_H__ */
|
#endif /* __HDMI_UTIL_H__ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue