ASoC: Intel: boards: updates for 6.7

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

A couple of new boards, one DMI quirk fix and a nice cleanup from
Brent Lu to make all HDMI stuff common across drivers.
This commit is contained in:
Mark Brown 2023-10-16 15:41:40 +01:00
commit 2e1a4596dc
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
17 changed files with 458 additions and 613 deletions

View file

@ -44,6 +44,9 @@ config SND_SOC_INTEL_SOF_NUVOTON_COMMON
config SND_SOC_INTEL_SOF_SSP_COMMON
tristate
config SND_SOC_INTEL_SOF_BOARD_HELPERS
tristate
if SND_SOC_INTEL_CATPT
config SND_SOC_INTEL_HASWELL_MACH
@ -495,8 +498,8 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
select SND_SOC_RT5682_I2C
select SND_SOC_RT5682S
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
@ -514,8 +517,8 @@ config SND_SOC_INTEL_SOF_CS42L42_MACH
select SND_SOC_CS42L42
select SND_SOC_MAX98357A
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON
help
@ -565,8 +568,8 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
select SND_SOC_MAX98357A
select SND_SOC_NAU8315
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_MAXIM_COMMON
select SND_SOC_INTEL_SOF_NUVOTON_COMMON
select SND_SOC_INTEL_SOF_REALTEK_COMMON
@ -637,8 +640,8 @@ config SND_SOC_INTEL_SOF_SSP_AMP_MACH
select SND_SOC_RT1308
select SND_SOC_CS35L41_I2C
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_INTEL_SOF_REALTEK_COMMON
select SND_SOC_INTEL_SOF_CIRRUS_COMMON
select SND_SOC_INTEL_SOF_SSP_COMMON

View file

@ -102,3 +102,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_NUVOTON_COMMON) += snd-soc-intel-sof-nuvoton-comm
snd-soc-intel-sof-ssp-common-objs += sof_ssp_common.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o
snd-soc-intel-sof-board-helpers-objs += sof_board_helpers.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_BOARD_HELPERS) += snd-soc-intel-sof-board-helpers.o

View file

@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2023 Intel Corporation. All rights reserved.
#include <sound/soc.h>
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
/*
* Intel HDMI DAI Link
*/
static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
ctx->hdmi.hdmi_comp = dai->component;
return 0;
}
int sof_intel_board_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
if (!ctx->hdmi_num)
return 0;
if (!ctx->hdmi.idisp_codec)
return 0;
if (!ctx->hdmi.hdmi_comp)
return -EINVAL;
return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
}
EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS);
/*
* DAI Link Helpers
*/
static struct snd_soc_dai_link_component platform_component[] = {
{
/* name might be overridden during probe */
.name = "0000:00:1f.3"
}
};
int sof_intel_board_set_intel_hdmi_link(struct device *dev,
struct snd_soc_dai_link *link, int be_id,
int hdmi_id, bool idisp_codec)
{
struct snd_soc_dai_link_component *cpus, *codecs;
dev_dbg(dev, "link %d: intel hdmi, hdmi id %d, idisp codec %d\n",
be_id, hdmi_id, idisp_codec);
/* link name */
link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id);
if (!link->name)
return -ENOMEM;
/* cpus */
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL);
if (!cpus)
return -ENOMEM;
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id);
if (!cpus->dai_name)
return -ENOMEM;
link->cpus = cpus;
link->num_cpus = 1;
/* codecs */
if (idisp_codec) {
codecs = devm_kzalloc(dev,
sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL);
if (!codecs)
return -ENOMEM;
codecs->name = "ehdaudio0D2";
codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"intel-hdmi-hifi%d", hdmi_id);
if (!codecs->dai_name)
return -ENOMEM;
link->codecs = codecs;
} else {
link->codecs = &snd_soc_dummy_dlc;
}
link->num_codecs = 1;
/* platforms */
link->platforms = platform_component;
link->num_platforms = ARRAY_SIZE(platform_component);
link->id = be_id;
link->init = (hdmi_id == 1) ? hdmi_init : NULL;
link->no_pcm = 1;
link->dpcm_playback = 1;
return 0;
}
EXPORT_SYMBOL_NS(sof_intel_board_set_intel_hdmi_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);

View file

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2023 Intel Corporation.
*/
#ifndef __SOF_INTEL_BOARD_HELPERS_H
#define __SOF_INTEL_BOARD_HELPERS_H
#include <sound/soc.h>
#include "sof_hdmi_common.h"
#include "sof_ssp_common.h"
/*
* sof_rt5682_private: private data for rt5682 machine driver
*
* @mclk: mclk clock data
* @is_legacy_cpu: true for BYT/CHT boards
*/
struct sof_rt5682_private {
struct clk *mclk;
bool is_legacy_cpu;
};
/*
* sof_card_private: common data for machine drivers
*
* @headset_jack: headset jack data
* @hdmi: init data for hdmi dai link
* @codec_type: type of headset codec
* @amp_type: type of speaker amplifier
* @hdmi_num: number of Intel HDMI BE link
* @rt5682: private data for rt5682 machine driver
*/
struct sof_card_private {
struct snd_soc_jack headset_jack;
struct sof_hdmi_private hdmi;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
int hdmi_num;
union {
struct sof_rt5682_private rt5682;
};
};
int sof_intel_board_card_late_probe(struct snd_soc_card *card);
int sof_intel_board_set_intel_hdmi_link(struct device *dev,
struct snd_soc_dai_link *link, int be_id,
int hdmi_id, bool idisp_codec);
#endif /* __SOF_INTEL_BOARD_HELPERS_H */

View file

