Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/sound/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ struct hda_codec {
unsigned int force_pin_prefix:1; /* Add location prefix */
unsigned int link_down_at_suspend:1; /* link down at runtime suspend */
unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */

#ifdef CONFIG_PM
unsigned long power_on_acct;
Expand Down
2 changes: 2 additions & 0 deletions include/sound/soc-acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
* @acpi_ipc_irq_index: used for BYT-CR detection
* @platform: string used for HDaudio codec support
* @codec_mask: used for HDAudio support
* @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver
*/
struct snd_soc_acpi_mach_params {
u32 acpi_ipc_irq_index;
const char *platform;
u32 codec_mask;
u32 dmic_num;
bool common_hdmi_codec_drv;
};

/**
Expand Down
19 changes: 14 additions & 5 deletions sound/pci/hda/patch_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2072,15 +2072,24 @@ static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
static int generic_hdmi_build_pcms(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
int idx;
int idx, pcm_num;

/*
* for non-mst mode, pcm number is the same as before
* for DP MST mode, pcm number is (nid number + dev_num - 1)
* dev_num is the device entry number in a pin
*
* for DP MST mode without extra PCM, pcm number is same
* for DP MST mode with extra PCMs, pcm number is
* (nid number + dev_num - 1)
* dev_num is the device entry number in a pin
*/
for (idx = 0; idx < spec->num_nids + spec->dev_num - 1; idx++) {

if (codec->mst_no_extra_pcms)
pcm_num = spec->num_nids;
else
pcm_num = spec->num_nids + spec->dev_num - 1;

codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);

for (idx = 0; idx < pcm_num; idx++) {
struct hda_pcm *info;
struct hda_pcm_stream *pstr;

Expand Down
114 changes: 102 additions & 12 deletions sound/soc/codecs/hdac_hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_i915.h>
#include <sound/hda_codec.h>
#include <sound/hda_register.h>
#include "hdac_hda.h"

#define HDAC_ANALOG_DAI_ID 0
#define HDAC_DIGITAL_DAI_ID 1
#define HDAC_ALT_ANALOG_DAI_ID 2
#include "hdac_hda.h"

#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_U8 | \
Expand All @@ -32,6 +30,11 @@
SNDRV_PCM_FMTBIT_U32_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)

#define STUB_HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000)

static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai);
static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
Expand Down Expand Up @@ -121,7 +124,46 @@ static struct snd_soc_dai_driver hdac_hda_dais[] = {
.formats = STUB_FORMATS,
.sig_bits = 24,
},
}
},
{
.id = HDAC_HDMI_0_DAI_ID,
.name = "intel-hdmi-hifi1",
.ops = &hdac_hda_dai_ops,
.playback = {
.stream_name = "hifi1",
.channels_min = 1,
.channels_max = 32,
.rates = STUB_HDMI_RATES,
.formats = STUB_FORMATS,
.sig_bits = 24,
},
},
{
.id = HDAC_HDMI_1_DAI_ID,
.name = "intel-hdmi-hifi2",
.ops = &hdac_hda_dai_ops,
.playback = {
.stream_name = "hifi2",
.channels_min = 1,
.channels_max = 32,
.rates = STUB_HDMI_RATES,
.formats = STUB_FORMATS,
.sig_bits = 24,
},
},
{
.id = HDAC_HDMI_2_DAI_ID,
.name = "intel-hdmi-hifi3",
.ops = &hdac_hda_dai_ops,
.playback = {
.stream_name = "hifi3",
.channels_min = 1,
.channels_max = 32,
.rates = STUB_HDMI_RATES,
.formats = STUB_FORMATS,
.sig_bits = 24,
},
},

};

Expand All @@ -135,10 +177,11 @@ static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai,

hda_pvt = snd_soc_component_get_drvdata(component);
pcm = &hda_pvt->pcm[dai->id];

if (tx_mask)
pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
pcm->stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
else
pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
pcm->stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;

return 0;
}
Expand Down Expand Up @@ -278,6 +321,12 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
struct hda_pcm *cpcm;
const char *pcm_name;

/*
* map DAI ID to the closest matching PCM name, using the naming
* scheme used by hda-codec snd_hda_gen_build_pcms() and for
* HDMI in hda_codec patch_hdmi.c)
*/

switch (dai->id) {
case HDAC_ANALOG_DAI_ID:
pcm_name = "Analog";
Expand All @@ -288,20 +337,41 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
case HDAC_ALT_ANALOG_DAI_ID:
pcm_name = "Alt Analog";
break;
case HDAC_HDMI_0_DAI_ID:
pcm_name = "HDMI 0";
break;
case HDAC_HDMI_1_DAI_ID:
pcm_name = "HDMI 1";
break;
case HDAC_HDMI_2_DAI_ID:
pcm_name = "HDMI 2";
break;
default:
dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id);
return NULL;
}

list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
if (strpbrk(cpcm->name, pcm_name))
if (strstr(cpcm->name, pcm_name))
return cpcm;
}

dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name);
return NULL;
}

