]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'v4.10-rc1' into asoc-intel
authorMark Brown <broonie@kernel.org>
Tue, 24 Jan 2017 16:24:18 +0000 (16:24 +0000)
committerMark Brown <broonie@kernel.org>
Tue, 24 Jan 2017 16:24:18 +0000 (16:24 +0000)
Linux 4.10-rc1

21 files changed:
include/sound/soc.h
sound/hda/ext/hdac_ext_stream.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/intel/Kconfig
sound/soc/intel/Makefile
sound/soc/intel/atom/Makefile
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/atom/sst/sst_ipc.c
sound/soc/intel/atom/sst/sst_stream.c
sound/soc/intel/boards/broadwell.c
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/common/sst-dsp.c
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-tplg-interface.h
sound/soc/soc-core.c

index 2b502f6cc6d036be6e25c6834671be1cde2fd8da..8cad99dfb78cdff0266589888a20f3a7c2297a66 100644 (file)
@@ -497,6 +497,8 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
 int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
        unsigned int dai_fmt);
 
+int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour);
+
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
 int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -1098,6 +1100,8 @@ struct snd_soc_card {
        const char *name;
        const char *long_name;
        const char *driver_name;
+       char dmi_longname[80];
+
        struct device *dev;
        struct snd_card *snd_card;
        struct module *owner;
index 3be051ab55335746d57d46aa1445fb42f5eafce2..c96d7a7a36af033b0c8241e20538e7722828bc0e 100644 (file)
@@ -128,14 +128,17 @@ void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus,
 {
        struct hdac_stream *hstream = &stream->hstream;
        struct hdac_bus *bus = &ebus->bus;
+       u32 val;
+       int mask = AZX_PPCTL_PROCEN(hstream->index);
 
        spin_lock_irq(&bus->reg_lock);
-       if (decouple)
-               snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0,
-                               AZX_PPCTL_PROCEN(hstream->index));
-       else
-               snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL,
-                                       AZX_PPCTL_PROCEN(hstream->index), 0);
+       val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask;
+
+       if (decouple && !val)
+               snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, mask);
+       else if (!decouple && val)
+               snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0);
+
        stream->decoupled = decouple;
        spin_unlock_irq(&bus->reg_lock);
 }
index 0c6228a0bf950fcce779491baca38381e7d24e69..4b4e376cc3f628dbc3b310c60034a05362680c20 100644 (file)
 #define ELD_MAX_SIZE    256
 #define ELD_FIXED_BYTES        20
 
+#define ELD_VER_CEA_861D 2
+#define ELD_VER_PARTIAL 31
+#define ELD_MAX_MNL     16
+
 struct hdac_hdmi_cvt_params {
        unsigned int channels_min;
        unsigned int channels_max;
@@ -81,8 +85,6 @@ struct hdac_hdmi_pin {
        hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
        struct hdac_hdmi_eld eld;
        struct hdac_ext_device *edev;
-       int repoll_count;
-       struct delayed_work work;
        struct mutex lock;
        bool chmap_set;
        unsigned char chmap[8]; /* ALSA API channel-map */
@@ -114,6 +116,12 @@ struct hdac_hdmi_priv {
        struct hdac_chmap chmap;
 };
 
+static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
+                       struct hdac_hdmi_dai_pin_map *dai_map);
+
+static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
+                       struct hdac_hdmi_dai_pin_map *dai_map);
+
 static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
                                                int pcm_idx)
 {
@@ -173,80 +181,6 @@ format_constraint:
 
 }
 
- /* HDMI ELD routines */
-static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
-                               hda_nid_t nid, int byte_index)
-{
-       unsigned int val;
-
-       val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD,
-                                                       byte_index);
-
-       dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n",
-                                       byte_index, val);
-
-       return val;
-}
-
-static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
-{
-       return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
-                                                AC_DIPSIZE_ELD_BUF);
-}
-
-/*
- * This function queries the ELD size and ELD data and fills in the buffer
- * passed by user
- */
-static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid,
-                            unsigned char *buf, int *eld_size)
-{
-       int i, size, ret = 0;
-
-       /*
-        * ELD size is initialized to zero in caller function. If no errors and
-        * ELD is valid, actual eld_size is assigned.
-        */
-
-       size = hdac_hdmi_get_eld_size(codec, nid);
-       if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
-               dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
-               return -ERANGE;
-       }
-
-       /* set ELD buffer */
-       for (i = 0; i < size; i++) {
-               unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i);
-               /*
-                * Graphics driver might be writing to ELD buffer right now.
-                * Just abort. The caller will repoll after a while.
-                */
-               if (!(val & AC_ELDD_ELD_VALID)) {
-                       dev_err(&codec->dev,
-                               "HDMI: invalid ELD data byte %d\n", i);
-                       ret = -EINVAL;
-                       goto error;
-               }
-               val &= AC_ELDD_ELD_DATA;
-               /*
-                * The first byte cannot be zero. This can happen on some DVI
-                * connections. Some Intel chips may also need some 250ms delay
-                * to return non-zero ELD data, even when the graphics driver
-                * correctly writes ELD content before setting ELD_valid bit.
-                */
-               if (!val && !i) {
-                       dev_err(&codec->dev, "HDMI: 0 ELD data\n");
-                       ret = -EINVAL;
-                       goto error;
-               }
-               buf[i] = val;
-       }
-
-       *eld_size = size;
-error:
-       return ret;
-}
-
 static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
                                hda_nid_t cvt_nid, hda_nid_t pin_nid,
                                u32 stream_tag, int format)
@@ -411,6 +345,10 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
        dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n",
                        dd->stream_tag, dd->format);
 
+       hdac_hdmi_enable_cvt(hdac, dai_map);
+       ret = hdac_hdmi_enable_pin(hdac, dai_map);
+       if (ret < 0)
+               return ret;
        mutex_lock(&pin->lock);
        pin->channels = substream->runtime->channels;
 
@@ -464,12 +402,7 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
 static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai);
        struct hdac_ext_dma_params *dd;
-       struct hdac_hdmi_priv *hdmi = edev->private_data;
-       struct hdac_hdmi_dai_pin_map *dai_map;
-
-       dai_map = &hdmi->dai_map[dai->id];
 
        dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
 
@@ -622,11 +555,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 
        dai_map->pin = pin;
 
-       hdac_hdmi_enable_cvt(hdac, dai_map);
-       ret = hdac_hdmi_enable_pin(hdac, dai_map);
-       if (ret < 0)
-               return ret;
-
        ret = hdac_hdmi_eld_limit_formats(substream->runtime,
                                pin->eld.eld_buffer);
        if (ret < 0)
