From a715804225a38fc592a0f4fede3d8d1e027e355f Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Mon, 5 Oct 2015 01:21:42 -0700 Subject: [PATCH] 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 --- drivers/misc/hdcp.c | 9 +- drivers/video/fbdev/msm/mdss_hdmi_hdcp.c | 41 +- drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c | 133 ++--- drivers/video/fbdev/msm/mdss_hdmi_tx.c | 21 +- drivers/video/fbdev/msm/mdss_hdmi_util.c | 532 ++++++++++++-------- drivers/video/fbdev/msm/mdss_hdmi_util.h | 47 +- 6 files changed, 438 insertions(+), 345 deletions(-) diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index 7319d51114b0..edf4837dd2f7 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -333,6 +333,7 @@ struct hdcp_lib_handle { uint32_t tz_ctxhandle; uint32_t hdcp_timeout; bool no_stored_km_flag; + bool feature_supported; void *client_ctx; struct hdcp_client_ops *client_ops; struct mutex hdcp_lock; @@ -745,9 +746,15 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext) goto exit; } + if (handle->feature_supported) { + supported = true; + goto exit; + } + rc = hdcp_lib_library_load(handle); if (!rc) { pr_debug("HDCP2p2 supported\n"); + handle->feature_supported = true; hdcp_lib_library_unload(handle); supported = true; } @@ -769,7 +776,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) 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) { handle->last_msg_recvd_len = data->recvd_msg_len; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c index f67a8f3aec5f..c9bc0fee2bf5 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c @@ -366,7 +366,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; 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) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, 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_len = 8; 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) { DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME); 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_len = 5; 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) { DEV_ERR("%s: %s: AKSV write failed\n", __func__, 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.what = "Bksv"; 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) { DEV_ERR("%s: %s: BKSV read failed\n", __func__, 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.what = "R0'"; 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) { DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME); goto error; @@ -684,7 +697,8 @@ do { \ ddc_data.offset = (off); \ memset(what, 0, sizeof(what)); \ 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) { \ DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \ what); \ @@ -868,7 +882,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; 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) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, 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.what = "Bstatuss"; 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) { DEV_ERR("%s: %s: BSTATUS read failed\n", __func__, 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.what = "KSV FIFO"; ddc_data.no_align = true; + + hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; + cnt = 0; 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) { DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__, HDCP_STATE_NAME); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c index 1ef90afe3f32..7d8535635fb8 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c @@ -86,7 +86,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) 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->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; 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)); ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR; 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.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) pr_err("Cannot read HDCP message register\n"); return rc; @@ -340,24 +346,14 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; 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) pr_err("Cannot write HDCP message register"); 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, u8 *hdcp2version) { @@ -373,7 +369,9 @@ static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; 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) { pr_err("Cannot read HDCP2Version register"); return rc; @@ -424,44 +422,6 @@ static struct attribute_group hdmi_hdcp2p2_fs_attr_group = { .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) { struct hdmi_hdcp2p2_ctrl *ctrl = input; @@ -525,12 +485,12 @@ exit: static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) { - int rc = 0, msg_size = 0, retries = 5; + int rc = 0; u64 mult; char *recvd_msg_buf = NULL; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, 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 msm_hdmi_mode_timing_info *timing; 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; + if (!ddc_ctrl) + goto exit; - do { - timing = ctrl->init_data.timing; + hdmi_ddc_config(ddc_ctrl); - 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; + ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; - hdmi_ddc_config(ddc_ctrl); - pr_debug("Reading rxstatus, timer delay %u\n", (u32)mult); + memset(ddc_data, 0, sizeof(*ddc_data)); - rc = hdmi_hdcp2p2_ddc_read_rxstatus( - ddc_ctrl, &hdcp2p2_ddc_data, - &ctrl->rxstatus_completion); - if (rc) { - pr_err("Could not read rxstatus from sink\n"); - continue; - } - - if (!msg_size) { - pr_err("recvd invalid message size\n"); - rc = -EINVAL; - continue; - } - } while (rc && (retries-- > 0)); + 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) { - pr_err("error reading valid rxstatus data\n"); + pr_err("error reading rxstatus %d\n", rc); 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) goto exit; rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf, - msg_size, ctrl->timeout); + ddc_data->message_size, ctrl->timeout); if (rc) - pr_err("ERROR reading message from sink\n"); - - hdmi_hdcp2p2_ddc_abort(ctrl); - hdmi_hdcp2p2_ddc_reset(ddc_ctrl); - hdmi_hdcp2p2_ddc_disable(ddc_ctrl); + pr_err("error reading message %d\n", rc); cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; cdata.recvd_msg_buf = recvd_msg_buf; - cdata.recvd_msg_len = msg_size; + cdata.recvd_msg_len = ddc_data->message_size; exit: if (rc == -ETIMEDOUT) 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; int rc; static struct hdmi_hdcp_ops ops = { - .hdmi_hdcp_isr = hdmi_hdcp2p2_isr, .hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate, .hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate, .feature_supported = hdmi_hdcp2p2_feature_supported, diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index c55e76c11cf2..0655c4971442 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -1291,11 +1291,13 @@ static u32 hdmi_tx_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl, ddc_data.what = "EDID"; ddc_data.no_align = false; + ddc_ctrl->ddc_data = ddc_data; + /* Read EDID twice with 32bit alighnment too */ if (block < 2) - status = hdmi_ddc_read(ddc_ctrl, &ddc_data); + status = hdmi_ddc_read(ddc_ctrl); else - status = hdmi_ddc_read_seg(ddc_ctrl, &ddc_data); + status = hdmi_ddc_read_seg(ddc_ctrl); if (status) 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])) 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_hdcp_isr( - hdmi_ctrl->hdcp_feature_data)) - DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__); + 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( + hdmi_ctrl->hdcp_feature_data)) + DEV_ERR("%s: hdmi_hdcp_isr failed\n", + __func__); + } + } end: return IRQ_HANDLED; } /* 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]; 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_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_feature_data); + hdmi_ctrl->hdcp_ops = NULL; + rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false); if (rc) diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 53c8006b0071..8f61e27c0876 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -11,6 +11,8 @@ * */ +#define pr_fmt(fmt) "%s: " fmt, __func__ + #include #include #include "mdss_hdmi_util.h" @@ -119,7 +121,7 @@ bool hdmi_is_valid_resv_timing(int mode) struct msm_hdmi_mode_timing_info *info; 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; } @@ -378,7 +380,7 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, u32 ret; if (!timing_in) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); goto exit; } @@ -429,12 +431,12 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, } if (vic < 0) { - DEV_ERR("%s: timing is not supported h=%d v=%d\n", - __func__, timing_in->active_h, timing_in->active_v); + pr_err("timing is not supported h=%d v=%d\n", + timing_in->active_h, timing_in->active_v); } 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)); return vic; @@ -481,19 +483,18 @@ ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size) return len; } /* hdmi_get_video_3d_fmt_2string */ -static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data, - const char *caller) +static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data) { if (!ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); return; } - DEV_DBG("%s: buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n", - caller, ddc_data->data_buf, ddc_data->data_len, + pr_debug("what: %s, buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n", + ddc_data->what, ddc_data->data_buf, ddc_data->data_len, ddc_data->dev_addr, ddc_data->no_align); - DEV_DBG("%s: offset=0x%x, req_len=0x%x, retry=%d, what=%s\n", - caller, ddc_data->offset, ddc_data->request_len, + pr_debug("what: %s, offset=0x%x, req_len=0x%x, retry=%d, what=%s\n", + ddc_data->what, ddc_data->offset, ddc_data->request_len, ddc_data->retry, ddc_data->what); } /* 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; if (!ddc_ctrl || !ddc_ctrl->io) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); 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); if (!time_out_count) { - DEV_ERR("%s[%s]: timedout\n", __func__, what); + pr_err("%s: timedout\n", what); return -ETIMEDOUT; } return 0; } /*hdmi_ddc_clear_irq */ -static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl, - struct hdmi_tx_ddc_data *ddc_data) +static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { u32 reg_val, ndx, time_out_count, wait_time; + struct hdmi_tx_ddc_data *ddc_data; int status = 0; int log_retry_fail; - if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + if (!ddc_ctrl || !ddc_ctrl->io) { + pr_err("invalid input\n"); return -EINVAL; } + ddc_data = &ddc_ctrl->ddc_data; + if (!ddc_data->data_buf) { status = -EINVAL; - DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what); + pr_err("%s: invalid buf\n", ddc_data->what); goto error; } - hdmi_ddc_print_data(ddc_data, __func__); + hdmi_ddc_print_data(ddc_data); log_retry_fail = ddc_data->retry != 1; again: @@ -624,8 +627,7 @@ again: DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20)); if (ddc_data->hard_timeout) { - DEV_DBG("%s: using hard_timeout %dms\n", __func__, - ddc_data->hard_timeout); + pr_debug("using hard_timeout %dms\n", ddc_data->hard_timeout); wait_time = msecs_to_jiffies(ddc_data->hard_timeout); } else { wait_time = HZ/2; @@ -633,20 +635,18 @@ again: time_out_count = wait_for_completion_timeout( &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)); if (!time_out_count) { if (ddc_data->retry-- > 0) { - DEV_INFO("%s: failed timout, retry=%d\n", __func__, - ddc_data->retry); + pr_debug("failed timout, retry=%d\n", ddc_data->retry); goto again; } 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)); - DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n", - __func__, + pr_err("DDC SW Status=%08x, HW Status=%08x\n", DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS), DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS)); goto error; @@ -666,20 +666,20 @@ again: DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1)); if (ddc_data->retry-- > 0) { - DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n", - __func__, ddc_data->what, reg_val, + pr_debug("%s: failed NACK=0x%08x, retry=%d\n", + ddc_data->what, reg_val, ddc_data->retry); - DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n", - __func__, ddc_data->dev_addr, + pr_debug("daddr=0x%02x,off=0x%02x,len=%d\n", + ddc_data->dev_addr, ddc_data->offset, ddc_data->data_len); goto again; } status = -EIO; if (log_retry_fail) { - DEV_ERR("%s(%s): failed NACK=0x%08x\n", - __func__, ddc_data->what, reg_val); - DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n", - __func__, ddc_data->dev_addr, + pr_err("%s: failed NACK=0x%08x\n", + ddc_data->what, reg_val); + pr_err("daddr=0x%02x,off=0x%02x,len=%d\n", + ddc_data->dev_addr, ddc_data->offset, ddc_data->data_len); } goto error; @@ -704,7 +704,7 @@ again: 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: return status; @@ -713,7 +713,7 @@ error: void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { if (!ddc_ctrl || !ddc_ctrl->io) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); 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)); } /* 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) { 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; if (!ddc_ctrl || !ddc_ctrl->io) { - DEV_ERR("%s: invalid input\n", __func__); + pr_err("invalid input\n"); 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); } - 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) goto end; ddc_timer_int = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL2); if (ddc_timer_int & BIT(12)) { /* DDC_INT_CTRL2.SCRAMBLER_STATUS_NOT is set */ - DEV_ERR("%s: Sink cannot descramble the signal\n", - __func__); + pr_err("Sink cannot descramble the signal\n"); /* Clear interrupt */ ddc_timer_int |= BIT(14); 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 * is set */ - DEV_ERR( - "%s: DDC timeout while reading SCRAMBLER STATUS\n", - __func__); + pr_err("DDC timeout while reading SCRAMBLER STATUS\n"); ddc_timer_int |= BIT(13); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL5, 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); } end: + hdmi_ddc_hdcp2p2_isr(ddc_ctrl); return 0; } /* hdmi_ddc_isr */ -int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl, - struct hdmi_tx_ddc_data *ddc_data) +int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { int rc = 0; + struct hdmi_tx_ddc_data *ddc_data; - if (!ddc_ctrl || !ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + if (!ddc_ctrl) { + pr_err("invalid ddc ctrl\n"); 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) return rc; if (ddc_data->no_align) { - rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data); + rc = hdmi_ddc_read_retry(ddc_ctrl); } else { 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; } /* hdmi_ddc_read */ -int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *ddc_ctrl, - struct hdmi_tx_ddc_data *ddc_data) +int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { int status = 0; u32 reg_val, ndx, time_out_count; int log_retry_fail; int seg_addr = 0x60, seg_num = 0x01; + struct hdmi_tx_ddc_data *ddc_data; - if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + if (!ddc_ctrl || !ddc_ctrl->io) { + pr_err("invalid input\n"); return -EINVAL; } + ddc_data = &ddc_ctrl->ddc_data; + if (!ddc_data->data_buf) { status = -EINVAL; - DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what); + pr_err("%s: invalid buf\n", ddc_data->what); goto error; } @@ -930,15 +1065,13 @@ again: DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2))); if (!time_out_count) { if (ddc_data->retry-- > 0) { - DEV_INFO("%s: failed timout, retry=%d\n", __func__, - ddc_data->retry); + pr_debug("failed timout, retry=%d\n", ddc_data->retry); goto again; } 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)); - DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n", - __func__, + pr_err("DDC SW Status=%08x, HW Status=%08x\n", DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS), DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS)); goto error; @@ -956,20 +1089,20 @@ again: /* SOFT_RESET */ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1)); if (ddc_data->retry-- > 0) { - DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n", - __func__, ddc_data->what, reg_val, + pr_debug("%s: failed NACK=0x%08x, retry=%d\n", + ddc_data->what, reg_val, ddc_data->retry); - DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n", - __func__, ddc_data->dev_addr, + pr_debug("daddr=0x%02x,off=0x%02x,len=%d\n", + ddc_data->dev_addr, ddc_data->offset, ddc_data->data_len); goto again; } status = -EIO; if (log_retry_fail) { - DEV_ERR("%s(%s): failed NACK=0x%08x\n", - __func__, ddc_data->what, reg_val); - DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n", - __func__, ddc_data->dev_addr, + pr_err("%s: failed NACK=0x%08x\n", + ddc_data->what, reg_val); + pr_err("daddr=0x%02x,off=0x%02x,len=%d\n", + ddc_data->dev_addr, ddc_data->offset, ddc_data->data_len); } goto error; @@ -995,27 +1128,29 @@ again: 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: return status; } /* hdmi_ddc_read_seg */ -int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl, - struct hdmi_tx_ddc_data *ddc_data) +int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { u32 reg_val, ndx; int status = 0, retry = 10; u32 time_out_count; + struct hdmi_tx_ddc_data *ddc_data; - if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + if (!ddc_ctrl || !ddc_ctrl->io) { + pr_err("invalid input\n"); return -EINVAL; } + ddc_data = &ddc_ctrl->ddc_data; + if (!ddc_data->data_buf) { status = -EINVAL; - DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what); + pr_err("%s: invalid buf\n", ddc_data->what); goto error; } @@ -1090,22 +1225,21 @@ again: time_out_count = wait_for_completion_timeout( &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); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2))); if (!time_out_count) { 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); goto again; } status = -ETIMEDOUT; - DEV_ERR("%s[%s]: timedout, Int Ctrl=%08x\n", - __func__, ddc_data->what, + pr_err("%s: timedout, Int Ctrl=%08x\n", + ddc_data->what, DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL)); - DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n", - __func__, + pr_err("DDC SW Status=%08x, HW Status=%08x\n", DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS), DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS)); goto error; @@ -1125,34 +1259,35 @@ again: DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1)); if (retry-- > 0) { - DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n", - __func__, ddc_data->what, reg_val, retry); + pr_debug("%s: failed NACK=%08x, retry=%d\n", + ddc_data->what, reg_val, retry); msleep(100); goto again; } status = -EIO; - DEV_ERR("%s[%s]: failed NACK: %08x\n", __func__, - ddc_data->what, reg_val); + pr_err("%s: failed NACK: %08x\n", ddc_data->what, reg_val); goto error; } - DEV_DBG("%s[%s] success\n", __func__, ddc_data->what); + pr_debug("%s: success\n", ddc_data->what); error: return status; } /* hdmi_ddc_write */ -int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *ddc_ctrl, - struct hdmi_tx_ddc_data *ddc_data) +int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { int status; + struct hdmi_tx_ddc_data *ddc_data; - if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) { - DEV_ERR("%s: invalid input\n", __func__); + if (!ddc_ctrl || !ddc_ctrl->io) { + pr_err("invalid input\n"); return -EINVAL; } + ddc_data = &ddc_ctrl->ddc_data; + status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what); if (status) 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}; if (!ctrl || !ctrl->io || !val) { - DEV_ERR("%s: Bad Parameters\n", __func__); + pr_err("Bad Parameters\n"); return -EINVAL; } if (data_type >= HDMI_TX_SCDC_MAX) { - DEV_ERR("%s: Unsupported data type\n", __func__); + pr_err("Unsupported data type\n"); return -EINVAL; } @@ -1230,9 +1365,11 @@ int hdmi_scdc_read(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 *val) break; } - rc = hdmi_ddc_read(ctrl, &data); + ctrl->ddc_data = data; + + rc = hdmi_ddc_read(ctrl); 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; } @@ -1285,12 +1422,12 @@ int hdmi_scdc_write(struct hdmi_tx_ddc_ctrl *ctrl, u32 data_type, u32 val) u8 read_val = 0; if (!ctrl || !ctrl->io) { - DEV_ERR("%s: Bad Parameters\n", __func__); + pr_err("Bad Parameters\n"); return -EINVAL; } if (data_type >= HDMI_TX_SCDC_MAX) { - DEV_ERR("%s: Unsupported data type\n", __func__); + pr_err("Unsupported data type\n"); 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.offset = HDMI_SCDC_TMDS_CONFIG; rdata.request_len = 1; - rc = hdmi_ddc_read(ctrl, &rdata); + ctrl->ddc_data = rdata; + rc = hdmi_ddc_read(ctrl); if (rc) { - DEV_ERR("%s: scdc read failed\n", __func__); + pr_err("scdc read failed\n"); return rc; } 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); break; 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); return -EINVAL; } - rc = hdmi_ddc_write(ctrl, &data); + ctrl->ddc_data = data; + + rc = hdmi_ddc_write(ctrl); 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; } @@ -1352,12 +1492,12 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl, u32 type, u32 to_in_num_lines) { if (!ctrl) { - DEV_ERR("%s: Invalid parameters\n", __func__); + pr_err("Invalid parameters\n"); return -EINVAL; } 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; } @@ -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); break; default: - DEV_ERR("%s: %d type not supported\n", __func__, type); + pr_err("%d type not supported\n", type); return -EINVAL; } @@ -1378,7 +1518,7 @@ void hdmi_hdcp2p2_ddc_reset(struct hdmi_tx_ddc_ctrl *ctrl) u32 reg_val; if (!ctrl) { - DEV_ERR("%s: Invalid parameters\n", __func__); + pr_err("Invalid parameters\n"); return; } @@ -1404,7 +1544,7 @@ void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl) bool ddc_hw_not_ready; if (!ctrl) { - DEV_ERR("%s: Invalid parameters\n", __func__); + pr_err("Invalid parameters\n"); 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); } -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) +int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) { u32 reg_val; - u32 reg_field_shift; - u32 reg_field_mask; - u32 reg_intr_ack_shift; - u32 reg_intr_mask_shift; + u32 intr_en_mask; u32 timeout; - u32 rxstatus_read_method; - u32 rxstatus_bytes; - bool poll_sink; + int rc = 0; + struct hdmi_tx_hdcp2p2_ddc_data *data; - if (!hdcp2p2_ddc_data) - return -EINVAL; - - /* 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: + if (!ctrl) { + pr_err("Invalid ctrl data\n"); return -EINVAL; } - DEV_DBG("%s: Requested msg size, shift %u mask %u ack %u mask %u\n", - __func__, reg_field_shift, reg_field_mask, - reg_intr_ack_shift, reg_intr_mask_shift); + data = &ctrl->hdcp2p2_ddc_data; + if (!data) { + 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 */ reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_CTRL); reg_val |= BIT(4); 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 * 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 * 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); + /* Set both urgent and hw-timeout fields to the same value */ 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 */ - reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0); - reg_val |= BIT(reg_intr_mask_shift); - reg_val |= BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK); - DEV_DBG("%s: Enabling interrupts for req field\n", __func__); + /* enable interrupts */ + reg_val = intr_en_mask; + /* Clear interrupt status bits */ + reg_val |= intr_en_mask >> 1; + + pr_debug("writng HDMI_DDC_INT_CTRL0 0x%x\n", 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 &= ~(BIT(1) | BIT(0)); - rxstatus_read_method = - poll_sink ? HDCP2P2_RXSTATUS_HW_DDC_AUTOMATIC_LOOP - : HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; + pr_debug("data->read_method %d\n", data->read_method); - if (poll_sink) - reg_val |= BIT(0); + if (data->read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER) + reg_val |= BIT(1) | BIT(0); 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); - 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 */ DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1); - /* - * Now wait for interrupt bits to be set to indicate that the - * register is available to read - */ - 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)); + reinit_completion(&ctrl->rxstatus_completion); + timeout = wait_for_completion_timeout( + &ctrl->rxstatus_completion, + 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); + if (reg_val & BIT(0)) + pr_debug("ddc busy\n"); - /* Check for NACK0, NACK1, TIMEOUT, ABORT bits */ - reg_val &= (BIT(12) | BIT(14) | BIT(4) | BIT(8)); - - if (reg_val) { - DEV_ERR("%s: DDC transaction error, hdcp2p2_ddc_status 0x%x\n", - __func__, reg_val); - return -EIO; + if (reg_val & BIT(4)) { + pr_err("ddc aborted\n"); + reg_val |= BIT(5); + rc = -ECONNABORTED; } - /* Read the RxStatus field that was requested */ - reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0); - rxstatus_bytes = reg_val; - rxstatus_bytes &= reg_field_mask; - rxstatus_bytes >>= reg_field_shift; - memcpy(hdcp2p2_ddc_data->ddc_data.data_buf, - &rxstatus_bytes, sizeof(rxstatus_bytes)); + if (reg_val & BIT(8)) { + pr_err("timed out\n"); + reg_val |= BIT(9); + rc = -ETIMEDOUT; + } - /* Read the RxStatus field that was requested */ - /* Write the interrupt ack back */ - reg_val |= BIT(reg_intr_ack_shift); - DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val); + if (reg_val & BIT(12)) { + pr_err("NACK0\n"); + reg_val |= BIT(13); + rc = -EIO; + } - /* Clear the ack bits and the DDC_FAILED bit next */ - reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL0); - reg_val &= ~BIT(reg_intr_ack_shift); - reg_val &= ~BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK); - DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val); + if (reg_val & BIT(14)) { + pr_err("NACK1\n"); + reg_val |= BIT(15); + rc = -EIO; + } - /* 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); - return 0; + /* Disable hardware access to RxStatus register */ + hdmi_hdcp2p2_ddc_disable(ctrl); + + return rc; } diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h index f1e7a8b68bf8..8f574ee5b152 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h @@ -353,6 +353,7 @@ #define HDCP2P2_RXSTATUS_DDC_FAILED_SHIFT 8 #define HDCP2P2_RXSTATUS_DDC_FAILED_ACKSHIFT 9 #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 @@ -395,11 +396,6 @@ enum hdmi_tx_ddc_timer_type { 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 { char *what; u8 *data_buf; @@ -412,20 +408,34 @@ struct hdmi_tx_ddc_data { int retry; }; -enum hdmi_tx_hdcp2p2_rxstatus_field { - RXSTATUS_MESSAGE_SIZE, - RXSTATUS_REAUTH_REQ, - RXSTATUS_READY, +enum hdmi_tx_hdcp2p2_rxstatus_intr_mask { + RXSTATUS_MESSAGE_SIZE = BIT(31), + RXSTATUS_READY = BIT(18), + RXSTATUS_REAUTH_REQ = BIT(14), }; struct hdmi_tx_hdcp2p2_ddc_data { - struct hdmi_tx_ddc_data ddc_data; - enum hdmi_tx_hdcp2p2_rxstatus_field rxstatus_field; + enum hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask; 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; }; +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 { bool ds_registered; @@ -469,11 +479,10 @@ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type); /* DDC */ void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *); 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_read_seg(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *); -int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *); -int hdmi_ddc_abort_transaction(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 *); +int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *); +int hdmi_ddc_abort_transaction(struct hdmi_tx_ddc_ctrl *); 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); @@ -481,8 +490,6 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl, u32 type, u32 to_in_num_lines); void hdmi_hdcp2p2_ddc_reset(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, - struct hdmi_tx_hdcp2p2_ddc_data *hdcp2p2_ddc_data, - struct completion *rxstatus_completion); +int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl); #endif /* __HDMI_UTIL_H__ */