static bool is_hdmi_codec(struct hda_codec *hcodec)
{
struct hda_pcm *cpcm;

list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
return true;
}

return false;
}

static int hdac_hda_codec_probe(struct snd_soc_component *component)
{
struct hdac_hda_priv *hda_pvt =
Expand All @@ -322,6 +392,15 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)

snd_hdac_ext_bus_link_get(hdev->bus, hlink);

/*
* Ensure any HDA display is powered at codec probe.
* After snd_hda_codec_device_new(), display power is
* managed by runtime PM.
*/
if (hda_pvt->need_display_power)
snd_hdac_display_power(hdev->bus,
HDA_CODEC_IDX_CONTROLLER, true);

ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card,
hdev->addr, hcodec);
if (ret < 0) {
Expand Down Expand Up @@ -366,20 +445,31 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
dev_dbg(&hdev->dev, "no patch file found\n");
}

/* configure codec for 1:1 PCM:DAI mapping */
hcodec->mst_no_extra_pcms = 1;

ret = snd_hda_codec_parse_pcms(hcodec);
if (ret < 0) {
dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
goto error;
}

ret = snd_hda_codec_build_controls(hcodec);
if (ret < 0) {
dev_err(&hdev->dev, "unable to create controls %d\n", ret);
goto error;
/* HDMI controls need to be created in machine drivers */
if (!is_hdmi_codec(hcodec)) {
ret = snd_hda_codec_build_controls(hcodec);
if (ret < 0) {
dev_err(&hdev->dev, "unable to create controls %d\n",
ret);
goto error;
}
}

hcodec->core.lazy_cache = true;

if (hda_pvt->need_display_power)
snd_hdac_display_power(hdev->bus,
HDA_CODEC_IDX_CONTROLLER, false);

/*
* hdac_device core already sets the state to active and calls
* get_noresume. So enable runtime and set the device to suspend.
Expand Down
13 changes: 12 additions & 1 deletion sound/soc/codecs/hdac_hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,25 @@
#ifndef __HDAC_HDA_H__
#define __HDAC_HDA_H__

enum {
HDAC_ANALOG_DAI_ID = 0,
HDAC_DIGITAL_DAI_ID,
HDAC_ALT_ANALOG_DAI_ID,
HDAC_HDMI_0_DAI_ID,
HDAC_HDMI_1_DAI_ID,
HDAC_HDMI_2_DAI_ID,
HDAC_LAST_DAI_ID = HDAC_HDMI_2_DAI_ID,
};

struct hdac_hda_pcm {
int stream_tag[2];
unsigned int format_val[2];
};

struct hdac_hda_priv {
struct hda_codec codec;
struct hdac_hda_pcm pcm[2];
struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID];
bool need_display_power;
};

#define hdac_to_hda_priv(_hdac) \
Expand Down
12 changes: 6 additions & 6 deletions sound/soc/intel/boards/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o
snd-soc-sst-broadwell-objs := broadwell.o
snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o
snd-soc-sst-bxt-rt298-objs := bxt_rt298.o
snd-soc-sst-bxt-pcm512x-objs := bxt_pcm512x.o
snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o hda_dsp_common.o
snd-soc-sst-bxt-rt298-objs := bxt_rt298.o hda_dsp_common.o
snd-soc-sst-bxt-pcm512x-objs := bxt_pcm512x.o hda_dsp_common.o
snd-soc-sst-bxt-wm8804-objs := bxt_wm8804.o
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
Expand All @@ -19,15 +19,15 @@ snd-soc-sst-byt-cht-cx2072x-objs := bytcht_cx2072x.o
snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o
snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o
snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
snd-soc-sof_rt5682-objs := sof_rt5682.o
snd-soc-sof_rt5682-objs := sof_rt5682.o hda_dsp_common.o
snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o
snd-soc-kbl_rt5660-objs := kbl_rt5660.o
snd-soc-skl_rt286-objs := skl_rt286.o
snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o
snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o hda_dsp_common.o
snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
snd-soc-tgl-rt1308-objs := tgl_rt1308.o
Expand Down
11 changes: 11 additions & 0 deletions sound/soc/intel/boards/bxt_da7219_max98357a.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "../../codecs/da7219.h"
#include "../../codecs/da7219-aad.h"
#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"

#define BXT_DIALOG_CODEC_DAI "da7219-hifi"
#define BXT_MAXIM_CODEC_DAI "HiFi"
Expand All @@ -38,6 +39,7 @@ struct bxt_hdmi_pcm {

struct bxt_card_private {
struct list_head hdmi_pcm_list;
bool common_hdmi_codec_drv;
};

enum {
Expand Down Expand Up @@ -615,6 +617,13 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
snd_soc_dapm_add_routes(&card->dapm, broxton_map,
ARRAY_SIZE(broxton_map));

pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
head);
component = pcm->codec_dai->component;

if (ctx->common_hdmi_codec_drv)
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),
Expand Down Expand Up @@ -720,6 +729,8 @@ static int broxton_audio_probe(struct platform_device *pdev)
if (ret)
return ret;

ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;

return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card);
}

Expand Down
Loading