@@ -639,18 +567,15 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
 static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
                struct snd_soc_dai *dai)
 {
-       struct hdac_hdmi_dai_pin_map *dai_map;
-       struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
-       struct hdac_hdmi_priv *hdmi = hdac->private_data;
-       int ret;
-
-       dai_map = &hdmi->dai_map[dai->id];
-       if (cmd == SNDRV_PCM_TRIGGER_RESUME) {
-               ret = hdac_hdmi_enable_pin(hdac, dai_map);
-               if (ret < 0)
-                       return ret;
 
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                return hdac_hdmi_playback_prepare(substream, dai);
+
+       default:
+               return 0;
        }
 
        return 0;
@@ -1059,32 +984,59 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
        return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
 }
 
-static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
+static int  hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
                        struct hdac_hdmi_pin *pin)
 {
+       unsigned int ver, mnl;
+
+       ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK)
+                                               >> DRM_ELD_VER_SHIFT;
+
+       if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) {
+               dev_err(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver);
+               return -EINVAL;
+       }
+
+       mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] &
+               DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
+
+       if (mnl > ELD_MAX_MNL) {
+               dev_err(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl);
+               return -EINVAL;
+       }
+
        pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER];
+
+       return 0;
 }
 
-static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
+static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin)
 {
        struct hdac_ext_device *edev = pin->edev;
        struct hdac_hdmi_priv *hdmi = edev->private_data;
        struct hdac_hdmi_pcm *pcm;
-       int val;
-
-       pin->repoll_count = repoll;
+       int size;
 
-       pm_runtime_get_sync(&edev->hdac.dev);
-       val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0,
-                                       AC_VERB_GET_PIN_SENSE, 0);
+       mutex_lock(&hdmi->pin_mutex);
+       pin->eld.monitor_present = false;
 
-       dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n",
-                                               val, pin->nid);
+       size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1,
+                               &pin->eld.monitor_present, pin->eld.eld_buffer,
+                               ELD_MAX_SIZE);
 
+       if (size > 0) {
+               size = min(size, ELD_MAX_SIZE);
+               if (hdac_hdmi_parse_eld(edev, pin) < 0)
+                       size = -EINVAL;
+       }
 
-       mutex_lock(&hdmi->pin_mutex);
-       pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE);
-       pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV);
+       if (size > 0) {
+               pin->eld.eld_valid = true;
+               pin->eld.eld_size = size;
+       } else {
+               pin->eld.eld_valid = false;
+               pin->eld.eld_size = 0;
+       }
 
        pcm = hdac_hdmi_get_pcm(edev, pin);
 
@@ -1106,66 +1058,23 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
                }
 
                mutex_unlock(&hdmi->pin_mutex);
-               goto put_hdac_device;
+               return;
        }
 
        if (pin->eld.monitor_present && pin->eld.eld_valid) {
-               /* TODO: use i915 component for reading ELD later */
-               if (hdac_hdmi_get_eld(&edev->hdac, pin->nid,
-                               pin->eld.eld_buffer,
-                               &pin->eld.eld_size) == 0) {
-
-                       if (pcm) {
-                               dev_dbg(&edev->hdac.dev,
-                                       "jack report for pcm=%d\n",
-                                       pcm->pcm_id);
-
-                               snd_jack_report(pcm->jack, SND_JACK_AVOUT);
-                       }
-                       hdac_hdmi_parse_eld(edev, pin);
-
-                       print_hex_dump_debug("ELD: ",
-                                       DUMP_PREFIX_OFFSET, 16, 1,
-                                       pin->eld.eld_buffer, pin->eld.eld_size,
-                                       true);
-               } else {
-                       pin->eld.monitor_present = false;
-                       pin->eld.eld_valid = false;
-
-                       if (pcm) {
-                               dev_dbg(&edev->hdac.dev,
-                                       "jack report for pcm=%d\n",
-                                       pcm->pcm_id);
+               if (pcm) {
+                       dev_dbg(&edev->hdac.dev,
+                               "jack report for pcm=%d\n",
+                               pcm->pcm_id);
 
-                               snd_jack_report(pcm->jack, 0);
-                       }
+                       snd_jack_report(pcm->jack, SND_JACK_AVOUT);
                }
+
+               print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
+                         pin->eld.eld_buffer, pin->eld.eld_size, false);
        }
 
        mutex_unlock(&hdmi->pin_mutex);
-
-       /*
-        * Sometimes the pin_sense may present invalid monitor
-        * present and eld_valid. If ELD data is not valid, loop few
-        * more times to get correct pin sense and valid ELD.
-        */
-       if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll)
-               schedule_delayed_work(&pin->work, msecs_to_jiffies(300));
-
-put_hdac_device:
-       pm_runtime_put_sync(&edev->hdac.dev);
-}
-
-static void hdac_hdmi_repoll_eld(struct work_struct *work)
-{
-       struct hdac_hdmi_pin *pin =
-               container_of(to_delayed_work(work), struct hdac_hdmi_pin, work);
-
-       /* picked from legacy HDA driver */
-       if (pin->repoll_count++ > 6)
-               pin->repoll_count = 0;
-
-       hdac_hdmi_present_sense(pin, pin->repoll_count);
 }
 
 static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
@@ -1184,7 +1093,6 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 
        pin->edev = edev;
        mutex_init(&pin->lock);
-       INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld);
 
        return 0;
 }
@@ -1395,7 +1303,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
 
        list_for_each_entry(pin, &hdmi->pin_list, head) {
                if (pin->nid == pin_nid)
-                       hdac_hdmi_present_sense(pin, 1);
+                       hdac_hdmi_present_sense(pin);
        }
 }
 
@@ -1496,7 +1404,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
        }
 
        list_for_each_entry(pin, &hdmi->pin_list, head)
-               hdac_hdmi_present_sense(pin, 1);
+               hdac_hdmi_present_sense(pin);
 
        /* Imp: Store the card pointer in hda_codec */
        edev->card = dapm->card->snd_card;
@@ -1561,7 +1469,7 @@ static void hdmi_codec_complete(struct device *dev)
         * all pins here.
         */
        list_for_each_entry(pin, &hdmi->pin_list, head)
-               hdac_hdmi_present_sense(pin, 1);
+               hdac_hdmi_present_sense(pin);
 
        pm_runtime_put_sync(&edev->hdac.dev);
 }
index fd5d1e0910382e94233702094658b6b868c71b83..526855ad479e3c52358522764f5735fe205bada3 100644 (file)
@@ -2,7 +2,7 @@ config SND_MFLD_MACHINE
        tristate "SOC Machine Audio driver for Intel Medfield MID platform"
        depends on INTEL_SCU_IPC
        select SND_SOC_SN95031
-       select SND_SST_MFLD_PLATFORM
+       select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SST_IPC_PCI
        help
           This adds support for ASoC machine driver for Intel(R) MID Medfield platform
@@ -10,7 +10,7 @@ config SND_MFLD_MACHINE
           Say Y if you have such a device.
           If unsure select "N".
 
