Merge "msm: mdss: dp: fix HBR2 pattern generation"
This commit is contained in:
commit
252a3a5bb6
16 changed files with 2318 additions and 562 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -559,6 +559,7 @@ static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle);
|
|||
static struct qseecom_handle *hdcp1_handle;
|
||||
static bool hdcp1_supported = true;
|
||||
static bool hdcp1_enc_enabled;
|
||||
static struct mutex hdcp1_ta_cmd_lock;
|
||||
|
||||
static const char *hdcp_lib_message_name(int msg_id)
|
||||
{
|
||||
|
@ -805,8 +806,8 @@ static int hdcp_lib_get_version(struct hdcp_lib_handle *handle)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
|
||||
pr_err("library already loaded\n");
|
||||
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
|
||||
pr_err("library not loaded\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -901,8 +902,8 @@ static int hdcp_app_init_legacy(struct hdcp_lib_handle *handle)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
|
||||
pr_err("library already loaded\n");
|
||||
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
|
||||
pr_err("library not loaded\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -949,8 +950,8 @@ static int hdcp_app_init(struct hdcp_lib_handle *handle)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
|
||||
pr_err("library already loaded\n");
|
||||
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
|
||||
pr_err("library not loaded\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1024,6 +1025,7 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
handle->hdcp_state |= HDCP_STATE_APP_LOADED;
|
||||
pr_debug("qseecom_start_app success\n");
|
||||
|
||||
rc = hdcp_lib_get_version(handle);
|
||||
|
@ -1050,8 +1052,6 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
|
|||
pr_err("app init failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
handle->hdcp_state |= HDCP_STATE_APP_LOADED;
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
@ -1240,8 +1240,8 @@ static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (handle->hdcp_state & HDCP_STATE_TXMTR_INIT) {
|
||||
pr_err("txmtr already initialized\n");
|
||||
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
|
||||
pr_err("library not loaded\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1622,6 +1622,12 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle)
|
|||
rc = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (handle->hdcp_state & HDCP_STATE_APP_LOADED) {
|
||||
pr_debug("library already loaded\n");
|
||||
rc = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
if (atomic_read(&handle->hdcp_off)) {
|
||||
pr_debug("hdcp2.2 session tearing down\n");
|
||||
|
@ -2212,6 +2218,8 @@ bool hdcp1_check_if_supported_load_app(void)
|
|||
if (rc) {
|
||||
pr_err("qseecom_start_app failed %d\n", rc);
|
||||
hdcp1_supported = false;
|
||||
} else {
|
||||
mutex_init(&hdcp1_ta_cmd_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2276,12 +2284,16 @@ int hdcp1_set_enc(bool enable)
|
|||
struct hdcp1_set_enc_req *set_enc_req;
|
||||
struct hdcp1_set_enc_rsp *set_enc_rsp;
|
||||
|
||||
if (!hdcp1_supported || !hdcp1_handle)
|
||||
return -EINVAL;
|
||||
mutex_lock(&hdcp1_ta_cmd_lock);
|
||||
|
||||
if (!hdcp1_supported || !hdcp1_handle) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (hdcp1_enc_enabled == enable) {
|
||||
pr_debug("already %s\n", enable ? "enabled" : "disabled");
|
||||
return rc;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* set keys and request aksv */
|
||||
|
@ -2299,18 +2311,21 @@ int hdcp1_set_enc(bool enable)
|
|||
|
||||
if (rc < 0) {
|
||||
pr_err("qseecom cmd failed err=%d\n", rc);
|
||||
return -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = set_enc_rsp->ret;
|
||||
if (rc) {
|
||||
pr_err("enc cmd failed, rsp=%d\n", set_enc_rsp->ret);
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
hdcp1_enc_enabled = enable;
|
||||
pr_debug("%s success\n", enable ? "enable" : "disable");
|
||||
return 0;
|
||||
end:
|
||||
mutex_unlock(&hdcp1_ta_cmd_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hdcp_library_register(struct hdcp_register_data *data)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -269,6 +269,32 @@ struct dpcd_test_request {
|
|||
u32 test_link_rate;
|
||||
u32 test_lane_count;
|
||||
u32 phy_test_pattern_sel;
|
||||
u32 test_video_pattern;
|
||||
u32 test_bit_depth;
|
||||
u32 test_dyn_range;
|
||||
u32 test_h_total;
|
||||
u32 test_v_total;
|
||||
u32 test_h_start;
|
||||
u32 test_v_start;
|
||||
u32 test_hsync_pol;
|
||||
u32 test_hsync_width;
|
||||
u32 test_vsync_pol;
|
||||
u32 test_vsync_width;
|
||||
u32 test_h_width;
|
||||
u32 test_v_height;
|
||||
u32 test_rr_d;
|
||||
u32 test_rr_n;
|
||||
u32 test_audio_sampling_rate;
|
||||
u32 test_audio_channel_count;
|
||||
u32 test_audio_pattern_type;
|
||||
u32 test_audio_period_ch_1;
|
||||
u32 test_audio_period_ch_2;
|
||||
u32 test_audio_period_ch_3;
|
||||
u32 test_audio_period_ch_4;
|
||||
u32 test_audio_period_ch_5;
|
||||
u32 test_audio_period_ch_6;
|
||||
u32 test_audio_period_ch_7;
|
||||
u32 test_audio_period_ch_8;
|
||||
u32 response;
|
||||
};
|
||||
|
||||
|
@ -376,6 +402,28 @@ struct dp_hdcp {
|
|||
bool feature_enabled;
|
||||
};
|
||||
|
||||
struct mdss_dp_event {
|
||||
struct mdss_dp_drv_pdata *dp;
|
||||
u32 id;
|
||||
};
|
||||
|
||||
#define MDSS_DP_EVENT_Q_MAX 4
|
||||
|
||||
struct mdss_dp_event_data {
|
||||
wait_queue_head_t event_q;
|
||||
u32 pndx;
|
||||
u32 gndx;
|
||||
struct mdss_dp_event event_list[MDSS_DP_EVENT_Q_MAX];
|
||||
spinlock_t event_lock;
|
||||
};
|
||||
|
||||
struct mdss_dp_crc_data {
|
||||
bool en;
|
||||
u32 r_cr;
|
||||
u32 g_y;
|
||||
u32 b_cb;
|
||||
};
|
||||
|
||||
struct mdss_dp_drv_pdata {
|
||||
/* device driver */
|
||||
int (*on) (struct mdss_panel_data *pdata);
|
||||
|
@ -402,6 +450,7 @@ struct mdss_dp_drv_pdata {
|
|||
bool sink_info_read;
|
||||
bool hpd;
|
||||
bool psm_enabled;
|
||||
bool audio_test_req;
|
||||
|
||||
/* dp specific */
|
||||
unsigned char *base;
|
||||
|
@ -413,8 +462,11 @@ struct mdss_dp_drv_pdata {
|
|||
struct dss_io_data hdcp_io;
|
||||
int base_size;
|
||||
unsigned char *mmss_cc_base;
|
||||
bool override_config;
|
||||
u32 mask1;
|
||||
u32 mask2;
|
||||
struct mdss_dp_crc_data ctl_crc;
|
||||
struct mdss_dp_crc_data sink_crc;
|
||||
|
||||
struct mdss_panel_data panel_data;
|
||||
struct mdss_util_intf *mdss_util;
|
||||
|
@ -451,7 +503,6 @@ struct mdss_dp_drv_pdata {
|
|||
|
||||
/* aux */
|
||||
struct completion aux_comp;
|
||||
struct completion train_comp;
|
||||
struct completion idle_comp;
|
||||
struct completion video_comp;
|
||||
struct completion irq_comp;
|
||||
|
@ -478,18 +529,15 @@ struct mdss_dp_drv_pdata {
|
|||
char tu_desired;
|
||||
char valid_boundary;
|
||||
char delay_start;
|
||||
u32 bpp;
|
||||
struct dp_statistic dp_stat;
|
||||
bool hpd_irq_on;
|
||||
bool hpd_irq_toggled;
|
||||
bool hpd_irq_clients_notified;
|
||||
u32 hpd_notification_status;
|
||||
|
||||
struct mdss_dp_event_data dp_event;
|
||||
struct task_struct *ev_thread;
|
||||
|
||||
/* event */
|
||||
struct workqueue_struct *workq;
|
||||
struct work_struct work;
|
||||
struct delayed_work hdcp_cb_work;
|
||||
u32 current_event;
|
||||
spinlock_t event_lock;
|
||||
spinlock_t lock;
|
||||
struct switch_dev sdev;
|
||||
struct kobject *kobj;
|
||||
|
@ -512,6 +560,55 @@ enum dp_lane_count {
|
|||
DP_LANE_COUNT_4 = 4,
|
||||
};
|
||||
|
||||
enum audio_pattern_type {
|
||||
AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00,
|
||||
AUDIO_TEST_PATTERN_SAWTOOTH = 0x01,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_get_audio_test_pattern(u32 pattern)
|
||||
{
|
||||
switch (pattern) {
|
||||
case AUDIO_TEST_PATTERN_OPERATOR_DEFINED:
|
||||
return DP_ENUM_STR(AUDIO_TEST_PATTERN_OPERATOR_DEFINED);
|
||||
case AUDIO_TEST_PATTERN_SAWTOOTH:
|
||||
return DP_ENUM_STR(AUDIO_TEST_PATTERN_SAWTOOTH);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
enum audio_sample_rate {
|
||||
AUDIO_SAMPLE_RATE_32_KHZ = 0x00,
|
||||
AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01,
|
||||
AUDIO_SAMPLE_RATE_48_KHZ = 0x02,
|
||||
AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03,
|
||||
AUDIO_SAMPLE_RATE_96_KHZ = 0x04,
|
||||
AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05,
|
||||
AUDIO_SAMPLE_RATE_192_KHZ = 0x06,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_get_audio_sample_rate(u32 rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case AUDIO_SAMPLE_RATE_32_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_32_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_44_1_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_44_1_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_48_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_48_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_88_2_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_88_2_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_96_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_96_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_176_4_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_176_4_KHZ);
|
||||
case AUDIO_SAMPLE_RATE_192_KHZ:
|
||||
return DP_ENUM_STR(AUDIO_SAMPLE_RATE_192_KHZ);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
enum phy_test_pattern {
|
||||
PHY_TEST_PATTERN_NONE,
|
||||
PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING,
|
||||
|
@ -608,17 +705,22 @@ static inline char *mdss_dp_get_test_response(u32 test_response)
|
|||
|
||||
enum test_type {
|
||||
UNKNOWN_TEST = 0,
|
||||
TEST_LINK_TRAINING = BIT(0),
|
||||
PHY_TEST_PATTERN = BIT(3),
|
||||
TEST_EDID_READ = BIT(2),
|
||||
TEST_LINK_TRAINING = 0x1,
|
||||
TEST_VIDEO_PATTERN = 0x2,
|
||||
PHY_TEST_PATTERN = 0x8,
|
||||
TEST_EDID_READ = 0x4,
|
||||
TEST_AUDIO_PATTERN = 32,
|
||||
TEST_AUDIO_DISABLED_VIDEO = 64,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_get_test_name(u32 test_requested)
|
||||
{
|
||||
switch (test_requested) {
|
||||
case TEST_LINK_TRAINING: return DP_ENUM_STR(TEST_LINK_TRAINING);
|
||||
case TEST_VIDEO_PATTERN: return DP_ENUM_STR(TEST_VIDEO_PATTERN);
|
||||
case PHY_TEST_PATTERN: return DP_ENUM_STR(PHY_TEST_PATTERN);
|
||||
case TEST_EDID_READ: return DP_ENUM_STR(TEST_EDID_READ);
|
||||
case TEST_AUDIO_PATTERN: return DP_ENUM_STR(TEST_AUDIO_PATTERN);
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
@ -661,11 +763,252 @@ static inline char *mdss_dp_ev_event_to_string(int event)
|
|||
return DP_ENUM_STR(EV_IDLE_PATTERNS_SENT);
|
||||
case EV_VIDEO_READY:
|
||||
return DP_ENUM_STR(EV_VIDEO_READY);
|
||||
case EV_USBPD_DISCOVER_MODES:
|
||||
return DP_ENUM_STR(EV_USBPD_DISCOVER_MODES);
|
||||
case EV_USBPD_ENTER_MODE:
|
||||
return DP_ENUM_STR(EV_USBPD_ENTER_MODE);
|
||||
case EV_USBPD_DP_STATUS:
|
||||
return DP_ENUM_STR(EV_USBPD_DP_STATUS);
|
||||
case EV_USBPD_DP_CONFIGURE:
|
||||
return DP_ENUM_STR(EV_USBPD_DP_CONFIGURE);
|
||||
case EV_USBPD_CC_PIN_POLARITY:
|
||||
return DP_ENUM_STR(EV_USBPD_CC_PIN_POLARITY);
|
||||
case EV_USBPD_EXIT_MODE:
|
||||
return DP_ENUM_STR(EV_USBPD_EXIT_MODE);
|
||||
case EV_USBPD_ATTENTION:
|
||||
return DP_ENUM_STR(EV_USBPD_ATTENTION);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
enum dynamic_range {
|
||||
DP_DYNAMIC_RANGE_RGB_VESA = 0x00,
|
||||
DP_DYNAMIC_RANGE_RGB_CEA = 0x01,
|
||||
DP_DYNAMIC_RANGE_UNKNOWN = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_dynamic_range_to_string(u32 dr)
|
||||
{
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_VESA);
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
return DP_ENUM_STR(DP_DYNAMIC_RANGE_RGB_CEA);
|
||||
case DP_DYNAMIC_RANGE_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_dynamic_range_valid() - validates the dynamic range
|
||||
* @bit_depth: the dynamic range value to be checked
|
||||
*
|
||||
* Returns true if the dynamic range value is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_dynamic_range_valid(u32 dr)
|
||||
{
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum test_bit_depth {
|
||||
DP_TEST_BIT_DEPTH_6 = 0x00,
|
||||
DP_TEST_BIT_DEPTH_8 = 0x01,
|
||||
DP_TEST_BIT_DEPTH_10 = 0x02,
|
||||
DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_test_bit_depth_to_string(u32 tbd)
|
||||
{
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_6);
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_8);
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
return DP_ENUM_STR(DP_TEST_BIT_DEPTH_10);
|
||||
case DP_TEST_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_test_bit_depth_valid() - validates the bit depth requested
|
||||
* @bit_depth: bit depth requested by the sink
|
||||
*
|
||||
* Returns true if the requested bit depth is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_test_bit_depth_valid(u32 tbd)
|
||||
{
|
||||
/* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
|
||||
* @tbd: test bit depth
|
||||
*
|
||||
* Returns the bits per pixel (bpp) to be used corresponding to the
|
||||
* git bit depth value. This function assumes that bit depth has
|
||||
* already been validated.
|
||||
*/
|
||||
static inline u32 mdss_dp_test_bit_depth_to_bpp(enum test_bit_depth tbd)
|
||||
{
|
||||
u32 bpp;
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
* 1. Bit depth is per color component
|
||||
* 2. If bit depth is unknown return 0
|
||||
* 3. Assume 3 color components
|
||||
*/
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
bpp = 18;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
bpp = 24;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
bpp = 30;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
bpp = 0;
|
||||
}
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_bpp_to_test_bit_depth() - convert bpp to test bit depth
|
||||
* &bpp: the bpp to be converted
|
||||
*
|
||||
* Return the bit depth per color component to used with the video
|
||||
* test pattern data based on the bits per pixel value.
|
||||
*/
|
||||
static inline u32 mdss_dp_bpp_to_test_bit_depth(u32 bpp)
|
||||
{
|
||||
enum test_bit_depth tbd;
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
* 1. Test bit depth is bit depth per color component
|
||||
* 2. Assume 3 color components
|
||||
*/
|
||||
switch (bpp) {
|
||||
case 18:
|
||||
tbd = DP_TEST_BIT_DEPTH_6;
|
||||
break;
|
||||
case 24:
|
||||
tbd = DP_TEST_BIT_DEPTH_8;
|
||||
break;
|
||||
case 30:
|
||||
tbd = DP_TEST_BIT_DEPTH_10;
|
||||
break;
|
||||
default:
|
||||
tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return tbd;
|
||||
}
|
||||
|
||||
enum test_video_pattern {
|
||||
DP_TEST_VIDEO_PATTERN_NONE = 0x00,
|
||||
DP_TEST_VIDEO_PATTERN_COLOR_RAMPS = 0x01,
|
||||
DP_TEST_VIDEO_PATTERN_BW_VERT_LINES = 0x02,
|
||||
DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
|
||||
};
|
||||
|
||||
static inline char *mdss_dp_test_video_pattern_to_string(u32 test_video_pattern)
|
||||
{
|
||||
switch (test_video_pattern) {
|
||||
case DP_TEST_VIDEO_PATTERN_NONE:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_NONE);
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_RAMPS);
|
||||
case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_BW_VERT_LINES);
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
|
||||
return DP_ENUM_STR(DP_TEST_VIDEO_PATTERN_COLOR_SQUARE);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_is_test_video_pattern_valid() - validates the video pattern
|
||||
* @pattern: video pattern requested by the sink
|
||||
*
|
||||
* Returns true if the requested video pattern is supported.
|
||||
*/
|
||||
static inline bool mdss_dp_is_test_video_pattern_valid(u32 pattern)
|
||||
{
|
||||
switch (pattern) {
|
||||
case DP_TEST_VIDEO_PATTERN_NONE:
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_RAMPS:
|
||||
case DP_TEST_VIDEO_PATTERN_BW_VERT_LINES:
|
||||
case DP_TEST_VIDEO_PATTERN_COLOR_SQUARE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum notification_status {
|
||||
NOTIFY_UNKNOWN,
|
||||
NOTIFY_CONNECT,
|
||||
NOTIFY_DISCONNECT,
|
||||
NOTIFY_CONNECT_IRQ_HPD,
|
||||
NOTIFY_DISCONNECT_IRQ_HPD,
|
||||
};
|
||||
|
||||
static inline char const *mdss_dp_notification_status_to_string(
|
||||
enum notification_status status)
|
||||
{
|
||||
switch (status) {
|
||||
case NOTIFY_UNKNOWN:
|
||||
return DP_ENUM_STR(NOTIFY_UNKNOWN);
|
||||
case NOTIFY_CONNECT:
|
||||
return DP_ENUM_STR(NOTIFY_CONNECT);
|
||||
case NOTIFY_DISCONNECT:
|
||||
return DP_ENUM_STR(NOTIFY_DISCONNECT);
|
||||
case NOTIFY_CONNECT_IRQ_HPD:
|
||||
return DP_ENUM_STR(NOTIFY_CONNECT_IRQ_HPD);
|
||||
case NOTIFY_DISCONNECT_IRQ_HPD:
|
||||
return DP_ENUM_STR(NOTIFY_DISCONNECT_IRQ_HPD);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mdss_dp_reset_frame_crc_data(struct mdss_dp_crc_data *crc)
|
||||
{
|
||||
if (!crc)
|
||||
return;
|
||||
|
||||
crc->r_cr = 0;
|
||||
crc->g_y = 0;
|
||||
crc->b_cb = 0;
|
||||
crc->en = false;
|
||||
}
|
||||
|
||||
void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
|
||||
|
||||
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
|
||||
|
@ -681,7 +1024,7 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep);
|
|||
void mdss_dp_sink_power_down(struct mdss_dp_drv_pdata *ep);
|
||||
void mdss_dp_lane_power_ctrl(struct mdss_dp_drv_pdata *ep, int up);
|
||||
void mdss_dp_config_ctrl(struct mdss_dp_drv_pdata *ep);
|
||||
char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt);
|
||||
char mdss_dp_gen_link_clk(struct mdss_dp_drv_pdata *dp);
|
||||
int mdss_dp_aux_set_sink_power_state(struct mdss_dp_drv_pdata *ep, char state);
|
||||
int mdss_dp_aux_send_psm_request(struct mdss_dp_drv_pdata *dp, bool enable);
|
||||
void mdss_dp_aux_send_test_response(struct mdss_dp_drv_pdata *ep);
|
||||
|
@ -694,5 +1037,9 @@ bool mdss_dp_aux_is_lane_count_valid(u32 lane_count);
|
|||
int mdss_dp_aux_link_status_read(struct mdss_dp_drv_pdata *ep, int len);
|
||||
void mdss_dp_aux_update_voltage_and_pre_emphasis_lvl(
|
||||
struct mdss_dp_drv_pdata *dp);
|
||||
int mdss_dp_aux_read_sink_frame_crc(struct mdss_dp_drv_pdata *dp);
|
||||
int mdss_dp_aux_config_sink_frame_crc(struct mdss_dp_drv_pdata *dp,
|
||||
bool enable);
|
||||
int mdss_dp_aux_parse_vx_px(struct mdss_dp_drv_pdata *ep);
|
||||
|
||||
#endif /* MDSS_DP_H */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -370,6 +370,8 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
|
|||
|
||||
dp_hdcp2p2_set_interrupts(ctrl, false);
|
||||
|
||||
atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
|
||||
|
||||
/* notify DP about HDCP failure */
|
||||
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
|
||||
HDCP_STATE_AUTH_FAIL);
|
||||
|
@ -625,6 +627,12 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
|
||||
atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
|
||||
pr_err("invalid hdcp state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cdata.context = ctrl->lib_ctx;
|
||||
|
||||
if (ctrl->sink_rx_status & ctrl->abort_mask) {
|
||||
|
@ -685,6 +693,13 @@ static int dp_hdcp2p2_cp_irq(void *input)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
|
||||
atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
|
||||
pr_err("invalid hdcp state\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctrl->sink_rx_status = 0;
|
||||
rc = mdss_dp_aux_read_rx_status(ctrl->init_data.cb_data,
|
||||
&ctrl->sink_rx_status);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -202,6 +202,45 @@ void mdss_dp_configuration_ctrl(struct dss_io_data *ctrl_io, u32 data)
|
|||
writel_relaxed(data, ctrl_io->base + DP_CONFIGURATION_CTRL);
|
||||
}
|
||||
|
||||
void mdss_dp_config_ctl_frame_crc(struct mdss_dp_drv_pdata *dp, bool enable)
|
||||
{
|
||||
if (dp->ctl_crc.en == enable) {
|
||||
pr_debug("CTL crc already %s\n",
|
||||
enable ? "enabled" : "disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
writel_relaxed(BIT(8), dp->ctrl_io.base + MMSS_DP_TIMING_ENGINE_EN);
|
||||
if (!enable)
|
||||
mdss_dp_reset_frame_crc_data(&dp->ctl_crc);
|
||||
dp->ctl_crc.en = enable;
|
||||
|
||||
pr_debug("CTL crc %s\n", enable ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
int mdss_dp_read_ctl_frame_crc(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
u32 data;
|
||||
u32 crc_rg = 0;
|
||||
struct mdss_dp_crc_data *crc = &dp->ctl_crc;
|
||||
|
||||
data = readl_relaxed(dp->ctrl_io.base + MMSS_DP_TIMING_ENGINE_EN);
|
||||
if (!(data & BIT(8))) {
|
||||
pr_debug("frame CRC calculation not enabled\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
crc_rg = readl_relaxed(dp->ctrl_io.base + MMSS_DP_PSR_CRC_RG);
|
||||
crc->r_cr = crc_rg & 0xFFFF;
|
||||
crc->g_y = crc_rg >> 16;
|
||||
crc->b_cb = readl_relaxed(dp->ctrl_io.base + MMSS_DP_PSR_CRC_B);
|
||||
|
||||
pr_debug("r_cr=0x%08x\t g_y=0x%08x\t b_cb=0x%08x\n",
|
||||
crc->r_cr, crc->g_y, crc->b_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DP state controller*/
|
||||
void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data)
|
||||
{
|
||||
|
@ -735,7 +774,9 @@ void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io,
|
|||
|
||||
data = pinfo->lcdc.v_pulse_width;
|
||||
data <<= 16;
|
||||
data |= (pinfo->lcdc.v_active_low << 31);
|
||||
data |= pinfo->lcdc.h_pulse_width;
|
||||
data |= (pinfo->lcdc.h_active_low << 15);
|
||||
/* DP_HSYNC_VSYNC_WIDTH_POLARITY */
|
||||
writel_relaxed(data, ctrl_io->base + DP_HSYNC_VSYNC_WIDTH_POLARITY);
|
||||
|
||||
|
@ -765,28 +806,15 @@ void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io,
|
|||
writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID);
|
||||
}
|
||||
|
||||
void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
|
||||
struct mdss_panel_info *pinfo)
|
||||
void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc)
|
||||
{
|
||||
u32 bpp = pinfo->bpp;
|
||||
u32 misc_val = 0x0;
|
||||
|
||||
switch (bpp) {
|
||||
case 18:
|
||||
misc_val |= (0x0 << 5);
|
||||
break;
|
||||
case 30:
|
||||
misc_val |= (0x2 << 5);
|
||||
break;
|
||||
case 24:
|
||||
default:
|
||||
misc_val |= (0x1 << 5);
|
||||
}
|
||||
u32 misc_val = cc;
|
||||
|
||||
misc_val |= (bd << 5);
|
||||
misc_val |= BIT(0); /* Configure clock to synchronous mode */
|
||||
|
||||
pr_debug("Misc settings = 0x%x\n", misc_val);
|
||||
writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0);
|
||||
writel_relaxed(misc_val, dp->ctrl_io.base + DP_MISC1_MISC0);
|
||||
}
|
||||
|
||||
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
|
||||
|
@ -1113,7 +1141,8 @@ static u8 mdss_dp_calculate_parity_byte(u32 data)
|
|||
return parityByte;
|
||||
}
|
||||
|
||||
static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
|
||||
static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io,
|
||||
u32 num_of_channels)
|
||||
{
|
||||
u32 value = 0;
|
||||
u32 new_value = 0;
|
||||
|
@ -1131,7 +1160,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
|
|||
|
||||
/* Config header and parity byte 2 */
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
new_value = 0x0;
|
||||
new_value = value;
|
||||
parity_byte = mdss_dp_calculate_parity_byte(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
|
@ -1141,7 +1170,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io)
|
|||
|
||||
/* Config header and parity byte 3 */
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
new_value = 0x01;
|
||||
new_value = num_of_channels - 1;
|
||||
parity_byte = mdss_dp_calculate_parity_byte(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
|
@ -1179,7 +1208,7 @@ static void mdss_dp_audio_setup_audio_timestamp_sdp(struct dss_io_data *ctrl_io)
|
|||
|
||||
/* Config header and parity byte 3 */
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1);
|
||||
new_value = (0x0 | (0x12 << 2));
|
||||
new_value = (0x0 | (0x11 << 2));
|
||||
parity_byte = mdss_dp_calculate_parity_byte(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
|
@ -1216,7 +1245,7 @@ static void mdss_dp_audio_setup_audio_infoframe_sdp(struct dss_io_data *ctrl_io)
|
|||
|
||||
/* Config header and parity byte 3 */
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1);
|
||||
new_value = (0x0 | (0x12 << 2));
|
||||
new_value = (0x0 | (0x11 << 2));
|
||||
parity_byte = mdss_dp_calculate_parity_byte(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
|
@ -1309,7 +1338,7 @@ static void mdss_dp_audio_setup_isrc_sdp(struct dss_io_data *ctrl_io)
|
|||
writel_relaxed(0x0, ctrl_io->base + MMSS_DP_AUDIO_ISRC_4);
|
||||
}
|
||||
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io)
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io, u32 num_of_channels)
|
||||
{
|
||||
u32 sdp_cfg = 0;
|
||||
u32 sdp_cfg2 = 0;
|
||||
|
@ -1335,7 +1364,7 @@ void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io)
|
|||
|
||||
writel_relaxed(sdp_cfg2, ctrl_io->base + MMSS_DP_SDP_CFG2);
|
||||
|
||||
mdss_dp_audio_setup_audio_stream_sdp(ctrl_io);
|
||||
mdss_dp_audio_setup_audio_stream_sdp(ctrl_io, num_of_channels);
|
||||
mdss_dp_audio_setup_audio_timestamp_sdp(ctrl_io);
|
||||
mdss_dp_audio_setup_audio_infoframe_sdp(ctrl_io);
|
||||
mdss_dp_audio_setup_copy_management_sdp(ctrl_io);
|
||||
|
@ -1366,7 +1395,7 @@ void mdss_dp_set_safe_to_exit_level(struct dss_io_data *ctrl_io,
|
|||
}
|
||||
|
||||
mainlink_levels = readl_relaxed(ctrl_io->base + DP_MAINLINK_LEVELS);
|
||||
mainlink_levels &= 0xFF0;
|
||||
mainlink_levels &= 0xFE0;
|
||||
mainlink_levels |= safe_to_exit_level;
|
||||
|
||||
pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
|
||||
|
@ -1406,28 +1435,17 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Disable mainlink */
|
||||
writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
|
||||
|
||||
/* Reset mainlink */
|
||||
mdss_dp_mainlink_reset(io);
|
||||
|
||||
/* Enable mainlink */
|
||||
writel_relaxed(0x0, io->base + DP_MAINLINK_CTRL);
|
||||
|
||||
/* Initialize DP state control */
|
||||
mdss_dp_state_ctrl(io, 0x00);
|
||||
writel_relaxed(0x0, io->base + DP_STATE_CTRL);
|
||||
|
||||
pr_debug("phy_test_pattern_sel = %s\n",
|
||||
mdss_dp_get_phy_test_pattern(phy_test_pattern_sel));
|
||||
|
||||
switch (phy_test_pattern_sel) {
|
||||
case PHY_TEST_PATTERN_D10_2_NO_SCRAMBLING:
|
||||
mdss_dp_state_ctrl(io, BIT(0));
|
||||
writel_relaxed(0x1, io->base + DP_STATE_CTRL);
|
||||
break;
|
||||
case PHY_TEST_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
|
||||
value = readl_relaxed(io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value &= ~(1 << 16);
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
|
@ -1438,7 +1456,7 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
|
|||
mdss_dp_state_ctrl(io, BIT(4));
|
||||
break;
|
||||
case PHY_TEST_PATTERN_PRBS7:
|
||||
mdss_dp_state_ctrl(io, BIT(5));
|
||||
writel_relaxed(0x20, io->base + DP_STATE_CTRL);
|
||||
break;
|
||||
case PHY_TEST_PATTERN_80_BIT_CUSTOM_PATTERN:
|
||||
mdss_dp_state_ctrl(io, BIT(6));
|
||||
|
@ -1453,9 +1471,7 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
|
|||
DP_TEST_80BIT_CUSTOM_PATTERN_REG2);
|
||||
break;
|
||||
case PHY_TEST_PATTERN_HBR2_CTS_EYE_PATTERN:
|
||||
value = readl_relaxed(io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value |= BIT(16);
|
||||
value = BIT(16);
|
||||
writel_relaxed(value, io->base +
|
||||
DP_HBR2_COMPLIANCE_SCRAMBLER_RESET);
|
||||
value |= 0xFC;
|
||||
|
@ -1469,4 +1485,8 @@ void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp)
|
|||
phy_test_pattern_sel);
|
||||
return;
|
||||
}
|
||||
|
||||
value = 0x0;
|
||||
value = readl_relaxed(io->base + DP_MAINLINK_READY);
|
||||
pr_info("DP_MAINLINK_READY = 0x%x\n", value);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -65,6 +65,7 @@
|
|||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000004C4)
|
||||
#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000004C8)
|
||||
|
||||
#define MMSS_DP_MISC1_MISC0 (0x0000042C)
|
||||
#define MMSS_DP_AUDIO_TIMING_GEN (0x00000480)
|
||||
#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000484)
|
||||
#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000488)
|
||||
|
@ -73,6 +74,9 @@
|
|||
#define MMSS_DP_AUDIO_TIMING_RBR_48 (0x00000494)
|
||||
#define MMSS_DP_AUDIO_TIMING_HBR_48 (0x00000498)
|
||||
|
||||
#define MMSS_DP_PSR_CRC_RG (0x00000554)
|
||||
#define MMSS_DP_PSR_CRC_B (0x00000558)
|
||||
|
||||
#define MMSS_DP_AUDIO_CFG (0x00000600)
|
||||
#define MMSS_DP_AUDIO_STATUS (0x00000604)
|
||||
#define MMSS_DP_AUDIO_PKT_CTRL (0x00000608)
|
||||
|
@ -135,6 +139,8 @@
|
|||
#define MMSS_DP_GENERIC1_8 (0x00000748)
|
||||
#define MMSS_DP_GENERIC1_9 (0x0000074C)
|
||||
|
||||
#define MMSS_DP_TIMING_ENGINE_EN (0x00000A10)
|
||||
|
||||
/*DP PHY Register offsets */
|
||||
#define DP_PHY_REVISION_ID0 (0x00000000)
|
||||
#define DP_PHY_REVISION_ID1 (0x00000004)
|
||||
|
@ -285,8 +291,7 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io);
|
|||
void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert);
|
||||
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
|
||||
u8 ln_cnt, u32 res, struct mdss_panel_info *pinfo);
|
||||
void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
|
||||
struct mdss_panel_info *pinfo);
|
||||
void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc);
|
||||
void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io);
|
||||
void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable);
|
||||
void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
|
||||
|
@ -312,7 +317,7 @@ void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io,
|
|||
u8 orientation, u8 ln_cnt);
|
||||
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,
|
||||
char link_rate);
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io);
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io, u32 num_of_channels);
|
||||
void mdss_dp_audio_enable(struct dss_io_data *ctrl_io, bool enable);
|
||||
void mdss_dp_audio_select_core(struct dss_io_data *ctrl_io);
|
||||
void mdss_dp_audio_set_sample_rate(struct dss_io_data *ctrl_io,
|
||||
|
@ -321,5 +326,7 @@ void mdss_dp_set_safe_to_exit_level(struct dss_io_data *ctrl_io,
|
|||
uint32_t lane_cnt);
|
||||
int mdss_dp_aux_read_rx_status(struct mdss_dp_drv_pdata *dp, u8 *rx_status);
|
||||
void mdss_dp_phy_send_test_pattern(struct mdss_dp_drv_pdata *dp);
|
||||
void mdss_dp_config_ctl_frame_crc(struct mdss_dp_drv_pdata *dp, bool enable);
|
||||
int mdss_dp_read_ctl_frame_crc(struct mdss_dp_drv_pdata *dp);
|
||||
|
||||
#endif /* __DP_UTIL_H__ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2016 The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -643,7 +643,8 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
|
|||
/* Wait for HDCP keys to be checked and validated */
|
||||
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
|
||||
((link0_status >> reg_set->keys_offset) & 0x7)
|
||||
== HDCP_KEYS_STATE_VALID,
|
||||
== HDCP_KEYS_STATE_VALID ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("key not ready\n");
|
||||
|
@ -658,7 +659,8 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
|
|||
|
||||
/* Wait for An0 and An1 bit to be ready */
|
||||
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
|
||||
(link0_status & (BIT(8) | BIT(9))),
|
||||
(link0_status & (BIT(8) | BIT(9))) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("An not ready\n");
|
||||
|
@ -668,6 +670,9 @@ static int hdcp_1x_wait_for_hw_ready(struct hdcp_1x *hdcp)
|
|||
/* As per hardware recommendations, wait before reading An */
|
||||
msleep(20);
|
||||
error:
|
||||
if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
|
||||
rc = -EINVAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -820,7 +825,8 @@ static int hdcp_1x_verify_r0(struct hdcp_1x *hdcp)
|
|||
|
||||
/* Wait for HDCP R0 computation to be completed */
|
||||
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
|
||||
link0_status & BIT(reg_set->r0_offset),
|
||||
(link0_status & BIT(reg_set->r0_offset)) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("R0 not ready\n");
|
||||
|
@ -862,10 +868,14 @@ static int hdcp_1x_verify_r0(struct hdcp_1x *hdcp)
|
|||
DSS_REG_W(io, reg_set->data2_0, (((u32)buf[1]) << 8) | buf[0]);
|
||||
|
||||
rc = readl_poll_timeout(io->base + reg_set->status,
|
||||
link0_status, link0_status & BIT(12),
|
||||
link0_status, (link0_status & BIT(12)) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
r0_read_delay_us, r0_read_timeout_us);
|
||||
} while (rc && --r0_retry);
|
||||
error:
|
||||
if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
|
||||
rc = -EINVAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1092,9 +1102,9 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
|
|||
*/
|
||||
if (i && !((i + 1) % 64)) {
|
||||
rc = readl_poll_timeout(io->base + reg_set->sha_status,
|
||||
sha_status, sha_status & BIT(0),
|
||||
HDCP_POLL_SLEEP_US,
|
||||
HDCP_POLL_TIMEOUT_US);
|
||||
sha_status, (sha_status & BIT(0)) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("block not done\n");
|
||||
goto error;
|
||||
|
@ -1108,7 +1118,8 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
|
|||
|
||||
/* Now wait for HDCP_SHA_COMP_DONE */
|
||||
rc = readl_poll_timeout(io->base + reg_set->sha_status, sha_status,
|
||||
sha_status & BIT(4),
|
||||
(sha_status & BIT(4)) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("V computation not done\n");
|
||||
|
@ -1117,13 +1128,17 @@ static int hdcp_1x_write_ksv_fifo(struct hdcp_1x *hdcp)
|
|||
|
||||
/* Wait for V_MATCHES */
|
||||
rc = readl_poll_timeout(io->base + reg_set->status, status,
|
||||
status & BIT(reg_set->v_offset),
|
||||
(status & BIT(reg_set->v_offset)) ||
|
||||
!hdcp_1x_state(HDCP_STATE_AUTHENTICATING),
|
||||
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
pr_err("V mismatch\n");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
error:
|
||||
if (!hdcp_1x_state(HDCP_STATE_AUTHENTICATING))
|
||||
rc = -EINVAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1273,8 +1288,6 @@ static void hdcp_1x_update_auth_status(struct hdcp_1x *hdcp)
|
|||
if (hdcp_1x_state(HDCP_STATE_AUTHENTICATED)) {
|
||||
hdcp_1x_cache_topology(hdcp);
|
||||
hdcp_1x_notify_topology(hdcp);
|
||||
} else {
|
||||
hdcp1_set_enc(false);
|
||||
}
|
||||
|
||||
if (hdcp->init_data.notify_status &&
|
||||
|
@ -1459,9 +1472,6 @@ void hdcp_1x_off(void *input)
|
|||
return;
|
||||
}
|
||||
|
||||
if (hdcp_1x_state(HDCP_STATE_AUTHENTICATED))
|
||||
hdcp1_set_enc(false);
|
||||
|
||||
/*
|
||||
* Disable HDCP interrupts.
|
||||
* Also, need to set the state to inactive here so that any ongoing
|
||||
|
@ -1482,11 +1492,13 @@ void hdcp_1x_off(void *input)
|
|||
* No more reauthentiaction attempts will be scheduled since we
|
||||
* set the currect state to inactive.
|
||||
*/
|
||||
rc = cancel_delayed_work(&hdcp->hdcp_auth_work);
|
||||
rc = cancel_delayed_work_sync(&hdcp->hdcp_auth_work);
|
||||
if (rc)
|
||||
pr_debug("%s: Deleted hdcp auth work\n",
|
||||
HDCP_STATE_NAME);
|
||||
|
||||
hdcp1_set_enc(false);
|
||||
|
||||
reg = DSS_REG_R(io, reg_set->reset);
|
||||
DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -122,13 +122,6 @@ struct hdmi_edid_sink_caps {
|
|||
bool ind_view_support;
|
||||
};
|
||||
|
||||
struct hdmi_edid_override_data {
|
||||
int scramble;
|
||||
int sink_mode;
|
||||
int format;
|
||||
int vic;
|
||||
};
|
||||
|
||||
struct hdmi_edid_ctrl {
|
||||
u8 pt_scan_info;
|
||||
u8 it_scan_info;
|
||||
|
@ -1607,9 +1600,14 @@ static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl,
|
|||
(timing.refresh_rate % 100) / 10,
|
||||
timing.refresh_rate % 10);
|
||||
|
||||
rc = hdmi_get_video_id_code(&timing, NULL);
|
||||
if (rc < 0)
|
||||
rc = hdmi_set_resv_timing_info(&timing);
|
||||
/*
|
||||
* Always add resolutions parsed from DTD in the reserved
|
||||
* timing info. This can avoid matching resolutions that have
|
||||
* a non-integral fps denominators with corresponding
|
||||
* resolutions that have an integral fps denominator.
|
||||
* For example - 640x480p@59.94Hz --> 640x480p@60Hz
|
||||
*/
|
||||
rc = hdmi_set_resv_timing_info(&timing);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
@ -1983,7 +1981,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
{
|
||||
u8 i = 0, offset = 0, std_blk = 0;
|
||||
u32 video_format = HDMI_VFRMT_640x480p60_4_3;
|
||||
u32 has480p = false;
|
||||
u8 len = 0;
|
||||
u8 num_of_cea_blocks;
|
||||
u8 *data_buf;
|
||||
|
@ -2046,9 +2043,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
video_format == HDMI_VFRMT_2880x576p50_16_9 ||
|
||||
video_format == HDMI_VFRMT_1920x1250i50_16_9)
|
||||
has50hz_mode = true;
|
||||
|
||||
if (video_format == HDMI_VFRMT_640x480p60_4_3)
|
||||
has480p = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2067,9 +2061,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
hdmi_edid_add_sink_video_format(edid_ctrl,
|
||||
video_format);
|
||||
|
||||
if (video_format == HDMI_VFRMT_640x480p60_4_3)
|
||||
has480p = true;
|
||||
|
||||
/* Make a note of the preferred video format */
|
||||
if (i == 0)
|
||||
sink_data->preferred_video_format =
|
||||
|
@ -2091,7 +2082,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
desc_offset = edid_blk1[0x02];
|
||||
if (desc_offset < (EDID_BLOCK_SIZE - EDID_DTD_LEN)) {
|
||||
i = 0;
|
||||
while (!edid_blk1[desc_offset]) {
|
||||
while ((i < 4) && edid_blk1[desc_offset]) {
|
||||
hdmi_edid_detail_desc(edid_ctrl,
|
||||
edid_blk1+desc_offset,
|
||||
&video_format);
|
||||
|
@ -2103,8 +2094,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
|
||||
hdmi_edid_add_sink_video_format(edid_ctrl,
|
||||
video_format);
|
||||
if (video_format == HDMI_VFRMT_640x480p60_4_3)
|
||||
has480p = true;
|
||||
|
||||
/* Make a note of the preferred video format */
|
||||
if (i == 0) {
|
||||
|
@ -2192,15 +2181,6 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
|
|||
if (!rc)
|
||||
pr_debug("%s: 3D formats in VSD\n", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to add default 640 by 480 timings, in case not described
|
||||
* in the EDID structure.
|
||||
* All DTV sink devices should support this mode
|
||||
*/
|
||||
if (!has480p)
|
||||
hdmi_edid_add_sink_video_format(edid_ctrl,
|
||||
HDMI_VFRMT_640x480p60_4_3);
|
||||
} /* hdmi_edid_get_display_mode */
|
||||
|
||||
u32 hdmi_edid_get_raw_data(void *input, u8 *buf, u32 size)
|
||||
|
@ -2610,6 +2590,31 @@ void hdmi_edid_set_video_resolution(void *input, u32 resolution, bool reset)
|
|||
}
|
||||
} /* hdmi_edid_set_video_resolution */
|
||||
|
||||
void hdmi_edid_config_override(void *input, bool enable,
|
||||
struct hdmi_edid_override_data *data)
|
||||
{
|
||||
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
|
||||
struct hdmi_edid_override_data *ov_data = &edid_ctrl->override_data;
|
||||
|
||||
if ((!edid_ctrl) || (enable && !data)) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
edid_ctrl->edid_override = enable;
|
||||
pr_debug("EDID override %s\n", enable ? "enabled" : "disabled");
|
||||
|
||||
if (enable) {
|
||||
ov_data->scramble = data->scramble;
|
||||
ov_data->sink_mode = data->sink_mode;
|
||||
ov_data->format = data->format;
|
||||
ov_data->vic = data->vic;
|
||||
pr_debug("%s: Override data: scramble=%d sink_mode=%d format=%d vic=%d\n",
|
||||
__func__, ov_data->scramble, ov_data->sink_mode,
|
||||
ov_data->format, ov_data->vic);
|
||||
}
|
||||
}
|
||||
|
||||
void hdmi_edid_deinit(void *input)
|
||||
{
|
||||
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -44,6 +44,20 @@ struct hdmi_edid_hdr_data {
|
|||
u32 min_luminance;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct hdmi_override_data - Resolution Override Data
|
||||
* @scramble - scrambler enable
|
||||
* @sink_mode - 0 for DVI and 1 for HDMI
|
||||
* @format - pixel format (refer to msm_hdmi_modes.h)
|
||||
* @vic - resolution code
|
||||
*/
|
||||
struct hdmi_edid_override_data {
|
||||
int scramble;
|
||||
int sink_mode;
|
||||
int format;
|
||||
int vic;
|
||||
};
|
||||
|
||||
int hdmi_edid_parser(void *edid_ctrl);
|
||||
u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size);
|
||||
u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution);
|
||||
|
@ -63,5 +77,7 @@ u8 hdmi_edid_get_deep_color(void *edid_ctrl);
|
|||
u32 hdmi_edid_get_max_pclk(void *edid_ctrl);
|
||||
void hdmi_edid_get_hdr_data(void *edid_ctrl,
|
||||
struct hdmi_edid_hdr_data **hdr_data);
|
||||
void hdmi_edid_config_override(void *input, bool enable,
|
||||
struct hdmi_edid_override_data *data);
|
||||
|
||||
#endif /* __HDMI_EDID_H__ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -421,8 +421,10 @@ static inline void hdmi_tx_send_cable_notification(
|
|||
if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd) {
|
||||
u32 flags = 0;
|
||||
|
||||
if (hdmi_tx_is_dvi_mode(hdmi_ctrl))
|
||||
flags |= MSM_EXT_DISP_HPD_NO_AUDIO;
|
||||
flags |= MSM_EXT_DISP_HPD_VIDEO;
|
||||
|
||||
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
|
||||
flags |= MSM_EXT_DISP_HPD_AUDIO;
|
||||
|
||||
hdmi_ctrl->ext_audio_data.intf_ops.hpd(hdmi_ctrl->ext_pdev,
|
||||
hdmi_ctrl->ext_audio_data.type, val, flags);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -555,6 +555,9 @@ int msm_hdmi_get_timing_info(
|
|||
case HDMI_VFRMT_3840x2160p60_64_27:
|
||||
MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p60_64_27);
|
||||
break;
|
||||
case HDMI_VFRMT_640x480p59_4_3:
|
||||
MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_640x480p59_4_3);
|
||||
break;
|
||||
default:
|
||||
ret = hdmi_get_resv_timing_info(mode, id);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -372,9 +372,11 @@ struct lcd_panel_info {
|
|||
u32 h_back_porch;
|
||||
u32 h_front_porch;
|
||||
u32 h_pulse_width;
|
||||
u32 h_active_low;
|
||||
u32 v_back_porch;
|
||||
u32 v_front_porch;
|
||||
u32 v_pulse_width;
|
||||
u32 v_active_low;
|
||||
u32 border_clr;
|
||||
u32 underflow_clr;
|
||||
u32 hsync_skew;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -42,6 +42,7 @@ struct msm_ext_disp {
|
|||
struct list_head display_list;
|
||||
struct mutex lock;
|
||||
struct completion hpd_comp;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static int msm_ext_disp_get_intf_data(struct msm_ext_disp *ext_disp,
|
||||
|
@ -365,7 +366,7 @@ static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
if (flags & MSM_EXT_DISP_HPD_NO_VIDEO) {
|
||||
if (!(flags & MSM_EXT_DISP_HPD_VIDEO)) {
|
||||
pr_debug("skipping video setup for display (%s)\n",
|
||||
msm_ext_disp_name(type));
|
||||
goto end;
|
||||
|
@ -398,7 +399,7 @@ static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
|
||||
if (!(flags & MSM_EXT_DISP_HPD_AUDIO)) {
|
||||
pr_debug("skipping audio setup for display (%s)\n",
|
||||
msm_ext_disp_name(type));
|
||||
goto end;
|
||||
|
@ -425,6 +426,47 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool msm_ext_disp_validate_connect(struct msm_ext_disp *ext_disp,
|
||||
enum msm_ext_disp_type type, u32 flags)
|
||||
{
|
||||
/* allow new connections */
|
||||
if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX)
|
||||
goto end;
|
||||
|
||||
/* if already connected, block a new connection */
|
||||
if (ext_disp->current_disp != type)
|
||||
return false;
|
||||
|
||||
/* if same display connected, block same connection type */
|
||||
if (ext_disp->flags & flags)
|
||||
return false;
|
||||
|
||||
end:
|
||||
ext_disp->flags |= flags;
|
||||
ext_disp->current_disp = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool msm_ext_disp_validate_disconnect(struct msm_ext_disp *ext_disp,
|
||||
enum msm_ext_disp_type type, u32 flags)
|
||||
{
|
||||
/* check if nothing connected */
|
||||
if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX)
|
||||
return false;
|
||||
|
||||
/* check if a different display's request */
|
||||
if (ext_disp->current_disp != type)
|
||||
return false;
|
||||
|
||||
/* allow only an already connected type */
|
||||
if (ext_disp->flags & flags) {
|
||||
ext_disp->flags &= ~flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int msm_ext_disp_hpd(struct platform_device *pdev,
|
||||
enum msm_ext_disp_type type,
|
||||
enum msm_ext_disp_cable_state state,
|
||||
|
@ -446,8 +488,8 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
|
|||
|
||||
mutex_lock(&ext_disp->lock);
|
||||
|
||||
pr_debug("HPD for display (%s), NEW STATE = %d\n",
|
||||
msm_ext_disp_name(type), state);
|
||||
pr_debug("HPD for display (%s), NEW STATE = %d, flags = %d\n",
|
||||
msm_ext_disp_name(type), state, flags);
|
||||
|
||||
if (state < EXT_DISPLAY_CABLE_DISCONNECT ||
|
||||
state >= EXT_DISPLAY_CABLE_STATE_MAX) {
|
||||
|
@ -456,24 +498,13 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if ((state == EXT_DISPLAY_CABLE_CONNECT) &&
|
||||
(ext_disp->current_disp != EXT_DISPLAY_TYPE_MAX)) {
|
||||
pr_err("Display interface (%s) already connected\n",
|
||||
msm_ext_disp_name(ext_disp->current_disp));
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((state == EXT_DISPLAY_CABLE_DISCONNECT) &&
|
||||
(ext_disp->current_disp != type)) {
|
||||
pr_err("Display interface (%s) is not connected\n",
|
||||
msm_ext_disp_name(type));
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (state == EXT_DISPLAY_CABLE_CONNECT) {
|
||||
ext_disp->current_disp = type;
|
||||
if (!msm_ext_disp_validate_connect(ext_disp, type, flags)) {
|
||||
pr_err("Display interface (%s) already connected\n",
|
||||
msm_ext_disp_name(ext_disp->current_disp));
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = msm_ext_disp_process_display(ext_disp, type, state,
|
||||
flags);
|
||||
|
@ -490,11 +521,19 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
|
|||
if (ret)
|
||||
goto end;
|
||||
} else {
|
||||
if (!msm_ext_disp_validate_disconnect(ext_disp, type, flags)) {
|
||||
pr_err("Display interface (%s) not connected\n",
|
||||
msm_ext_disp_name(type));
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
msm_ext_disp_process_audio(ext_disp, type, state, flags);
|
||||
msm_ext_disp_update_audio_ops(ext_disp, type, state, flags);
|
||||
msm_ext_disp_process_display(ext_disp, type, state, flags);
|
||||
|
||||
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
|
||||
if (!ext_disp->flags)
|
||||
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
|
||||
}
|
||||
|
||||
pr_debug("Hpd (%d) for display (%s)\n", state,
|
||||
|
@ -653,7 +692,7 @@ static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
|
|||
int ret = 0;
|
||||
struct msm_ext_disp_audio_codec_ops *ops = ext_disp->ops;
|
||||
|
||||
if (flags & MSM_EXT_DISP_HPD_NO_AUDIO) {
|
||||
if (!(flags & MSM_EXT_DISP_HPD_AUDIO)) {
|
||||
pr_debug("skipping audio ops setup for display (%s)\n",
|
||||
msm_ext_disp_name(type));
|
||||
goto end;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* include/linux/msm_ext_display.h
|
||||
*
|
||||
* Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -24,11 +24,11 @@
|
|||
/**
|
||||
* Flags to be used with the HPD operation of the external display
|
||||
* interface:
|
||||
* MSM_EXT_DISP_HPD_NO_AUDIO: audio will not be routed to external display
|
||||
* MSM_EXT_DISP_HPD_NO_VIDEO: video will not be routed to external display
|
||||
* MSM_EXT_DISP_HPD_AUDIO: audio will be routed to external display
|
||||
* MSM_EXT_DISP_HPD_VIDEO: video will be routed to external display
|
||||
*/
|
||||
#define MSM_EXT_DISP_HPD_NO_AUDIO BIT(0)
|
||||
#define MSM_EXT_DISP_HPD_NO_VIDEO BIT(1)
|
||||
#define MSM_EXT_DISP_HPD_AUDIO BIT(0)
|
||||
#define MSM_EXT_DISP_HPD_VIDEO BIT(1)
|
||||
|
||||
/**
|
||||
* struct ext_disp_cable_notify - cable notify handler structure
|
||||
|
|
|
@ -234,7 +234,11 @@ struct msm_hdmi_mode_timing_info {
|
|||
#define HDMI_VFRMT_1920x1200p60_16_10 ETIII_OFF(8)
|
||||
#define ETIII_VFRMT_END HDMI_VFRMT_1920x1200p60_16_10
|
||||
|
||||
#define RESERVE_OFF(x) (ETIII_VFRMT_END + x)
|
||||
#define MISC_VFRMT_OFF(x) (ETIII_VFRMT_END + x)
|
||||
#define HDMI_VFRMT_640x480p59_4_3 MISC_VFRMT_OFF(1)
|
||||
#define MISC_VFRMT_END HDMI_VFRMT_640x480p59_4_3
|
||||
|
||||
#define RESERVE_OFF(x) (MISC_VFRMT_END + x)
|
||||
|
||||
#define HDMI_VFRMT_RESERVE1 RESERVE_OFF(1)
|
||||
#define HDMI_VFRMT_RESERVE2 RESERVE_OFF(2)
|
||||
|
@ -425,6 +429,11 @@ struct msm_hdmi_mode_timing_info {
|
|||
{HDMI_VFRMT_3840x2160p60_64_27, 3840, 176, 88, 296, false, \
|
||||
2160, 8, 10, 72, false, 594000, 60000, false, true, \
|
||||
HDMI_RES_AR_64_27, 0}
|
||||
#define HDMI_VFRMT_640x480p59_4_3_TIMING \
|
||||
{HDMI_VFRMT_640x480p59_4_3, 640, 16, 96, 48, true, \
|
||||
480, 10, 2, 33, true, 25170, 59928, false, true, \
|
||||
HDMI_RES_AR_4_3, 1}
|
||||
|
||||
|
||||
#define MSM_HDMI_MODES_SET_TIMING(LUT, MODE) do { \
|
||||
struct msm_hdmi_mode_timing_info mode = MODE##_TIMING; \
|
||||
|
@ -508,6 +517,8 @@ do { \
|
|||
HDMI_VFRMT_3840x2160p50_64_27); \
|
||||
MSM_HDMI_MODES_SET_TIMING(__lut, \
|
||||
HDMI_VFRMT_3840x2160p60_64_27); \
|
||||
MSM_HDMI_MODES_SET_TIMING(__lut, \
|
||||
HDMI_VFRMT_640x480p59_4_3); \
|
||||
} \
|
||||
if (__type & MSM_HDMI_MODES_XTND) { \
|
||||
MSM_HDMI_MODES_SET_TIMING(__lut, \
|
||||
|
|
Loading…
Add table
Reference in a new issue