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
Kirill Smelkov
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