-config SND_SST_MFLD_PLATFORM
+config SND_SST_ATOM_HIFI2_PLATFORM
        tristate
        select SND_SOC_COMPRESS
 
@@ -31,13 +31,10 @@ config SND_SOC_INTEL_SST
        tristate
        select SND_SOC_INTEL_SST_ACPI if ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
-       depends on (X86 || COMPILE_TEST)
 
-# firmware stuff depends DW_DMAC_CORE; since there is no depends-on from
-# the reverse selection, each machine driver needs to select
-# SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE
 config SND_SOC_INTEL_SST_FIRMWARE
        tristate
+       select DW_DMAC_CORE
 
 config SND_SOC_INTEL_SST_ACPI
        tristate
@@ -47,16 +44,18 @@ config SND_SOC_INTEL_SST_MATCH
 
 config SND_SOC_INTEL_HASWELL
        tristate
+       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SST_FIRMWARE
 
 config SND_SOC_INTEL_BAYTRAIL
        tristate
+       select SND_SOC_INTEL_SST
+       select SND_SOC_INTEL_SST_FIRMWARE
 
 config SND_SOC_INTEL_HASWELL_MACH
        tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
        depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
-       depends on DW_DMAC_CORE
-       select SND_SOC_INTEL_SST
+       depends on DMADEVICES
        select SND_SOC_INTEL_HASWELL
        select SND_SOC_RT5640
        help
@@ -68,7 +67,6 @@ config SND_SOC_INTEL_HASWELL_MACH
 config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
        tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode"
        depends on X86 && ACPI && I2C
-       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_DA7219
        select SND_SOC_MAX98357A
@@ -84,7 +82,6 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
 config SND_SOC_INTEL_BXT_RT298_MACH
        tristate "ASoC Audio driver for Broxton with RT298 I2S mode"
        depends on X86 && ACPI && I2C
-       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_RT298
        select SND_SOC_DMIC
@@ -99,9 +96,8 @@ config SND_SOC_INTEL_BXT_RT298_MACH
 config SND_SOC_INTEL_BYT_RT5640_MACH
        tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
        depends on X86_INTEL_LPSS && I2C
-       depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
-       select SND_SOC_INTEL_SST
-       select SND_SOC_INTEL_SST_FIRMWARE
+       depends on DMADEVICES
+       depends on SND_SST_IPC_ACPI = n
        select SND_SOC_INTEL_BAYTRAIL
        select SND_SOC_RT5640
        help
@@ -112,9 +108,8 @@ config SND_SOC_INTEL_BYT_RT5640_MACH
 config SND_SOC_INTEL_BYT_MAX98090_MACH
        tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
        depends on X86_INTEL_LPSS && I2C
-       depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
-       select SND_SOC_INTEL_SST
-       select SND_SOC_INTEL_SST_FIRMWARE
+       depends on DMADEVICES
+       depends on SND_SST_IPC_ACPI = n
        select SND_SOC_INTEL_BAYTRAIL
        select SND_SOC_MAX98090
        help
@@ -123,9 +118,8 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
 
 config SND_SOC_INTEL_BDW_RT5677_MACH
        tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec"
-       depends on X86_INTEL_LPSS && GPIOLIB && I2C && DW_DMAC
-       depends on DW_DMAC_CORE=y
-       select SND_SOC_INTEL_SST
+       depends on X86_INTEL_LPSS && GPIOLIB && I2C
+       depends on DMADEVICES
        select SND_SOC_INTEL_HASWELL
        select SND_SOC_RT5677
        help
@@ -134,10 +128,8 @@ config SND_SOC_INTEL_BDW_RT5677_MACH
 
 config SND_SOC_INTEL_BROADWELL_MACH
        tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
-       depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
-                  I2C_DESIGNWARE_PLATFORM
-       depends on DW_DMAC_CORE
-       select SND_SOC_INTEL_SST
+       depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
+       depends on DMADEVICES
        select SND_SOC_INTEL_HASWELL
        select SND_SOC_RT286
        help
@@ -150,7 +142,7 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH
         tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
        depends on X86 && I2C && ACPI
        select SND_SOC_RT5640
-       select SND_SST_MFLD_PLATFORM
+       select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SST_IPC_ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
        help
@@ -163,7 +155,7 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
         tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec"
        depends on X86 && I2C && ACPI
        select SND_SOC_RT5651
-       select SND_SST_MFLD_PLATFORM
+       select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SST_IPC_ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
        help
@@ -176,7 +168,7 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
         tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec"
         depends on X86_INTEL_LPSS && I2C && ACPI
         select SND_SOC_RT5670
-        select SND_SST_MFLD_PLATFORM
+        select SND_SST_ATOM_HIFI2_PLATFORM
         select SND_SST_IPC_ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
         help
@@ -189,7 +181,7 @@ config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
        tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec"
        depends on X86_INTEL_LPSS && I2C && ACPI
        select SND_SOC_RT5645
-       select SND_SST_MFLD_PLATFORM
+       select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SST_IPC_ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
        help
@@ -202,7 +194,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
        depends on X86_INTEL_LPSS && I2C && ACPI
        select SND_SOC_MAX98090
        select SND_SOC_TS3A227E
-       select SND_SST_MFLD_PLATFORM
+       select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SST_IPC_ACPI
        select SND_SOC_INTEL_SST_MATCH if ACPI
        help
@@ -220,7 +212,6 @@ config SND_SOC_INTEL_SKYLAKE
 config SND_SOC_INTEL_SKL_RT286_MACH
        tristate "ASoC Audio driver for SKL with RT286 I2S mode"
        depends on X86 && ACPI && I2C
-       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_RT286
        select SND_SOC_DMIC
@@ -234,7 +225,6 @@ config SND_SOC_INTEL_SKL_RT286_MACH
 config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
        tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode"
        depends on X86_INTEL_LPSS && I2C
-       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_NAU8825
        select SND_SOC_SSM4567
@@ -249,7 +239,6 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
 config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
        tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode"
        depends on X86_INTEL_LPSS && I2C
-       select SND_SOC_INTEL_SST
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_NAU8825
        select SND_SOC_MAX98357A
index 2b45435e6245c6c517e98f6558d5b591576e52e6..cdd495f7ee2c46e6ec4831a97ce88f2d69ec7f8a 100644 (file)
@@ -4,7 +4,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SST) += common/
 # Platform Support
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/
 obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/
-obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/
 obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/
 
 # Machine support
index ce8074fa6d667c7abe1214d36c47a80ffa75c291..aa6548c6feab0a530e805e08b965637fbe9e5407 100644 (file)
@@ -1,7 +1,8 @@
-snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \
-               sst-mfld-platform-compress.o sst-atom-controls.o
+snd-soc-sst-atom-hifi2-platform-objs :=        sst-mfld-platform-pcm.o \
+                                       sst-mfld-platform-compress.o \
+                                       sst-atom-controls.o
 
-obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o
+obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += snd-soc-sst-atom-hifi2-platform.o
 
 # DSP driver
 obj-$(CONFIG_SND_SST_IPC) += sst/
index f5a8050351b53a0fdfc60af61a176cf3e60b08a2..21cac1c8dd4cb295cf9013386ea6f4549e14d1bf 100644 (file)
@@ -357,14 +357,14 @@ static void sst_media_close(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
        struct sst_runtime_stream *stream;
-       int ret_val = 0, str_id;
+       int str_id;
 
        stream = substream->runtime->private_data;
        power_down_sst(stream);
 
        str_id = stream->stream_info.str_id;
        if (str_id)
-               ret_val = stream->ops->close(sst->dev, str_id);
+               stream->ops->close(sst->dev, str_id);
        module_put(sst->dev->driver->owner);
        kfree(stream);
 }
@@ -839,4 +839,5 @@ MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
 MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sst-atom-hifi2-platform");
 MODULE_ALIAS("platform:sst-mfld-platform");
index 374bb61c596d8f928c3b76ea33be0be1a3cf37d9..14c2d9d1818010fd8fcb1192a79873808b7107b2 100644 (file)
@@ -260,10 +260,8 @@ static void process_fw_async_msg(struct intel_sst_drv *sst_drv_ctx,
        u32 data_size, i;
        void *data_offset;
        struct stream_info *stream;
-       union ipc_header_high msg_high;
        u32 msg_low, pipe_id;
 
-       msg_high = msg->mrfld_header.p.header_high;
        msg_low = msg->mrfld_header.p.header_low_payload;
        msg_id = ((struct ipc_dsp_hdr *)msg->mailbox_data)->cmd_id;
        data_offset = (msg->mailbox_data + sizeof(struct ipc_dsp_hdr));
index 51bdeeecb7c842fdf8035716d3402a607a0ebf37..83d8dda152331054650f6fca0d5d09d160d73108 100644 (file)
@@ -394,7 +394,6 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
 {
        int retval = 0;
        struct stream_info *str_info;
-       struct intel_sst_ops *ops;
 
        dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
 
@@ -407,7 +406,6 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
        str_info = get_stream_info(sst_drv_ctx, str_id);
        if (!str_info)
                return -EINVAL;
-       ops = sst_drv_ctx->ops;
 
        mutex_lock(&str_info->lock);
        if (str_info->status != STREAM_UN_INIT) {
index 4d7e9decfa92e476af9f6dbc66454ec603ad1c85..faf865bb176540c8b17d57df4a495aacc0000a98 100644 (file)
@@ -270,6 +270,8 @@ static int broadwell_audio_probe(struct platform_device *pdev)
 {
        broadwell_rt286.dev = &pdev->dev;
 
+       snd_soc_set_dmi_name(&broadwell_rt286, NULL);
+
        return devm_snd_soc_register_card(&pdev->dev, &broadwell_rt286);
 }
 
index 1b4330cd273921a1f5f0ad393d6ac8b8b579425a..02439ace3519276381ba2151d47b59349d129876 100644 (file)
@@ -357,7 +357,6 @@ static struct snd_soc_dai_link broxton_dais[] = {
                .platform_name = "0000:00:0e.0",
                .init = NULL,
                .dpcm_capture = 1,
-               .ignore_suspend = 1,
                .nonatomic = 1,
                .dynamic = 1,
                .ops = &broxton_refcap_ops,
index 507a86a5eafe5646bb9731f865b85571eb6ffdfc..613e5286555ad4dea0fe52dcdc933adc33e452ad 100644 (file)
@@ -386,6 +386,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                                 BYT_RT5640_MCLK_EN |
                                                 BYT_RT5640_SSP0_AIF1),
 
+       },
+       {
+               .callback = byt_rt5640_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+               },
+               .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP |
+                                                BYT_RT5640_MCLK_EN |
+                                                BYT_RT5640_SSP0_AIF1),
+
        },
        {}
 };
index c00ede4ea4d7040c255556802ea8ebddd12bd1ad..11c0805393ff96c50b03b2b29fb70a32b53fa3dc 100644 (file)
@@ -252,44 +252,44 @@ void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset,
 EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced);
 
 int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
-                        u32 target, u32 timeout, char *operation)
+                        u32 target, u32 time, char *operation)
 {
-       int time, ret;
        u32 reg;
-       bool done = false;
+       unsigned long timeout;
+       int k = 0, s = 500;
 
        /*
-        * we will poll for couple of ms using mdelay, if not successful
-        * then go to longer sleep using usleep_range
+        * split the loop into sleeps of varying resolution. more accurately,
+        * the range of wakeups are:
+        * Phase 1(first 5ms): min sleep 0.5ms; max sleep 1ms.
+        * Phase 2:( 5ms to 10ms) : min sleep 0.5ms; max sleep 10ms
+        * (usleep_range (500, 1000) and usleep_range(5000, 10000) are
+        * both possible in this phase depending on whether k > 10 or not).
+        * Phase 3: (beyond 10 ms) min sleep 5ms; max sleep 10ms.
         */
 
-       /* check if set state successful */
-       for (time = 0; time < 5; time++) {
-               if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) {
-                       done = true;
-                       break;
-               }
-               mdelay(1);
+       timeout = jiffies + msecs_to_jiffies(time);
+       while (((sst_dsp_shim_read_unlocked(ctx, offset) & mask) != target)
+               && time_before(jiffies, timeout)) {
+               k++;
+               if (k > 10)
+                       s = 5000;
+
+               usleep_range(s, 2*s);
        }
 
-       if (done ==  false) {
-               /* sleeping in 10ms steps so adjust timeout value */
-               timeout /= 10;
+       reg = sst_dsp_shim_read_unlocked(ctx, offset);
 
-               for (time = 0; time < timeout; time++) {
-                       if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target)
-                               break;
+       if ((reg & mask) == target) {
+               dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n",
+                                       reg, operation);
 
-                       usleep_range(5000, 10000);
-               }
+               return 0;
        }
 
-       reg = sst_dsp_shim_read_unlocked(ctx, offset);
-       dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation,
-                       (time < timeout) ? "successful" : "timedout");
-       ret = time < timeout ? 0 : -ETIME;
-
-       return ret;
+       dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s timedout\n",
+                                       reg, operation);
+       return -ETIME;
 }
 EXPORT_SYMBOL_GPL(sst_dsp_register_poll);
 
index 1f9f33d34000b13f752c875680038383c48561a4..15a063a403ccc28762abedb3e0124a6b1e70b78f 100644 (file)
@@ -23,7 +23,6 @@
 #include "../common/sst-dsp.h"
 #include "../common/sst-dsp-priv.h"
 #include "skl-sst-ipc.h"