@ -19,14 +19,11 @@
#include <sound/sof.h>
#include <sound/soc-acpi.h>
#include <dt-bindings/sound/cs42l42.h>
#include "../../codecs/hdac_hdmi.h"
#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
#include "sof_maxim_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_CS42L42_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_CS42L42_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_CS42L42_SSP_AMP_SHIFT 4
@ -70,40 +67,6 @@ static struct snd_soc_jack_pin jack_pins[] = {
/* Default: SSP2 */
static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2);
struct sof_hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
struct snd_soc_jack hdmi_jack;
int device;
};
struct sof_card_private {
struct snd_soc_jack headset_jack;
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct sof_hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
/* dai_link id is 1:1 mapped to the PCM device */
pcm->device = rtd->dai_link->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
return 0;
}
static int sof_cs42l42_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
@ -184,39 +147,7 @@ static struct snd_soc_dai_link_component platform_component[] = {
static int sof_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_component *component = NULL;
char jack_name[NAME_SIZE];
struct sof_hdmi_pcm *pcm;
int err;
if (list_empty(&ctx->hdmi_pcm_list))
return -EINVAL;
if (ctx->common_hdmi_codec_drv) {
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
head);
component = pcm->codec_dai->component;
return hda_dsp_hdmi_build_controls(card, component);
}
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
component = pcm->codec_dai->component;
snprintf(jack_name, sizeof(jack_name),
"HDMI/DP, pcm=%d Jack", pcm->device);
err = snd_soc_card_jack_new(card, jack_name,
SND_JACK_AVOUT, &pcm->hdmi_jack);
if (err)
return err;
err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
&pcm->hdmi_jack);
if (err < 0)
return err;
}
return hdac_hdmi_jack_port_init(component, &card->dapm);
return sof_intel_board_card_late_probe(card);
}
static const struct snd_kcontrol_new sof_controls[] = {
@ -432,65 +363,6 @@ static int create_dmic_dai_links(struct device *dev,
return 0;
}
static int create_hdmi_dai_links(struct device *dev,
struct snd_soc_dai_link *links,
struct snd_soc_dai_link_component *cpus,
int *id, int hdmi_num)
{
struct snd_soc_dai_link_component *idisp_components;
int i;
/* HDMI */
if (hdmi_num <= 0)
return 0;
idisp_components = devm_kcalloc(dev,
hdmi_num,
sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
if (!idisp_components)
goto devm_err;
for (i = 1; i <= hdmi_num; i++) {
links[*id].name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d", i);
if (!links[*id].name)
goto devm_err;
links[*id].id = *id;
links[*id].cpus = &cpus[*id];
links[*id].num_cpus = 1;
links[*id].cpus->dai_name = devm_kasprintf(dev,
GFP_KERNEL,
"iDisp%d Pin",
i);
if (!links[*id].cpus->dai_name)
goto devm_err;
idisp_components[i - 1].name = "ehdaudio0D2";
idisp_components[i - 1].dai_name = devm_kasprintf(dev,
GFP_KERNEL,
"intel-hdmi-hifi%d",
i);
if (!idisp_components[i - 1].dai_name)
goto devm_err;
links[*id].codecs = &idisp_components[i - 1];
links[*id].num_codecs = 1;
links[*id].platforms = platform_component;
links[*id].num_platforms = ARRAY_SIZE(platform_component);
links[*id].init = sof_hdmi_init;
links[*id].dpcm_playback = 1;
links[*id].no_pcm = 1;
(*id)++;
}
return 0;
devm_err:
return -ENOMEM;
}
static int create_bt_offload_dai_links(struct device *dev,
struct snd_soc_dai_link *links,
struct snd_soc_dai_link_component *cpus,
@ -534,11 +406,14 @@ static int create_bt_offload_dai_links(struct device *dev,
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int ssp_amp, int ssp_bt,
int dmic_be_num, int hdmi_num)
int dmic_be_num, int hdmi_num, bool idisp_codec)
{
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
int ret, id = 0, link_seq;
int ret;
int id = 0;
int link_seq;
int i;
links = devm_kcalloc(dev, sof_audio_card_cs42l42.num_links,
sizeof(struct snd_soc_dai_link), GFP_KERNEL);
@ -579,11 +454,18 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
}
break;
case LINK_HDMI:
ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num);
if (ret < 0) {
dev_err(dev, "fail to create hdmi dai links, ret %d\n",
ret);
goto devm_err;
for (i = 1; i <= hdmi_num; i++) {
ret = sof_intel_board_set_intel_hdmi_link(dev,
&links[id],
id, i,
idisp_codec);
if (ret) {
dev_err(dev, "fail to create hdmi link, ret %d\n",
ret);
goto devm_err;
}
id++;
}
break;
case LINK_BT:
@ -611,10 +493,10 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
static int sof_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct snd_soc_dai_link *dai_links;
struct snd_soc_acpi_mach *mach;
struct sof_card_private *ctx;
int dmic_be_num, hdmi_num;
int dmic_be_num;
int ret, ssp_bt, ssp_amp, ssp_codec;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
@ -624,23 +506,24 @@ static int sof_audio_probe(struct platform_device *pdev)
if (pdev->id_entry && pdev->id_entry->driver_data)
sof_cs42l42_quirk = (unsigned long)pdev->id_entry->driver_data;
mach = pdev->dev.platform_data;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (soc_intel_is_glk()) {
dmic_be_num = 1;
hdmi_num = 3;
ctx->hdmi_num = 3;
} else {
dmic_be_num = 2;
hdmi_num = (sof_cs42l42_quirk & SOF_CS42L42_NUM_HDMIDEV_MASK) >>
ctx->hdmi_num = (sof_cs42l42_quirk & SOF_CS42L42_NUM_HDMIDEV_MASK) >>
SOF_CS42L42_NUM_HDMIDEV_SHIFT;
/* default number of HDMI DAI's */
if (!hdmi_num)
hdmi_num = 3;
if (!ctx->hdmi_num)
ctx->hdmi_num = 3;
}
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
ctx->hdmi.idisp_codec = true;
dev_dbg(&pdev->dev, "sof_cs42l42_quirk = %lx\n", sof_cs42l42_quirk);
ssp_bt = (sof_cs42l42_quirk & SOF_CS42L42_SSP_BT_MASK) >>
@ -652,7 +535,7 @@ static int sof_audio_probe(struct platform_device *pdev)
ssp_codec = sof_cs42l42_quirk & SOF_CS42L42_SSP_CODEC_MASK;
/* compute number of dai links */
sof_audio_card_cs42l42.num_links = 1 + dmic_be_num + hdmi_num;
sof_audio_card_cs42l42.num_links = 1 + dmic_be_num + ctx->hdmi_num;
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_cs42l42.num_links++;
@ -661,14 +544,13 @@ static int sof_audio_probe(struct platform_device *pdev)
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, ssp_amp, ssp_bt,
dmic_be_num, hdmi_num);
dmic_be_num, ctx->hdmi_num,
ctx->hdmi.idisp_codec);
if (!dai_links)
return -ENOMEM;
sof_audio_card_cs42l42.dai_link = dai_links;
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_audio_card_cs42l42.dev = &pdev->dev;
/* set platform name for each dailink */
@ -677,8 +559,6 @@ static int sof_audio_probe(struct platform_device *pdev)
if (ret)
return ret;
ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
snd_soc_card_set_drvdata(&sof_audio_card_cs42l42, ctx);
return devm_snd_soc_register_card(&pdev->dev,
@ -725,6 +605,6 @@ module_platform_driver(sof_audio)
MODULE_DESCRIPTION("SOF Audio Machine driver for CS42L42");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);

