hal: enable audio over display port
Add support for audio over display port.
Change-Id: I3480d89c61ee5e5983715ec943fb02b1a9d5d151
diff --git a/hal/Android.mk b/hal/Android.mk
index 705e5e8..812ed99 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -310,6 +310,10 @@
LOCAL_SHARED_LIBRARIES += libperipheral_client
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DISPLAY_PORT)),true)
+ LOCAL_CFLAGS += -DDISPLAY_PORT_ENABLED
+endif
+
LOCAL_CFLAGS += -Wall -Werror
LOCAL_COPY_HEADERS_TO := mm-audio
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 569b4b2..65f516c 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -96,7 +96,7 @@
* this is done when device switch happens by setting audioparamter
*/
-#define HDMI_PLUG_STATUS_NOTIFY_ENABLE 0x30
+#define EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE 0x30
static ssize_t update_sysfs_node(const char *path, const char *data, size_t len)
{
@@ -121,56 +121,60 @@
return err;
}
-static int get_hdmi_sysfs_node_index()
+static int get_ext_disp_sysfs_node_index(int ext_disp_type)
{
- static int node_index = -1;
+ int node_index = -1;
char fbvalue[80] = {0};
char fbpath[80] = {0};
int i = 0;
- FILE *hdmi_fp = NULL;
-
- if(node_index >= 0) {
- //hdmi sysfs node will not change so we just need to get the index once.
- ALOGV("HDMI sysfs node is at fb%d", node_index);
- return node_index;
- }
+ FILE *ext_disp_fd = NULL;
for(i = 0; i < 3; i++) {
snprintf(fbpath, sizeof(fbpath),
"/sys/class/graphics/fb%d/msm_fb_type", i);
- hdmi_fp = fopen(fbpath, "r");
- if(hdmi_fp) {
- fread(fbvalue, sizeof(char), 80, hdmi_fp);
- if(strncmp(fbvalue, "dtv panel", strlen("dtv panel")) == 0) {
- node_index = i;
- ALOGV("HDMI is at fb%d",i);
- fclose(hdmi_fp);
- return node_index;
+ ext_disp_fd = fopen(fbpath, "r");
+ if (ext_disp_fd) {
+ if (fread(fbvalue, sizeof(char), 80, ext_disp_fd)) {
+ if(((strncmp(fbvalue, "dtv panel", strlen("dtv panel")) == 0) &&
+ (ext_disp_type == EXT_DISPLAY_TYPE_HDMI)) ||
+ ((strncmp(fbvalue, "dp panel", strlen("dp panel")) == 0) &&
+ (ext_disp_type == EXT_DISPLAY_TYPE_DP))) {
+ node_index = i;
+ ALOGD("%s: Ext Disp:%d is at fb%d", __func__, ext_disp_type, i);
+ fclose(ext_disp_fd);
+ return node_index;
+ }
}
- fclose(hdmi_fp);
+ fclose(ext_disp_fd);
} else {
- ALOGE("Failed to open fb node %d",i);
+ ALOGE("%s: Failed to open fb node %d", __func__, i);
}
}
return -1;
}
-static int update_hdmi_sysfs_node(int node_value)
+static int update_ext_disp_sysfs_node(const struct audio_device *adev, int node_value)
{
- char hdmi_ack_path[80] = {0};
- char hdmi_ack_value[3] = {0};
+ char ext_disp_ack_path[80] = {0};
+ char ext_disp_ack_value[3] = {0};
int index, ret = -1;
+ int ext_disp_type = platform_get_ext_disp_type(adev->platform);
- index = get_hdmi_sysfs_node_index();
+ if (ext_disp_type < 0) {
+ ALOGE("%s, Unable to get the external display type, err:%d",
+ __func__, ext_disp_type);
+ return -EINVAL;
+ }
+ index = get_ext_disp_sysfs_node_index(ext_disp_type);
if (index >= 0) {
- snprintf(hdmi_ack_value, sizeof(hdmi_ack_value), "%d", node_value);
- snprintf(hdmi_ack_path, sizeof(hdmi_ack_path),
+ snprintf(ext_disp_ack_value, sizeof(ext_disp_ack_value), "%d", node_value);
+ snprintf(ext_disp_ack_path, sizeof(ext_disp_ack_path),
"/sys/class/graphics/fb%d/hdmi_audio_cb", index);
- ret = update_sysfs_node(hdmi_ack_path, hdmi_ack_value,
- sizeof(hdmi_ack_value));
+ ret = update_sysfs_node(ext_disp_ack_path, ext_disp_ack_value,
+ sizeof(ext_disp_ack_value));
ALOGI("update hdmi_audio_cb at fb[%d] to:[%d] %s",
index, node_value, (ret >= 0) ? "success":"fail");
@@ -179,25 +183,27 @@
return ret;
}
-static void check_and_set_hdmi_connection_status(struct str_parms *parms)
+static void check_and_set_ext_disp_connection_status(const struct audio_device *adev,
+ struct str_parms *parms)
{
char value[32] = {0};
static bool is_hdmi_sysfs_node_init = false;
if (str_parms_get_str(parms, "connect", value, sizeof(value)) >= 0
- && (atoi(value) & AUDIO_DEVICE_OUT_HDMI)) {
- //params = "connect=1024" for HDMI connection.
+ && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ //params = "connect=1024" for external display connection.
if (is_hdmi_sysfs_node_init == false) {
+ //check if this is different for dp and hdmi
is_hdmi_sysfs_node_init = true;
- update_hdmi_sysfs_node(HDMI_PLUG_STATUS_NOTIFY_ENABLE);
+ update_ext_disp_sysfs_node(adev, EXT_DISPLAY_PLUG_STATUS_NOTIFY_ENABLE);
}
- update_hdmi_sysfs_node(1);
+ update_ext_disp_sysfs_node(adev, 1);
} else if(str_parms_get_str(parms, "disconnect", value, sizeof(value)) >= 0
- && (atoi(value) & AUDIO_DEVICE_OUT_HDMI)){
- //params = "disconnect=1024" for HDMI disconnection.
- update_hdmi_sysfs_node(0);
+ && (atoi(value) & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+ //params = "disconnect=1024" for external display disconnection.
+ update_ext_disp_sysfs_node(adev, 0);
} else {
- // handle hdmi devices only
+ // handle ext disp devices only
return;
}
}
@@ -764,7 +770,7 @@
audio_extn_source_track_set_parameters(adev, parms);
audio_extn_fbsp_set_parameters(parms);
audio_extn_keep_alive_set_parameters(adev, parms);
- check_and_set_hdmi_connection_status(parms);
+ check_and_set_ext_disp_connection_status(adev, parms);
if (adev->offload_effects_set_parameters != NULL)
adev->offload_effects_set_parameters(parms);
}
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e8caeee..1d5b12e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -407,6 +407,12 @@
#define AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH 0x10000
#endif
+enum {
+ EXT_DISPLAY_TYPE_NONE,
+ EXT_DISPLAY_TYPE_HDMI,
+ EXT_DISPLAY_TYPE_DP
+};
+
#ifndef HDMI_PASSTHROUGH_ENABLED
#define audio_extn_passthru_update_stream_configuration(adev, out) (0)
#define audio_extn_passthru_is_convert_supported(adev, out) (0)
diff --git a/hal/audio_extn/keep_alive.c b/hal/audio_extn/keep_alive.c
index 60e7eef..1df6d08 100644
--- a/hal/audio_extn/keep_alive.c
+++ b/hal/audio_extn/keep_alive.c
@@ -36,8 +36,6 @@
#include "platform_api.h"
#include <platform.h>
-#define SILENCE_MIXER_PATH "silence-playback hdmi"
-#define SILENCE_DEV_ID 32 /* index into machine driver */
#define SILENCE_INTERVAL 2 /*In secs*/
typedef enum {
@@ -131,11 +129,14 @@
if (ka.pcm)
return -EEXIST;
- ALOGD("opening silence device %d", SILENCE_DEV_ID);
+ int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+ PCM_PLAYBACK);
+
+ ALOGD("opening silence device %d", silence_pcm_dev_id);
struct audio_device * adev = (struct audio_device *)ka.userdata;
- ka.pcm = pcm_open(adev->snd_card, SILENCE_DEV_ID,
+ ka.pcm = pcm_open(adev->snd_card, silence_pcm_dev_id,
flags, &silence_config);
- ALOGD("opened silence device %d", SILENCE_DEV_ID);
+ ALOGD("opened silence device %d", silence_pcm_dev_id);
if (ka.pcm == NULL || !pcm_is_ready(ka.pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(ka.pcm));
if (ka.pcm != NULL) {
@@ -208,8 +209,10 @@
ka.done = false;
/*configure app type */
+ int silence_pcm_dev_id = platform_get_pcm_device_id(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+ PCM_PLAYBACK);
snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
- "Audio Stream %d App Type Cfg",SILENCE_DEV_ID);
+ "Audio Stream %d App Type Cfg", silence_pcm_dev_id);
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
@@ -219,7 +222,28 @@
goto exit;
}
- snd_device = SND_DEVICE_OUT_HDMI;
+ /* Configure HDMI/DP Backend with default values, this as well
+ * helps reconfigure HDMI/DP backend after passthrough.
+ */
+ int ext_disp_type = platform_get_ext_disp_type(adev->platform);
+ switch(ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ snd_device = SND_DEVICE_OUT_HDMI;
+ set_mixer_control(adev->mixer, "HDMI RX Format", "LPCM");
+ set_mixer_control(adev->mixer, "HDMI_RX SampleRate", "KHZ_48");
+ set_mixer_control(adev->mixer, "HDMI_RX Channels", "Two");
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+ set_mixer_control(adev->mixer, "Display Port Format", "LPCM");
+ set_mixer_control(adev->mixer, "Display Port RX SampleRate", "KHZ_48");
+ set_mixer_control(adev->mixer, "Display Port RX Channels", "Two");
+ break;
+ default:
+ ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+ goto exit;
+ }
+
acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
if (acdb_dev_id < 0) {
ALOGE("%s: Couldn't get the acdb dev id", __func__);
@@ -237,23 +261,27 @@
platform_get_default_app_type(adev->platform),
acdb_dev_id, sample_rate);
mixer_ctl_set_array(ctl, app_type_cfg, len);
- /*Configure HDMI Backend with default values, this as well
- *helps reconfigure HDMI backend after passthrough
- */
- set_mixer_control(adev->mixer, "HDMI RX Format", "LPCM");
- set_mixer_control(adev->mixer, "HDMI_RX SampleRate", "KHZ_48");
- set_mixer_control(adev->mixer, "HDMI_RX Channels", "Two");
/*send calibration*/
usecase = calloc(1, sizeof(struct audio_usecase));
usecase->type = PCM_PLAYBACK;
- usecase->out_snd_device = SND_DEVICE_OUT_HDMI;
+ usecase->out_snd_device = snd_device;
platform_send_audio_calibration(adev->platform, usecase,
platform_get_default_app_type(adev->platform), sample_rate);
/*apply audio route */
- audio_route_apply_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
+ switch(ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ audio_route_apply_and_update_path(adev->audio_route, "silence-playback hdmi");
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ audio_route_apply_and_update_path(adev->audio_route, "silence-playback display-port");
+ break;
+ default:
+ ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+ goto exit;
+ }
if (open_silence_stream() == 0) {
send_cmd_l(REQUEST_WRITE);
@@ -284,7 +312,19 @@
pthread_cond_wait(&ka.cond, &ka.lock);
}
close_silence_stream();
- audio_route_reset_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
+
+ /*apply audio route */
+ int ext_disp_type = platform_get_ext_disp_type(adev->platform);
+ switch(ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ audio_route_reset_and_update_path(adev->audio_route, "silence-playback hdmi");
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ audio_route_reset_and_update_path(adev->audio_route, "silence-playback display-port");
+ break;
+ default:
+ ALOGE("%s: Invalid external display type:%d", __func__, ext_disp_type);
+ }
exit:
pthread_mutex_unlock(&ka.lock);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1215d2d..ee7647e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -255,6 +255,7 @@
[USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
[USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
+ [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
};
static const audio_usecase_t offload_usecases[] = {
@@ -849,7 +850,7 @@
if (SND_DEVICE_OUT_BT_A2DP == snd_device)
audio_extn_a2dp_stop_playback();
- if (snd_device == SND_DEVICE_OUT_HDMI)
+ if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
adev->is_channel_status_set = false;
else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
adev->native_playback_enabled) {
@@ -1084,6 +1085,13 @@
reset_hdmi_sink_caps(out);
+ /* Cache ext disp type */
+ ret = platform_get_ext_disp_type(adev->platform);
+ if (ret < 0) {
+ ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
+ return ret;
+ }
+
switch (channels) {
case 8:
ALOGV("%s: HDMI supports 7.1 channels", __func__);
@@ -4108,7 +4116,12 @@
if (ret >= 0) {
val = atoi(value);
if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
- ALOGV("cache new edid");
+ ALOGV("cache new ext disp type and edid");
+ ret = platform_get_ext_disp_type(adev->platform);
+ if (ret < 0) {
+ ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
+ return ret;
+ }
platform_cache_edid(adev->platform);
} else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
!(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 664d1fc..c1797bd 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -146,6 +146,8 @@
USECASE_AUDIO_PLAYBACK_AFE_PROXY,
USECASE_AUDIO_RECORD_AFE_PROXY,
+ USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE,
+
AUDIO_USECASE_MAX
};
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 6309ce2..7fe114b 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -68,7 +68,6 @@
#define PLATFORM_INFO_XML_PATH_EXTCODEC "/system/etc/audio_platform_info_extcodec.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
-#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
#define CVD_VERSION_MIXER_CTL "CVD Version"
#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
@@ -243,6 +242,7 @@
struct csd_data *csd;
void *edid_info;
bool edid_valid;
+ int ext_disp_type;
codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
char ec_ref_mixer_path[64];
@@ -318,6 +318,7 @@
AFE_PROXY_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
AFE_PROXY_RECORD_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
};
/* Array to store sound devices */
@@ -346,6 +347,8 @@
[SND_DEVICE_OUT_VOICE_LINE] = "voice-line",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
+ [SND_DEVICE_OUT_DISPLAY_PORT] = "display-port",
+ [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
[SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
[SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
[SND_DEVICE_OUT_BT_A2DP] = "bt-a2dp",
@@ -467,6 +470,8 @@
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
+ [SND_DEVICE_OUT_DISPLAY_PORT] = 18,
+ [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = 14,
[SND_DEVICE_OUT_BT_SCO] = 22,
[SND_DEVICE_OUT_BT_SCO_WB] = 39,
[SND_DEVICE_OUT_BT_A2DP] = 20,
@@ -590,6 +595,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_LINE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_DISPLAY_PORT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_A2DP)},
@@ -712,6 +719,7 @@
{TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
{TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
{TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE)},
};
#define NO_COLS 2
@@ -1203,6 +1211,8 @@
backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+ backend_tag_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("display-port");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("speaker-and-display-port");
backend_tag_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
backend_tag_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
backend_tag_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
@@ -1219,6 +1229,8 @@
hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
+ hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
@@ -1672,6 +1684,7 @@
my_data->slowtalk = false;
my_data->hd_voice = false;
my_data->edid_info = NULL;
+ my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
my_data->is_wsa_speaker = false;
my_data->hw_dep_fd = -1;
@@ -1932,6 +1945,13 @@
my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
strdup("HDMI_RX Channels");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("Display Port RX Bit Format");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("Display Port RX SampleRate");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
+ strdup("Display Port RX Channels");
+
ret = audio_extn_utils_get_codec_version(snd_card_name,
my_data->adev->snd_card,
my_data->codec_version);
@@ -2462,6 +2482,8 @@
port = HEADPHONE_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
port = HDMI_RX_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "display-port") == 0)
+ port = DISP_PORT_RX_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
port = USB_AUDIO_RX_BACKEND;
}
@@ -2824,6 +2846,19 @@
new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_DISPLAY_PORT)) {
+ *num_devices = 2;
+
+ if (my_data->is_vbat_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_WSA;
+ else
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+
+ new_snd_devices[1] = SND_DEVICE_OUT_DISPLAY_PORT;
+ status = true;
} else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
!platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
*num_devices = 2;
@@ -2842,6 +2877,42 @@
return status;
}
+int platform_get_ext_disp_type(void *platform)
+{
+ int disp_type;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (my_data->ext_disp_type != EXT_DISPLAY_TYPE_NONE) {
+ ALOGD("%s: Returning cached ext disp type:%s",
+ __func__, (my_data->ext_disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+ return my_data->ext_disp_type;
+ }
+
+#ifdef DISPLAY_PORT_ENABLED
+ struct audio_device *adev = my_data->adev;
+ struct mixer_ctl *ctl;
+ char *mixer_ctl_name = "External Display Type";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ disp_type = mixer_ctl_get_value(ctl, 0);
+ if (disp_type == EXT_DISPLAY_TYPE_NONE) {
+ ALOGE("%s: Invalid external display type: %d", __func__, disp_type);
+ return -EINVAL;
+ }
+#else
+ disp_type = EXT_DISPLAY_TYPE_HDMI;
+#endif
+ my_data->ext_disp_type = disp_type;
+ ALOGD("%s: ext disp type:%s", __func__, (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+ return disp_type;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -2899,7 +2970,17 @@
snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
} else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT;
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ goto exit;
+ }
} else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_OUT_SPEAKER)) {
snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
@@ -3043,7 +3124,17 @@
else
snd_device = SND_DEVICE_OUT_BT_SCO;
} else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
- snd_device = SND_DEVICE_OUT_HDMI ;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ snd_device = SND_DEVICE_OUT_HDMI;
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ goto exit;
+ }
} else if (devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
snd_device = SND_DEVICE_OUT_BT_A2DP;
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
@@ -3468,7 +3559,7 @@
struct audio_device *adev = my_data->adev;
struct mixer_ctl *ctl;
const char *channel_cnt_str = NULL;
- const char *mixer_ctl_name = "HDMI_RX Channels";
+ char *mixer_ctl_name;
switch (channel_count) {
case 8:
channel_cnt_str = "Eight"; break;
@@ -3485,13 +3576,25 @@
default:
channel_cnt_str = "Two"; break;
}
+
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mixer_ctl_name = "HDMI_RX Channels";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mixer_ctl_name = "Display Port RX Channels";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
__func__, mixer_ctl_name);
return -EINVAL;
}
- ALOGV("HDMI channel count: %s", channel_cnt_str);
+ ALOGV("Ext disp channel count: %s", channel_cnt_str);
mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
return 0;
}
@@ -4162,7 +4265,7 @@
mixer_ctl_set_enum_by_string(ctl, rate_str);
my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
}
- if ((backend_idx == HDMI_RX_BACKEND) &&
+ if ((backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) &&
(channels != my_data->current_backend_cfg[backend_idx].channels)) {
struct mixer_ctl *ctl;
char *channel_cnt_str = NULL;
@@ -4199,22 +4302,32 @@
my_data->current_backend_cfg[backend_idx].channels_mixer_ctl, channel_cnt_str);
}
- if (backend_idx == HDMI_RX_BACKEND) {
- const char *hdmi_format_ctrl = "HDMI RX Format";
- struct mixer_ctl *ctl;
- ctl = mixer_get_ctl_by_name(adev->mixer,hdmi_format_ctrl);
+ bool set_ext_disp_format = false;
+ char *ext_disp_format = NULL;
+ if (backend_idx == HDMI_RX_BACKEND) {
+ ext_disp_format = "HDMI RX Format";
+ set_ext_disp_format = true;
+ } else if (backend_idx == DISP_PORT_RX_BACKEND) {
+ ext_disp_format = "Display Port Rx Format";
+ set_ext_disp_format = true;
+ } else {
+ ALOGV("%s: Format doesnt have to be set", __func__);
+ }
+
+ if (set_ext_disp_format) {
+ struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, ext_disp_format);
if (!ctl) {
ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
- __func__, hdmi_format_ctrl);
+ __func__, ext_disp_format);
return -EINVAL;
}
if (passthrough_enabled) {
- ALOGD("%s:HDMI compress format", __func__);
+ ALOGD("%s:Ext display compress format", __func__);
mixer_ctl_set_enum_by_string(ctl, "Compr");
} else {
- ALOGD("%s: HDMI PCM format", __func__);
+ ALOGD("%s: Ext display PCM format", __func__);
mixer_ctl_set_enum_by_string(ctl, "LPCM");
}
}
@@ -4228,6 +4341,7 @@
*/
static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
struct audio_usecase* usecase,
+ int backend_idx,
struct audio_backend_cfg *hdmi_backend_cfg)
{
unsigned int bit_width;
@@ -4261,13 +4375,13 @@
//Check EDID info for supported samplerate
if (!edid_is_supported_sr(edid_info,sample_rate)) {
//reset to current sample rate
- sample_rate = my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate;
+ sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
}
//Check EDID info for supported bit width
if (!edid_is_supported_bps(edid_info,bit_width)) {
//reset to current sample rate
- bit_width = my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width;
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
}
if (channels > max_supported_channels)
@@ -4430,7 +4544,7 @@
hdmi_backend_cfg.channels = channels;
hdmi_backend_cfg.passthrough_enabled = false;
- platform_check_hdmi_backend_cfg(adev, usecase, &hdmi_backend_cfg);
+ platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
bit_width = hdmi_backend_cfg.bit_width;
sample_rate = hdmi_backend_cfg.sample_rate;
@@ -4879,7 +4993,7 @@
struct audio_device *adev = my_data->adev;
char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
int ret, count;
-
+ char *mix_ctl_name;
struct mixer_ctl *ctl;
char edid_data[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE + 1] = {0};
edid_audio_info *info;
@@ -4889,17 +5003,28 @@
return 0;
}
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mix_ctl_name = "HDMI EDID";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mix_ctl_name = "Display Port EDID";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
+
if (my_data->edid_info == NULL) {
my_data->edid_info =
(struct edid_audio_info *)calloc(1, sizeof(struct edid_audio_info));
}
info = my_data->edid_info;
-
- ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
+ ctl = mixer_get_ctl_by_name(adev->mixer, mix_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
- __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
+ __func__, mix_ctl_name);
goto fail;
}
@@ -4918,8 +5043,9 @@
}
edid_data[0] = count;
memcpy(&edid_data[1], block, count);
+
if (!edid_get_sink_caps(info, edid_data)) {
- ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
+ ALOGE("%s: Failed to get extn disp sink capabilities", __func__);
goto fail;
}
my_data->edid_valid = true;
@@ -4938,16 +5064,28 @@
int platform_set_channel_allocation(void *platform, int channel_alloc)
{
struct mixer_ctl *ctl;
- const char *mixer_ctl_name = "HDMI RX CA";
+ char *mixer_ctl_name;
int ret;
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mixer_ctl_name = "HDMI RX CA";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mixer_ctl_name = "Display Port RX CA";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
+
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
__func__, mixer_ctl_name);
- ret = EINVAL;
+ return -EINVAL;
}
ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
@@ -4962,7 +5100,7 @@
int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd_id)
{
struct mixer_ctl *ctl;
- char mixer_ctl_name[44]; // max length of name is 44 as defined
+ char mixer_ctl_name[44] = {0}; // max length of name is 44 as defined
int ret;
unsigned int i;
int set_values[8] = {0};
@@ -5178,16 +5316,25 @@
void platform_invalidate_hdmi_config(void * platform)
{
+ //reset ext display EDID info
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
- //reset HDMI_RX_BACKEND to default values
- my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
- my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+ if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_HDMI) {
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ } else {
+ //reset Display port BACKEND to default values
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ }
+ my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 6c89d0a..516a298 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -96,6 +96,8 @@
SND_DEVICE_OUT_VOICE_LINE,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+ SND_DEVICE_OUT_DISPLAY_PORT,
+ SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
SND_DEVICE_OUT_BT_SCO,
SND_DEVICE_OUT_BT_SCO_WB,
SND_DEVICE_OUT_BT_A2DP,
@@ -218,6 +220,7 @@
HEADPHONE_BACKEND,
SLIMBUS_6_RX = HEADPHONE_BACKEND,
HDMI_RX_BACKEND,
+ DISP_PORT_RX_BACKEND,
USB_AUDIO_RX_BACKEND,
MAX_CODEC_BACKENDS
};
@@ -281,6 +284,7 @@
#define AUDIO_RECORD_PCM_DEVICE 0
#define MULTIMEDIA2_PCM_DEVICE 1
#define MULTIMEDIA3_PCM_DEVICE 4
+#define MULTIMEDIA9_PCM_DEVICE 32
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index e5d42bd..f3c4d28 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -667,6 +667,11 @@
return -ENOSYS;
}
+int platform_get_ext_disp_type(void *platform)
+{
+ return EXT_DISPLAY_TYPE_HDMI;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 07060b6..c9ac74a 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -63,6 +63,8 @@
SND_DEVICE_OUT_VOICE_HEADPHONES,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+ SND_DEVICE_OUT_DISPLAY_PORT,
+ SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
SND_DEVICE_OUT_BT_SCO,
SND_DEVICE_OUT_BT_A2DP,
SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP,
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 24bee89..ff062b6 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -57,7 +57,6 @@
#include <linux/msm_audio.h>
#define LIB_ACDB_LOADER "libacdbloader.so"
-#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
#define CVD_VERSION_MIXER_CTL "CVD Version"
#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
@@ -237,6 +236,7 @@
struct csd_data *csd;
void *edid_info;
bool edid_valid;
+ int ext_disp_type;
char ec_ref_mixer_path[64];
codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
@@ -322,6 +322,7 @@
AFE_PROXY_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
AFE_PROXY_RECORD_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
};
@@ -350,6 +351,8 @@
[SND_DEVICE_OUT_VOICE_LINE] = "voice-line",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
+ [SND_DEVICE_OUT_DISPLAY_PORT] = "display-port",
+ [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = "speaker-and-display-port",
[SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
[SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
[SND_DEVICE_OUT_BT_A2DP] = "bt-a2dp",
@@ -467,6 +470,8 @@
[SND_DEVICE_OUT_VOICE_LINE] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
+ [SND_DEVICE_OUT_DISPLAY_PORT] = 18,
+ [SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = 14,
[SND_DEVICE_OUT_BT_SCO] = 22,
[SND_DEVICE_OUT_BT_SCO_WB] = 39,
[SND_DEVICE_OUT_BT_A2DP] = 20,
@@ -586,6 +591,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_LINE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_DISPLAY_PORT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
{TO_NAME_INDEX(SND_DEVICE_OUT_BT_A2DP)},
@@ -707,6 +714,7 @@
{TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE)},
};
#define NO_COLS 2
@@ -1098,6 +1106,8 @@
backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+ backend_tag_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("display-port");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("speaker-and-display-port");
backend_tag_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
backend_tag_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
backend_tag_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
@@ -1117,6 +1127,8 @@
hw_interface_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("SLIMBUS_5_RX");
hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
+ hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
@@ -1527,6 +1539,7 @@
my_data->slowtalk = false;
my_data->hd_voice = false;
my_data->edid_info = NULL;
+ my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
my_data->hw_dep_fd = -1;
property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
@@ -1774,6 +1787,12 @@
strdup("HDMI_RX SampleRate");
my_data->current_backend_cfg[HDMI_RX_BACKEND].channels_mixer_ctl =
strdup("HDMI_RX Channels");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("Display Port RX Bit Format");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("Display Port RX SampleRate");
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels_mixer_ctl =
+ strdup("Display Port RX Channels");
my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
strdup("USB_AUDIO_RX Format");
@@ -2315,6 +2334,8 @@
port = HEADPHONE_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
port = HDMI_RX_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "display-port") == 0)
+ port = DISP_PORT_RX_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
port = USB_AUDIO_RX_BACKEND;
}
@@ -2672,6 +2693,12 @@
new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_DISPLAY_PORT)) {
+ *num_devices = 2;
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+ new_snd_devices[1] = SND_DEVICE_OUT_DISPLAY_PORT;
+ status = true;
} else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
!platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
*num_devices = 2;
@@ -2691,6 +2718,43 @@
return status;
}
+int platform_get_ext_disp_type(void *platform)
+{
+ int disp_type;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (my_data->ext_disp_type != EXT_DISPLAY_TYPE_NONE) {
+ ALOGD("%s: Returning cached ext disp type:%s",
+ __func__, (my_data->ext_disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+ return my_data->ext_disp_type;
+ }
+
+#ifdef DISPLAY_PORT_ENABLED
+ struct audio_device *adev = my_data->adev;
+ struct mixer_ctl *ctl;
+ char *mixer_ctl_name = "External Display Type";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ disp_type = mixer_ctl_get_value(ctl, 0);
+ if (disp_type == EXT_DISPLAY_TYPE_NONE) {
+ ALOGE("%s: Invalid external display type: %d", __func__, disp_type);
+ return -EINVAL;
+ }
+#else
+ disp_type = EXT_DISPLAY_TYPE_HDMI;
+#endif
+
+ my_data->ext_disp_type = disp_type;
+ ALOGD("%s: ext disp type:%s", __func__, (disp_type == EXT_DISPLAY_TYPE_DP) ? "DisplayPort" : "HDMI");
+ return disp_type;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -2736,7 +2800,17 @@
snd_device = SND_DEVICE_OUT_SPEAKER_AND_LINE;
} else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT;
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ goto exit;
+ }
} else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_OUT_SPEAKER)) {
snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
@@ -2861,7 +2935,17 @@
} else if (devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
snd_device = SND_DEVICE_OUT_BT_A2DP;
} else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
- snd_device = SND_DEVICE_OUT_HDMI ;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ snd_device = SND_DEVICE_OUT_HDMI;
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ snd_device = SND_DEVICE_OUT_DISPLAY_PORT;
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ goto exit;
+ }
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
@@ -3267,7 +3351,7 @@
struct audio_device *adev = my_data->adev;
struct mixer_ctl *ctl;
const char *channel_cnt_str = NULL;
- const char *mixer_ctl_name = "HDMI_RX Channels";
+ char *mixer_ctl_name;
switch (channel_count) {
case 8:
channel_cnt_str = "Eight"; break;
@@ -3284,13 +3368,26 @@
default:
channel_cnt_str = "Two"; break;
}
+
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mixer_ctl_name = "HDMI_RX Channels";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mixer_ctl_name = "Display Port RX Channels";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
+
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
__func__, mixer_ctl_name);
return -EINVAL;
}
- ALOGV("HDMI channel count: %s", channel_cnt_str);
+ ALOGV("Ext disp channel count: %s", channel_cnt_str);
mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
return 0;
}
@@ -4199,7 +4296,7 @@
mixer_ctl_set_enum_by_string(ctl, rate_str);
my_data->current_backend_cfg[backend_idx].sample_rate = sample_rate;
}
- if ((backend_idx == HDMI_RX_BACKEND) &&
+ if ((backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) &&
(channels != my_data->current_backend_cfg[backend_idx].channels)) {
struct mixer_ctl *ctl;
char *channel_cnt_str = NULL;
@@ -4236,22 +4333,32 @@
my_data->current_backend_cfg[backend_idx].channels_mixer_ctl, channel_cnt_str);
}
- if (backend_idx == HDMI_RX_BACKEND) {
- const char *hdmi_format_ctrl = "HDMI RX Format";
- struct mixer_ctl *ctl;
- ctl = mixer_get_ctl_by_name(adev->mixer,hdmi_format_ctrl);
+ bool set_ext_disp_format = false;
+ char *ext_disp_format = NULL;
+ if (backend_idx == HDMI_RX_BACKEND) {
+ ext_disp_format = "HDMI RX Format";
+ set_ext_disp_format = true;
+ } else if (backend_idx == DISP_PORT_RX_BACKEND) {
+ ext_disp_format = "Display Port Rx Format";
+ set_ext_disp_format = true;
+ } else {
+ ALOGV("%s: Format doesnt have to be set", __func__);
+ }
+
+ if (set_ext_disp_format) {
+ struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, ext_disp_format);
if (!ctl) {
ALOGE("%s:becf: afe: Could not get ctl for mixer command - %s",
- __func__, hdmi_format_ctrl);
+ __func__, ext_disp_format);
return -EINVAL;
}
if (passthrough_enabled) {
- ALOGD("%s:HDMI compress format", __func__);
+ ALOGD("%s:Ext display compress format", __func__);
mixer_ctl_set_enum_by_string(ctl, "Compr");
} else {
- ALOGD("%s: HDMI PCM format", __func__);
+ ALOGD("%s: Ext display PCM format", __func__);
mixer_ctl_set_enum_by_string(ctl, "LPCM");
}
}
@@ -4276,6 +4383,7 @@
*/
static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
struct audio_usecase* usecase,
+ int backend_idx,
struct audio_backend_cfg *hdmi_backend_cfg)
{
unsigned int bit_width;
@@ -4309,13 +4417,13 @@
//Check EDID info for supported samplerate
if (!edid_is_supported_sr(edid_info,sample_rate)) {
//reset to current sample rate
- sample_rate = my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate;
+ sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
}
//Check EDID info for supported bit width
if (!edid_is_supported_bps(edid_info,bit_width)) {
//reset to current sample rate
- bit_width = my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width;
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
}
if (channels > max_supported_channels)
@@ -4469,14 +4577,14 @@
__func__, bit_width, sample_rate, channels);
}
- if (backend_idx == HDMI_RX_BACKEND) {
+ if (backend_idx == HDMI_RX_BACKEND || backend_idx == DISP_PORT_RX_BACKEND) {
struct audio_backend_cfg hdmi_backend_cfg;
hdmi_backend_cfg.bit_width = bit_width;
hdmi_backend_cfg.sample_rate = sample_rate;
hdmi_backend_cfg.channels = channels;
hdmi_backend_cfg.passthrough_enabled = false;
- platform_check_hdmi_backend_cfg(adev, usecase, &hdmi_backend_cfg);
+ platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
bit_width = hdmi_backend_cfg.bit_width;
sample_rate = hdmi_backend_cfg.sample_rate;
@@ -4927,7 +5035,7 @@
struct audio_device *adev = my_data->adev;
char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
int ret, count;
-
+ char *mix_ctl_name;
struct mixer_ctl *ctl;
char edid_data[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE + 1] = {0};
edid_audio_info *info;
@@ -4937,17 +5045,28 @@
return 0;
}
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mix_ctl_name = "HDMI EDID";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mix_ctl_name = "Display Port EDID";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
+
if (my_data->edid_info == NULL) {
my_data->edid_info =
(struct edid_audio_info *)calloc(1, sizeof(struct edid_audio_info));
}
info = my_data->edid_info;
-
- ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
+ ctl = mixer_get_ctl_by_name(adev->mixer, mix_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
- __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
+ __func__, mix_ctl_name);
goto fail;
}
@@ -4968,7 +5087,7 @@
memcpy(&edid_data[1], block, count);
if (!edid_get_sink_caps(info, edid_data)) {
- ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
+ ALOGE("%s: Failed to get extn disp sink capabilities", __func__);
goto fail;
}
my_data->edid_valid = true;
@@ -4987,16 +5106,28 @@
int platform_set_channel_allocation(void *platform, int channel_alloc)
{
struct mixer_ctl *ctl;
- const char *mixer_ctl_name = "HDMI RX CA";
+ char *mixer_ctl_name;
int ret;
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
+ switch(my_data->ext_disp_type) {
+ case EXT_DISPLAY_TYPE_HDMI:
+ mixer_ctl_name = "HDMI RX CA";
+ break;
+ case EXT_DISPLAY_TYPE_DP:
+ mixer_ctl_name = "Display Port RX CA";
+ break;
+ default:
+ ALOGE("%s: Invalid disp_type %d", __func__, my_data->ext_disp_type);
+ return -EINVAL;
+ }
+
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
__func__, mixer_ctl_name);
- ret = EINVAL;
+ return -EINVAL;
}
ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
@@ -5228,17 +5359,25 @@
void platform_invalidate_hdmi_config(void * platform)
{
- //reset HDMI EDID info
+ //reset ext display EDID info
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
- //reset HDMI_RX_BACKEND to default values
- my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
- my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ if (my_data->ext_disp_type == EXT_DISPLAY_TYPE_HDMI) {
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ } else {
+ //reset Display port BACKEND to default values
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].channels = DEFAULT_HDMI_OUT_CHANNELS;
+ my_data->current_backend_cfg[DISP_PORT_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ }
+ my_data->ext_disp_type = EXT_DISPLAY_TYPE_NONE;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9394ef8..9b8c01b 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -93,6 +93,8 @@
SND_DEVICE_OUT_VOICE_LINE,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
+ SND_DEVICE_OUT_DISPLAY_PORT,
+ SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT,
SND_DEVICE_OUT_BT_SCO,
SND_DEVICE_OUT_BT_SCO_WB,
SND_DEVICE_OUT_BT_A2DP,
@@ -210,6 +212,7 @@
HEADPHONE_BACKEND,
SLIMBUS_6_RX = HEADPHONE_BACKEND,
HDMI_RX_BACKEND,
+ DISP_PORT_RX_BACKEND,
USB_AUDIO_RX_BACKEND,
MAX_CODEC_BACKENDS
};
@@ -273,6 +276,7 @@
#define AUDIO_RECORD_PCM_DEVICE 0
#define MULTIMEDIA2_PCM_DEVICE 1
#define MULTIMEDIA3_PCM_DEVICE 4
+#define MULTIMEDIA9_PCM_DEVICE 32
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
diff --git a/hal/platform_api.h b/hal/platform_api.h
index ec64206..25ff64c 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -158,4 +158,5 @@
bool platform_check_codec_dsd_support(void *platform);
bool platform_check_codec_asrc_support(void *platform);
int platform_get_backend_index(snd_device_t snd_device);
+int platform_get_ext_disp_type(void *platform);
#endif // AUDIO_PLATFORM_API_H