msm: mdss: hdmi: propagation of content stream management info

Add support for propagating content stream related information downstream.
Send/receive repeater authentication stream manage/ready messages as per
hdcp2.2 standard.

Change-Id: I8d37f9f6d4cb131b29128222bb43c9c290c78437
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
This commit is contained in:
Ajay Singh Parmar 2015-10-05 22:33:17 -07:00 committed by David Keitel
parent bdb2680679
commit 0057829118
3 changed files with 31 additions and 30 deletions

View file

@ -337,6 +337,7 @@ struct hdcp_lib_handle {
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;
struct mutex wakeup_mutex;
enum hdcp_state hdcp_state; enum hdcp_state hdcp_state;
enum hdcp_lib_wakeup_cmd wakeup_cmd; enum hdcp_lib_wakeup_cmd wakeup_cmd;
bool repeater_flag; bool repeater_flag;
@ -356,6 +357,7 @@ struct hdcp_lib_handle {
struct kthread_work timeout; struct kthread_work timeout;
struct kthread_work clean; struct kthread_work clean;
struct kthread_work topology; struct kthread_work topology;
struct kthread_work stream;
}; };
struct hdcp_lib_message_map { struct hdcp_lib_message_map {
@ -671,30 +673,20 @@ exit:
return rc; return rc;
} }
static int hdcp_lib_query_stream_type(void *phdcpcontext) static void hdcp_lib_query_stream_type_work(struct kthread_work *work)
{ {
int rc = 0; int rc = 0;
struct hdcp_query_stream_type_req *req_buf; struct hdcp_query_stream_type_req *req_buf;
struct hdcp_query_stream_type_rsp *rsp_buf; struct hdcp_query_stream_type_rsp *rsp_buf;
struct hdcp_lib_handle *handle = phdcpcontext; struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle, stream);
if (!handle) { if (!handle) {
pr_err("invalid input\n"); pr_err("invalid handle\n");
return -EINVAL; return;
} }
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { mutex_lock(&handle->hdcp_lock);
pr_debug("hdcp library not loaded\n");
goto exit;
}
if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) {
pr_err("txmtr is not initialized\n");
rc = -EINVAL;
goto exit;
}
flush_kthread_worker(&handle->worker);
/* send command to TZ */ /* send command to TZ */
req_buf = (struct hdcp_query_stream_type_req *)handle-> req_buf = (struct hdcp_query_stream_type_req *)handle->
@ -718,7 +710,7 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext)
goto exit; goto exit;
} }
pr_debug("message received is %s\n", pr_debug("message received from TZ: %s\n",
hdcp_lib_message_name((int)rsp_buf->msg[0])); hdcp_lib_message_name((int)rsp_buf->msg[0]));
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
@ -726,15 +718,11 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext)
rsp_buf->msglen); rsp_buf->msglen);
handle->hdcp_timeout = rsp_buf->timeout; handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen; handle->msglen = rsp_buf->msglen;
if (!atomic_read(&handle->hdcp_off))
hdcp_lib_send_message(handle);
else
goto exit;
pr_debug("success\n");
exit: exit:
return rc; mutex_unlock(&handle->hdcp_lock);
if (!rc && !atomic_read(&handle->hdcp_off))
hdcp_lib_send_message(handle);
} }
static bool hdcp_lib_client_feature_supported(void *phdcpcontext) static bool hdcp_lib_client_feature_supported(void *phdcpcontext)
@ -776,6 +764,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
if (!handle) if (!handle)
return -EINVAL; return -EINVAL;
mutex_lock(&handle->wakeup_mutex);
handle->wakeup_cmd = data->cmd; handle->wakeup_cmd = data->cmd;
pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
@ -830,10 +820,15 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
if (!atomic_read(&handle->hdcp_off)) if (!atomic_read(&handle->hdcp_off))
queue_kthread_work(&handle->worker, &handle->timeout); queue_kthread_work(&handle->worker, &handle->timeout);
break; break;
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
if (!atomic_read(&handle->hdcp_off))
queue_kthread_work(&handle->worker, &handle->stream);
break;
default: default:
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
} }
exit: exit:
mutex_unlock(&handle->wakeup_mutex);
return 0; return 0;
} }
@ -1256,7 +1251,6 @@ int hdcp_library_register(void **pphdcpcontext,
/* populate ops to be called by client */ /* populate ops to be called by client */
txmtr_ops->feature_supported = hdcp_lib_client_feature_supported; txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
txmtr_ops->wakeup = hdcp_lib_wakeup; txmtr_ops->wakeup = hdcp_lib_wakeup;
txmtr_ops->hdcp_query_stream_type = hdcp_lib_query_stream_type;
handle = kzalloc(sizeof(*handle), GFP_KERNEL); handle = kzalloc(sizeof(*handle), GFP_KERNEL);
if (!handle) { if (!handle) {
@ -1270,6 +1264,7 @@ int hdcp_library_register(void **pphdcpcontext,
atomic_set(&handle->hdcp_off, 0); atomic_set(&handle->hdcp_off, 0);
mutex_init(&handle->hdcp_lock); mutex_init(&handle->hdcp_lock);
mutex_init(&handle->wakeup_mutex);
init_kthread_worker(&handle->worker); init_kthread_worker(&handle->worker);
@ -1279,6 +1274,7 @@ int hdcp_library_register(void **pphdcpcontext,
init_kthread_work(&handle->timeout, hdcp_lib_manage_timeout_work); init_kthread_work(&handle->timeout, hdcp_lib_manage_timeout_work);
init_kthread_work(&handle->clean, hdcp_lib_cleanup_work); init_kthread_work(&handle->clean, hdcp_lib_cleanup_work);
init_kthread_work(&handle->topology, hdcp_lib_topology_work); init_kthread_work(&handle->topology, hdcp_lib_topology_work);
init_kthread_work(&handle->stream, hdcp_lib_query_stream_type_work);
init_completion(&handle->topo_wait); init_completion(&handle->topo_wait);
@ -1322,6 +1318,7 @@ void hdcp_library_deregister(void *phdcpcontext)
kzfree(handle->qseecom_handle); kzfree(handle->qseecom_handle);
mutex_destroy(&handle->hdcp_lock); mutex_destroy(&handle->hdcp_lock);
mutex_destroy(&handle->wakeup_mutex);
kzfree(handle->listener_buf); kzfree(handle->listener_buf);
kzfree(handle); kzfree(handle);

View file

@ -275,7 +275,8 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev,
{ {
struct hdmi_hdcp2p2_ctrl *ctrl = struct hdmi_hdcp2p2_ctrl *ctrl =
hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2); hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2);
int res; struct hdcp_lib_wakeup_data cdata = {
HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE};
if (!ctrl) { if (!ctrl) {
pr_err("invalid input\n"); pr_err("invalid input\n");
@ -283,8 +284,9 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev,
} }
pr_debug("notification of minimum level change received\n"); pr_debug("notification of minimum level change received\n");
res = ctrl->lib->
hdcp_query_stream_type(ctrl->lib_ctx); cdata.context = ctrl->lib_ctx;
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
return count; return count;
} }

View file

@ -23,6 +23,7 @@ enum hdcp_lib_wakeup_cmd {
HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS, HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS,
HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED, HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED,
HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT, HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT,
HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE,
}; };
enum hdmi_hdcp_wakeup_cmd { enum hdmi_hdcp_wakeup_cmd {
@ -85,6 +86,8 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd)
return "HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED"; return "HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED";
case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT: case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT"; return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT";
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
return "HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE";
default: default:
return "???"; return "???";
} }
@ -96,7 +99,6 @@ struct hdcp_txmtr_ops {
int (*hdcp_txmtr_get_state)(void *phdcpcontext, int (*hdcp_txmtr_get_state)(void *phdcpcontext,
uint32_t *state); uint32_t *state);
int (*hdcp_query_stream_type)(void *phdcpcontext);
}; };
struct hdcp_client_ops { struct hdcp_client_ops {