View file

@ -16,6 +16,7 @@
#include <sound/sof.h>
#include "../../codecs/da7219.h"
#include "hda_dsp_common.h"
#include "sof_hdmi_common.h"
#include "sof_maxim_common.h"
#include "sof_ssp_common.h"
@ -24,16 +25,9 @@
#define DIALOG_CODEC_DAI "da7219-hifi"
struct hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
int device;
};
struct card_private {
struct snd_soc_jack headset_jack;
struct list_head hdmi_pcm_list;
struct snd_soc_jack hdmi[3];
struct sof_hdmi_private hdmi;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
@ -232,16 +226,8 @@ static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
pcm->device = dai->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
ctx->hdmi.hdmi_comp = dai->component;
return 0;
}
@ -249,17 +235,14 @@ static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
static int card_late_probe(struct snd_soc_card *card)
{
struct card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach *mach = (card->dev)->platform_data;
struct hdmi_pcm *pcm;
if (mach->mach_params.common_hdmi_codec_drv) {
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
head);
return hda_dsp_hdmi_build_controls(card,
pcm->codec_dai->component);
}
if (!ctx->hdmi.idisp_codec)
return 0;
return -EINVAL;
if (!ctx->hdmi.hdmi_comp)
return -EINVAL;
return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
}
SND_SOC_DAILINK_DEF(ssp0_pin,
@ -479,6 +462,9 @@ static int audio_probe(struct platform_device *pdev)
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
ctx->hdmi.idisp_codec = true;
if (board_quirk & SOF_DA7219_JSL_BOARD) {
/* backward-compatible with existing devices */
switch (ctx->amp_type) {
@ -534,8 +520,6 @@ static int audio_probe(struct platform_device *pdev)
card_da7219.dai_link = dai_links;
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
card_da7219.dev = &pdev->dev;
ret = snd_soc_fixup_dai_links_platform_name(&card_da7219,

View file

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2023 Intel Corporation.
*/
#ifndef __SOF_HDMI_COMMON_H
#define __SOF_HDMI_COMMON_H
#include <sound/soc.h>
#define IDISP_CODEC_MASK 0x4
/*
* sof_hdmi_private: data for Intel HDMI dai link (idisp) initialization
*
* @hdmi_comp: ASoC component of idisp codec
* @idisp_codec: true to indicate idisp codec is present
*/
struct sof_hdmi_private {
struct snd_soc_component *hdmi_comp;
bool idisp_codec;
};
#endif /* __SOF_HDMI_COMMON_H */

View file

@ -20,14 +20,12 @@
#include <sound/soc-acpi.h>
#include "../../codecs/nau8825.h"
#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
#include "sof_realtek_common.h"
#include "sof_maxim_common.h"
#include "sof_nuvoton_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_NAU8825_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_NAU8825_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_NAU8825_SSP_AMP_SHIFT 4
@ -48,39 +46,6 @@
static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
struct sof_hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
int device;
};
struct sof_card_private {
struct clk *mclk;
struct snd_soc_jack sof_headset;
struct list_head hdmi_pcm_list;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct sof_hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
/* dai_link id is 1:1 mapped to the PCM device */
pcm->device = rtd->dai_link->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
return 0;
}
static struct snd_soc_jack_pin jack_pins[] = {
{
.pin = "Headphone Jack",
@ -96,8 +61,7 @@ static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
struct snd_soc_jack *jack;
struct snd_soc_jack *jack = &ctx->headset_jack;
int ret;
/*
@ -108,7 +72,7 @@ static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3,
&ctx->sof_headset,
jack,
jack_pins,
ARRAY_SIZE(jack_pins));
if (ret) {
@ -116,14 +80,12 @@ static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
jack = &ctx->sof_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, jack, NULL);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) {
dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
return ret;
@ -187,7 +149,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dapm_context *dapm = &card->dapm;
struct sof_hdmi_pcm *pcm;
int err;
if (ctx->amp_type == CODEC_MAX98373) {
@ -199,12 +160,7 @@ static int sof_card_late_probe(struct snd_soc_card *card)
return err;
}
if (list_empty(&ctx->hdmi_pcm_list))
return -EINVAL;
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
return sof_intel_board_card_late_probe(card);
}
static const struct snd_kcontrol_new sof_controls[] = {
@ -292,12 +248,13 @@ static struct snd_soc_dai_link_component dmic_component[] = {
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int ssp_amp, int dmic_be_num,
int hdmi_num)
int hdmi_num, bool idisp_codec)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
int i, id = 0;
int i;
int id = 0;
int ret;
links = devm_kcalloc(dev, sof_audio_card_nau8825.num_links,
sizeof(struct snd_soc_dai_link), GFP_KERNEL);
@ -364,43 +321,12 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
}
/* HDMI */
if (hdmi_num > 0) {
idisp_components = devm_kcalloc(dev,
hdmi_num,
sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL);
if (!idisp_components)
goto devm_err;
}
for (i = 1; i <= hdmi_num; i++) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d", i);
if (!links[id].name)
goto devm_err;
ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], id,
i, idisp_codec);
if (ret)
return NULL;
links[id].id = id;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d Pin", i);
if (!links[id].cpus->dai_name)
goto devm_err;
idisp_components[i - 1].name = "ehdaudio0D2";
idisp_components[i - 1].dai_name = devm_kasprintf(dev,
GFP_KERNEL,
"intel-hdmi-hifi%d",
i);
if (!idisp_components[i - 1].dai_name)
goto devm_err;
links[id].codecs = &idisp_components[i - 1];
links[id].num_codecs = 1;
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_hdmi_init;
links[id].dpcm_playback = 1;
links[id].no_pcm = 1;
id++;
}
@ -485,10 +411,10 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
static int sof_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct snd_soc_dai_link *dai_links;
struct snd_soc_acpi_mach *mach;
struct sof_card_private *ctx;
int dmic_be_num, hdmi_num;
int dmic_be_num;
int ret, ssp_amp, ssp_codec;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
@ -498,8 +424,6 @@ static int sof_audio_probe(struct platform_device *pdev)
if (pdev->id_entry && pdev->id_entry->driver_data)
sof_nau8825_quirk = (unsigned long)pdev->id_entry->driver_data;
mach = pdev->dev.platform_data;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
@ -507,11 +431,14 @@ static int sof_audio_probe(struct platform_device *pdev)
/* default number of DMIC DAI's */
dmic_be_num = 2;
hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >>
ctx->hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >>
SOF_NAU8825_NUM_HDMIDEV_SHIFT;
/* default number of HDMI DAI's */
if (!hdmi_num)
hdmi_num = 3;
if (!ctx->hdmi_num)
ctx->hdmi_num = 3;
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
ctx->hdmi.idisp_codec = true;
ssp_amp = (sof_nau8825_quirk & SOF_NAU8825_SSP_AMP_MASK) >>
SOF_NAU8825_SSP_AMP_SHIFT;
@ -519,7 +446,7 @@ static int sof_audio_probe(struct platform_device *pdev)
ssp_codec = sof_nau8825_quirk & SOF_NAU8825_SSP_CODEC_MASK;
/* compute number of dai links */
sof_audio_card_nau8825.num_links = 1 + dmic_be_num + hdmi_num;
sof_audio_card_nau8825.num_links = 1 + dmic_be_num + ctx->hdmi_num;
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_nau8825.num_links++;
@ -529,7 +456,8 @@ static int sof_audio_probe(struct platform_device *pdev)
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, ssp_amp, dmic_be_num,
hdmi_num);
ctx->hdmi_num,
ctx->hdmi.idisp_codec);
if (!dai_links)
return -ENOMEM;
@ -554,8 +482,6 @@ static int sof_audio_probe(struct platform_device *pdev)
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_audio_card_nau8825.dev = &pdev->dev;
/* set platform name for each dailink */
@ -655,7 +581,7 @@ MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_NUVOTON_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);

