未验证 提交 b68cbc1d 编写于 作者: M Mark Brown

Merge remote-tracking branch 'asoc/topic/intel' into asoc-next

...@@ -737,16 +737,17 @@ bool acpi_dev_found(const char *hid) ...@@ -737,16 +737,17 @@ bool acpi_dev_found(const char *hid)
} }
EXPORT_SYMBOL(acpi_dev_found); EXPORT_SYMBOL(acpi_dev_found);
struct acpi_dev_present_info { struct acpi_dev_match_info {
const char *dev_name;
struct acpi_device_id hid[2]; struct acpi_device_id hid[2];
const char *uid; const char *uid;
s64 hrv; s64 hrv;
}; };
static int acpi_dev_present_cb(struct device *dev, void *data) static int acpi_dev_match_cb(struct device *dev, void *data)
{ {
struct acpi_device *adev = to_acpi_device(dev); struct acpi_device *adev = to_acpi_device(dev);
struct acpi_dev_present_info *match = data; struct acpi_dev_match_info *match = data;
unsigned long long hrv; unsigned long long hrv;
acpi_status status; acpi_status status;
...@@ -757,6 +758,8 @@ static int acpi_dev_present_cb(struct device *dev, void *data) ...@@ -757,6 +758,8 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
strcmp(adev->pnp.unique_id, match->uid))) strcmp(adev->pnp.unique_id, match->uid)))
return 0; return 0;
match->dev_name = acpi_dev_name(adev);
if (match->hrv == -1) if (match->hrv == -1)
return 1; return 1;
...@@ -789,20 +792,44 @@ static int acpi_dev_present_cb(struct device *dev, void *data) ...@@ -789,20 +792,44 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
*/ */
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv) bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
{ {
struct acpi_dev_present_info match = {}; struct acpi_dev_match_info match = {};
struct device *dev; struct device *dev;
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id)); strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
match.uid = uid; match.uid = uid;
match.hrv = hrv; match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match, dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
acpi_dev_present_cb);
return !!dev; return !!dev;
} }
EXPORT_SYMBOL(acpi_dev_present); EXPORT_SYMBOL(acpi_dev_present);
/**
* acpi_dev_get_first_match_name - Return name of first match of ACPI device
* @hid: Hardware ID of the device.
* @uid: Unique ID of the device, pass NULL to not check _UID
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
*
* Return device name if a matching device was present
* at the moment of invocation, or NULL otherwise.
*
* See additional information in acpi_dev_present() as well.
*/
const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
{
struct acpi_dev_match_info match = {};
struct device *dev;
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
match.uid = uid;
match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
return dev ? match.dev_name : NULL;
}
EXPORT_SYMBOL(acpi_dev_get_first_match_name);
/* /*
* acpi_backlight= handling, this is done here rather then in video_detect.c * acpi_backlight= handling, this is done here rather then in video_detect.c
* because __setup cannot be used in modules. * because __setup cannot be used in modules.
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/acpi.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -380,9 +381,16 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv) ...@@ -380,9 +381,16 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
} }
} }
static const char *mrfld_gpio_get_pinctrl_dev_name(void)
{
const char *dev_name = acpi_dev_get_first_match_name("INTC1002", NULL, -1);
return dev_name ? dev_name : "pinctrl-merrifield";
}
static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
const struct mrfld_gpio_pinrange *range; const struct mrfld_gpio_pinrange *range;
const char *pinctrl_dev_name;
struct mrfld_gpio *priv; struct mrfld_gpio *priv;
u32 gpio_base, irq_base; u32 gpio_base, irq_base;
void __iomem *base; void __iomem *base;
...@@ -439,10 +447,11 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -439,10 +447,11 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
return retval; return retval;
} }
pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name();
for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) {
range = &mrfld_gpio_ranges[i]; range = &mrfld_gpio_ranges[i];
retval = gpiochip_add_pin_range(&priv->chip, retval = gpiochip_add_pin_range(&priv->chip,
"pinctrl-merrifield", pinctrl_dev_name,
range->gpio_base, range->gpio_base,
range->pin_base, range->pin_base,
range->npins); range->npins);
......
...@@ -91,6 +91,9 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev, ...@@ -91,6 +91,9 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
bool acpi_dev_found(const char *hid); bool acpi_dev_found(const char *hid);
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv); bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
......
...@@ -640,6 +640,12 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv) ...@@ -640,6 +640,12 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
return false; return false;
} }
static inline const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
{
return NULL;
}
static inline bool is_acpi_node(struct fwnode_handle *fwnode) static inline bool is_acpi_node(struct fwnode_handle *fwnode)
{ {
return false; return false;
......
...@@ -193,7 +193,7 @@ struct hda_dai_map { ...@@ -193,7 +193,7 @@ struct hda_dai_map {
* @pvt_data - private data, for asoc contains asoc codec object * @pvt_data - private data, for asoc contains asoc codec object
*/ */
struct hdac_ext_device { struct hdac_ext_device {
struct hdac_device hdac; struct hdac_device hdev;
struct hdac_ext_bus *ebus; struct hdac_ext_bus *ebus;
/* soc-dai to nid map */ /* soc-dai to nid map */
...@@ -213,7 +213,7 @@ struct hdac_ext_dma_params { ...@@ -213,7 +213,7 @@ struct hdac_ext_dma_params {
u8 stream_tag; u8 stream_tag;
}; };
#define to_ehdac_device(dev) (container_of((dev), \ #define to_ehdac_device(dev) (container_of((dev), \
struct hdac_ext_device, hdac)) struct hdac_ext_device, hdev))
/* /*
* HD-audio codec base driver * HD-audio codec base driver
*/ */
......
...@@ -27,17 +27,13 @@ struct snd_soc_acpi_package_context { ...@@ -27,17 +27,13 @@ struct snd_soc_acpi_package_context {
bool data_valid; bool data_valid;
}; };
/* codec name is used in DAIs is i2c-<HID>:00 with HID being 8 chars */
#define SND_ACPI_I2C_ID_LEN (4 + ACPI_ID_LEN + 3 + 1)
#if IS_ENABLED(CONFIG_ACPI) #if IS_ENABLED(CONFIG_ACPI)
/* translation fron HID to I2C name, needed for DAI codec_name */
const char *snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx); struct snd_soc_acpi_package_context *ctx);
#else #else
static inline const char *
snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
{
return NULL;
}
static inline bool static inline bool
snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx) struct snd_soc_acpi_package_context *ctx)
...@@ -50,9 +46,6 @@ snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], ...@@ -50,9 +46,6 @@ snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_mach * struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines); snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines);
/* acpi check hid */
bool snd_soc_acpi_check_hid(const u8 hid[ACPI_ID_LEN]);
/** /**
* snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are * snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are
* related to the hardware, except for the firmware and topology file names. * related to the hardware, except for the firmware and topology file names.
......
...@@ -222,6 +222,17 @@ ...@@ -222,6 +222,17 @@
* %SKL_TKN_MM_U32_NUM_IN_FMT: Number of input formats * %SKL_TKN_MM_U32_NUM_IN_FMT: Number of input formats
* %SKL_TKN_MM_U32_NUM_OUT_FMT: Number of output formats * %SKL_TKN_MM_U32_NUM_OUT_FMT: Number of output formats
* *
* %SKL_TKN_U32_ASTATE_IDX: Table Index for the A-State entry to be filled
* with kcps and clock source
*
* %SKL_TKN_U32_ASTATE_COUNT: Number of valid entries in A-State table
*
* %SKL_TKN_U32_ASTATE_KCPS: Specifies the core load threshold (in kilo
* cycles per second) below which DSP is clocked
* from source specified by clock source.
*
* %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
*
* module_id and loadable flags dont have tokens as these values will be * module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest * read from the DSP FW manifest
* *
...@@ -309,7 +320,11 @@ enum SKL_TKNS { ...@@ -309,7 +320,11 @@ enum SKL_TKNS {
SKL_TKN_MM_U32_NUM_IN_FMT, SKL_TKN_MM_U32_NUM_IN_FMT,
SKL_TKN_MM_U32_NUM_OUT_FMT, SKL_TKN_MM_U32_NUM_OUT_FMT,
SKL_TKN_MAX = SKL_TKN_MM_U32_NUM_OUT_FMT, SKL_TKN_U32_ASTATE_IDX,
SKL_TKN_U32_ASTATE_COUNT,
SKL_TKN_U32_ASTATE_KCPS,
SKL_TKN_U32_ASTATE_CLK_SRC,
SKL_TKN_MAX = SKL_TKN_U32_ASTATE_CLK_SRC,
}; };
#endif #endif
...@@ -146,7 +146,7 @@ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) ...@@ -146,7 +146,7 @@ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr)
edev = kzalloc(sizeof(*edev), GFP_KERNEL); edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev) if (!edev)
return -ENOMEM; return -ENOMEM;
hdev = &edev->hdac; hdev = &edev->hdev;
edev->ebus = ebus; edev->ebus = ebus;
snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr);
......
...@@ -133,7 +133,6 @@ config SND_SOC_ALL_CODECS ...@@ -133,7 +133,6 @@ config SND_SOC_ALL_CODECS
select SND_SOC_SGTL5000 if I2C select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SIRF_AUDIO_CODEC select SND_SOC_SIRF_AUDIO_CODEC
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF select SND_SOC_SPDIF
select SND_SOC_SSM2518 if I2C select SND_SOC_SSM2518 if I2C
select SND_SOC_SSM2602_SPI if SPI_MASTER select SND_SOC_SSM2602_SPI if SPI_MASTER
...@@ -818,9 +817,6 @@ config SND_SOC_SIRF_AUDIO_CODEC ...@@ -818,9 +817,6 @@ config SND_SOC_SIRF_AUDIO_CODEC
tristate "SiRF SoC internal audio codec" tristate "SiRF SoC internal audio codec"
select REGMAP_MMIO select REGMAP_MMIO
config SND_SOC_SN95031
tristate
config SND_SOC_SPDIF config SND_SOC_SPDIF
tristate "S/PDIF CODEC" tristate "S/PDIF CODEC"
......
...@@ -140,7 +140,6 @@ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o ...@@ -140,7 +140,6 @@ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o snd-soc-si476x-objs := si476x.o
snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-ssm2518-objs := ssm2518.o snd-soc-ssm2518-objs := ssm2518.o
......
此差异已折叠。
此差异已折叠。
/*
* sn95031.h - TI sn95031 Codec driver
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*/
#ifndef _SN95031_H
#define _SN95031_H
/*register map*/
#define SN95031_VAUD 0xDB
#define SN95031_VHSP 0xDC
#define SN95031_VHSN 0xDD
#define SN95031_VIHF 0xC9
#define SN95031_AUDPLLCTRL 0x240
#define SN95031_DMICBUF0123 0x241
#define SN95031_DMICBUF45 0x242
#define SN95031_DMICGPO 0x244
#define SN95031_DMICMUX 0x245
#define SN95031_DMICLK 0x246
#define SN95031_MICBIAS 0x247
#define SN95031_ADCCONFIG 0x248
#define SN95031_MICAMP1 0x249
#define SN95031_MICAMP2 0x24A
#define SN95031_NOISEMUX 0x24B
#define SN95031_AUDIOMUX12 0x24C
#define SN95031_AUDIOMUX34 0x24D
#define SN95031_AUDIOSINC 0x24E
#define SN95031_AUDIOTXEN 0x24F
#define SN95031_HSEPRXCTRL 0x250
#define SN95031_IHFRXCTRL 0x251
#define SN95031_HSMIXER 0x256
#define SN95031_DACCONFIG 0x257
#define SN95031_SOFTMUTE 0x258
#define SN95031_HSLVOLCTRL 0x259
#define SN95031_HSRVOLCTRL 0x25A
#define SN95031_IHFLVOLCTRL 0x25B
#define SN95031_IHFRVOLCTRL 0x25C
#define SN95031_DRIVEREN 0x25D
#define SN95031_LOCTL 0x25E
#define SN95031_VIB1C1 0x25F
#define SN95031_VIB1C2 0x260
#define SN95031_VIB1C3 0x261
#define SN95031_VIB1SPIPCM1 0x262
#define SN95031_VIB1SPIPCM2 0x263
#define SN95031_VIB1C5 0x264
#define SN95031_VIB2C1 0x265
#define SN95031_VIB2C2 0x266
#define SN95031_VIB2C3 0x267
#define SN95031_VIB2SPIPCM1 0x268
#define SN95031_VIB2SPIPCM2 0x269
#define SN95031_VIB2C5 0x26A
#define SN95031_BTNCTRL1 0x26B
#define SN95031_BTNCTRL2 0x26C
#define SN95031_PCM1TXSLOT01 0x26D
#define SN95031_PCM1TXSLOT23 0x26E
#define SN95031_PCM1TXSLOT45 0x26F
#define SN95031_PCM1RXSLOT0_3 0x270
#define SN95031_PCM1RXSLOT45 0x271
#define SN95031_PCM2TXSLOT01 0x272
#define SN95031_PCM2TXSLOT23 0x273
#define SN95031_PCM2TXSLOT45 0x274
#define SN95031_PCM2RXSLOT01 0x275
#define SN95031_PCM2RXSLOT23 0x276
#define SN95031_PCM2RXSLOT45 0x277
#define SN95031_PCM1C1 0x278
#define SN95031_PCM1C2 0x279
#define SN95031_PCM1C3 0x27A
#define SN95031_PCM2C1 0x27B
#define SN95031_PCM2C2 0x27C
/*end codec register defn*/
/*vendor defn these are not part of avp*/
#define SN95031_SSR2 0x381
#define SN95031_SSR3 0x382
#define SN95031_SSR5 0x384
#define SN95031_SSR6 0x385
/* ADC registers */
#define SN95031_ADC1CNTL1 0x1C0
#define SN95031_ADC_ENBL 0x10
#define SN95031_ADC_START 0x08
#define SN95031_ADC1CNTL3 0x1C2
#define SN95031_ADCTHERM_ENBL 0x04
#define SN95031_ADCRRDATA_ENBL 0x05
#define SN95031_STOPBIT_MASK 16
#define SN95031_ADCTHERM_MASK 4
#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */
#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
#define SN95031_ADC_NO_LOOP 0x07
#define SN95031_AUDIO_GPIO_CTRL 0x070
/* ADC channel code values */
#define SN95031_AUDIO_DETECT_CODE 0x06
/* ADC base addresses */
#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
#define SN95031_ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
/* multipier to convert to mV */
#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
struct mfld_jack_data {
int intr_id;
int micbias_vol;
struct snd_soc_jack *mfld_jack;
};
extern void sn95031_jack_detection(struct snd_soc_codec *codec,
struct mfld_jack_data *jack_data);
#endif
config SND_SOC_INTEL_SST_TOPLEVEL
bool "Intel ASoC SST drivers"
default y
depends on X86 || COMPILE_TEST
select SND_SOC_INTEL_MACH
help
Intel ASoC SST Platform Drivers. If you have a Intel machine that
has an audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Intel SST drivers.
if SND_SOC_INTEL_SST_TOPLEVEL
config SND_SST_IPC config SND_SST_IPC
tristate tristate
# This option controls the IPC core for HiFi2 platforms
config SND_SST_IPC_PCI config SND_SST_IPC_PCI
tristate tristate
select SND_SST_IPC select SND_SST_IPC
# This option controls the PCI-based IPC for HiFi2 platforms
# (Medfield, Merrifield).
config SND_SST_IPC_ACPI config SND_SST_IPC_ACPI
tristate tristate
select SND_SST_IPC select SND_SST_IPC
select SND_SOC_INTEL_SST # This option controls the ACPI-based IPC for HiFi2 platforms
select IOSF_MBI # (Baytrail, Cherrytrail)
config SND_SOC_INTEL_COMMON config SND_SOC_INTEL_SST_ACPI
tristate tristate
# This option controls ACPI-based probing on
# Haswell/Broadwell/Baytrail legacy and will be set
# when these platforms are enabled
config SND_SOC_INTEL_SST config SND_SOC_INTEL_SST
tristate tristate
select SND_SOC_INTEL_SST_ACPI if ACPI
config SND_SOC_INTEL_SST_FIRMWARE config SND_SOC_INTEL_SST_FIRMWARE
tristate tristate
select DW_DMAC_CORE select DW_DMAC_CORE
# This option controls firmware download on
config SND_SOC_INTEL_SST_ACPI # Haswell/Broadwell/Baytrail legacy and will be set
tristate # when these platforms are enabled
config SND_SOC_ACPI_INTEL_MATCH
tristate
select SND_SOC_ACPI if ACPI
config SND_SOC_INTEL_SST_TOPLEVEL
tristate "Intel ASoC SST drivers"
depends on X86 || COMPILE_TEST
select SND_SOC_INTEL_MACH
select SND_SOC_INTEL_COMMON
help
Intel ASoC Audio Drivers. If you have a Intel machine that
has audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y or M
If unsure select "N".
config SND_SOC_INTEL_HASWELL config SND_SOC_INTEL_HASWELL
tristate "Intel ASoC SST driver for Haswell/Broadwell" tristate "Haswell/Broadwell Platforms"
depends on SND_SOC_INTEL_SST_TOPLEVEL && SND_DMA_SGBUF depends on SND_DMA_SGBUF
depends on DMADEVICES depends on DMADEVICES && ACPI
select SND_SOC_INTEL_SST select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_ACPI
select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Haswell or Broadwell platform connected to
an I2S codec, then enable this option by saying Y or m. This is
typically used for Chromebooks. This is a recommended option.
config SND_SOC_INTEL_BAYTRAIL config SND_SOC_INTEL_BAYTRAIL
tristate "Intel ASoC SST driver for Baytrail (legacy)" tristate "Baytrail (legacy) Platforms"
depends on SND_SOC_INTEL_SST_TOPLEVEL depends on DMADEVICES && ACPI
depends on DMADEVICES
select SND_SOC_INTEL_SST select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_ACPI
select SND_SOC_INTEL_SST_FIRMWARE select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Baytrail platform connected to an I2S codec,
then enable this option by saying Y or m. This was typically used
for Baytrail Chromebooks but this option is now deprecated and is
not recommended, use SND_SST_ATOM_HIFI2_PLATFORM instead.
config SND_SST_ATOM_HIFI2_PLATFORM_PCI
tristate "PCI HiFi2 (Medfield, Merrifield) Platforms"
depends on X86 && PCI
select SND_SST_IPC_PCI
select SND_SOC_COMPRESS
help
If you have a Intel Medfield or Merrifield/Edison platform, then
enable this option by saying Y or m. Distros will typically not
enable this option: Medfield devices are not available to
developers and while Merrifield/Edison can run a mainline kernel with
limited functionality it will require a firmware file which
is not in the standard firmware tree
config SND_SST_ATOM_HIFI2_PLATFORM config SND_SST_ATOM_HIFI2_PLATFORM
tristate "Intel ASoC SST driver for HiFi2 platforms (*field, *trail)" tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
depends on SND_SOC_INTEL_SST_TOPLEVEL && X86 depends on X86 && ACPI
select SND_SST_IPC_ACPI
select SND_SOC_COMPRESS select SND_SOC_COMPRESS
select SND_SOC_ACPI_INTEL_MATCH
select IOSF_MBI
help
If you have a Intel Baytrail or Cherrytrail platform with an I2S
codec, then enable this option by saying Y or m. This is a
recommended option
config SND_SOC_INTEL_SKYLAKE config SND_SOC_INTEL_SKYLAKE
tristate "Intel ASoC SST driver for SKL/BXT/KBL/GLK/CNL" tristate "SKL/BXT/KBL/GLK/CNL... Platforms"
depends on SND_SOC_INTEL_SST_TOPLEVEL && PCI && ACPI depends on PCI && ACPI
select SND_HDA_EXT_CORE select SND_HDA_EXT_CORE
select SND_HDA_DSP_LOADER select SND_HDA_DSP_LOADER
select SND_SOC_TOPOLOGY select SND_SOC_TOPOLOGY
select SND_SOC_INTEL_SST select SND_SOC_INTEL_SST
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with the DSP enabled in the BIOS
then enable this option by saying Y or m.
config SND_SOC_ACPI_INTEL_MATCH
tristate
select SND_SOC_ACPI if ACPI
# this option controls the compilation of ACPI matching tables and
# helpers and is not meant to be selected by the user.
endif ## SND_SOC_INTEL_SST_TOPLEVEL
# ASoC codec drivers # ASoC codec drivers
source "sound/soc/intel/boards/Kconfig" source "sound/soc/intel/boards/Kconfig"
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# Core support # Core support
obj-$(CONFIG_SND_SOC_INTEL_COMMON) += common/ obj-$(CONFIG_SND_SOC) += common/
# Platform Support # Platform Support
obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/
......
...@@ -236,6 +236,9 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ...@@ -236,6 +236,9 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx)
/* Find the IRQ */ /* Find the IRQ */
ctx->irq_num = platform_get_irq(pdev, ctx->irq_num = platform_get_irq(pdev,
ctx->pdata->res_info->acpi_ipc_irq_index); ctx->pdata->res_info->acpi_ipc_irq_index);
if (ctx->irq_num <= 0)
return ctx->irq_num < 0 ? ctx->irq_num : -EIO;
return 0; return 0;
} }
......
...@@ -220,10 +220,10 @@ int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, ...@@ -220,10 +220,10 @@ int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
sst_free_block(sst_drv_ctx, block); sst_free_block(sst_drv_ctx, block);
out: out:
test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id); test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
return 0; return ret;
} }
/* /**
* sst_pause_stream - Send msg for a pausing stream * sst_pause_stream - Send msg for a pausing stream
* @str_id: stream ID * @str_id: stream ID
* *
...@@ -261,7 +261,7 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) ...@@ -261,7 +261,7 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
} }
} else { } else {
retval = -EBADRQC; retval = -EBADRQC;
dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n "); dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n");
} }
return retval; return retval;
...@@ -284,7 +284,7 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) ...@@ -284,7 +284,7 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
if (!str_info) if (!str_info)
return -EINVAL; return -EINVAL;
if (str_info->status == STREAM_RUNNING) if (str_info->status == STREAM_RUNNING)
return 0; return 0;
if (str_info->status == STREAM_PAUSED) { if (str_info->status == STREAM_PAUSED) {
retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD, IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
......
config SND_SOC_INTEL_MACH menuconfig SND_SOC_INTEL_MACH
tristate "Intel Audio machine drivers" bool "Intel Machine drivers"
depends on SND_SOC_INTEL_SST_TOPLEVEL depends on SND_SOC_INTEL_SST_TOPLEVEL
select SND_SOC_ACPI_INTEL_MATCH if ACPI help
Intel ASoC Machine Drivers. If you have a Intel machine that
has an audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Intel ASoC machine drivers.
if SND_SOC_INTEL_MACH if SND_SOC_INTEL_MACH
config SND_MFLD_MACHINE if SND_SOC_INTEL_HASWELL
tristate "SOC Machine Audio driver for Intel Medfield MID platform"
depends on INTEL_SCU_IPC
select SND_SOC_SN95031
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_PCI
help
This adds support for ASoC machine driver for Intel(R) MID Medfield platform
used as alsa device in audio substem in Intel(R) MID devices
Say Y if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_HASWELL_MACH config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" tristate "Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640 select SND_SOC_RT5640
help help
This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell
Ultrabook platforms. Ultrabook platforms. This is a recommended option.
Say Y if you have such a device. Say Y or m if you have such a device.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BDW_RT5677_MACH config SND_SOC_INTEL_BDW_RT5677_MACH
tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec" tristate "Broadwell with RT5677 codec"
depends on X86_INTEL_LPSS && GPIOLIB && I2C depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM && GPIOLIB
depends on SND_SOC_INTEL_HASWELL
select SND_SOC_RT5677 select SND_SOC_RT5677
help help
This adds support for Intel Broadwell platform based boards with This adds support for Intel Broadwell platform based boards with
the RT5677 audio codec. the RT5677 audio codec. This is a recommended option.
Say Y or m if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_BROADWELL_MACH config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" tristate "Broadwell Wildcatpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on SND_SOC_INTEL_HASWELL
select SND_SOC_RT286 select SND_SOC_RT286
help help
This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
Ultrabook platforms. Ultrabook platforms.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
endif ## SND_SOC_INTEL_HASWELL
if SND_SOC_INTEL_BAYTRAIL
config SND_SOC_INTEL_BYT_MAX98090_MACH config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" tristate "Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C depends on X86_INTEL_LPSS && I2C
depends on SND_SST_IPC_ACPI = n
depends on SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090 select SND_SOC_MAX98090
help help
This adds audio driver for Intel Baytrail platform based boards This adds audio driver for Intel Baytrail platform based boards
with the MAX98090 audio codec. with the MAX98090 audio codec. This driver is deprecated, use
SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH instead for better
functionality.
config SND_SOC_INTEL_BYT_RT5640_MACH config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" tristate "Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C depends on X86_INTEL_LPSS && I2C
depends on SND_SST_IPC_ACPI = n
depends on SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640 select SND_SOC_RT5640
help help
This adds audio driver for Intel Baytrail platform based boards This adds audio driver for Intel Baytrail platform based boards
with the RT5640 audio codec. This driver is deprecated, use with the RT5640 audio codec. This driver is deprecated, use
SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality. SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality.
endif ## SND_SOC_INTEL_BAYTRAIL
if SND_SST_ATOM_HIFI2_PLATFORM
config SND_SOC_INTEL_BYTCR_RT5640_MACH config SND_SOC_INTEL_BYTCR_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec" tristate "Baytrail and Baytrail-CR with RT5640 codec"
depends on X86 && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5640 select SND_SOC_RT5640
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5640 audio codec. platforms with RT5640 audio codec.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BYTCR_RT5651_MACH config SND_SOC_INTEL_BYTCR_RT5651_MACH
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec" tristate "Baytrail and Baytrail-CR with RT5651 codec"
depends on X86 && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5651 select SND_SOC_RT5651
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5651 audio codec. platforms with RT5651 audio codec.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" tristate "Cherrytrail & Braswell with RT5672 codec"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_RT5670 select SND_SOC_ACPI
depends on SND_SST_ATOM_HIFI2_PLATFORM select SND_SOC_RT5670
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with RT5672 audio codec. platforms with RT5672 audio codec.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5645_MACH config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" tristate "Cherrytrail & Braswell with RT5645/5650 codec"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5645 select SND_SOC_RT5645
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with RT5645/5650 audio codec. platforms with RT5645/5650 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with MAX98090 & TI codec" tristate "Cherrytrail & Braswell with MAX98090 & TI codec"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_MAX98090 select SND_SOC_MAX98090
select SND_SOC_TS3A227E select SND_SOC_TS3A227E
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with MAX98090 audio codec it also can support TI jack chip as aux device. platforms with MAX98090 audio codec it also can support TI jack chip as aux device.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_DA7213_MACH config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with DA7212/7213 codec" tristate "Baytrail & Cherrytrail with DA7212/7213 codec"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_DA7213 select SND_SOC_DA7213
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Baytrail & CherryTrail This adds support for ASoC machine driver for Intel(R) Baytrail & CherryTrail
platforms with DA7212/7213 audio codec. platforms with DA7212/7213 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_ES8316_MACH config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with ES8316 codec" tristate "Baytrail & Cherrytrail with ES8316 codec"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_ES8316 select SND_SOC_ES8316
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for Intel(R) Baytrail & This adds support for ASoC machine driver for Intel(R) Baytrail &
Cherrytrail platforms with ES8316 audio codec. Cherrytrail platforms with ES8316 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" tristate "Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)"
depends on X86_INTEL_LPSS && I2C && ACPI depends on X86_INTEL_LPSS && I2C && ACPI
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help help
This adds support for ASoC machine driver for the MinnowBoard Max or This adds support for ASoC machine driver for the MinnowBoard Max or
Up boards and provides access to I2S signals on the Low-Speed Up boards and provides access to I2S signals on the Low-Speed
connector connector. This is not a recommended option outside of these cases.
It is not intended to be enabled by distros by default.
Say Y or m if you have such a device.
If unsure select "N". If unsure select "N".
endif ## SND_SST_ATOM_HIFI2_PLATFORM
if SND_SOC_INTEL_SKYLAKE
config SND_SOC_INTEL_SKL_RT286_MACH config SND_SOC_INTEL_SKL_RT286_MACH
tristate "ASoC Audio driver for SKL with RT286 I2S mode" tristate "SKL with RT286 I2S mode"
depends on X86 && ACPI && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT286 select SND_SOC_RT286
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI select SND_SOC_HDAC_HDMI
help help
This adds support for ASoC machine driver for Skylake platforms This adds support for ASoC machine driver for Skylake platforms
with RT286 I2S audio codec. with RT286 I2S audio codec.
Say Y if you have such a device. Say Y or m if you have such a device.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode" tristate "SKL with NAU88L25 and SSM4567 in I2S Mode"
depends on X86_INTEL_LPSS && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_NAU8825 select SND_SOC_NAU8825
select SND_SOC_SSM4567 select SND_SOC_SSM4567
select SND_SOC_DMIC select SND_SOC_DMIC
...@@ -185,13 +185,12 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH ...@@ -185,13 +185,12 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + SSM4567. create an alsa sound card for NAU88L25 + SSM4567.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode" tristate "SKL with NAU88L25 and MAX98357A in I2S Mode"
depends on X86_INTEL_LPSS && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_NAU8825 select SND_SOC_NAU8825
select SND_SOC_MAX98357A select SND_SOC_MAX98357A
select SND_SOC_DMIC select SND_SOC_DMIC
...@@ -199,13 +198,12 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH ...@@ -199,13 +198,12 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + MAX98357A. create an alsa sound card for NAU88L25 + MAX98357A.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode" tristate "Broxton with DA7219 and MAX98357A in I2S Mode"
depends on X86 && ACPI && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_DA7219 select SND_SOC_DA7219
select SND_SOC_MAX98357A select SND_SOC_MAX98357A
select SND_SOC_DMIC select SND_SOC_DMIC
...@@ -214,13 +212,12 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH ...@@ -214,13 +212,12 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
help help
This adds support for ASoC machine driver for Broxton-P platforms This adds support for ASoC machine driver for Broxton-P platforms
with DA7219 + MAX98357A I2S audio codec. with DA7219 + MAX98357A I2S audio codec.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_BXT_RT298_MACH config SND_SOC_INTEL_BXT_RT298_MACH
tristate "ASoC Audio driver for Broxton with RT298 I2S mode" tristate "Broxton with RT298 I2S mode"
depends on X86 && ACPI && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT298 select SND_SOC_RT298
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI select SND_SOC_HDAC_HDMI
...@@ -228,14 +225,12 @@ config SND_SOC_INTEL_BXT_RT298_MACH ...@@ -228,14 +225,12 @@ config SND_SOC_INTEL_BXT_RT298_MACH
help help
This adds support for ASoC machine driver for Broxton platforms This adds support for ASoC machine driver for Broxton platforms
with RT286 I2S audio codec. with RT286 I2S audio codec.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode" tristate "KBL with RT5663 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_INTEL_SST
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT5663 select SND_SOC_RT5663
select SND_SOC_MAX98927 select SND_SOC_MAX98927
select SND_SOC_DMIC select SND_SOC_DMIC
...@@ -243,14 +238,13 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH ...@@ -243,14 +238,13 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + MAX98927. create an alsa sound card for RT5663 + MAX98927.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" tristate "KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C && SPI depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_INTEL_SST depends on SPI
depends on SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT5663 select SND_SOC_RT5663
select SND_SOC_RT5514 select SND_SOC_RT5514
select SND_SOC_RT5514_SPI select SND_SOC_RT5514_SPI
...@@ -259,7 +253,8 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH ...@@ -259,7 +253,8 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + RT5514 + MAX98927. create an alsa sound card for RT5663 + RT5514 + MAX98927.
Say Y if you have such a device. Say Y or m if you have such a device. This is a recommended option.
If unsure select "N". If unsure select "N".
endif ## SND_SOC_INTEL_SKYLAKE
endif endif ## SND_SOC_INTEL_MACH
...@@ -219,7 +219,7 @@ static struct snd_soc_card bytcht_da7213_card = { ...@@ -219,7 +219,7 @@ static struct snd_soc_card bytcht_da7213_card = {
.num_dapm_routes = ARRAY_SIZE(audio_map), .num_dapm_routes = ARRAY_SIZE(audio_map),
}; };
static char codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ static char codec_name[SND_ACPI_I2C_ID_LEN];
static int bytcht_da7213_probe(struct platform_device *pdev) static int bytcht_da7213_probe(struct platform_device *pdev)
{ {
...@@ -243,7 +243,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev) ...@@ -243,7 +243,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
} }
/* fixup codec name based on HID */ /* fixup codec name based on HID */
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id); i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) { if (i2c_name) {
snprintf(codec_name, sizeof(codec_name), snprintf(codec_name, sizeof(codec_name),
"%s%s", "i2c-", i2c_name); "%s%s", "i2c-", i2c_name);
......
...@@ -232,15 +232,39 @@ static struct snd_soc_card byt_cht_es8316_card = { ...@@ -232,15 +232,39 @@ static struct snd_soc_card byt_cht_es8316_card = {
.fully_routed = true, .fully_routed = true,
}; };
static char codec_name[SND_ACPI_I2C_ID_LEN];
static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
{ {
int ret = 0;
struct byt_cht_es8316_private *priv; struct byt_cht_es8316_private *priv;
struct snd_soc_acpi_mach *mach;
const char *i2c_name = NULL;
int dai_index = 0;
int i;
int ret = 0;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
mach = (&pdev->dev)->platform_data;
/* fix index of codec dai */
for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
if (!strcmp(byt_cht_es8316_dais[i].codec_name,
"i2c-ESSX8316:00")) {
dai_index = i;
break;
}
}
/* fixup codec name based on HID */
i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) {
snprintf(codec_name, sizeof(codec_name),
"%s%s", "i2c-", i2c_name);
byt_cht_es8316_dais[dai_index].codec_name = codec_name;
}
/* register the soc card */ /* register the soc card */
byt_cht_es8316_card.dev = &pdev->dev; byt_cht_es8316_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv); snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
......
...@@ -713,7 +713,7 @@ static struct snd_soc_card byt_rt5640_card = { ...@@ -713,7 +713,7 @@ static struct snd_soc_card byt_rt5640_card = {
.fully_routed = true, .fully_routed = true,
}; };
static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */
static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
...@@ -762,7 +762,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ...@@ -762,7 +762,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
} }
/* fixup codec name based on HID */ /* fixup codec name based on HID */
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id); i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) { if (i2c_name) {
snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
"%s%s", "i2c-", i2c_name); "%s%s", "i2c-", i2c_name);
......
...@@ -38,6 +38,8 @@ enum { ...@@ -38,6 +38,8 @@ enum {
BYT_RT5651_DMIC_MAP, BYT_RT5651_DMIC_MAP,
BYT_RT5651_IN1_MAP, BYT_RT5651_IN1_MAP,
BYT_RT5651_IN2_MAP, BYT_RT5651_IN2_MAP,
BYT_RT5651_IN1_IN2_MAP,
BYT_RT5651_IN3_MAP,
}; };
#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(7, 0)) #define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(7, 0))
...@@ -62,6 +64,8 @@ static void log_quirks(struct device *dev) ...@@ -62,6 +64,8 @@ static void log_quirks(struct device *dev)
dev_info(dev, "quirk IN1_MAP enabled"); dev_info(dev, "quirk IN1_MAP enabled");
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP) if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
dev_info(dev, "quirk IN2_MAP enabled"); dev_info(dev, "quirk IN2_MAP enabled");
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
dev_info(dev, "quirk IN3_MAP enabled");
if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
dev_info(dev, "quirk DMIC enabled"); dev_info(dev, "quirk DMIC enabled");
if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
...@@ -127,6 +131,7 @@ static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = { ...@@ -127,6 +131,7 @@ static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Internal Mic", NULL), SND_SOC_DAPM_MIC("Internal Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL), SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_LINE("Line In", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_PRE_PMU | platform_clock_control, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_POST_PMD),
...@@ -138,6 +143,7 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = { ...@@ -138,6 +143,7 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
{"Headset Mic", NULL, "Platform Clock"}, {"Headset Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "Platform Clock"}, {"Internal Mic", NULL, "Platform Clock"},
{"Speaker", NULL, "Platform Clock"}, {"Speaker", NULL, "Platform Clock"},
{"Line In", NULL, "Platform Clock"},
{"AIF1 Playback", NULL, "ssp2 Tx"}, {"AIF1 Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"}, {"ssp2 Tx", NULL, "codec_out0"},
...@@ -151,6 +157,9 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = { ...@@ -151,6 +157,9 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
{"Headphone", NULL, "HPOR"}, {"Headphone", NULL, "HPOR"},
{"Speaker", NULL, "LOUTL"}, {"Speaker", NULL, "LOUTL"},
{"Speaker", NULL, "LOUTR"}, {"Speaker", NULL, "LOUTR"},
{"IN2P", NULL, "Line In"},
{"IN2N", NULL, "Line In"},
}; };
static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = { static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
...@@ -171,11 +180,25 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = { ...@@ -171,11 +180,25 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
{"IN2P", NULL, "Internal Mic"}, {"IN2P", NULL, "Internal Mic"},
}; };
static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
{"Internal Mic", NULL, "micbias1"},
{"IN1P", NULL, "Internal Mic"},
{"IN2P", NULL, "Internal Mic"},
{"IN3P", NULL, "Headset Mic"},
};
static const struct snd_soc_dapm_route byt_rt5651_intmic_in3_map[] = {
{"Internal Mic", NULL, "micbias1"},
{"IN3P", NULL, "Headset Mic"},
{"IN1P", NULL, "Internal Mic"},
};
static const struct snd_kcontrol_new byt_rt5651_controls[] = { static const struct snd_kcontrol_new byt_rt5651_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Internal Mic"), SOC_DAPM_PIN_SWITCH("Internal Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"), SOC_DAPM_PIN_SWITCH("Speaker"),
SOC_DAPM_PIN_SWITCH("Line In"),
}; };
static struct snd_soc_jack_pin bytcr_jack_pins[] = { static struct snd_soc_jack_pin bytcr_jack_pins[] = {
...@@ -247,8 +270,16 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = { ...@@ -247,8 +270,16 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
}, },
.driver_data = (void *)(BYT_RT5651_DMIC_MAP | .driver_data = (void *)(BYT_RT5651_IN3_MAP),
BYT_RT5651_DMIC_EN), },
{
.callback = byt_rt5651_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
},
.driver_data = (void *)(BYT_RT5651_MCLK_EN |
BYT_RT5651_IN3_MAP),
}, },
{ {
.callback = byt_rt5651_quirk_cb, .callback = byt_rt5651_quirk_cb,
...@@ -256,7 +287,8 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = { ...@@ -256,7 +287,8 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "KIANO"), DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"), DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
}, },
.driver_data = (void *)(BYT_RT5651_IN2_MAP), .driver_data = (void *)(BYT_RT5651_MCLK_EN |
BYT_RT5651_IN1_IN2_MAP),
}, },
{} {}
}; };
...@@ -281,6 +313,14 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) ...@@ -281,6 +313,14 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
custom_map = byt_rt5651_intmic_in2_map; custom_map = byt_rt5651_intmic_in2_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map); num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
break; break;
case BYT_RT5651_IN1_IN2_MAP:
custom_map = byt_rt5651_intmic_in1_in2_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
break;
case BYT_RT5651_IN3_MAP:
custom_map = byt_rt5651_intmic_in3_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_in3_map);
break;
default: default:
custom_map = byt_rt5651_intmic_dmic_map; custom_map = byt_rt5651_intmic_dmic_map;
num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map); num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
...@@ -469,7 +509,7 @@ static struct snd_soc_card byt_rt5651_card = { ...@@ -469,7 +509,7 @@ static struct snd_soc_card byt_rt5651_card = {
.fully_routed = true, .fully_routed = true,
}; };
static char byt_rt5651_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
{ {
...@@ -499,7 +539,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) ...@@ -499,7 +539,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
} }
/* fixup codec name based on HID */ /* fixup codec name based on HID */
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id); i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) { if (i2c_name) {
snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
"%s%s", "i2c-", i2c_name); "%s%s", "i2c-", i2c_name);
......
...@@ -49,7 +49,7 @@ struct cht_acpi_card { ...@@ -49,7 +49,7 @@ struct cht_acpi_card {
struct cht_mc_private { struct cht_mc_private {
struct snd_soc_jack jack; struct snd_soc_jack jack;
struct cht_acpi_card *acpi_card; struct cht_acpi_card *acpi_card;
char codec_name[16]; char codec_name[SND_ACPI_I2C_ID_LEN];
struct clk *mclk; struct clk *mclk;
}; };
...@@ -499,7 +499,7 @@ static struct cht_acpi_card snd_soc_cards[] = { ...@@ -499,7 +499,7 @@ static struct cht_acpi_card snd_soc_cards[] = {
{"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
}; };
static char cht_rt5645_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ static char cht_rt5645_codec_name[SND_ACPI_I2C_ID_LEN];
static char cht_rt5645_codec_aif_name[12]; /* = "rt5645-aif[1|2]" */ static char cht_rt5645_codec_aif_name[12]; /* = "rt5645-aif[1|2]" */
static char cht_rt5645_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ static char cht_rt5645_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
...@@ -566,7 +566,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -566,7 +566,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
} }
/* fixup codec name based on HID */ /* fixup codec name based on HID */
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id); i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) { if (i2c_name) {
snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name), snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
"%s%s", "i2c-", i2c_name); "%s%s", "i2c-", i2c_name);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
struct cht_mc_private { struct cht_mc_private {
struct snd_soc_jack headset; struct snd_soc_jack headset;
char codec_name[16]; char codec_name[SND_ACPI_I2C_ID_LEN];
struct clk *mclk; struct clk *mclk;
}; };
...@@ -396,7 +396,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -396,7 +396,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
/* fixup codec name based on HID */ /* fixup codec name based on HID */
if (mach) { if (mach) {
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id); i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) { if (i2c_name) {
snprintf(drv->codec_name, sizeof(drv->codec_name), snprintf(drv->codec_name, sizeof(drv->codec_name),
"i2c-%s", i2c_name); "i2c-%s", i2c_name);
......
...@@ -76,7 +76,7 @@ static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, ...@@ -76,7 +76,7 @@ static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream,
} }
/* set correct codec filter for DAI format and clock config */ /* set correct codec filter for DAI format and clock config */
snd_soc_update_bits(rtd->codec, 0x83, 0xffff, 0x8000); snd_soc_component_update_bits(codec_dai->component, 0x83, 0xffff, 0x8000);
return ret; return ret;
} }
......
...@@ -225,7 +225,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -225,7 +225,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
} }
jack = &ctx->kabylake_headset; jack = &ctx->kabylake_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); 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_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
......
...@@ -195,7 +195,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -195,7 +195,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
} }
jack = &ctx->kabylake_headset; jack = &ctx->kabylake_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); 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_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
......
/*
* mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include "../codecs/sn95031.h"
#define MID_MONO 1
#define MID_STEREO 2
#define MID_MAX_CAP 5
#define MFLD_JACK_INSERT 0x04
enum soc_mic_bias_zones {
MFLD_MV_START = 0,
/* mic bias volutage range for Headphones*/
MFLD_MV_HP = 400,
/* mic bias volutage range for American Headset*/
MFLD_MV_AM_HS = 650,
/* mic bias volutage range for Headset*/
MFLD_MV_HS = 2000,
MFLD_MV_UNDEFINED,
};
static unsigned int hs_switch;
static unsigned int lo_dac;
static struct snd_soc_codec *mfld_codec;
struct mfld_mc_private {
void __iomem *int_base;
u8 interrupt_status;
};
struct snd_soc_jack mfld_jack;
/*Headset jack detection DAPM pins */
static struct snd_soc_jack_pin mfld_jack_pins[] = {
{
.pin = "Headphones",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "AMIC1",
.mask = SND_JACK_MICROPHONE,
},
};
/* jack detection voltage zones */
static struct snd_soc_jack_zone mfld_zones[] = {
{MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE},
{MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET},
};
/* sound card controls */
static const char * const headset_switch_text[] = {"Earpiece", "Headset"};
static const char * const lo_text[] = {"Vibra", "Headset", "IHF", "None"};
static const struct soc_enum headset_enum =
SOC_ENUM_SINGLE_EXT(2, headset_switch_text);
static const struct soc_enum lo_enum =
SOC_ENUM_SINGLE_EXT(4, lo_text);
static int headset_get_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = hs_switch;
return 0;
}
static int headset_set_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = &card->dapm;
if (ucontrol->value.enumerated.item[0] == hs_switch)
return 0;
snd_soc_dapm_mutex_lock(dapm);
if (ucontrol->value.enumerated.item[0]) {
pr_debug("hs_set HS path\n");
snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
} else {
pr_debug("hs_set EP path\n");
snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT");
}
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
hs_switch = ucontrol->value.enumerated.item[0];
return 0;
}
static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm)
{
snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL");
snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR");
snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL");
snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR");
snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT");
snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT");
if (hs_switch) {
snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
} else {
snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT");
}
}
static int lo_get_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = lo_dac;
return 0;
}
static int lo_set_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = &card->dapm;
if (ucontrol->value.enumerated.item[0] == lo_dac)
return 0;
snd_soc_dapm_mutex_lock(dapm);
/* we dont want to work with last state of lineout so just enable all
* pins and then disable pins not required
*/
lo_enable_out_pins(dapm);
switch (ucontrol->value.enumerated.item[0]) {
case 0:
pr_debug("set vibra path\n");
snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT");
snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT");
snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0);
break;
case 1:
pr_debug("set hs path\n");
snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x22);
break;
case 2:
pr_debug("set spkr path\n");
snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL");
snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR");
snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x44);
break;
case 3:
pr_debug("set null path\n");
snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL");
snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR");
snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x66);
break;
}
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
lo_dac = ucontrol->value.enumerated.item[0];
return 0;
}
static const struct snd_kcontrol_new mfld_snd_controls[] = {
SOC_ENUM_EXT("Playback Switch", headset_enum,
headset_get_switch, headset_set_switch),
SOC_ENUM_EXT("Lineout Mux", lo_enum,
lo_get_switch, lo_set_switch),
};
static const struct snd_soc_dapm_widget mfld_widgets[] = {
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("Mic", NULL),
};
static const struct snd_soc_dapm_route mfld_map[] = {
{"Headphones", NULL, "HPOUTR"},
{"Headphones", NULL, "HPOUTL"},
{"Mic", NULL, "AMIC1"},
};
static void mfld_jack_check(unsigned int intr_status)
{
struct mfld_jack_data jack_data;
if (!mfld_codec)
return;
jack_data.mfld_jack = &mfld_jack;
jack_data.intr_id = intr_status;
sn95031_jack_detection(mfld_codec, &jack_data);
/* TODO: add american headset detection post gpiolib support */
}
static int mfld_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_dapm_context *dapm = &runtime->card->dapm;
int ret_val;
/* default is earpiece pin, userspace sets it explcitly */
snd_soc_dapm_disable_pin(dapm, "Headphones");
/* default is lineout NC, userspace sets it explcitly */
snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
lo_dac = 3;
hs_switch = 0;
/* we dont use linein in this so set to NC */
snd_soc_dapm_disable_pin(dapm, "LINEINL");
snd_soc_dapm_disable_pin(dapm, "LINEINR");
/* Headset and button jack detection */
ret_val = snd_soc_card_jack_new(runtime->card,
"Intel(R) MID Audio Jack", SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack,
mfld_jack_pins, ARRAY_SIZE(mfld_jack_pins));
if (ret_val) {
pr_err("jack creation failed\n");
return ret_val;
}
ret_val = snd_soc_jack_add_zones(&mfld_jack,
ARRAY_SIZE(mfld_zones), mfld_zones);
if (ret_val) {
pr_err("adding jack zones failed\n");
return ret_val;
}
mfld_codec = runtime->codec;
/* we want to check if anything is inserted at boot,
* so send a fake event to codec and it will read adc
* to find if anything is there or not */
mfld_jack_check(MFLD_JACK_INSERT);
return ret_val;
}
static struct snd_soc_dai_link mfld_msic_dailink[] = {
{
.name = "Medfield Headset",
.stream_name = "Headset",
.cpu_dai_name = "Headset-cpu-dai",
.codec_dai_name = "SN95031 Headset",
.codec_name = "sn95031",
.platform_name = "sst-platform",
.init = mfld_init,
},
{
.name = "Medfield Speaker",
.stream_name = "Speaker",
.cpu_dai_name = "Speaker-cpu-dai",
.codec_dai_name = "SN95031 Speaker",
.codec_name = "sn95031",
.platform_name = "sst-platform",
.init = NULL,
},
{
.name = "Medfield Vibra",
.stream_name = "Vibra1",
.cpu_dai_name = "Vibra1-cpu-dai",
.codec_dai_name = "SN95031 Vibra1",
.codec_name = "sn95031",
.platform_name = "sst-platform",
.init = NULL,
},
{
.name = "Medfield Haptics",
.stream_name = "Vibra2",
.cpu_dai_name = "Vibra2-cpu-dai",
.codec_dai_name = "SN95031 Vibra2",
.codec_name = "sn95031",
.platform_name = "sst-platform",
.init = NULL,
},
{
.name = "Medfield Compress",
.stream_name = "Speaker",
.cpu_dai_name = "Compress-cpu-dai",
.codec_dai_name = "SN95031 Speaker",
.codec_name = "sn95031",
.platform_name = "sst-platform",
.init = NULL,
},
};
/* SoC card */
static struct snd_soc_card snd_soc_card_mfld = {
.name = "medfield_audio",
.owner = THIS_MODULE,
.dai_link = mfld_msic_dailink,
.num_links = ARRAY_SIZE(mfld_msic_dailink),
.controls = mfld_snd_controls,
.num_controls = ARRAY_SIZE(mfld_snd_controls),
.dapm_widgets = mfld_widgets,
.num_dapm_widgets = ARRAY_SIZE(mfld_widgets),
.dapm_routes = mfld_map,
.num_dapm_routes = ARRAY_SIZE(mfld_map),
};
static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev)
{
struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev;
memcpy_fromio(&mc_private->interrupt_status,
((void *)(mc_private->int_base)),
sizeof(u8));
return IRQ_WAKE_THREAD;
}
static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
{
struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
mfld_jack_check(mc_drv_ctx->interrupt_status);
return IRQ_HANDLED;
}
static int snd_mfld_mc_probe(struct platform_device *pdev)
{
int ret_val = 0, irq;
struct mfld_mc_private *mc_drv_ctx;
struct resource *irq_mem;
pr_debug("snd_mfld_mc_probe called\n");
/* retrive the irq number */
irq = platform_get_irq(pdev, 0);
/* audio interrupt base of SRAM location where
* interrupts are stored by System FW */
mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC);
if (!mc_drv_ctx)
return -ENOMEM;
irq_mem = platform_get_resource_byname(
pdev, IORESOURCE_MEM, "IRQ_BASE");
if (!irq_mem) {
pr_err("no mem resource given\n");
return -ENODEV;
}
mc_drv_ctx->int_base = devm_ioremap_nocache(&pdev->dev, irq_mem->start,
resource_size(irq_mem));
if (!mc_drv_ctx->int_base) {
pr_err("Mapping of cache failed\n");
return -ENOMEM;
}
/* register for interrupt */
ret_val = devm_request_threaded_irq(&pdev->dev, irq,
snd_mfld_jack_intr_handler,
snd_mfld_jack_detection,
IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx);
if (ret_val) {
pr_err("cannot register IRQ\n");
return ret_val;
}
/* register the soc card */
snd_soc_card_mfld.dev = &pdev->dev;
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_mfld);
if (ret_val) {
pr_debug("snd_soc_register_card failed %d\n", ret_val);
return ret_val;
}
platform_set_drvdata(pdev, mc_drv_ctx);
pr_debug("successfully exited probe\n");
return 0;
}
static struct platform_driver snd_mfld_mc_driver = {
.driver = {
.name = "msic_audio",
},
.probe = snd_mfld_mc_probe,
};
module_platform_driver(snd_mfld_mc_driver);
MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:msic-audio");
...@@ -269,7 +269,7 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, ...@@ -269,7 +269,7 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
*/ */
timeout = jiffies + msecs_to_jiffies(time); timeout = jiffies + msecs_to_jiffies(time);
while (((sst_dsp_shim_read_unlocked(ctx, offset) & mask) != target) while ((((reg = sst_dsp_shim_read_unlocked(ctx, offset)) & mask) != target)
&& time_before(jiffies, timeout)) { && time_before(jiffies, timeout)) {
k++; k++;
if (k > 10) if (k > 10)
...@@ -278,8 +278,6 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, ...@@ -278,8 +278,6 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
usleep_range(s, 2*s); usleep_range(s, 2*s);
} }
reg = sst_dsp_shim_read_unlocked(ctx, offset);
if ((reg & mask) == target) { if ((reg & mask) == target) {
dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n", dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n",
reg, operation); reg, operation);
......
...@@ -595,7 +595,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -595,7 +595,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3);
skl->d0i3.state = SKL_DSP_D0I3_NONE; skl->d0i3.state = SKL_DSP_D0I3_NONE;
return 0; return skl_dsp_acquire_irq(sst);
} }
EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
......
...@@ -458,7 +458,7 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -458,7 +458,7 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
cnl->boot_complete = false; cnl->boot_complete = false;
init_waitqueue_head(&cnl->boot_wait); init_waitqueue_head(&cnl->boot_wait);
return 0; return skl_dsp_acquire_irq(sst);
} }
EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); EXPORT_SYMBOL_GPL(cnl_sst_dsp_init);
......
/*
* skl-i2s.h - i2s blob mapping
*
* Copyright (C) 2017 Intel Corp
* Author: Subhransu S. Prusty < subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef __SOUND_SOC_SKL_I2S_H
#define __SOUND_SOC_SKL_I2S_H
#define SKL_I2S_MAX_TIME_SLOTS 8
#define SKL_MCLK_DIV_CLK_SRC_MASK GENMASK(17, 16)
#define SKL_MNDSS_DIV_CLK_SRC_MASK GENMASK(21, 20)
#define SKL_SHIFT(x) (ffs(x) - 1)
#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0)
struct skl_i2s_config {
u32 ssc0;
u32 ssc1;
u32 sscto;
u32 sspsp;
u32 sstsa;
u32 ssrsa;
u32 ssc2;
u32 sspsp2;
u32 ssc3;
u32 ssioc;
} __packed;
struct skl_i2s_config_mclk {
u32 mdivctrl;
u32 mdivr;
};
/**
* struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway
* configuration legacy blob
*
* @gtw_attr: Gateway attribute for the I2S Gateway
* @tdm_ts_group: TDM slot mapping against channels in the Gateway.
* @i2s_cfg: I2S HW registers
* @mclk: MCLK clock source and divider values
*/
struct skl_i2s_config_blob_legacy {
u32 gtw_attr;
u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS];
struct skl_i2s_config i2s_cfg;
struct skl_i2s_config_mclk mclk;
};
#endif /* __SOUND_SOC_SKL_I2S_H */
...@@ -55,6 +55,19 @@ static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) ...@@ -55,6 +55,19 @@ static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
return 0; return 0;
} }
#define SKL_ASTATE_PARAM_ID 4
void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data)
{
struct skl_ipc_large_config_msg msg = {0};
msg.large_param_id = SKL_ASTATE_PARAM_ID;
msg.param_data_size = (cnt * sizeof(struct skl_astate_param) +
sizeof(cnt));
skl_ipc_set_large_config(&ctx->ipc, &msg, data);
}
#define NOTIFICATION_PARAM_ID 3 #define NOTIFICATION_PARAM_ID 3
#define NOTIFICATION_MASK 0xf #define NOTIFICATION_MASK 0xf
...@@ -404,11 +417,20 @@ int skl_resume_dsp(struct skl *skl) ...@@ -404,11 +417,20 @@ int skl_resume_dsp(struct skl *skl)
if (skl->skl_sst->is_first_boot == true) if (skl->skl_sst->is_first_boot == true)
return 0; return 0;
/* disable dynamic clock gating during fw and lib download */
ctx->enable_miscbdcge(ctx->dev, false);
ret = skl_dsp_wake(ctx->dsp); ret = skl_dsp_wake(ctx->dsp);
ctx->enable_miscbdcge(ctx->dev, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
skl_dsp_enable_notification(skl->skl_sst, false); skl_dsp_enable_notification(skl->skl_sst, false);
if (skl->cfg.astate_cfg != NULL) {
skl_dsp_set_astate_cfg(skl->skl_sst, skl->cfg.astate_cfg->count,
skl->cfg.astate_cfg);
}
return ret; return ret;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#include <linux/pci.h> #include <linux/pci.h>
#include "skl.h" #include "skl.h"
#include "skl-i2s.h"
#define NHLT_ACPI_HEADER_SIG "NHLT" #define NHLT_ACPI_HEADER_SIG "NHLT"
...@@ -277,3 +278,157 @@ void skl_nhlt_remove_sysfs(struct skl *skl) ...@@ -277,3 +278,157 @@ void skl_nhlt_remove_sysfs(struct skl *skl)
sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr);
} }
/*
* Queries NHLT for all the fmt configuration for a particular endpoint and
* stores all possible rates supported in a rate table for the corresponding
* sclk/sclkfs.
*/
static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks,
struct nhlt_fmt *fmt, u8 id)
{
struct skl_i2s_config_blob_legacy *i2s_config;
struct skl_clk_parent_src *parent;
struct skl_ssp_clk *sclk, *sclkfs;
struct nhlt_fmt_cfg *fmt_cfg;
struct wav_fmt_ext *wav_fmt;
unsigned long rate = 0;
bool present = false;
int rate_index = 0;
u16 channels, bps;
u8 clk_src;
int i, j;
u32 fs;
sclk = &ssp_clks[SKL_SCLK_OFS];
sclkfs = &ssp_clks[SKL_SCLKFS_OFS];
if (fmt->fmt_count == 0)
return;
for (i = 0; i < fmt->fmt_count; i++) {
fmt_cfg = &fmt->fmt_config[i];
wav_fmt = &fmt_cfg->fmt_ext;
channels = wav_fmt->fmt.channels;
bps = wav_fmt->fmt.bits_per_sample;
fs = wav_fmt->fmt.samples_per_sec;
/*
* In case of TDM configuration on a ssp, there can
* be more than one blob in which channel masks are
* different for each usecase for a specific rate and bps.
* But the sclk rate will be generated for the total
* number of channels used for that endpoint.
*
* So for the given fs and bps, choose blob which has
* the superset of all channels for that endpoint and
* derive the rate.
*/
for (j = i; j < fmt->fmt_count; j++) {
fmt_cfg = &fmt->fmt_config[j];
wav_fmt = &fmt_cfg->fmt_ext;
if ((fs == wav_fmt->fmt.samples_per_sec) &&
(bps == wav_fmt->fmt.bits_per_sample))
channels = max_t(u16, channels,
wav_fmt->fmt.channels);
}
rate = channels * bps * fs;
/* check if the rate is added already to the given SSP's sclk */
for (j = 0; (j < SKL_MAX_CLK_RATES) &&
(sclk[id].rate_cfg[j].rate != 0); j++) {
if (sclk[id].rate_cfg[j].rate == rate) {
present = true;
break;
}
}
/* Fill rate and parent for sclk/sclkfs */
if (!present) {
/* MCLK Divider Source Select */
i2s_config = (struct skl_i2s_config_blob_legacy *)
fmt->fmt_config[0].config.caps;
clk_src = ((i2s_config->mclk.mdivctrl)
& SKL_MNDSS_DIV_CLK_SRC_MASK) >>
SKL_SHIFT(SKL_MNDSS_DIV_CLK_SRC_MASK);
parent = skl_get_parent_clk(clk_src);
/*
* Do not copy the config data if there is no parent
* clock available for this clock source select
*/
if (!parent)
continue;
sclk[id].rate_cfg[rate_index].rate = rate;
sclk[id].rate_cfg[rate_index].config = fmt_cfg;
sclkfs[id].rate_cfg[rate_index].rate = rate;
sclkfs[id].rate_cfg[rate_index].config = fmt_cfg;
sclk[id].parent_name = parent->name;
sclkfs[id].parent_name = parent->name;
rate_index++;
}
}
}
static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk,
struct nhlt_fmt *fmt, u8 id)
{
struct skl_i2s_config_blob_legacy *i2s_config;
struct nhlt_specific_cfg *fmt_cfg;
struct skl_clk_parent_src *parent;
u32 clkdiv, div_ratio;
u8 clk_src;
fmt_cfg = &fmt->fmt_config[0].config;
i2s_config = (struct skl_i2s_config_blob_legacy *)fmt_cfg->caps;
/* MCLK Divider Source Select */
clk_src = ((i2s_config->mclk.mdivctrl) & SKL_MCLK_DIV_CLK_SRC_MASK) >>
SKL_SHIFT(SKL_MCLK_DIV_CLK_SRC_MASK);
clkdiv = i2s_config->mclk.mdivr & SKL_MCLK_DIV_RATIO_MASK;
/* bypass divider */
div_ratio = 1;
if (clkdiv != SKL_MCLK_DIV_RATIO_MASK)
/* Divider is 2 + clkdiv */
div_ratio = clkdiv + 2;
/* Calculate MCLK rate from source using div value */
parent = skl_get_parent_clk(clk_src);
if (!parent)
return;
mclk[id].rate_cfg[0].rate = parent->rate/div_ratio;
mclk[id].rate_cfg[0].config = &fmt->fmt_config[0];
mclk[id].parent_name = parent->name;
}
void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks)
{
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
struct nhlt_endpoint *epnt;
struct nhlt_fmt *fmt;
int i;
u8 id;
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (i = 0; i < nhlt->endpoint_count; i++) {
if (epnt->linktype == NHLT_LINK_SSP) {
id = epnt->virtual_bus_id;
fmt = (struct nhlt_fmt *)(epnt->config.caps
+ epnt->config.size);
skl_get_ssp_clks(skl, ssp_clks, fmt, id);
skl_get_mclk(skl, ssp_clks, fmt, id);
}
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
}
...@@ -537,7 +537,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, ...@@ -537,7 +537,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); link = snd_hdac_ext_bus_get_link(ebus, codec_dai->component->name);
if (!link) if (!link)
return -EINVAL; return -EINVAL;
...@@ -620,7 +620,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, ...@@ -620,7 +620,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
link_dev->link_prepared = 0; link_dev->link_prepared = 0;
link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name); link = snd_hdac_ext_bus_get_link(ebus, rtd->codec_dai->component->name);
if (!link) if (!link)
return -EINVAL; return -EINVAL;
...@@ -1343,7 +1343,11 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) ...@@ -1343,7 +1343,11 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
return -EIO; return -EIO;
} }
/* disable dynamic clock gating during fw and lib download */
skl->skl_sst->enable_miscbdcge(platform->dev, false);
ret = ops->init_fw(platform->dev, skl->skl_sst); ret = ops->init_fw(platform->dev, skl->skl_sst);
skl->skl_sst->enable_miscbdcge(platform->dev, true);
if (ret < 0) { if (ret < 0) {
dev_err(platform->dev, "Failed to boot first fw: %d\n", ret); dev_err(platform->dev, "Failed to boot first fw: %d\n", ret);
return ret; return ret;
...@@ -1351,6 +1355,12 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) ...@@ -1351,6 +1355,12 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
skl_populate_modules(skl); skl_populate_modules(skl);
skl->skl_sst->update_d0i3c = skl_update_d0i3c; skl->skl_sst->update_d0i3c = skl_update_d0i3c;
skl_dsp_enable_notification(skl->skl_sst, false); skl_dsp_enable_notification(skl->skl_sst, false);
if (skl->cfg.astate_cfg != NULL) {
skl_dsp_set_astate_cfg(skl->skl_sst,
skl->cfg.astate_cfg->count,
skl->cfg.astate_cfg);
}
} }
pm_runtime_mark_last_busy(platform->dev); pm_runtime_mark_last_busy(platform->dev);
pm_runtime_put_autosuspend(platform->dev); pm_runtime_put_autosuspend(platform->dev);
......
/*
* skl-ssp-clk.h - Skylake ssp clock information and ipc structure
*
* Copyright (C) 2017 Intel Corp
* Author: Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>
* Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef SOUND_SOC_SKL_SSP_CLK_H
#define SOUND_SOC_SKL_SSP_CLK_H
#define SKL_MAX_SSP 6
/* xtal/cardinal/pll, parent of ssp clocks and mclk */
#define SKL_MAX_CLK_SRC 3
#define SKL_MAX_SSP_CLK_TYPES 3 /* mclk, sclk, sclkfs */
#define SKL_MAX_CLK_CNT (SKL_MAX_SSP * SKL_MAX_SSP_CLK_TYPES)
/* Max number of configurations supported for each clock */
#define SKL_MAX_CLK_RATES 10
#define SKL_SCLK_OFS SKL_MAX_SSP
#define SKL_SCLKFS_OFS (SKL_SCLK_OFS + SKL_MAX_SSP)
enum skl_clk_type {
SKL_MCLK,
SKL_SCLK,
SKL_SCLK_FS,
};
enum skl_clk_src_type {
SKL_XTAL,
SKL_CARDINAL,
SKL_PLL,
};
struct skl_clk_parent_src {
u8 clk_id;
const char *name;
unsigned long rate;
const char *parent_name;
};
struct skl_clk_rate_cfg_table {
unsigned long rate;
void *config;
};
/*
* rate for mclk will be in rates[0]. For sclk and sclkfs, rates[] store
* all possible clocks ssp can generate for that platform.
*/
struct skl_ssp_clk {
const char *name;
const char *parent_name;
struct skl_clk_rate_cfg_table rate_cfg[SKL_MAX_CLK_RATES];
};
struct skl_clk_pdata {
struct skl_clk_parent_src *parent_clks;
int num_clks;
struct skl_ssp_clk *ssp_clks;
void *pvt_data;
};
#endif /* SOUND_SOC_SKL_SSP_CLK_H */
...@@ -435,16 +435,22 @@ struct sst_dsp *skl_dsp_ctx_init(struct device *dev, ...@@ -435,16 +435,22 @@ struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
return NULL; return NULL;
} }
return sst;
}
int skl_dsp_acquire_irq(struct sst_dsp *sst)
{
struct sst_dsp_device *sst_dev = sst->sst_dev;
int ret;
/* Register the ISR */ /* Register the ISR */
ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
if (ret) { if (ret)
dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
sst->irq); sst->irq);
return NULL;
}
return sst; return ret;
} }
void skl_dsp_free(struct sst_dsp *dsp) void skl_dsp_free(struct sst_dsp *dsp)
......
...@@ -206,6 +206,7 @@ int skl_cldma_wait_interruptible(struct sst_dsp *ctx); ...@@ -206,6 +206,7 @@ int skl_cldma_wait_interruptible(struct sst_dsp *ctx);
void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
struct sst_dsp_device *sst_dev, int irq); struct sst_dsp_device *sst_dev, int irq);
int skl_dsp_acquire_irq(struct sst_dsp *sst);
bool is_skl_dsp_running(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx);
unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx); unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx);
...@@ -251,6 +252,9 @@ void skl_freeup_uuid_list(struct skl_sst *ctx); ...@@ -251,6 +252,9 @@ void skl_freeup_uuid_list(struct skl_sst *ctx);
int skl_dsp_strip_extended_manifest(struct firmware *fw); int skl_dsp_strip_extended_manifest(struct firmware *fw);
void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable); void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable);
void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data);
int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name,
struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp,
struct sst_dsp_device *skl_dev); struct sst_dsp_device *skl_dev);
......
...@@ -178,7 +178,8 @@ static inline int skl_pvtid_128(struct uuid_module *module) ...@@ -178,7 +178,8 @@ static inline int skl_pvtid_128(struct uuid_module *module)
* skl_get_pvt_id: generate a private id for use as module id * skl_get_pvt_id: generate a private id for use as module id
* *
* @ctx: driver context * @ctx: driver context
* @mconfig: module configuration data * @uuid_mod: module's uuid
* @instance_id: module's instance id
* *
* This generates a 128 bit private unique id for a module TYPE so that * This generates a 128 bit private unique id for a module TYPE so that
* module instance is unique * module instance is unique
...@@ -208,7 +209,8 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id); ...@@ -208,7 +209,8 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id);
* skl_put_pvt_id: free up the private id allocated * skl_put_pvt_id: free up the private id allocated
* *
* @ctx: driver context * @ctx: driver context
* @mconfig: module configuration data * @uuid_mod: module's uuid
* @pvt_id: module pvt id
* *
* This frees a 128 bit private unique id previously generated * This frees a 128 bit private unique id previously generated
*/ */
......
...@@ -569,7 +569,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -569,7 +569,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst->fw_ops = skl_fw_ops; sst->fw_ops = skl_fw_ops;
return 0; return skl_dsp_acquire_irq(sst);
} }
EXPORT_SYMBOL_GPL(skl_sst_dsp_init); EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
......
...@@ -190,7 +190,6 @@ skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) ...@@ -190,7 +190,6 @@ skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig)
u8 res_idx = mconfig->res_idx; u8 res_idx = mconfig->res_idx;
struct skl_module_res *res = &mconfig->module->resources[res_idx]; struct skl_module_res *res = &mconfig->module->resources[res_idx];
res = &mconfig->module->resources[res_idx];
skl->resource.mcps -= res->cps; skl->resource.mcps -= res->cps;
} }
...@@ -3056,11 +3055,13 @@ static int skl_tplg_get_int_tkn(struct device *dev, ...@@ -3056,11 +3055,13 @@ static int skl_tplg_get_int_tkn(struct device *dev,
struct snd_soc_tplg_vendor_value_elem *tkn_elem, struct snd_soc_tplg_vendor_value_elem *tkn_elem,
struct skl *skl) struct skl *skl)
{ {
int tkn_count = 0, ret; int tkn_count = 0, ret, size;
static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx;
struct skl_module_res *res = NULL; struct skl_module_res *res = NULL;
struct skl_module_iface *fmt = NULL; struct skl_module_iface *fmt = NULL;
struct skl_module *mod = NULL; struct skl_module *mod = NULL;
static struct skl_astate_param *astate_table;
static int astate_cfg_idx, count;
int i; int i;
if (skl->modules) { if (skl->modules) {
...@@ -3093,6 +3094,46 @@ static int skl_tplg_get_int_tkn(struct device *dev, ...@@ -3093,6 +3094,46 @@ static int skl_tplg_get_int_tkn(struct device *dev,
mod_idx = tkn_elem->value; mod_idx = tkn_elem->value;
break; break;
case SKL_TKN_U32_ASTATE_COUNT:
if (astate_table != NULL) {
dev_err(dev, "More than one entry for A-State count");
return -EINVAL;
}
if (tkn_elem->value > SKL_MAX_ASTATE_CFG) {
dev_err(dev, "Invalid A-State count %d\n",
tkn_elem->value);
return -EINVAL;
}
size = tkn_elem->value * sizeof(struct skl_astate_param) +
sizeof(count);
skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL);
if (!skl->cfg.astate_cfg)
return -ENOMEM;
astate_table = skl->cfg.astate_cfg->astate_table;
count = skl->cfg.astate_cfg->count = tkn_elem->value;
break;
case SKL_TKN_U32_ASTATE_IDX:
if (tkn_elem->value >= count) {
dev_err(dev, "Invalid A-State index %d\n",
tkn_elem->value);
return -EINVAL;
}
astate_cfg_idx = tkn_elem->value;
break;
case SKL_TKN_U32_ASTATE_KCPS:
astate_table[astate_cfg_idx].kcps = tkn_elem->value;
break;
case SKL_TKN_U32_ASTATE_CLK_SRC:
astate_table[astate_cfg_idx].clk_src = tkn_elem->value;
break;
case SKL_TKN_U8_IN_PIN_TYPE: case SKL_TKN_U8_IN_PIN_TYPE:
case SKL_TKN_U8_OUT_PIN_TYPE: case SKL_TKN_U8_OUT_PIN_TYPE:
case SKL_TKN_U8_IN_QUEUE_COUNT: case SKL_TKN_U8_IN_QUEUE_COUNT:
......
...@@ -355,6 +355,7 @@ static int skl_resume(struct device *dev) ...@@ -355,6 +355,7 @@ static int skl_resume(struct device *dev)
if (ebus->cmd_dma_state) if (ebus->cmd_dma_state)
snd_hdac_bus_init_cmd_io(&ebus->bus); snd_hdac_bus_init_cmd_io(&ebus->bus);
ret = 0;
} else { } else {
ret = _skl_resume(ebus); ret = _skl_resume(ebus);
...@@ -435,19 +436,51 @@ static int skl_free(struct hdac_ext_bus *ebus) ...@@ -435,19 +436,51 @@ static int skl_free(struct hdac_ext_bus *ebus)
return 0; return 0;
} }
static int skl_machine_device_register(struct skl *skl, void *driver_data) /*
* For each ssp there are 3 clocks (mclk/sclk/sclkfs).
* e.g. for ssp0, clocks will be named as
* "ssp0_mclk", "ssp0_sclk", "ssp0_sclkfs"
* So for skl+, there are 6 ssps, so 18 clocks will be created.
*/
static struct skl_ssp_clk skl_ssp_clks[] = {
{.name = "ssp0_mclk"}, {.name = "ssp1_mclk"}, {.name = "ssp2_mclk"},
{.name = "ssp3_mclk"}, {.name = "ssp4_mclk"}, {.name = "ssp5_mclk"},
{.name = "ssp0_sclk"}, {.name = "ssp1_sclk"}, {.name = "ssp2_sclk"},
{.name = "ssp3_sclk"}, {.name = "ssp4_sclk"}, {.name = "ssp5_sclk"},
{.name = "ssp0_sclkfs"}, {.name = "ssp1_sclkfs"},
{.name = "ssp2_sclkfs"},
{.name = "ssp3_sclkfs"}, {.name = "ssp4_sclkfs"},
{.name = "ssp5_sclkfs"},
};
static int skl_find_machine(struct skl *skl, void *driver_data)
{ {
struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
struct platform_device *pdev;
struct snd_soc_acpi_mach *mach = driver_data; struct snd_soc_acpi_mach *mach = driver_data;
int ret; struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
struct skl_machine_pdata *pdata;
mach = snd_soc_acpi_find_machine(mach); mach = snd_soc_acpi_find_machine(mach);
if (mach == NULL) { if (mach == NULL) {
dev_err(bus->dev, "No matching machine driver found\n"); dev_err(bus->dev, "No matching machine driver found\n");
return -ENODEV; return -ENODEV;
} }
skl->mach = mach;
skl->fw_name = mach->fw_filename; skl->fw_name = mach->fw_filename;
pdata = skl->mach->pdata;
if (mach->pdata)
skl->use_tplg_pcm = pdata->use_tplg_pcm;
return 0;
}
static int skl_machine_device_register(struct skl *skl)
{
struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
struct snd_soc_acpi_mach *mach = skl->mach;
struct platform_device *pdev;
int ret;
pdev = platform_device_alloc(mach->drv_name, -1); pdev = platform_device_alloc(mach->drv_name, -1);
if (pdev == NULL) { if (pdev == NULL) {
...@@ -462,11 +495,8 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data) ...@@ -462,11 +495,8 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data)
return -EIO; return -EIO;
} }
if (mach->pdata) { if (mach->pdata)
skl->use_tplg_pcm =
((struct skl_machine_pdata *)mach->pdata)->use_tplg_pcm;
dev_set_drvdata(&pdev->dev, mach->pdata); dev_set_drvdata(&pdev->dev, mach->pdata);
}
skl->i2s_dev = pdev; skl->i2s_dev = pdev;
...@@ -509,6 +539,74 @@ static void skl_dmic_device_unregister(struct skl *skl) ...@@ -509,6 +539,74 @@ static void skl_dmic_device_unregister(struct skl *skl)
platform_device_unregister(skl->dmic_dev); platform_device_unregister(skl->dmic_dev);
} }
static struct skl_clk_parent_src skl_clk_src[] = {
{ .clk_id = SKL_XTAL, .name = "xtal" },
{ .clk_id = SKL_CARDINAL, .name = "cardinal", .rate = 24576000 },
{ .clk_id = SKL_PLL, .name = "pll", .rate = 96000000 },
};
struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(skl_clk_src); i++) {
if (skl_clk_src[i].clk_id == clk_id)
return &skl_clk_src[i];
}
return NULL;
}
static void init_skl_xtal_rate(int pci_id)
{
switch (pci_id) {
case 0x9d70:
case 0x9d71:
skl_clk_src[0].rate = 24000000;
return;
default:
skl_clk_src[0].rate = 19200000;
return;
}
}
static int skl_clock_device_register(struct skl *skl)
{
struct platform_device_info pdevinfo = {NULL};
struct skl_clk_pdata *clk_pdata;
clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata),
GFP_KERNEL);
if (!clk_pdata)
return -ENOMEM;
init_skl_xtal_rate(skl->pci->device);
clk_pdata->parent_clks = skl_clk_src;
clk_pdata->ssp_clks = skl_ssp_clks;
clk_pdata->num_clks = ARRAY_SIZE(skl_ssp_clks);
/* Query NHLT to fill the rates and parent */
skl_get_clks(skl, clk_pdata->ssp_clks);
clk_pdata->pvt_data = skl;
/* Register Platform device */
pdevinfo.parent = &skl->pci->dev;
pdevinfo.id = -1;
pdevinfo.name = "skl-ssp-clk";
pdevinfo.data = clk_pdata;
pdevinfo.size_data = sizeof(*clk_pdata);
skl->clk_dev = platform_device_register_full(&pdevinfo);
return PTR_ERR_OR_ZERO(skl->clk_dev);
}
static void skl_clock_device_unregister(struct skl *skl)
{
if (skl->clk_dev)
platform_device_unregister(skl->clk_dev);
}
/* /*
* Probe the given codec address * Probe the given codec address
*/ */
...@@ -615,18 +713,30 @@ static void skl_probe_work(struct work_struct *work) ...@@ -615,18 +713,30 @@ static void skl_probe_work(struct work_struct *work)
/* create codec instances */ /* create codec instances */
skl_codec_create(ebus); skl_codec_create(ebus);
/* register platform dai and controls */
err = skl_platform_register(bus->dev);
if (err < 0) {
dev_err(bus->dev, "platform register failed: %d\n", err);
return;
}
if (bus->ppcap) {
err = skl_machine_device_register(skl);
if (err < 0) {
dev_err(bus->dev, "machine register failed: %d\n", err);
goto out_err;
}
}
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = snd_hdac_display_power(bus, false); err = snd_hdac_display_power(bus, false);
if (err < 0) { if (err < 0) {
dev_err(bus->dev, "Cannot turn off display power on i915\n"); dev_err(bus->dev, "Cannot turn off display power on i915\n");
skl_machine_device_unregister(skl);
return; return;
} }
} }
/* register platform dai and controls */
err = skl_platform_register(bus->dev);
if (err < 0)
return;
/* /*
* we are done probing so decrement link counts * we are done probing so decrement link counts
*/ */
...@@ -791,18 +901,21 @@ static int skl_probe(struct pci_dev *pci, ...@@ -791,18 +901,21 @@ static int skl_probe(struct pci_dev *pci,
/* check if dsp is there */ /* check if dsp is there */
if (bus->ppcap) { if (bus->ppcap) {
err = skl_machine_device_register(skl, /* create device for dsp clk */
(void *)pci_id->driver_data); err = skl_clock_device_register(skl);
if (err < 0)
goto out_clk_free;
err = skl_find_machine(skl, (void *)pci_id->driver_data);
if (err < 0) if (err < 0)
goto out_nhlt_free; goto out_nhlt_free;
err = skl_init_dsp(skl); err = skl_init_dsp(skl);
if (err < 0) { if (err < 0) {
dev_dbg(bus->dev, "error failed to register dsp\n"); dev_dbg(bus->dev, "error failed to register dsp\n");
goto out_mach_free; goto out_nhlt_free;
} }
skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge; skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
} }
if (bus->mlcap) if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(ebus); snd_hdac_ext_bus_get_ml_capabilities(ebus);
...@@ -820,8 +933,8 @@ static int skl_probe(struct pci_dev *pci, ...@@ -820,8 +933,8 @@ static int skl_probe(struct pci_dev *pci,
out_dsp_free: out_dsp_free:
skl_free_dsp(skl); skl_free_dsp(skl);
out_mach_free: out_clk_free:
skl_machine_device_unregister(skl); skl_clock_device_unregister(skl);
out_nhlt_free: out_nhlt_free:
skl_nhlt_free(skl->nhlt); skl_nhlt_free(skl->nhlt);
out_free: out_free:
...@@ -872,6 +985,7 @@ static void skl_remove(struct pci_dev *pci) ...@@ -872,6 +985,7 @@ static void skl_remove(struct pci_dev *pci)
skl_free_dsp(skl); skl_free_dsp(skl);
skl_machine_device_unregister(skl); skl_machine_device_unregister(skl);
skl_dmic_device_unregister(skl); skl_dmic_device_unregister(skl);
skl_clock_device_unregister(skl);
skl_nhlt_remove_sysfs(skl); skl_nhlt_remove_sysfs(skl);
skl_nhlt_free(skl->nhlt); skl_nhlt_free(skl->nhlt);
skl_free(ebus); skl_free(ebus);
......
...@@ -25,9 +25,12 @@ ...@@ -25,9 +25,12 @@
#include <sound/hdaudio_ext.h> #include <sound/hdaudio_ext.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "skl-nhlt.h" #include "skl-nhlt.h"
#include "skl-ssp-clk.h"
#define SKL_SUSPEND_DELAY 2000 #define SKL_SUSPEND_DELAY 2000
#define SKL_MAX_ASTATE_CFG 3
#define AZX_PCIREG_PGCTL 0x44 #define AZX_PCIREG_PGCTL 0x44
#define AZX_PGCTL_LSRMD_MASK (1 << 4) #define AZX_PGCTL_LSRMD_MASK (1 << 4)
#define AZX_PCIREG_CGCTL 0x48 #define AZX_PCIREG_CGCTL 0x48
...@@ -45,6 +48,20 @@ struct skl_dsp_resource { ...@@ -45,6 +48,20 @@ struct skl_dsp_resource {
struct skl_debug; struct skl_debug;
struct skl_astate_param {
u32 kcps;
u32 clk_src;
};
struct skl_astate_config {
u32 count;
struct skl_astate_param astate_table[0];
};
struct skl_fw_config {
struct skl_astate_config *astate_cfg;
};
struct skl { struct skl {
struct hdac_ext_bus ebus; struct hdac_ext_bus ebus;
struct pci_dev *pci; struct pci_dev *pci;
...@@ -52,6 +69,7 @@ struct skl { ...@@ -52,6 +69,7 @@ struct skl {
unsigned int init_done:1; /* delayed init status */ unsigned int init_done:1; /* delayed init status */
struct platform_device *dmic_dev; struct platform_device *dmic_dev;
struct platform_device *i2s_dev; struct platform_device *i2s_dev;
struct platform_device *clk_dev;
struct snd_soc_platform *platform; struct snd_soc_platform *platform;
struct snd_soc_dai_driver *dais; struct snd_soc_dai_driver *dais;
...@@ -75,6 +93,8 @@ struct skl { ...@@ -75,6 +93,8 @@ struct skl {
u8 nr_modules; u8 nr_modules;
struct skl_module **modules; struct skl_module **modules;
bool use_tplg_pcm; bool use_tplg_pcm;
struct skl_fw_config cfg;
struct snd_soc_acpi_mach *mach;
}; };
#define skl_to_ebus(s) (&(s)->ebus) #define skl_to_ebus(s) (&(s)->ebus)
...@@ -125,6 +145,8 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); ...@@ -125,6 +145,8 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id);
void skl_update_d0i3c(struct device *dev, bool enable); void skl_update_d0i3c(struct device *dev, bool enable);
int skl_nhlt_create_sysfs(struct skl *skl); int skl_nhlt_create_sysfs(struct skl *skl);
void skl_nhlt_remove_sysfs(struct skl *skl); void skl_nhlt_remove_sysfs(struct skl *skl);
void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks);
struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id);
struct skl_module_cfg; struct skl_module_cfg;
......
...@@ -16,74 +16,13 @@ ...@@ -16,74 +16,13 @@
#include <sound/soc-acpi.h> #include <sound/soc-acpi.h>
static acpi_status snd_soc_acpi_find_name(acpi_handle handle, u32 level,
void *context, void **ret)
{
struct acpi_device *adev;
const char *name = NULL;
if (acpi_bus_get_device(handle, &adev))
return AE_OK;
if (adev->status.present && adev->status.functional) {
name = acpi_dev_name(adev);
*(const char **)ret = name;
return AE_CTRL_TERMINATE;
}
return AE_OK;
}
const char *snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
{
const char *name = NULL;
acpi_status status;
status = acpi_get_devices(hid, snd_soc_acpi_find_name, NULL,
(void **)&name);
if (ACPI_FAILURE(status) || name[0] == '\0')
return NULL;
return name;
}
EXPORT_SYMBOL_GPL(snd_soc_acpi_find_name_from_hid);
static acpi_status snd_soc_acpi_mach_match(acpi_handle handle, u32 level,
void *context, void **ret)
{
unsigned long long sta;
acpi_status status;
*(bool *)context = true;
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
*(bool *)context = false;
return AE_OK;
}
bool snd_soc_acpi_check_hid(const u8 hid[ACPI_ID_LEN])
{
acpi_status status;
bool found = false;
status = acpi_get_devices(hid, snd_soc_acpi_mach_match, &found, NULL);
if (ACPI_FAILURE(status))
return false;
return found;
}
EXPORT_SYMBOL_GPL(snd_soc_acpi_check_hid);
struct snd_soc_acpi_mach * struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines) snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
{ {
struct snd_soc_acpi_mach *mach; struct snd_soc_acpi_mach *mach;
for (mach = machines; mach->id[0]; mach++) { for (mach = machines; mach->id[0]; mach++) {
if (snd_soc_acpi_check_hid(mach->id) == true) { if (acpi_dev_present(mach->id, NULL, -1)) {
if (mach->machine_quirk) if (mach->machine_quirk)
mach = mach->machine_quirk(mach); mach = mach->machine_quirk(mach);
return mach; return mach;
...@@ -161,7 +100,7 @@ struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) ...@@ -161,7 +100,7 @@ struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
return mach; return mach;
for (i = 0; i < codec_list->num_codecs; i++) { for (i = 0; i < codec_list->num_codecs; i++) {
if (snd_soc_acpi_check_hid(codec_list->codecs[i]) != true) if (!acpi_dev_present(codec_list->codecs[i], NULL, -1))
return NULL; return NULL;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册