mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
drm: start hdcp work when the "Content Protection" was set thought atomic [1/1]
PD#SWPL-4866 Problem: 1. The old implement not support atomic. (the atomic check on am_meson hdmi.c will disable CP,The set property function will not reached when use atomic set CP) 2. The hdcp work kthread start and terminal not match cause coredump. Problem: need add hdcp function. Solution: Start hdcp work when the encoder enabled.stop when encoder disabled. modified hdcp work state machine. Verify: On u212 drm backend, use drm-helper-client to set CP property. need enable atomic on wayland.based on below CL http://scgit.amlogic.com:8080/#/c/78810/1 http://scgit.amlogic.com:8080/#/c/78804/2 http://scgit.amlogic.com:8080/#/c/78811/1 Change-Id: If213b7def89ff1f1ec63b866a21a3323e098786f Signed-off-by: lingjie li <lingjie.li@amlogic.com>
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/amlogic/media/vout/vout_notify.h>
|
||||
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
|
||||
@@ -300,21 +301,38 @@ int am_hdcp22_auth(struct am_hdmi_tx *am_hdmi)
|
||||
int am_hdcp_work(void *data)
|
||||
{
|
||||
struct am_hdmi_tx *am_hdmi = data;
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
int hdcp_fsm = 0;
|
||||
struct drm_connector *conn = &(am_hdmi->connector);
|
||||
int hdcp_fsm = HDCP_READY;
|
||||
int hdcp_feature = 0;
|
||||
|
||||
DRM_INFO("start hdcp work CP=%u\n", conn->state->content_protection);
|
||||
is_hdcp_hdmirx_supported(am_hdmi);
|
||||
if ((am_hdmi->hdcp_tx_type & 0x2) &&
|
||||
(am_hdmi->hdcp_rx_type & 0x2))
|
||||
hdcp_fsm = HDCP22_ENABLE;
|
||||
hdcp_feature = HDCP22_ENABLE;
|
||||
else
|
||||
hdcp_fsm = HDCP14_ENABLE;
|
||||
hdcp_feature = HDCP14_ENABLE;
|
||||
|
||||
while (hdcp_fsm) {
|
||||
if (am_hdmi->hdcp_stop_flag)
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
do {
|
||||
/* The state ptr will update pre atomic commit */
|
||||
if (conn->state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
if (hdcp_fsm != HDCP_READY) {
|
||||
hdcp_fsm = HDCP_READY;
|
||||
DRM_INFO("HDCP status reset!\n");
|
||||
}
|
||||
} else if (hdcp_fsm == HDCP_READY) {
|
||||
hdcp_fsm = hdcp_feature;
|
||||
}
|
||||
if (hdcp_fsm == HDCP_QUIT)
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
|
||||
switch (hdcp_fsm) {
|
||||
case HDCP_READY:
|
||||
/* wait for content_protection change */
|
||||
msleep_interruptible(5000);
|
||||
break;
|
||||
case HDCP22_ENABLE:
|
||||
am_hdcp22_enable(am_hdmi);
|
||||
DRM_INFO("hdcp22 work after 10s\n");
|
||||
@@ -329,16 +347,13 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP22_FAIL;
|
||||
break;
|
||||
case HDCP22_SUCCESS:
|
||||
state->content_protection =
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
DRM_DEBUG("hdcp22 is authenticated successfully\n");
|
||||
hdcp_fsm = HDCP22_AUTH;
|
||||
msleep_interruptible(200);
|
||||
break;
|
||||
case HDCP22_FAIL:
|
||||
am_hdcp22_disable(am_hdmi);
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
DRM_INFO("hdcp22 failure and start hdcp14\n");
|
||||
hdcp_fsm = HDCP14_ENABLE;
|
||||
msleep_interruptible(2000);
|
||||
@@ -348,6 +363,7 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
break;
|
||||
}
|
||||
DRM_INFO("hdcp14 work start");
|
||||
am_hdcp14_enable(am_hdmi);
|
||||
msleep_interruptible(500);
|
||||
hdcp_fsm = HDCP14_AUTH;
|
||||
@@ -359,24 +375,22 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP14_FAIL;
|
||||
break;
|
||||
case HDCP14_SUCCESS:
|
||||
state->content_protection =
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
DRM_DEBUG("hdcp14 is authenticated successfully\n");
|
||||
hdcp_fsm = HDCP14_AUTH;
|
||||
msleep_interruptible(200);
|
||||
break;
|
||||
case HDCP14_FAIL:
|
||||
am_hdcp14_disable(am_hdmi);
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
DRM_DEBUG("hdcp14 failure\n");
|
||||
DRM_INFO("hdcp14 failure\n");
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
break;
|
||||
case HDCP_QUIT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!kthread_should_stop());
|
||||
DRM_INFO("hdcp worker stopped\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(am_hdcp_work);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define HDCP22_AUTH 6
|
||||
#define HDCP22_SUCCESS 7
|
||||
#define HDCP22_FAIL 8
|
||||
#define HDCP_READY 9
|
||||
|
||||
int am_hdcp_init(struct am_hdmi_tx *am_hdmi);
|
||||
int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi);
|
||||
|
||||
@@ -179,6 +179,29 @@ static enum drm_connector_status am_hdmi_connector_detect
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
void am_hdmi_hdcp_work_state_change(struct am_hdmi_tx *am_hdmi, int stop)
|
||||
{
|
||||
if (am_hdmi->hdcp_tx_type == 0) {
|
||||
DRM_INFO("hdcp not support\n");
|
||||
return;
|
||||
}
|
||||
if (am_hdmi->hdcp_work == NULL && stop != 1) {
|
||||
am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
|
||||
(void *)am_hdmi, "kthread_hdcp_task");
|
||||
if (IS_ERR(am_hdmi->hdcp_work)) {
|
||||
DRM_INFO("hdcp work create failed\n");
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (am_hdmi->hdcp_work != NULL && stop == 1) {
|
||||
DRM_INFO("stop hdcp work\n");
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
am_hdcp_disable(am_hdmi);
|
||||
}
|
||||
}
|
||||
|
||||
static int am_hdmi_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property, uint64_t val)
|
||||
{
|
||||
@@ -187,6 +210,8 @@ static int am_hdmi_connector_set_property(struct drm_connector *connector,
|
||||
|
||||
if (property == connector->content_protection_property) {
|
||||
DRM_INFO("property:%s val: %lld\n", property->name, val);
|
||||
/* For none atomic commit */
|
||||
/* atomic will be filter on drm_moder_object.c */
|
||||
if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
|
||||
return -EINVAL;
|
||||
@@ -266,7 +291,6 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
enum vmode_e vmode = get_current_vmode();
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
|
||||
if (vmode == VMODE_HDMI)
|
||||
DRM_INFO("am_hdmi_encoder_enable\n");
|
||||
@@ -276,16 +300,9 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
|
||||
set_vout_vmode(vmode);
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
mdelay(1000);
|
||||
if (state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED) {
|
||||
if (am_hdmi->hdcp_tx_type) {
|
||||
am_hdmi->hdcp_stop_flag = 0;
|
||||
am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
|
||||
(void *)am_hdmi, "kthread_hdcp_task");
|
||||
} else
|
||||
DRM_INFO("hdmitx doesn't has hdcp key\n");
|
||||
}
|
||||
am_hdmi_hdcp_work_state_change(am_hdmi, 0);
|
||||
}
|
||||
|
||||
void am_hdmi_encoder_disable(struct drm_encoder *encoder)
|
||||
@@ -293,32 +310,15 @@ void am_hdmi_encoder_disable(struct drm_encoder *encoder)
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
|
||||
/*need to add hdmitx disable function ..todo*/
|
||||
if (state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
am_hdmi->hdcp_stop_flag = 1;
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdcp_disable(am_hdmi);
|
||||
}
|
||||
state->content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
am_hdmi_hdcp_work_state_change(am_hdmi, 1);
|
||||
|
||||
}
|
||||
|
||||
static int am_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
|
||||
DRM_INFO("content_protection:%d\n", conn_state->content_protection);
|
||||
|
||||
if (conn_state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdcp_disable(am_hdmi);
|
||||
conn_state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/amlogic/media/vout/vout_notify.h>
|
||||
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
|
||||
@@ -300,21 +301,38 @@ int am_hdcp22_auth(struct am_hdmi_tx *am_hdmi)
|
||||
int am_hdcp_work(void *data)
|
||||
{
|
||||
struct am_hdmi_tx *am_hdmi = data;
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
int hdcp_fsm = 0;
|
||||
struct drm_connector *conn = &(am_hdmi->connector);
|
||||
int hdcp_fsm = HDCP_READY;
|
||||
int hdcp_feature = 0;
|
||||
|
||||
DRM_INFO("start hdcp work CP=%u\n", conn->state->content_protection);
|
||||
is_hdcp_hdmirx_supported(am_hdmi);
|
||||
if ((am_hdmi->hdcp_tx_type & 0x2) &&
|
||||
(am_hdmi->hdcp_rx_type & 0x2))
|
||||
hdcp_fsm = HDCP22_ENABLE;
|
||||
hdcp_feature = HDCP22_ENABLE;
|
||||
else
|
||||
hdcp_fsm = HDCP14_ENABLE;
|
||||
hdcp_feature = HDCP14_ENABLE;
|
||||
|
||||
while (hdcp_fsm) {
|
||||
if (am_hdmi->hdcp_stop_flag)
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
do {
|
||||
/* The state ptr will update pre atomic commit */
|
||||
if (conn->state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
if (hdcp_fsm != HDCP_READY) {
|
||||
hdcp_fsm = HDCP_READY;
|
||||
DRM_INFO("HDCP status reset!\n");
|
||||
}
|
||||
} else if (hdcp_fsm == HDCP_READY) {
|
||||
hdcp_fsm = hdcp_feature;
|
||||
}
|
||||
if (hdcp_fsm == HDCP_QUIT)
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
|
||||
switch (hdcp_fsm) {
|
||||
case HDCP_READY:
|
||||
/* wait for content_protection change. */
|
||||
msleep_interruptible(5000);
|
||||
break;
|
||||
case HDCP22_ENABLE:
|
||||
am_hdcp22_enable(am_hdmi);
|
||||
DRM_INFO("hdcp22 work after 10s\n");
|
||||
@@ -329,16 +347,13 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP22_FAIL;
|
||||
break;
|
||||
case HDCP22_SUCCESS:
|
||||
state->content_protection =
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
DRM_DEBUG("hdcp22 is authenticated successfully\n");
|
||||
hdcp_fsm = HDCP22_AUTH;
|
||||
msleep_interruptible(200);
|
||||
break;
|
||||
case HDCP22_FAIL:
|
||||
am_hdcp22_disable(am_hdmi);
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
DRM_INFO("hdcp22 failure and start hdcp14\n");
|
||||
hdcp_fsm = HDCP14_ENABLE;
|
||||
msleep_interruptible(2000);
|
||||
@@ -348,6 +363,7 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
break;
|
||||
}
|
||||
DRM_INFO("hdcp14 work start");
|
||||
am_hdcp14_enable(am_hdmi);
|
||||
msleep_interruptible(500);
|
||||
hdcp_fsm = HDCP14_AUTH;
|
||||
@@ -359,24 +375,22 @@ int am_hdcp_work(void *data)
|
||||
hdcp_fsm = HDCP14_FAIL;
|
||||
break;
|
||||
case HDCP14_SUCCESS:
|
||||
state->content_protection =
|
||||
conn->state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
DRM_DEBUG("hdcp14 is authenticated successfully\n");
|
||||
hdcp_fsm = HDCP14_AUTH;
|
||||
msleep_interruptible(200);
|
||||
break;
|
||||
case HDCP14_FAIL:
|
||||
am_hdcp14_disable(am_hdmi);
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
DRM_DEBUG("hdcp14 failure\n");
|
||||
DRM_INFO("hdcp14 failure\n");
|
||||
hdcp_fsm = HDCP_QUIT;
|
||||
break;
|
||||
case HDCP_QUIT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!kthread_should_stop());
|
||||
DRM_INFO("hdcp worker stopped\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(am_hdcp_work);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define HDCP22_AUTH 6
|
||||
#define HDCP22_SUCCESS 7
|
||||
#define HDCP22_FAIL 8
|
||||
#define HDCP_READY 9
|
||||
|
||||
int am_hdcp_init(struct am_hdmi_tx *am_hdmi);
|
||||
int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi);
|
||||
|
||||
@@ -179,6 +179,29 @@ static enum drm_connector_status am_hdmi_connector_detect
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
void am_hdmi_hdcp_work_state_change(struct am_hdmi_tx *am_hdmi, int stop)
|
||||
{
|
||||
if (am_hdmi->hdcp_tx_type == 0) {
|
||||
DRM_INFO("hdcp not support\n");
|
||||
return;
|
||||
}
|
||||
if (am_hdmi->hdcp_work == NULL && stop != 1) {
|
||||
am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
|
||||
(void *)am_hdmi, "kthread_hdcp_task");
|
||||
if (IS_ERR(am_hdmi->hdcp_work)) {
|
||||
DRM_INFO("hdcp work create failed\n");
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (am_hdmi->hdcp_work != NULL && stop == 1) {
|
||||
DRM_INFO("stop hdcp work\n");
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
am_hdcp_disable(am_hdmi);
|
||||
}
|
||||
}
|
||||
|
||||
static int am_hdmi_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property, uint64_t val)
|
||||
{
|
||||
@@ -187,6 +210,8 @@ static int am_hdmi_connector_set_property(struct drm_connector *connector,
|
||||
|
||||
if (property == connector->content_protection_property) {
|
||||
DRM_INFO("property:%s val: %lld\n", property->name, val);
|
||||
/* For none atomic commit */
|
||||
/* atomic will be filter on drm_moder_object.c */
|
||||
if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
|
||||
return -EINVAL;
|
||||
@@ -266,7 +291,6 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
enum vmode_e vmode = get_current_vmode();
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
|
||||
if (vmode == VMODE_HDMI)
|
||||
DRM_INFO("enable\n");
|
||||
@@ -276,18 +300,9 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
|
||||
set_vout_vmode(vmode);
|
||||
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
|
||||
am_hdmi->hdcp_work = NULL;
|
||||
mdelay(1000);
|
||||
if (state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED) {
|
||||
if (am_hdmi->hdcp_tx_type) {
|
||||
am_hdmi->hdcp_stop_flag = 0;
|
||||
am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
|
||||
(void *)am_hdmi,
|
||||
"kthread_hdcp_task");
|
||||
} else {
|
||||
DRM_INFO("hdmitx doesn't has hdcp key\n");
|
||||
}
|
||||
}
|
||||
am_hdmi_hdcp_work_state_change(am_hdmi, 0);
|
||||
}
|
||||
|
||||
void am_hdmi_encoder_disable(struct drm_encoder *encoder)
|
||||
@@ -295,32 +310,15 @@ void am_hdmi_encoder_disable(struct drm_encoder *encoder)
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
struct drm_connector_state *state = am_hdmi->connector.state;
|
||||
|
||||
/*need to add hdmitx disable function ..todo*/
|
||||
if (state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
am_hdmi->hdcp_stop_flag = 1;
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdcp_disable(am_hdmi);
|
||||
}
|
||||
state->content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
am_hdmi_hdcp_work_state_change(am_hdmi, 1);
|
||||
|
||||
}
|
||||
|
||||
static int am_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
|
||||
|
||||
DRM_INFO("content_protection:%d\n", conn_state->content_protection);
|
||||
|
||||
if (conn_state->content_protection ==
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
kthread_stop(am_hdmi->hdcp_work);
|
||||
am_hdcp_disable(am_hdmi);
|
||||
conn_state->content_protection =
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user