View file

@ -23,15 +23,12 @@
#include "../../codecs/rt5682.h"
#include "../../codecs/rt5682s.h"
#include "../../codecs/rt5645.h"
#include "../../codecs/hdac_hdmi.h"
#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
#include "sof_maxim_common.h"
#include "sof_realtek_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
#define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
#define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0))
#define SOF_RT5682_MCLK_EN BIT(3)
@ -62,25 +59,6 @@
static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0);
static int is_legacy_cpu;
struct sof_hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
struct snd_soc_jack hdmi_jack;
int device;
};
struct sof_card_private {
struct clk *mclk;
struct snd_soc_jack sof_headset;
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
bool idisp_codec;
enum sof_ssp_codec codec_type;
enum sof_ssp_codec amp_type;
};
static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
{
sof_rt5682_quirk = (unsigned long)id->driver_data;
@ -232,25 +210,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
{}
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct sof_hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
/* dai_link id is 1:1 mapped to the PCM device */
pcm->device = rtd->dai_link->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
return 0;
}
static struct snd_soc_jack_pin jack_pins[] = {
{
.pin = "Headphone Jack",
@ -266,7 +225,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
struct snd_soc_jack *jack;
struct snd_soc_jack *jack = &ctx->headset_jack;
int extra_jack_data;
int ret, mclk_freq;
@ -322,11 +281,11 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
* to disable a clock that has not been enabled,
* we need to enable the clock first.
*/
ret = clk_prepare_enable(ctx->mclk);
ret = clk_prepare_enable(ctx->rt5682.mclk);
if (!ret)
clk_disable_unprepare(ctx->mclk);
clk_disable_unprepare(ctx->rt5682.mclk);
ret = clk_set_rate(ctx->mclk, 19200000);
ret = clk_set_rate(ctx->rt5682.mclk, 19200000);
if (ret)
dev_err(rtd->dev, "unable to set MCLK rate\n");
@ -341,7 +300,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3,
&ctx->sof_headset,
jack,
jack_pins,
ARRAY_SIZE(jack_pins));
if (ret) {
@ -349,8 +308,6 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
jack = &ctx->sof_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
@ -387,7 +344,7 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
ret = clk_prepare_enable(ctx->mclk);
ret = clk_prepare_enable(ctx->rt5682.mclk);
if (ret < 0) {
dev_err(rtd->dev,
"could not configure MCLK state");
@ -516,10 +473,7 @@ static struct snd_soc_dai_link_component platform_component[] = {
static int sof_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_component *component = NULL;
struct snd_soc_dapm_context *dapm = &card->dapm;
char jack_name[NAME_SIZE];
struct sof_hdmi_pcm *pcm;
int err;
if (ctx->amp_type == CODEC_MAX98373) {
@ -531,37 +485,7 @@ static int sof_card_late_probe(struct snd_soc_card *card)
return err;
}
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
if (is_legacy_cpu || !ctx->idisp_codec)
return 0;
if (list_empty(&ctx->hdmi_pcm_list))
return -EINVAL;
if (ctx->common_hdmi_codec_drv) {
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
head);
component = pcm->codec_dai->component;
return hda_dsp_hdmi_build_controls(card, component);
}
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
component = pcm->codec_dai->component;
snprintf(jack_name, sizeof(jack_name),
"HDMI/DP, pcm=%d Jack", pcm->device);
err = snd_soc_card_jack_new(card, jack_name,
SND_JACK_AVOUT, &pcm->hdmi_jack);
if (err)
return err;
err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
&pcm->hdmi_jack);
if (err < 0)
return err;
}
return hdac_hdmi_jack_port_init(component, &card->dapm);
return sof_intel_board_card_late_probe(card);
}
static const struct snd_kcontrol_new sof_controls[] = {
@ -684,18 +608,17 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
#define IDISP_CODEC_MASK 0x4
static struct snd_soc_dai_link *
sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type,
enum sof_ssp_codec amp_type, int ssp_codec,
int ssp_amp, int dmic_be_num, int hdmi_num,
bool idisp_codec)
bool idisp_codec, bool is_legacy_cpu)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
int i, id = 0;
int i;
int id = 0;
int ret;
int hdmi_id_offset = 0;
links = devm_kcalloc(dev, sof_audio_card_rt5682.num_links,
@ -796,47 +719,12 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type,
}
/* HDMI */
if (hdmi_num > 0) {
idisp_components = devm_kcalloc(dev,
hdmi_num,
sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL);
if (!idisp_components)
goto devm_err;
}
for (i = 1; i <= hdmi_num; i++) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d", i);
if (!links[id].name)
goto devm_err;
ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], id,
i, idisp_codec);
if (ret)
return NULL;
links[id].id = id;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d Pin", i);
if (!links[id].cpus->dai_name)
goto devm_err;
if (idisp_codec) {
idisp_components[i - 1].name = "ehdaudio0D2";
idisp_components[i - 1].dai_name = devm_kasprintf(dev,
GFP_KERNEL,
"intel-hdmi-hifi%d",
i);
if (!idisp_components[i - 1].dai_name)
goto devm_err;
} else {
idisp_components[i - 1] = snd_soc_dummy_dlc;
}
links[id].codecs = &idisp_components[i - 1];
links[id].num_codecs = 1;
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_hdmi_init;
links[id].dpcm_playback = 1;
links[id].no_pcm = 1;
id++;
}
@ -974,10 +862,10 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec codec_type,
static int sof_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct snd_soc_dai_link *dai_links;
struct snd_soc_acpi_mach *mach;
struct sof_card_private *ctx;
int dmic_be_num, hdmi_num;
int dmic_be_num;
int ret, ssp_amp, ssp_codec;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
@ -989,8 +877,6 @@ static int sof_audio_probe(struct platform_device *pdev)
dmi_check_system(sof_rt5682_quirk_table);
mach = pdev->dev.platform_data;
ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev);
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
@ -1004,30 +890,31 @@ static int sof_audio_probe(struct platform_device *pdev)
}
if (soc_intel_is_byt() || soc_intel_is_cht()) {
is_legacy_cpu = 1;
ctx->rt5682.is_legacy_cpu = true;
dmic_be_num = 0;
hdmi_num = 0;
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
ctx->hdmi_num = 0;
/* default quirk for legacy cpu */
sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_BYTCHT_EN |
SOF_RT5682_SSP_CODEC(2);
} else {
dmic_be_num = 2;
hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
ctx->hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
SOF_RT5682_NUM_HDMIDEV_SHIFT;
/* default number of HDMI DAI's */
if (!hdmi_num)
hdmi_num = 3;
if (!ctx->hdmi_num)
ctx->hdmi_num = 3;
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
ctx->idisp_codec = true;
ctx->hdmi.idisp_codec = true;
}
/* need to get main clock from pmc */
if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(ctx->mclk)) {
ret = PTR_ERR(ctx->mclk);
ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (IS_ERR(ctx->rt5682.mclk)) {
ret = PTR_ERR(ctx->rt5682.mclk);
dev_err(&pdev->dev,
"Failed to get MCLK from pmc_plt_clk_3: %d\n",
@ -1035,7 +922,7 @@ static int sof_audio_probe(struct platform_device *pdev)
return ret;
}
ret = clk_prepare_enable(ctx->mclk);
ret = clk_prepare_enable(ctx->rt5682.mclk);
if (ret < 0) {
dev_err(&pdev->dev,
"could not configure MCLK state");
@ -1051,7 +938,7 @@ static int sof_audio_probe(struct platform_device *pdev)
ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
/* compute number of dai links */
sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
sof_audio_card_rt5682.num_links = 1 + dmic_be_num + ctx->hdmi_num;
if (ctx->amp_type != CODEC_NONE)
sof_audio_card_rt5682.num_links++;
@ -1066,8 +953,9 @@ static int sof_audio_probe(struct platform_device *pdev)
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->codec_type,
ctx->amp_type, ssp_codec, ssp_amp,
dmic_be_num, hdmi_num,
ctx->idisp_codec);
dmic_be_num, ctx->hdmi_num,
ctx->hdmi.idisp_codec,
ctx->rt5682.is_legacy_cpu);
if (!dai_links)
return -ENOMEM;
@ -1102,8 +990,6 @@ static int sof_audio_probe(struct platform_device *pdev)
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_audio_card_rt5682.dev = &pdev->dev;
/* set platform name for each dailink */
@ -1112,8 +998,6 @@ static int sof_audio_probe(struct platform_device *pdev)
if (ret)
return ret;
ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
return devm_snd_soc_register_card(&pdev->dev,
@ -1331,7 +1215,7 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);

View file

@ -402,7 +402,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
RT711_JD2),
@ -1542,8 +1542,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
return 0;
}
#define IDISP_CODEC_MASK 0x4
static int sof_card_dai_links_create(struct snd_soc_card *card)
{
struct device *dev = card->dev;
@ -1587,7 +1585,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
}
if (mach_params->codec_mask & IDISP_CODEC_MASK) {
ctx->idisp_codec = true;
ctx->hdmi.idisp_codec = true;
if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
hdmi_num = SOF_TGL_HDMI_COUNT;
@ -1757,7 +1755,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
if (ctx->idisp_codec) {
if (ctx->hdmi.idisp_codec) {
codec_name = "ehdaudio0D2";
codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
"intel-hdmi-hifi%d", i + 1);
@ -1769,7 +1767,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name,
1, 0, // HDMI only supports playback
cpu_dai_name, codec_name, codec_dai_name,
sof_sdw_hdmi_init, NULL);
i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
if (ret)
return ret;
@ -1814,7 +1812,7 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card)
}
}
if (ctx->idisp_codec)
if (ctx->hdmi.idisp_codec)
ret = sof_sdw_hdmi_card_late_probe(card);
return ret;
@ -1893,8 +1891,6 @@ static int mc_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
snd_soc_card_set_drvdata(card, ctx);
dmi_check_system(sof_sdw_quirk_table);

