summaryrefslogtreecommitdiff
path: root/sound/soc/intel/avs/board_selection.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/avs/board_selection.c')
-rw-r--r--sound/soc/intel/avs/board_selection.c309
1 files changed, 120 insertions, 189 deletions
diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c
index fb49167f5fc4..52e6266a7cb8 100644
--- a/sound/soc/intel/avs/board_selection.c
+++ b/sound/soc/intel/avs/board_selection.c
@@ -17,6 +17,8 @@
#include <sound/soc-acpi.h>
#include <sound/soc-component.h>
#include "avs.h"
+#include "debug.h"
+#include "pcm.h"
#include "utils.h"
static char *i2s_test;
@@ -56,19 +58,13 @@ static const struct dmi_system_id kblr_dmi_table[] = {
static struct snd_soc_acpi_mach *dmi_match_quirk(void *arg)
{
struct snd_soc_acpi_mach *mach = arg;
- const struct dmi_system_id *dmi_id;
struct dmi_system_id *dmi_table;
- if (mach->quirk_data == NULL)
- return mach;
-
dmi_table = (struct dmi_system_id *)mach->quirk_data;
- dmi_id = dmi_first_match(dmi_table);
- if (!dmi_id)
- return NULL;
-
- return mach;
+ if (!dmi_table || dmi_first_match(dmi_table))
+ return mach;
+ return NULL;
}
#define AVS_SSP(x) (BIT(x))
@@ -368,10 +364,10 @@ struct avs_acpi_boards {
/* supported I2S boards per platform */
static const struct avs_acpi_boards i2s_boards[] = {
- AVS_MACH_ENTRY(HDA_SKL_LP, avs_skl_i2s_machines),
- AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines),
- AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines),
- AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines),
+ AVS_MACH_ENTRY(HDA_SKL_LP, avs_skl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines),
AVS_MACH_ENTRY(HDA_CNL_LP, avs_cnl_i2s_machines),
AVS_MACH_ENTRY(HDA_CNL_H, avs_cnl_i2s_machines),
AVS_MACH_ENTRY(HDA_CML_LP, avs_cnl_i2s_machines),
@@ -386,185 +382,122 @@ static const struct avs_acpi_boards i2s_boards[] = {
{ },
};
-static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev)
+static struct snd_soc_acpi_mach *avs_get_i2s_machines(struct avs_dev *adev)
{
int id, i;
id = adev->base.pci->device;
for (i = 0; i < ARRAY_SIZE(i2s_boards); i++)
if (i2s_boards[i].id == id)
- return &i2s_boards[i];
+ return i2s_boards[i].machs;
return NULL;
}
-/* platform devices owned by AVS audio are removed with this hook */
-static void board_pdev_unregister(void *data)
+/* Platform devices spawned by AVS driver are removed with this hook. */
+static void avs_unregister_board(void *pdev)
{
- platform_device_unregister(data);
+ platform_device_unregister(pdev);
}
-static int __maybe_unused avs_register_probe_board(struct avs_dev *adev)
+static struct platform_device *avs_register_board(struct avs_dev *adev, const char *name,
+ const void *data, size_t size)
{
- struct platform_device *board;
- struct snd_soc_acpi_mach mach = {{0}};
+ struct platform_device *pdev;
int ret;
- ret = avs_probe_platform_register(adev, "probe-platform");
- if (ret < 0)
- return ret;
-
- mach.mach_params.platform = "probe-platform";
+ pdev = platform_device_register_data(NULL, name, PLATFORM_DEVID_AUTO, data, size);
+ if (IS_ERR(pdev))
+ return pdev;
- board = platform_device_register_data(NULL, "avs_probe_mb", PLATFORM_DEVID_NONE,
- (const void *)&mach, sizeof(mach));
- if (IS_ERR(board)) {
- dev_err(adev->dev, "probe board register failed\n");
- return PTR_ERR(board);
- }
+ ret = devm_add_action_or_reset(adev->dev, avs_unregister_board, pdev);
+ if (ret)
+ return ERR_PTR(ret);
- ret = devm_add_action(adev->dev, board_pdev_unregister, board);
- if (ret < 0) {
- platform_device_unregister(board);
- return ret;
- }
- return 0;
+ return pdev;
}
-static int avs_register_dmic_board(struct avs_dev *adev)
+static struct platform_device *avs_register_board_pdata(struct avs_dev *adev, const char *name,
+ struct snd_soc_acpi_mach *mach,
+ struct hda_codec *codec,
+ unsigned long *tdms, char *codec_name)
{
- struct platform_device *codec, *board;
- struct snd_soc_acpi_mach mach = {{0}};
struct avs_mach_pdata *pdata;
- int ret;
-
- if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) {
- dev_dbg(adev->dev, "no DMIC endpoints present\n");
- return 0;
- }
-
- codec = platform_device_register_simple("dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
- if (IS_ERR(codec)) {
- dev_err(adev->dev, "dmic codec register failed\n");
- return PTR_ERR(codec);
- }
-
- ret = devm_add_action(adev->dev, board_pdev_unregister, codec);
- if (ret < 0) {
- platform_device_unregister(codec);
- return ret;
- }
-
- ret = avs_dmic_platform_register(adev, "dmic-platform");
- if (ret < 0)
- return ret;
pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
- return -ENOMEM;
- pdata->obsolete_card_names = obsolete_card_names;
- mach.pdata = pdata;
- mach.tplg_filename = "dmic-tplg.bin";
- mach.mach_params.platform = "dmic-platform";
-
- board = platform_device_register_data(NULL, "avs_dmic", PLATFORM_DEVID_NONE,
- (const void *)&mach, sizeof(mach));
- if (IS_ERR(board)) {
- dev_err(adev->dev, "dmic board register failed\n");
- return PTR_ERR(board);
- }
+ return ERR_PTR(-ENOMEM);
- ret = devm_add_action(adev->dev, board_pdev_unregister, board);
- if (ret < 0) {
- platform_device_unregister(board);
- return ret;
- }
+ pdata->codec = codec;
+ pdata->tdms = tdms;
+ pdata->codec_name = codec_name;
+ pdata->obsolete_card_names = obsolete_card_names;
+ mach->pdata = pdata;
- return 0;
+ return avs_register_board(adev, name, mach, sizeof(*mach));
}
-static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach)
+static int __maybe_unused avs_register_probe_board(struct avs_dev *adev)
{
- struct platform_device *board;
- struct avs_mach_pdata *pdata;
- int num_ssps;
- char *name;
- int ret;
- int uid;
-
- num_ssps = adev->hw_cfg.i2s_caps.ctrl_count;
- if (fls(mach->mach_params.i2s_link_mask) > num_ssps) {
- dev_err(adev->dev, "Platform supports %d SSPs but board %s requires SSP%ld\n",
- num_ssps, mach->drv_name,
- (unsigned long)__fls(mach->mach_params.i2s_link_mask));
- return -ENODEV;
- }
+ struct platform_device *pdev;
- pdata = mach->pdata;
- if (!pdata)
- pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
- pdata->obsolete_card_names = obsolete_card_names;
- mach->pdata = pdata;
+ pdev = avs_register_board(adev, "avs_probe_mb", NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- uid = mach->mach_params.i2s_link_mask;
- if (avs_mach_singular_ssp(mach))
- uid = (uid << AVS_CHANNELS_MAX) + avs_mach_ssp_tdm(mach, avs_mach_ssp_port(mach));
+ return avs_register_probe_component(adev, dev_name(&pdev->dev));
+}
- name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, uid);
- if (!name)
- return -ENOMEM;
+static int avs_register_dmic_board(struct avs_dev *adev)
+{
+ static struct snd_soc_acpi_mach mach = {
+ .tplg_filename = "dmic-tplg.bin",
+ };
+ struct platform_device *pdev;
+ char *codec_name;
- ret = avs_i2s_platform_register(adev, name, mach->mach_params.i2s_link_mask, pdata->tdms);
- if (ret < 0)
- return ret;
+ if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) {
+ dev_dbg(adev->dev, "no DMIC endpoints present\n");
+ return 0;
+ }
- mach->mach_params.platform = name;
+ /* DMIC present in Intel PCH is enumerated statically. */
+ pdev = avs_register_board(adev, "dmic-codec", NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- board = platform_device_register_data(NULL, mach->drv_name, uid,
- (const void *)mach, sizeof(*mach));
- if (IS_ERR(board)) {
- dev_err(adev->dev, "ssp board register failed\n");
- return PTR_ERR(board);
- }
+ codec_name = devm_kstrdup(adev->dev, dev_name(&pdev->dev), GFP_KERNEL);
+ if (!codec_name)
+ return -ENOMEM;
- ret = devm_add_action(adev->dev, board_pdev_unregister, board);
- if (ret < 0) {
- platform_device_unregister(board);
- return ret;
- }
+ pdev = avs_register_board_pdata(adev, "avs_dmic", &mach, NULL, NULL, codec_name);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- return 0;
+ return avs_register_dmic_component(adev, dev_name(&pdev->dev));
}
static int avs_register_i2s_test_board(struct avs_dev *adev, int ssp_port, int tdm_slot)
{
- struct snd_soc_acpi_mach *mach;
- int tdm_mask = BIT(tdm_slot);
- unsigned long *tdm_cfg;
- char *tplg_name;
- int ret;
-
- mach = devm_kzalloc(adev->dev, sizeof(*mach), GFP_KERNEL);
- tdm_cfg = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(unsigned long), GFP_KERNEL);
- tplg_name = devm_kasprintf(adev->dev, GFP_KERNEL, AVS_STRING_FMT("i2s", "-test-tplg.bin",
- ssp_port, tdm_slot));
- if (!mach || !tdm_cfg || !tplg_name)
+ struct snd_soc_acpi_mach mach = {{0}};
+ struct platform_device *pdev;
+ unsigned long *tdms;
+
+ tdms = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(*tdms), GFP_KERNEL);
+ mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
+ AVS_STRING_FMT("i2s", "-test-tplg.bin",
+ ssp_port, tdm_slot));
+ if (!tdms || !mach.tplg_filename)
return -ENOMEM;
- mach->drv_name = "avs_i2s_test";
- mach->mach_params.i2s_link_mask = AVS_SSP(ssp_port);
- tdm_cfg[ssp_port] = tdm_mask;
- mach->pdata = tdm_cfg;
- mach->tplg_filename = tplg_name;
+ tdms[ssp_port] = BIT(tdm_slot);
+ mach.drv_name = "avs_i2s_test";
+ mach.mach_params.i2s_link_mask = AVS_SSP(ssp_port);
- ret = avs_register_i2s_board(adev, mach);
- if (ret < 0) {
- dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret);
- return ret;
- }
+ pdev = avs_register_board_pdata(adev, mach.drv_name, &mach, NULL, tdms, NULL);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- return 0;
+ return avs_register_i2s_component(adev, dev_name(&pdev->dev), AVS_SSP(ssp_port), tdms);
}
static int avs_register_i2s_test_boards(struct avs_dev *adev)
@@ -574,6 +507,9 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev)
unsigned long tdm_slots;
u32 *array, num_elems;
+ if (!i2s_test)
+ return 0;
+
ret = parse_int_array(i2s_test, strlen(i2s_test), (int **)&array);
if (ret) {
dev_err(adev->dev, "failed to parse i2s_test parameter\n");
@@ -599,9 +535,26 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev)
return 0;
}
+static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach)
+{
+ u32 i2s_mask = mach->mach_params.i2s_link_mask;
+ struct platform_device *pdev;
+ unsigned long *tdms = NULL;
+
+ if (mach->pdata)
+ tdms = ((struct avs_mach_pdata *)mach->pdata)->tdms;
+
+ pdev = avs_register_board_pdata(adev, mach->drv_name, mach, NULL, tdms, NULL);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return avs_register_i2s_component(adev, dev_name(&pdev->dev), i2s_mask, tdms);
+}
+
static int avs_register_i2s_boards(struct avs_dev *adev)
{
- const struct avs_acpi_boards *boards;
+ int num_ssps = adev->hw_cfg.i2s_caps.ctrl_count;
+ struct snd_soc_acpi_mach *machs;
struct snd_soc_acpi_mach *mach;
int ret;
@@ -610,19 +563,22 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
return 0;
}
- if (i2s_test)
- return avs_register_i2s_test_boards(adev);
-
- boards = avs_get_i2s_boards(adev);
- if (!boards) {
+ machs = avs_get_i2s_machines(adev);
+ if (!machs) {
dev_dbg(adev->dev, "no I2S endpoints supported\n");
return 0;
}
- for (mach = boards->machs; mach->id[0]; mach++) {
+ for (mach = machs; mach->id[0]; mach++) {
if (!acpi_dev_present(mach->id, mach->uid, -1))
continue;
+ if (fls(mach->mach_params.i2s_link_mask) > num_ssps) {
+ dev_err(adev->dev, "Platform supports %d SSPs but board %s requires SSP%ld\n",
+ num_ssps, mach->drv_name,
+ (unsigned long)__fls(mach->mach_params.i2s_link_mask));
+ continue;
+ }
if (mach->machine_quirk)
if (!mach->machine_quirk(mach))
continue;
@@ -637,49 +593,20 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
static int avs_register_hda_board(struct avs_dev *adev, struct hda_codec *codec)
{
- struct snd_soc_acpi_mach mach = {{0}};
- struct platform_device *board;
- struct avs_mach_pdata *pdata;
struct hdac_device *hdev = &codec->core;
- char *pname;
- int ret, id;
-
- pname = devm_kasprintf(adev->dev, GFP_KERNEL, "%s-platform", dev_name(&hdev->dev));
- if (!pname)
- return -ENOMEM;
-
- pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
- pdata->obsolete_card_names = obsolete_card_names;
- pdata->codec = codec;
-
- ret = avs_hda_platform_register(adev, pname);
- if (ret < 0)
- return ret;
+ struct snd_soc_acpi_mach mach = {{0}};
+ struct platform_device *pdev;
- mach.pdata = pdata;
- mach.mach_params.platform = pname;
mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, "hda-%08x-tplg.bin",
hdev->vendor_id);
if (!mach.tplg_filename)
return -ENOMEM;
- id = adev->base.core.idx * HDA_MAX_CODECS + hdev->addr;
- board = platform_device_register_data(NULL, "avs_hdaudio", id, (const void *)&mach,
- sizeof(mach));
- if (IS_ERR(board)) {
- dev_err(adev->dev, "hda board register failed\n");
- return PTR_ERR(board);
- }
-
- ret = devm_add_action(adev->dev, board_pdev_unregister, board);
- if (ret < 0) {
- platform_device_unregister(board);
- return ret;
- }
+ pdev = avs_register_board_pdata(adev, "avs_hdaudio", &mach, codec, NULL, NULL);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- return 0;
+ return avs_register_hda_component(adev, dev_name(&pdev->dev));
}
static int avs_register_hda_boards(struct avs_dev *adev)
@@ -722,6 +649,10 @@ int avs_register_all_boards(struct avs_dev *adev)
dev_warn(adev->dev, "enumerate DMIC endpoints failed: %d\n",
ret);
+ ret = avs_register_i2s_test_boards(adev);
+ if (ret)
+ dev_dbg(adev->dev, "enumerate I2S TEST endpoints failed: %d\n", ret);
+
ret = avs_register_i2s_boards(adev);
if (ret < 0)
dev_warn(adev->dev, "enumerate I2S endpoints failed: %d\n",