-#include "skl-tplg-interface.h"
 
 #define BXT_BASEFW_TIMEOUT     3000
 #define BXT_INIT_TIMEOUT       500
@@ -52,7 +51,7 @@ static unsigned int bxt_get_errorcode(struct sst_dsp *ctx)
 }
 
 static int
-bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo)
+bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count)
 {
        struct snd_dma_buffer dmab;
        struct skl_sst *skl = ctx->thread_context;
@@ -61,11 +60,11 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo)
        int ret = 0, i, dma_id, stream_tag;
 
        /* library indices start from 1 to N. 0 represents base FW */
-       for (i = 1; i < minfo->lib_count; i++) {
-               ret = request_firmware(&fw, minfo->lib[i].name, ctx->dev);
+       for (i = 1; i < lib_count; i++) {
+               ret = request_firmware(&fw, linfo[i].name, ctx->dev);
                if (ret < 0) {
                        dev_err(ctx->dev, "Request lib %s failed:%d\n",
-                                       minfo->lib[i].name, ret);
+                                       linfo[i].name, ret);
                        return ret;
                }
 
@@ -96,7 +95,7 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo)
                ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i);
                if (ret < 0)
                        dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n",
-                                       minfo->lib[i].name, ret);
+                                       linfo[i].name, ret);
 
                ctx->dsp_ops.trigger(ctx->dev, false, stream_tag);
                ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag);
@@ -119,8 +118,7 @@ load_library_failed:
 static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
                        const void *fwdata, u32 fwsize)
 {
-       int stream_tag, ret, i;
-       u32 reg;
+       int stream_tag, ret;
 
        stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab);
        if (stream_tag <= 0) {
@@ -153,23 +151,13 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
        }
 
        /* Step 4: Wait for DONE Bit */
-       for (i = BXT_INIT_TIMEOUT; i > 0; --i) {
-               reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE);
-
-               if (reg & SKL_ADSP_REG_HIPCIE_DONE) {
-                       sst_dsp_shim_update_bits_forced(ctx,
-                                       SKL_ADSP_REG_HIPCIE,
+       ret = sst_dsp_register_poll(ctx, SKL_ADSP_REG_HIPCIE,
                                        SKL_ADSP_REG_HIPCIE_DONE,
-                                       SKL_ADSP_REG_HIPCIE_DONE);
-                       break;
-               }
-               mdelay(1);
-       }
-       if (!i) {
-               dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg);
-               sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE,
-                               SKL_ADSP_REG_HIPCIE_DONE,
-                               SKL_ADSP_REG_HIPCIE_DONE);
+                                       SKL_ADSP_REG_HIPCIE_DONE,
+                                       BXT_INIT_TIMEOUT, "HIPCIE Done");
+       if (ret < 0) {
+               dev_err(ctx->dev, "Timout for Purge Request%d\n", ret);
+               goto base_fw_load_failed;
        }
 
        /* Step 5: power down core1 */
@@ -184,19 +172,10 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
        skl_ipc_op_int_enable(ctx);
 
        /* Step 7: Wait for ROM init */
-       for (i = BXT_INIT_TIMEOUT; i > 0; --i) {
-               if (SKL_FW_INIT ==
-                               (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) &
-                               SKL_FW_STS_MASK)) {
-
-                       dev_info(ctx->dev, "ROM loaded, continue FW loading\n");
-                       break;
-               }
-               mdelay(1);
-       }
-       if (!i) {
-               dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg);
-               ret = -EIO;
+       ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK,
+                       SKL_FW_INIT, BXT_INIT_TIMEOUT, "ROM Load");
+       if (ret < 0) {
+               dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret);
                goto base_fw_load_failed;
        }
 
@@ -432,7 +411,6 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
        int ret;
        struct skl_ipc_dxstate_info dx;
        unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
-       struct skl_dfw_manifest *minfo = &skl->manifest;
 
        if (skl->fw_loaded == false) {
                skl->boot_complete = false;
@@ -442,8 +420,9 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
                        return ret;
                }
 
-               if (minfo->lib_count > 1) {
-                       ret = bxt_load_library(ctx, minfo);
+               if (skl->lib_count > 1) {
+                       ret = bxt_load_library(ctx, skl->lib_info,
+                                               skl->lib_count);
                        if (ret < 0) {
                                dev_err(ctx->dev, "reload libs failed: %d\n", ret);
                                return ret;
@@ -640,8 +619,9 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx)
 
        skl_dsp_init_core_state(sst);
 
-       if (ctx->manifest.lib_count > 1) {
-               ret = sst->fw_ops.load_library(sst, &ctx->manifest);
+       if (ctx->lib_count > 1) {
+               ret = sst->fw_ops.load_library(sst, ctx->lib_info,
+                                               ctx->lib_count);
                if (ret < 0) {
                        dev_err(dev, "Load Library failed : %x\n", ret);
                        return ret;
index 84b5101e6ca691df0e0896b59a95e07a55e3b5e7..ae7997ab19b199ef0af0725ff4724bebc46f0786 100644 (file)
@@ -137,6 +137,80 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream,
                skl->supend_active--;
 }
 
+int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       unsigned int format_val;
+       struct hdac_stream *hstream;
+       struct hdac_ext_stream *stream;
+       int err;
+
+       hstream = snd_hdac_get_stream(bus, params->stream,
+                                       params->host_dma_id + 1);
+       if (!hstream)
+               return -EINVAL;
+
+       stream = stream_to_hdac_ext_stream(hstream);
+       snd_hdac_ext_stream_decouple(ebus, stream, true);
+
+       format_val = snd_hdac_calc_stream_format(params->s_freq,
+                               params->ch, params->format, 32, 0);
+
+       dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
+               format_val, params->s_freq, params->ch, params->format);
+
+       snd_hdac_stream_reset(hdac_stream(stream));
+       err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
+       if (err < 0)
+               return err;
+
+       err = snd_hdac_stream_setup(hdac_stream(stream));
+       if (err < 0)
+               return err;
+
+       hdac_stream(stream)->prepared = 1;
+
+       return 0;
+}
+
+int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       unsigned int format_val;
+       struct hdac_stream *hstream;
+       struct hdac_ext_stream *stream;
+       struct hdac_ext_link *link;
+
+       hstream = snd_hdac_get_stream(bus, params->stream,
+                                       params->link_dma_id + 1);
+       if (!hstream)
+               return -EINVAL;
+
+       stream = stream_to_hdac_ext_stream(hstream);
+       snd_hdac_ext_stream_decouple(ebus, stream, true);
+       format_val = snd_hdac_calc_stream_format(params->s_freq,
+                               params->ch, params->format, 24, 0);
+
+       dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
+               format_val, params->s_freq, params->ch, params->format);
+
+       snd_hdac_ext_link_stream_reset(stream);
+
+       snd_hdac_ext_link_stream_setup(stream, format_val);
+
+       list_for_each_entry(link, &ebus->hlink_list, list) {
+               if (link->index == params->link_index)
+                       snd_hdac_ext_link_set_stream_id(link,
+                                       hstream->stream_tag);
+       }
+
+       stream->link_prepared = 1;
+
+       return 0;
+}
+
 static int skl_pcm_open(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -185,32 +259,6 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int skl_get_format(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct skl_dma_params *dma_params;
-       struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
-       int format_val = 0;
-
-       if ((ebus_to_hbus(ebus))->ppcap) {
-               struct snd_pcm_runtime *runtime = substream->runtime;
-
-               format_val = snd_hdac_calc_stream_format(runtime->rate,
-                                               runtime->channels,
-                                               runtime->format,
-                                               32, 0);
-       } else {
-               struct snd_soc_dai *codec_dai = rtd->codec_dai;
-
-               dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
-               if (dma_params)
-                       format_val = dma_params->format;
-       }
-
-       return format_val;
-}
-
 static int skl_be_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -231,37 +279,19 @@ static int skl_be_prepare(struct snd_pcm_substream *substream,
 static int skl_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
        struct skl *skl = get_skl_ctx(dai->dev);
-       unsigned int format_val;
-       int err;
        struct skl_module_cfg *mconfig;
 
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
 
        mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
 
-       format_val = skl_get_format(substream, dai);
-       dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
-                               hdac_stream(stream)->stream_tag, format_val);
-       snd_hdac_stream_reset(hdac_stream(stream));
-
        /* In case of XRUN recovery, reset the FW pipe to clean state */
        if (mconfig && (substream->runtime->status->state ==
                                        SNDRV_PCM_STATE_XRUN))
                skl_reset_pipe(skl->skl_sst, mconfig->pipe);
 
-       err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
-       if (err < 0)
-               return err;
-
-       err = snd_hdac_stream_setup(hdac_stream(stream));
-       if (err < 0)
-               return err;
-
-       hdac_stream(stream)->prepared = 1;
-
-       return err;
+       return 0;
 }
 
 static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -292,6 +322,7 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
        p_params.s_freq = params_rate(params);
        p_params.host_dma_id = dma_id;
        p_params.stream = substream->stream;