View file

@ -12,6 +12,7 @@
#include <linux/bits.h>
#include <linux/types.h>
#include <sound/soc.h>
#include "sof_hdmi_common.h"
#define MAX_NO_PROPS 2
#define MAX_HDMI_NUM 4
@ -94,9 +95,8 @@ struct sof_sdw_codec_info {
};
struct mc_private {
struct list_head hdmi_pcm_list;
bool idisp_codec;
struct snd_soc_jack sdw_headset;
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 */

View file

@ -15,47 +15,25 @@
#include "sof_sdw_common.h"
#include "hda_dsp_common.h"
struct hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
int device;
};
int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
/* dai_link id is 1:1 mapped to the PCM device */
pcm->device = rtd->dai_link->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
ctx->hdmi.hdmi_comp = dai->component;
return 0;
}
#define NAME_SIZE 32
int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card)
{
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
struct hdmi_pcm *pcm;
struct snd_soc_component *component = NULL;
if (!ctx->idisp_codec)
if (!ctx->hdmi.idisp_codec)
return 0;
if (list_empty(&ctx->hdmi_pcm_list))
if (!ctx->hdmi.hdmi_comp)
return -EINVAL;
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
head);
component = pcm->codec_dai->component;
return hda_dsp_hdmi_build_controls(card, component);
return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
}

