mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
AMD SOF based generic SoundWire machine driver
Merge series from Vijendar Mukunda <Vijendar.Mukunda@amd.com>: This patch series majorly consists of below changes. - Rename structures, macros and codec helper names used in Intel SoundWire generic driver to make it generic. - Move Intel SoundWire driver common structures, macros and codec helper functions to common placeholder so that it can be used by other platform machine driver. - Refactor few SoundWire common codec helper functions. - AMD SOF based generic SoundWire machine driver for ACP 6.3 variant. This work started a couple of months ago to avoid duplication of code that wasn't really Intel-specific in the "sof_sdw" machine driver. The code went through multiple iterations, was tested for multiple weeks and a couple of build issues reported by the Intel kbuild bots were corrected. This is the initial version of SoundWire machine driver for AMD platforms. Additional code refactoring will be done in the next step on the AMD side. Link: https://github.com/thesofproject/linux/pull/5068 Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
This commit is contained in:
commit
bb2bf8568a
@ -70,6 +70,7 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
||||
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
||||
* @subsystem_vendor: optional PCI SSID vendor value
|
||||
* @subsystem_device: optional PCI SSID device value
|
||||
* @subsystem_rev: optional PCI SSID revision value
|
||||
* @subsystem_id_set: true if a value has been written to
|
||||
* subsystem_vendor and subsystem_device.
|
||||
*/
|
||||
@ -86,6 +87,7 @@ struct snd_soc_acpi_mach_params {
|
||||
struct snd_soc_dai_driver *dai_drivers;
|
||||
unsigned short subsystem_vendor;
|
||||
unsigned short subsystem_device;
|
||||
unsigned short subsystem_rev;
|
||||
bool subsystem_id_set;
|
||||
};
|
||||
|
||||
|
216
include/sound/soc_sdw_utils.h
Normal file
216
include/sound/soc_sdw_utils.h
Normal file
@ -0,0 +1,216 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* This file incorporates work covered by the following copyright notice:
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
* Copyright(c) 2024 Advanced Micro Devices, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SOC_SDW_UTILS_H
|
||||
#define SOC_SDW_UTILS_H
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
|
||||
#define SOC_SDW_MAX_DAI_NUM 8
|
||||
#define SOC_SDW_MAX_NO_PROPS 2
|
||||
#define SOC_SDW_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
|
||||
|
||||
/* If a CODEC has an optional speaker output, this quirk will enable it */
|
||||
#define SOC_SDW_CODEC_SPKR BIT(15)
|
||||
/*
|
||||
* If the CODEC has additional devices attached directly to it.
|
||||
*
|
||||
* For the cs42l43:
|
||||
* - 0 - No speaker output
|
||||
* - SOC_SDW_CODEC_SPKR - CODEC internal speaker
|
||||
* - SOC_SDW_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker
|
||||
* - SOC_SDW_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported
|
||||
*/
|
||||
#define SOC_SDW_SIDECAR_AMPS BIT(16)
|
||||
|
||||
#define SOC_SDW_UNUSED_DAI_ID -1
|
||||
#define SOC_SDW_JACK_OUT_DAI_ID 0
|
||||
#define SOC_SDW_JACK_IN_DAI_ID 1
|
||||
#define SOC_SDW_AMP_OUT_DAI_ID 2
|
||||
#define SOC_SDW_AMP_IN_DAI_ID 3
|
||||
#define SOC_SDW_DMIC_DAI_ID 4
|
||||
|
||||
#define SOC_SDW_DAI_TYPE_JACK 0
|
||||
#define SOC_SDW_DAI_TYPE_AMP 1
|
||||
#define SOC_SDW_DAI_TYPE_MIC 2
|
||||
|
||||
struct asoc_sdw_codec_info;
|
||||
|
||||
struct asoc_sdw_dai_info {
|
||||
const bool direction[2]; /* playback & capture support */
|
||||
const char *dai_name;
|
||||
const int dai_type;
|
||||
const int dailink[2]; /* dailink id for each direction */
|
||||
const struct snd_kcontrol_new *controls;
|
||||
const int num_controls;
|
||||
const struct snd_soc_dapm_widget *widgets;
|
||||
const int num_widgets;
|
||||
int (*init)(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
bool rtd_init_done; /* Indicate that the rtd_init callback is done */
|
||||
unsigned long quirk;
|
||||
};
|
||||
|
||||
struct asoc_sdw_codec_info {
|
||||
const int part_id;
|
||||
const int version_id;
|
||||
const char *codec_name;
|
||||
int amp_num;
|
||||
const u8 acpi_id[ACPI_ID_LEN];
|
||||
const bool ignore_internal_dmic;
|
||||
const struct snd_soc_ops *ops;
|
||||
struct asoc_sdw_dai_info dais[SOC_SDW_MAX_DAI_NUM];
|
||||
const int dai_num;
|
||||
|
||||
int (*codec_card_late_probe)(struct snd_soc_card *card);
|
||||
|
||||
int (*count_sidecar)(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int (*add_sidecar)(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
};
|
||||
|
||||
struct asoc_sdw_mc_private {
|
||||
struct snd_soc_card card;
|
||||
struct snd_soc_jack sdw_headset;
|
||||
struct device *headset_codec_dev; /* only one headset per card */
|
||||
struct device *amp_dev1, *amp_dev2;
|
||||
bool append_dai_type;
|
||||
bool ignore_internal_dmic;
|
||||
void *private;
|
||||
unsigned long mc_quirk;
|
||||
int codec_info_list_count;
|
||||
};
|
||||
|
||||
extern struct asoc_sdw_codec_info codec_info_list[];
|
||||
int asoc_sdw_get_codec_info_list_count(void);
|
||||
|
||||
int asoc_sdw_startup(struct snd_pcm_substream *substream);
|
||||
int asoc_sdw_prepare(struct snd_pcm_substream *substream);
|
||||
int asoc_sdw_prepare(struct snd_pcm_substream *substream);
|
||||
int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||
int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params);
|
||||
int asoc_sdw_hw_free(struct snd_pcm_substream *substream);
|
||||
void asoc_sdw_shutdown(struct snd_pcm_substream *substream);
|
||||
|
||||
const char *asoc_sdw_get_codec_name(struct device *dev,
|
||||
const struct asoc_sdw_codec_info *codec_info,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
int adr_index);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name,
|
||||
int *dai_index);
|
||||
|
||||
struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card,
|
||||
const char *dai_name);
|
||||
|
||||
void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card);
|
||||
|
||||
int asoc_sdw_card_late_probe(struct snd_soc_card *card);
|
||||
|
||||
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||
int *be_id, char *name, int playback, int capture,
|
||||
struct snd_soc_dai_link_component *cpus, int cpus_num,
|
||||
struct snd_soc_dai_link_component *platform_component,
|
||||
int num_platforms, struct snd_soc_dai_link_component *codecs,
|
||||
int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||
const struct snd_soc_ops *ops);
|
||||
|
||||
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||
int *be_id, char *name, int playback, int capture,
|
||||
const char *cpu_dai_name, const char *platform_comp_name,
|
||||
int num_platforms, const char *codec_name,
|
||||
const char *codec_dai_name,
|
||||
int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||
const struct snd_soc_ops *ops);
|
||||
|
||||
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* DMIC support */
|
||||
int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* RT711 support */
|
||||
int asoc_sdw_rt711_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT711-SDCA support */
|
||||
int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT1308 I2S support */
|
||||
extern const struct snd_soc_ops soc_sdw_rt1308_i2s_ops;
|
||||
|
||||
/* generic amp support */
|
||||
int asoc_sdw_rt_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* CS42L43 support */
|
||||
int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* CS AMP support */
|
||||
int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* MAXIM codec support */
|
||||
int asoc_sdw_maxim_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* dai_link init callbacks */
|
||||
int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
|
||||
#endif
|
@ -126,6 +126,8 @@ source "sound/soc/xtensa/Kconfig"
|
||||
# Supported codecs
|
||||
source "sound/soc/codecs/Kconfig"
|
||||
|
||||
source "sound/soc/sdw_utils/Kconfig"
|
||||
|
||||
# generic frame-work
|
||||
source "sound/soc/generic/Kconfig"
|
||||
|
||||
|
@ -75,3 +75,4 @@ obj-$(CONFIG_SND_SOC) += uniphier/
|
||||
obj-$(CONFIG_SND_SOC) += ux500/
|
||||
obj-$(CONFIG_SND_SOC) += xilinx/
|
||||
obj-$(CONFIG_SND_SOC) += xtensa/
|
||||
obj-$(CONFIG_SND_SOC) += sdw_utils/
|
||||
|
@ -13,6 +13,10 @@ config SND_SOC_AMD_ACP_COMMON
|
||||
This option enables common modules for Audio-Coprocessor i.e. ACP
|
||||
IP block on AMD platforms.
|
||||
|
||||
config SND_SOC_ACPI_AMD_MATCH
|
||||
tristate
|
||||
select SND_SOC_ACPI if ACPI
|
||||
|
||||
if SND_SOC_AMD_ACP_COMMON
|
||||
|
||||
config SND_SOC_AMD_ACP_PDM
|
||||
@ -115,6 +119,24 @@ config SND_SOC_AMD_SOF_MACH
|
||||
help
|
||||
This option enables SOF sound card support for ACP audio.
|
||||
|
||||
config SND_SOC_AMD_SOF_SDW_MACH
|
||||
tristate "AMD SOF Soundwire Machine Driver Support"
|
||||
depends on X86 && PCI && ACPI
|
||||
depends on SOUNDWIRE
|
||||
select SND_SOC_SDW_UTILS
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_RT711_SDW
|
||||
select SND_SOC_RT711_SDCA_SDW
|
||||
select SND_SOC_RT1316_SDW
|
||||
select SND_SOC_RT715_SDW
|
||||
select SND_SOC_RT715_SDCA_SDW
|
||||
help
|
||||
This option enables SOF sound card support for SoundWire enabled
|
||||
AMD platforms along with ACP PDM controller.
|
||||
Say Y if you want to enable SoundWire based machine driver support
|
||||
on AMD platform.
|
||||
If unsure select "N".
|
||||
|
||||
endif # SND_SOC_AMD_ACP_COMMON
|
||||
|
||||
config SND_AMD_SOUNDWIRE_ACPI
|
||||
|
@ -22,6 +22,8 @@ snd-acp70-y := acp70.o
|
||||
snd-acp-mach-y := acp-mach-common.o
|
||||
snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
|
||||
snd-acp-sof-mach-y := acp-sof-mach.o
|
||||
snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o
|
||||
snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
|
||||
@ -38,3 +40,5 @@ obj-$(CONFIG_SND_AMD_SOUNDWIRE_ACPI) += snd-amd-sdw-acpi.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o
|
||||
obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o
|
||||
|
742
sound/soc/amd/acp/acp-sdw-sof-mach.c
Normal file
742
sound/soc/amd/acp/acp-sdw-sof-mach.c
Normal file
@ -0,0 +1,742 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright(c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* acp-sdw-sof-mach - ASoC Machine driver for AMD SoundWire platforms
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "soc_amd_sdw_common.h"
|
||||
#include "../../codecs/rt711.h"
|
||||
|
||||
static unsigned long sof_sdw_quirk = RT711_JD1;
|
||||
static int quirk_override = -1;
|
||||
module_param_named(quirk, quirk_override, int, 0444);
|
||||
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
|
||||
|
||||
static void log_quirks(struct device *dev)
|
||||
{
|
||||
if (SOC_JACK_JDSRC(sof_sdw_quirk))
|
||||
dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
|
||||
SOC_JACK_JDSRC(sof_sdw_quirk));
|
||||
if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC)
|
||||
dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
|
||||
}
|
||||
|
||||
static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
|
||||
{
|
||||
sof_sdw_quirk = (unsigned long)id->driver_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "AMD"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"),
|
||||
},
|
||||
.driver_data = (void *)RT711_JD2,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component platform_component[] = {
|
||||
{
|
||||
/* name might be overridden during probe */
|
||||
.name = "0000:04:00.5",
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops sdw_ops = {
|
||||
.startup = asoc_sdw_startup,
|
||||
.prepare = asoc_sdw_prepare,
|
||||
.trigger = asoc_sdw_trigger,
|
||||
.hw_params = asoc_sdw_hw_params,
|
||||
.hw_free = asoc_sdw_hw_free,
|
||||
.shutdown = asoc_sdw_shutdown,
|
||||
};
|
||||
|
||||
/*
|
||||
* get BE dailink number and CPU DAI number based on sdw link adr.
|
||||
* Since some sdw slaves may be aggregated, the CPU DAI number
|
||||
* may be larger than the number of BE dailinks.
|
||||
*/
|
||||
static int get_dailink_info(struct device *dev,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
int *sdw_be_num, int *codecs_num)
|
||||
{
|
||||
bool group_visited[AMD_SDW_MAX_GROUPS];
|
||||
int i;
|
||||
int j;
|
||||
|
||||
*sdw_be_num = 0;
|
||||
|
||||
if (!adr_link)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < AMD_SDW_MAX_GROUPS; i++)
|
||||
group_visited[i] = false;
|
||||
|
||||
for (; adr_link->num_adr; adr_link++) {
|
||||
const struct snd_soc_acpi_endpoint *endpoint;
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
int stream;
|
||||
u64 adr;
|
||||
|
||||
/* make sure the link mask has a single bit set */
|
||||
if (!is_power_of_2(adr_link->mask))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < adr_link->num_adr; i++) {
|
||||
adr = adr_link->adr_d[i].adr;
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
*codecs_num += codec_info->dai_num;
|
||||
|
||||
if (!adr_link->adr_d[i].name_prefix) {
|
||||
dev_err(dev, "codec 0x%llx does not have a name prefix\n",
|
||||
adr_link->adr_d[i].adr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
endpoint = adr_link->adr_d[i].endpoints;
|
||||
if (endpoint->aggregated && !endpoint->group_id) {
|
||||
dev_err(dev, "invalid group id on link %x\n",
|
||||
adr_link->mask);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (j = 0; j < codec_info->dai_num; j++) {
|
||||
/* count DAI number for playback and capture */
|
||||
for_each_pcm_streams(stream) {
|
||||
if (!codec_info->dais[j].direction[stream])
|
||||
continue;
|
||||
|
||||
/* count BE for each non-aggregated slave or group */
|
||||
if (!endpoint->aggregated ||
|
||||
!group_visited[endpoint->group_id])
|
||||
(*sdw_be_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
if (endpoint->aggregated)
|
||||
group_visited[endpoint->group_id] = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fill_sdw_codec_dlc(struct device *dev,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
struct snd_soc_dai_link_component *codec,
|
||||
int adr_index, int dai_index)
|
||||
{
|
||||
u64 adr = adr_link->adr_d[adr_index].adr;
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
codec->name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, adr_index);
|
||||
if (!codec->name)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->dai_name = codec_info->dais[dai_index].dai_name;
|
||||
dev_err(dev, "codec->dai_name:%s\n", codec->dai_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_codec_init_func(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
bool playback, int group_id, int adr_index, int dai_index)
|
||||
{
|
||||
int i = adr_index;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Initialize the codec. If codec is part of an aggregated
|
||||
* group (group_id>0), initialize all codecs belonging to
|
||||
* same group.
|
||||
* The first link should start with adr_link->adr_d[adr_index]
|
||||
* because that is the device that we want to initialize and
|
||||
* we should end immediately if it is not aggregated (group_id=0)
|
||||
*/
|
||||
for ( ; i < adr_link->num_adr; i++) {
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
/* The group_id is > 0 iff the codec is aggregated */
|
||||
if (adr_link->adr_d[i].endpoints->group_id != group_id)
|
||||
continue;
|
||||
if (codec_info->dais[dai_index].init)
|
||||
codec_info->dais[dai_index].init(card,
|
||||
dai_links,
|
||||
codec_info,
|
||||
playback);
|
||||
|
||||
if (!group_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
adr_link++;
|
||||
} while (adr_link->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check endpoint status in slaves and gather link ID for all slaves in
|
||||
* the same group to generate different CPU DAI. Now only support
|
||||
* one sdw link with all slaves set with only single group id.
|
||||
*
|
||||
* one slave on one sdw link with aggregated = 0
|
||||
* one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
|
||||
*
|
||||
* two or more slaves on one sdw link with aggregated = 1
|
||||
* one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs
|
||||
*/
|
||||
static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
|
||||
struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
|
||||
int *codec_num, unsigned int *group_id,
|
||||
int adr_index)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!adr_link->adr_d[adr_index].endpoints->aggregated) {
|
||||
cpu_dai_id[0] = ffs(adr_link->mask) - 1;
|
||||
*cpu_dai_num = 1;
|
||||
*codec_num = 1;
|
||||
*group_id = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*codec_num = 0;
|
||||
*cpu_dai_num = 0;
|
||||
*group_id = adr_link->adr_d[adr_index].endpoints->group_id;
|
||||
|
||||
/* Count endpoints with the same group_id in the adr_link */
|
||||
for (; adr_link && adr_link->num_adr; adr_link++) {
|
||||
unsigned int link_codecs = 0;
|
||||
|
||||
for (i = 0; i < adr_link->num_adr; i++) {
|
||||
if (adr_link->adr_d[i].endpoints->aggregated &&
|
||||
adr_link->adr_d[i].endpoints->group_id == *group_id)
|
||||
link_codecs++;
|
||||
}
|
||||
|
||||
if (link_codecs) {
|
||||
*codec_num += link_codecs;
|
||||
|
||||
if (*cpu_dai_num >= ACP63_SDW_MAX_CPU_DAIS) {
|
||||
dev_err(dev, "cpu_dai_id array overflowed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
|
||||
{
|
||||
switch (sdw_link_id) {
|
||||
case AMD_SDW0:
|
||||
switch (be_id) {
|
||||
case SOC_SDW_JACK_OUT_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW0_AUDIO0_TX;
|
||||
break;
|
||||
case SOC_SDW_JACK_IN_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW0_AUDIO0_RX;
|
||||
break;
|
||||
case SOC_SDW_AMP_OUT_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW0_AUDIO1_TX;
|
||||
break;
|
||||
case SOC_SDW_AMP_IN_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW0_AUDIO1_RX;
|
||||
break;
|
||||
case SOC_SDW_DMIC_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW0_AUDIO2_RX;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Invalid be id:%d\n", be_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case AMD_SDW1:
|
||||
switch (be_id) {
|
||||
case SOC_SDW_JACK_OUT_DAI_ID:
|
||||
case SOC_SDW_AMP_OUT_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW1_AUDIO0_TX;
|
||||
break;
|
||||
case SOC_SDW_JACK_IN_DAI_ID:
|
||||
case SOC_SDW_AMP_IN_DAI_ID:
|
||||
case SOC_SDW_DMIC_DAI_ID:
|
||||
*cpu_pin_id = ACP63_SW1_AUDIO0_RX;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid be_id:%d\n", be_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Invalid link id:%d\n", sdw_link_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
|
||||
|
||||
static int create_sdw_dailink(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
struct snd_soc_codec_conf **codec_conf,
|
||||
int *be_id, int adr_index, int dai_index)
|
||||
{
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
|
||||
struct device *dev = card->dev;
|
||||
const struct snd_soc_acpi_link_adr *adr_link_next;
|
||||
struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps;
|
||||
struct snd_soc_dai_link_component *codecs;
|
||||
struct snd_soc_dai_link_component *cpus;
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
int cpu_dai_id[ACP63_SDW_MAX_CPU_DAIS];
|
||||
int cpu_dai_num;
|
||||
unsigned int group_id;
|
||||
unsigned int sdw_link_id;
|
||||
int codec_dlc_index = 0;
|
||||
int codec_num;
|
||||
int stream;
|
||||
int i = 0;
|
||||
int j, k;
|
||||
int ret;
|
||||
int cpu_pin_id;
|
||||
|
||||
ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
|
||||
&group_id, adr_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
|
||||
if (!codecs)
|
||||
return -ENOMEM;
|
||||
|
||||
sdw_codec_ch_maps = devm_kcalloc(dev, codec_num,
|
||||
sizeof(*sdw_codec_ch_maps), GFP_KERNEL);
|
||||
if (!sdw_codec_ch_maps)
|
||||
return -ENOMEM;
|
||||
|
||||
/* generate codec name on different links in the same group */
|
||||
j = adr_index;
|
||||
for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr &&
|
||||
i < cpu_dai_num; adr_link_next++) {
|
||||
/* skip the link excluded by this processed group */
|
||||
if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1)
|
||||
continue;
|
||||
|
||||
/* j reset after loop, adr_index only applies to first link */
|
||||
for (k = 0 ; (j < adr_link_next->num_adr) && (k < codec_num) ; j++, k++) {
|
||||
const struct snd_soc_acpi_endpoint *endpoints;
|
||||
|
||||
endpoints = adr_link_next->adr_d[j].endpoints;
|
||||
if (group_id && (!endpoints->aggregated ||
|
||||
endpoints->group_id != group_id))
|
||||
continue;
|
||||
|
||||
/* sanity check */
|
||||
if (*codec_conf >= card->codec_conf + card->num_configs) {
|
||||
dev_err(dev, "codec_conf array overflowed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = fill_sdw_codec_dlc(dev, adr_link_next,
|
||||
&codecs[codec_dlc_index],
|
||||
j, dai_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
(*codec_conf)->dlc = codecs[codec_dlc_index];
|
||||
(*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix;
|
||||
|
||||
sdw_codec_ch_maps[codec_dlc_index].cpu = i;
|
||||
sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index;
|
||||
|
||||
codec_dlc_index++;
|
||||
(*codec_conf)++;
|
||||
}
|
||||
j = 0;
|
||||
|
||||
/* check next link to create codec dai in the processed group */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* find codec info to create BE DAI */
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[adr_index].adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;
|
||||
|
||||
sdw_link_id = (adr_link->adr_d[adr_index].adr) >> 48;
|
||||
for_each_pcm_streams(stream) {
|
||||
char *name, *cpu_name;
|
||||
int playback, capture;
|
||||
static const char * const sdw_stream_name[] = {
|
||||
"SDW%d-PIN%d-PLAYBACK",
|
||||
"SDW%d-PIN%d-CAPTURE",
|
||||
"SDW%d-PIN%d-PLAYBACK-%s",
|
||||
"SDW%d-PIN%d-CAPTURE-%s",
|
||||
};
|
||||
|
||||
if (!codec_info->dais[dai_index].direction[stream])
|
||||
continue;
|
||||
|
||||
*be_id = codec_info->dais[dai_index].dailink[stream];
|
||||
if (*be_id < 0) {
|
||||
dev_err(dev, "Invalid dailink id %d\n", *be_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (amd_ctx->acp_rev) {
|
||||
case ACP63_PCI_REV:
|
||||
ret = get_acp63_cpu_pin_id(sdw_link_id, *be_id, &cpu_pin_id, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* create stream name according to first link id */
|
||||
if (ctx->append_dai_type) {
|
||||
name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
sdw_stream_name[stream + 2], sdw_link_id, cpu_pin_id,
|
||||
type_strings[codec_info->dais[dai_index].dai_type]);
|
||||
} else {
|
||||
name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
sdw_stream_name[stream], sdw_link_id, cpu_pin_id);
|
||||
}
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL);
|
||||
if (!cpus)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* generate CPU DAI name base on the sdw link ID and
|
||||
* cpu pin id according to sdw dai driver.
|
||||
*/
|
||||
for (k = 0; k < cpu_dai_num; k++) {
|
||||
cpu_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SDW%d Pin%d", sdw_link_id, cpu_pin_id);
|
||||
if (!cpu_name)
|
||||
return -ENOMEM;
|
||||
|
||||
cpus[k].dai_name = cpu_name;
|
||||
}
|
||||
|
||||
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
|
||||
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
|
||||
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name,
|
||||
playback, capture,
|
||||
cpus, cpu_dai_num,
|
||||
platform_component, ARRAY_SIZE(platform_component),
|
||||
codecs, codec_num,
|
||||
asoc_sdw_rtd_init, &sdw_ops);
|
||||
/*
|
||||
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
|
||||
* based on wait_for_completion(), tag them as 'nonatomic'.
|
||||
*/
|
||||
(*dai_links)->nonatomic = true;
|
||||
(*dai_links)->ch_maps = sdw_codec_ch_maps;
|
||||
|
||||
ret = set_codec_init_func(card, adr_link, *dai_links,
|
||||
playback, group_id, adr_index, dai_index);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*dai_links)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_dmic_dailinks(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links, int *be_id)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
int ret;
|
||||
|
||||
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
|
||||
0, 1, // DMIC only supports capture
|
||||
"acp-sof-dmic", platform_component->name,
|
||||
ARRAY_SIZE(platform_component),
|
||||
"dmic-codec", "dmic-hifi",
|
||||
asoc_sdw_dmic_init, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*dai_links)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
|
||||
int sdw_be_num = 0, dmic_num = 0;
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
|
||||
const struct snd_soc_acpi_link_adr *adr_link = mach_params->links;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
int codec_conf_num = 0;
|
||||
bool group_generated[AMD_SDW_MAX_GROUPS] = { };
|
||||
struct snd_soc_dai_link *dai_links;
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
int num_links;
|
||||
int i, j, be_id = 0;
|
||||
int ret;
|
||||
|
||||
ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get sdw link info %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable dmic */
|
||||
if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num)
|
||||
dmic_num = 1;
|
||||
|
||||
dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num);
|
||||
|
||||
/* allocate BE dailinks */
|
||||
num_links = sdw_be_num + dmic_num;
|
||||
dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
|
||||
if (!dai_links)
|
||||
return -ENOMEM;
|
||||
|
||||
/* allocate codec conf, will be populated when dailinks are created */
|
||||
codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf),
|
||||
GFP_KERNEL);
|
||||
if (!codec_conf)
|
||||
return -ENOMEM;
|
||||
|
||||
card->dai_link = dai_links;
|
||||
card->num_links = num_links;
|
||||
card->codec_conf = codec_conf;
|
||||
card->num_configs = codec_conf_num;
|
||||
|
||||
/* SDW */
|
||||
if (!sdw_be_num)
|
||||
goto DMIC;
|
||||
|
||||
for (; adr_link->num_adr; adr_link++) {
|
||||
/*
|
||||
* If there are two or more different devices on the same sdw link, we have to
|
||||
* append the codec type to the dai link name to prevent duplicated dai link name.
|
||||
* The same type devices on the same sdw link will be in the same
|
||||
* snd_soc_acpi_adr_device array. They won't be described in different adr_links.
|
||||
*/
|
||||
for (i = 0; i < adr_link->num_adr; i++) {
|
||||
/* find codec info to get dai_num */
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
if (codec_info->dai_num > 1) {
|
||||
ctx->append_dai_type = true;
|
||||
goto out;
|
||||
}
|
||||
for (j = 0; j < i; j++) {
|
||||
if ((SDW_PART_ID(adr_link->adr_d[i].adr) !=
|
||||
SDW_PART_ID(adr_link->adr_d[j].adr)) ||
|
||||
(SDW_MFG_ID(adr_link->adr_d[i].adr) !=
|
||||
SDW_MFG_ID(adr_link->adr_d[j].adr))) {
|
||||
ctx->append_dai_type = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
/* generate DAI links by each sdw link */
|
||||
for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) {
|
||||
for (i = 0; i < adr_link->num_adr; i++) {
|
||||
const struct snd_soc_acpi_endpoint *endpoint;
|
||||
|
||||
endpoint = adr_link->adr_d[i].endpoints;
|
||||
|
||||
/* this group has been generated */
|
||||
if (endpoint->aggregated &&
|
||||
group_generated[endpoint->group_id])
|
||||
continue;
|
||||
|
||||
/* find codec info to get dai_num */
|
||||
codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
for (j = 0; j < codec_info->dai_num ; j++) {
|
||||
int current_be_id;
|
||||
|
||||
ret = create_sdw_dailink(card, &dai_links, adr_link,
|
||||
&codec_conf, ¤t_be_id,
|
||||
i, j);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"failed to create dai link %d on 0x%x\n",
|
||||
j, codec_info->part_id);
|
||||
return ret;
|
||||
}
|
||||
/* Update the be_id to match the highest ID used for SDW link */
|
||||
if (be_id < current_be_id)
|
||||
be_id = current_be_id;
|
||||
}
|
||||
|
||||
if (endpoint->aggregated)
|
||||
group_generated[endpoint->group_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
DMIC:
|
||||
/* dmic */
|
||||
if (dmic_num > 0) {
|
||||
if (ctx->ignore_internal_dmic) {
|
||||
dev_warn(dev, "Ignoring ACP DMIC\n");
|
||||
} else {
|
||||
be_id = SOC_SDW_DMIC_DAI_ID;
|
||||
ret = create_dmic_dailinks(card, &dai_links, &be_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(dai_links != card->dai_link + card->num_links);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SoC card */
|
||||
static const char sdw_card_long_name[] = "AMD Soundwire SOF";
|
||||
|
||||
static int mc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
|
||||
struct snd_soc_card *card;
|
||||
struct amd_mc_ctx *amd_ctx;
|
||||
struct asoc_sdw_mc_private *ctx;
|
||||
int amp_num = 0, i;
|
||||
int ret;
|
||||
|
||||
amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL);
|
||||
if (!amd_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
amd_ctx->acp_rev = mach->mach_params.subsystem_rev;
|
||||
amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS;
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
|
||||
ctx->private = amd_ctx;
|
||||
card = &ctx->card;
|
||||
card->dev = &pdev->dev;
|
||||
card->name = "amd-soundwire",
|
||||
card->owner = THIS_MODULE,
|
||||
card->late_probe = asoc_sdw_card_late_probe,
|
||||
|
||||
snd_soc_card_set_drvdata(card, ctx);
|
||||
|
||||
dmi_check_system(sof_sdw_quirk_table);
|
||||
|
||||
if (quirk_override != -1) {
|
||||
dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
|
||||
sof_sdw_quirk, quirk_override);
|
||||
sof_sdw_quirk = quirk_override;
|
||||
}
|
||||
|
||||
log_quirks(card->dev);
|
||||
|
||||
ctx->mc_quirk = sof_sdw_quirk;
|
||||
/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
|
||||
for (i = 0; i < ctx->codec_info_list_count; i++)
|
||||
codec_info_list[i].amp_num = 0;
|
||||
|
||||
ret = sof_card_dai_links_create(card);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* the default amp_num is zero for each codec and
|
||||
* amp_num will only be increased for active amp
|
||||
* codecs on used platform
|
||||
*/
|
||||
for (i = 0; i < ctx->codec_info_list_count; i++)
|
||||
amp_num += codec_info_list[i].amp_num;
|
||||
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
" cfg-amp:%d", amp_num);
|
||||
if (!card->components)
|
||||
return -ENOMEM;
|
||||
|
||||
card->long_name = sdw_card_long_name;
|
||||
|
||||
/* Register the card */
|
||||
ret = devm_snd_soc_register_card(card->dev, card);
|
||||
if (ret) {
|
||||
dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
|
||||
asoc_sdw_mc_dailink_exit_loop(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
asoc_sdw_mc_dailink_exit_loop(card);
|
||||
}
|
||||
|
||||
static const struct platform_device_id mc_id_table[] = {
|
||||
{ "amd_sof_sdw", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, mc_id_table);
|
||||
|
||||
static struct platform_driver sof_sdw_driver = {
|
||||
.driver = {
|
||||
.name = "amd_sof_sdw",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = mc_probe,
|
||||
.remove_new = mc_remove,
|
||||
.id_table = mc_id_table,
|
||||
};
|
||||
|
||||
module_platform_driver(sof_sdw_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver");
|
||||
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:amd_sof_sdw");
|
||||
MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
|
90
sound/soc/amd/acp/amd-acp63-acpi-match.c
Normal file
90
sound/soc/amd/acp/amd-acp63-acpi-match.c
Normal file
@ -0,0 +1,90 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* amd-acp63-acpi-match.c - tables and support for ACP 6.3 platform
|
||||
* ACPI enumeration.
|
||||
*
|
||||
* Copyright 2024 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "../mach-config.h"
|
||||
|
||||
static const struct snd_soc_acpi_endpoint single_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 0,
|
||||
.group_position = 0,
|
||||
.group_id = 0
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint spk_l_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 1,
|
||||
.group_position = 0,
|
||||
.group_id = 1
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 1,
|
||||
.group_position = 1,
|
||||
.group_id = 1
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = {
|
||||
{
|
||||
.adr = 0x000030025D071101ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
.name_prefix = "rt711"
|
||||
},
|
||||
{
|
||||
.adr = 0x000030025D131601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_l_endpoint,
|
||||
.name_prefix = "rt1316-1"
|
||||
},
|
||||
{
|
||||
.adr = 0x000032025D131601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_r_endpoint,
|
||||
.name_prefix = "rt1316-2"
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt714_adr[] = {
|
||||
{
|
||||
.adr = 0x130025d071401ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
.name_prefix = "rt714"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = {
|
||||
{ .mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt711_rt1316_group_adr),
|
||||
.adr_d = rt711_rt1316_group_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt714_adr),
|
||||
.adr_d = rt714_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = {
|
||||
{
|
||||
.link_mask = BIT(0) | BIT(1),
|
||||
.links = acp63_4_in_1_sdca,
|
||||
.drv_name = "amd_sof_sdw",
|
||||
.sof_tplg_filename = "sof-acp_6_3-rt711-l0-rt1316-l0-rt714-l1.tplg",
|
||||
.fw_filename = "sof-acp_6_3.ri",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines);
|
||||
|
||||
MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
|
44
sound/soc/amd/acp/soc_amd_sdw_common.h
Normal file
44
sound/soc/amd/acp/soc_amd_sdw_common.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
* Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved
|
||||
*/
|
||||
|
||||
/*
|
||||
* soc_amd_sdw_common.h - prototypes for common helpers
|
||||
*/
|
||||
|
||||
#ifndef SOC_AMD_SDW_COMMON_H
|
||||
#define SOC_AMD_SDW_COMMON_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/types.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
#define ACP63_SDW_MAX_CPU_DAIS 8
|
||||
#define ACP63_SDW_MAX_LINKS 2
|
||||
|
||||
#define AMD_SDW_MAX_GROUPS 9
|
||||
#define ACP63_PCI_REV 0x63
|
||||
#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
|
||||
#define ASOC_SDW_FOUR_SPK BIT(4)
|
||||
#define ASOC_SDW_ACP_DMIC BIT(5)
|
||||
|
||||
#define AMD_SDW0 0
|
||||
#define AMD_SDW1 1
|
||||
#define ACP63_SW0_AUDIO0_TX 0
|
||||
#define ACP63_SW0_AUDIO1_TX 1
|
||||
#define ACP63_SW0_AUDIO2_TX 2
|
||||
|
||||
#define ACP63_SW0_AUDIO0_RX 3
|
||||
#define ACP63_SW0_AUDIO1_RX 4
|
||||
#define ACP63_SW0_AUDIO2_RX 5
|
||||
|
||||
#define ACP63_SW1_AUDIO0_TX 0
|
||||
#define ACP63_SW1_AUDIO0_RX 1
|
||||
|
||||
struct amd_mc_ctx {
|
||||
unsigned int acp_rev;
|
||||
unsigned int max_sdw_links;
|
||||
};
|
||||
|
||||
#endif
|
@ -23,6 +23,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[];
|
||||
|
||||
struct config_entry {
|
||||
u32 flags;
|
||||
|
@ -656,6 +656,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
|
||||
depends on MFD_INTEL_LPSS || COMPILE_TEST
|
||||
depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
|
||||
depends on SOUNDWIRE
|
||||
select SND_SOC_SDW_UTILS
|
||||
select SND_SOC_MAX98363
|
||||
select SND_SOC_MAX98373_I2C
|
||||
select SND_SOC_MAX98373_SDW
|
||||
|
@ -35,15 +35,6 @@ snd-soc-skl_nau88l25_ssm4567-y := skl_nau88l25_ssm4567.o
|
||||
snd-soc-ehl-rt5660-y := ehl_rt5660.o
|
||||
snd-soc-sof-ssp-amp-y := sof_ssp_amp.o
|
||||
snd-soc-sof-sdw-y += sof_sdw.o \
|
||||
sof_sdw_maxim.o sof_sdw_rt_amp.o \
|
||||
bridge_cs35l56.o \
|
||||
sof_sdw_rt5682.o sof_sdw_rt700.o \
|
||||
sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \
|
||||
sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \
|
||||
sof_sdw_rt_dmic.o \
|
||||
sof_sdw_cs42l42.o sof_sdw_cs42l43.o \
|
||||
sof_sdw_cs_amp.o \
|
||||
sof_sdw_dmic.o \
|
||||
sof_sdw_hdmi.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,18 +12,12 @@
|
||||
#include <linux/bits.h>
|
||||
#include <linux/types.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
#include "sof_hdmi_common.h"
|
||||
|
||||
#define MAX_NO_PROPS 2
|
||||
#define MAX_HDMI_NUM 4
|
||||
#define SDW_UNUSED_DAI_ID -1
|
||||
#define SDW_JACK_OUT_DAI_ID 0
|
||||
#define SDW_JACK_IN_DAI_ID 1
|
||||
#define SDW_AMP_OUT_DAI_ID 2
|
||||
#define SDW_AMP_IN_DAI_ID 3
|
||||
#define SDW_DMIC_DAI_ID 4
|
||||
#define SDW_MAX_CPU_DAIS 16
|
||||
#define SDW_INTEL_BIDIR_PDI_BASE 2
|
||||
#define SOC_SDW_MAX_CPU_DAIS 16
|
||||
#define SOC_SDW_INTEL_BIDIR_PDI_BASE 2
|
||||
|
||||
#define SDW_MAX_LINKS 4
|
||||
|
||||
@ -44,27 +38,14 @@ enum {
|
||||
SOF_I2S_SSP5 = BIT(5),
|
||||
};
|
||||
|
||||
#define SOF_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
|
||||
/* Deprecated and no longer supported by the code */
|
||||
#define SOF_SDW_FOUR_SPK BIT(4)
|
||||
#define SOC_SDW_FOUR_SPK BIT(4)
|
||||
#define SOF_SDW_TGL_HDMI BIT(5)
|
||||
#define SOF_SDW_PCH_DMIC BIT(6)
|
||||
#define SOC_SDW_PCH_DMIC BIT(6)
|
||||
#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7)
|
||||
#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0))
|
||||
/* Deprecated and no longer supported by the code */
|
||||
#define SOF_SDW_NO_AGGREGATION BIT(14)
|
||||
/* If a CODEC has an optional speaker output, this quirk will enable it */
|
||||
#define SOF_CODEC_SPKR BIT(15)
|
||||
/*
|
||||
* If the CODEC has additional devices attached directly to it.
|
||||
*
|
||||
* For the cs42l43:
|
||||
* - 0 - No speaker output
|
||||
* - SOF_CODEC_SPKR - CODEC internal speaker
|
||||
* - SOF_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker
|
||||
* - SOF_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported
|
||||
*/
|
||||
#define SOF_SIDECAR_AMPS BIT(16)
|
||||
#define SOC_SDW_NO_AGGREGATION BIT(14)
|
||||
|
||||
/* BT audio offload: reserve 3 bits for future */
|
||||
#define SOF_BT_OFFLOAD_SSP_SHIFT 15
|
||||
@ -73,150 +54,17 @@ enum {
|
||||
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
|
||||
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18)
|
||||
|
||||
#define SOF_SDW_DAI_TYPE_JACK 0
|
||||
#define SOF_SDW_DAI_TYPE_AMP 1
|
||||
#define SOF_SDW_DAI_TYPE_MIC 2
|
||||
|
||||
#define SOF_SDW_MAX_DAI_NUM 8
|
||||
|
||||
struct sof_sdw_codec_info;
|
||||
|
||||
struct sof_sdw_dai_info {
|
||||
const bool direction[2]; /* playback & capture support */
|
||||
const char *dai_name;
|
||||
const int dai_type;
|
||||
const int dailink[2]; /* dailink id for each direction */
|
||||
const struct snd_kcontrol_new *controls;
|
||||
const int num_controls;
|
||||
const struct snd_soc_dapm_widget *widgets;
|
||||
const int num_widgets;
|
||||
int (*init)(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
bool rtd_init_done; /* Indicate that the rtd_init callback is done */
|
||||
unsigned long quirk;
|
||||
};
|
||||
|
||||
struct sof_sdw_codec_info {
|
||||
const int part_id;
|
||||
const int version_id;
|
||||
const char *codec_name;
|
||||
int amp_num;
|
||||
const u8 acpi_id[ACPI_ID_LEN];
|
||||
const bool ignore_pch_dmic;
|
||||
const struct snd_soc_ops *ops;
|
||||
struct sof_sdw_dai_info dais[SOF_SDW_MAX_DAI_NUM];
|
||||
const int dai_num;
|
||||
|
||||
int (*codec_card_late_probe)(struct snd_soc_card *card);
|
||||
|
||||
int (*count_sidecar)(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int (*add_sidecar)(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
};
|
||||
|
||||
struct mc_private {
|
||||
struct snd_soc_card card;
|
||||
struct snd_soc_jack sdw_headset;
|
||||
struct intel_mc_ctx {
|
||||
struct sof_hdmi_private hdmi;
|
||||
struct device *headset_codec_dev; /* only one headset per card */
|
||||
struct device *amp_dev1, *amp_dev2;
|
||||
/* To store SDW Pin index for each SoundWire link */
|
||||
unsigned int sdw_pin_index[SDW_MAX_LINKS];
|
||||
bool append_dai_type;
|
||||
bool ignore_pch_dmic;
|
||||
};
|
||||
|
||||
extern unsigned long sof_sdw_quirk;
|
||||
|
||||
int sdw_startup(struct snd_pcm_substream *substream);
|
||||
int sdw_prepare(struct snd_pcm_substream *substream);
|
||||
int sdw_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||
int sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params);
|
||||
int sdw_hw_free(struct snd_pcm_substream *substream);
|
||||
void sdw_shutdown(struct snd_pcm_substream *substream);
|
||||
|
||||
/* generic HDMI support */
|
||||
int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card);
|
||||
|
||||
/* DMIC support */
|
||||
int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* RT711 support */
|
||||
int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT711-SDCA support */
|
||||
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT1308 I2S support */
|
||||
extern const struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
|
||||
|
||||
/* generic amp support */
|
||||
int sof_sdw_rt_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* MAXIM codec support */
|
||||
int sof_sdw_maxim_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* CS42L43 support */
|
||||
int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* CS AMP support */
|
||||
int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs);
|
||||
int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf);
|
||||
int bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* dai_link init callbacks */
|
||||
|
||||
int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
|
||||
|
||||
#endif
|
||||
|
@ -17,23 +17,25 @@
|
||||
|
||||
int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
|
||||
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
|
||||
ctx->hdmi.hdmi_comp = dai->component;
|
||||
intel_ctx->hdmi.hdmi_comp = dai->component;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
|
||||
|
||||
if (!ctx->hdmi.idisp_codec)
|
||||
if (!intel_ctx->hdmi.idisp_codec)
|
||||
return 0;
|
||||
|
||||
if (!ctx->hdmi.hdmi_comp)
|
||||
if (!intel_ctx->hdmi.hdmi_comp)
|
||||
return -EINVAL;
|
||||
|
||||
return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
|
||||
return hda_dsp_hdmi_build_controls(card, intel_ctx->hdmi.hdmi_comp);
|
||||
}
|
||||
|
6
sound/soc/sdw_utils/Kconfig
Normal file
6
sound/soc/sdw_utils/Kconfig
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config SND_SOC_SDW_UTILS
|
||||
tristate
|
||||
help
|
||||
This option enables to use SoundWire common helper functions and
|
||||
SoundWire codec helper functions in machine driver.
|
11
sound/soc/sdw_utils/Makefile
Normal file
11
sound/soc/sdw_utils/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \
|
||||
soc_sdw_rt700.o soc_sdw_rt711.o \
|
||||
soc_sdw_rt712_sdca.o soc_sdw_rt722_sdca.o \
|
||||
soc_sdw_rt5682.o soc_sdw_rt_sdca_jack_common.o \
|
||||
soc_sdw_rt_amp.o \
|
||||
soc_sdw_bridge_cs35l56.o \
|
||||
soc_sdw_cs42l42.o soc_sdw_cs42l43.o \
|
||||
soc_sdw_cs_amp.o \
|
||||
soc_sdw_maxim.o
|
||||
obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o
|
@ -1,6 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2024 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* soc_sdw_bridge_cs35l56 - codec helper functions for handling CS35L56 Smart AMP
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -9,7 +14,7 @@
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget bridge_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Bridge Speaker", NULL),
|
||||
@ -25,7 +30,7 @@ static const char * const bridge_cs35l56_name_prefixes[] = {
|
||||
"AMPR",
|
||||
};
|
||||
|
||||
static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static int asoc_sdw_bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int i, ret;
|
||||
@ -73,7 +78,7 @@ static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_pcm_stream bridge_params = {
|
||||
static const struct snd_soc_pcm_stream asoc_sdw_bridge_params = {
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.rate_min = 48000,
|
||||
.rate_max = 48000,
|
||||
@ -81,7 +86,7 @@ static const struct snd_soc_pcm_stream bridge_params = {
|
||||
.channels_max = 2,
|
||||
};
|
||||
|
||||
SND_SOC_DAILINK_DEFS(bridge_dai,
|
||||
SND_SOC_DAILINK_DEFS(asoc_sdw_bridge_dai,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"),
|
||||
COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")),
|
||||
@ -89,28 +94,33 @@ SND_SOC_DAILINK_DEFS(bridge_dai,
|
||||
|
||||
static const struct snd_soc_dai_link bridge_dai_template = {
|
||||
.name = "cs42l43-cs35l56",
|
||||
.init = bridge_cs35l56_asp_init,
|
||||
.c2c_params = &bridge_params,
|
||||
.init = asoc_sdw_bridge_cs35l56_asp_init,
|
||||
.c2c_params = &asoc_sdw_bridge_params,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC,
|
||||
SND_SOC_DAILINK_REG(bridge_dai),
|
||||
SND_SOC_DAILINK_REG(asoc_sdw_bridge_dai),
|
||||
};
|
||||
|
||||
int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs)
|
||||
int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
|
||||
int *num_dais, int *num_devs)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS) {
|
||||
(*num_dais)++;
|
||||
(*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_count_sidecar, SND_SOC_SDW_UTILS);
|
||||
|
||||
int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf)
|
||||
int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link **dai_links,
|
||||
struct snd_soc_codec_conf **codec_conf)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS) {
|
||||
**dai_links = bridge_dai_template;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) {
|
||||
@ -124,14 +134,18 @@ int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_add_sidecar, SND_SOC_SDW_UTILS);
|
||||
|
||||
int bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS)
|
||||
info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_spk_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2023 Intel Corporation
|
||||
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
/*
|
||||
* sof_sdw_cs42l42 - Helpers to handle CS42L42 from generic machine driver
|
||||
* soc_sdw_cs42l42 - Helpers to handle CS42L42 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -15,7 +16,7 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_route cs42l42_map[] = {
|
||||
/* HP jack connectors - unknown if we have jack detection */
|
||||
@ -36,10 +37,10 @@ static struct snd_soc_jack_pin cs42l42_jack_pins[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
int ret;
|
||||
@ -87,4 +88,4 @@ int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs42l42_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,9 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Based on sof_sdw_rt5682.c
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2023 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_cs42l43 - Helpers to handle CS42L43 from generic machine driver
|
||||
* soc_sdw_cs42l43 - Helpers to handle CS42L43 from generic machine driver
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
@ -16,7 +18,7 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_route cs42l43_hs_map[] = {
|
||||
{ "Headphone", NULL, "cs42l43 AMP3_OUT" },
|
||||
@ -37,7 +39,7 @@ static const struct snd_soc_dapm_route cs42l43_dmic_map[] = {
|
||||
{ "cs42l43 PDM2_DIN", NULL, "DMIC" },
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_pin sof_jack_pins[] = {
|
||||
static struct snd_soc_jack_pin soc_jack_pins[] = {
|
||||
{
|
||||
.pin = "Headphone",
|
||||
.mask = SND_JACK_HEADPHONE,
|
||||
@ -48,10 +50,10 @@ static struct snd_soc_jack_pin sof_jack_pins[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct snd_soc_jack *jack = &ctx->sdw_headset;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -73,8 +75,8 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai
|
||||
SND_JACK_HEADSET | SND_JACK_LINEOUT |
|
||||
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3,
|
||||
jack, sof_jack_pins,
|
||||
ARRAY_SIZE(sof_jack_pins));
|
||||
jack, soc_jack_pins,
|
||||
ARRAY_SIZE(soc_jack_pins));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "Failed to create jack: %d\n", ret);
|
||||
return ret;
|
||||
@ -98,13 +100,15 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
|
||||
if (!(sof_sdw_quirk & SOF_SIDECAR_AMPS)) {
|
||||
if (!(ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS)) {
|
||||
/* Will be set by the bridge code in this case */
|
||||
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
||||
"%s spk:cs42l43-spk",
|
||||
@ -120,11 +124,12 @@ int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *da
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
/* Do init on playback link only. */
|
||||
if (!playback)
|
||||
@ -132,10 +137,11 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card,
|
||||
|
||||
info->amp_num++;
|
||||
|
||||
return bridge_cs35l56_spk_init(card, dai_links, info, playback);
|
||||
return asoc_sdw_bridge_cs35l56_spk_init(card, dai_links, info, playback);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -152,4 +158,4 @@ int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *d
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_dmic_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2023 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_cs_amp - Helpers to handle CS35L56 from generic machine driver
|
||||
* soc_sdw_cs_amp - Helpers to handle CS35L56 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -10,11 +12,11 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dai.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
#define CODEC_NAME_SIZE 8
|
||||
|
||||
int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
const char *dai_name = rtd->dai_link->codecs->dai_name;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
@ -44,11 +46,12 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
/* Do init on playback link only. */
|
||||
if (!playback)
|
||||
@ -58,3 +61,4 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_cs_amp_init, SND_SOC_SDW_UTILS);
|
@ -1,14 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_dmic - Helpers to handle dmic from generic machine driver
|
||||
* soc_sdw_dmic - Helpers to handle dmic from generic machine driver
|
||||
*/
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget dmic_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
||||
@ -19,7 +21,7 @@ static const struct snd_soc_dapm_route dmic_map[] = {
|
||||
{"DMic", NULL, "SoC DMIC"},
|
||||
};
|
||||
|
||||
int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd)
|
||||
int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -40,4 +42,4 @@ int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_dmic_init, SND_SOC_SDW_UTILS);
|
@ -1,7 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// sof_sdw_maxim - Helpers to handle maxim codecs
|
||||
// soc_sdw_maxim - Helpers to handle maxim codecs
|
||||
// codec devices from generic machine driver
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -10,18 +12,18 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static int maxim_part_id;
|
||||
#define SOF_SDW_PART_ID_MAX98363 0x8363
|
||||
#define SOF_SDW_PART_ID_MAX98373 0x8373
|
||||
#define SOC_SDW_PART_ID_MAX98363 0x8363
|
||||
#define SOC_SDW_PART_ID_MAX98373 0x8373
|
||||
|
||||
static const struct snd_soc_dapm_route max_98373_dapm_routes[] = {
|
||||
{ "Left Spk", NULL, "Left BE_OUT" },
|
||||
{ "Right Spk", NULL, "Right BE_OUT" },
|
||||
};
|
||||
|
||||
int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -41,8 +43,9 @@ int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_maxim_spk_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable)
|
||||
static int asoc_sdw_mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *codec_dai;
|
||||
@ -75,40 +78,40 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
|
||||
static int asoc_sdw_mx8373_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* according to soc_pcm_prepare dai link prepare is called first */
|
||||
ret = sdw_prepare(substream);
|
||||
ret = asoc_sdw_prepare(substream);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return mx8373_enable_spk_pin(substream, true);
|
||||
return asoc_sdw_mx8373_enable_spk_pin(substream, true);
|
||||
}
|
||||
|
||||
static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream)
|
||||
static int asoc_sdw_mx8373_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* according to soc_pcm_hw_free dai link free is called first */
|
||||
ret = sdw_hw_free(substream);
|
||||
ret = asoc_sdw_hw_free(substream);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return mx8373_enable_spk_pin(substream, false);
|
||||
return asoc_sdw_mx8373_enable_spk_pin(substream, false);
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops max_98373_sdw_ops = {
|
||||
.startup = sdw_startup,
|
||||
.prepare = mx8373_sdw_prepare,
|
||||
.trigger = sdw_trigger,
|
||||
.hw_params = sdw_hw_params,
|
||||
.hw_free = mx8373_sdw_hw_free,
|
||||
.shutdown = sdw_shutdown,
|
||||
.startup = asoc_sdw_startup,
|
||||
.prepare = asoc_sdw_mx8373_prepare,
|
||||
.trigger = asoc_sdw_trigger,
|
||||
.hw_params = asoc_sdw_hw_params,
|
||||
.hw_free = asoc_sdw_mx8373_hw_free,
|
||||
.shutdown = asoc_sdw_shutdown,
|
||||
};
|
||||
|
||||
static int mx8373_sdw_late_probe(struct snd_soc_card *card)
|
||||
static int asoc_sdw_mx8373_sdw_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &card->dapm;
|
||||
|
||||
@ -118,22 +121,22 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card)
|
||||
return snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
int sof_sdw_maxim_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_maxim_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
info->amp_num++;
|
||||
|
||||
maxim_part_id = info->part_id;
|
||||
switch (maxim_part_id) {
|
||||
case SOF_SDW_PART_ID_MAX98363:
|
||||
case SOC_SDW_PART_ID_MAX98363:
|
||||
/* Default ops are set in function init_dai_link.
|
||||
* called as part of function create_sdw_dailink
|
||||
*/
|
||||
break;
|
||||
case SOF_SDW_PART_ID_MAX98373:
|
||||
info->codec_card_late_probe = mx8373_sdw_late_probe;
|
||||
case SOC_SDW_PART_ID_MAX98373:
|
||||
info->codec_card_late_probe = asoc_sdw_mx8373_sdw_late_probe;
|
||||
dai_links->ops = &max_98373_sdw_ops;
|
||||
break;
|
||||
default:
|
||||
@ -142,3 +145,4 @@ int sof_sdw_maxim_init(struct snd_soc_card *card,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_maxim_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver
|
||||
* soc_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -15,7 +17,7 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_route rt5682_map[] = {
|
||||
/*Headphones*/
|
||||
@ -35,10 +37,10 @@ static struct snd_soc_jack_pin rt5682_jack_pins[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
int ret;
|
||||
@ -86,4 +88,4 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt5682_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt700 - Helpers to handle RT700 from generic machine driver
|
||||
* soc_sdw_rt700 - Helpers to handle RT700 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -13,7 +15,7 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_route rt700_map[] = {
|
||||
/* Headphones */
|
||||
@ -33,10 +35,10 @@ static struct snd_soc_jack_pin rt700_jack_pins[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
int ret;
|
||||
@ -83,4 +85,4 @@ int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt700_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt711 - Helpers to handle RT711 from generic machine driver
|
||||
* soc_sdw_rt711 - Helpers to handle RT711 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -15,21 +17,21 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
/*
|
||||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int rt711_add_codec_device_props(struct device *sdw_dev)
|
||||
static int rt711_add_codec_device_props(struct device *sdw_dev, unsigned long quirk)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {};
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
|
||||
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
|
||||
if (!SOC_SDW_JACK_JDSRC(quirk))
|
||||
return 0;
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk));
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOC_SDW_JACK_JDSRC(quirk));
|
||||
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
@ -59,10 +61,10 @@ static struct snd_soc_jack_pin rt711_jack_pins[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
int ret;
|
||||
@ -110,10 +112,11 @@ int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt711_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (!ctx->headset_codec_dev)
|
||||
return 0;
|
||||
@ -123,13 +126,14 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt711_exit, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_rt711_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct device *sdw_dev;
|
||||
int ret;
|
||||
|
||||
@ -144,7 +148,7 @@ int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ret = rt711_add_codec_device_props(sdw_dev);
|
||||
ret = rt711_add_codec_device_props(sdw_dev, ctx->mc_quirk);
|
||||
if (ret < 0) {
|
||||
put_device(sdw_dev);
|
||||
return ret;
|
||||
@ -153,4 +157,4 @@ int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
|
||||
return 0;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt711_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2023 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver
|
||||
* soc_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -13,7 +15,7 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
/*
|
||||
* dapm routes for rt712 spk will be registered dynamically according
|
||||
@ -26,7 +28,7 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = {
|
||||
{ "Speaker", NULL, "rt712 SPOR" },
|
||||
};
|
||||
|
||||
int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -43,4 +45,4 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt712_spk_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2023 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver
|
||||
* soc_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -13,13 +15,13 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_route rt722_spk_map[] = {
|
||||
{ "Speaker", NULL, "rt722 SPK" },
|
||||
};
|
||||
|
||||
int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
@ -36,4 +38,4 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt722_spk_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2022 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver
|
||||
* soc_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -14,9 +16,9 @@
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include "sof_sdw_amp_coeff_tables.h"
|
||||
#include "../../codecs/rt1308.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
#include "soc_sdw_rt_amp_coeff_tables.h"
|
||||
#include "../codecs/rt1308.h"
|
||||
|
||||
#define CODEC_NAME_SIZE 7
|
||||
|
||||
@ -173,7 +175,7 @@ static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_
|
||||
return rt1318_map;
|
||||
}
|
||||
|
||||
int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
const struct snd_soc_dapm_route *rt_amp_map;
|
||||
@ -199,6 +201,7 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_spk_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
@ -233,13 +236,14 @@ static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
/* machine stream operations */
|
||||
const struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
|
||||
const struct snd_soc_ops soc_sdw_rt1308_i2s_ops = {
|
||||
.hw_params = rt1308_i2s_hw_params,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(soc_sdw_rt1308_i2s_ops, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (ctx->amp_dev1) {
|
||||
device_remove_software_node(ctx->amp_dev1);
|
||||
@ -253,13 +257,14 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_exit, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_rt_amp_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct device *sdw_dev1, *sdw_dev2;
|
||||
int ret;
|
||||
|
||||
@ -295,3 +300,4 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_init, SND_SOC_SDW_UTILS);
|
@ -2,11 +2,11 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* sof_sdw_amp_coeff_tables.h - related coefficients for amplifier parameters
|
||||
* soc_sdw_rt_amp_coeff_tables.h - related coefficients for RTK amplifier parameters
|
||||
*/
|
||||
|
||||
#ifndef SND_SOC_SOF_SDW_AMP_COEFF_H
|
||||
#define SND_SOC_SOF_SDW_AMP_COEFF_H
|
||||
#ifndef SND_SOC_SDW_RT_SDW_AMP_COEFF_H
|
||||
#define SND_SOC_SDW_RT_SDW_AMP_COEFF_H
|
||||
|
||||
#define RT1308_MAX_BQ_REG 480
|
||||
#define RT1316_MAX_BQ_REG 580
|
@ -1,18 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2024 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver
|
||||
* soc_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "sof_board_helpers.h"
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_component *component;
|
||||
@ -39,4 +40,4 @@ int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
|
||||
return 0;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_dmic_rtd_init, SND_SOC_SDW_UTILS);
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright (c) 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
/*
|
||||
* sof_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver
|
||||
* soc_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -15,22 +17,22 @@
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/jack.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
/*
|
||||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev)
|
||||
static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev, unsigned long quirk)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {};
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
|
||||
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
|
||||
if (!SOC_SDW_JACK_JDSRC(quirk))
|
||||
return 0;
|
||||
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk));
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOC_SDW_JACK_JDSRC(quirk));
|
||||
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
@ -83,10 +85,10 @@ static const char * const need_sdca_suffix[] = {
|
||||
"rt711", "rt713"
|
||||
};
|
||||
|
||||
int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_jack *jack;
|
||||
int ret;
|
||||
@ -160,15 +162,16 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *d
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (!ctx->headset_codec_dev)
|
||||
return 0;
|
||||
|
||||
if (!SOF_JACK_JDSRC(sof_sdw_quirk))
|
||||
if (!SOC_SDW_JACK_JDSRC(ctx->mc_quirk))
|
||||
return 0;
|
||||
|
||||
device_remove_software_node(ctx->headset_codec_dev);
|
||||
@ -177,13 +180,14 @@ int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_exit, SND_SOC_SDW_UTILS);
|
||||
|
||||
int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct asoc_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct device *sdw_dev;
|
||||
int ret;
|
||||
|
||||
@ -198,7 +202,7 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ret = rt_sdca_jack_add_codec_device_props(sdw_dev);
|
||||
ret = rt_sdca_jack_add_codec_device_props(sdw_dev, ctx->mc_quirk);
|
||||
if (ret < 0) {
|
||||
put_device(sdw_dev);
|
||||
return ret;
|
||||
@ -207,4 +211,4 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
|
||||
|
||||
return 0;
|
||||
}
|
||||
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_init, SND_SOC_SDW_UTILS);
|
990
sound/soc/sdw_utils/soc_sdw_utils.c
Normal file
990
sound/soc/sdw_utils/soc_sdw_utils.c
Normal file
@ -0,0 +1,990 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// This file incorporates work covered by the following copyright notice:
|
||||
// Copyright (c) 2020 Intel Corporation
|
||||
// Copyright(c) 2024 Advanced Micro Devices, Inc.
|
||||
/*
|
||||
* soc-sdw-utils.c - common SoundWire machine driver helper functions
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <sound/soc_sdw_utils.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget generic_dmic_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("DMIC", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget generic_jack_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new generic_jack_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphone"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget generic_spk_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new generic_spk_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Speaker"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget maxim_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Left Spk", NULL),
|
||||
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new maxim_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Left Spk"),
|
||||
SOC_DAPM_PIN_SWITCH("Right Spk"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget rt700_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphones", NULL),
|
||||
SND_SOC_DAPM_MIC("AMIC", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new rt700_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphones"),
|
||||
SOC_DAPM_PIN_SWITCH("AMIC"),
|
||||
SOC_DAPM_PIN_SWITCH("Speaker"),
|
||||
};
|
||||
|
||||
struct asoc_sdw_codec_info codec_info_list[] = {
|
||||
{
|
||||
.part_id = 0x700,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt700-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt700_rtd_init,
|
||||
.controls = rt700_controls,
|
||||
.num_controls = ARRAY_SIZE(rt700_controls),
|
||||
.widgets = rt700_widgets,
|
||||
.num_widgets = ARRAY_SIZE(rt700_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x711,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt711-sdca-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_sdca_jack_init,
|
||||
.exit = asoc_sdw_rt_sdca_jack_exit,
|
||||
.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x711,
|
||||
.version_id = 2,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt711-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt711_init,
|
||||
.exit = asoc_sdw_rt711_exit,
|
||||
.rtd_init = asoc_sdw_rt711_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x712,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt712-sdca-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_sdca_jack_init,
|
||||
.exit = asoc_sdw_rt_sdca_jack_exit,
|
||||
.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "rt712-sdca-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.init = asoc_sdw_rt_amp_init,
|
||||
.exit = asoc_sdw_rt_amp_exit,
|
||||
.rtd_init = asoc_sdw_rt712_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 2,
|
||||
},
|
||||
{
|
||||
.part_id = 0x1712,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt712-sdca-dmic-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x713,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt712-sdca-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_sdca_jack_init,
|
||||
.exit = asoc_sdw_rt_sdca_jack_exit,
|
||||
.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x1713,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt712-sdca-dmic-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x1308,
|
||||
.acpi_id = "10EC1308",
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "rt1308-aif",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.init = asoc_sdw_rt_amp_init,
|
||||
.exit = asoc_sdw_rt_amp_exit,
|
||||
.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
.ops = &soc_sdw_rt1308_i2s_ops,
|
||||
},
|
||||
{
|
||||
.part_id = 0x1316,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt1316-aif",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_amp_init,
|
||||
.exit = asoc_sdw_rt_amp_exit,
|
||||
.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x1318,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt1318-aif",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_amp_init,
|
||||
.exit = asoc_sdw_rt_amp_exit,
|
||||
.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x714,
|
||||
.version_id = 3,
|
||||
.ignore_internal_dmic = true,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt715-sdca-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x715,
|
||||
.version_id = 3,
|
||||
.ignore_internal_dmic = true,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt715-sdca-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x714,
|
||||
.version_id = 2,
|
||||
.ignore_internal_dmic = true,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt715-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x715,
|
||||
.version_id = 2,
|
||||
.ignore_internal_dmic = true,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt715-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x722,
|
||||
.version_id = 3,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt722-sdca-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.init = asoc_sdw_rt_sdca_jack_init,
|
||||
.exit = asoc_sdw_rt_sdca_jack_exit,
|
||||
.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "rt722-sdca-aif2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
/* No feedback capability is provided by rt722-sdca codec driver*/
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.init = asoc_sdw_rt_amp_init,
|
||||
.exit = asoc_sdw_rt_amp_exit,
|
||||
.rtd_init = asoc_sdw_rt722_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "rt722-sdca-aif3",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
|
||||
},
|
||||
},
|
||||
.dai_num = 3,
|
||||
},
|
||||
{
|
||||
.part_id = 0x8373,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "max98373-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
|
||||
.init = asoc_sdw_maxim_init,
|
||||
.rtd_init = asoc_sdw_maxim_spk_rtd_init,
|
||||
.controls = maxim_controls,
|
||||
.num_controls = ARRAY_SIZE(maxim_controls),
|
||||
.widgets = maxim_widgets,
|
||||
.num_widgets = ARRAY_SIZE(maxim_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x8363,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "max98363-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.init = asoc_sdw_maxim_init,
|
||||
.rtd_init = asoc_sdw_maxim_spk_rtd_init,
|
||||
.controls = maxim_controls,
|
||||
.num_controls = ARRAY_SIZE(maxim_controls),
|
||||
.widgets = maxim_widgets,
|
||||
.num_widgets = ARRAY_SIZE(maxim_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x5682,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "rt5682-sdw",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.rtd_init = asoc_sdw_rt5682_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x3556,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "cs35l56-sdw1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
|
||||
.init = asoc_sdw_cs_amp_init,
|
||||
.rtd_init = asoc_sdw_cs_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x4242,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "cs42l42-sdw",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
.rtd_init = asoc_sdw_cs42l42_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x4243,
|
||||
.codec_name = "cs42l43-codec",
|
||||
.count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
|
||||
.add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "cs42l43-dp5",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.rtd_init = asoc_sdw_cs42l43_hs_rtd_init,
|
||||
.controls = generic_jack_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_jack_controls),
|
||||
.widgets = generic_jack_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_jack_widgets),
|
||||
},
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "cs42l43-dp1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
.rtd_init = asoc_sdw_cs42l43_dmic_rtd_init,
|
||||
.widgets = generic_dmic_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
|
||||
},
|
||||
{
|
||||
.direction = {false, true},
|
||||
.dai_name = "cs42l43-dp2",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
},
|
||||
{
|
||||
.direction = {true, false},
|
||||
.dai_name = "cs42l43-dp6",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
|
||||
.init = asoc_sdw_cs42l43_spk_init,
|
||||
.rtd_init = asoc_sdw_cs42l43_spk_rtd_init,
|
||||
.controls = generic_spk_controls,
|
||||
.num_controls = ARRAY_SIZE(generic_spk_controls),
|
||||
.widgets = generic_spk_widgets,
|
||||
.num_widgets = ARRAY_SIZE(generic_spk_widgets),
|
||||
.quirk = SOC_SDW_CODEC_SPKR | SOC_SDW_SIDECAR_AMPS,
|
||||
},
|
||||
},
|
||||
.dai_num = 4,
|
||||
},
|
||||
{
|
||||
.part_id = 0xaaaa, /* generic codec mockup */
|
||||
.version_id = 0,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0xaa55, /* headset codec mockup */
|
||||
.version_id = 0,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_JACK,
|
||||
.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x55aa, /* amplifier mockup */
|
||||
.version_id = 0,
|
||||
.dais = {
|
||||
{
|
||||
.direction = {true, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.dai_type = SOC_SDW_DAI_TYPE_AMP,
|
||||
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
{
|
||||
.part_id = 0x5555,
|
||||
.version_id = 0,
|
||||
.dais = {
|
||||
{
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.direction = {false, true},
|
||||
.dai_type = SOC_SDW_DAI_TYPE_MIC,
|
||||
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
|
||||
},
|
||||
},
|
||||
.dai_num = 1,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_NS(codec_info_list, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_get_codec_info_list_count(void)
|
||||
{
|
||||
return ARRAY_SIZE(codec_info_list);
|
||||
};
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, SND_SOC_SDW_UTILS);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
|
||||
{
|
||||
unsigned int part_id, sdw_version;
|
||||
int i;
|
||||
|
||||
part_id = SDW_PART_ID(adr);
|
||||
sdw_version = SDW_VERSION(adr);
|
||||
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
|
||||
/*
|
||||
* A codec info is for all sdw version with the part id if
|
||||
* version_id is not specified in the codec info.
|
||||
*/
|
||||
if (part_id == codec_info_list[i].part_id &&
|
||||
(!codec_info_list[i].version_id ||
|
||||
sdw_version == codec_info_list[i].version_id))
|
||||
return &codec_info_list[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, SND_SOC_SDW_UTILS);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!acpi_id[0])
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
|
||||
if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN))
|
||||
return &codec_info_list[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_acpi, SND_SOC_SDW_UTILS);
|
||||
|
||||
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, int *dai_index)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
|
||||
for (j = 0; j < codec_info_list[i].dai_num; j++) {
|
||||
if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
|
||||
*dai_index = j;
|
||||
return &codec_info_list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct asoc_sdw_codec_info *codec_info;
|
||||
struct snd_soc_dai *dai;
|
||||
int dai_index;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for_each_rtd_codec_dais(rtd, i, dai) {
|
||||
codec_info = asoc_sdw_find_codec_info_dai(dai->name, &dai_index);
|
||||
if (!codec_info)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* A codec dai can be connected to different dai links for capture and playback,
|
||||
* but we only need to call the rtd_init function once.
|
||||
* The rtd_init for each codec dai is independent. So, the order of rtd_init
|
||||
* doesn't matter.
|
||||
*/
|
||||
if (codec_info->dais[dai_index].rtd_init_done)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Add card controls and dapm widgets for the first codec dai.
|
||||
* The controls and widgets will be used for all codec dais.
|
||||
*/
|
||||
|
||||
if (i > 0)
|
||||
goto skip_add_controls_widgets;
|
||||
|
||||
if (codec_info->dais[dai_index].controls) {
|
||||
ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
|
||||
codec_info->dais[dai_index].num_controls);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%#x controls addition failed: %d\n",
|
||||
codec_info->part_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (codec_info->dais[dai_index].widgets) {
|
||||
ret = snd_soc_dapm_new_controls(&card->dapm,
|
||||
codec_info->dais[dai_index].widgets,
|
||||
codec_info->dais[dai_index].num_widgets);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%#x widgets addition failed: %d\n",
|
||||
codec_info->part_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
skip_add_controls_widgets:
|
||||
if (codec_info->dais[dai_index].rtd_init) {
|
||||
ret = codec_info->dais[dai_index].rtd_init(rtd, dai);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
codec_info->dais[dai_index].rtd_init_done = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, SND_SOC_SDW_UTILS);
|
||||
|
||||
/* these wrappers are only needed to avoid typecast compilation errors */
|
||||
int asoc_sdw_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return sdw_startup_stream(substream);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_startup, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct sdw_stream_runtime *sdw_stream;
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
/* Find stream from first CPU DAI */
|
||||
dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
|
||||
if (IS_ERR(sdw_stream)) {
|
||||
dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
|
||||
return PTR_ERR(sdw_stream);
|
||||
}
|
||||
|
||||
return sdw_prepare_stream(sdw_stream);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_prepare, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct sdw_stream_runtime *sdw_stream;
|
||||
struct snd_soc_dai *dai;
|
||||
int ret;
|
||||
|
||||
/* Find stream from first CPU DAI */
|
||||
dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
|
||||
if (IS_ERR(sdw_stream)) {
|
||||
dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
|
||||
return PTR_ERR(sdw_stream);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
ret = sdw_enable_stream(sdw_stream);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
ret = sdw_disable_stream(sdw_stream);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_trigger, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai_link_ch_map *ch_maps;
|
||||
int ch = params_channels(params);
|
||||
unsigned int ch_mask;
|
||||
int num_codecs;
|
||||
int step;
|
||||
int i;
|
||||
|
||||
if (!rtd->dai_link->ch_maps)
|
||||
return 0;
|
||||
|
||||
/* Identical data will be sent to all codecs in playback */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
ch_mask = GENMASK(ch - 1, 0);
|
||||
step = 0;
|
||||
} else {
|
||||
num_codecs = rtd->dai_link->num_codecs;
|
||||
|
||||
if (ch < num_codecs || ch % num_codecs != 0) {
|
||||
dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n",
|
||||
ch, num_codecs);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ch_mask = GENMASK(ch / num_codecs - 1, 0);
|
||||
step = hweight_long(ch_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* The captured data will be combined from each cpu DAI if the dai
|
||||
* link has more than one codec DAIs. Set codec channel mask and
|
||||
* ASoC will set the corresponding channel numbers for each cpu dai.
|
||||
*/
|
||||
for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
|
||||
ch_maps->ch_mask = ch_mask << (i * step);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_hw_params, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct sdw_stream_runtime *sdw_stream;
|
||||
struct snd_soc_dai *dai;
|
||||
|
||||
/* Find stream from first CPU DAI */
|
||||
dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
|
||||
if (IS_ERR(sdw_stream)) {
|
||||
dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
|
||||
return PTR_ERR(sdw_stream);
|
||||
}
|
||||
|
||||
return sdw_deprepare_stream(sdw_stream);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_hw_free, SND_SOC_SDW_UTILS);
|
||||
|
||||
void asoc_sdw_shutdown(struct snd_pcm_substream *substream)
|
||||
{
|
||||
sdw_shutdown_stream(substream);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_shutdown, SND_SOC_SDW_UTILS);
|
||||
|
||||
static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_link,
|
||||
unsigned int sdw_version,
|
||||
unsigned int mfg_id,
|
||||
unsigned int part_id,
|
||||
unsigned int class_id,
|
||||
int index_in_link)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adr_link->num_adr; i++) {
|
||||
unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
|
||||
u64 adr;
|
||||
|
||||
/* skip itself */
|
||||
if (i == index_in_link)
|
||||
continue;
|
||||
|
||||
adr = adr_link->adr_d[i].adr;
|
||||
|
||||
sdw1_version = SDW_VERSION(adr);
|
||||
mfg1_id = SDW_MFG_ID(adr);
|
||||
part1_id = SDW_PART_ID(adr);
|
||||
class1_id = SDW_CLASS_ID(adr);
|
||||
|
||||
if (sdw_version == sdw1_version &&
|
||||
mfg_id == mfg1_id &&
|
||||
part_id == part1_id &&
|
||||
class_id == class1_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *asoc_sdw_get_codec_name(struct device *dev,
|
||||
const struct asoc_sdw_codec_info *codec_info,
|
||||
const struct snd_soc_acpi_link_adr *adr_link,
|
||||
int adr_index)
|
||||
{
|
||||
u64 adr = adr_link->adr_d[adr_index].adr;
|
||||
unsigned int sdw_version = SDW_VERSION(adr);
|
||||
unsigned int link_id = SDW_DISCO_LINK_ID(adr);
|
||||
unsigned int unique_id = SDW_UNIQUE_ID(adr);
|
||||
unsigned int mfg_id = SDW_MFG_ID(adr);
|
||||
unsigned int part_id = SDW_PART_ID(adr);
|
||||
unsigned int class_id = SDW_CLASS_ID(adr);
|
||||
|
||||
if (codec_info->codec_name)
|
||||
return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL);
|
||||
else if (asoc_sdw_is_unique_device(adr_link, sdw_version, mfg_id, part_id,
|
||||
class_id, adr_index))
|
||||
return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x",
|
||||
link_id, mfg_id, part_id, class_id);
|
||||
else
|
||||
return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
|
||||
link_id, mfg_id, part_id, class_id, unique_id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, SND_SOC_SDW_UTILS);
|
||||
|
||||
/* helper to get the link that the codec DAI is used */
|
||||
struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card,
|
||||
const char *dai_name)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for_each_card_prelinks(card, i, dai_link) {
|
||||
for (j = 0; j < dai_link->num_codecs; j++) {
|
||||
/* Check each codec in a link */
|
||||
if (!strcmp(dai_link->codecs[j].dai_name, dai_name))
|
||||
return dai_link;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_mc_find_codec_dai_used, SND_SOC_SDW_UTILS);
|
||||
|
||||
void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ctx->codec_info_list_count; i++) {
|
||||
for (j = 0; j < codec_info_list[i].dai_num; j++) {
|
||||
codec_info_list[i].dais[j].rtd_init_done = false;
|
||||
/* Check each dai in codec_info_lis to see if it is used in the link */
|
||||
if (!codec_info_list[i].dais[j].exit)
|
||||
continue;
|
||||
/*
|
||||
* We don't need to call .exit function if there is no matched
|
||||
* dai link found.
|
||||
*/
|
||||
dai_link = asoc_sdw_mc_find_codec_dai_used(card,
|
||||
codec_info_list[i].dais[j].dai_name);
|
||||
if (dai_link) {
|
||||
/* Do the .exit function if the codec dai is used in the link */
|
||||
ret = codec_info_list[i].dais[j].exit(card, dai_link);
|
||||
if (ret)
|
||||
dev_warn(card->dev,
|
||||
"codec exit failed %d\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_mc_dailink_exit_loop, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_card_late_probe(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
|
||||
if (codec_info_list[i].codec_card_late_probe) {
|
||||
ret = codec_info_list[i].codec_card_late_probe(card);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, SND_SOC_SDW_UTILS);
|
||||
|
||||
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||
int *be_id, char *name, int playback, int capture,
|
||||
struct snd_soc_dai_link_component *cpus, int cpus_num,
|
||||
struct snd_soc_dai_link_component *platform_component,
|
||||
int num_platforms, struct snd_soc_dai_link_component *codecs,
|
||||
int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||
const struct snd_soc_ops *ops)
|
||||
{
|
||||
dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id);
|
||||
dai_links->id = (*be_id)++;
|
||||
dai_links->name = name;
|
||||
dai_links->platforms = platform_component;
|
||||
dai_links->num_platforms = num_platforms;
|
||||
dai_links->no_pcm = 1;
|
||||
dai_links->cpus = cpus;
|
||||
dai_links->num_cpus = cpus_num;
|
||||
dai_links->codecs = codecs;
|
||||
dai_links->num_codecs = codecs_num;
|
||||
dai_links->dpcm_playback = playback;
|
||||
dai_links->dpcm_capture = capture;
|
||||
dai_links->init = init;
|
||||
dai_links->ops = ops;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, SND_SOC_SDW_UTILS);
|
||||
|
||||
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||
int *be_id, char *name, int playback, int capture,
|
||||
const char *cpu_dai_name, const char *platform_comp_name,
|
||||
int num_platforms, const char *codec_name,
|
||||
const char *codec_dai_name,
|
||||
int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||
const struct snd_soc_ops *ops)
|
||||
{
|
||||
struct snd_soc_dai_link_component *dlc;
|
||||
|
||||
/* Allocate three DLCs one for the CPU, one for platform and one for the CODEC */
|
||||
dlc = devm_kcalloc(dev, 3, sizeof(*dlc), GFP_KERNEL);
|
||||
if (!dlc || !name || !cpu_dai_name || !platform_comp_name || !codec_name || !codec_dai_name)
|
||||
return -ENOMEM;
|
||||
|
||||
dlc[0].dai_name = cpu_dai_name;
|
||||
dlc[1].name = platform_comp_name;
|
||||
|
||||
dlc[2].name = codec_name;
|
||||
dlc[2].dai_name = codec_dai_name;
|
||||
|
||||
asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture,
|
||||
&dlc[0], 1, &dlc[1], num_platforms,
|
||||
&dlc[2], 1, init, ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, SND_SOC_SDW_UTILS);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SoundWire ASoC helpers");
|
@ -23,6 +23,7 @@ config SND_SOC_SOF_AMD_COMMON
|
||||
select SND_AMD_ACP_CONFIG
|
||||
select SND_SOC_SOF_XTENSA
|
||||
select SND_SOC_SOF_ACP_PROBES
|
||||
select SND_SOC_ACPI_AMD_MATCH
|
||||
select SND_SOC_ACPI if ACPI
|
||||
help
|
||||
This option is not user-selectable but automatically handled by
|
||||
|
@ -153,6 +153,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *
|
||||
break;
|
||||
}
|
||||
if (mach && mach->link_mask) {
|
||||
mach->mach_params.subsystem_rev = acp_data->pci_rev;
|
||||
mach->mach_params.links = mach->links;
|
||||
mach->mach_params.link_mask = mach->link_mask;
|
||||
mach->mach_params.platform = dev_name(sdev->dev);
|
||||
@ -173,6 +174,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *
|
||||
struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev)
|
||||
{
|
||||
struct snd_sof_pdata *sof_pdata = sdev->pdata;
|
||||
struct acp_dev_data *acp_data = sdev->pdata->hw_pdata;
|
||||
const struct sof_dev_desc *desc = sof_pdata->desc;
|
||||
struct snd_soc_acpi_mach *mach = NULL;
|
||||
|
||||
@ -186,6 +188,7 @@ struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev)
|
||||
}
|
||||
}
|
||||
|
||||
mach->mach_params.subsystem_rev = acp_data->pci_rev;
|
||||
sof_pdata->tplg_filename = mach->sof_tplg_filename;
|
||||
sof_pdata->fw_filename = mach->fw_filename;
|
||||
|
||||
|
@ -695,6 +695,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
|
||||
pci_set_master(pci);
|
||||
adata->addr = addr;
|
||||
adata->reg_range = chip->reg_end_addr - chip->reg_start_addr;
|
||||
adata->pci_rev = pci->revision;
|
||||
mutex_init(&adata->acp_lock);
|
||||
sdev->pdata->hw_pdata = adata;
|
||||
adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL);
|
||||
|
@ -251,6 +251,7 @@ struct acp_dev_data {
|
||||
bool is_dram_in_use;
|
||||
bool is_sram_in_use;
|
||||
bool sdw_en_stat;
|
||||
unsigned int pci_rev;
|
||||
};
|
||||
|
||||
void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes);
|
||||
|
@ -48,6 +48,7 @@ static const struct sof_amd_acp_desc acp63_chip_info = {
|
||||
|
||||
static const struct sof_dev_desc acp63_desc = {
|
||||
.machines = snd_soc_acpi_amd_acp63_sof_machines,
|
||||
.alt_machines = snd_soc_acpi_amd_acp63_sof_sdw_machines,
|
||||
.resindex_lpe_base = 0,
|
||||
.resindex_pcicfg_base = -1,
|
||||
.resindex_imr_base = -1,
|
||||
|
Loading…
Reference in New Issue
Block a user