+       p_params.format = params_format(params);
 
        m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
        if (m_cfg)
@@ -435,7 +466,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
                if (!w->ignore_suspend) {
-                       skl_pcm_prepare(substream, dai);
                        /*
                         * enable DMA Resume enable bit for the stream, set the
                         * dpib & lpib position to resume before starting the
@@ -444,7 +474,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                        snd_hdac_ext_stream_drsm_enable(ebus, true,
                                                hdac_stream(stream)->index);
                        snd_hdac_ext_stream_set_dpibr(ebus, stream,
-                                                       stream->dpib);
+                                                       stream->lpib);
                        snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
                }
 
@@ -456,7 +486,6 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                 * pipeline is started but there is a delay in starting the
                 * DMA channel on the host.
                 */
-               snd_hdac_ext_stream_decouple(ebus, stream, true);
                ret = skl_decoupled_trigger(substream, cmd);
                if (ret < 0)
                        return ret;
@@ -506,6 +535,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        struct hdac_ext_dma_params *dma_params;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct skl_pipe_params p_params = {0};
+       struct hdac_ext_link *link;
 
        link_dev = snd_hdac_ext_stream_assign(ebus, substream,
                                        HDAC_EXT_STREAM_TYPE_LINK);
@@ -514,6 +544,10 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
 
        snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
 
+       link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
+       if (!link)
+               return -EINVAL;
+
        /* set the stream tag in the codec dai dma params  */
        dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
        if (dma_params)
@@ -524,6 +558,8 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        p_params.s_freq = params_rate(params);
        p_params.stream = substream->stream;
        p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1;
+       p_params.link_index = link->index;
+       p_params.format = params_format(params);
 
        return skl_tplg_be_update_params(dai, &p_params);
 }
@@ -531,41 +567,15 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
 static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
-       struct hdac_ext_stream *link_dev =
-                       snd_soc_dai_get_dma_data(dai, substream);
-       unsigned int format_val = 0;
-       struct skl_dma_params *dma_params;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct hdac_ext_link *link;
        struct skl *skl = get_skl_ctx(dai->dev);
        struct skl_module_cfg *mconfig = NULL;
 
-       dma_params  = (struct skl_dma_params *)
-                       snd_soc_dai_get_dma_data(codec_dai, substream);
-       if (dma_params)
-               format_val = dma_params->format;
-       dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
-                       hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
-
-       link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
-       if (!link)
-               return -EINVAL;
-
-       snd_hdac_ext_link_stream_reset(link_dev);
-
        /* In case of XRUN recovery, reset the FW pipe to clean state */
        mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
-       if (mconfig && (substream->runtime->status->state ==
-                                       SNDRV_PCM_STATE_XRUN))
+       if (mconfig && !mconfig->pipe->passthru &&
+               (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN))
                skl_reset_pipe(skl->skl_sst, mconfig->pipe);
 
-       snd_hdac_ext_link_stream_setup(link_dev, format_val);
-
-       snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
-       link_dev->link_prepared = 1;
-
        return 0;
 }
 
@@ -580,10 +590,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
        dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
-               skl_link_pcm_prepare(substream, dai);
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               snd_hdac_ext_stream_decouple(ebus, stream, true);
                snd_hdac_ext_link_stream_start(link_dev);
                break;
 
index 7c272ba0f4b517da8faeb590f5265ed6ec602dfd..849410d0823e96ec4cd658263cb0aaeb254a5397 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/interrupt.h>
 #include <sound/memalloc.h>
 #include "skl-sst-cldma.h"
-#include "skl-tplg-interface.h"
 #include "skl-topology.h"
 
 struct sst_dsp;
@@ -145,7 +144,7 @@ struct skl_dsp_fw_ops {
        int (*load_fw)(struct sst_dsp  *ctx);
        /* FW module parser/loader */
        int (*load_library)(struct sst_dsp *ctx,
-               struct skl_dfw_manifest *minfo);
+               struct skl_lib_info *linfo, int count);
        int (*parse_fw)(struct sst_dsp *ctx);
        int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
        int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);