View file

@ -80,10 +80,12 @@ int sof_sdw_rt712_spk_init(struct snd_soc_card *card,
static int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s mic:rt712-sdca-dmic",
card->components);
"%s mic:%s",
card->components, component->name_prefix);
if (!card->components)
return -ENOMEM;

View file

@ -58,6 +58,11 @@ static const struct snd_soc_dapm_route rt712_sdca_map[] = {
{ "rt712 MIC2", NULL, "Headset Mic" },
};
static const struct snd_soc_dapm_route rt713_sdca_map[] = {
{ "Headphone", NULL, "rt713 HP" },
{ "rt713 MIC2", NULL, "Headset Mic" },
};
static const struct snd_kcontrol_new rt_sdca_jack_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
@ -109,6 +114,9 @@ static int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd)
} else if (strstr(component->name_prefix, "rt712")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt712_sdca_map,
ARRAY_SIZE(rt712_sdca_map));
} else if (strstr(component->name_prefix, "rt713")) {
ret = snd_soc_dapm_add_routes(&card->dapm, rt713_sdca_map,
ARRAY_SIZE(rt713_sdca_map));
} else {
dev_err(card->dev, "%s is not supported\n", component->name_prefix);
return -EINVAL;

View file

@ -17,14 +17,11 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/sof.h>
#include "../../codecs/hdac_hdmi.h"
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
#include "sof_realtek_common.h"
#include "sof_cirrus_common.h"
#include "sof_ssp_common.h"
#define NAME_SIZE 32
/* SSP port ID for speaker amplifier */
#define SOF_AMPLIFIER_SSP(quirk) ((quirk) & GENMASK(3, 0))
#define SOF_AMPLIFIER_SSP_MASK (GENMASK(3, 0))
@ -63,20 +60,6 @@
/* Default: SSP2 */
static unsigned long sof_ssp_amp_quirk = SOF_AMPLIFIER_SSP(2);
struct sof_hdmi_pcm {
struct list_head head;
struct snd_soc_jack sof_hdmi;
struct snd_soc_dai *codec_dai;
int device;
};
struct sof_card_private {
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
bool idisp_codec;
enum sof_ssp_codec amp_type;
};
static const struct dmi_system_id chromebook_platforms[] = {
{
.ident = "Google Chromebooks",
@ -98,46 +81,7 @@ static const struct snd_soc_dapm_route sof_ssp_amp_dapm_routes[] = {
static int sof_card_late_probe(struct snd_soc_card *card)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_component *component = NULL;
char jack_name[NAME_SIZE];
struct sof_hdmi_pcm *pcm;
int err;
if (!(sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT))
return 0;
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
if (!ctx->idisp_codec)
return 0;
if (list_empty(&ctx->hdmi_pcm_list))
return -EINVAL;
if (ctx->common_hdmi_codec_drv) {
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
head);
component = pcm->codec_dai->component;
return hda_dsp_hdmi_build_controls(card, component);
}
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
component = pcm->codec_dai->component;
snprintf(jack_name, sizeof(jack_name),
"HDMI/DP, pcm=%d Jack", pcm->device);
err = snd_soc_card_jack_new(card, jack_name,
SND_JACK_AVOUT, &pcm->sof_hdmi);
if (err)
return err;
err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
&pcm->sof_hdmi);
if (err < 0)
return err;
}
return hdac_hdmi_jack_port_init(component, &card->dapm);
return sof_intel_board_card_late_probe(card);
}
static struct snd_soc_card sof_ssp_amp_card = {
@ -165,27 +109,6 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
struct sof_hdmi_pcm *pcm;
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
/* dai_link id is 1:1 mapped to the PCM device */
pcm->device = rtd->dai_link->id;
pcm->codec_dai = dai;
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
return 0;
}
#define IDISP_CODEC_MASK 0x4
/* BE ID defined in sof-tgl-rt1308-hdmi-ssp.m4 */
#define HDMI_IN_BE_ID 0
#define SPK_BE_ID 2
@ -197,11 +120,13 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
int ssp_codec, int dmic_be_num, int hdmi_num,
bool idisp_codec)
{
struct snd_soc_dai_link_component *idisp_components;
struct snd_soc_dai_link_component *cpus;
struct snd_soc_dai_link *links;
int i, id = 0;
int i;
int id = 0;
int ret;
bool fixed_be = false;
int be_id;
links = devm_kcalloc(dev, sof_ssp_amp_card.num_links,
sizeof(struct snd_soc_dai_link), GFP_KERNEL);
@ -308,51 +233,14 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
}
/* HDMI playback */
if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) {
/* HDMI */
if (hdmi_num > 0) {
idisp_components = devm_kcalloc(dev,
hdmi_num,
sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL);
if (!idisp_components)
goto devm_err;
}
for (i = 1; i <= hdmi_num; i++) {
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d", i);
if (!links[id].name)
goto devm_err;
for (i = 1; i <= hdmi_num; i++) {
be_id = fixed_be ? (INTEL_HDMI_BE_ID + i - 1) : id;
ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], be_id,
i, idisp_codec);
if (ret)
return NULL;
links[id].id = fixed_be ? (INTEL_HDMI_BE_ID + i - 1) : id;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"iDisp%d Pin", i);
if (!links[id].cpus->dai_name)
goto devm_err;
if (idisp_codec) {
idisp_components[i - 1].name = "ehdaudio0D2";
idisp_components[i - 1].dai_name = devm_kasprintf(dev,
GFP_KERNEL,
"intel-hdmi-hifi%d",
i);
if (!idisp_components[i - 1].dai_name)
goto devm_err;
} else {
idisp_components[i - 1] = snd_soc_dummy_dlc;
}
links[id].codecs = &idisp_components[i - 1];
links[id].num_codecs = 1;
links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_hdmi_init;
links[id].dpcm_playback = 1;
links[id].no_pcm = 1;
id++;
}
id++;
}
/* BT audio offload */
@ -387,10 +275,10 @@ sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
static int sof_ssp_amp_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
struct snd_soc_dai_link *dai_links;
struct snd_soc_acpi_mach *mach;
struct sof_card_private *ctx;
int dmic_be_num = 0, hdmi_num = 0;
int dmic_be_num = 0;
int ret, ssp_codec;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
@ -400,8 +288,6 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
if (pdev->id_entry && pdev->id_entry->driver_data)
sof_ssp_amp_quirk = (unsigned long)pdev->id_entry->driver_data;
mach = pdev->dev.platform_data;
ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev);
if (dmi_check_system(chromebook_platforms) || mach->mach_params.dmic_num > 0)
@ -420,24 +306,27 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT;
if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) {
hdmi_num = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_PLAYBACK_MASK) >>
ctx->hdmi_num = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_PLAYBACK_MASK) >>
SOF_NO_OF_HDMI_PLAYBACK_SHIFT;
/* default number of HDMI DAI's */
if (!hdmi_num)
hdmi_num = 3;
if (!ctx->hdmi_num)
ctx->hdmi_num = 3;
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
ctx->idisp_codec = true;
ctx->hdmi.idisp_codec = true;
sof_ssp_amp_card.num_links += hdmi_num;
sof_ssp_amp_card.num_links += ctx->hdmi_num;
} else {
ctx->hdmi_num = 0;
}
if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
sof_ssp_amp_card.num_links++;
dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
ssp_codec, dmic_be_num, hdmi_num,
ctx->idisp_codec);
ssp_codec, dmic_be_num,
ctx->hdmi_num,
ctx->hdmi.idisp_codec);
if (!dai_links)
return -ENOMEM;
@ -457,8 +346,6 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
return -EINVAL;
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_ssp_amp_card.dev = &pdev->dev;
/* set platform name for each dailink */
@ -467,8 +354,6 @@ static int sof_ssp_amp_probe(struct platform_device *pdev)
if (ret)
return ret;
ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
snd_soc_card_set_drvdata(&sof_ssp_amp_card, ctx);
return devm_snd_soc_register_card(&pdev->dev, &sof_ssp_amp_card);
@ -512,6 +397,15 @@ static const struct platform_device_id board_ids[] = {
SOF_NO_OF_HDMI_PLAYBACK(3) |
SOF_HDMI_PLAYBACK_PRESENT),
},
{
.name = "mtl_lt6911_hdmi_ssp",
.driver_data = (kernel_ulong_t)(SOF_NO_OF_HDMI_CAPTURE_SSP(2) |
SOF_HDMI_CAPTURE_1_SSP(0) |
SOF_HDMI_CAPTURE_2_SSP(2) |
SOF_SSP_HDMI_CAPTURE_PRESENT |
SOF_NO_OF_HDMI_PLAYBACK(3) |
SOF_HDMI_PLAYBACK_PRESENT),
},
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
@ -530,7 +424,7 @@ MODULE_DESCRIPTION("ASoC Intel(R) SOF Amplifier Machine driver");
MODULE_AUTHOR("Balamurugan C <balamurugan.c@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON);
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);

