msm: mdss: hdmi: schedule link work from isr
Do not schedule link work periodically to check for new message or authentication status. Hardware automatically poll sink for the same. Once new message is available or sink indicates re-authentication required, isr is triggered. Queue link check work from isr to avoid unnecessary software polling. Change-Id: I83c71f5151aa077e863b6578a89f6515f6497159 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
This commit is contained in:
parent
bd9d0784e8
commit
178d4d6f8b
3 changed files with 37 additions and 29 deletions
|
@ -74,8 +74,6 @@ struct hdmi_hdcp2p2_ctrl {
|
||||||
struct kthread_work send_msg;
|
struct kthread_work send_msg;
|
||||||
struct kthread_work recv_msg;
|
struct kthread_work recv_msg;
|
||||||
struct kthread_work link;
|
struct kthread_work link;
|
||||||
|
|
||||||
struct delayed_work link_check_work;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl);
|
static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl);
|
||||||
|
@ -777,8 +775,9 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
ddc_data->timeout_hsync = timeout_hsync;
|
ddc_data->timeout_hsync = timeout_hsync;
|
||||||
ddc_data->periodic_timer_hsync = timeout_hsync / 20;
|
ddc_data->periodic_timer_hsync = timeout_hsync / 20;
|
||||||
ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
||||||
|
ddc_data->wait = true;
|
||||||
|
|
||||||
rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, true);
|
rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("error reading rxstatus %d\n", rc);
|
pr_err("error reading rxstatus %d\n", rc);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -831,6 +830,19 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work)
|
||||||
hdmi_hdcp2p2_recv_msg(ctrl);
|
hdmi_hdcp2p2_recv_msg(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdmi_hdcp2p2_link_cb(void *data)
|
||||||
|
{
|
||||||
|
struct hdmi_hdcp2p2_ctrl *ctrl = data;
|
||||||
|
|
||||||
|
if (!ctrl) {
|
||||||
|
pr_err("invalid input\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE)
|
||||||
|
queue_kthread_work(&ctrl->worker, &ctrl->link);
|
||||||
|
}
|
||||||
|
|
||||||
static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
|
static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
|
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
|
||||||
|
@ -862,8 +874,10 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
ddc_data->timeout_hsync = timeout_hsync;
|
ddc_data->timeout_hsync = timeout_hsync;
|
||||||
ddc_data->periodic_timer_hsync = timeout_hsync;
|
ddc_data->periodic_timer_hsync = timeout_hsync;
|
||||||
ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER;
|
||||||
|
ddc_data->link_cb = hdmi_hdcp2p2_link_cb;
|
||||||
|
ddc_data->link_data = ctrl;
|
||||||
|
|
||||||
return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, false);
|
return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl)
|
static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
|
@ -884,8 +898,7 @@ static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
|
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
|
||||||
HDCP_STATE_AUTHENTICATED);
|
HDCP_STATE_AUTHENTICATED);
|
||||||
|
|
||||||
if (!hdmi_hdcp2p2_link_check(ctrl))
|
hdmi_hdcp2p2_link_check(ctrl);
|
||||||
queue_kthread_work(&ctrl->worker, &ctrl->link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,16 +910,6 @@ static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work)
|
||||||
hdmi_hdcp2p2_auth_status(ctrl);
|
hdmi_hdcp2p2_auth_status(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_link_schedule_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(to_delayed_work(work),
|
|
||||||
struct hdmi_hdcp2p2_ctrl, link_check_work);
|
|
||||||
|
|
||||||
if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE)
|
|
||||||
queue_kthread_work(&ctrl->worker, &ctrl->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_link_work(struct kthread_work *work)
|
static void hdmi_hdcp2p2_link_work(struct kthread_work *work)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -980,10 +983,6 @@ exit:
|
||||||
hdmi_hdcp2p2_auth_failed(ctrl);
|
hdmi_hdcp2p2_auth_failed(ctrl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recheck within 1sec as per hdcp 2.2 standard */
|
|
||||||
schedule_delayed_work(&ctrl->link_check_work,
|
|
||||||
msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl)
|
static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
|
@ -1122,9 +1121,6 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
|
||||||
ctrl->thread = kthread_run(kthread_worker_fn,
|
ctrl->thread = kthread_run(kthread_worker_fn,
|
||||||
&ctrl->worker, "hdmi_hdcp2p2");
|
&ctrl->worker, "hdmi_hdcp2p2");
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&ctrl->link_check_work,
|
|
||||||
hdmi_hdcp2p2_link_schedule_work);
|
|
||||||
|
|
||||||
if (IS_ERR(ctrl->thread)) {
|
if (IS_ERR(ctrl->thread)) {
|
||||||
pr_err("unable to start hdcp2p2 thread\n");
|
pr_err("unable to start hdcp2p2 thread\n");
|
||||||
rc = PTR_ERR(ctrl->thread);
|
rc = PTR_ERR(ctrl->thread);
|
||||||
|
|
|
@ -919,6 +919,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
struct hdmi_tx_hdcp2p2_ddc_data *data;
|
struct hdmi_tx_hdcp2p2_ddc_data *data;
|
||||||
u32 intr0, intr2, intr5;
|
u32 intr0, intr2, intr5;
|
||||||
u32 msg_size;
|
u32 msg_size;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
if (!ddc_ctrl || !ddc_ctrl->io) {
|
if (!ddc_ctrl || !ddc_ctrl->io) {
|
||||||
pr_err("invalid input\n");
|
pr_err("invalid input\n");
|
||||||
|
@ -1041,10 +1042,18 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
}
|
}
|
||||||
DSS_REG_W_ND(io, HDMI_DDC_INT_CTRL5, intr5);
|
DSS_REG_W_ND(io, HDMI_DDC_INT_CTRL5, intr5);
|
||||||
|
|
||||||
if (data->message_size || data->ready || data->reauth_req)
|
if (data->message_size || data->ready || data->reauth_req) {
|
||||||
|
if (data->wait) {
|
||||||
atomic_set(&ddc_ctrl->rxstatus_busy_wait_done, 1);
|
atomic_set(&ddc_ctrl->rxstatus_busy_wait_done, 1);
|
||||||
|
} else if (data->link_cb && data->link_data) {
|
||||||
|
data->link_cb(data->link_data);
|
||||||
|
} else {
|
||||||
|
pr_err("new msg/reauth not handled\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdmi_ddc_scrambling_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
static int hdmi_ddc_scrambling_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
|
||||||
|
@ -1605,7 +1614,7 @@ 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, bool wait)
|
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
u32 reg_val;
|
u32 reg_val;
|
||||||
u32 intr_en_mask;
|
u32 intr_en_mask;
|
||||||
|
@ -1704,7 +1713,7 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait)
|
||||||
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
DSS_REG_W(ctrl->io, HDMI_HW_DDC_CTRL, reg_val);
|
||||||
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1);
|
DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1);
|
||||||
|
|
||||||
if (wait) {
|
if (data->wait) {
|
||||||
while (busy_wait_us > 0 &&
|
while (busy_wait_us > 0 &&
|
||||||
!atomic_read(&ctrl->rxstatus_busy_wait_done)) {
|
!atomic_read(&ctrl->rxstatus_busy_wait_done)) {
|
||||||
udelay(HDMI_BUSY_WAIT_DELAY_US);
|
udelay(HDMI_BUSY_WAIT_DELAY_US);
|
||||||
|
|
|
@ -433,7 +433,10 @@ struct hdmi_tx_hdcp2p2_ddc_data {
|
||||||
bool ddc_done;
|
bool ddc_done;
|
||||||
bool ddc_read_req;
|
bool ddc_read_req;
|
||||||
bool ddc_timeout;
|
bool ddc_timeout;
|
||||||
|
bool wait;
|
||||||
int irq_wait_count;
|
int irq_wait_count;
|
||||||
|
void (*link_cb)(void *data);
|
||||||
|
void *link_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hdmi_tx_ddc_ctrl {
|
struct hdmi_tx_ddc_ctrl {
|
||||||
|
@ -500,8 +503,8 @@ 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_scrambler_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl);
|
void hdmi_scrambler_ddc_disable(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, bool wait);
|
|
||||||
int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl);
|
int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl);
|
||||||
|
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl);
|
||||||
int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing,
|
int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing,
|
||||||
u32 timeout_ms);
|
u32 timeout_ms);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue