Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
460f623a
Commit
460f623a
authored
Sep 01, 2017
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
parents
39e0a0ae
38a77085
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
2419 additions
and
277 deletions
+2419
-277
include/uapi/sound/snd_sst_tokens.h
include/uapi/sound/snd_sst_tokens.h
+91
-1
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+1
-0
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdac_hdmi.c
+34
-5
sound/soc/codecs/max98371.c
sound/soc/codecs/max98371.c
+8
-6
sound/soc/intel/Kconfig
sound/soc/intel/Kconfig
+2
-1
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
+5
-5
sound/soc/intel/atom/sst/sst_drv_interface.c
sound/soc/intel/atom/sst/sst_drv_interface.c
+2
-2
sound/soc/intel/atom/sst/sst_pci.c
sound/soc/intel/atom/sst/sst_pci.c
+1
-1
sound/soc/intel/baytrail/sst-baytrail-pcm.c
sound/soc/intel/baytrail/sst-baytrail-pcm.c
+2
-2
sound/soc/intel/boards/bxt_rt298.c
sound/soc/intel/boards/bxt_rt298.c
+82
-4
sound/soc/intel/boards/kbl_rt5663_max98927.c
sound/soc/intel/boards/kbl_rt5663_max98927.c
+258
-52
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+68
-13
sound/soc/intel/boards/mfld_machine.c
sound/soc/intel/boards/mfld_machine.c
+1
-3
sound/soc/intel/haswell/sst-haswell-pcm.c
sound/soc/intel/haswell/sst-haswell-pcm.c
+1
-1
sound/soc/intel/skylake/Makefile
sound/soc/intel/skylake/Makefile
+3
-2
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/bxt-sst.c
+7
-7
sound/soc/intel/skylake/cnl-sst-dsp.c
sound/soc/intel/skylake/cnl-sst-dsp.c
+274
-0
sound/soc/intel/skylake/cnl-sst-dsp.h
sound/soc/intel/skylake/cnl-sst-dsp.h
+112
-0
sound/soc/intel/skylake/cnl-sst.c
sound/soc/intel/skylake/cnl-sst.c
+497
-0
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-messages.c
+135
-28
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-pcm.c
+72
-10
sound/soc/intel/skylake/skl-sst-dsp.c
sound/soc/intel/skylake/skl-sst-dsp.c
+3
-3
sound/soc/intel/skylake/skl-sst-ipc.c
sound/soc/intel/skylake/skl-sst-ipc.c
+3
-3
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst-ipc.h
+8
-4
sound/soc/intel/skylake/skl-sst-utils.c
sound/soc/intel/skylake/skl-sst-utils.c
+1
-5
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-sst.c
+8
-4
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.c
+633
-108
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-topology.h
+83
-0
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.c
+21
-7
sound/soc/intel/skylake/skl.h
sound/soc/intel/skylake/skl.h
+3
-0
No files found.
include/uapi/sound/snd_sst_tokens.h
View file @
460f623a
...
...
@@ -163,8 +163,71 @@
*
* %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
* 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
{
SKL_TKN_UUID
=
1
,
...
...
@@ -218,7 +281,34 @@ enum SKL_TKNS {
SKL_TKL_U32_D0I3_CAPS
,
/* Typo added at v4.10 */
SKL_TKN_U32_D0I3_CAPS
=
SKL_TKL_U32_D0I3_CAPS
,
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
sound/soc/codecs/Makefile
View file @
460f623a
...
...
@@ -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_MAX98095)
+=
snd-soc-max98095.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_MAX98925)
+=
snd-soc-max98925.o
obj-$(CONFIG_SND_SOC_MAX98926)
+=
snd-soc-max98926.o
...
...
sound/soc/codecs/hdac_hdmi.c
View file @
460f623a
...
...
@@ -121,6 +121,10 @@ struct hdac_hdmi_dai_port_map {
struct
hdac_hdmi_cvt
*
cvt
;
};
struct
hdac_hdmi_drv_data
{
unsigned
int
vendor_nid
;
};
struct
hdac_hdmi_priv
{
struct
hdac_hdmi_dai_port_map
dai_map
[
HDA_MAX_CVTS
];
struct
list_head
pin_list
;
...
...
@@ -131,6 +135,7 @@ struct hdac_hdmi_priv {
int
num_ports
;
struct
mutex
pin_mutex
;
struct
hdac_chmap
chmap
;
struct
hdac_hdmi_drv_data
*
drv_data
;
};
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_GLK_VENDOR_NID 0x0b
#define INTEL_GET_VENDOR_VERB 0xf81
#define INTEL_SET_VENDOR_VERB 0x781
#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
)
{
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
);
if
(
vendor_param
==
-
1
||
vendor_param
&
INTEL_EN_ALL_PIN_CVTS
)
return
;
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
);
if
(
vendor_param
==
-
1
)
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
)
{
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
);
if
(
vendor_param
==
-
1
||
vendor_param
&
INTEL_EN_DP12
)
return
;
/* enable DP1.2 mode */
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
);
if
(
vendor_param
==
-
1
)
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
;
}
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
)
{
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
;
int
num_dais
=
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 */
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
.
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
);
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
(
0x8086280a
,
0x100000
,
"Broxton 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
),
{}
};
...
...
sound/soc/codecs/max98371.c
View file @
460f623a
...
...
@@ -349,12 +349,14 @@ static struct snd_soc_dai_driver max98371_dai[] = {
};
static
const
struct
snd_soc_codec_driver
max98371_codec
=
{
.
controls
=
max98371_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
max98371_snd_controls
),
.
dapm_routes
=
max98371_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
max98371_audio_map
),
.
dapm_widgets
=
max98371_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
max98371_dapm_widgets
),
.
component_driver
=
{
.
controls
=
max98371_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
max98371_snd_controls
),
.
dapm_routes
=
max98371_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
max98371_audio_map
),
.
dapm_widgets
=
max98371_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
max98371_dapm_widgets
),
},
};
static
const
struct
regmap_config
max98371_regmap
=
{
...
...
sound/soc/intel/Kconfig
View file @
460f623a
...
...
@@ -255,11 +255,12 @@ config SND_SOC_INTEL_KBL_RT5663_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"
depends on X86_INTEL_LPSS && I2C
depends on X86_INTEL_LPSS && I2C
&& SPI
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT5663
select SND_SOC_RT5514
select SND_SOC_RT5514_SPI
select SND_SOC_MAX98927
select SND_SOC_HDAC_HDMI
help
...
...
sound/soc/intel/atom/sst-mfld-platform-pcm.c
View file @
460f623a
...
...
@@ -76,7 +76,7 @@ int sst_unregister_dsp(struct sst_device *dev)
}
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
|
SNDRV_PCM_INFO_DOUBLE
|
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
,
.
shutdown
=
sst_media_close
,
.
prepare
=
sst_media_prepare
,
...
...
@@ -480,11 +480,11 @@ static struct snd_soc_dai_ops sst_media_dai_ops = {
.
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
,
};
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
,
.
hw_params
=
sst_be_hw_params
,
.
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
);
}
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
,
.
ops
=
&
sst_platform_ops
,
.
compr_ops
=
&
sst_platform_compr_ops
,
...
...
sound/soc/intel/atom/sst/sst_drv_interface.c
View file @
460f623a
...
...
@@ -407,7 +407,7 @@ static int sst_cdev_caps(struct snd_compr_caps *caps)
return
0
;
}
static
struct
snd_compr_codec_caps
caps_mp3
=
{
static
const
struct
snd_compr_codec_caps
caps_mp3
=
{
.
num_descriptors
=
1
,
.
descriptor
[
0
].
max_ch
=
2
,
.
descriptor
[
0
].
sample_rates
[
0
]
=
48000
,
...
...
@@ -424,7 +424,7 @@ static struct snd_compr_codec_caps caps_mp3 = {
.
descriptor
[
0
].
formats
=
0
,
};
static
struct
snd_compr_codec_caps
caps_aac
=
{
static
const
struct
snd_compr_codec_caps
caps_aac
=
{
.
num_descriptors
=
2
,
.
descriptor
[
1
].
max_ch
=
2
,
.
descriptor
[
0
].
sample_rates
[
0
]
=
48000
,
...
...
sound/soc/intel/atom/sst/sst_pci.c
View file @
460f623a
...
...
@@ -181,7 +181,7 @@ static void intel_sst_remove(struct pci_dev *pci)
}
/* 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
},
{
0
,
}
};
...
...
sound/soc/intel/baytrail/sst-baytrail-pcm.c
View file @
460f623a
...
...
@@ -309,7 +309,7 @@ static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
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
,
.
close
=
sst_byt_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
...
...
@@ -395,7 +395,7 @@ static int sst_byt_pcm_remove(struct snd_soc_platform *platform)
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
,
.
remove
=
sst_byt_pcm_remove
,
.
ops
=
&
sst_byt_pcm_ops
,
...
...
sound/soc/intel/boards/bxt_rt298.c
View file @
460f623a
...
...
@@ -114,7 +114,44 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
{
"iDisp2 Tx"
,
NULL
,
"iDisp2_out"
},
{
"hifi1"
,
NULL
,
"iDisp1 Tx"
},
{
"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
)
...
...
@@ -492,7 +529,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
/* broxton audio machine driver for SPT + RT298S */
static
struct
snd_soc_card
broxton_rt298
=
{
.
name
=
"broxton-rt298"
,
.
owner
=
THIS_MODULE
,
.
dai_link
=
broxton_rt298_dais
,
.
num_links
=
ARRAY_SIZE
(
broxton_rt298_dais
),
.
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
)
{
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
);
if
(
!
ctx
)
...
...
@@ -516,18 +584,27 @@ static int broxton_audio_probe(struct platform_device *pdev)
INIT_LIST_HEAD
(
&
ctx
->
hdmi_pcm_list
);
broxton_rt298
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
broxton_rt298
,
ctx
);
card
->
dev
=
&
pdev
->
dev
;
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
=
{
.
probe
=
broxton_audio_probe
,
.
driver
=
{
.
name
=
"bxt_alc298s_i2s"
,
.
pm
=
&
snd_soc_pm_ops
,
},
.
id_table
=
bxt_board_ids
,
};
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_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:bxt_alc298s_i2s"
);
MODULE_ALIAS
(
"platform:glk_alc298s_i2s"
);
sound/soc/intel/boards/kbl_rt5663_max98927.c
View file @
460f623a
...
...
@@ -34,7 +34,7 @@
#define MAXIM_DEV0_NAME "i2c-MX98927:00"
#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
struct
snd_soc_jack
skylake_hdmi
[
3
];
...
...
@@ -52,6 +52,8 @@ struct kbl_rt5663_private {
enum
{
KBL_DPCM_AUDIO_PB
=
0
,
KBL_DPCM_AUDIO_CP
,
KBL_DPCM_AUDIO_HS_PB
,
KBL_DPCM_AUDIO_ECHO_REF_CP
,
KBL_DPCM_AUDIO_REF_CP
,
KBL_DPCM_AUDIO_DMIC_CP
,
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
(
"Right Spk"
,
NULL
),
SND_SOC_DAPM_MIC
(
"SoC DMIC"
,
NULL
),
SND_SOC_DAPM_SPK
(
"DP"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI1"
,
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"
},
{
"DMic"
,
NULL
,
"SoC DMIC"
},
{
"HDMI"
,
NULL
,
"hif5 Output"
},
{
"DP"
,
NULL
,
"hif6 Output"
},
/* CODEC BE connections */
{
"Left 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"
},
{
"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"
},
/* IV feedback path */
{
"codec0_fb_in"
,
NULL
,
"ssp0 Rx"
},
{
"ssp0 Rx"
,
NULL
,
"Left HiFi Capture"
},
{
"ssp0 Rx"
,
NULL
,
"Right HiFi Capture"
},
/* DMIC */
{
"dmic01_hifi"
,
NULL
,
"DMIC01 Rx"
},
{
"DMIC01 Rx"
,
NULL
,
"DMIC AIF"
},
...
...
@@ -117,6 +122,49 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
{
"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
[]
=
{
{
.
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.
* 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_BTN_2
|
SND_JACK_BTN_3
,
&
ctx
->
kabylake_headset
,
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
);
return
ret
;
}
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"
);
if
(
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
;
}
static
int
kabylake_hdmi
1_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
snd_soc_dai
*
dai
=
rtd
->
codec_dai
;
...
...
@@ -194,7 +252,7 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
if
(
!
pcm
)
return
-
ENOMEM
;
pcm
->
device
=
KBL_DPCM_AUDIO_HDMI1_PB
;
pcm
->
device
=
device
;
pcm
->
codec_dai
=
dai
;
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
;
}
static
int
kabylake_hdmi
2
_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
kabylake_hdmi
1
_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
kbl_rt5663_private
*
ctx
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
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
kabylake_hdmi_init
(
rtd
,
KBL_DPCM_AUDIO_HDMI1_PB
);
}
return
0
;
static
int
kabylake_hdmi2_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
return
kabylake_hdmi_init
(
rtd
,
KBL_DPCM_AUDIO_HDMI2_PB
);
}
static
int
kabylake_hdmi3_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
kbl_rt5663_private
*
ctx
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
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_HDMI3_PB
;
pcm
->
codec_dai
=
dai
;
return
kabylake_hdmi_init
(
rtd
,
KBL_DPCM_AUDIO_HDMI3_PB
);
}
list_add_tail
(
&
pcm
->
head
,
&
ctx
->
hdmi_pcm_list
);
static
int
kabylake_5663_hdmi1_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
return
kabylake_hdmi_init
(
rtd
,
KBL_DPCM_AUDIO_5663_HDMI1_PB
);
}
return
0
;
static
int
kabylake_5663_hdmi2_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
return
kabylake_hdmi_init
(
rtd
,
KBL_DPCM_AUDIO_5663_HDMI2_PB
);
}
static
unsigned
int
rates
[]
=
{
48000
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_rates
=
{
static
const
struct
snd_pcm_hw_constraint_list
constraints_rates
=
{
.
count
=
ARRAY_SIZE
(
rates
),
.
list
=
rates
,
.
mask
=
0
,
...
...
@@ -252,7 +299,7 @@ static unsigned int channels[] = {
2
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_channels
=
{
static
const
struct
snd_pcm_hw_constraint_list
constraints_channels
=
{
.
count
=
ARRAY_SIZE
(
channels
),
.
list
=
channels
,
.
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
;
int
ret
;
ret
=
snd_soc_dai_set_sysclk
(
codec_dai
,
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
);
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
,
RT5663_SCLK_S_MCLK
,
24576000
,
SND_SOC_CLOCK_IN
);
if
(
ret
<
0
)
dev_err
(
rtd
->
dev
,
"snd_soc_dai_set_sysclk err = %d
\n
"
,
ret
);
...
...
@@ -381,7 +430,7 @@ static unsigned int rates_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
),
.
list
=
rates_16000
,
};
...
...
@@ -443,6 +492,28 @@ static struct snd_soc_dai_link kabylake_dais[] = {
.
dpcm_capture
=
1
,
.
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
]
=
{
.
name
=
"Kbl Audio Reference cap"
,
.
stream_name
=
"Wake on Voice"
,
...
...
@@ -538,7 +609,7 @@ static struct snd_soc_dai_link kabylake_dais[] = {
.
no_pcm
=
1
,
.
codec_name
=
"i2c-10EC5663:00"
,
.
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
|
SND_SOC_DAIFMT_CBS_CFS
,
.
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
static
int
kabylake_card_late_probe
(
struct
snd_soc_card
*
card
)
{
struct
kbl_rt5663_private
*
ctx
=
snd_soc_card_get_drvdata
(
card
);
struct
kbl_hdmi_pcm
*
pcm
;
struct
snd_soc_codec
*
codec
=
NULL
;
int
err
,
i
=
0
;
char
jack_name
[
NAME_SIZE
];
list_for_each_entry
(
pcm
,
&
ctx
->
hdmi_pcm_list
,
head
)
{
codec
=
pcm
->
codec_dai
->
codec
;
snprintf
(
jack_name
,
sizeof
(
jack_name
),
"HDMI/DP, pcm=%d Jack"
,
pcm
->
device
);
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
++
;
}
return
0
;
if
(
!
codec
)
return
-
EINVAL
;
return
hdac_hdmi_jack_port_init
(
codec
,
&
card
->
dapm
);
}
/* 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"
,
.
owner
=
THIS_MODULE
,
.
dai_link
=
kabylake_dais
,
...
...
@@ -641,6 +819,22 @@ static struct snd_soc_card kabylake_audio_card = {
.
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
)
{
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
);
kabylake_audio_card
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
kabylake_audio_card
,
ctx
);
kabylake_audio_card
=
(
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
);
if
(
pdata
)
dmic_constraints
=
pdata
->
dmic_num
==
2
?
&
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
[]
=
{
{
.
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
(
"Harsha Priya <harshapriya.n@intel.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:kbl_rt5663"
);
MODULE_ALIAS
(
"platform:kbl_rt5663_m98927"
);
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
View file @
460f623a
...
...
@@ -18,6 +18,7 @@
* GNU General Public License for more details.
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
...
...
@@ -62,7 +63,10 @@ struct kbl_codec_private {
enum
{
KBL_DPCM_AUDIO_PB
=
0
,
KBL_DPCM_AUDIO_CP
,
KBL_DPCM_AUDIO_HS_PB
,
KBL_DPCM_AUDIO_ECHO_REF_CP
,
KBL_DPCM_AUDIO_DMIC_CP
,
KBL_DPCM_AUDIO_RT5514_DSP
,
KBL_DPCM_AUDIO_HDMI1_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
(
"Right Spk"
,
NULL
),
SND_SOC_DAPM_MIC
(
"DMIC"
,
NULL
),
SND_SOC_DAPM_SPK
(
"
DP
"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI"
,
NULL
),
SND_SOC_DAPM_SPK
(
"
HDMI1
"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI
2
"
,
NULL
),
};
...
...
@@ -99,23 +103,25 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
{
"IN1P"
,
NULL
,
"Headset Mic"
},
{
"IN1N"
,
NULL
,
"Headset Mic"
},
{
"HDMI"
,
NULL
,
"hif5 Output"
},
{
"DP"
,
NULL
,
"hif6 Output"
},
/* CODEC BE connections */
{
"Left 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"
},
{
"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"
},
{
"codec1_in"
,
NULL
,
"ssp0 Rx"
},
{
"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 */
{
"DMIC1L"
,
NULL
,
"DMIC"
},
{
"DMIC1R"
,
NULL
,
"DMIC"
},
...
...
@@ -173,6 +179,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
int
ret
;
struct
kbl_codec_private
*
ctx
=
snd_soc_card_get_drvdata
(
rtd
->
card
);
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
snd_soc_jack
*
jack
;
/*
* 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
;
}
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
);
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
;
}
}
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
,
0xF0
,
3
,
8
,
16
);
if
(
!
strcmp
(
codec_dai
->
component
->
name
,
MAXIM_DEV0_NAME
))
{
ret
=
snd_soc_dai_set_tdm_slot
(
codec_dai
,
0x30
,
3
,
8
,
16
);
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
;
}
}
...
...
@@ -442,6 +462,36 @@ static struct snd_soc_dai_link kabylake_dais[] = {
.
dpcm_capture
=
1
,
.
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
]
=
{
.
name
=
"Kbl Audio DMIC cap"
,
.
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_hdmi_pcm
*
pcm
;
struct
snd_soc_codec
*
codec
=
NULL
;
int
err
,
i
=
0
;
char
jack_name
[
NAME_SIZE
];
list_for_each_entry
(
pcm
,
&
ctx
->
hdmi_pcm_list
,
head
)
{
codec
=
pcm
->
codec_dai
->
codec
;
err
=
snd_soc_card_jack_new
(
card
,
jack_name
,
SND_JACK_AVOUT
,
&
ctx
->
kabylake_hdmi
[
i
],
NULL
,
0
);
...
...
@@ -565,7 +617,10 @@ static int kabylake_card_late_probe(struct snd_soc_card *card)
i
++
;
}
return
0
;
if
(
!
codec
)
return
-
EINVAL
;
return
hdac_hdmi_jack_port_init
(
codec
,
&
card
->
dapm
);
}
/*
...
...
sound/soc/intel/boards/mfld_machine.c
View file @
460f623a
...
...
@@ -376,10 +376,8 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
/* audio interrupt base of SRAM location where
* interrupts are stored by System FW */
mc_drv_ctx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
mc_drv_ctx
),
GFP_ATOMIC
);
if
(
!
mc_drv_ctx
)
{
pr_err
(
"allocation failed
\n
"
);
if
(
!
mc_drv_ctx
)
return
-
ENOMEM
;
}
irq_mem
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"IRQ_BASE"
);
...
...
sound/soc/intel/haswell/sst-haswell-pcm.c
View file @
460f623a
...
...
@@ -1135,7 +1135,7 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform)
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
,
.
remove
=
hsw_pcm_remove
,
.
ops
=
&
hsw_pcm_ops
,
...
...
sound/soc/intel/skylake/Makefile
View file @
460f623a
...
...
@@ -8,7 +8,8 @@ endif
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE)
+=
snd-soc-skl.o
# Skylake IPC Support
snd-soc-skl-ipc-objs
:=
skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o
\
skl-sst.o bxt-sst.o skl-sst-utils.o
snd-soc-skl-ipc-objs
:=
skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.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
sound/soc/intel/skylake/bxt-sst.c
View file @
460f623a
...
...
@@ -530,7 +530,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
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_D3
=
bxt_set_dsp_D3
,
.
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
),
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 */
skl
->
ipc
.
ops
.
check_dsp_lp_on
=
skl_ipc_check_D0i0
;
skl
->
cores
.
count
=
2
;
skl
->
boot_complete
=
false
;
init_waitqueue_head
(
&
skl
->
boot_wait
);
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
);
skl_freeup_uuid_list
(
ctx
);
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
);
}
EXPORT_SYMBOL_GPL
(
bxt_sst_dsp_cleanup
);
...
...
sound/soc/intel/skylake/cnl-sst-dsp.c
0 → 100644
View file @
460f623a
/*
* 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
);
}
sound/soc/intel/skylake/cnl-sst-dsp.h
0 → 100644
View file @
460f623a
/*
* 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__*/
sound/soc/intel/skylake/cnl-sst.c
0 → 100644
View file @
460f623a
/*
* 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"
);
sound/soc/intel/skylake/skl-messages.c
View file @
460f623a
...
...
@@ -22,6 +22,7 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include "skl-sst-dsp.h"
#include "cnl-sst-dsp.h"
#include "skl-sst-ipc.h"
#include "skl.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
[]
=
{
{
.
id
=
0x9d70
,
.
num_cores
=
2
,
.
loader_ops
=
skl_get_loader_ops
,
.
init
=
skl_sst_dsp_init
,
.
init_fw
=
skl_sst_init_fw
,
...
...
@@ -208,6 +210,7 @@ static const struct skl_dsp_ops dsp_ops[] = {
},
{
.
id
=
0x9d71
,
.
num_cores
=
2
,
.
loader_ops
=
skl_get_loader_ops
,
.
init
=
kbl_sst_dsp_init
,
.
init_fw
=
skl_sst_init_fw
,
...
...
@@ -215,6 +218,7 @@ static const struct skl_dsp_ops dsp_ops[] = {
},
{
.
id
=
0x5a98
,
.
num_cores
=
2
,
.
loader_ops
=
bxt_get_loader_ops
,
.
init
=
bxt_sst_dsp_init
,
.
init_fw
=
bxt_sst_init_fw
,
...
...
@@ -222,11 +226,20 @@ static const struct skl_dsp_ops dsp_ops[] = {
},
{
.
id
=
0x3198
,
.
num_cores
=
2
,
.
loader_ops
=
bxt_get_loader_ops
,
.
init
=
bxt_sst_dsp_init
,
.
init_fw
=
bxt_sst_init_fw
,
.
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
)
...
...
@@ -249,6 +262,7 @@ int skl_init_dsp(struct skl *skl)
struct
skl_dsp_loader_ops
loader_ops
;
int
irq
=
bus
->
irq
;
const
struct
skl_dsp_ops
*
ops
;
struct
skl_dsp_cores
*
cores
;
int
ret
;
/* enable ppcap interrupt */
...
...
@@ -263,8 +277,10 @@ int skl_init_dsp(struct skl *skl)
}
ops
=
skl_get_dsp_ops
(
skl
->
pci
->
device
);
if
(
!
ops
)
return
-
EIO
;
if
(
!
ops
)
{
ret
=
-
EIO
;
goto
unmap_mmio
;
}
loader_ops
=
ops
->
loader_ops
();
ret
=
ops
->
init
(
bus
->
dev
,
mmio_base
,
irq
,
...
...
@@ -272,11 +288,35 @@ int skl_init_dsp(struct skl *skl)
&
skl
->
skl_sst
);
if
(
ret
<
0
)
return
ret
;
goto
unmap_mmio
;
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
);
return
0
;
free_core_state:
kfree
(
cores
->
state
);
unmap_mmio:
iounmap
(
mmio_base
);
return
ret
;
}
...
...
@@ -291,6 +331,9 @@ int skl_free_dsp(struct skl *skl)
ctx
->
dsp_ops
->
cleanup
(
bus
->
dev
,
ctx
);
kfree
(
ctx
->
cores
.
state
);
kfree
(
ctx
->
cores
.
usage_count
);
if
(
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_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
.
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
->
cps
=
mconfig
->
m
cps
;
base_cfg
->
ibs
=
mconfig
->
ibs
;
base_cfg
->
obs
=
mconfig
->
obs
;
base_cfg
->
is_pages
=
mconfig
->
mem
_pages
;
base_cfg
->
cps
=
res
->
cps
;
base_cfg
->
ibs
=
res
->
ibs
;
base_cfg
->
obs
=
res
->
obs
;
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
)
{
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
);
...
...
@@ -516,19 +565,27 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
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
)
{
case
SKL_CONN_SOURCE
:
if
(
mconfig
->
dev_type
==
SKL_DEVICE_HDAHOST
)
dma_io_buf
=
mconfig
->
ibs
;
dma_io_buf
=
res
->
ibs
;
else
dma_io_buf
=
mconfig
->
obs
;
dma_io_buf
=
res
->
obs
;
break
;
case
SKL_CONN_SINK
:
if
(
mconfig
->
dev_type
==
SKL_DEVICE_HDAHOST
)
dma_io_buf
=
mconfig
->
obs
;
dma_io_buf
=
res
->
obs
;
else
dma_io_buf
=
mconfig
->
ibs
;
dma_io_buf
=
res
->
ibs
;
break
;
default:
...
...
@@ -543,11 +600,12 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
/* fallback to 2ms default value */
if
(
!
cpr_mconfig
->
gtw_cfg
.
dma_buffer_size
)
{
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
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
->
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_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
->
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_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
,
(
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_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
;
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
"
,
__func__
,
src_module
->
id
.
module_id
,
src_module
->
id
.
pvt_id
);
dev_dbg
(
ctx
->
dev
,
"%s: dst_module=%d dst_insta
cn
e=%d
\n
"
,
__func__
,
dev_dbg
(
ctx
->
dev
,
"%s: dst_module=%d dst_insta
nc
e=%d
\n
"
,
__func__
,
dst_module
->
id
.
module_id
,
dst_module
->
id
.
pvt_id
);
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_module_inst_id
src_id
=
src_mcfg
->
id
;
struct
skl_module_inst_id
dst_id
=
dst_mcfg
->
id
;
int
in_max
=
dst_mcfg
->
m
ax_in_queue
;
int
out_max
=
src_mcfg
->
m
ax_out_queue
;
int
in_max
=
dst_mcfg
->
m
odule
->
max_input_pins
;
int
out_max
=
src_mcfg
->
m
odule
->
max_output_pins
;
int
src_index
,
dst_index
,
src_pin_state
,
dst_pin_state
;
skl_dump_bind_info
(
ctx
,
src_mcfg
,
dst_mcfg
);
...
...
@@ -1019,6 +1083,21 @@ int skl_unbind_modules(struct skl_sst *ctx,
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
* 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
*
dst_mcfg
)
{
int
ret
;
int
ret
=
0
;
struct
skl_ipc_bind_unbind_msg
msg
;
int
in_max
=
dst_mcfg
->
m
ax_in_queue
;
int
out_max
=
src_mcfg
->
m
ax_out_queue
;
int
in_max
=
dst_mcfg
->
m
odule
->
max_input_pins
;
int
out_max
=
src_mcfg
->
m
odule
->
max_output_pins
;
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
);
...
...
@@ -1053,6 +1136,29 @@ int skl_bind_modules(struct skl_sst *ctx,
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
;
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_out_pin
[
src_index
].
pin_state
=
SKL_PIN_BIND_DONE
;
dst_mcfg
->
m_in_pin
[
dst_index
].
pin_state
=
SKL_PIN_BIND_DONE
;
}
else
{
/* 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
;
}
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
;
}
...
...
sound/soc/intel/skylake/skl-pcm.c
View file @
460f623a
...
...
@@ -33,7 +33,7 @@
#define HDA_STEREO 2
#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
|
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
...
...
@@ -628,7 +628,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
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
,
.
shutdown
=
skl_pcm_close
,
.
prepare
=
skl_pcm_prepare
,
...
...
@@ -637,15 +637,15 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.
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
,
};
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
,
};
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
,
.
hw_params
=
skl_link_hw_params
,
.
hw_free
=
skl_link_hw_free
,
...
...
@@ -674,6 +674,32 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.
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"
,
.
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
)
{
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
;
uuid_le
*
uuid_mod
;
int
i
,
ret
=
-
EIO
;
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
)
{
if
(
uuid_le_cmp
(
*
uuid_mod
,
module
->
uuid
)
==
0
)
{
mconfig
->
id
.
module_id
=
module
->
id
;
mconfig
->
is_loadable
=
module
->
is_loadable
;
return
0
;
if
(
mconfig
->
module
)
mconfig
->
module
->
loadable
=
module
->
is_loadable
;
ret
=
0
;
break
;
}
}
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
;
return
-
EIO
;
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
)
...
...
@@ -1284,7 +1346,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
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
,
.
ops
=
&
skl_platform_ops
,
.
pcm_new
=
skl_pcm_new
,
...
...
sound/soc/intel/skylake/skl-sst-dsp.c
View file @
460f623a
...
...
@@ -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
.
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
.
usage_count
[
i
]
=
0
;
}
...
...
@@ -351,6 +351,8 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
return
-
EINVAL
;
}
skl
->
cores
.
usage_count
[
core_id
]
++
;
if
(
skl
->
cores
.
state
[
core_id
]
==
SKL_DSP_RESET
)
{
ret
=
ctx
->
fw_ops
.
set_state_D0
(
ctx
,
core_id
);
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:
dev_dbg
(
ctx
->
dev
,
"core id %d state %d usage_count %d
\n
"
,
core_id
,
skl
->
cores
.
state
[
core_id
],
...
...
sound/soc/intel/skylake/skl-sst-ipc.c
View file @
460f623a
...
...
@@ -283,7 +283,7 @@ enum skl_ipc_module_msg {
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
)
{
if
(
tx_size
)
...
...
@@ -347,7 +347,7 @@ static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
}
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_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
ipc_message
*
msg
;
...
...
sound/soc/intel/skylake/skl-sst-ipc.h
View file @
460f623a
...
...
@@ -44,12 +44,10 @@ struct skl_ipc_header {
u32
extension
;
};
#define SKL_DSP_CORES_MAX 2
struct
skl_dsp_cores
{
unsigned
int
count
;
enum
skl_dsp_states
state
[
SKL_DSP_CORES_MAX
]
;
int
usage_count
[
SKL_DSP_CORES_MAX
]
;
enum
skl_dsp_states
*
state
;
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
);
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 */
sound/soc/intel/skylake/skl-sst-utils.c
View file @
460f623a
...
...
@@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name,
{
struct
skl_sst
*
skl
;
struct
sst_dsp
*
sst
;
int
ret
;
skl
=
devm_kzalloc
(
dev
,
sizeof
(
*
skl
),
GFP_KERNEL
);
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
;
init_waitqueue_head
(
&
skl
->
mod_load_wait
);
INIT_LIST_HEAD
(
&
sst
->
module_list
);
ret
=
skl_ipc_init
(
dev
,
skl
);
if
(
ret
)
return
ret
;
skl
->
is_first_boot
=
true
;
if
(
dsp
)
*
dsp
=
skl
;
return
ret
;
return
0
;
}
int
skl_prepare_lib_load
(
struct
skl_sst
*
skl
,
struct
skl_lib_info
*
linfo
,
...
...
sound/soc/intel/skylake/skl-sst.c
View file @
460f623a
...
...
@@ -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_D3
=
skl_set_dsp_D3
,
.
load_fw
=
skl_load_base_firmware
,
...
...
@@ -512,7 +512,7 @@ static struct skl_dsp_fw_ops skl_fw_ops = {
.
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_D3
=
skl_set_dsp_D3
,
.
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
),
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
;
}
s
kl
->
cores
.
count
=
2
;
s
st
->
fw_ops
=
skl_fw_ops
;
return
0
;
}
...
...
sound/soc/intel/skylake/skl-topology.c
View file @
460f623a
...
...
@@ -49,6 +49,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = {
{
0
,
1
,
2
,
3
},
};
#define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \
((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq))
void
skl_tplg_d0i3_get
(
struct
skl
*
skl
,
enum
d0i3_capability
caps
)
{
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
skl_sst
->
d0i3
;
...
...
@@ -153,8 +156,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl,
struct
skl_module_cfg
*
mconfig
)
{
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
u8
res_idx
=
mconfig
->
res_idx
;
struct
skl_module_res
*
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
if
(
skl
->
resource
.
mcps
+
mconfig
->
m
cps
>
skl
->
resource
.
max_mcps
)
{
if
(
skl
->
resource
.
mcps
+
res
->
cps
>
skl
->
resource
.
max_mcps
)
{
dev_err
(
ctx
->
dev
,
"%s: module_id %d instance %d
\n
"
,
__func__
,
mconfig
->
id
.
module_id
,
mconfig
->
id
.
instance_id
);
...
...
@@ -170,7 +175,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl,
static
void
skl_tplg_alloc_pipe_mcps
(
struct
skl
*
skl
,
struct
skl_module_cfg
*
mconfig
)
{
skl
->
resource
.
mcps
+=
mconfig
->
mcps
;
u8
res_idx
=
mconfig
->
res_idx
;
struct
skl_module_res
*
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
skl
->
resource
.
mcps
+=
res
->
cps
;
}
/*
...
...
@@ -179,7 +187,11 @@ static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
static
void
skl_tplg_free_pipe_mcps
(
struct
skl
*
skl
,
struct
skl_module_cfg
*
mconfig
)
{
skl
->
resource
.
mcps
-=
mconfig
->
mcps
;
u8
res_idx
=
mconfig
->
res_idx
;
struct
skl_module_res
*
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
skl
->
resource
.
mcps
-=
res
->
cps
;
}
/*
...
...
@@ -195,17 +207,21 @@ skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig)
static
void
skl_dump_mconfig
(
struct
skl_sst
*
ctx
,
struct
skl_module_cfg
*
mcfg
)
{
struct
skl_module_iface
*
iface
=
&
mcfg
->
module
->
formats
[
0
];
dev_dbg
(
ctx
->
dev
,
"Dumping config
\n
"
);
dev_dbg
(
ctx
->
dev
,
"Input Format:
\n
"
);
dev_dbg
(
ctx
->
dev
,
"channels = %d
\n
"
,
mcfg
->
in_fmt
[
0
].
channels
);
dev_dbg
(
ctx
->
dev
,
"s_freq = %d
\n
"
,
mcfg
->
in_fmt
[
0
].
s_freq
);
dev_dbg
(
ctx
->
dev
,
"ch_cfg = %d
\n
"
,
mcfg
->
in_fmt
[
0
].
ch_cfg
);
dev_dbg
(
ctx
->
dev
,
"valid bit depth = %d
\n
"
,
mcfg
->
in_fmt
[
0
].
valid_bit_depth
);
dev_dbg
(
ctx
->
dev
,
"channels = %d
\n
"
,
iface
->
inputs
[
0
].
fmt
.
channels
);
dev_dbg
(
ctx
->
dev
,
"s_freq = %d
\n
"
,
iface
->
inputs
[
0
].
fmt
.
s_freq
);
dev_dbg
(
ctx
->
dev
,
"ch_cfg = %d
\n
"
,
iface
->
inputs
[
0
].
fmt
.
ch_cfg
);
dev_dbg
(
ctx
->
dev
,
"valid bit depth = %d
\n
"
,
iface
->
inputs
[
0
].
fmt
.
valid_bit_depth
);
dev_dbg
(
ctx
->
dev
,
"Output Format:
\n
"
);
dev_dbg
(
ctx
->
dev
,
"channels = %d
\n
"
,
mcfg
->
out_fmt
[
0
].
channels
);
dev_dbg
(
ctx
->
dev
,
"s_freq = %d
\n
"
,
mcfg
->
out_fmt
[
0
].
s_freq
);
dev_dbg
(
ctx
->
dev
,
"valid bit depth = %d
\n
"
,
mcfg
->
out_fmt
[
0
].
valid_bit_depth
);
dev_dbg
(
ctx
->
dev
,
"ch_cfg = %d
\n
"
,
mcfg
->
out_fmt
[
0
].
ch_cfg
);
dev_dbg
(
ctx
->
dev
,
"channels = %d
\n
"
,
iface
->
outputs
[
0
].
fmt
.
channels
);
dev_dbg
(
ctx
->
dev
,
"s_freq = %d
\n
"
,
iface
->
outputs
[
0
].
fmt
.
s_freq
);
dev_dbg
(
ctx
->
dev
,
"valid bit depth = %d
\n
"
,
iface
->
outputs
[
0
].
fmt
.
valid_bit_depth
);
dev_dbg
(
ctx
->
dev
,
"ch_cfg = %d
\n
"
,
iface
->
outputs
[
0
].
fmt
.
ch_cfg
);
}
static
void
skl_tplg_update_chmap
(
struct
skl_module_fmt
*
fmt
,
int
chs
)
...
...
@@ -273,8 +289,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
struct
skl_module_fmt
*
in_fmt
,
*
out_fmt
;
/* Fixups will be applied to pin 0 only */
in_fmt
=
&
m_cfg
->
in_fmt
[
0
]
;
out_fmt
=
&
m_cfg
->
out_fmt
[
0
]
;
in_fmt
=
&
m_cfg
->
module
->
formats
[
0
].
inputs
[
0
].
fmt
;
out_fmt
=
&
m_cfg
->
module
->
formats
[
0
].
outputs
[
0
].
fmt
;
if
(
params
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
if
(
is_fe
)
{
...
...
@@ -312,21 +328,23 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
{
int
multiplier
=
1
;
struct
skl_module_fmt
*
in_fmt
,
*
out_fmt
;
struct
skl_module_res
*
res
;
/* Since fixups is applied to pin 0 only, ibs, obs needs
* change for pin 0 only
*/
in_fmt
=
&
mcfg
->
in_fmt
[
0
];
out_fmt
=
&
mcfg
->
out_fmt
[
0
];
res
=
&
mcfg
->
module
->
resources
[
0
];
in_fmt
=
&
mcfg
->
module
->
formats
[
0
].
inputs
[
0
].
fmt
;
out_fmt
=
&
mcfg
->
module
->
formats
[
0
].
outputs
[
0
].
fmt
;
if
(
mcfg
->
m_type
==
SKL_MODULE_TYPE_SRCINT
)
multiplier
=
5
;
mcfg
->
ibs
=
DIV_ROUND_UP
(
in_fmt
->
s_freq
,
1000
)
*
res
->
ibs
=
DIV_ROUND_UP
(
in_fmt
->
s_freq
,
1000
)
*
in_fmt
->
channels
*
(
in_fmt
->
bit_depth
>>
3
)
*
multiplier
;
mcfg
->
obs
=
DIV_ROUND_UP
(
out_fmt
->
s_freq
,
1000
)
*
res
->
obs
=
DIV_ROUND_UP
(
out_fmt
->
s_freq
,
1000
)
*
out_fmt
->
channels
*
(
out_fmt
->
bit_depth
>>
3
)
*
multiplier
;
}
...
...
@@ -365,6 +383,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
struct
nhlt_specific_cfg
*
cfg
;
struct
skl
*
skl
=
get_skl_ctx
(
ctx
->
dev
);
u8
dev_type
=
skl_tplg_be_dev_type
(
m_cfg
->
dev_type
);
int
fmt_idx
=
m_cfg
->
fmt_idx
;
struct
skl_module_iface
*
m_iface
=
&
m_cfg
->
module
->
formats
[
fmt_idx
];
/* check if we already have blob */
if
(
m_cfg
->
formats_config
.
caps_size
>
0
)
...
...
@@ -375,23 +395,23 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
case
SKL_DEVICE_DMIC
:
link_type
=
NHLT_LINK_DMIC
;
dir
=
SNDRV_PCM_STREAM_CAPTURE
;
s_freq
=
m_
cfg
->
in_fmt
[
0
]
.
s_freq
;
s_fmt
=
m_
cfg
->
in_fmt
[
0
]
.
bit_depth
;
ch
=
m_
cfg
->
in_fmt
[
0
]
.
channels
;
s_freq
=
m_
iface
->
inputs
[
0
].
fmt
.
s_freq
;
s_fmt
=
m_
iface
->
inputs
[
0
].
fmt
.
bit_depth
;
ch
=
m_
iface
->
inputs
[
0
].
fmt
.
channels
;
break
;
case
SKL_DEVICE_I2S
:
link_type
=
NHLT_LINK_SSP
;
if
(
m_cfg
->
hw_conn_type
==
SKL_CONN_SOURCE
)
{
dir
=
SNDRV_PCM_STREAM_PLAYBACK
;
s_freq
=
m_
cfg
->
out_fmt
[
0
]
.
s_freq
;
s_fmt
=
m_
cfg
->
out_fmt
[
0
]
.
bit_depth
;
ch
=
m_
cfg
->
out_fmt
[
0
]
.
channels
;
s_freq
=
m_
iface
->
outputs
[
0
].
fmt
.
s_freq
;
s_fmt
=
m_
iface
->
outputs
[
0
].
fmt
.
bit_depth
;
ch
=
m_
iface
->
outputs
[
0
].
fmt
.
channels
;
}
else
{
dir
=
SNDRV_PCM_STREAM_CAPTURE
;
s_freq
=
m_
cfg
->
in_fmt
[
0
]
.
s_freq
;
s_fmt
=
m_
cfg
->
in_fmt
[
0
]
.
bit_depth
;
ch
=
m_
cfg
->
in_fmt
[
0
]
.
channels
;
s_freq
=
m_
iface
->
inputs
[
0
].
fmt
.
s_freq
;
s_fmt
=
m_
iface
->
inputs
[
0
].
fmt
.
bit_depth
;
ch
=
m_
iface
->
inputs
[
0
].
fmt
.
channels
;
}
break
;
...
...
@@ -549,6 +569,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
struct
snd_soc_dapm_widget
*
w
;
struct
skl_module_cfg
*
mconfig
;
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
u8
cfg_idx
;
int
ret
=
0
;
list_for_each_entry
(
w_module
,
&
pipe
->
w_list
,
node
)
{
...
...
@@ -564,11 +585,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
return
-
EIO
;
}
cfg_idx
=
mconfig
->
pipe
->
cur_config_idx
;
mconfig
->
fmt_idx
=
mconfig
->
mod_cfg
[
cfg_idx
].
fmt_idx
;
mconfig
->
res_idx
=
mconfig
->
mod_cfg
[
cfg_idx
].
res_idx
;
/* check resource available */
if
(
!
skl_is_pipe_mcps_avail
(
skl
,
mconfig
))
return
-
ENOMEM
;
if
(
mconfig
->
is_
loadable
&&
ctx
->
dsp
->
fw_ops
.
load_mod
)
{
if
(
mconfig
->
module
->
loadable
&&
ctx
->
dsp
->
fw_ops
.
load_mod
)
{
ret
=
ctx
->
dsp
->
fw_ops
.
load_mod
(
ctx
->
dsp
,
mconfig
->
id
.
module_id
,
mconfig
->
guid
);
if
(
ret
<
0
)
...
...
@@ -596,24 +621,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
if
(
mconfig
->
id
.
pvt_id
<
0
)
return
ret
;
skl_tplg_set_module_init_data
(
w
);
ret
=
skl_dsp_get_core
(
ctx
->
dsp
,
mconfig
->
core_id
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to wake up core %d ret=%d
\n
"
,
mconfig
->
core_id
,
ret
);
return
ret
;
}
ret
=
skl_init_module
(
ctx
,
mconfig
);
if
(
ret
<
0
)
{
skl_put_pvt_id
(
ctx
,
uuid_mod
,
&
mconfig
->
id
.
pvt_id
);
return
ret
;
goto
err
;
}
skl_tplg_alloc_pipe_mcps
(
skl
,
mconfig
);
ret
=
skl_tplg_set_module_params
(
w
,
ctx
);
if
(
ret
<
0
)
return
ret
;
goto
err
;
}
return
0
;
err:
skl_dsp_put_core
(
ctx
->
dsp
,
mconfig
->
core_id
);
return
ret
;
}
static
int
skl_tplg_unload_pipe_modules
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
)
{
int
ret
;
int
ret
=
0
;
struct
skl_pipe_module
*
w_module
=
NULL
;
struct
skl_module_cfg
*
mconfig
=
NULL
;
...
...
@@ -622,7 +658,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
mconfig
=
w_module
->
w
->
priv
;
uuid_mod
=
(
uuid_le
*
)
mconfig
->
guid
;
if
(
mconfig
->
is_
loadable
&&
ctx
->
dsp
->
fw_ops
.
unload_mod
&&
if
(
mconfig
->
module
->
loadable
&&
ctx
->
dsp
->
fw_ops
.
unload_mod
&&
mconfig
->
m_state
>
SKL_MODULE_UNINIT
)
{
ret
=
ctx
->
dsp
->
fw_ops
.
unload_mod
(
ctx
->
dsp
,
mconfig
->
id
.
module_id
);
...
...
@@ -630,10 +666,76 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
return
-
EIO
;
}
skl_put_pvt_id
(
ctx
,
uuid_mod
,
&
mconfig
->
id
.
pvt_id
);
ret
=
skl_dsp_put_core
(
ctx
->
dsp
,
mconfig
->
core_id
);
if
(
ret
<
0
)
{
/* don't return; continue with other modules */
dev_err
(
ctx
->
dev
,
"Failed to sleep core %d ret=%d
\n
"
,
mconfig
->
core_id
,
ret
);
}
}
/* no modules to unload in this path, so return */
return
0
;
return
ret
;
}
/*
* Here, we select pipe format based on the pipe type and pipe
* direction to determine the current config index for the pipeline.
* The config index is then used to select proper module resources.
* Intermediate pipes currently have a fixed format hence we select the
* 0th configuratation by default for such pipes.
*/
static
int
skl_tplg_get_pipe_config
(
struct
skl
*
skl
,
struct
skl_module_cfg
*
mconfig
)
{
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
struct
skl_pipe
*
pipe
=
mconfig
->
pipe
;
struct
skl_pipe_params
*
params
=
pipe
->
p_params
;
struct
skl_path_config
*
pconfig
=
&
pipe
->
configs
[
0
];
struct
skl_pipe_fmt
*
fmt
=
NULL
;
bool
in_fmt
=
false
;
int
i
;
if
(
pipe
->
nr_cfgs
==
0
)
{
pipe
->
cur_config_idx
=
0
;
return
0
;
}
if
(
pipe
->
conn_type
==
SKL_PIPE_CONN_TYPE_NONE
)
{
dev_dbg
(
ctx
->
dev
,
"No conn_type detected, take 0th config
\n
"
);
pipe
->
cur_config_idx
=
0
;
pipe
->
memory_pages
=
pconfig
->
mem_pages
;
return
0
;
}
if
((
pipe
->
conn_type
==
SKL_PIPE_CONN_TYPE_FE
&&
pipe
->
direction
==
SNDRV_PCM_STREAM_PLAYBACK
)
||
(
pipe
->
conn_type
==
SKL_PIPE_CONN_TYPE_BE
&&
pipe
->
direction
==
SNDRV_PCM_STREAM_CAPTURE
))
in_fmt
=
true
;
for
(
i
=
0
;
i
<
pipe
->
nr_cfgs
;
i
++
)
{
pconfig
=
&
pipe
->
configs
[
i
];
if
(
in_fmt
)
fmt
=
&
pconfig
->
in_fmt
;
else
fmt
=
&
pconfig
->
out_fmt
;
if
(
CHECK_HW_PARAMS
(
params
->
ch
,
params
->
s_freq
,
params
->
s_fmt
,
fmt
->
channels
,
fmt
->
freq
,
fmt
->
bps
))
{
pipe
->
cur_config_idx
=
i
;
pipe
->
memory_pages
=
pconfig
->
mem_pages
;
dev_dbg
(
ctx
->
dev
,
"Using pipe config: %d
\n
"
,
i
);
return
0
;
}
}
dev_err
(
ctx
->
dev
,
"Invalid pipe config: %d %d %d for pipe: %d
\n
"
,
params
->
ch
,
params
->
s_freq
,
params
->
s_fmt
,
pipe
->
ppl_id
);
return
-
EINVAL
;
}
/*
...
...
@@ -655,6 +757,10 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
struct
skl_module_deferred_bind
*
modules
;
ret
=
skl_tplg_get_pipe_config
(
skl
,
mconfig
);
if
(
ret
<
0
)
return
ret
;
/* check resource available */
if
(
!
skl_is_pipe_mcps_avail
(
skl
,
mconfig
))
return
-
EBUSY
;
...
...
@@ -758,12 +864,12 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
* check all out/in pins are in bind state.
* if so set the module param
*/
for
(
i
=
0
;
i
<
mcfg
->
m
ax_out_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
mcfg
->
m
odule
->
max_output_pins
;
i
++
)
{
if
(
mcfg
->
m_out_pin
[
i
].
pin_state
!=
SKL_PIN_BIND_DONE
)
return
0
;
}
for
(
i
=
0
;
i
<
mcfg
->
m
ax_in_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
mcfg
->
m
odule
->
max_input_pins
;
i
++
)
{
if
(
mcfg
->
m_in_pin
[
i
].
pin_state
!=
SKL_PIN_BIND_DONE
)
return
0
;
}
...
...
@@ -814,7 +920,7 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl,
int
i
;
/* only supported for module with static pin connection */
for
(
i
=
0
;
i
<
dst
->
m
ax_in_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
dst
->
m
odule
->
max_input_pins
;
i
++
)
{
struct
skl_module_pin
*
pin
=
&
dst
->
m_in_pin
[
i
];
if
(
pin
->
is_dynamic
)
...
...
@@ -925,7 +1031,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
}
}
if
(
!
sink
)
if
(
!
sink
&&
next_sink
)
return
skl_tplg_bind_sinks
(
next_sink
,
skl
,
src_w
,
src_mconfig
);
return
0
;
...
...
@@ -1074,7 +1180,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
sink_mconfig
->
m
ax_in_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
sink_mconfig
->
m
odule
->
max_input_pins
;
i
++
)
{
if
(
sink_mconfig
->
m_in_pin
[
i
].
pin_state
==
SKL_PIN_BIND_DONE
)
{
src_mconfig
=
sink_mconfig
->
m_in_pin
[
i
].
tgt_mcfg
;
if
(
!
src_mconfig
)
...
...
@@ -1185,7 +1291,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
src_mconfig
->
m
ax_out_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
src_mconfig
->
m
odule
->
max_output_pins
;
i
++
)
{
if
(
src_mconfig
->
m_out_pin
[
i
].
pin_state
==
SKL_PIN_BIND_DONE
)
{
sink_mconfig
=
src_mconfig
->
m_out_pin
[
i
].
tgt_mcfg
;
if
(
!
sink_mconfig
)
...
...
@@ -1479,14 +1585,22 @@ int skl_tplg_update_pipe_params(struct device *dev,
struct
skl_module_cfg
*
mconfig
,
struct
skl_pipe_params
*
params
)
{
struct
skl_module_res
*
res
=
&
mconfig
->
module
->
resources
[
0
];
struct
skl
*
skl
=
get_skl_ctx
(
dev
);
struct
skl_module_fmt
*
format
=
NULL
;
u8
cfg_idx
=
mconfig
->
pipe
->
cur_config_idx
;
skl_tplg_fill_dma_id
(
mconfig
,
params
);
mconfig
->
fmt_idx
=
mconfig
->
mod_cfg
[
cfg_idx
].
fmt_idx
;
mconfig
->
res_idx
=
mconfig
->
mod_cfg
[
cfg_idx
].
res_idx
;
if
(
skl
->
nr_modules
)
return
0
;
if
(
params
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
format
=
&
mconfig
->
in_fmt
[
0
]
;
format
=
&
mconfig
->
module
->
formats
[
0
].
inputs
[
0
].
fmt
;
else
format
=
&
mconfig
->
out_fmt
[
0
]
;
format
=
&
mconfig
->
module
->
formats
[
0
].
outputs
[
0
].
fmt
;
/* set the hw_params */
format
->
s_freq
=
params
->
s_freq
;
...
...
@@ -1514,11 +1628,11 @@ int skl_tplg_update_pipe_params(struct device *dev,
}
if
(
params
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
mconfig
->
ibs
=
(
format
->
s_freq
/
1000
)
*
res
->
ibs
=
(
format
->
s_freq
/
1000
)
*
(
format
->
channels
)
*
(
format
->
bit_depth
>>
3
);
}
else
{
mconfig
->
obs
=
(
format
->
s_freq
/
1000
)
*
res
->
obs
=
(
format
->
s_freq
/
1000
)
*
(
format
->
channels
)
*
(
format
->
bit_depth
>>
3
);
}
...
...
@@ -1792,6 +1906,54 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
},
};
static
int
skl_tplg_fill_pipe_cfg
(
struct
device
*
dev
,
struct
skl_pipe
*
pipe
,
u32
tkn
,
u32
tkn_val
,
int
conf_idx
,
int
dir
)
{
struct
skl_pipe_fmt
*
fmt
;
struct
skl_path_config
*
config
;
switch
(
dir
)
{
case
SKL_DIR_IN
:
fmt
=
&
pipe
->
configs
[
conf_idx
].
in_fmt
;
break
;
case
SKL_DIR_OUT
:
fmt
=
&
pipe
->
configs
[
conf_idx
].
out_fmt
;
break
;
default:
dev_err
(
dev
,
"Invalid direction: %d
\n
"
,
dir
);
return
-
EINVAL
;
}
config
=
&
pipe
->
configs
[
conf_idx
];
switch
(
tkn
)
{
case
SKL_TKN_U32_CFG_FREQ
:
fmt
->
freq
=
tkn_val
;
break
;
case
SKL_TKN_U8_CFG_CHAN
:
fmt
->
channels
=
tkn_val
;
break
;
case
SKL_TKN_U8_CFG_BPS
:
fmt
->
bps
=
tkn_val
;
break
;
case
SKL_TKN_U32_PATH_MEM_PGS
:
config
->
mem_pages
=
tkn_val
;
break
;
default:
dev_err
(
dev
,
"Invalid token config: %d
\n
"
,
tkn
);
return
-
EINVAL
;
}
return
0
;
}
static
int
skl_tplg_fill_pipe_tkn
(
struct
device
*
dev
,
struct
skl_pipe
*
pipe
,
u32
tkn
,
u32
tkn_val
)
...
...
@@ -1814,6 +1976,14 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev,
pipe
->
lp_mode
=
tkn_val
;
break
;
case
SKL_TKN_U32_PIPE_DIRECTION
:
pipe
->
direction
=
tkn_val
;
break
;
case
SKL_TKN_U32_NUM_CONFIGS
:
pipe
->
nr_cfgs
=
tkn_val
;
break
;
default:
dev_err
(
dev
,
"Token not handled %d
\n
"
,
tkn
);
return
-
EINVAL
;
...
...
@@ -1930,27 +2100,9 @@ static int skl_tplg_fill_pins_info(struct device *dev,
* on the direction
*/
static
int
skl_tplg_fill_fmt
(
struct
device
*
dev
,
struct
skl_module_
cfg
*
mconfig
,
u32
tkn
,
u32
value
,
u32
dir
,
u32
pin_count
)
struct
skl_module_
fmt
*
dst_fmt
,
u32
tkn
,
u32
value
)
{
struct
skl_module_fmt
*
dst_fmt
;
switch
(
dir
)
{
case
SKL_DIR_IN
:
dst_fmt
=
mconfig
->
in_fmt
;
dst_fmt
+=
pin_count
;
break
;
case
SKL_DIR_OUT
:
dst_fmt
=
mconfig
->
out_fmt
;
dst_fmt
+=
pin_count
;
break
;
default:
dev_err
(
dev
,
"Invalid direction value
\n
"
);
return
-
EINVAL
;
}
switch
(
tkn
)
{
case
SKL_TKN_U32_FMT_CH
:
dst_fmt
->
channels
=
value
;
...
...
@@ -1992,6 +2144,32 @@ static int skl_tplg_fill_fmt(struct device *dev,
return
0
;
}
static
int
skl_tplg_widget_fill_fmt
(
struct
device
*
dev
,
struct
skl_module_iface
*
fmt
,
u32
tkn
,
u32
val
,
u32
dir
,
int
fmt_idx
)
{
struct
skl_module_fmt
*
dst_fmt
;
if
(
!
fmt
)
return
-
EINVAL
;
switch
(
dir
)
{
case
SKL_DIR_IN
:
dst_fmt
=
&
fmt
->
inputs
[
fmt_idx
].
fmt
;
break
;
case
SKL_DIR_OUT
:
dst_fmt
=
&
fmt
->
outputs
[
fmt_idx
].
fmt
;
break
;
default:
dev_err
(
dev
,
"Invalid direction: %d
\n
"
,
dir
);
return
-
EINVAL
;
}
return
skl_tplg_fill_fmt
(
dev
,
dst_fmt
,
tkn
,
val
);
}
static
int
skl_tplg_get_uuid
(
struct
device
*
dev
,
struct
skl_module_cfg
*
mconfig
,
struct
snd_soc_tplg_vendor_uuid_elem
*
uuid_tkn
)
{
...
...
@@ -2014,6 +2192,108 @@ static void skl_tplg_fill_pin_dynamic_val(
mpin
[
i
].
is_dynamic
=
value
;
}
/*
* Resource table in the manifest has pin specific resources
* like pin and pin buffer size
*/
static
int
skl_tplg_manifest_pin_res_tkn
(
struct
device
*
dev
,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
struct
skl_module_res
*
res
,
int
pin_idx
,
int
dir
)
{
struct
skl_module_pin_resources
*
m_pin
;
switch
(
dir
)
{
case
SKL_DIR_IN
:
m_pin
=
&
res
->
input
[
pin_idx
];
break
;
case
SKL_DIR_OUT
:
m_pin
=
&
res
->
output
[
pin_idx
];
break
;
default:
dev_err
(
dev
,
"Invalid pin direction: %d
\n
"
,
dir
);
return
-
EINVAL
;
}
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_MM_U32_RES_PIN_ID
:
m_pin
->
pin_index
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_PIN_BUF
:
m_pin
->
buf_size
=
tkn_elem
->
value
;
break
;
default:
dev_err
(
dev
,
"Invalid token: %d
\n
"
,
tkn_elem
->
token
);
return
-
EINVAL
;
}
return
0
;
}
/*
* Fill module specific resources from the manifest's resource
* table like CPS, DMA size, mem_pages.
*/
static
int
skl_tplg_fill_res_tkn
(
struct
device
*
dev
,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
struct
skl_module_res
*
res
,
int
pin_idx
,
int
dir
)
{
int
ret
,
tkn_count
=
0
;
if
(
!
res
)
return
-
EINVAL
;
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_MM_U32_CPS
:
res
->
cps
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_DMA_SIZE
:
res
->
dma_buffer_size
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_CPC
:
res
->
cpc
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_MEM_PAGES
:
res
->
is_pages
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_OBS
:
res
->
obs
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_IBS
:
res
->
ibs
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_MAX_MCPS
:
res
->
cps
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_RES_PIN_ID
:
case
SKL_TKN_MM_U32_PIN_BUF
:
ret
=
skl_tplg_manifest_pin_res_tkn
(
dev
,
tkn_elem
,
res
,
pin_idx
,
dir
);
if
(
ret
<
0
)
return
ret
;
break
;
default:
dev_err
(
dev
,
"Not a res type token: %d"
,
tkn_elem
->
token
);
return
-
EINVAL
;
}
tkn_count
++
;
return
tkn_count
;
}
/*
* Parse tokens to fill up the module private data
*/
...
...
@@ -2024,49 +2304,54 @@ static int skl_tplg_get_token(struct device *dev,
int
tkn_count
=
0
;
int
ret
;
static
int
is_pipe_exists
;
static
int
pin_index
,
dir
;
static
int
pin_index
,
dir
,
conf_idx
;
struct
skl_module_iface
*
iface
=
NULL
;
struct
skl_module_res
*
res
=
NULL
;
int
res_idx
=
mconfig
->
res_idx
;
int
fmt_idx
=
mconfig
->
fmt_idx
;
/*
* If the manifest structure contains no modules, fill all
* the module data to 0th index.
* res_idx and fmt_idx are default set to 0.
*/
if
(
skl
->
nr_modules
==
0
)
{
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
iface
=
&
mconfig
->
module
->
formats
[
fmt_idx
];
}
if
(
tkn_elem
->
token
>
SKL_TKN_MAX
)
return
-
EINVAL
;
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_U8_IN_QUEUE_COUNT
:
mconfig
->
max_in_queue
=
tkn_elem
->
value
;
mconfig
->
m_in_pin
=
devm_kzalloc
(
dev
,
mconfig
->
max_in_queue
*
sizeof
(
*
mconfig
->
m_in_pin
),
GFP_KERNEL
);
if
(
!
mconfig
->
m_in_pin
)
return
-
ENOMEM
;
mconfig
->
module
->
max_input_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_OUT_QUEUE_COUNT
:
mconfig
->
max_out_queue
=
tkn_elem
->
value
;
mconfig
->
m_out_pin
=
devm_kzalloc
(
dev
,
mconfig
->
max_out_queue
*
sizeof
(
*
mconfig
->
m_out_pin
),
GFP_KERNEL
);
if
(
!
mconfig
->
m_out_pin
)
return
-
ENOMEM
;
mconfig
->
module
->
max_output_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_DYN_IN_PIN
:
if
(
!
mconfig
->
m_in_pin
)
mconfig
->
m_in_pin
=
devm_kzalloc
(
dev
,
MAX_IN_QUEUE
*
sizeof
(
*
mconfig
->
m_in_pin
),
GFP_KERNEL
);
if
(
!
mconfig
->
m_in_pin
)
return
-
ENOMEM
;
skl_tplg_fill_pin_dynamic_val
(
mconfig
->
m_in_pin
,
mconfig
->
max_in_queue
,
tkn_elem
->
value
);
skl_tplg_fill_pin_dynamic_val
(
mconfig
->
m_in_pin
,
MAX_IN_QUEUE
,
tkn_elem
->
value
);
break
;
case
SKL_TKN_U8_DYN_OUT_PIN
:
if
(
!
mconfig
->
m_out_pin
)
mconfig
->
m_out_pin
=
devm_kzalloc
(
dev
,
MAX_IN_QUEUE
*
sizeof
(
*
mconfig
->
m_in_pin
),
GFP_KERNEL
);
if
(
!
mconfig
->
m_out_pin
)
return
-
ENOMEM
;
skl_tplg_fill_pin_dynamic_val
(
mconfig
->
m_out_pin
,
mconfig
->
max_out_queue
,
tkn_elem
->
value
);
skl_tplg_fill_pin_dynamic_val
(
mconfig
->
m_out_pin
,
MAX_OUT_QUEUE
,
tkn_elem
->
value
);
break
;
case
SKL_TKN_U8_TIME_SLOT
:
...
...
@@ -2094,19 +2379,13 @@ static int skl_tplg_get_token(struct device *dev,
break
;
case
SKL_TKN_U32_MEM_PAGES
:
mconfig
->
mem_pages
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_MAX_MCPS
:
mconfig
->
mcps
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_OBS
:
mconfig
->
obs
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_IBS
:
mconfig
->
ibs
=
tkn_elem
->
value
;
ret
=
skl_tplg_fill_res_tkn
(
dev
,
tkn_elem
,
res
,
dir
,
pin_index
);
if
(
ret
<
0
)
return
ret
;
break
;
case
SKL_TKN_U32_VBUS_ID
:
...
...
@@ -2139,10 +2418,16 @@ static int skl_tplg_get_token(struct device *dev,
break
;
case
SKL_TKN_U32_PIPE_CONFIG_ID
:
conf_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_PIPE_CONN_TYPE
:
case
SKL_TKN_U32_PIPE_PRIORITY
:
case
SKL_TKN_U32_PIPE_MEM_PGS
:
case
SKL_TKN_U32_PMODE
:
case
SKL_TKN_U32_PIPE_DIRECTION
:
case
SKL_TKN_U32_NUM_CONFIGS
:
if
(
is_pipe_exists
)
{
ret
=
skl_tplg_fill_pipe_tkn
(
dev
,
mconfig
->
pipe
,
tkn_elem
->
token
,
tkn_elem
->
value
);
...
...
@@ -2152,6 +2437,27 @@ static int skl_tplg_get_token(struct device *dev,
break
;
case
SKL_TKN_U32_PATH_MEM_PGS
:
case
SKL_TKN_U32_CFG_FREQ
:
case
SKL_TKN_U8_CFG_CHAN
:
case
SKL_TKN_U8_CFG_BPS
:
if
(
mconfig
->
pipe
->
nr_cfgs
)
{
ret
=
skl_tplg_fill_pipe_cfg
(
dev
,
mconfig
->
pipe
,
tkn_elem
->
token
,
tkn_elem
->
value
,
conf_idx
,
dir
);
if
(
ret
<
0
)
return
ret
;
}
break
;
case
SKL_TKN_CFG_MOD_RES_ID
:
mconfig
->
mod_cfg
[
conf_idx
].
res_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_CFG_MOD_FMT_ID
:
mconfig
->
mod_cfg
[
conf_idx
].
fmt_idx
=
tkn_elem
->
value
;
break
;
/*
* SKL_TKN_U32_DIR_PIN_COUNT token has the value for both
* direction and the pin count. The first four bits represent
...
...
@@ -2172,7 +2478,7 @@ static int skl_tplg_get_token(struct device *dev,
case
SKL_TKN_U32_FMT_INTERLEAVE
:
case
SKL_TKN_U32_FMT_SAMPLE_TYPE
:
case
SKL_TKN_U32_FMT_CH_MAP
:
ret
=
skl_tplg_
fill_fmt
(
dev
,
mconfig
,
tkn_elem
->
token
,
ret
=
skl_tplg_
widget_fill_fmt
(
dev
,
iface
,
tkn_elem
->
token
,
tkn_elem
->
value
,
dir
,
pin_index
);
if
(
ret
<
0
)
...
...
@@ -2397,11 +2703,11 @@ static void skl_clear_pin_config(struct snd_soc_platform *platform,
strlen
(
platform
->
component
.
name
)))
{
mconfig
=
w
->
priv
;
pipe
=
mconfig
->
pipe
;
for
(
i
=
0
;
i
<
mconfig
->
m
ax_in_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
mconfig
->
m
odule
->
max_input_pins
;
i
++
)
{
mconfig
->
m_in_pin
[
i
].
in_use
=
false
;
mconfig
->
m_in_pin
[
i
].
pin_state
=
SKL_PIN_UNBIND
;
}
for
(
i
=
0
;
i
<
mconfig
->
m
ax_out_queue
;
i
++
)
{
for
(
i
=
0
;
i
<
mconfig
->
m
odule
->
max_output_pins
;
i
++
)
{
mconfig
->
m_out_pin
[
i
].
in_use
=
false
;
mconfig
->
m_out_pin
[
i
].
pin_state
=
SKL_PIN_UNBIND
;
}
...
...
@@ -2460,6 +2766,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
if
(
!
mconfig
)
return
-
ENOMEM
;
if
(
skl
->
nr_modules
==
0
)
{
mconfig
->
module
=
devm_kzalloc
(
bus
->
dev
,
sizeof
(
*
mconfig
->
module
),
GFP_KERNEL
);
if
(
!
mconfig
->
module
)
return
-
ENOMEM
;
}
w
->
priv
=
mconfig
;
/*
...
...
@@ -2602,13 +2915,13 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
str_elem
->
string
,
ARRAY_SIZE
(
skl
->
skl_sst
->
lib_info
[
ref_count
].
name
));
ref_count
++
;
tkn_count
++
;
break
;
default:
dev_err
(
dev
,
"Not a string token %d
\n
"
,
str_elem
->
token
);
break
;
}
tkn_count
++
;
return
tkn_count
;
}
...
...
@@ -2634,26 +2947,236 @@ static int skl_tplg_get_str_tkn(struct device *dev,
return
tkn_count
;
}
static
int
skl_tplg_manifest_fill_fmt
(
struct
device
*
dev
,
struct
skl_module_iface
*
fmt
,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
u32
dir
,
int
fmt_idx
)
{
struct
skl_module_pin_fmt
*
dst_fmt
;
struct
skl_module_fmt
*
mod_fmt
;
int
ret
;
if
(
!
fmt
)
return
-
EINVAL
;
switch
(
dir
)
{
case
SKL_DIR_IN
:
dst_fmt
=
&
fmt
->
inputs
[
fmt_idx
];
break
;
case
SKL_DIR_OUT
:
dst_fmt
=
&
fmt
->
outputs
[
fmt_idx
];
break
;
default:
dev_err
(
dev
,
"Invalid direction: %d
\n
"
,
dir
);
return
-
EINVAL
;
}
mod_fmt
=
&
dst_fmt
->
fmt
;
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_MM_U32_INTF_PIN_ID
:
dst_fmt
->
id
=
tkn_elem
->
value
;
break
;
default:
ret
=
skl_tplg_fill_fmt
(
dev
,
mod_fmt
,
tkn_elem
->
token
,
tkn_elem
->
value
);
if
(
ret
<
0
)
return
ret
;
break
;
}
return
0
;
}
static
int
skl_tplg_fill_mod_info
(
struct
device
*
dev
,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
struct
skl_module
*
mod
)
{
if
(
!
mod
)
return
-
EINVAL
;
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_U8_IN_PIN_TYPE
:
mod
->
input_pin_type
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_OUT_PIN_TYPE
:
mod
->
output_pin_type
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_IN_QUEUE_COUNT
:
mod
->
max_input_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_OUT_QUEUE_COUNT
:
mod
->
max_output_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U8_NUM_RES
:
mod
->
nr_resources
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U8_NUM_INTF
:
mod
->
nr_interfaces
=
tkn_elem
->
value
;
break
;
default:
dev_err
(
dev
,
"Invalid mod info token %d"
,
tkn_elem
->
token
);
return
-
EINVAL
;
}
return
0
;
}
static
int
skl_tplg_get_int_tkn
(
struct
device
*
dev
,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
struct
skl
*
skl
)
{
int
tkn_count
=
0
;
int
tkn_count
=
0
,
ret
;
static
int
mod_idx
,
res_val_idx
,
intf_val_idx
,
dir
,
pin_idx
;
struct
skl_module_res
*
res
=
NULL
;
struct
skl_module_iface
*
fmt
=
NULL
;
struct
skl_module
*
mod
=
NULL
;
int
i
;
if
(
skl
->
modules
)
{
mod
=
skl
->
modules
[
mod_idx
];
res
=
&
mod
->
resources
[
res_val_idx
];
fmt
=
&
mod
->
formats
[
intf_val_idx
];
}
switch
(
tkn_elem
->
token
)
{
case
SKL_TKN_U32_LIB_COUNT
:
skl
->
skl_sst
->
lib_count
=
tkn_elem
->
value
;
tkn_count
++
;
break
;
case
SKL_TKN_U8_NUM_MOD
:
skl
->
nr_modules
=
tkn_elem
->
value
;
skl
->
modules
=
devm_kcalloc
(
dev
,
skl
->
nr_modules
,
sizeof
(
*
skl
->
modules
),
GFP_KERNEL
);
if
(
!
skl
->
modules
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
skl
->
nr_modules
;
i
++
)
{
skl
->
modules
[
i
]
=
devm_kzalloc
(
dev
,
sizeof
(
struct
skl_module
),
GFP_KERNEL
);
if
(
!
skl
->
modules
[
i
])
return
-
ENOMEM
;
}
break
;
case
SKL_TKN_MM_U8_MOD_IDX
:
mod_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_IN_PIN_TYPE
:
case
SKL_TKN_U8_OUT_PIN_TYPE
:
case
SKL_TKN_U8_IN_QUEUE_COUNT
:
case
SKL_TKN_U8_OUT_QUEUE_COUNT
:
case
SKL_TKN_MM_U8_NUM_RES
:
case
SKL_TKN_MM_U8_NUM_INTF
:
ret
=
skl_tplg_fill_mod_info
(
dev
,
tkn_elem
,
mod
);
if
(
ret
<
0
)
return
ret
;
break
;
case
SKL_TKN_U32_DIR_PIN_COUNT
:
dir
=
tkn_elem
->
value
&
SKL_IN_DIR_BIT_MASK
;
pin_idx
=
(
tkn_elem
->
value
&
SKL_PIN_COUNT_MASK
)
>>
4
;
break
;
case
SKL_TKN_MM_U32_RES_ID
:
if
(
!
res
)
return
-
EINVAL
;
res
->
id
=
tkn_elem
->
value
;
res_val_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_FMT_ID
:
if
(
!
fmt
)
return
-
EINVAL
;
fmt
->
fmt_idx
=
tkn_elem
->
value
;
intf_val_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_CPS
:
case
SKL_TKN_MM_U32_DMA_SIZE
:
case
SKL_TKN_MM_U32_CPC
:
case
SKL_TKN_U32_MEM_PAGES
:
case
SKL_TKN_U32_OBS
:
case
SKL_TKN_U32_IBS
:
case
SKL_TKN_MM_U32_RES_PIN_ID
:
case
SKL_TKN_MM_U32_PIN_BUF
:
ret
=
skl_tplg_fill_res_tkn
(
dev
,
tkn_elem
,
res
,
pin_idx
,
dir
);
if
(
ret
<
0
)
return
ret
;
break
;
case
SKL_TKN_MM_U32_NUM_IN_FMT
:
if
(
!
fmt
)
return
-
EINVAL
;
res
->
nr_input_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_MM_U32_NUM_OUT_FMT
:
if
(
!
fmt
)
return
-
EINVAL
;
res
->
nr_output_pins
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_FMT_CH
:
case
SKL_TKN_U32_FMT_FREQ
:
case
SKL_TKN_U32_FMT_BIT_DEPTH
:
case
SKL_TKN_U32_FMT_SAMPLE_SIZE
:
case
SKL_TKN_U32_FMT_CH_CONFIG
:
case
SKL_TKN_U32_FMT_INTERLEAVE
:
case
SKL_TKN_U32_FMT_SAMPLE_TYPE
:
case
SKL_TKN_U32_FMT_CH_MAP
:
case
SKL_TKN_MM_U32_INTF_PIN_ID
:
ret
=
skl_tplg_manifest_fill_fmt
(
dev
,
fmt
,
tkn_elem
,
dir
,
pin_idx
);
if
(
ret
<
0
)
return
ret
;
break
;
default:
dev_err
(
dev
,
"Not a manifest token %d
\n
"
,
tkn_elem
->
token
);
return
-
EINVAL
;
}
tkn_count
++
;
return
tkn_count
;
}
static
int
skl_tplg_get_manifest_uuid
(
struct
device
*
dev
,
struct
skl
*
skl
,
struct
snd_soc_tplg_vendor_uuid_elem
*
uuid_tkn
)
{
static
int
ref_count
;
struct
skl_module
*
mod
;
if
(
uuid_tkn
->
token
==
SKL_TKN_UUID
)
{
mod
=
skl
->
modules
[
ref_count
];
memcpy
(
&
mod
->
uuid
,
&
uuid_tkn
->
uuid
,
sizeof
(
uuid_tkn
->
uuid
));
ref_count
++
;
}
else
{
dev_err
(
dev
,
"Not an UUID token tkn %d
\n
"
,
uuid_tkn
->
token
);
return
-
EINVAL
;
}
return
0
;
}
/*
* Fill the manifest structure by parsing the tokens based on the
* type.
...
...
@@ -2686,7 +3209,11 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
continue
;
case
SND_SOC_TPLG_TUPLE_TYPE_UUID
:
dev_warn
(
dev
,
"no uuid tokens for skl tplf manifest
\n
"
);
ret
=
skl_tplg_get_manifest_uuid
(
dev
,
skl
,
array
->
uuid
);
if
(
ret
<
0
)
return
ret
;
tuple_size
+=
sizeof
(
*
array
->
uuid
);
continue
;
default:
...
...
@@ -2703,14 +3230,12 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
tkn_count
=
tkn_count
+
ret
;
tkn_elem
++
;
tuple_size
+=
tkn_count
*
sizeof
(
struct
snd_soc_tplg_vendor_value_elem
);
break
;
}
tuple_size
+=
(
tkn_count
*
sizeof
(
*
tkn_elem
));
tkn_count
=
0
;
}
return
0
;
return
off
;
}
/*
...
...
@@ -2733,11 +3258,10 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
num_blocks
=
ret
;
off
+=
array
->
size
;
array
=
(
struct
snd_soc_tplg_vendor_array
*
)
(
manifest
->
priv
.
data
+
off
);
/* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
while
(
num_blocks
>
0
)
{
array
=
(
struct
snd_soc_tplg_vendor_array
*
)
(
manifest
->
priv
.
data
+
off
);
ret
=
skl_tplg_get_desc_blocks
(
dev
,
array
);
if
(
ret
<
0
)
...
...
@@ -2771,6 +3295,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
}
else
{
return
-
EINVAL
;
}
off
+=
ret
;
}
return
0
;
...
...
sound/soc/intel/skylake/skl-topology.h
View file @
460f623a
...
...
@@ -44,6 +44,13 @@
#define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF
#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
{
SKL_CHANNEL_LEFT
=
0
,
SKL_CHANNEL_RIGHT
=
1
,
...
...
@@ -131,6 +138,11 @@ struct skl_cpr_cfg {
struct
skl_cpr_gtw_cfg
gtw_cfg
;
}
__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_base_cfg
base_cfg
;
...
...
@@ -214,6 +226,7 @@ struct skl_kpb_params {
};
struct
skl_module_inst_id
{
uuid_le
mod_uuid
;
int
module_id
;
u32
instance_id
;
int
pvt_id
;
...
...
@@ -266,6 +279,23 @@ struct skl_pipe_params {
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
{
u8
ppl_id
;
u8
pipe_priority
;
...
...
@@ -274,6 +304,10 @@ struct skl_pipe {
u8
lp_mode
;
struct
skl_pipe_params
*
p_params
;
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
;
bool
passthru
;
};
...
...
@@ -292,9 +326,57 @@ enum d0i3_capability {
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
{
u8
guid
[
16
];
struct
skl_module_inst_id
id
;
struct
skl_module
*
module
;
int
res_idx
;
int
fmt_idx
;
u8
domain
;
bool
homogenous_inputs
;
bool
homogenous_outputs
;
...
...
@@ -329,6 +411,7 @@ struct skl_module_cfg {
enum
skl_module_state
m_state
;
struct
skl_pipe
*
pipe
;
struct
skl_specific_cfg
formats_config
;
struct
skl_pipe_mcfg
mod_cfg
[
SKL_MAX_MODULES_IN_PIPE
];
};
struct
skl_algo_data
{
...
...
sound/soc/intel/skylake/skl.c
View file @
460f623a
...
...
@@ -415,7 +415,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
snd_hdac_ext_stop_streams
(
ebus
);
if
(
bus
->
irq
>=
0
)
free_irq
(
bus
->
irq
,
(
void
*
)
bus
);
free_irq
(
bus
->
irq
,
(
void
*
)
e
bus
);
snd_hdac_bus_free_stream_pages
(
bus
);
snd_hdac_stream_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 */
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
);
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
=
{
...
...
@@ -612,9 +610,7 @@ static void skl_probe_work(struct work_struct *work)
dev_info
(
bus
->
dev
,
"no hda codecs found!
\n
"
);
/* create codec instances */
err
=
skl_codec_create
(
ebus
);
if
(
err
<
0
)
goto
out_err
;
skl_codec_create
(
ebus
);
if
(
IS_ENABLED
(
CONFIG_SND_SOC_HDAC_HDMI
))
{
err
=
snd_hdac_display_power
(
bus
,
false
);
...
...
@@ -702,6 +698,8 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
return
-
ENXIO
;
}
skl_init_chip
(
bus
,
true
);
snd_hdac_bus_parse_capabilities
(
bus
);
if
(
skl_acquire_irq
(
ebus
,
0
)
<
0
)
...
...
@@ -982,6 +980,11 @@ static struct sst_acpi_mach sst_kbl_devdata[] = {
.
quirk_data
=
&
kbl_poppy_codecs
,
.
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 */
static
const
struct
pci_device_id
skl_ids
[]
=
{
/* Sunrise Point-LP */
...
...
@@ -1009,6 +1020,9 @@ static const struct pci_device_id skl_ids[] = {
/* GLK */
{
PCI_DEVICE
(
0x8086
,
0x3198
),
.
driver_data
=
(
unsigned
long
)
&
sst_glk_devdata
},
/* CNL */
{
PCI_DEVICE
(
0x8086
,
0x9dc8
),
.
driver_data
=
(
unsigned
long
)
&
sst_cnl_devdata
},
{
0
,
}
};
MODULE_DEVICE_TABLE
(
pci
,
skl_ids
);
...
...
sound/soc/intel/skylake/skl.h
View file @
460f623a
...
...
@@ -71,6 +71,8 @@ struct skl {
struct
work_struct
probe_work
;
struct
skl_debug
*
debugfs
;
u8
nr_modules
;
struct
skl_module
**
modules
;
};
#define skl_to_ebus(s) (&(s)->ebus)
...
...
@@ -90,6 +92,7 @@ struct skl_machine_pdata {
struct
skl_dsp_ops
{
int
id
;
unsigned
int
num_cores
;
struct
skl_dsp_loader_ops
(
*
loader_ops
)(
void
);
int
(
*
init
)(
struct
device
*
dev
,
void
__iomem
*
mmio_base
,
int
irq
,
const
char
*
fw_name
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment