Loading include/sound/apr_audio-v2.h +119 −0 Original line number Diff line number Diff line Loading @@ -789,6 +789,7 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SECONDARY_PCM_RX 0x100C #define AFE_PORT_ID_SECONDARY_PCM_TX 0x100D #define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E #define AFE_PORT_ID_SPDIF_RX 0x5000 #define AFE_PORT_ID_RT_PROXY_PORT_001_RX 0x2000 #define AFE_PORT_ID_RT_PROXY_PORT_001_TX 0x2001 #define AFE_PORT_ID_INTERNAL_BT_SCO_RX 0x3000 Loading Loading @@ -1411,6 +1412,123 @@ struct afe_param_id_i2s_cfg { /* * This param id is used to configure PCM interface */ #define AFE_API_VERSION_SPDIF_CONFIG 0x1 #define AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG 0x1 #define AFE_API_VERSION_SPDIF_CLK_CONFIG 0x1 #define AFE_CH_STATUS_A 1 #define AFE_CH_STATUS_B 2 #define AFE_PARAM_ID_SPDIF_CONFIG 0x00010244 #define AFE_PARAM_ID_CH_STATUS_CONFIG 0x00010245 #define AFE_PARAM_ID_SPDIF_CLK_CONFIG 0x00010246 #define AFE_PORT_CLK_ROOT_LPAPLL 0x3 #define AFE_PORT_CLK_ROOT_LPAQ6PLL 0x4 struct afe_param_id_spdif_cfg { /* Minor version used for tracking the version of the SPDIF * configuration interface. * Supported values: #AFE_API_VERSION_SPDIF_CONFIG */ u32 spdif_cfg_minor_version; /* Sampling rate of the port. * Supported values: * - #AFE_PORT_SAMPLE_RATE_22_05K * - #AFE_PORT_SAMPLE_RATE_32K * - #AFE_PORT_SAMPLE_RATE_44_1K * - #AFE_PORT_SAMPLE_RATE_48K * - #AFE_PORT_SAMPLE_RATE_96K * - #AFE_PORT_SAMPLE_RATE_176_4K * - #AFE_PORT_SAMPLE_RATE_192K */ u32 sample_rate; /* data format * Supported values: * - #AFE_LINEAR_PCM_DATA * - #AFE_NON_LINEAR_DATA */ u16 data_format; /* Number of channels supported by the port * - PCM - 1, Compressed Case - 2 */ u16 num_channels; /* Bit width of the sample. * Supported values: 16, 24 */ u16 bit_width; /* This field must be set to zero. */ u16 reserved; } __packed; struct afe_param_id_spdif_ch_status_cfg { u32 ch_status_cfg_minor_version; /* Minor version used for tracking the version of channel * status configuration. Current supported version is 1 */ u32 status_type; /* Indicate if the channel status is for channel A or B * Supported values: * - #AFE_CH_STATUS_A * - #AFE_CH_STATUS_B */ u8 status_bits[24]; /* Channel status - 192 bits for channel * Byte ordering as defined by IEC60958-3 */ u8 status_mask[24]; /* Channel status with mask bits 1 will be applied. * Byte ordering as defined by IEC60958-3 */ } __packed; struct afe_param_id_spdif_clk_cfg { u32 clk_cfg_minor_version; /* Minor version used for tracking the version of SPDIF * interface clock configuration. Current supported version * is 1 */ u32 clk_value; /* Specifies the clock frequency in Hz to set * Supported values: * 0 - Disable the clock * 2 (byphase) * 32 (60958 subframe size) * sampling rate * 2 * (channels A and B) */ u32 clk_root; /* Specifies SPDIF root clk source * Supported Values: * - #AFE_PORT_CLK_ROOT_LPAPLL * - #AFE_PORT_CLK_ROOT_LPAQ6PLL */ } __packed; struct afe_spdif_clk_config_command { struct apr_hdr hdr; struct afe_port_cmd_set_param_v2 param; struct afe_port_param_data_v2 pdata; struct afe_param_id_spdif_clk_cfg clk_cfg; } __packed; struct afe_spdif_chstatus_config_command { struct apr_hdr hdr; struct afe_port_cmd_set_param_v2 param; struct afe_port_param_data_v2 pdata; struct afe_param_id_spdif_ch_status_cfg ch_status; } __packed; struct afe_spdif_port_config { struct afe_param_id_spdif_cfg cfg; struct afe_param_id_spdif_ch_status_cfg ch_status; } __packed; #define AFE_PARAM_ID_PCM_CONFIG 0x0001020E #define AFE_API_VERSION_PCM_CONFIG 0x1 /* Enumeration for the auxiliary PCM synchronization signal Loading Loading @@ -2017,6 +2135,7 @@ union afe_port_config { struct afe_param_id_internal_bt_fm_cfg int_bt_fm; struct afe_param_id_pseudo_port_cfg pseudo_port; struct afe_param_id_device_hw_delay_cfg hw_delay; struct afe_param_id_spdif_cfg spdif; } __packed; struct afe_audioif_config_command_no_payload { Loading include/sound/q6afe-v2.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2014, 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 Loading Loading @@ -86,6 +86,7 @@ enum { IDX_VOICE2_PLAYBACK_TX = 44, IDX_SLIMBUS_6_RX = 45, IDX_SLIMBUS_6_TX = 46, IDX_SPDIF_RX = 47, IDX_GLOBAL_CFG, IDX_AUDIO_PORT_ID_I2S_RX, AFE_MAX_PORTS Loading Loading @@ -197,6 +198,14 @@ int afe_set_lpass_internal_digital_codec_clock(u16 port_id, struct afe_digital_clk_cfg *cfg); int q6afe_check_osr_clk_freq(u32 freq); int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg, u16 port_id); int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg *ch_status_cfg, u16 port_id); int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port, u32 rate); int afe_turn_onoff_hw_mad(u16 mad_type, u16 mad_enable); int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type); enum afe_mad_type afe_port_get_mad_type(u16 port_id); Loading sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +330 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,11 @@ #define MSM_DAI_PRI_AUXPCM_DT_DEV_ID 1 #define MSM_DAI_SEC_AUXPCM_DT_DEV_ID 2 #define spdif_clock_value(rate) (2*rate*32*2) #define CHANNEL_STATUS_SIZE 24 #define CHANNEL_STATUS_MASK_INIT 0x0 #define CHANNEL_STATUS_MASK 0x4 static const struct afe_clk_cfg lpass_clk_cfg_default = { AFE_API_VERSION_I2S_CONFIG, Q6AFE_LPASS_OSR_CLK_2_P048_MHZ, Loading Loading @@ -63,6 +68,14 @@ struct msm_dai_q6_dai_data { union afe_port_config port_config; }; struct msm_dai_q6_spdif_dai_data { DECLARE_BITMAP(status_mask, STATUS_MAX); u32 rate; u32 channels; u32 bitwidth; struct afe_spdif_port_config spdif_port; }; struct msm_dai_q6_mi2s_dai_config { u16 pdata_mi2s_lines; struct msm_dai_q6_dai_data mi2s_dai_data; Loading Loading @@ -527,6 +540,274 @@ static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_dai[] = { } }; static int msm_dai_q6_spdif_format_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; int value = ucontrol->value.integer.value[0]; dai_data->spdif_port.cfg.data_format = value; pr_debug("%s: value = %d\n", __func__, value); return 0; } static int msm_dai_q6_spdif_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; ucontrol->value.integer.value[0] = dai_data->spdif_port.cfg.data_format; return 0; } static const char * const spdif_format[] = { "LPCM", "Compr" }; static const struct soc_enum spdif_config_enum[] = { SOC_ENUM_SINGLE_EXT(2, spdif_format), }; static int msm_dai_q6_spdif_chstatus_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; int ret = 0; dai_data->spdif_port.ch_status.status_type = AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG; memset(dai_data->spdif_port.ch_status.status_mask, CHANNEL_STATUS_MASK_INIT, CHANNEL_STATUS_SIZE); dai_data->spdif_port.ch_status.status_mask[0] = CHANNEL_STATUS_MASK; memcpy(dai_data->spdif_port.ch_status.status_bits, ucontrol->value.iec958.status, CHANNEL_STATUS_SIZE); if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { pr_debug("%s: Port already started. Dynamic update\n", __func__); ret = afe_send_spdif_ch_status_cfg( &dai_data->spdif_port.ch_status, AFE_PORT_ID_SPDIF_RX); } return ret; } static int msm_dai_q6_spdif_chstatus_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; memcpy(ucontrol->value.iec958.status, dai_data->spdif_port.ch_status.status_bits, CHANNEL_STATUS_SIZE); return 0; } static int msm_dai_q6_spdif_chstatus_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } static const struct snd_kcontrol_new spdif_config_controls[] = { { .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE), .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), .info = msm_dai_q6_spdif_chstatus_info, .get = msm_dai_q6_spdif_chstatus_get, .put = msm_dai_q6_spdif_chstatus_put, }, SOC_ENUM_EXT("SPDIF RX Format", spdif_config_enum[0], msm_dai_q6_spdif_format_get, msm_dai_q6_spdif_format_put) }; static int msm_dai_q6_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); dai->id = AFE_PORT_ID_SPDIF_RX; dai_data->channels = params_channels(params); dai_data->spdif_port.cfg.num_channels = dai_data->channels; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dai_data->spdif_port.cfg.bit_width = 16; break; case SNDRV_PCM_FORMAT_S24_LE: dai_data->spdif_port.cfg.bit_width = 24; break; default: return -EINVAL; } dai_data->rate = params_rate(params); dai_data->bitwidth = dai_data->spdif_port.cfg.bit_width; dai_data->spdif_port.cfg.sample_rate = dai_data->rate; dai_data->spdif_port.cfg.spdif_cfg_minor_version = AFE_API_VERSION_SPDIF_CONFIG; dev_dbg(dai->dev, " channel %d sample rate %d bit width %d\n", dai_data->channels, dai_data->rate, dai_data->spdif_port.cfg.bit_width); dai_data->spdif_port.cfg.reserved = 0; return 0; } static void msm_dai_q6_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { pr_info("%s: afe port not started. dai_data->status_mask = %ld\n", __func__, *dai_data->status_mask); return; } rc = afe_close(dai->id); if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to close AFE port\n"); pr_debug("%s: dai_data->status_mask = %ld\n", __func__, *dai_data->status_mask); clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); } static int msm_dai_q6_spdif_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, "%s clk_config failed", __func__); return rc; } if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { rc = afe_spdif_port_start(dai->id, &dai_data->spdif_port, dai_data->rate); if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to open AFE port %x\n", dai->id); else set_bit(STATUS_PORT_STARTED, dai_data->status_mask); } return rc; } static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data; const struct snd_kcontrol_new *kcontrol; int rc = 0; struct snd_soc_dapm_route intercon; dai_data = kzalloc(sizeof(struct msm_dai_q6_spdif_dai_data), GFP_KERNEL); if (!dai_data) { dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n", AFE_PORT_ID_SPDIF_RX); rc = -ENOMEM; } else rc = dev_set_drvdata(dai->dev, dai_data); kcontrol = &spdif_config_controls[1]; rc = snd_ctl_add(dai->card->snd_card, snd_ctl_new1(kcontrol, dai_data)); memset(&intercon, 0 , sizeof(intercon)); if (!rc && dai && dai->driver) { if (dai->driver->playback.stream_name && dai->driver->playback.aif_name) { dev_dbg(dai->dev, "%s add route for widget %s", __func__, dai->driver->playback.stream_name); intercon.source = dai->driver->playback.aif_name; intercon.sink = dai->driver->playback.stream_name; dev_dbg(dai->dev, "%s src %s sink %s\n", __func__, intercon.source, intercon.sink); snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1); } if (dai->driver->capture.stream_name && dai->driver->capture.aif_name) { dev_dbg(dai->dev, "%s add route for widget %s", __func__, dai->driver->capture.stream_name); intercon.sink = dai->driver->capture.aif_name; intercon.source = dai->driver->capture.stream_name; dev_dbg(dai->dev, "%s src %s sink %s\n", __func__, intercon.source, intercon.sink); snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1); } } return rc; } static int msm_dai_q6_spdif_dai_remove(struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data; int rc; dai_data = dev_get_drvdata(dai->dev); /* If AFE port is still up, close it */ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { rc = afe_close(dai->id); /* can block */ if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to close AFE port\n"); clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); } kfree(dai_data); snd_soc_unregister_component(dai->dev); return 0; } static struct snd_soc_dai_ops msm_dai_q6_spdif_ops = { .prepare = msm_dai_q6_spdif_prepare, .hw_params = msm_dai_q6_spdif_hw_params, .shutdown = msm_dai_q6_spdif_shutdown, }; static struct snd_soc_dai_driver msm_dai_q6_spdif_spdif_rx_dai = { .playback = { .stream_name = "SPDIF Playback", .aif_name = "SPDIF_RX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 1, .channels_max = 4, .rate_min = 8000, .rate_max = 48000, }, .ops = &msm_dai_q6_spdif_ops, .probe = msm_dai_q6_spdif_dai_probe, .remove = msm_dai_q6_spdif_dai_remove, }; static const struct snd_soc_component_driver msm_dai_spdif_q6_component = { .name = "msm-dai-q6-spdif", }; static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { Loading Loading @@ -2668,6 +2949,46 @@ static struct platform_driver msm_dai_q6_mi2s_driver = { }, }; static int msm_dai_q6_spdif_dev_probe(struct platform_device *pdev) { int rc; pdev->id = AFE_PORT_ID_SPDIF_RX; dev_set_name(&pdev->dev, "%s", "msm-dai-q6-spdif"); pr_debug("%s: dev name %s, id:%d\n", __func__, dev_name(&pdev->dev), pdev->id); rc = snd_soc_register_component(&pdev->dev, &msm_dai_spdif_q6_component, &msm_dai_q6_spdif_spdif_rx_dai, 1); return rc; } static int msm_dai_q6_spdif_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); return 0; } static const struct of_device_id msm_dai_q6_spdif_dt_match[] = { {.compatible = "qcom,msm-dai-q6-spdif"}, {} }; MODULE_DEVICE_TABLE(of, msm_dai_q6_spdif_dt_match); static struct platform_driver msm_dai_q6_spdif_driver = { .probe = msm_dai_q6_spdif_dev_probe, .remove = msm_dai_q6_spdif_dev_remove, .driver = { .name = "msm-dai-q6-spdif", .owner = THIS_MODULE, .of_match_table = msm_dai_q6_spdif_dt_match, }, }; static int __init msm_dai_q6_init(void) { int rc; Loading Loading @@ -2701,8 +3022,16 @@ static int __init msm_dai_q6_init(void) pr_err("%s: fail to register dai MI2S\n", __func__); goto dai_mi2s_q6_fail; } rc = platform_driver_register(&msm_dai_q6_spdif_driver); if (rc) { pr_err("%s: fail to register dai SPDIF\n", __func__); goto dai_spdif_q6_fail; } return rc; dai_spdif_q6_fail: platform_driver_unregister(&msm_dai_q6_spdif_driver); dai_mi2s_q6_fail: platform_driver_unregister(&msm_dai_q6_mi2s_driver); dai_q6_mi2s_drv_fail: Loading @@ -2721,6 +3050,7 @@ static void __exit msm_dai_q6_exit(void) platform_driver_unregister(&msm_dai_q6_dev); platform_driver_unregister(&msm_dai_q6); platform_driver_unregister(&msm_auxpcm_dev_driver); platform_driver_unregister(&msm_dai_q6_spdif_driver); } module_exit(msm_dai_q6_exit); Loading sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +46 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0}, { SLIMBUS_6_RX, 0, 0, 0, 0, 0}, { SLIMBUS_6_TX, 0, 0, 0, 0, 0}, { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0}, }; Loading Loading @@ -1735,6 +1736,36 @@ static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = { msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SPDIF_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, Loading Loading @@ -3544,6 +3575,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SEC_I2S_RX", "Secondary I2S Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("SPDIF_RX", "SPDIF Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0), Loading Loading @@ -3640,6 +3672,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)), SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)), SND_SOC_DAPM_MIXER("SPDIF_RX Audio Mixer", SND_SOC_NOPM, 0, 0, spdif_rx_mixer_controls, ARRAY_SIZE(spdif_rx_mixer_controls)), SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)), SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, Loading Loading @@ -3849,6 +3883,17 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia9", "MM_DL9"}, {"HDMI", NULL, "HDMI Mixer"}, {"SPDIF_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"SPDIF_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"SPDIF_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, {"SPDIF_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, {"SPDIF_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, {"SPDIF_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, {"SPDIF_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, {"SPDIF_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, {"SPDIF_RX Audio Mixer", "MultiMedia9", "MM_DL9"}, {"SPDIF_RX", NULL, "SPDIF_RX Audio Mixer"}, /* incall */ {"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"}, {"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"}, Loading Loading @@ -4303,6 +4348,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "SLIMBUS_4_RX"}, {"BE_OUT", NULL, "SLIMBUS_6_RX"}, {"BE_OUT", NULL, "HDMI"}, {"BE_OUT", NULL, "SPDIF_RX"}, {"BE_OUT", NULL, "MI2S_RX"}, {"BE_OUT", NULL, "QUAT_MI2S_RX"}, {"BE_OUT", NULL, "TERT_MI2S_RX"}, Loading sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX" #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX" #define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX" #define LPASS_BE_SPDIF_RX "SPDIF_RX" #define LPASS_BE_MI2S_RX "MI2S_RX" #define LPASS_BE_MI2S_TX "MI2S_TX" Loading Loading @@ -135,6 +136,7 @@ enum { MSM_BACKEND_DAI_SEC_AUXPCM_TX, MSM_BACKEND_DAI_SLIMBUS_6_RX, MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_BACKEND_DAI_SPDIF_RX, MSM_BACKEND_DAI_MAX, }; Loading Loading
include/sound/apr_audio-v2.h +119 −0 Original line number Diff line number Diff line Loading @@ -789,6 +789,7 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SECONDARY_PCM_RX 0x100C #define AFE_PORT_ID_SECONDARY_PCM_TX 0x100D #define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E #define AFE_PORT_ID_SPDIF_RX 0x5000 #define AFE_PORT_ID_RT_PROXY_PORT_001_RX 0x2000 #define AFE_PORT_ID_RT_PROXY_PORT_001_TX 0x2001 #define AFE_PORT_ID_INTERNAL_BT_SCO_RX 0x3000 Loading Loading @@ -1411,6 +1412,123 @@ struct afe_param_id_i2s_cfg { /* * This param id is used to configure PCM interface */ #define AFE_API_VERSION_SPDIF_CONFIG 0x1 #define AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG 0x1 #define AFE_API_VERSION_SPDIF_CLK_CONFIG 0x1 #define AFE_CH_STATUS_A 1 #define AFE_CH_STATUS_B 2 #define AFE_PARAM_ID_SPDIF_CONFIG 0x00010244 #define AFE_PARAM_ID_CH_STATUS_CONFIG 0x00010245 #define AFE_PARAM_ID_SPDIF_CLK_CONFIG 0x00010246 #define AFE_PORT_CLK_ROOT_LPAPLL 0x3 #define AFE_PORT_CLK_ROOT_LPAQ6PLL 0x4 struct afe_param_id_spdif_cfg { /* Minor version used for tracking the version of the SPDIF * configuration interface. * Supported values: #AFE_API_VERSION_SPDIF_CONFIG */ u32 spdif_cfg_minor_version; /* Sampling rate of the port. * Supported values: * - #AFE_PORT_SAMPLE_RATE_22_05K * - #AFE_PORT_SAMPLE_RATE_32K * - #AFE_PORT_SAMPLE_RATE_44_1K * - #AFE_PORT_SAMPLE_RATE_48K * - #AFE_PORT_SAMPLE_RATE_96K * - #AFE_PORT_SAMPLE_RATE_176_4K * - #AFE_PORT_SAMPLE_RATE_192K */ u32 sample_rate; /* data format * Supported values: * - #AFE_LINEAR_PCM_DATA * - #AFE_NON_LINEAR_DATA */ u16 data_format; /* Number of channels supported by the port * - PCM - 1, Compressed Case - 2 */ u16 num_channels; /* Bit width of the sample. * Supported values: 16, 24 */ u16 bit_width; /* This field must be set to zero. */ u16 reserved; } __packed; struct afe_param_id_spdif_ch_status_cfg { u32 ch_status_cfg_minor_version; /* Minor version used for tracking the version of channel * status configuration. Current supported version is 1 */ u32 status_type; /* Indicate if the channel status is for channel A or B * Supported values: * - #AFE_CH_STATUS_A * - #AFE_CH_STATUS_B */ u8 status_bits[24]; /* Channel status - 192 bits for channel * Byte ordering as defined by IEC60958-3 */ u8 status_mask[24]; /* Channel status with mask bits 1 will be applied. * Byte ordering as defined by IEC60958-3 */ } __packed; struct afe_param_id_spdif_clk_cfg { u32 clk_cfg_minor_version; /* Minor version used for tracking the version of SPDIF * interface clock configuration. Current supported version * is 1 */ u32 clk_value; /* Specifies the clock frequency in Hz to set * Supported values: * 0 - Disable the clock * 2 (byphase) * 32 (60958 subframe size) * sampling rate * 2 * (channels A and B) */ u32 clk_root; /* Specifies SPDIF root clk source * Supported Values: * - #AFE_PORT_CLK_ROOT_LPAPLL * - #AFE_PORT_CLK_ROOT_LPAQ6PLL */ } __packed; struct afe_spdif_clk_config_command { struct apr_hdr hdr; struct afe_port_cmd_set_param_v2 param; struct afe_port_param_data_v2 pdata; struct afe_param_id_spdif_clk_cfg clk_cfg; } __packed; struct afe_spdif_chstatus_config_command { struct apr_hdr hdr; struct afe_port_cmd_set_param_v2 param; struct afe_port_param_data_v2 pdata; struct afe_param_id_spdif_ch_status_cfg ch_status; } __packed; struct afe_spdif_port_config { struct afe_param_id_spdif_cfg cfg; struct afe_param_id_spdif_ch_status_cfg ch_status; } __packed; #define AFE_PARAM_ID_PCM_CONFIG 0x0001020E #define AFE_API_VERSION_PCM_CONFIG 0x1 /* Enumeration for the auxiliary PCM synchronization signal Loading Loading @@ -2017,6 +2135,7 @@ union afe_port_config { struct afe_param_id_internal_bt_fm_cfg int_bt_fm; struct afe_param_id_pseudo_port_cfg pseudo_port; struct afe_param_id_device_hw_delay_cfg hw_delay; struct afe_param_id_spdif_cfg spdif; } __packed; struct afe_audioif_config_command_no_payload { Loading
include/sound/q6afe-v2.h +10 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2014, 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 Loading Loading @@ -86,6 +86,7 @@ enum { IDX_VOICE2_PLAYBACK_TX = 44, IDX_SLIMBUS_6_RX = 45, IDX_SLIMBUS_6_TX = 46, IDX_SPDIF_RX = 47, IDX_GLOBAL_CFG, IDX_AUDIO_PORT_ID_I2S_RX, AFE_MAX_PORTS Loading Loading @@ -197,6 +198,14 @@ int afe_set_lpass_internal_digital_codec_clock(u16 port_id, struct afe_digital_clk_cfg *cfg); int q6afe_check_osr_clk_freq(u32 freq); int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg, u16 port_id); int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg *ch_status_cfg, u16 port_id); int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port, u32 rate); int afe_turn_onoff_hw_mad(u16 mad_type, u16 mad_enable); int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type); enum afe_mad_type afe_port_get_mad_type(u16 port_id); Loading
sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +330 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,11 @@ #define MSM_DAI_PRI_AUXPCM_DT_DEV_ID 1 #define MSM_DAI_SEC_AUXPCM_DT_DEV_ID 2 #define spdif_clock_value(rate) (2*rate*32*2) #define CHANNEL_STATUS_SIZE 24 #define CHANNEL_STATUS_MASK_INIT 0x0 #define CHANNEL_STATUS_MASK 0x4 static const struct afe_clk_cfg lpass_clk_cfg_default = { AFE_API_VERSION_I2S_CONFIG, Q6AFE_LPASS_OSR_CLK_2_P048_MHZ, Loading Loading @@ -63,6 +68,14 @@ struct msm_dai_q6_dai_data { union afe_port_config port_config; }; struct msm_dai_q6_spdif_dai_data { DECLARE_BITMAP(status_mask, STATUS_MAX); u32 rate; u32 channels; u32 bitwidth; struct afe_spdif_port_config spdif_port; }; struct msm_dai_q6_mi2s_dai_config { u16 pdata_mi2s_lines; struct msm_dai_q6_dai_data mi2s_dai_data; Loading Loading @@ -527,6 +540,274 @@ static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_dai[] = { } }; static int msm_dai_q6_spdif_format_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; int value = ucontrol->value.integer.value[0]; dai_data->spdif_port.cfg.data_format = value; pr_debug("%s: value = %d\n", __func__, value); return 0; } static int msm_dai_q6_spdif_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; ucontrol->value.integer.value[0] = dai_data->spdif_port.cfg.data_format; return 0; } static const char * const spdif_format[] = { "LPCM", "Compr" }; static const struct soc_enum spdif_config_enum[] = { SOC_ENUM_SINGLE_EXT(2, spdif_format), }; static int msm_dai_q6_spdif_chstatus_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; int ret = 0; dai_data->spdif_port.ch_status.status_type = AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG; memset(dai_data->spdif_port.ch_status.status_mask, CHANNEL_STATUS_MASK_INIT, CHANNEL_STATUS_SIZE); dai_data->spdif_port.ch_status.status_mask[0] = CHANNEL_STATUS_MASK; memcpy(dai_data->spdif_port.ch_status.status_bits, ucontrol->value.iec958.status, CHANNEL_STATUS_SIZE); if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { pr_debug("%s: Port already started. Dynamic update\n", __func__); ret = afe_send_spdif_ch_status_cfg( &dai_data->spdif_port.ch_status, AFE_PORT_ID_SPDIF_RX); } return ret; } static int msm_dai_q6_spdif_chstatus_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data; memcpy(ucontrol->value.iec958.status, dai_data->spdif_port.ch_status.status_bits, CHANNEL_STATUS_SIZE); return 0; } static int msm_dai_q6_spdif_chstatus_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } static const struct snd_kcontrol_new spdif_config_controls[] = { { .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE), .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), .info = msm_dai_q6_spdif_chstatus_info, .get = msm_dai_q6_spdif_chstatus_get, .put = msm_dai_q6_spdif_chstatus_put, }, SOC_ENUM_EXT("SPDIF RX Format", spdif_config_enum[0], msm_dai_q6_spdif_format_get, msm_dai_q6_spdif_format_put) }; static int msm_dai_q6_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); dai->id = AFE_PORT_ID_SPDIF_RX; dai_data->channels = params_channels(params); dai_data->spdif_port.cfg.num_channels = dai_data->channels; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dai_data->spdif_port.cfg.bit_width = 16; break; case SNDRV_PCM_FORMAT_S24_LE: dai_data->spdif_port.cfg.bit_width = 24; break; default: return -EINVAL; } dai_data->rate = params_rate(params); dai_data->bitwidth = dai_data->spdif_port.cfg.bit_width; dai_data->spdif_port.cfg.sample_rate = dai_data->rate; dai_data->spdif_port.cfg.spdif_cfg_minor_version = AFE_API_VERSION_SPDIF_CONFIG; dev_dbg(dai->dev, " channel %d sample rate %d bit width %d\n", dai_data->channels, dai_data->rate, dai_data->spdif_port.cfg.bit_width); dai_data->spdif_port.cfg.reserved = 0; return 0; } static void msm_dai_q6_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { pr_info("%s: afe port not started. dai_data->status_mask = %ld\n", __func__, *dai_data->status_mask); return; } rc = afe_close(dai->id); if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to close AFE port\n"); pr_debug("%s: dai_data->status_mask = %ld\n", __func__, *dai_data->status_mask); clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); } static int msm_dai_q6_spdif_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, "%s clk_config failed", __func__); return rc; } if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { rc = afe_spdif_port_start(dai->id, &dai_data->spdif_port, dai_data->rate); if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to open AFE port %x\n", dai->id); else set_bit(STATUS_PORT_STARTED, dai_data->status_mask); } return rc; } static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data; const struct snd_kcontrol_new *kcontrol; int rc = 0; struct snd_soc_dapm_route intercon; dai_data = kzalloc(sizeof(struct msm_dai_q6_spdif_dai_data), GFP_KERNEL); if (!dai_data) { dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n", AFE_PORT_ID_SPDIF_RX); rc = -ENOMEM; } else rc = dev_set_drvdata(dai->dev, dai_data); kcontrol = &spdif_config_controls[1]; rc = snd_ctl_add(dai->card->snd_card, snd_ctl_new1(kcontrol, dai_data)); memset(&intercon, 0 , sizeof(intercon)); if (!rc && dai && dai->driver) { if (dai->driver->playback.stream_name && dai->driver->playback.aif_name) { dev_dbg(dai->dev, "%s add route for widget %s", __func__, dai->driver->playback.stream_name); intercon.source = dai->driver->playback.aif_name; intercon.sink = dai->driver->playback.stream_name; dev_dbg(dai->dev, "%s src %s sink %s\n", __func__, intercon.source, intercon.sink); snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1); } if (dai->driver->capture.stream_name && dai->driver->capture.aif_name) { dev_dbg(dai->dev, "%s add route for widget %s", __func__, dai->driver->capture.stream_name); intercon.sink = dai->driver->capture.aif_name; intercon.source = dai->driver->capture.stream_name; dev_dbg(dai->dev, "%s src %s sink %s\n", __func__, intercon.source, intercon.sink); snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1); } } return rc; } static int msm_dai_q6_spdif_dai_remove(struct snd_soc_dai *dai) { struct msm_dai_q6_spdif_dai_data *dai_data; int rc; dai_data = dev_get_drvdata(dai->dev); /* If AFE port is still up, close it */ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { rc = afe_close(dai->id); /* can block */ if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to close AFE port\n"); clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); } kfree(dai_data); snd_soc_unregister_component(dai->dev); return 0; } static struct snd_soc_dai_ops msm_dai_q6_spdif_ops = { .prepare = msm_dai_q6_spdif_prepare, .hw_params = msm_dai_q6_spdif_hw_params, .shutdown = msm_dai_q6_spdif_shutdown, }; static struct snd_soc_dai_driver msm_dai_q6_spdif_spdif_rx_dai = { .playback = { .stream_name = "SPDIF Playback", .aif_name = "SPDIF_RX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .channels_min = 1, .channels_max = 4, .rate_min = 8000, .rate_max = 48000, }, .ops = &msm_dai_q6_spdif_ops, .probe = msm_dai_q6_spdif_dai_probe, .remove = msm_dai_q6_spdif_dai_remove, }; static const struct snd_soc_component_driver msm_dai_spdif_q6_component = { .name = "msm-dai-q6-spdif", }; static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { Loading Loading @@ -2668,6 +2949,46 @@ static struct platform_driver msm_dai_q6_mi2s_driver = { }, }; static int msm_dai_q6_spdif_dev_probe(struct platform_device *pdev) { int rc; pdev->id = AFE_PORT_ID_SPDIF_RX; dev_set_name(&pdev->dev, "%s", "msm-dai-q6-spdif"); pr_debug("%s: dev name %s, id:%d\n", __func__, dev_name(&pdev->dev), pdev->id); rc = snd_soc_register_component(&pdev->dev, &msm_dai_spdif_q6_component, &msm_dai_q6_spdif_spdif_rx_dai, 1); return rc; } static int msm_dai_q6_spdif_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); return 0; } static const struct of_device_id msm_dai_q6_spdif_dt_match[] = { {.compatible = "qcom,msm-dai-q6-spdif"}, {} }; MODULE_DEVICE_TABLE(of, msm_dai_q6_spdif_dt_match); static struct platform_driver msm_dai_q6_spdif_driver = { .probe = msm_dai_q6_spdif_dev_probe, .remove = msm_dai_q6_spdif_dev_remove, .driver = { .name = "msm-dai-q6-spdif", .owner = THIS_MODULE, .of_match_table = msm_dai_q6_spdif_dt_match, }, }; static int __init msm_dai_q6_init(void) { int rc; Loading Loading @@ -2701,8 +3022,16 @@ static int __init msm_dai_q6_init(void) pr_err("%s: fail to register dai MI2S\n", __func__); goto dai_mi2s_q6_fail; } rc = platform_driver_register(&msm_dai_q6_spdif_driver); if (rc) { pr_err("%s: fail to register dai SPDIF\n", __func__); goto dai_spdif_q6_fail; } return rc; dai_spdif_q6_fail: platform_driver_unregister(&msm_dai_q6_spdif_driver); dai_mi2s_q6_fail: platform_driver_unregister(&msm_dai_q6_mi2s_driver); dai_q6_mi2s_drv_fail: Loading @@ -2721,6 +3050,7 @@ static void __exit msm_dai_q6_exit(void) platform_driver_unregister(&msm_dai_q6_dev); platform_driver_unregister(&msm_dai_q6); platform_driver_unregister(&msm_auxpcm_dev_driver); platform_driver_unregister(&msm_dai_q6_spdif_driver); } module_exit(msm_dai_q6_exit); Loading
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +46 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0}, { SLIMBUS_6_RX, 0, 0, 0, 0, 0}, { SLIMBUS_6_TX, 0, 0, 0, 0, 0}, { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0}, }; Loading Loading @@ -1735,6 +1736,36 @@ static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = { msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SPDIF_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SPDIF_RX, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, Loading Loading @@ -3544,6 +3575,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SEC_I2S_RX", "Secondary I2S Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("SPDIF_RX", "SPDIF Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0), Loading Loading @@ -3640,6 +3672,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)), SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)), SND_SOC_DAPM_MIXER("SPDIF_RX Audio Mixer", SND_SOC_NOPM, 0, 0, spdif_rx_mixer_controls, ARRAY_SIZE(spdif_rx_mixer_controls)), SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)), SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, Loading Loading @@ -3849,6 +3883,17 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia9", "MM_DL9"}, {"HDMI", NULL, "HDMI Mixer"}, {"SPDIF_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"SPDIF_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"SPDIF_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, {"SPDIF_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, {"SPDIF_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, {"SPDIF_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, {"SPDIF_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, {"SPDIF_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, {"SPDIF_RX Audio Mixer", "MultiMedia9", "MM_DL9"}, {"SPDIF_RX", NULL, "SPDIF_RX Audio Mixer"}, /* incall */ {"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"}, {"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"}, Loading Loading @@ -4303,6 +4348,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "SLIMBUS_4_RX"}, {"BE_OUT", NULL, "SLIMBUS_6_RX"}, {"BE_OUT", NULL, "HDMI"}, {"BE_OUT", NULL, "SPDIF_RX"}, {"BE_OUT", NULL, "MI2S_RX"}, {"BE_OUT", NULL, "QUAT_MI2S_RX"}, {"BE_OUT", NULL, "TERT_MI2S_RX"}, Loading
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX" #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX" #define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX" #define LPASS_BE_SPDIF_RX "SPDIF_RX" #define LPASS_BE_MI2S_RX "MI2S_RX" #define LPASS_BE_MI2S_TX "MI2S_TX" Loading Loading @@ -135,6 +136,7 @@ enum { MSM_BACKEND_DAI_SEC_AUXPCM_TX, MSM_BACKEND_DAI_SLIMBUS_6_RX, MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_BACKEND_DAI_SPDIF_RX, MSM_BACKEND_DAI_MAX, }; Loading