View file

@ -77,6 +77,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
},
/* place amp-only boards in the end of table */
{
.id = "INTC10B0",
.drv_name = "mtl_lt6911_hdmi_ssp",
.sof_tplg_filename = "sof-mtl-hdmi-ssp02.tplg",
},
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines);
@ -158,6 +164,24 @@ static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt713_0_single_adr[] = {
{
.adr = 0x000031025D071301ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt713"
}
};
static const struct snd_soc_acpi_adr_device rt1713_3_single_adr[] = {
{
.adr = 0x000331025D171301ull,
.num_endpoints = 1,
.endpoints = &single_endpoint,
.name_prefix = "rt713-dmic"
}
};
static const struct snd_soc_acpi_adr_device mx8373_0_adr[] = {
{
.adr = 0x000023019F837300ull,
@ -200,6 +224,24 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = {
}
};
static const struct snd_soc_acpi_adr_device rt1316_1_group2_adr[] = {
{
.adr = 0x000131025D131601ull,
.num_endpoints = 1,
.endpoints = &spk_l_endpoint,
.name_prefix = "rt1316-1"
}
};
static const struct snd_soc_acpi_adr_device rt1316_2_group2_adr[] = {
{
.adr = 0x000230025D131601ull,
.num_endpoints = 1,
.endpoints = &spk_r_endpoint,
.name_prefix = "rt1316-2"
}
};
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
{
.adr = 0x000130025D131801ull,
@ -356,6 +398,30 @@ static const struct snd_soc_acpi_link_adr mtl_sdw_rt1318_l12_rt714_l0[] = {
{}
};
static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12_rt1713_l3[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt713_0_single_adr),
.adr_d = rt713_0_single_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1316_1_group2_adr),
.adr_d = rt1316_1_group2_adr,
},
{
.mask = BIT(2),
.num_adr = ARRAY_SIZE(rt1316_2_group2_adr),
.adr_d = rt1316_2_group2_adr,
},
{
.mask = BIT(3),
.num_adr = ARRAY_SIZE(rt1713_3_single_adr),
.adr_d = rt1713_3_single_adr,
},
{}
};
static const struct snd_soc_acpi_adr_device mx8363_2_adr[] = {
{
.adr = 0x000230019F836300ull,
@ -435,6 +501,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt715-rt711-rt1308-mono.tplg",
},
{
.link_mask = GENMASK(3, 0),
.links = mtl_rt713_l0_rt1316_l12_rt1713_l3,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-rt713-l0-rt1316-l12-rt1713-l3.tplg",
},
{
.link_mask = BIT(3) | BIT(0),
.links = mtl_712_only,

View file

@ -246,6 +246,25 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link2_rt1316_link01[] =
{}
};
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1316_link12[] = {
{
.mask = BIT(0),
.num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
.adr_d = rt711_sdca_0_adr,
},
{
.mask = BIT(1),
.num_adr = ARRAY_SIZE(rt1316_1_group1_adr),
.adr_d = rt1316_1_group1_adr,
},
{
.mask = BIT(2),
.num_adr = ARRAY_SIZE(rt1316_2_group1_adr),
.adr_d = rt1316_2_group1_adr,
},
{}
};
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12_rt714_link3[] = {
{
.mask = BIT(0),
@ -459,6 +478,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-rpl-rt711-l0-rt1318-l12-rt714-l3.tplg",
},
{
.link_mask = 0x7, /* rt711 on link0 & two rt1316s on link1 and link2 */
.links = rpl_sdw_rt711_link0_rt1316_link12,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-rpl-rt711-l0-rt1316-l12.tplg",
},
{
.link_mask = 0x7, /* rt711 on link0 & two rt1318s on link1 and link2 */
.links = rpl_sdw_rt711_link0_rt1318_link12,