@@ -236,5 +235,4 @@ int skl_get_pvt_instance_id_map(struct skl_sst *ctx,
 void skl_freeup_uuid_list(struct skl_sst *ctx);
 
 int skl_dsp_strip_extended_manifest(struct firmware *fw);
-
 #endif /*__SKL_SST_DSP_H__*/
index cc40341233fa63c952534a3c9287b378b5f88d99..9660ace379ababf63d9ab29ab5941b7e3000c03d 100644 (file)
@@ -97,8 +97,9 @@ struct skl_sst {
        /* multi-core */
        struct skl_dsp_cores cores;
 
-       /* tplg manifest */
-       struct skl_dfw_manifest manifest;
+       /* library info */
+       struct skl_lib_info  lib_info[SKL_MAX_LIB];
+       int lib_count;
 
        /* Callback to update D0i3C register */
        void (*update_d0i3c)(struct device *dev, bool enable);
index bd313c907b20df470a8c7727f8169c036fae25b9..e6e76237f46b114288e406569ce869b41669eab0 100644 (file)
@@ -496,6 +496,20 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
        return 0;
 }
 
+static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe,
+               struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg)
+{
+       switch (mcfg->dev_type) {
+       case SKL_DEVICE_HDAHOST:
+               return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params);
+
+       case SKL_DEVICE_HDALINK:
+               return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params);
+       }
+
+       return 0;
+}
+
 /*
  * Inside a pipe instance, we can have various modules. These modules need
  * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by
@@ -535,6 +549,11 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
                        mconfig->m_state = SKL_MODULE_LOADED;
                }
 
+               /* prepare the DMA if the module is gateway cpr */
+               ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig);
+               if (ret < 0)
+                       return ret;
+
                /* update blob if blob is null for be with default value */
                skl_tplg_update_be_blob(w, ctx);
 
@@ -974,7 +993,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
        struct skl_module_cfg *src_module = NULL, *dst_module;
        struct skl_sst *ctx = skl->skl_sst;
        struct skl_pipe *s_pipe = mconfig->pipe;
-       int ret = 0;
 
        if (s_pipe->state == SKL_PIPE_INVALID)
                return -EINVAL;
@@ -996,7 +1014,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
                src_module = dst_module;
        }
 
-       ret = skl_delete_pipe(ctx, mconfig->pipe);
+       skl_delete_pipe(ctx, mconfig->pipe);
 
        return skl_tplg_unload_pipe_modules(ctx, s_pipe);
 }
