Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
This commit is contained in:
Коммит
460f623a6e
|
@ -163,8 +163,71 @@
|
||||||
*
|
*
|
||||||
* %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec
|
* %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec
|
||||||
*
|
*
|
||||||
|
* %SKL_TKN_U32_PIPE_DIR: Specifies pipe direction. Can be
|
||||||
|
* playback/capture.
|
||||||
|
*
|
||||||
|
* %SKL_TKN_U32_NUM_CONFIGS: Number of pipe configs
|
||||||
|
*
|
||||||
|
* %SKL_TKN_U32_PATH_MEM_PGS: Size of memory (in pages) required for pipeline
|
||||||
|
* and its data
|
||||||
|
*
|
||||||
|
* %SKL_TKN_U32_PIPE_CONFIG_ID: Config id for the modules in the pipe
|
||||||
|
* and PCM params supported by that pipe
|
||||||
|
* config. This is used as index to fill
|
||||||
|
* up the pipe config and module config
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* %SKL_TKN_U32_CFG_FREQ:
|
||||||
|
* %SKL_TKN_U8_CFG_CHAN:
|
||||||
|
* %SKL_TKN_U8_CFG_BPS: PCM params (freq, channels, bits per sample)
|
||||||
|
* supported for each of the pipe configs.
|
||||||
|
*
|
||||||
|
* %SKL_TKN_CFG_MOD_RES_ID: Module's resource index for each of the
|
||||||
|
* pipe config
|
||||||
|
*
|
||||||
|
* %SKL_TKN_CFG_MOD_FMT_ID: Module's interface index for each of the
|
||||||
|
* pipe config
|
||||||
|
*
|
||||||
|
* %SKL_TKN_U8_NUM_MOD: Number of modules in the manifest
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U8_MOD_IDX: Current index of the module in the manifest
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U8_NUM_RES: Number of resources for the module
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U8_NUM_INTF: Number of interfaces for the module
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_RES_ID: Resource index for the resource info to
|
||||||
|
* be filled into.
|
||||||
|
* A module can support multiple resource
|
||||||
|
* configuration and is represnted as a
|
||||||
|
* resource table. This index is used to
|
||||||
|
* fill information into appropriate index.
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_CPS: DSP cycles per second
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_DMA_SIZE: Allocated buffer size for gateway DMA
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_CPC: DSP cycles allocated per frame
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_RES_PIN_ID: Resource pin index in the module
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_INTF_PIN_ID: Interface index in the module
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_PIN_BUF: Buffer size of the module pin
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_FMT_ID: Format index for each of the interface/
|
||||||
|
* format information to be filled into.
|
||||||
|
*
|
||||||
|
* %SKL_TKN_MM_U32_NUM_IN_FMT: Number of input formats
|
||||||
|
* %SKL_TKN_MM_U32_NUM_OUT_FMT: Number of output formats
|
||||||
|
*
|
||||||
* 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
|
||||||
|
*
|
||||||
|
* Tokens defined can be used either in the manifest or widget private data.
|
||||||
|
*
|
||||||
|
* SKL_TKN_MM is used as a suffix for all tokens that represent
|
||||||
|
* module data in the manifest.
|
||||||
*/
|
*/
|
||||||
enum SKL_TKNS {
|
enum SKL_TKNS {
|
||||||
SKL_TKN_UUID = 1,
|
SKL_TKN_UUID = 1,
|
||||||
|
@ -218,7 +281,34 @@ enum SKL_TKNS {
|
||||||
SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */
|
SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */
|
||||||
SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS,
|
SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS,
|
||||||
SKL_TKN_U32_DMA_BUF_SIZE,
|
SKL_TKN_U32_DMA_BUF_SIZE,
|
||||||
SKL_TKN_MAX = SKL_TKN_U32_DMA_BUF_SIZE,
|
|
||||||
|
SKL_TKN_U32_PIPE_DIRECTION,
|
||||||
|
SKL_TKN_U32_PIPE_CONFIG_ID,
|
||||||
|
SKL_TKN_U32_NUM_CONFIGS,
|
||||||
|
SKL_TKN_U32_PATH_MEM_PGS,
|
||||||
|
|
||||||
|
SKL_TKN_U32_CFG_FREQ,
|
||||||
|
SKL_TKN_U8_CFG_CHAN,
|
||||||
|
SKL_TKN_U8_CFG_BPS,
|
||||||
|
SKL_TKN_CFG_MOD_RES_ID,
|
||||||
|
SKL_TKN_CFG_MOD_FMT_ID,
|
||||||
|
SKL_TKN_U8_NUM_MOD,
|
||||||
|
|
||||||
|
SKL_TKN_MM_U8_MOD_IDX,
|
||||||
|
SKL_TKN_MM_U8_NUM_RES,
|
||||||
|
SKL_TKN_MM_U8_NUM_INTF,
|
||||||
|
SKL_TKN_MM_U32_RES_ID,
|
||||||
|
SKL_TKN_MM_U32_CPS,
|
||||||
|
SKL_TKN_MM_U32_DMA_SIZE,
|
||||||
|
SKL_TKN_MM_U32_CPC,
|
||||||
|
SKL_TKN_MM_U32_RES_PIN_ID,
|
||||||
|
SKL_TKN_MM_U32_INTF_PIN_ID,
|
||||||
|
SKL_TKN_MM_U32_PIN_BUF,
|
||||||
|
SKL_TKN_MM_U32_FMT_ID,
|
||||||
|
SKL_TKN_MM_U32_NUM_IN_FMT,
|
||||||
|
SKL_TKN_MM_U32_NUM_OUT_FMT,
|
||||||
|
|
||||||
|
SKL_TKN_MAX = SKL_TKN_MM_U32_NUM_OUT_FMT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -321,6 +321,7 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
|
obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
|
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o
|
obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o
|
||||||
|
obj-$(CONFIG_SND_SOC_MAX98371) += snd-soc-max98371.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o
|
obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
|
obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
|
||||||
obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
|
obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
|
||||||
|
|
|
@ -121,6 +121,10 @@ struct hdac_hdmi_dai_port_map {
|
||||||
struct hdac_hdmi_cvt *cvt;
|
struct hdac_hdmi_cvt *cvt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hdac_hdmi_drv_data {
|
||||||
|
unsigned int vendor_nid;
|
||||||
|
};
|
||||||
|
|
||||||
struct hdac_hdmi_priv {
|
struct hdac_hdmi_priv {
|
||||||
struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
|
struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS];
|
||||||
struct list_head pin_list;
|
struct list_head pin_list;
|
||||||
|
@ -131,6 +135,7 @@ struct hdac_hdmi_priv {
|
||||||
int num_ports;
|
int num_ports;
|
||||||
struct mutex pin_mutex;
|
struct mutex pin_mutex;
|
||||||
struct hdac_chmap chmap;
|
struct hdac_chmap chmap;
|
||||||
|
struct hdac_hdmi_drv_data *drv_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hdac_hdmi_pcm *
|
static struct hdac_hdmi_pcm *
|
||||||
|
@ -1321,6 +1326,7 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INTEL_VENDOR_NID 0x08
|
#define INTEL_VENDOR_NID 0x08
|
||||||
|
#define INTEL_GLK_VENDOR_NID 0x0b
|
||||||
#define INTEL_GET_VENDOR_VERB 0xf81
|
#define INTEL_GET_VENDOR_VERB 0xf81
|
||||||
#define INTEL_SET_VENDOR_VERB 0x781
|
#define INTEL_SET_VENDOR_VERB 0x781
|
||||||
#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
|
#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
|
||||||
|
@ -1329,14 +1335,17 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
|
||||||
static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
|
static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
|
||||||
{
|
{
|
||||||
unsigned int vendor_param;
|
unsigned int vendor_param;
|
||||||
|
struct hdac_ext_device *edev = to_ehdac_device(hdac);
|
||||||
|
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||||
|
unsigned int vendor_nid = hdmi->drv_data->vendor_nid;
|
||||||
|
|
||||||
vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
|
vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0,
|
||||||
INTEL_GET_VENDOR_VERB, 0);
|
INTEL_GET_VENDOR_VERB, 0);
|
||||||
if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
|
if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vendor_param |= INTEL_EN_ALL_PIN_CVTS;
|
vendor_param |= INTEL_EN_ALL_PIN_CVTS;
|
||||||
vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
|
vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0,
|
||||||
INTEL_SET_VENDOR_VERB, vendor_param);
|
INTEL_SET_VENDOR_VERB, vendor_param);
|
||||||
if (vendor_param == -1)
|
if (vendor_param == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -1345,15 +1354,18 @@ static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
|
||||||
static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
|
static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
|
||||||
{
|
{
|
||||||
unsigned int vendor_param;
|
unsigned int vendor_param;
|
||||||
|
struct hdac_ext_device *edev = to_ehdac_device(hdac);
|
||||||
|
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||||
|
unsigned int vendor_nid = hdmi->drv_data->vendor_nid;
|
||||||
|
|
||||||
vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
|
vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0,
|
||||||
INTEL_GET_VENDOR_VERB, 0);
|
INTEL_GET_VENDOR_VERB, 0);
|
||||||
if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
|
if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* enable DP1.2 mode */
|
/* enable DP1.2 mode */
|
||||||
vendor_param |= INTEL_EN_DP12;
|
vendor_param |= INTEL_EN_DP12;
|
||||||
vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
|
vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0,
|
||||||
INTEL_SET_VENDOR_VERB, vendor_param);
|
INTEL_SET_VENDOR_VERB, vendor_param);
|
||||||
if (vendor_param == -1)
|
if (vendor_param == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -1927,6 +1939,14 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
|
||||||
return port->eld.info.spk_alloc;
|
return port->eld.info.spk_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct hdac_hdmi_drv_data intel_glk_drv_data = {
|
||||||
|
.vendor_nid = INTEL_GLK_VENDOR_NID,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct hdac_hdmi_drv_data intel_drv_data = {
|
||||||
|
.vendor_nid = INTEL_VENDOR_NID,
|
||||||
|
};
|
||||||
|
|
||||||
static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
||||||
{
|
{
|
||||||
struct hdac_device *codec = &edev->hdac;
|
struct hdac_device *codec = &edev->hdac;
|
||||||
|
@ -1935,6 +1955,8 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
||||||
struct hdac_ext_link *hlink = NULL;
|
struct hdac_ext_link *hlink = NULL;
|
||||||
int num_dais = 0;
|
int num_dais = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct hdac_driver *hdrv = drv_to_hdac_driver(codec->dev.driver);
|
||||||
|
const struct hda_device_id *hdac_id = hdac_get_device_id(codec, hdrv);
|
||||||
|
|
||||||
/* hold the ref while we probe */
|
/* hold the ref while we probe */
|
||||||
hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
|
hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
|
||||||
|
@ -1956,6 +1978,12 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
|
||||||
hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached;
|
hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached;
|
||||||
hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc;
|
hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc;
|
||||||
|
|
||||||
|
if (hdac_id->driver_data)
|
||||||
|
hdmi_priv->drv_data =
|
||||||
|
(struct hdac_hdmi_drv_data *)hdac_id->driver_data;
|
||||||
|
else
|
||||||
|
hdmi_priv->drv_data = &intel_drv_data;
|
||||||
|
|
||||||
dev_set_drvdata(&codec->dev, edev);
|
dev_set_drvdata(&codec->dev, edev);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&hdmi_priv->pin_list);
|
INIT_LIST_HEAD(&hdmi_priv->pin_list);
|
||||||
|
@ -2127,7 +2155,8 @@ static const struct hda_device_id hdmi_list[] = {
|
||||||
HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
|
HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
|
||||||
HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
|
HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
|
||||||
HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0),
|
HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0),
|
||||||
HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI", 0),
|
HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI",
|
||||||
|
&intel_glk_drv_data),
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -349,12 +349,14 @@ static struct snd_soc_dai_driver max98371_dai[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_soc_codec_driver max98371_codec = {
|
static const struct snd_soc_codec_driver max98371_codec = {
|
||||||
.controls = max98371_snd_controls,
|
.component_driver = {
|
||||||
.num_controls = ARRAY_SIZE(max98371_snd_controls),
|
.controls = max98371_snd_controls,
|
||||||
.dapm_routes = max98371_audio_map,
|
.num_controls = ARRAY_SIZE(max98371_snd_controls),
|
||||||
.num_dapm_routes = ARRAY_SIZE(max98371_audio_map),
|
.dapm_routes = max98371_audio_map,
|
||||||
.dapm_widgets = max98371_dapm_widgets,
|
.num_dapm_routes = ARRAY_SIZE(max98371_audio_map),
|
||||||
.num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets),
|
.dapm_widgets = max98371_dapm_widgets,
|
||||||
|
.num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regmap_config max98371_regmap = {
|
static const struct regmap_config max98371_regmap = {
|
||||||
|
|
|
@ -255,11 +255,12 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
|
||||||
|
|
||||||
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 "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
|
||||||
depends on X86_INTEL_LPSS && I2C
|
depends on X86_INTEL_LPSS && I2C && SPI
|
||||||
select SND_SOC_INTEL_SST
|
select SND_SOC_INTEL_SST
|
||||||
select SND_SOC_INTEL_SKYLAKE
|
select 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_MAX98927
|
select SND_SOC_MAX98927
|
||||||
select SND_SOC_HDAC_HDMI
|
select SND_SOC_HDAC_HDMI
|
||||||
help
|
help
|
||||||
|
|
|
@ -76,7 +76,7 @@ int sst_unregister_dsp(struct sst_device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sst_unregister_dsp);
|
EXPORT_SYMBOL_GPL(sst_unregister_dsp);
|
||||||
|
|
||||||
static struct snd_pcm_hardware sst_platform_pcm_hw = {
|
static const struct snd_pcm_hardware sst_platform_pcm_hw = {
|
||||||
.info = (SNDRV_PCM_INFO_INTERLEAVED |
|
.info = (SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_DOUBLE |
|
SNDRV_PCM_INFO_DOUBLE |
|
||||||
SNDRV_PCM_INFO_PAUSE |
|
SNDRV_PCM_INFO_PAUSE |
|
||||||
|
@ -471,7 +471,7 @@ static void sst_disable_ssp(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_dai_ops sst_media_dai_ops = {
|
static const struct snd_soc_dai_ops sst_media_dai_ops = {
|
||||||
.startup = sst_media_open,
|
.startup = sst_media_open,
|
||||||
.shutdown = sst_media_close,
|
.shutdown = sst_media_close,
|
||||||
.prepare = sst_media_prepare,
|
.prepare = sst_media_prepare,
|
||||||
|
@ -480,11 +480,11 @@ static struct snd_soc_dai_ops sst_media_dai_ops = {
|
||||||
.mute_stream = sst_media_digital_mute,
|
.mute_stream = sst_media_digital_mute,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops sst_compr_dai_ops = {
|
static const struct snd_soc_dai_ops sst_compr_dai_ops = {
|
||||||
.mute_stream = sst_media_digital_mute,
|
.mute_stream = sst_media_digital_mute,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops sst_be_dai_ops = {
|
static const struct snd_soc_dai_ops sst_be_dai_ops = {
|
||||||
.startup = sst_enable_ssp,
|
.startup = sst_enable_ssp,
|
||||||
.hw_params = sst_be_hw_params,
|
.hw_params = sst_be_hw_params,
|
||||||
.set_fmt = sst_set_format,
|
.set_fmt = sst_set_format,
|
||||||
|
@ -705,7 +705,7 @@ static int sst_soc_probe(struct snd_soc_platform *platform)
|
||||||
return sst_dsp_init_v2_dpcm(platform);
|
return sst_dsp_init_v2_dpcm(platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_platform_driver sst_soc_platform_drv = {
|
static const struct snd_soc_platform_driver sst_soc_platform_drv = {
|
||||||
.probe = sst_soc_probe,
|
.probe = sst_soc_probe,
|
||||||
.ops = &sst_platform_ops,
|
.ops = &sst_platform_ops,
|
||||||
.compr_ops = &sst_platform_compr_ops,
|
.compr_ops = &sst_platform_compr_ops,
|
||||||
|
|
|
@ -407,7 +407,7 @@ static int sst_cdev_caps(struct snd_compr_caps *caps)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_compr_codec_caps caps_mp3 = {
|
static const struct snd_compr_codec_caps caps_mp3 = {
|
||||||
.num_descriptors = 1,
|
.num_descriptors = 1,
|
||||||
.descriptor[0].max_ch = 2,
|
.descriptor[0].max_ch = 2,
|
||||||
.descriptor[0].sample_rates[0] = 48000,
|
.descriptor[0].sample_rates[0] = 48000,
|
||||||
|
@ -424,7 +424,7 @@ static struct snd_compr_codec_caps caps_mp3 = {
|
||||||
.descriptor[0].formats = 0,
|
.descriptor[0].formats = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_compr_codec_caps caps_aac = {
|
static const struct snd_compr_codec_caps caps_aac = {
|
||||||
.num_descriptors = 2,
|
.num_descriptors = 2,
|
||||||
.descriptor[1].max_ch = 2,
|
.descriptor[1].max_ch = 2,
|
||||||
.descriptor[0].sample_rates[0] = 48000,
|
.descriptor[0].sample_rates[0] = 48000,
|
||||||
|
|
|
@ -181,7 +181,7 @@ static void intel_sst_remove(struct pci_dev *pci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PCI Routines */
|
/* PCI Routines */
|
||||||
static struct pci_device_id intel_sst_ids[] = {
|
static const struct pci_device_id intel_sst_ids[] = {
|
||||||
{ PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
|
{ PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0},
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
|
|
|
@ -309,7 +309,7 @@ static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
|
||||||
return snd_pcm_lib_default_mmap(substream, vma);
|
return snd_pcm_lib_default_mmap(substream, vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_pcm_ops sst_byt_pcm_ops = {
|
static const struct snd_pcm_ops sst_byt_pcm_ops = {
|
||||||
.open = sst_byt_pcm_open,
|
.open = sst_byt_pcm_open,
|
||||||
.close = sst_byt_pcm_close,
|
.close = sst_byt_pcm_close,
|
||||||
.ioctl = snd_pcm_lib_ioctl,
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
|
@ -395,7 +395,7 @@ static int sst_byt_pcm_remove(struct snd_soc_platform *platform)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_platform_driver byt_soc_platform = {
|
static const struct snd_soc_platform_driver byt_soc_platform = {
|
||||||
.probe = sst_byt_pcm_probe,
|
.probe = sst_byt_pcm_probe,
|
||||||
.remove = sst_byt_pcm_remove,
|
.remove = sst_byt_pcm_remove,
|
||||||
.ops = &sst_byt_pcm_ops,
|
.ops = &sst_byt_pcm_ops,
|
||||||
|
|
|
@ -114,7 +114,44 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
|
||||||
{ "iDisp2 Tx", NULL, "iDisp2_out"},
|
{ "iDisp2 Tx", NULL, "iDisp2_out"},
|
||||||
{ "hifi1", NULL, "iDisp1 Tx"},
|
{ "hifi1", NULL, "iDisp1 Tx"},
|
||||||
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_dapm_route geminilake_rt298_map[] = {
|
||||||
|
/* speaker */
|
||||||
|
{"Speaker", NULL, "SPOR"},
|
||||||
|
{"Speaker", NULL, "SPOL"},
|
||||||
|
|
||||||
|
/* HP jack connectors - unknown if we have jack detect */
|
||||||
|
{"Headphone Jack", NULL, "HPO Pin"},
|
||||||
|
|
||||||
|
/* other jacks */
|
||||||
|
{"MIC1", NULL, "Mic Jack"},
|
||||||
|
|
||||||
|
/* digital mics */
|
||||||
|
{"DMIC1 Pin", NULL, "DMIC2"},
|
||||||
|
{"DMic", NULL, "SoC DMIC"},
|
||||||
|
|
||||||
|
{"HDMI1", NULL, "hif5-0 Output"},
|
||||||
|
{"HDMI2", NULL, "hif6-0 Output"},
|
||||||
|
{"HDMI2", NULL, "hif7-0 Output"},
|
||||||
|
|
||||||
|
/* CODEC BE connections */
|
||||||
|
{ "AIF1 Playback", NULL, "ssp2 Tx"},
|
||||||
|
{ "ssp2 Tx", NULL, "codec0_out"},
|
||||||
|
{ "ssp2 Tx", NULL, "codec1_out"},
|
||||||
|
|
||||||
|
{ "codec0_in", NULL, "ssp2 Rx" },
|
||||||
|
{ "ssp2 Rx", NULL, "AIF1 Capture" },
|
||||||
|
|
||||||
|
{ "dmic01_hifi", NULL, "DMIC01 Rx" },
|
||||||
|
{ "DMIC01 Rx", NULL, "Capture" },
|
||||||
|
|
||||||
|
{ "hifi3", NULL, "iDisp3 Tx"},
|
||||||
|
{ "iDisp3 Tx", NULL, "iDisp3_out"},
|
||||||
|
{ "hifi2", NULL, "iDisp2 Tx"},
|
||||||
|
{ "iDisp2 Tx", NULL, "iDisp2_out"},
|
||||||
|
{ "hifi1", NULL, "iDisp1 Tx"},
|
||||||
|
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
|
static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
@ -492,7 +529,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
|
||||||
/* broxton audio machine driver for SPT + RT298S */
|
/* broxton audio machine driver for SPT + RT298S */
|
||||||
static struct snd_soc_card broxton_rt298 = {
|
static struct snd_soc_card broxton_rt298 = {
|
||||||
.name = "broxton-rt298",
|
.name = "broxton-rt298",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.dai_link = broxton_rt298_dais,
|
.dai_link = broxton_rt298_dais,
|
||||||
.num_links = ARRAY_SIZE(broxton_rt298_dais),
|
.num_links = ARRAY_SIZE(broxton_rt298_dais),
|
||||||
.controls = broxton_controls,
|
.controls = broxton_controls,
|
||||||
|
@ -506,9 +542,41 @@ static struct snd_soc_card broxton_rt298 = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_card geminilake_rt298 = {
|
||||||
|
.name = "geminilake-rt298",
|
||||||
|
.dai_link = broxton_rt298_dais,
|
||||||
|
.num_links = ARRAY_SIZE(broxton_rt298_dais),
|
||||||
|
.controls = broxton_controls,
|
||||||
|
.num_controls = ARRAY_SIZE(broxton_controls),
|
||||||
|
.dapm_widgets = broxton_widgets,
|
||||||
|
.num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
|
||||||
|
.dapm_routes = geminilake_rt298_map,
|
||||||
|
.num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map),
|
||||||
|
.fully_routed = true,
|
||||||
|
.late_probe = bxt_card_late_probe,
|
||||||
|
};
|
||||||
|
|
||||||
static int broxton_audio_probe(struct platform_device *pdev)
|
static int broxton_audio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct bxt_rt286_private *ctx;
|
struct bxt_rt286_private *ctx;
|
||||||
|
struct snd_soc_card *card =
|
||||||
|
(struct snd_soc_card *)pdev->id_entry->driver_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) {
|
||||||
|
if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00",
|
||||||
|
I2C_NAME_SIZE)) {
|
||||||
|
if (!strncmp(card->name, "broxton-rt298",
|
||||||
|
PLATFORM_NAME_SIZE)) {
|
||||||
|
card->dai_link[i].name = "SSP5-Codec";
|
||||||
|
card->dai_link[i].cpu_dai_name = "SSP5 Pin";
|
||||||
|
} else if (!strncmp(card->name, "geminilake-rt298",
|
||||||
|
PLATFORM_NAME_SIZE)) {
|
||||||
|
card->dai_link[i].name = "SSP2-Codec";
|
||||||
|
card->dai_link[i].cpu_dai_name = "SSP2 Pin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
|
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
|
@ -516,18 +584,27 @@ static int broxton_audio_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
|
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
|
||||||
|
|
||||||
broxton_rt298.dev = &pdev->dev;
|
card->dev = &pdev->dev;
|
||||||
snd_soc_card_set_drvdata(&broxton_rt298, ctx);
|
snd_soc_card_set_drvdata(card, ctx);
|
||||||
|
|
||||||
return devm_snd_soc_register_card(&pdev->dev, &broxton_rt298);
|
return devm_snd_soc_register_card(&pdev->dev, card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct platform_device_id bxt_board_ids[] = {
|
||||||
|
{ .name = "bxt_alc298s_i2s", .driver_data =
|
||||||
|
(unsigned long)&broxton_rt298 },
|
||||||
|
{ .name = "glk_alc298s_i2s", .driver_data =
|
||||||
|
(unsigned long)&geminilake_rt298 },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver broxton_audio = {
|
static struct platform_driver broxton_audio = {
|
||||||
.probe = broxton_audio_probe,
|
.probe = broxton_audio_probe,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "bxt_alc298s_i2s",
|
.name = "bxt_alc298s_i2s",
|
||||||
.pm = &snd_soc_pm_ops,
|
.pm = &snd_soc_pm_ops,
|
||||||
},
|
},
|
||||||
|
.id_table = bxt_board_ids,
|
||||||
};
|
};
|
||||||
module_platform_driver(broxton_audio)
|
module_platform_driver(broxton_audio)
|
||||||
|
|
||||||
|
@ -537,3 +614,4 @@ MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>");
|
||||||
MODULE_DESCRIPTION("Intel SST Audio for Broxton");
|
MODULE_DESCRIPTION("Intel SST Audio for Broxton");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_ALIAS("platform:bxt_alc298s_i2s");
|
MODULE_ALIAS("platform:bxt_alc298s_i2s");
|
||||||
|
MODULE_ALIAS("platform:glk_alc298s_i2s");
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define MAXIM_DEV0_NAME "i2c-MX98927:00"
|
#define MAXIM_DEV0_NAME "i2c-MX98927:00"
|
||||||
#define MAXIM_DEV1_NAME "i2c-MX98927:01"
|
#define MAXIM_DEV1_NAME "i2c-MX98927:01"
|
||||||
|
|
||||||
static struct snd_soc_card kabylake_audio_card;
|
static struct snd_soc_card *kabylake_audio_card;
|
||||||
static const struct snd_pcm_hw_constraint_list *dmic_constraints;
|
static const struct snd_pcm_hw_constraint_list *dmic_constraints;
|
||||||
static struct snd_soc_jack skylake_hdmi[3];
|
static struct snd_soc_jack skylake_hdmi[3];
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ struct kbl_rt5663_private {
|
||||||
enum {
|
enum {
|
||||||
KBL_DPCM_AUDIO_PB = 0,
|
KBL_DPCM_AUDIO_PB = 0,
|
||||||
KBL_DPCM_AUDIO_CP,
|
KBL_DPCM_AUDIO_CP,
|
||||||
|
KBL_DPCM_AUDIO_HS_PB,
|
||||||
|
KBL_DPCM_AUDIO_ECHO_REF_CP,
|
||||||
KBL_DPCM_AUDIO_REF_CP,
|
KBL_DPCM_AUDIO_REF_CP,
|
||||||
KBL_DPCM_AUDIO_DMIC_CP,
|
KBL_DPCM_AUDIO_DMIC_CP,
|
||||||
KBL_DPCM_AUDIO_HDMI1_PB,
|
KBL_DPCM_AUDIO_HDMI1_PB,
|
||||||
|
@ -72,8 +74,9 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
|
||||||
SND_SOC_DAPM_SPK("Left Spk", NULL),
|
SND_SOC_DAPM_SPK("Left Spk", NULL),
|
||||||
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
||||||
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
||||||
SND_SOC_DAPM_SPK("DP", NULL),
|
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
||||||
SND_SOC_DAPM_SPK("HDMI", NULL),
|
SND_SOC_DAPM_SPK("HDMI2", NULL),
|
||||||
|
SND_SOC_DAPM_SPK("HDMI3", NULL),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,20 +94,22 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||||
{ "IN1N", NULL, "Headset Mic" },
|
{ "IN1N", NULL, "Headset Mic" },
|
||||||
{ "DMic", NULL, "SoC DMIC" },
|
{ "DMic", NULL, "SoC DMIC" },
|
||||||
|
|
||||||
{ "HDMI", NULL, "hif5 Output" },
|
|
||||||
{ "DP", NULL, "hif6 Output" },
|
|
||||||
|
|
||||||
/* CODEC BE connections */
|
/* CODEC BE connections */
|
||||||
{ "Left HiFi Playback", NULL, "ssp0 Tx" },
|
{ "Left HiFi Playback", NULL, "ssp0 Tx" },
|
||||||
{ "Right HiFi Playback", NULL, "ssp0 Tx" },
|
{ "Right HiFi Playback", NULL, "ssp0 Tx" },
|
||||||
{ "ssp0 Tx", NULL, "codec0_out" },
|
{ "ssp0 Tx", NULL, "spk_out" },
|
||||||
|
|
||||||
{ "AIF Playback", NULL, "ssp1 Tx" },
|
{ "AIF Playback", NULL, "ssp1 Tx" },
|
||||||
{ "ssp1 Tx", NULL, "codec1_out" },
|
{ "ssp1 Tx", NULL, "hs_out" },
|
||||||
|
|
||||||
{ "codec0_in", NULL, "ssp1 Rx" },
|
{ "hs_in", NULL, "ssp1 Rx" },
|
||||||
{ "ssp1 Rx", NULL, "AIF Capture" },
|
{ "ssp1 Rx", NULL, "AIF Capture" },
|
||||||
|
|
||||||
|
/* IV feedback path */
|
||||||
|
{ "codec0_fb_in", NULL, "ssp0 Rx"},
|
||||||
|
{ "ssp0 Rx", NULL, "Left HiFi Capture" },
|
||||||
|
{ "ssp0 Rx", NULL, "Right HiFi Capture" },
|
||||||
|
|
||||||
/* DMIC */
|
/* DMIC */
|
||||||
{ "dmic01_hifi", NULL, "DMIC01 Rx" },
|
{ "dmic01_hifi", NULL, "DMIC01 Rx" },
|
||||||
{ "DMIC01 Rx", NULL, "DMIC AIF" },
|
{ "DMIC01 Rx", NULL, "DMIC AIF" },
|
||||||
|
@ -117,6 +122,49 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||||
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
KBL_DPCM_AUDIO_5663_PB = 0,
|
||||||
|
KBL_DPCM_AUDIO_5663_CP,
|
||||||
|
KBL_DPCM_AUDIO_5663_HDMI1_PB,
|
||||||
|
KBL_DPCM_AUDIO_5663_HDMI2_PB,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new kabylake_5663_controls[] = {
|
||||||
|
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
|
||||||
|
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_dapm_widget kabylake_5663_widgets[] = {
|
||||||
|
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||||
|
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||||
|
SND_SOC_DAPM_SPK("DP", NULL),
|
||||||
|
SND_SOC_DAPM_SPK("HDMI", NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_dapm_route kabylake_5663_map[] = {
|
||||||
|
{ "Headphone Jack", NULL, "HPOL" },
|
||||||
|
{ "Headphone Jack", NULL, "HPOR" },
|
||||||
|
|
||||||
|
/* other jacks */
|
||||||
|
{ "IN1P", NULL, "Headset Mic" },
|
||||||
|
{ "IN1N", NULL, "Headset Mic" },
|
||||||
|
|
||||||
|
{ "HDMI", NULL, "hif5 Output" },
|
||||||
|
{ "DP", NULL, "hif6 Output" },
|
||||||
|
|
||||||
|
/* CODEC BE connections */
|
||||||
|
{ "AIF Playback", NULL, "ssp1 Tx" },
|
||||||
|
{ "ssp1 Tx", NULL, "codec1_out" },
|
||||||
|
|
||||||
|
{ "codec0_in", NULL, "ssp1 Rx" },
|
||||||
|
{ "ssp1 Rx", NULL, "AIF Capture" },
|
||||||
|
|
||||||
|
{ "hifi2", NULL, "iDisp2 Tx"},
|
||||||
|
{ "iDisp2 Tx", NULL, "iDisp2_out"},
|
||||||
|
{ "hifi1", NULL, "iDisp1 Tx"},
|
||||||
|
{ "iDisp1 Tx", NULL, "iDisp1_out"},
|
||||||
|
};
|
||||||
|
|
||||||
static struct snd_soc_codec_conf max98927_codec_conf[] = {
|
static struct snd_soc_codec_conf max98927_codec_conf[] = {
|
||||||
{
|
{
|
||||||
.dev_name = MAXIM_DEV0_NAME,
|
.dev_name = MAXIM_DEV0_NAME,
|
||||||
|
@ -165,7 +213,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
* Headset buttons map to the google Reference headset.
|
* Headset buttons map to the google Reference headset.
|
||||||
* These can be configured by userspace.
|
* These can be configured by userspace.
|
||||||
*/
|
*/
|
||||||
ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack",
|
ret = snd_soc_card_jack_new(kabylake_audio_card, "Headset Jack",
|
||||||
SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||||
SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset,
|
SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
@ -173,8 +221,18 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
|
dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
|
rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kabylake_rt5663_max98927_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = kabylake_rt5663_codec_init(rtd);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
|
ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret);
|
dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret);
|
||||||
|
@ -184,7 +242,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
|
static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device)
|
||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||||
struct snd_soc_dai *dai = rtd->codec_dai;
|
struct snd_soc_dai *dai = rtd->codec_dai;
|
||||||
|
@ -194,7 +252,7 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pcm->device = KBL_DPCM_AUDIO_HDMI1_PB;
|
pcm->device = device;
|
||||||
pcm->codec_dai = dai;
|
pcm->codec_dai = dai;
|
||||||
|
|
||||||
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
|
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
|
||||||
|
@ -202,47 +260,36 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB);
|
||||||
|
}
|
||||||
|
|
||||||
static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
|
static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB);
|
||||||
struct snd_soc_dai *dai = rtd->codec_dai;
|
|
||||||
struct kbl_hdmi_pcm *pcm;
|
|
||||||
|
|
||||||
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
|
|
||||||
if (!pcm)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
pcm->device = KBL_DPCM_AUDIO_HDMI2_PB;
|
|
||||||
pcm->codec_dai = dai;
|
|
||||||
|
|
||||||
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
|
static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB);
|
||||||
struct snd_soc_dai *dai = rtd->codec_dai;
|
}
|
||||||
struct kbl_hdmi_pcm *pcm;
|
|
||||||
|
|
||||||
pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
|
static int kabylake_5663_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
if (!pcm)
|
{
|
||||||
return -ENOMEM;
|
return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI1_PB);
|
||||||
|
}
|
||||||
|
|
||||||
pcm->device = KBL_DPCM_AUDIO_HDMI3_PB;
|
static int kabylake_5663_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
pcm->codec_dai = dai;
|
{
|
||||||
|
return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI2_PB);
|
||||||
list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int rates[] = {
|
static unsigned int rates[] = {
|
||||||
48000,
|
48000,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_pcm_hw_constraint_list constraints_rates = {
|
static const struct snd_pcm_hw_constraint_list constraints_rates = {
|
||||||
.count = ARRAY_SIZE(rates),
|
.count = ARRAY_SIZE(rates),
|
||||||
.list = rates,
|
.list = rates,
|
||||||
.mask = 0,
|
.mask = 0,
|
||||||
|
@ -252,7 +299,7 @@ static unsigned int channels[] = {
|
||||||
2,
|
2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_pcm_hw_constraint_list constraints_channels = {
|
static const struct snd_pcm_hw_constraint_list constraints_channels = {
|
||||||
.count = ARRAY_SIZE(channels),
|
.count = ARRAY_SIZE(channels),
|
||||||
.list = channels,
|
.list = channels,
|
||||||
.mask = 0,
|
.mask = 0,
|
||||||
|
@ -312,11 +359,13 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */
|
||||||
|
rt5663_sel_asrc_clk_src(codec_dai->codec,
|
||||||
|
RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER,
|
||||||
|
RT5663_CLK_SEL_I2S1_ASRC);
|
||||||
|
|
||||||
ret = snd_soc_dai_set_sysclk(codec_dai,
|
ret = snd_soc_dai_set_sysclk(codec_dai,
|
||||||
RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
|
RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
|
||||||
/* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */
|
|
||||||
rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
|
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
|
||||||
|
|
||||||
|
@ -381,7 +430,7 @@ static unsigned int rates_16000[] = {
|
||||||
16000,
|
16000,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_pcm_hw_constraint_list constraints_16000 = {
|
static const struct snd_pcm_hw_constraint_list constraints_16000 = {
|
||||||
.count = ARRAY_SIZE(rates_16000),
|
.count = ARRAY_SIZE(rates_16000),
|
||||||
.list = rates_16000,
|
.list = rates_16000,
|
||||||
};
|
};
|
||||||
|
@ -443,6 +492,28 @@ static struct snd_soc_dai_link kabylake_dais[] = {
|
||||||
.dpcm_capture = 1,
|
.dpcm_capture = 1,
|
||||||
.ops = &kabylake_rt5663_fe_ops,
|
.ops = &kabylake_rt5663_fe_ops,
|
||||||
},
|
},
|
||||||
|
[KBL_DPCM_AUDIO_HS_PB] = {
|
||||||
|
.name = "Kbl Audio Headset Playback",
|
||||||
|
.stream_name = "Headset Audio",
|
||||||
|
.cpu_dai_name = "System Pin2",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.nonatomic = 1,
|
||||||
|
.dynamic = 1,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_ECHO_REF_CP] = {
|
||||||
|
.name = "Kbl Audio Echo Reference cap",
|
||||||
|
.stream_name = "Echoreference Capture",
|
||||||
|
.cpu_dai_name = "Echoref Pin",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.init = NULL,
|
||||||
|
.capture_only = 1,
|
||||||
|
.nonatomic = 1,
|
||||||
|
},
|
||||||
[KBL_DPCM_AUDIO_REF_CP] = {
|
[KBL_DPCM_AUDIO_REF_CP] = {
|
||||||
.name = "Kbl Audio Reference cap",
|
.name = "Kbl Audio Reference cap",
|
||||||
.stream_name = "Wake on Voice",
|
.stream_name = "Wake on Voice",
|
||||||
|
@ -538,7 +609,7 @@ static struct snd_soc_dai_link kabylake_dais[] = {
|
||||||
.no_pcm = 1,
|
.no_pcm = 1,
|
||||||
.codec_name = "i2c-10EC5663:00",
|
.codec_name = "i2c-10EC5663:00",
|
||||||
.codec_dai_name = KBL_REALTEK_CODEC_DAI,
|
.codec_dai_name = KBL_REALTEK_CODEC_DAI,
|
||||||
.init = kabylake_rt5663_codec_init,
|
.init = kabylake_rt5663_max98927_codec_init,
|
||||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||||
SND_SOC_DAIFMT_CBS_CFS,
|
SND_SOC_DAIFMT_CBS_CFS,
|
||||||
.ignore_pmdown_time = 1,
|
.ignore_pmdown_time = 1,
|
||||||
|
@ -594,15 +665,119 @@ static struct snd_soc_dai_link kabylake_dais[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_link kabylake_5663_dais[] = {
|
||||||
|
/* Front End DAI links */
|
||||||
|
[KBL_DPCM_AUDIO_5663_PB] = {
|
||||||
|
.name = "Kbl Audio Port",
|
||||||
|
.stream_name = "Audio",
|
||||||
|
.cpu_dai_name = "System Pin",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dynamic = 1,
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.nonatomic = 1,
|
||||||
|
.trigger = {
|
||||||
|
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.ops = &kabylake_rt5663_fe_ops,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_5663_CP] = {
|
||||||
|
.name = "Kbl Audio Capture Port",
|
||||||
|
.stream_name = "Audio Record",
|
||||||
|
.cpu_dai_name = "System Pin",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dynamic = 1,
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.nonatomic = 1,
|
||||||
|
.trigger = {
|
||||||
|
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||||
|
.dpcm_capture = 1,
|
||||||
|
.ops = &kabylake_rt5663_fe_ops,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_5663_HDMI1_PB] = {
|
||||||
|
.name = "Kbl HDMI Port1",
|
||||||
|
.stream_name = "Hdmi1",
|
||||||
|
.cpu_dai_name = "HDMI1 Pin",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.init = NULL,
|
||||||
|
.trigger = {
|
||||||
|
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||||
|
.nonatomic = 1,
|
||||||
|
.dynamic = 1,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_5663_HDMI2_PB] = {
|
||||||
|
.name = "Kbl HDMI Port2",
|
||||||
|
.stream_name = "Hdmi2",
|
||||||
|
.cpu_dai_name = "HDMI2 Pin",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.init = NULL,
|
||||||
|
.trigger = {
|
||||||
|
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||||
|
.nonatomic = 1,
|
||||||
|
.dynamic = 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Back End DAI links */
|
||||||
|
{
|
||||||
|
/* SSP1 - Codec */
|
||||||
|
.name = "SSP1-Codec",
|
||||||
|
.id = 0,
|
||||||
|
.cpu_dai_name = "SSP1 Pin",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.no_pcm = 1,
|
||||||
|
.codec_name = "i2c-10EC5663:00",
|
||||||
|
.codec_dai_name = KBL_REALTEK_CODEC_DAI,
|
||||||
|
.init = kabylake_rt5663_codec_init,
|
||||||
|
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||||
|
SND_SOC_DAIFMT_CBS_CFS,
|
||||||
|
.ignore_pmdown_time = 1,
|
||||||
|
.be_hw_params_fixup = kabylake_ssp_fixup,
|
||||||
|
.ops = &kabylake_rt5663_ops,
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.dpcm_capture = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "iDisp1",
|
||||||
|
.id = 1,
|
||||||
|
.cpu_dai_name = "iDisp1 Pin",
|
||||||
|
.codec_name = "ehdaudio0D2",
|
||||||
|
.codec_dai_name = "intel-hdmi-hifi1",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.init = kabylake_5663_hdmi1_init,
|
||||||
|
.no_pcm = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "iDisp2",
|
||||||
|
.id = 2,
|
||||||
|
.cpu_dai_name = "iDisp2 Pin",
|
||||||
|
.codec_name = "ehdaudio0D2",
|
||||||
|
.codec_dai_name = "intel-hdmi-hifi2",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.init = kabylake_5663_hdmi2_init,
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.no_pcm = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#define NAME_SIZE 32
|
#define NAME_SIZE 32
|
||||||
static int kabylake_card_late_probe(struct snd_soc_card *card)
|
static int kabylake_card_late_probe(struct snd_soc_card *card)
|
||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card);
|
struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card);
|
||||||
struct kbl_hdmi_pcm *pcm;
|
struct kbl_hdmi_pcm *pcm;
|
||||||
|
struct snd_soc_codec *codec = NULL;
|
||||||
int err, i = 0;
|
int err, i = 0;
|
||||||
char jack_name[NAME_SIZE];
|
char jack_name[NAME_SIZE];
|
||||||
|
|
||||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||||
|
codec = pcm->codec_dai->codec;
|
||||||
snprintf(jack_name, sizeof(jack_name),
|
snprintf(jack_name, sizeof(jack_name),
|
||||||
"HDMI/DP, pcm=%d Jack", pcm->device);
|
"HDMI/DP, pcm=%d Jack", pcm->device);
|
||||||
err = snd_soc_card_jack_new(card, jack_name,
|
err = snd_soc_card_jack_new(card, jack_name,
|
||||||
|
@ -620,11 +795,14 @@ static int kabylake_card_late_probe(struct snd_soc_card *card)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (!codec)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return hdac_hdmi_jack_port_init(codec, &card->dapm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* kabylake audio machine driver for SPT + RT5663 */
|
/* kabylake audio machine driver for SPT + RT5663 */
|
||||||
static struct snd_soc_card kabylake_audio_card = {
|
static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = {
|
||||||
.name = "kblrt5663max",
|
.name = "kblrt5663max",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.dai_link = kabylake_dais,
|
.dai_link = kabylake_dais,
|
||||||
|
@ -641,6 +819,22 @@ static struct snd_soc_card kabylake_audio_card = {
|
||||||
.late_probe = kabylake_card_late_probe,
|
.late_probe = kabylake_card_late_probe,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* kabylake audio machine driver for RT5663 */
|
||||||
|
static struct snd_soc_card kabylake_audio_card_rt5663 = {
|
||||||
|
.name = "kblrt5663",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.dai_link = kabylake_5663_dais,
|
||||||
|
.num_links = ARRAY_SIZE(kabylake_5663_dais),
|
||||||
|
.controls = kabylake_5663_controls,
|
||||||
|
.num_controls = ARRAY_SIZE(kabylake_5663_controls),
|
||||||
|
.dapm_widgets = kabylake_5663_widgets,
|
||||||
|
.num_dapm_widgets = ARRAY_SIZE(kabylake_5663_widgets),
|
||||||
|
.dapm_routes = kabylake_5663_map,
|
||||||
|
.num_dapm_routes = ARRAY_SIZE(kabylake_5663_map),
|
||||||
|
.fully_routed = true,
|
||||||
|
.late_probe = kabylake_card_late_probe,
|
||||||
|
};
|
||||||
|
|
||||||
static int kabylake_audio_probe(struct platform_device *pdev)
|
static int kabylake_audio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx;
|
struct kbl_rt5663_private *ctx;
|
||||||
|
@ -652,19 +846,30 @@ static int kabylake_audio_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
|
INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
|
||||||
|
|
||||||
kabylake_audio_card.dev = &pdev->dev;
|
kabylake_audio_card =
|
||||||
snd_soc_card_set_drvdata(&kabylake_audio_card, ctx);
|
(struct snd_soc_card *)pdev->id_entry->driver_data;
|
||||||
|
|
||||||
|
kabylake_audio_card->dev = &pdev->dev;
|
||||||
|
snd_soc_card_set_drvdata(kabylake_audio_card, ctx);
|
||||||
|
|
||||||
pdata = dev_get_drvdata(&pdev->dev);
|
pdata = dev_get_drvdata(&pdev->dev);
|
||||||
if (pdata)
|
if (pdata)
|
||||||
dmic_constraints = pdata->dmic_num == 2 ?
|
dmic_constraints = pdata->dmic_num == 2 ?
|
||||||
&constraints_dmic_2ch : &constraints_dmic_channels;
|
&constraints_dmic_2ch : &constraints_dmic_channels;
|
||||||
|
|
||||||
return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
|
return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id kbl_board_ids[] = {
|
static const struct platform_device_id kbl_board_ids[] = {
|
||||||
{ .name = "kbl_rt5663_m98927" },
|
{
|
||||||
|
.name = "kbl_rt5663",
|
||||||
|
.driver_data = (kernel_ulong_t)&kabylake_audio_card_rt5663,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "kbl_rt5663_m98927",
|
||||||
|
.driver_data =
|
||||||
|
(kernel_ulong_t)&kabylake_audio_card_rt5663_m98927,
|
||||||
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -684,4 +889,5 @@ MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode");
|
||||||
MODULE_AUTHOR("Naveen M <naveen.m@intel.com>");
|
MODULE_AUTHOR("Naveen M <naveen.m@intel.com>");
|
||||||
MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
|
MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_ALIAS("platform:kbl_rt5663");
|
||||||
MODULE_ALIAS("platform:kbl_rt5663_m98927");
|
MODULE_ALIAS("platform:kbl_rt5663_m98927");
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
|
@ -62,7 +63,10 @@ struct kbl_codec_private {
|
||||||
enum {
|
enum {
|
||||||
KBL_DPCM_AUDIO_PB = 0,
|
KBL_DPCM_AUDIO_PB = 0,
|
||||||
KBL_DPCM_AUDIO_CP,
|
KBL_DPCM_AUDIO_CP,
|
||||||
|
KBL_DPCM_AUDIO_HS_PB,
|
||||||
|
KBL_DPCM_AUDIO_ECHO_REF_CP,
|
||||||
KBL_DPCM_AUDIO_DMIC_CP,
|
KBL_DPCM_AUDIO_DMIC_CP,
|
||||||
|
KBL_DPCM_AUDIO_RT5514_DSP,
|
||||||
KBL_DPCM_AUDIO_HDMI1_PB,
|
KBL_DPCM_AUDIO_HDMI1_PB,
|
||||||
KBL_DPCM_AUDIO_HDMI2_PB,
|
KBL_DPCM_AUDIO_HDMI2_PB,
|
||||||
};
|
};
|
||||||
|
@ -81,8 +85,8 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
|
||||||
SND_SOC_DAPM_SPK("Left Spk", NULL),
|
SND_SOC_DAPM_SPK("Left Spk", NULL),
|
||||||
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
||||||
SND_SOC_DAPM_MIC("DMIC", NULL),
|
SND_SOC_DAPM_MIC("DMIC", NULL),
|
||||||
SND_SOC_DAPM_SPK("DP", NULL),
|
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
||||||
SND_SOC_DAPM_SPK("HDMI", NULL),
|
SND_SOC_DAPM_SPK("HDMI2", NULL),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,23 +103,25 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||||
{ "IN1P", NULL, "Headset Mic" },
|
{ "IN1P", NULL, "Headset Mic" },
|
||||||
{ "IN1N", NULL, "Headset Mic" },
|
{ "IN1N", NULL, "Headset Mic" },
|
||||||
|
|
||||||
{ "HDMI", NULL, "hif5 Output" },
|
|
||||||
{ "DP", NULL, "hif6 Output" },
|
|
||||||
|
|
||||||
/* CODEC BE connections */
|
/* CODEC BE connections */
|
||||||
{ "Left HiFi Playback", NULL, "ssp0 Tx" },
|
{ "Left HiFi Playback", NULL, "ssp0 Tx" },
|
||||||
{ "Right HiFi Playback", NULL, "ssp0 Tx" },
|
{ "Right HiFi Playback", NULL, "ssp0 Tx" },
|
||||||
{ "ssp0 Tx", NULL, "codec0_out" },
|
{ "ssp0 Tx", NULL, "spk_out" },
|
||||||
|
|
||||||
{ "AIF Playback", NULL, "ssp1 Tx" },
|
{ "AIF Playback", NULL, "ssp1 Tx" },
|
||||||
{ "ssp1 Tx", NULL, "codec1_out" },
|
{ "ssp1 Tx", NULL, "hs_out" },
|
||||||
|
|
||||||
{ "codec0_in", NULL, "ssp1 Rx" },
|
{ "hs_in", NULL, "ssp1 Rx" },
|
||||||
{ "ssp1 Rx", NULL, "AIF Capture" },
|
{ "ssp1 Rx", NULL, "AIF Capture" },
|
||||||
|
|
||||||
{ "codec1_in", NULL, "ssp0 Rx" },
|
{ "codec1_in", NULL, "ssp0 Rx" },
|
||||||
{ "ssp0 Rx", NULL, "AIF1 Capture" },
|
{ "ssp0 Rx", NULL, "AIF1 Capture" },
|
||||||
|
|
||||||
|
/* IV feedback path */
|
||||||
|
{ "codec0_fb_in", NULL, "ssp0 Rx"},
|
||||||
|
{ "ssp0 Rx", NULL, "Left HiFi Capture" },
|
||||||
|
{ "ssp0 Rx", NULL, "Right HiFi Capture" },
|
||||||
|
|
||||||
/* DMIC */
|
/* DMIC */
|
||||||
{ "DMIC1L", NULL, "DMIC" },
|
{ "DMIC1L", NULL, "DMIC" },
|
||||||
{ "DMIC1R", NULL, "DMIC" },
|
{ "DMIC1R", NULL, "DMIC" },
|
||||||
|
@ -173,6 +179,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
int ret;
|
int ret;
|
||||||
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
|
||||||
struct snd_soc_codec *codec = rtd->codec;
|
struct snd_soc_codec *codec = rtd->codec;
|
||||||
|
struct snd_soc_jack *jack;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Headset buttons map to the google Reference headset.
|
* Headset buttons map to the google Reference headset.
|
||||||
|
@ -187,6 +194,12 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_1, KEY_VOICECOMMAND);
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
|
||||||
|
|
||||||
rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
|
rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
|
||||||
|
|
||||||
ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC");
|
ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC");
|
||||||
|
@ -358,11 +371,18 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) ||
|
if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
|
||||||
!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
|
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16);
|
||||||
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
|
dev_err(rtd->dev, "DEV0 TDM slot err:%d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
|
||||||
|
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(rtd->dev, "DEV1 TDM slot err:%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,6 +462,36 @@ static struct snd_soc_dai_link kabylake_dais[] = {
|
||||||
.dpcm_capture = 1,
|
.dpcm_capture = 1,
|
||||||
.ops = &kabylake_rt5663_fe_ops,
|
.ops = &kabylake_rt5663_fe_ops,
|
||||||
},
|
},
|
||||||
|
[KBL_DPCM_AUDIO_HS_PB] = {
|
||||||
|
.name = "Kbl Audio Headset Playback",
|
||||||
|
.stream_name = "Headset Audio",
|
||||||
|
.cpu_dai_name = "System Pin2",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.dpcm_playback = 1,
|
||||||
|
.nonatomic = 1,
|
||||||
|
.dynamic = 1,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_ECHO_REF_CP] = {
|
||||||
|
.name = "Kbl Audio Echo Reference cap",
|
||||||
|
.stream_name = "Echoreference Capture",
|
||||||
|
.cpu_dai_name = "Echoref Pin",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
.platform_name = "0000:00:1f.3",
|
||||||
|
.init = NULL,
|
||||||
|
.capture_only = 1,
|
||||||
|
.nonatomic = 1,
|
||||||
|
},
|
||||||
|
[KBL_DPCM_AUDIO_RT5514_DSP] = {
|
||||||
|
.name = "rt5514 dsp",
|
||||||
|
.stream_name = "Wake on Voice",
|
||||||
|
.cpu_dai_name = "spi-PRP0001:00",
|
||||||
|
.platform_name = "spi-PRP0001:00",
|
||||||
|
.codec_name = "snd-soc-dummy",
|
||||||
|
.codec_dai_name = "snd-soc-dummy-dai",
|
||||||
|
},
|
||||||
[KBL_DPCM_AUDIO_DMIC_CP] = {
|
[KBL_DPCM_AUDIO_DMIC_CP] = {
|
||||||
.name = "Kbl Audio DMIC cap",
|
.name = "Kbl Audio DMIC cap",
|
||||||
.stream_name = "dmiccap",
|
.stream_name = "dmiccap",
|
||||||
|
@ -548,10 +598,12 @@ static int kabylake_card_late_probe(struct snd_soc_card *card)
|
||||||
{
|
{
|
||||||
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card);
|
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card);
|
||||||
struct kbl_hdmi_pcm *pcm;
|
struct kbl_hdmi_pcm *pcm;
|
||||||
|
struct snd_soc_codec *codec = NULL;
|
||||||
int err, i = 0;
|
int err, i = 0;
|
||||||
char jack_name[NAME_SIZE];
|
char jack_name[NAME_SIZE];
|
||||||
|
|
||||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||||
|
codec = pcm->codec_dai->codec;
|
||||||
err = snd_soc_card_jack_new(card, jack_name,
|
err = snd_soc_card_jack_new(card, jack_name,
|
||||||
SND_JACK_AVOUT, &ctx->kabylake_hdmi[i],
|
SND_JACK_AVOUT, &ctx->kabylake_hdmi[i],
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
@ -565,7 +617,10 @@ static int kabylake_card_late_probe(struct snd_soc_card *card)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (!codec)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return hdac_hdmi_jack_port_init(codec, &card->dapm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -376,10 +376,8 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
|
||||||
/* audio interrupt base of SRAM location where
|
/* audio interrupt base of SRAM location where
|
||||||
* interrupts are stored by System FW */
|
* interrupts are stored by System FW */
|
||||||
mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC);
|
mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC);
|
||||||
if (!mc_drv_ctx) {
|
if (!mc_drv_ctx)
|
||||||
pr_err("allocation failed\n");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
irq_mem = platform_get_resource_byname(
|
irq_mem = platform_get_resource_byname(
|
||||||
pdev, IORESOURCE_MEM, "IRQ_BASE");
|
pdev, IORESOURCE_MEM, "IRQ_BASE");
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_platform_driver hsw_soc_platform = {
|
static const struct snd_soc_platform_driver hsw_soc_platform = {
|
||||||
.probe = hsw_pcm_probe,
|
.probe = hsw_pcm_probe,
|
||||||
.remove = hsw_pcm_remove,
|
.remove = hsw_pcm_remove,
|
||||||
.ops = &hsw_pcm_ops,
|
.ops = &hsw_pcm_ops,
|
||||||
|
|
|
@ -8,7 +8,8 @@ endif
|
||||||
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
|
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
|
||||||
|
|
||||||
# Skylake IPC Support
|
# Skylake IPC Support
|
||||||
snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \
|
snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \
|
||||||
skl-sst.o bxt-sst.o skl-sst-utils.o
|
skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \
|
||||||
|
skl-sst-utils.o
|
||||||
|
|
||||||
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o
|
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o
|
||||||
|
|
|
@ -530,7 +530,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct skl_dsp_fw_ops bxt_fw_ops = {
|
static const struct skl_dsp_fw_ops bxt_fw_ops = {
|
||||||
.set_state_D0 = bxt_set_dsp_D0,
|
.set_state_D0 = bxt_set_dsp_D0,
|
||||||
.set_state_D3 = bxt_set_dsp_D3,
|
.set_state_D3 = bxt_set_dsp_D3,
|
||||||
.set_state_D0i3 = bxt_schedule_dsp_D0i3,
|
.set_state_D0i3 = bxt_schedule_dsp_D0i3,
|
||||||
|
@ -581,10 +581,15 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
||||||
sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
|
sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
|
||||||
SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
|
SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
|
||||||
|
|
||||||
|
ret = skl_ipc_init(dev, skl);
|
||||||
|
if (ret) {
|
||||||
|
skl_dsp_free(sst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* set the D0i3 check */
|
/* set the D0i3 check */
|
||||||
skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
|
skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
|
||||||
|
|
||||||
skl->cores.count = 2;
|
|
||||||
skl->boot_complete = false;
|
skl->boot_complete = false;
|
||||||
init_waitqueue_head(&skl->boot_wait);
|
init_waitqueue_head(&skl->boot_wait);
|
||||||
INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3);
|
INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3);
|
||||||
|
@ -629,11 +634,6 @@ void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
|
||||||
release_firmware(ctx->dsp->fw);
|
release_firmware(ctx->dsp->fw);
|
||||||
skl_freeup_uuid_list(ctx);
|
skl_freeup_uuid_list(ctx);
|
||||||
skl_ipc_free(&ctx->ipc);
|
skl_ipc_free(&ctx->ipc);
|
||||||
ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
|
|
||||||
|
|
||||||
if (ctx->dsp->addr.lpe)
|
|
||||||
iounmap(ctx->dsp->addr.lpe);
|
|
||||||
|
|
||||||
ctx->dsp->ops->free(ctx->dsp);
|
ctx->dsp->ops->free(ctx->dsp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup);
|
EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup);
|
||||||
|
|
|
@ -0,0 +1,274 @@
|
||||||
|
/*
|
||||||
|
* cnl-sst-dsp.c - CNL SST library generic function
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-17, Intel Corporation.
|
||||||
|
* Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
|
||||||
|
*
|
||||||
|
* Modified from:
|
||||||
|
* SKL SST library generic function
|
||||||
|
* Copyright (C) 2014-15, Intel Corporation.
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include "../common/sst-dsp.h"
|
||||||
|
#include "../common/sst-ipc.h"
|
||||||
|
#include "../common/sst-dsp-priv.h"
|
||||||
|
#include "cnl-sst-dsp.h"
|
||||||
|
|
||||||
|
/* various timeout values */
|
||||||
|
#define CNL_DSP_PU_TO 50
|
||||||
|
#define CNL_DSP_PD_TO 50
|
||||||
|
#define CNL_DSP_RESET_TO 50
|
||||||
|
|
||||||
|
static int
|
||||||
|
cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
/* update bits */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx,
|
||||||
|
CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask),
|
||||||
|
CNL_ADSPCS_CRST(core_mask));
|
||||||
|
|
||||||
|
/* poll with timeout to check if operation successful */
|
||||||
|
return sst_dsp_register_poll(ctx,
|
||||||
|
CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CRST(core_mask),
|
||||||
|
CNL_ADSPCS_CRST(core_mask),
|
||||||
|
CNL_DSP_RESET_TO,
|
||||||
|
"Set reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
/* update bits */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CRST(core_mask), 0);
|
||||||
|
|
||||||
|
/* poll with timeout to check if operation successful */
|
||||||
|
return sst_dsp_register_poll(ctx,
|
||||||
|
CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CRST(core_mask),
|
||||||
|
0,
|
||||||
|
CNL_DSP_RESET_TO,
|
||||||
|
"Unset reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
bool is_enable;
|
||||||
|
|
||||||
|
val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS);
|
||||||
|
|
||||||
|
is_enable = (val & CNL_ADSPCS_CPA(core_mask)) &&
|
||||||
|
(val & CNL_ADSPCS_SPA(core_mask)) &&
|
||||||
|
!(val & CNL_ADSPCS_CRST(core_mask)) &&
|
||||||
|
!(val & CNL_ADSPCS_CSTALL(core_mask));
|
||||||
|
|
||||||
|
dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n",
|
||||||
|
is_enable, core_mask);
|
||||||
|
|
||||||
|
return is_enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
/* stall core */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CSTALL(core_mask),
|
||||||
|
CNL_ADSPCS_CSTALL(core_mask));
|
||||||
|
|
||||||
|
/* set reset state */
|
||||||
|
return cnl_dsp_core_set_reset_state(ctx, core_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* unset reset state */
|
||||||
|
ret = cnl_dsp_core_unset_reset_state(ctx, core_mask);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* run core */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CSTALL(core_mask), 0);
|
||||||
|
|
||||||
|
if (!is_cnl_dsp_core_enable(ctx, core_mask)) {
|
||||||
|
cnl_dsp_reset_core(ctx, core_mask);
|
||||||
|
dev_err(ctx->dev, "DSP core mask %#x enable failed\n",
|
||||||
|
core_mask);
|
||||||
|
ret = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
/* update bits */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_SPA(core_mask),
|
||||||
|
CNL_ADSPCS_SPA(core_mask));
|
||||||
|
|
||||||
|
/* poll with timeout to check if operation successful */
|
||||||
|
return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CPA(core_mask),
|
||||||
|
CNL_ADSPCS_CPA(core_mask),
|
||||||
|
CNL_DSP_PU_TO,
|
||||||
|
"Power up");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
/* update bits */
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_SPA(core_mask), 0);
|
||||||
|
|
||||||
|
/* poll with timeout to check if operation successful */
|
||||||
|
return sst_dsp_register_poll(ctx,
|
||||||
|
CNL_ADSP_REG_ADSPCS,
|
||||||
|
CNL_ADSPCS_CPA(core_mask),
|
||||||
|
0,
|
||||||
|
CNL_DSP_PD_TO,
|
||||||
|
"Power down");
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* power up */
|
||||||
|
ret = cnl_dsp_core_power_up(ctx, core_mask);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_dbg(ctx->dev, "DSP core mask %#x power up failed",
|
||||||
|
core_mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnl_dsp_start_core(ctx, core_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = cnl_dsp_reset_core(ctx, core_mask);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "DSP core mask %#x reset failed\n",
|
||||||
|
core_mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* power down core*/
|
||||||
|
ret = cnl_dsp_core_power_down(ctx, core_mask);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "DSP core mask %#x power down failed\n",
|
||||||
|
core_mask);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_cnl_dsp_core_enable(ctx, core_mask)) {
|
||||||
|
dev_err(ctx->dev, "DSP core mask %#x disable failed\n",
|
||||||
|
core_mask);
|
||||||
|
ret = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct sst_dsp *ctx = dev_id;
|
||||||
|
u32 val;
|
||||||
|
irqreturn_t ret = IRQ_NONE;
|
||||||
|
|
||||||
|
spin_lock(&ctx->spinlock);
|
||||||
|
|
||||||
|
val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS);
|
||||||
|
ctx->intr_status = val;
|
||||||
|
|
||||||
|
if (val == 0xffffffff) {
|
||||||
|
spin_unlock(&ctx->spinlock);
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val & CNL_ADSPIS_IPC) {
|
||||||
|
cnl_ipc_int_disable(ctx);
|
||||||
|
ret = IRQ_WAKE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&ctx->spinlock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnl_dsp_free(struct sst_dsp *dsp)
|
||||||
|
{
|
||||||
|
cnl_ipc_int_disable(dsp);
|
||||||
|
|
||||||
|
free_irq(dsp->irq, dsp);
|
||||||
|
cnl_ipc_op_int_disable(dsp);
|
||||||
|
cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cnl_dsp_free);
|
||||||
|
|
||||||
|
void cnl_ipc_int_enable(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC,
|
||||||
|
CNL_ADSPIC_IPC, CNL_ADSPIC_IPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnl_ipc_int_disable(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC,
|
||||||
|
CNL_ADSPIC_IPC, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnl_ipc_op_int_enable(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
/* enable IPC DONE interrupt */
|
||||||
|
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_DONE,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_DONE);
|
||||||
|
|
||||||
|
/* enable IPC BUSY interrupt */
|
||||||
|
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_BUSY,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnl_ipc_op_int_disable(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
/* disable IPC DONE interrupt */
|
||||||
|
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_DONE, 0);
|
||||||
|
|
||||||
|
/* disable IPC BUSY interrupt */
|
||||||
|
sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_BUSY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cnl_ipc_int_status(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) &
|
||||||
|
CNL_ADSPIS_IPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnl_ipc_free(struct sst_generic_ipc *ipc)
|
||||||
|
{
|
||||||
|
cnl_ipc_op_int_disable(ipc->dsp);
|
||||||
|
sst_ipc_fini(ipc);
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Cannonlake SST DSP Support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-17, Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 __CNL_SST_DSP_H__
|
||||||
|
#define __CNL_SST_DSP_H__
|
||||||
|
|
||||||
|
struct sst_dsp;
|
||||||
|
struct skl_sst;
|
||||||
|
struct sst_dsp_device;
|
||||||
|
struct sst_generic_ipc;
|
||||||
|
|
||||||
|
/* Intel HD Audio General DSP Registers */
|
||||||
|
#define CNL_ADSP_GEN_BASE 0x0
|
||||||
|
#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04)
|
||||||
|
#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08)
|
||||||
|
#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c)
|
||||||
|
|
||||||
|
/* Intel HD Audio Inter-Processor Communication Registers */
|
||||||
|
#define CNL_ADSP_IPC_BASE 0xc0
|
||||||
|
#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00)
|
||||||
|
#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04)
|
||||||
|
#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08)
|
||||||
|
#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10)
|
||||||
|
#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14)
|
||||||
|
#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18)
|
||||||
|
#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28)
|
||||||
|
|
||||||
|
/* HIPCTDR */
|
||||||
|
#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31)
|
||||||
|
|
||||||
|
/* HIPCTDA */
|
||||||
|
#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31)
|
||||||
|
|
||||||
|
/* HIPCIDR */
|
||||||
|
#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31)
|
||||||
|
|
||||||
|
/* HIPCIDA */
|
||||||
|
#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31)
|
||||||
|
|
||||||
|
/* CNL HIPCCTL */
|
||||||
|
#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1)
|
||||||
|
#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0)
|
||||||
|
|
||||||
|
/* CNL HIPCT */
|
||||||
|
#define CNL_ADSP_REG_HIPCT_BUSY BIT(31)
|
||||||
|
|
||||||
|
/* Intel HD Audio SRAM Window 1 */
|
||||||
|
#define CNL_ADSP_SRAM1_BASE 0xa0000
|
||||||
|
|
||||||
|
#define CNL_ADSP_MMIO_LEN 0x10000
|
||||||
|
|
||||||
|
#define CNL_ADSP_W0_STAT_SZ 0x1000
|
||||||
|
|
||||||
|
#define CNL_ADSP_W0_UP_SZ 0x1000
|
||||||
|
|
||||||
|
#define CNL_ADSP_W1_SZ 0x1000
|
||||||
|
|
||||||
|
#define CNL_FW_STS_MASK 0xf
|
||||||
|
|
||||||
|
#define CNL_ADSPIC_IPC 0x1
|
||||||
|
#define CNL_ADSPIS_IPC 0x1
|
||||||
|
|
||||||
|
#define CNL_DSP_CORES 4
|
||||||
|
#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1)
|
||||||
|
|
||||||
|
/* core reset - asserted high */
|
||||||
|
#define CNL_ADSPCS_CRST_SHIFT 0
|
||||||
|
#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT)
|
||||||
|
|
||||||
|
/* core run/stall - when set to 1 core is stalled */
|
||||||
|
#define CNL_ADSPCS_CSTALL_SHIFT 8
|
||||||
|
#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT)
|
||||||
|
|
||||||
|
/* set power active - when set to 1 turn core on */
|
||||||
|
#define CNL_ADSPCS_SPA_SHIFT 16
|
||||||
|
#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT)
|
||||||
|
|
||||||
|
/* current power active - power status of cores, set by hardware */
|
||||||
|
#define CNL_ADSPCS_CPA_SHIFT 24
|
||||||
|
#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT)
|
||||||
|
|
||||||
|
int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core);
|
||||||
|
int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core);
|
||||||
|
irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id);
|
||||||
|
void cnl_dsp_free(struct sst_dsp *dsp);
|
||||||
|
|
||||||
|
void cnl_ipc_int_enable(struct sst_dsp *ctx);
|
||||||
|
void cnl_ipc_int_disable(struct sst_dsp *ctx);
|
||||||
|
void cnl_ipc_op_int_enable(struct sst_dsp *ctx);
|
||||||
|
void cnl_ipc_op_int_disable(struct sst_dsp *ctx);
|
||||||
|
bool cnl_ipc_int_status(struct sst_dsp *ctx);
|
||||||
|
void cnl_ipc_free(struct sst_generic_ipc *ipc);
|
||||||
|
|
||||||
|
int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
||||||
|
const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
||||||
|
struct skl_sst **dsp);
|
||||||
|
int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx);
|
||||||
|
void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
|
||||||
|
|
||||||
|
#endif /*__CNL_SST_DSP_H__*/
|
|
@ -0,0 +1,497 @@
|
||||||
|
/*
|
||||||
|
* cnl-sst.c - DSP library functions for CNL platform
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-17, Intel Corporation.
|
||||||
|
*
|
||||||
|
* Author: Guneshwor Singh <guneshwor.o.singh@intel.com>
|
||||||
|
*
|
||||||
|
* Modified from:
|
||||||
|
* HDA DSP library functions for SKL platform
|
||||||
|
* Copyright (C) 2014-15, Intel Corporation.
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
|
||||||
|
#include "../common/sst-dsp.h"
|
||||||
|
#include "../common/sst-dsp-priv.h"
|
||||||
|
#include "../common/sst-ipc.h"
|
||||||
|
#include "cnl-sst-dsp.h"
|
||||||
|
#include "skl-sst-dsp.h"
|
||||||
|
#include "skl-sst-ipc.h"
|
||||||
|
|
||||||
|
#define CNL_FW_ROM_INIT 0x1
|
||||||
|
#define CNL_FW_INIT 0x5
|
||||||
|
#define CNL_IPC_PURGE 0x01004000
|
||||||
|
#define CNL_INIT_TIMEOUT 300
|
||||||
|
#define CNL_BASEFW_TIMEOUT 3000
|
||||||
|
|
||||||
|
#define CNL_ADSP_SRAM0_BASE 0x80000
|
||||||
|
|
||||||
|
/* Firmware status window */
|
||||||
|
#define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE
|
||||||
|
#define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4)
|
||||||
|
|
||||||
|
#define CNL_INSTANCE_ID 0
|
||||||
|
#define CNL_BASE_FW_MODULE_ID 0
|
||||||
|
#define CNL_ADSP_FW_HDR_OFFSET 0x2000
|
||||||
|
#define CNL_ROM_CTRL_DMA_ID 0x9
|
||||||
|
|
||||||
|
static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret, stream_tag;
|
||||||
|
|
||||||
|
stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab);
|
||||||
|
if (stream_tag <= 0) {
|
||||||
|
dev_err(ctx->dev, "dma prepare failed: 0%#x\n", stream_tag);
|
||||||
|
return stream_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->dsp_ops.stream_tag = stream_tag;
|
||||||
|
memcpy(ctx->dmab.area, fwdata, fwsize);
|
||||||
|
|
||||||
|
/* purge FW request */
|
||||||
|
sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR,
|
||||||
|
CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE |
|
||||||
|
((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID)));
|
||||||
|
|
||||||
|
ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret);
|
||||||
|
ret = -EIO;
|
||||||
|
goto base_fw_load_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable interrupt */
|
||||||
|
cnl_ipc_int_enable(ctx);
|
||||||
|
cnl_ipc_op_int_enable(ctx);
|
||||||
|
|
||||||
|
ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK,
|
||||||
|
CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT,
|
||||||
|
"rom load");
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret);
|
||||||
|
goto base_fw_load_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
base_fw_load_failed:
|
||||||
|
ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag);
|
||||||
|
cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag);
|
||||||
|
ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK,
|
||||||
|
CNL_FW_INIT, CNL_BASEFW_TIMEOUT,
|
||||||
|
"firmware boot");
|
||||||
|
|
||||||
|
ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag);
|
||||||
|
ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_load_base_firmware(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
struct firmware stripped_fw;
|
||||||
|
struct skl_sst *cnl = ctx->thread_context;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ctx->fw) {
|
||||||
|
ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "request firmware failed: %d\n", ret);
|
||||||
|
goto cnl_load_base_firmware_failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse uuids if first boot */
|
||||||
|
if (cnl->is_first_boot) {
|
||||||
|
ret = snd_skl_parse_uuids(ctx, ctx->fw,
|
||||||
|
CNL_ADSP_FW_HDR_OFFSET, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto cnl_load_base_firmware_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
stripped_fw.data = ctx->fw->data;
|
||||||
|
stripped_fw.size = ctx->fw->size;
|
||||||
|
skl_dsp_strip_extended_manifest(&stripped_fw);
|
||||||
|
|
||||||
|
ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "prepare firmware failed: %d\n", ret);
|
||||||
|
goto cnl_load_base_firmware_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sst_transfer_fw_host_dma(ctx);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "transfer firmware failed: %d\n", ret);
|
||||||
|
cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
|
||||||
|
goto cnl_load_base_firmware_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete,
|
||||||
|
msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
|
||||||
|
if (ret == 0) {
|
||||||
|
dev_err(ctx->dev, "FW ready timed-out\n");
|
||||||
|
cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
|
||||||
|
ret = -EIO;
|
||||||
|
goto cnl_load_base_firmware_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnl->fw_loaded = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cnl_load_base_firmware_failed:
|
||||||
|
release_firmware(ctx->fw);
|
||||||
|
ctx->fw = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
|
||||||
|
{
|
||||||
|
struct skl_sst *cnl = ctx->thread_context;
|
||||||
|
unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
|
||||||
|
struct skl_ipc_dxstate_info dx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cnl->fw_loaded) {
|
||||||
|
cnl->boot_complete = false;
|
||||||
|
ret = cnl_load_base_firmware(ctx);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "fw reload failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnl->cores.state[core_id] = SKL_DSP_RUNNING;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cnl_dsp_enable_core(ctx, core_mask);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "enable dsp core %d failed: %d\n",
|
||||||
|
core_id, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core_id == SKL_DSP_CORE0_ID) {
|
||||||
|
/* enable interrupt */
|
||||||
|
cnl_ipc_int_enable(ctx);
|
||||||
|
cnl_ipc_op_int_enable(ctx);
|
||||||
|
cnl->boot_complete = false;
|
||||||
|
|
||||||
|
ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete,
|
||||||
|
msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
|
||||||
|
if (ret == 0) {
|
||||||
|
dev_err(ctx->dev,
|
||||||
|
"dsp boot timeout, status=%#x error=%#x\n",
|
||||||
|
sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS),
|
||||||
|
sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dx.core_mask = core_mask;
|
||||||
|
dx.dx_mask = core_mask;
|
||||||
|
|
||||||
|
ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID,
|
||||||
|
CNL_BASE_FW_MODULE_ID, &dx);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n",
|
||||||
|
core_id, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cnl->cores.state[core_id] = SKL_DSP_RUNNING;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
cnl_dsp_disable_core(ctx, core_mask);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
|
||||||
|
{
|
||||||
|
struct skl_sst *cnl = ctx->thread_context;
|
||||||
|
unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
|
||||||
|
struct skl_ipc_dxstate_info dx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dx.core_mask = core_mask;
|
||||||
|
dx.dx_mask = SKL_IPC_D3_MASK;
|
||||||
|
|
||||||
|
ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID,
|
||||||
|
CNL_BASE_FW_MODULE_ID, &dx);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev,
|
||||||
|
"dsp core %d to d3 failed; continue reset\n",
|
||||||
|
core_id);
|
||||||
|
cnl->fw_loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable interrupts if core 0 */
|
||||||
|
if (core_id == SKL_DSP_CORE0_ID) {
|
||||||
|
skl_ipc_op_int_disable(ctx);
|
||||||
|
skl_ipc_int_disable(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cnl_dsp_disable_core(ctx, core_mask);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "disable dsp core %d failed: %d\n",
|
||||||
|
core_id, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnl->cores.state[core_id] = SKL_DSP_RESET;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int cnl_get_errno(struct sst_dsp *ctx)
|
||||||
|
{
|
||||||
|
return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct skl_dsp_fw_ops cnl_fw_ops = {
|
||||||
|
.set_state_D0 = cnl_set_dsp_D0,
|
||||||
|
.set_state_D3 = cnl_set_dsp_D3,
|
||||||
|
.load_fw = cnl_load_base_firmware,
|
||||||
|
.get_fw_errcode = cnl_get_errno,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sst_ops cnl_ops = {
|
||||||
|
.irq_handler = cnl_dsp_sst_interrupt,
|
||||||
|
.write = sst_shim32_write,
|
||||||
|
.read = sst_shim32_read,
|
||||||
|
.ram_read = sst_memcpy_fromio_32,
|
||||||
|
.ram_write = sst_memcpy_toio_32,
|
||||||
|
.free = cnl_dsp_free,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29
|
||||||
|
#define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1
|
||||||
|
#define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \
|
||||||
|
& CNL_IPC_GLB_NOTIFY_RSP_MASK)
|
||||||
|
|
||||||
|
static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context)
|
||||||
|
{
|
||||||
|
struct sst_dsp *dsp = context;
|
||||||
|
struct skl_sst *cnl = sst_dsp_get_thread_context(dsp);
|
||||||
|
struct sst_generic_ipc *ipc = &cnl->ipc;
|
||||||
|
struct skl_ipc_header header = {0};
|
||||||
|
u32 hipcida, hipctdr, hipctdd;
|
||||||
|
int ipc_irq = 0;
|
||||||
|
|
||||||
|
/* here we handle ipc interrupts only */
|
||||||
|
if (!(dsp->intr_status & CNL_ADSPIS_IPC))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA);
|
||||||
|
hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR);
|
||||||
|
|
||||||
|
/* reply message from dsp */
|
||||||
|
if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) {
|
||||||
|
sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_DONE, 0);
|
||||||
|
|
||||||
|
/* clear done bit - tell dsp operation is complete */
|
||||||
|
sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA,
|
||||||
|
CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE);
|
||||||
|
|
||||||
|
ipc_irq = 1;
|
||||||
|
|
||||||
|
/* unmask done interrupt */
|
||||||
|
sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL,
|
||||||
|
CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* new message from dsp */
|
||||||
|
if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) {
|
||||||
|
hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD);
|
||||||
|
header.primary = hipctdr;
|
||||||
|
header.extension = hipctdd;
|
||||||
|
dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x",
|
||||||
|
header.primary);
|
||||||
|
dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x",
|
||||||
|
header.extension);
|
||||||
|
|
||||||
|
if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
|
||||||
|
/* Handle Immediate reply from DSP Core */
|
||||||
|
skl_ipc_process_reply(ipc, header);
|
||||||
|
} else {
|
||||||
|
dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
|
||||||
|
skl_ipc_process_notification(ipc, header);
|
||||||
|
}
|
||||||
|
/* clear busy interrupt */
|
||||||
|
sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR,
|
||||||
|
CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY);
|
||||||
|
|
||||||
|
/* set done bit to ack dsp */
|
||||||
|
sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA,
|
||||||
|
CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE);
|
||||||
|
ipc_irq = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipc_irq == 0)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
cnl_ipc_int_enable(dsp);
|
||||||
|
|
||||||
|
/* continue to send any remaining messages */
|
||||||
|
schedule_work(&ipc->kwork);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sst_dsp_device cnl_dev = {
|
||||||
|
.thread = cnl_dsp_irq_thread_handler,
|
||||||
|
.ops = &cnl_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
|
||||||
|
{
|
||||||
|
struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
|
||||||
|
|
||||||
|
if (msg->tx_size)
|
||||||
|
sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
|
||||||
|
sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD,
|
||||||
|
header->extension);
|
||||||
|
sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR,
|
||||||
|
header->primary | CNL_ADSP_REG_HIPCIDR_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp)
|
||||||
|
{
|
||||||
|
u32 hipcidr;
|
||||||
|
|
||||||
|
hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR);
|
||||||
|
|
||||||
|
return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl)
|
||||||
|
{
|
||||||
|
struct sst_generic_ipc *ipc;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ipc = &cnl->ipc;
|
||||||
|
ipc->dsp = cnl->dsp;
|
||||||
|
ipc->dev = dev;
|
||||||
|
|
||||||
|
ipc->tx_data_max_size = CNL_ADSP_W1_SZ;
|
||||||
|
ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ;
|
||||||
|
|
||||||
|
err = sst_ipc_init(ipc);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* overriding tx_msg and is_dsp_busy since
|
||||||
|
* ipc registers are different for cnl
|
||||||
|
*/
|
||||||
|
ipc->ops.tx_msg = cnl_ipc_tx_msg;
|
||||||
|
ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
|
||||||
|
ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
||||||
|
const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
||||||
|
struct skl_sst **dsp)
|
||||||
|
{
|
||||||
|
struct skl_sst *cnl;
|
||||||
|
struct sst_dsp *sst;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "%s: no device\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnl = *dsp;
|
||||||
|
sst = cnl->dsp;
|
||||||
|
sst->fw_ops = cnl_fw_ops;
|
||||||
|
sst->addr.lpe = mmio_base;
|
||||||
|
sst->addr.shim = mmio_base;
|
||||||
|
sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE;
|
||||||
|
sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE;
|
||||||
|
sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ;
|
||||||
|
sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ;
|
||||||
|
|
||||||
|
sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ),
|
||||||
|
CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE,
|
||||||
|
CNL_ADSP_W1_SZ);
|
||||||
|
|
||||||
|
ret = cnl_ipc_init(dev, cnl);
|
||||||
|
if (ret) {
|
||||||
|
skl_dsp_free(sst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnl->boot_complete = false;
|
||||||
|
init_waitqueue_head(&cnl->boot_wait);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cnl_sst_dsp_init);
|
||||||
|
|
||||||
|
int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct sst_dsp *sst = ctx->dsp;
|
||||||
|
|
||||||
|
ret = ctx->dsp->fw_ops.load_fw(sst);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "load base fw failed: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
skl_dsp_init_core_state(sst);
|
||||||
|
|
||||||
|
ctx->is_first_boot = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cnl_sst_init_fw);
|
||||||
|
|
||||||
|
void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->dsp->fw)
|
||||||
|
release_firmware(ctx->dsp->fw);
|
||||||
|
|
||||||
|
skl_freeup_uuid_list(ctx);
|
||||||
|
cnl_ipc_free(&ctx->ipc);
|
||||||
|
|
||||||
|
ctx->dsp->ops->free(ctx->dsp);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_DESCRIPTION("Intel Cannonlake IPC driver");
|
|
@ -22,6 +22,7 @@
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include "skl-sst-dsp.h"
|
#include "skl-sst-dsp.h"
|
||||||
|
#include "cnl-sst-dsp.h"
|
||||||
#include "skl-sst-ipc.h"
|
#include "skl-sst-ipc.h"
|
||||||
#include "skl.h"
|
#include "skl.h"
|
||||||
#include "../common/sst-dsp.h"
|
#include "../common/sst-dsp.h"
|
||||||
|
@ -201,6 +202,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void)
|
||||||
static const struct skl_dsp_ops dsp_ops[] = {
|
static const struct skl_dsp_ops dsp_ops[] = {
|
||||||
{
|
{
|
||||||
.id = 0x9d70,
|
.id = 0x9d70,
|
||||||
|
.num_cores = 2,
|
||||||
.loader_ops = skl_get_loader_ops,
|
.loader_ops = skl_get_loader_ops,
|
||||||
.init = skl_sst_dsp_init,
|
.init = skl_sst_dsp_init,
|
||||||
.init_fw = skl_sst_init_fw,
|
.init_fw = skl_sst_init_fw,
|
||||||
|
@ -208,6 +210,7 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.id = 0x9d71,
|
.id = 0x9d71,
|
||||||
|
.num_cores = 2,
|
||||||
.loader_ops = skl_get_loader_ops,
|
.loader_ops = skl_get_loader_ops,
|
||||||
.init = kbl_sst_dsp_init,
|
.init = kbl_sst_dsp_init,
|
||||||
.init_fw = skl_sst_init_fw,
|
.init_fw = skl_sst_init_fw,
|
||||||
|
@ -215,6 +218,7 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.id = 0x5a98,
|
.id = 0x5a98,
|
||||||
|
.num_cores = 2,
|
||||||
.loader_ops = bxt_get_loader_ops,
|
.loader_ops = bxt_get_loader_ops,
|
||||||
.init = bxt_sst_dsp_init,
|
.init = bxt_sst_dsp_init,
|
||||||
.init_fw = bxt_sst_init_fw,
|
.init_fw = bxt_sst_init_fw,
|
||||||
|
@ -222,11 +226,20 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.id = 0x3198,
|
.id = 0x3198,
|
||||||
|
.num_cores = 2,
|
||||||
.loader_ops = bxt_get_loader_ops,
|
.loader_ops = bxt_get_loader_ops,
|
||||||
.init = bxt_sst_dsp_init,
|
.init = bxt_sst_dsp_init,
|
||||||
.init_fw = bxt_sst_init_fw,
|
.init_fw = bxt_sst_init_fw,
|
||||||
.cleanup = bxt_sst_dsp_cleanup
|
.cleanup = bxt_sst_dsp_cleanup
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.id = 0x9dc8,
|
||||||
|
.num_cores = 4,
|
||||||
|
.loader_ops = bxt_get_loader_ops,
|
||||||
|
.init = cnl_sst_dsp_init,
|
||||||
|
.init_fw = cnl_sst_init_fw,
|
||||||
|
.cleanup = cnl_sst_dsp_cleanup
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
|
const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
|
||||||
|
@ -249,6 +262,7 @@ int skl_init_dsp(struct skl *skl)
|
||||||
struct skl_dsp_loader_ops loader_ops;
|
struct skl_dsp_loader_ops loader_ops;
|
||||||
int irq = bus->irq;
|
int irq = bus->irq;
|
||||||
const struct skl_dsp_ops *ops;
|
const struct skl_dsp_ops *ops;
|
||||||
|
struct skl_dsp_cores *cores;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* enable ppcap interrupt */
|
/* enable ppcap interrupt */
|
||||||
|
@ -263,8 +277,10 @@ int skl_init_dsp(struct skl *skl)
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = skl_get_dsp_ops(skl->pci->device);
|
ops = skl_get_dsp_ops(skl->pci->device);
|
||||||
if (!ops)
|
if (!ops) {
|
||||||
return -EIO;
|
ret = -EIO;
|
||||||
|
goto unmap_mmio;
|
||||||
|
}
|
||||||
|
|
||||||
loader_ops = ops->loader_ops();
|
loader_ops = ops->loader_ops();
|
||||||
ret = ops->init(bus->dev, mmio_base, irq,
|
ret = ops->init(bus->dev, mmio_base, irq,
|
||||||
|
@ -272,11 +288,35 @@ int skl_init_dsp(struct skl *skl)
|
||||||
&skl->skl_sst);
|
&skl->skl_sst);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto unmap_mmio;
|
||||||
|
|
||||||
skl->skl_sst->dsp_ops = ops;
|
skl->skl_sst->dsp_ops = ops;
|
||||||
|
cores = &skl->skl_sst->cores;
|
||||||
|
cores->count = ops->num_cores;
|
||||||
|
|
||||||
|
cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL);
|
||||||
|
if (!cores->state) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto unmap_mmio;
|
||||||
|
}
|
||||||
|
|
||||||
|
cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!cores->usage_count) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_core_state;
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
|
dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_core_state:
|
||||||
|
kfree(cores->state);
|
||||||
|
|
||||||
|
unmap_mmio:
|
||||||
|
iounmap(mmio_base);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +331,9 @@ int skl_free_dsp(struct skl *skl)
|
||||||
|
|
||||||
ctx->dsp_ops->cleanup(bus->dev, ctx);
|
ctx->dsp_ops->cleanup(bus->dev, ctx);
|
||||||
|
|
||||||
|
kfree(ctx->cores.state);
|
||||||
|
kfree(ctx->cores.usage_count);
|
||||||
|
|
||||||
if (ctx->dsp->addr.lpe)
|
if (ctx->dsp->addr.lpe)
|
||||||
iounmap(ctx->dsp->addr.lpe);
|
iounmap(ctx->dsp->addr.lpe);
|
||||||
|
|
||||||
|
@ -400,9 +443,12 @@ static void skl_set_base_module_format(struct skl_sst *ctx,
|
||||||
struct skl_module_cfg *mconfig,
|
struct skl_module_cfg *mconfig,
|
||||||
struct skl_base_cfg *base_cfg)
|
struct skl_base_cfg *base_cfg)
|
||||||
{
|
{
|
||||||
struct skl_module_fmt *format = &mconfig->in_fmt[0];
|
struct skl_module *module = mconfig->module;
|
||||||
|
struct skl_module_res *res = &module->resources[mconfig->res_idx];
|
||||||
|
struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
|
||||||
|
struct skl_module_fmt *format = &fmt->inputs[0].fmt;
|
||||||
|
|
||||||
base_cfg->audio_fmt.number_of_channels = (u8)format->channels;
|
base_cfg->audio_fmt.number_of_channels = format->channels;
|
||||||
|
|
||||||
base_cfg->audio_fmt.s_freq = format->s_freq;
|
base_cfg->audio_fmt.s_freq = format->s_freq;
|
||||||
base_cfg->audio_fmt.bit_depth = format->bit_depth;
|
base_cfg->audio_fmt.bit_depth = format->bit_depth;
|
||||||
|
@ -417,10 +463,10 @@ static void skl_set_base_module_format(struct skl_sst *ctx,
|
||||||
|
|
||||||
base_cfg->audio_fmt.interleaving = format->interleaving_style;
|
base_cfg->audio_fmt.interleaving = format->interleaving_style;
|
||||||
|
|
||||||
base_cfg->cps = mconfig->mcps;
|
base_cfg->cps = res->cps;
|
||||||
base_cfg->ibs = mconfig->ibs;
|
base_cfg->ibs = res->ibs;
|
||||||
base_cfg->obs = mconfig->obs;
|
base_cfg->obs = res->obs;
|
||||||
base_cfg->is_pages = mconfig->mem_pages;
|
base_cfg->is_pages = res->is_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -508,6 +554,9 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
||||||
struct skl_cpr_cfg *cpr_mconfig)
|
struct skl_cpr_cfg *cpr_mconfig)
|
||||||
{
|
{
|
||||||
u32 dma_io_buf;
|
u32 dma_io_buf;
|
||||||
|
struct skl_module_res *res;
|
||||||
|
int res_idx = mconfig->res_idx;
|
||||||
|
struct skl *skl = get_skl_ctx(ctx->dev);
|
||||||
|
|
||||||
cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);
|
cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);
|
||||||
|
|
||||||
|
@ -516,19 +565,27 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skl->nr_modules) {
|
||||||
|
res = &mconfig->module->resources[mconfig->res_idx];
|
||||||
|
cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size;
|
||||||
|
goto skip_buf_size_calc;
|
||||||
|
} else {
|
||||||
|
res = &mconfig->module->resources[res_idx];
|
||||||
|
}
|
||||||
|
|
||||||
switch (mconfig->hw_conn_type) {
|
switch (mconfig->hw_conn_type) {
|
||||||
case SKL_CONN_SOURCE:
|
case SKL_CONN_SOURCE:
|
||||||
if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
|
if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
|
||||||
dma_io_buf = mconfig->ibs;
|
dma_io_buf = res->ibs;
|
||||||
else
|
else
|
||||||
dma_io_buf = mconfig->obs;
|
dma_io_buf = res->obs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SKL_CONN_SINK:
|
case SKL_CONN_SINK:
|
||||||
if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
|
if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
|
||||||
dma_io_buf = mconfig->obs;
|
dma_io_buf = res->obs;
|
||||||
else
|
else
|
||||||
dma_io_buf = mconfig->ibs;
|
dma_io_buf = res->ibs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -543,11 +600,12 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
|
||||||
/* fallback to 2ms default value */
|
/* fallback to 2ms default value */
|
||||||
if (!cpr_mconfig->gtw_cfg.dma_buffer_size) {
|
if (!cpr_mconfig->gtw_cfg.dma_buffer_size) {
|
||||||
if (mconfig->hw_conn_type == SKL_CONN_SOURCE)
|
if (mconfig->hw_conn_type == SKL_CONN_SOURCE)
|
||||||
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs;
|
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs;
|
||||||
else
|
else
|
||||||
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs;
|
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_buf_size_calc:
|
||||||
cpr_mconfig->cpr_feature_mask = 0;
|
cpr_mconfig->cpr_feature_mask = 0;
|
||||||
cpr_mconfig->gtw_cfg.config_length = 0;
|
cpr_mconfig->gtw_cfg.config_length = 0;
|
||||||
|
|
||||||
|
@ -595,7 +653,9 @@ static void skl_setup_out_format(struct skl_sst *ctx,
|
||||||
struct skl_module_cfg *mconfig,
|
struct skl_module_cfg *mconfig,
|
||||||
struct skl_audio_data_format *out_fmt)
|
struct skl_audio_data_format *out_fmt)
|
||||||
{
|
{
|
||||||
struct skl_module_fmt *format = &mconfig->out_fmt[0];
|
struct skl_module *module = mconfig->module;
|
||||||
|
struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
|
||||||
|
struct skl_module_fmt *format = &fmt->outputs[0].fmt;
|
||||||
|
|
||||||
out_fmt->number_of_channels = (u8)format->channels;
|
out_fmt->number_of_channels = (u8)format->channels;
|
||||||
out_fmt->s_freq = format->s_freq;
|
out_fmt->s_freq = format->s_freq;
|
||||||
|
@ -620,7 +680,9 @@ static void skl_set_src_format(struct skl_sst *ctx,
|
||||||
struct skl_module_cfg *mconfig,
|
struct skl_module_cfg *mconfig,
|
||||||
struct skl_src_module_cfg *src_mconfig)
|
struct skl_src_module_cfg *src_mconfig)
|
||||||
{
|
{
|
||||||
struct skl_module_fmt *fmt = &mconfig->out_fmt[0];
|
struct skl_module *module = mconfig->module;
|
||||||
|
struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx];
|
||||||
|
struct skl_module_fmt *fmt = &iface->outputs[0].fmt;
|
||||||
|
|
||||||
skl_set_base_module_format(ctx, mconfig,
|
skl_set_base_module_format(ctx, mconfig,
|
||||||
(struct skl_base_cfg *)src_mconfig);
|
(struct skl_base_cfg *)src_mconfig);
|
||||||
|
@ -637,7 +699,9 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx,
|
||||||
struct skl_module_cfg *mconfig,
|
struct skl_module_cfg *mconfig,
|
||||||
struct skl_up_down_mixer_cfg *mixer_mconfig)
|
struct skl_up_down_mixer_cfg *mixer_mconfig)
|
||||||
{
|
{
|
||||||
struct skl_module_fmt *fmt = &mconfig->out_fmt[0];
|
struct skl_module *module = mconfig->module;
|
||||||
|
struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx];
|
||||||
|
struct skl_module_fmt *fmt = &iface->outputs[0].fmt;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
skl_set_base_module_format(ctx, mconfig,
|
skl_set_base_module_format(ctx, mconfig,
|
||||||
|
@ -950,7 +1014,7 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg
|
||||||
{
|
{
|
||||||
dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n",
|
dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n",
|
||||||
__func__, src_module->id.module_id, src_module->id.pvt_id);
|
__func__, src_module->id.module_id, src_module->id.pvt_id);
|
||||||
dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__,
|
dev_dbg(ctx->dev, "%s: dst_module=%d dst_instance=%d\n", __func__,
|
||||||
dst_module->id.module_id, dst_module->id.pvt_id);
|
dst_module->id.module_id, dst_module->id.pvt_id);
|
||||||
|
|
||||||
dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n",
|
dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n",
|
||||||
|
@ -970,8 +1034,8 @@ int skl_unbind_modules(struct skl_sst *ctx,
|
||||||
struct skl_ipc_bind_unbind_msg msg;
|
struct skl_ipc_bind_unbind_msg msg;
|
||||||
struct skl_module_inst_id src_id = src_mcfg->id;
|
struct skl_module_inst_id src_id = src_mcfg->id;
|
||||||
struct skl_module_inst_id dst_id = dst_mcfg->id;
|
struct skl_module_inst_id dst_id = dst_mcfg->id;
|
||||||
int in_max = dst_mcfg->max_in_queue;
|
int in_max = dst_mcfg->module->max_input_pins;
|
||||||
int out_max = src_mcfg->max_out_queue;
|
int out_max = src_mcfg->module->max_output_pins;
|
||||||
int src_index, dst_index, src_pin_state, dst_pin_state;
|
int src_index, dst_index, src_pin_state, dst_pin_state;
|
||||||
|
|
||||||
skl_dump_bind_info(ctx, src_mcfg, dst_mcfg);
|
skl_dump_bind_info(ctx, src_mcfg, dst_mcfg);
|
||||||
|
@ -1019,6 +1083,21 @@ int skl_unbind_modules(struct skl_sst *ctx,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
|
||||||
|
struct skl_module_fmt *format)
|
||||||
|
{
|
||||||
|
pin_fmt->number_of_channels = format->channels;
|
||||||
|
pin_fmt->s_freq = format->s_freq;
|
||||||
|
pin_fmt->bit_depth = format->bit_depth;
|
||||||
|
pin_fmt->valid_bit_depth = format->valid_bit_depth;
|
||||||
|
pin_fmt->ch_cfg = format->ch_cfg;
|
||||||
|
pin_fmt->sample_type = format->sample_type;
|
||||||
|
pin_fmt->channel_map = format->ch_map;
|
||||||
|
pin_fmt->interleaving = format->interleaving_style;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CPR_SINK_FMT_PARAM_ID 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once a module is instantiated it need to be 'bind' with other modules in
|
* Once a module is instantiated it need to be 'bind' with other modules in
|
||||||
* the pipeline. For binding we need to find the module pins which are bind
|
* the pipeline. For binding we need to find the module pins which are bind
|
||||||
|
@ -1030,11 +1109,15 @@ int skl_bind_modules(struct skl_sst *ctx,
|
||||||
struct skl_module_cfg *src_mcfg,
|
struct skl_module_cfg *src_mcfg,
|
||||||
struct skl_module_cfg *dst_mcfg)
|
struct skl_module_cfg *dst_mcfg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = 0;
|
||||||
struct skl_ipc_bind_unbind_msg msg;
|
struct skl_ipc_bind_unbind_msg msg;
|
||||||
int in_max = dst_mcfg->max_in_queue;
|
int in_max = dst_mcfg->module->max_input_pins;
|
||||||
int out_max = src_mcfg->max_out_queue;
|
int out_max = src_mcfg->module->max_output_pins;
|
||||||
int src_index, dst_index;
|
int src_index, dst_index;
|
||||||
|
struct skl_module_fmt *format;
|
||||||
|
struct skl_cpr_pin_fmt pin_fmt;
|
||||||
|
struct skl_module *module;
|
||||||
|
struct skl_module_iface *fmt;
|
||||||
|
|
||||||
skl_dump_bind_info(ctx, src_mcfg, dst_mcfg);
|
skl_dump_bind_info(ctx, src_mcfg, dst_mcfg);
|
||||||
|
|
||||||
|
@ -1053,6 +1136,29 @@ int skl_bind_modules(struct skl_sst *ctx,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copier module requires the separate large_config_set_ipc to
|
||||||
|
* configure the pins other than 0
|
||||||
|
*/
|
||||||
|
if (src_mcfg->m_type == SKL_MODULE_TYPE_COPIER && src_index > 0) {
|
||||||
|
pin_fmt.sink_id = src_index;
|
||||||
|
module = src_mcfg->module;
|
||||||
|
fmt = &module->formats[src_mcfg->fmt_idx];
|
||||||
|
|
||||||
|
/* Input fmt is same as that of src module input cfg */
|
||||||
|
format = &fmt->inputs[0].fmt;
|
||||||
|
fill_pin_params(&(pin_fmt.src_fmt), format);
|
||||||
|
|
||||||
|
format = &fmt->outputs[src_index].fmt;
|
||||||
|
fill_pin_params(&(pin_fmt.dst_fmt), format);
|
||||||
|
ret = skl_set_module_params(ctx, (void *)&pin_fmt,
|
||||||
|
sizeof(struct skl_cpr_pin_fmt),
|
||||||
|
CPR_SINK_FMT_PARAM_ID, src_mcfg);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
msg.dst_queue = dst_index;
|
msg.dst_queue = dst_index;
|
||||||
|
|
||||||
dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n",
|
dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n",
|
||||||
|
@ -1070,11 +1176,12 @@ int skl_bind_modules(struct skl_sst *ctx,
|
||||||
src_mcfg->m_state = SKL_MODULE_BIND_DONE;
|
src_mcfg->m_state = SKL_MODULE_BIND_DONE;
|
||||||
src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE;
|
src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE;
|
||||||
dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE;
|
dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE;
|
||||||
} else {
|
return ret;
|
||||||
/* error case , if IPC fails, clear the queue index */
|
|
||||||
skl_free_queue(src_mcfg->m_out_pin, src_index);
|
|
||||||
skl_free_queue(dst_mcfg->m_in_pin, dst_index);
|
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
/* error case , if IPC fails, clear the queue index */
|
||||||
|
skl_free_queue(src_mcfg->m_out_pin, src_index);
|
||||||
|
skl_free_queue(dst_mcfg->m_in_pin, dst_index);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#define HDA_STEREO 2
|
#define HDA_STEREO 2
|
||||||
#define HDA_QUAD 4
|
#define HDA_QUAD 4
|
||||||
|
|
||||||
static struct snd_pcm_hardware azx_pcm_hw = {
|
static const struct snd_pcm_hardware azx_pcm_hw = {
|
||||||
.info = (SNDRV_PCM_INFO_MMAP |
|
.info = (SNDRV_PCM_INFO_MMAP |
|
||||||
SNDRV_PCM_INFO_INTERLEAVED |
|
SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||||
|
@ -628,7 +628,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_dai_ops skl_pcm_dai_ops = {
|
static const struct snd_soc_dai_ops skl_pcm_dai_ops = {
|
||||||
.startup = skl_pcm_open,
|
.startup = skl_pcm_open,
|
||||||
.shutdown = skl_pcm_close,
|
.shutdown = skl_pcm_close,
|
||||||
.prepare = skl_pcm_prepare,
|
.prepare = skl_pcm_prepare,
|
||||||
|
@ -637,15 +637,15 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
|
||||||
.trigger = skl_pcm_trigger,
|
.trigger = skl_pcm_trigger,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops skl_dmic_dai_ops = {
|
static const struct snd_soc_dai_ops skl_dmic_dai_ops = {
|
||||||
.hw_params = skl_be_hw_params,
|
.hw_params = skl_be_hw_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
|
static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
|
||||||
.hw_params = skl_be_hw_params,
|
.hw_params = skl_be_hw_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops skl_link_dai_ops = {
|
static const struct snd_soc_dai_ops skl_link_dai_ops = {
|
||||||
.prepare = skl_link_pcm_prepare,
|
.prepare = skl_link_pcm_prepare,
|
||||||
.hw_params = skl_link_hw_params,
|
.hw_params = skl_link_hw_params,
|
||||||
.hw_free = skl_link_hw_free,
|
.hw_free = skl_link_hw_free,
|
||||||
|
@ -674,6 +674,32 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
|
||||||
.sig_bits = 32,
|
.sig_bits = 32,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "System Pin2",
|
||||||
|
.ops = &skl_pcm_dai_ops,
|
||||||
|
.playback = {
|
||||||
|
.stream_name = "Headset Playback",
|
||||||
|
.channels_min = HDA_MONO,
|
||||||
|
.channels_max = HDA_STEREO,
|
||||||
|
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
|
||||||
|
SNDRV_PCM_RATE_8000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "Echoref Pin",
|
||||||
|
.ops = &skl_pcm_dai_ops,
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "Echoreference Capture",
|
||||||
|
.channels_min = HDA_STEREO,
|
||||||
|
.channels_max = HDA_STEREO,
|
||||||
|
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
|
||||||
|
SNDRV_PCM_RATE_8000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "Reference Pin",
|
.name = "Reference Pin",
|
||||||
.ops = &skl_pcm_dai_ops,
|
.ops = &skl_pcm_dai_ops,
|
||||||
|
@ -1194,8 +1220,11 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||||
static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
|
static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
|
||||||
{
|
{
|
||||||
struct skl_sst *ctx = skl->skl_sst;
|
struct skl_sst *ctx = skl->skl_sst;
|
||||||
|
struct skl_module_inst_id *pin_id;
|
||||||
|
uuid_le *uuid_mod, *uuid_tplg;
|
||||||
|
struct skl_module *skl_module;
|
||||||
struct uuid_module *module;
|
struct uuid_module *module;
|
||||||
uuid_le *uuid_mod;
|
int i, ret = -EIO;
|
||||||
|
|
||||||
uuid_mod = (uuid_le *)mconfig->guid;
|
uuid_mod = (uuid_le *)mconfig->guid;
|
||||||
|
|
||||||
|
@ -1207,12 +1236,45 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
|
||||||
list_for_each_entry(module, &ctx->uuid_list, list) {
|
list_for_each_entry(module, &ctx->uuid_list, list) {
|
||||||
if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
|
if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
|
||||||
mconfig->id.module_id = module->id;
|
mconfig->id.module_id = module->id;
|
||||||
mconfig->is_loadable = module->is_loadable;
|
if (mconfig->module)
|
||||||
return 0;
|
mconfig->module->loadable = module->is_loadable;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EIO;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
uuid_mod = &module->uuid;
|
||||||
|
ret = -EIO;
|
||||||
|
for (i = 0; i < skl->nr_modules; i++) {
|
||||||
|
skl_module = skl->modules[i];
|
||||||
|
uuid_tplg = &skl_module->uuid;
|
||||||
|
if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) {
|
||||||
|
mconfig->module = skl_module;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skl->nr_modules && ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
list_for_each_entry(module, &ctx->uuid_list, list) {
|
||||||
|
for (i = 0; i < MAX_IN_QUEUE; i++) {
|
||||||
|
pin_id = &mconfig->m_in_pin[i].id;
|
||||||
|
if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
|
||||||
|
pin_id->module_id = module->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_OUT_QUEUE; i++) {
|
||||||
|
pin_id = &mconfig->m_out_pin[i].id;
|
||||||
|
if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
|
||||||
|
pin_id->module_id = module->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skl_populate_modules(struct skl *skl)
|
static int skl_populate_modules(struct skl *skl)
|
||||||
|
@ -1284,7 +1346,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static struct snd_soc_platform_driver skl_platform_drv = {
|
static const struct snd_soc_platform_driver skl_platform_drv = {
|
||||||
.probe = skl_platform_soc_probe,
|
.probe = skl_platform_soc_probe,
|
||||||
.ops = &skl_platform_ops,
|
.ops = &skl_platform_ops,
|
||||||
.pcm_new = skl_pcm_new,
|
.pcm_new = skl_pcm_new,
|
||||||
|
|
|
@ -47,7 +47,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx)
|
||||||
skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
|
skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
|
||||||
skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
|
skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
|
||||||
|
|
||||||
for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) {
|
for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) {
|
||||||
skl->cores.state[i] = SKL_DSP_RESET;
|
skl->cores.state[i] = SKL_DSP_RESET;
|
||||||
skl->cores.usage_count[i] = 0;
|
skl->cores.usage_count[i] = 0;
|
||||||
}
|
}
|
||||||
|
@ -351,6 +351,8 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skl->cores.usage_count[core_id]++;
|
||||||
|
|
||||||
if (skl->cores.state[core_id] == SKL_DSP_RESET) {
|
if (skl->cores.state[core_id] == SKL_DSP_RESET) {
|
||||||
ret = ctx->fw_ops.set_state_D0(ctx, core_id);
|
ret = ctx->fw_ops.set_state_D0(ctx, core_id);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -359,8 +361,6 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skl->cores.usage_count[core_id]++;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
|
dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
|
||||||
core_id, skl->cores.state[core_id],
|
core_id, skl->cores.state[core_id],
|
||||||
|
|
|
@ -283,7 +283,7 @@ enum skl_ipc_module_msg {
|
||||||
IPC_MOD_SET_D0IX = 8
|
IPC_MOD_SET_D0IX = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
|
void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
|
||||||
size_t tx_size)
|
size_t tx_size)
|
||||||
{
|
{
|
||||||
if (tx_size)
|
if (tx_size)
|
||||||
|
@ -347,7 +347,7 @@ out:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
|
int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
|
||||||
struct skl_ipc_header header)
|
struct skl_ipc_header header)
|
||||||
{
|
{
|
||||||
struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
|
struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
|
||||||
|
@ -406,7 +406,7 @@ static int skl_ipc_set_reply_error_code(u32 reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
||||||
struct skl_ipc_header header)
|
struct skl_ipc_header header)
|
||||||
{
|
{
|
||||||
struct ipc_message *msg;
|
struct ipc_message *msg;
|
||||||
|
|
|
@ -44,12 +44,10 @@ struct skl_ipc_header {
|
||||||
u32 extension;
|
u32 extension;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SKL_DSP_CORES_MAX 2
|
|
||||||
|
|
||||||
struct skl_dsp_cores {
|
struct skl_dsp_cores {
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
enum skl_dsp_states state[SKL_DSP_CORES_MAX];
|
enum skl_dsp_states *state;
|
||||||
int usage_count[SKL_DSP_CORES_MAX];
|
int *usage_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,4 +212,10 @@ void skl_ipc_free(struct sst_generic_ipc *ipc);
|
||||||
int skl_ipc_init(struct device *dev, struct skl_sst *skl);
|
int skl_ipc_init(struct device *dev, struct skl_sst *skl);
|
||||||
void skl_clear_module_cnt(struct sst_dsp *ctx);
|
void skl_clear_module_cnt(struct sst_dsp *ctx);
|
||||||
|
|
||||||
|
void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
||||||
|
struct skl_ipc_header header);
|
||||||
|
int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
|
||||||
|
struct skl_ipc_header header);
|
||||||
|
void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
|
||||||
|
size_t tx_size);
|
||||||
#endif /* __SKL_IPC_H */
|
#endif /* __SKL_IPC_H */
|
||||||
|
|
|
@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name,
|
||||||
{
|
{
|
||||||
struct skl_sst *skl;
|
struct skl_sst *skl;
|
||||||
struct sst_dsp *sst;
|
struct sst_dsp *sst;
|
||||||
int ret;
|
|
||||||
|
|
||||||
skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL);
|
skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL);
|
||||||
if (skl == NULL)
|
if (skl == NULL)
|
||||||
|
@ -388,15 +387,12 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name,
|
||||||
sst->dsp_ops = dsp_ops;
|
sst->dsp_ops = dsp_ops;
|
||||||
init_waitqueue_head(&skl->mod_load_wait);
|
init_waitqueue_head(&skl->mod_load_wait);
|
||||||
INIT_LIST_HEAD(&sst->module_list);
|
INIT_LIST_HEAD(&sst->module_list);
|
||||||
ret = skl_ipc_init(dev, skl);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
skl->is_first_boot = true;
|
skl->is_first_boot = true;
|
||||||
if (dsp)
|
if (dsp)
|
||||||
*dsp = skl;
|
*dsp = skl;
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo,
|
int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo,
|
||||||
|
|
|
@ -503,7 +503,7 @@ static void skl_clear_module_table(struct sst_dsp *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct skl_dsp_fw_ops skl_fw_ops = {
|
static const struct skl_dsp_fw_ops skl_fw_ops = {
|
||||||
.set_state_D0 = skl_set_dsp_D0,
|
.set_state_D0 = skl_set_dsp_D0,
|
||||||
.set_state_D3 = skl_set_dsp_D3,
|
.set_state_D3 = skl_set_dsp_D3,
|
||||||
.load_fw = skl_load_base_firmware,
|
.load_fw = skl_load_base_firmware,
|
||||||
|
@ -512,7 +512,7 @@ static struct skl_dsp_fw_ops skl_fw_ops = {
|
||||||
.unload_mod = skl_unload_module,
|
.unload_mod = skl_unload_module,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct skl_dsp_fw_ops kbl_fw_ops = {
|
static const struct skl_dsp_fw_ops kbl_fw_ops = {
|
||||||
.set_state_D0 = skl_set_dsp_D0,
|
.set_state_D0 = skl_set_dsp_D0,
|
||||||
.set_state_D3 = skl_set_dsp_D3,
|
.set_state_D3 = skl_set_dsp_D3,
|
||||||
.load_fw = skl_load_base_firmware,
|
.load_fw = skl_load_base_firmware,
|
||||||
|
@ -561,9 +561,13 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
||||||
sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
|
sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
|
||||||
SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
|
SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
|
||||||
|
|
||||||
sst->fw_ops = skl_fw_ops;
|
ret = skl_ipc_init(dev, skl);
|
||||||
|
if (ret) {
|
||||||
|
skl_dsp_free(sst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
skl->cores.count = 2;
|
sst->fw_ops = skl_fw_ops;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -44,6 +44,13 @@
|
||||||
#define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF
|
#define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF
|
||||||
#define SKL_MIC_SEL_SWITCH 0x3
|
#define SKL_MIC_SEL_SWITCH 0x3
|
||||||
|
|
||||||
|
#define SKL_OUTPUT_PIN 0
|
||||||
|
#define SKL_INPUT_PIN 1
|
||||||
|
#define SKL_MAX_PATH_CONFIGS 8
|
||||||
|
#define SKL_MAX_MODULES_IN_PIPE 8
|
||||||
|
#define SKL_MAX_MODULE_FORMATS 32
|
||||||
|
#define SKL_MAX_MODULE_RESOURCES 32
|
||||||
|
|
||||||
enum skl_channel_index {
|
enum skl_channel_index {
|
||||||
SKL_CHANNEL_LEFT = 0,
|
SKL_CHANNEL_LEFT = 0,
|
||||||
SKL_CHANNEL_RIGHT = 1,
|
SKL_CHANNEL_RIGHT = 1,
|
||||||
|
@ -131,6 +138,11 @@ struct skl_cpr_cfg {
|
||||||
struct skl_cpr_gtw_cfg gtw_cfg;
|
struct skl_cpr_gtw_cfg gtw_cfg;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct skl_cpr_pin_fmt {
|
||||||
|
u32 sink_id;
|
||||||
|
struct skl_audio_data_format src_fmt;
|
||||||
|
struct skl_audio_data_format dst_fmt;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct skl_src_module_cfg {
|
struct skl_src_module_cfg {
|
||||||
struct skl_base_cfg base_cfg;
|
struct skl_base_cfg base_cfg;
|
||||||
|
@ -214,6 +226,7 @@ struct skl_kpb_params {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct skl_module_inst_id {
|
struct skl_module_inst_id {
|
||||||
|
uuid_le mod_uuid;
|
||||||
int module_id;
|
int module_id;
|
||||||
u32 instance_id;
|
u32 instance_id;
|
||||||
int pvt_id;
|
int pvt_id;
|
||||||
|
@ -266,6 +279,23 @@ struct skl_pipe_params {
|
||||||
unsigned int link_bps;
|
unsigned int link_bps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct skl_pipe_fmt {
|
||||||
|
u32 freq;
|
||||||
|
u8 channels;
|
||||||
|
u8 bps;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_pipe_mcfg {
|
||||||
|
u8 res_idx;
|
||||||
|
u8 fmt_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_path_config {
|
||||||
|
u8 mem_pages;
|
||||||
|
struct skl_pipe_fmt in_fmt;
|
||||||
|
struct skl_pipe_fmt out_fmt;
|
||||||
|
};
|
||||||
|
|
||||||
struct skl_pipe {
|
struct skl_pipe {
|
||||||
u8 ppl_id;
|
u8 ppl_id;
|
||||||
u8 pipe_priority;
|
u8 pipe_priority;
|
||||||
|
@ -274,6 +304,10 @@ struct skl_pipe {
|
||||||
u8 lp_mode;
|
u8 lp_mode;
|
||||||
struct skl_pipe_params *p_params;
|
struct skl_pipe_params *p_params;
|
||||||
enum skl_pipe_state state;
|
enum skl_pipe_state state;
|
||||||
|
u8 direction;
|
||||||
|
u8 cur_config_idx;
|
||||||
|
u8 nr_cfgs;
|
||||||
|
struct skl_path_config configs[SKL_MAX_PATH_CONFIGS];
|
||||||
struct list_head w_list;
|
struct list_head w_list;
|
||||||
bool passthru;
|
bool passthru;
|
||||||
};
|
};
|
||||||
|
@ -292,9 +326,57 @@ enum d0i3_capability {
|
||||||
SKL_D0I3_NON_STREAMING = 2,
|
SKL_D0I3_NON_STREAMING = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct skl_module_pin_fmt {
|
||||||
|
u8 id;
|
||||||
|
struct skl_module_fmt fmt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_module_iface {
|
||||||
|
u8 fmt_idx;
|
||||||
|
u8 nr_in_fmt;
|
||||||
|
u8 nr_out_fmt;
|
||||||
|
struct skl_module_pin_fmt inputs[MAX_IN_QUEUE];
|
||||||
|
struct skl_module_pin_fmt outputs[MAX_OUT_QUEUE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_module_pin_resources {
|
||||||
|
u8 pin_index;
|
||||||
|
u32 buf_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_module_res {
|
||||||
|
u8 id;
|
||||||
|
u32 is_pages;
|
||||||
|
u32 cps;
|
||||||
|
u32 ibs;
|
||||||
|
u32 obs;
|
||||||
|
u32 dma_buffer_size;
|
||||||
|
u32 cpc;
|
||||||
|
u8 nr_input_pins;
|
||||||
|
u8 nr_output_pins;
|
||||||
|
struct skl_module_pin_resources input[MAX_IN_QUEUE];
|
||||||
|
struct skl_module_pin_resources output[MAX_OUT_QUEUE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skl_module {
|
||||||
|
uuid_le uuid;
|
||||||
|
u8 loadable;
|
||||||
|
u8 input_pin_type;
|
||||||
|
u8 output_pin_type;
|
||||||
|
u8 max_input_pins;
|
||||||
|
u8 max_output_pins;
|
||||||
|
u8 nr_resources;
|
||||||
|
u8 nr_interfaces;
|
||||||
|
struct skl_module_res resources[SKL_MAX_MODULE_RESOURCES];
|
||||||
|
struct skl_module_iface formats[SKL_MAX_MODULE_FORMATS];
|
||||||
|
};
|
||||||
|
|
||||||
struct skl_module_cfg {
|
struct skl_module_cfg {
|
||||||
u8 guid[16];
|
u8 guid[16];
|
||||||
struct skl_module_inst_id id;
|
struct skl_module_inst_id id;
|
||||||
|
struct skl_module *module;
|
||||||
|
int res_idx;
|
||||||
|
int fmt_idx;
|
||||||
u8 domain;
|
u8 domain;
|
||||||
bool homogenous_inputs;
|
bool homogenous_inputs;
|
||||||
bool homogenous_outputs;
|
bool homogenous_outputs;
|
||||||
|
@ -329,6 +411,7 @@ struct skl_module_cfg {
|
||||||
enum skl_module_state m_state;
|
enum skl_module_state m_state;
|
||||||
struct skl_pipe *pipe;
|
struct skl_pipe *pipe;
|
||||||
struct skl_specific_cfg formats_config;
|
struct skl_specific_cfg formats_config;
|
||||||
|
struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct skl_algo_data {
|
struct skl_algo_data {
|
||||||
|
|
|
@ -415,7 +415,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
|
||||||
snd_hdac_ext_stop_streams(ebus);
|
snd_hdac_ext_stop_streams(ebus);
|
||||||
|
|
||||||
if (bus->irq >= 0)
|
if (bus->irq >= 0)
|
||||||
free_irq(bus->irq, (void *)bus);
|
free_irq(bus->irq, (void *)ebus);
|
||||||
snd_hdac_bus_free_stream_pages(bus);
|
snd_hdac_bus_free_stream_pages(bus);
|
||||||
snd_hdac_stream_free_all(ebus);
|
snd_hdac_stream_free_all(ebus);
|
||||||
snd_hdac_link_free_all(ebus);
|
snd_hdac_link_free_all(ebus);
|
||||||
|
@ -528,7 +528,7 @@ static int probe_codec(struct hdac_ext_bus *ebus, int addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Codec initialization */
|
/* Codec initialization */
|
||||||
static int skl_codec_create(struct hdac_ext_bus *ebus)
|
static void skl_codec_create(struct hdac_ext_bus *ebus)
|
||||||
{
|
{
|
||||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||||
int c, max_slots;
|
int c, max_slots;
|
||||||
|
@ -559,8 +559,6 @@ static int skl_codec_create(struct hdac_ext_bus *ebus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct hdac_bus_ops bus_core_ops = {
|
static const struct hdac_bus_ops bus_core_ops = {
|
||||||
|
@ -612,9 +610,7 @@ static void skl_probe_work(struct work_struct *work)
|
||||||
dev_info(bus->dev, "no hda codecs found!\n");
|
dev_info(bus->dev, "no hda codecs found!\n");
|
||||||
|
|
||||||
/* create codec instances */
|
/* create codec instances */
|
||||||
err = skl_codec_create(ebus);
|
skl_codec_create(ebus);
|
||||||
if (err < 0)
|
|
||||||
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);
|
||||||
|
@ -702,6 +698,8 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skl_init_chip(bus, true);
|
||||||
|
|
||||||
snd_hdac_bus_parse_capabilities(bus);
|
snd_hdac_bus_parse_capabilities(bus);
|
||||||
|
|
||||||
if (skl_acquire_irq(ebus, 0) < 0)
|
if (skl_acquire_irq(ebus, 0) < 0)
|
||||||
|
@ -982,6 +980,11 @@ static struct sst_acpi_mach sst_kbl_devdata[] = {
|
||||||
.quirk_data = &kbl_poppy_codecs,
|
.quirk_data = &kbl_poppy_codecs,
|
||||||
.pdata = &skl_dmic_data
|
.pdata = &skl_dmic_data
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.id = "10EC5663",
|
||||||
|
.drv_name = "kbl_rt5663",
|
||||||
|
.fw_filename = "intel/dsp_fw_kbl.bin",
|
||||||
|
},
|
||||||
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
@ -995,6 +998,14 @@ static struct sst_acpi_mach sst_glk_devdata[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct sst_acpi_mach sst_cnl_devdata[] = {
|
||||||
|
{
|
||||||
|
.id = "INT34C2",
|
||||||
|
.drv_name = "cnl_rt274",
|
||||||
|
.fw_filename = "intel/dsp_fw_cnl.bin",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/* PCI IDs */
|
/* PCI IDs */
|
||||||
static const struct pci_device_id skl_ids[] = {
|
static const struct pci_device_id skl_ids[] = {
|
||||||
/* Sunrise Point-LP */
|
/* Sunrise Point-LP */
|
||||||
|
@ -1009,6 +1020,9 @@ static const struct pci_device_id skl_ids[] = {
|
||||||
/* GLK */
|
/* GLK */
|
||||||
{ PCI_DEVICE(0x8086, 0x3198),
|
{ PCI_DEVICE(0x8086, 0x3198),
|
||||||
.driver_data = (unsigned long)&sst_glk_devdata},
|
.driver_data = (unsigned long)&sst_glk_devdata},
|
||||||
|
/* CNL */
|
||||||
|
{ PCI_DEVICE(0x8086, 0x9dc8),
|
||||||
|
.driver_data = (unsigned long)&sst_cnl_devdata},
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, skl_ids);
|
MODULE_DEVICE_TABLE(pci, skl_ids);
|
||||||
|
|
|
@ -71,6 +71,8 @@ struct skl {
|
||||||
struct work_struct probe_work;
|
struct work_struct probe_work;
|
||||||
|
|
||||||
struct skl_debug *debugfs;
|
struct skl_debug *debugfs;
|
||||||
|
u8 nr_modules;
|
||||||
|
struct skl_module **modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define skl_to_ebus(s) (&(s)->ebus)
|
#define skl_to_ebus(s) (&(s)->ebus)
|
||||||
|
@ -90,6 +92,7 @@ struct skl_machine_pdata {
|
||||||
|
|
||||||
struct skl_dsp_ops {
|
struct skl_dsp_ops {
|
||||||
int id;
|
int id;
|
||||||
|
unsigned int num_cores;
|
||||||
struct skl_dsp_loader_ops (*loader_ops)(void);
|
struct skl_dsp_loader_ops (*loader_ops)(void);
|
||||||
int (*init)(struct device *dev, void __iomem *mmio_base,
|
int (*init)(struct device *dev, void __iomem *mmio_base,
|
||||||
int irq, const char *fw_name,
|
int irq, const char *fw_name,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче