&drm_amhdmitx {
status = "okay";
- hdcp = "disabled";
+ hdcp = "okay";
};
&drm_lcd {
&drm_amhdmitx {
status = "okay";
- hdcp = "disabled";
+ hdcp = "okay";
};
&drm_lcd {
#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>
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;
-
- while (hdcp_fsm) {
- if (am_hdmi->hdcp_stop_flag)
- hdcp_fsm = HDCP_QUIT;
+ hdcp_feature = HDCP14_ENABLE;
+
+ 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");
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);
hdcp_fsm = HDCP_QUIT;
break;
}
+ DRM_INFO("hdcp14 work start");
am_hdcp14_enable(am_hdmi);
msleep_interruptible(500);
hdcp_fsm = HDCP14_AUTH;
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);
#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);
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)
{
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;
{
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");
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)
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;
}
#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>
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;
-
- while (hdcp_fsm) {
- if (am_hdmi->hdcp_stop_flag)
- hdcp_fsm = HDCP_QUIT;
+ hdcp_feature = HDCP14_ENABLE;
+
+ 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");
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);
hdcp_fsm = HDCP_QUIT;
break;
}
+ DRM_INFO("hdcp14 work start");
am_hdcp14_enable(am_hdmi);
msleep_interruptible(500);
hdcp_fsm = HDCP14_AUTH;
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);
#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);
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)
{
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;
{
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");
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)
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;
}