@@ -1207,6 +1225,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg,
                switch (mcfg->dev_type) {
                case SKL_DEVICE_HDALINK:
                        pipe->p_params->link_dma_id = params->link_dma_id;
+                       pipe->p_params->link_index = params->link_index;
                        break;
 
                case SKL_DEVICE_HDAHOST:
@@ -1220,6 +1239,7 @@ static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg,
                pipe->p_params->ch = params->ch;
                pipe->p_params->s_freq = params->s_freq;
                pipe->p_params->stream = params->stream;
+               pipe->p_params->format = params->format;
 
        } else {
                memcpy(pipe->p_params, params, sizeof(*params));
@@ -2280,20 +2300,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
 
 static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
                struct snd_soc_tplg_vendor_string_elem *str_elem,
-               struct skl_dfw_manifest *minfo)
+               struct skl *skl)
 {
        int tkn_count = 0;
        static int ref_count;
 
        switch (str_elem->token) {
        case SKL_TKN_STR_LIB_NAME:
-               if (ref_count > minfo->lib_count - 1) {
+               if (ref_count > skl->skl_sst->lib_count - 1) {
                        ref_count = 0;
                        return -EINVAL;
                }
 
-               strncpy(minfo->lib[ref_count].name, str_elem->string,
-                               ARRAY_SIZE(minfo->lib[ref_count].name));
+               strncpy(skl->skl_sst->lib_info[ref_count].name,
+                       str_elem->string,
+                       ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name));
                ref_count++;
                tkn_count++;
                break;
@@ -2308,14 +2329,14 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
 
 static int skl_tplg_get_str_tkn(struct device *dev,
                struct snd_soc_tplg_vendor_array *array,
-               struct skl_dfw_manifest *minfo)
+               struct skl *skl)
 {
        int tkn_count = 0, ret;
        struct snd_soc_tplg_vendor_string_elem *str_elem;
 
        str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value;
        while (tkn_count < array->num_elems) {
-               ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo);
+               ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl);
                str_elem++;
 
                if (ret < 0)
@@ -2329,13 +2350,13 @@ static int skl_tplg_get_str_tkn(struct device *dev,
 
 static int skl_tplg_get_int_tkn(struct device *dev,
                struct snd_soc_tplg_vendor_value_elem *tkn_elem,
-               struct skl_dfw_manifest *minfo)
+               struct skl *skl)
 {
        int tkn_count = 0;
 
        switch (tkn_elem->token) {
        case SKL_TKN_U32_LIB_COUNT:
-               minfo->lib_count = tkn_elem->value;
+               skl->skl_sst->lib_count = tkn_elem->value;
                tkn_count++;
                break;
 
@@ -2352,7 +2373,7 @@ static int skl_tplg_get_int_tkn(struct device *dev,
  * type.
  */
 static int skl_tplg_get_manifest_tkn(struct device *dev,
-               char *pvt_data, struct skl_dfw_manifest *minfo,
+               char *pvt_data, struct skl *skl,
                int block_size)
 {
        int tkn_count = 0, ret;
@@ -2368,7 +2389,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
                off += array->size;
                switch (array->type) {
                case SND_SOC_TPLG_TUPLE_TYPE_STRING:
-                       ret = skl_tplg_get_str_tkn(dev, array, minfo);
+                       ret = skl_tplg_get_str_tkn(dev, array, skl);
 
                        if (ret < 0)
                                return ret;
@@ -2390,7 +2411,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
 
                while (tkn_count <= array->num_elems - 1) {
                        ret = skl_tplg_get_int_tkn(dev,
-                                       tkn_elem, minfo);
+                                       tkn_elem, skl);
                        if (ret < 0)
                                return ret;
 
@@ -2411,7 +2432,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
  * preceded by descriptors for type and size of data block.
  */
 static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
-                       struct device *dev, struct skl_dfw_manifest *minfo)
+                       struct device *dev, struct skl *skl)
 {
        struct snd_soc_tplg_vendor_array *array;
        int num_blocks, block_size = 0, block_type, off = 0;
@@ -2454,7 +2475,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
                data = (manifest->priv.data + off);
 
                if (block_type == SKL_TYPE_TUPLE) {
-                       ret = skl_tplg_get_manifest_tkn(dev, data, minfo,
+                       ret = skl_tplg_get_manifest_tkn(dev, data, skl,
                                        block_size);
 
                        if (ret < 0)
@@ -2472,27 +2493,23 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
 static int skl_manifest_load(struct snd_soc_component *cmpnt,
                                struct snd_soc_tplg_manifest *manifest)
 {
-       struct skl_dfw_manifest *minfo;
        struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
        struct skl *skl = ebus_to_skl(ebus);
-       int ret = 0;
 
        /* proceed only if we have private data defined */
        if (manifest->priv.size == 0)
                return 0;
 
-       minfo = &skl->skl_sst->manifest;
-
-       skl_tplg_get_manifest_data(manifest, bus->dev, minfo);
+       skl_tplg_get_manifest_data(manifest, bus->dev, skl);
 
-       if (minfo->lib_count > HDA_MAX_LIB) {
+       if (skl->skl_sst->lib_count > SKL_MAX_LIB) {
                dev_err(bus->dev, "Exceeding max Library count. Got:%d\n",
-                                       minfo->lib_count);
-               ret = -EINVAL;
+                                       skl->skl_sst->lib_count);
+               return  -EINVAL;
        }
 
-       return ret;
+       return 0;
 }
 
 static struct snd_soc_tplg_ops skl_tplg_ops  = {
index 08d39280b07bcd09bd3a62c7de4f99ba7290add3..fefab0e99a3bea56b1afc9c0135cb67ca91a83eb 100644 (file)
@@ -254,6 +254,8 @@ struct skl_pipe_params {
        u32 s_freq;
        u32 s_fmt;
        u8 linktype;
+       snd_pcm_format_t format;
+       int link_index;
        int stream;
 };
 
@@ -332,6 +334,19 @@ struct skl_pipeline {
        struct list_head node;
 };
 
+#define SKL_LIB_NAME_LENGTH 128
+#define SKL_MAX_LIB 16
+
+struct skl_lib_info {
+       char name[SKL_LIB_NAME_LENGTH];
+       const struct firmware *fw;
+};
+
+struct skl_manifest {
+       u32 lib_count;
+       struct skl_lib_info lib[SKL_MAX_LIB];
+};
+
 static inline struct skl *get_skl_ctx(struct device *dev)
 {
        struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
@@ -383,4 +398,8 @@ int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size,
 struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai,
                                                                int stream);
 enum skl_bitdepth skl_get_bit_depth(int params);
+int skl_pcm_host_dma_prepare(struct device *dev,
+                       struct skl_pipe_params *params);
+int skl_pcm_link_dma_prepare(struct device *dev,
+                       struct skl_pipe_params *params);
 #endif
index 2f6281e056d6a660fab453c47ee31a5167e74cbb..7a2febf99019be78f3f9c47c9c69edebafbefc20 100644 (file)
@@ -157,18 +157,6 @@ struct skl_dfw_algo_data {
        char params[0];
 } __packed;
 
-#define LIB_NAME_LENGTH        128
-#define HDA_MAX_LIB    16
-
-struct lib_info {
-       char name[LIB_NAME_LENGTH];
-} __packed;
-
-struct skl_dfw_manifest {
-       u32 lib_count;
-       struct lib_info lib[HDA_MAX_LIB];
-} __packed;
-
 enum skl_tkn_dir {
        SKL_DIR_IN,
        SKL_DIR_OUT
index f1901bb1466ec67b12189713c66ad040f1ae75c7..530a4dba0709a16578096036ad429ff98fc44e2d 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
@@ -1888,6 +1889,139 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
 
+
+/* Trim special characters, and replace '-' with '_' since '-' is used to
+ * separate different DMI fields in the card long name. Only number and
+ * alphabet characters and a few separator characters are kept.
+ */
+static void cleanup_dmi_name(char *name)
+{
+       int i, j = 0;
+
+       for (i = 0; name[i]; i++) {
+               if (isalnum(name[i]) || (name[i] == '.')
+                   || (name[i] == '_'))
+                       name[j++] = name[i];
+               else if (name[i] == '-')
+                       name[j++] = '_';
+       }
+
+       name[j] = '\0';
+}
+
+/**
+ * snd_soc_set_dmi_name() - Register DMI names to card
+ * @card: The card to register DMI names
+ * @flavour: The flavour "differentiator" for the card amongst its peers.
+ *
+ * An Intel machine driver may be used by many different devices but are
+ * difficult for userspace to differentiate, since machine drivers ususally
+ * use their own name as the card short name and leave the card long name
+ * blank. To differentiate such devices and fix bugs due to lack of
+ * device-specific configurations, this function allows DMI info to be used
+ * as the sound card long name, in the format of
+ * "vendor-product-version-board"
+ * (Character '-' is used to separate different DMI fields here).
+ * This will help the user space to load the device-specific Use Case Manager
+ * (UCM) configurations for the card.
+ *
+ * Possible card long names may be:
+ * DellInc.-XPS139343-01-0310JH
+ * ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
+ * Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
+ *
+ * This function also supports flavoring the card longname to provide
+ * the extra differentiation, like "vendor-product-version-board-flavor".
+ *
+ * We only keep number and alphabet characters and a few separator characters
+ * in the card long name since UCM in the user space uses the card long names
+ * as card configuration directory names and AudoConf cannot support special
+ * charactors like SPACE.
+ *
+ * Returns 0 on success, otherwise a negative error code.
+ */
+int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
+{
+       const char *vendor, *product, *product_version, *board;
+       size_t longname_buf_size = sizeof(card->snd_card->longname);
+       size_t len;
+
+       if (card->long_name)
+               return 0; /* long name already set by driver or from DMI */
+
+       /* make up dmi long name as: vendor.product.version.board */
+       vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+       if (!vendor) {
+               dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
+               return 0;
+       }
+
+       snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
+                        "%s", vendor);
+       cleanup_dmi_name(card->dmi_longname);
+
+       product = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (product) {
+               len = strlen(card->dmi_longname);
+               snprintf(card->dmi_longname + len,
+                        longname_buf_size - len,
+                        "-%s", product);
+
+               len++;  /* skip the separator "-" */
+               if (len < longname_buf_size)
+                       cleanup_dmi_name(card->dmi_longname + len);
+
+               /* some vendors like Lenovo may only put a self-explanatory
+                * name in the product version field
+                */
+               product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
+               if (product_version) {
+                       len = strlen(card->dmi_longname);
+                       snprintf(card->dmi_longname + len,
+                                longname_buf_size - len,
+                                "-%s", product_version);
+
+                       len++;
+                       if (len < longname_buf_size)
+                               cleanup_dmi_name(card->dmi_longname + len);
+               }
+       }
+
+       board = dmi_get_system_info(DMI_BOARD_NAME);
+       if (board) {
+               len = strlen(card->dmi_longname);
+               snprintf(card->dmi_longname + len,
+                        longname_buf_size - len,
+                        "-%s", board);
+
+               len++;
+               if (len < longname_buf_size)
+                       cleanup_dmi_name(card->dmi_longname + len);
+       } else if (!product) {
+               /* fall back to using legacy name */
+               dev_warn(card->dev, "ASoC: no DMI board/product name!\n");
+               return 0;
+       }
+
+       /* Add flavour to dmi long name */
+       if (flavour) {
+               len = strlen(card->dmi_longname);
+               snprintf(card->dmi_longname + len,
+                        longname_buf_size - len,
+                        "-%s", flavour);
+
+               len++;
+               if (len < longname_buf_size)
+                       cleanup_dmi_name(card->dmi_longname + len);
+       }
+
+       /* set the card long name */
+       card->long_name = card->dmi_longname;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
+
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;