hal: enable audio over display port
Add support for audio over display port.
Change-Id: I3480d89c61ee5e5983715ec943fb02b1a9d5d151
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