Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
44d62462
Commit
44d62462
authored
Jul 24, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
parents
0d911262
1b00126c
Changes
34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
1992 additions
and
450 deletions
+1992
-450
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdac_hdmi.c
+5
-2
sound/soc/codecs/rt286.c
sound/soc/codecs/rt286.c
+7
-0
sound/soc/intel/Kconfig
sound/soc/intel/Kconfig
+49
-24
sound/soc/intel/atom/sst/sst_acpi.c
sound/soc/intel/atom/sst/sst_acpi.c
+43
-1
sound/soc/intel/boards/Makefile
sound/soc/intel/boards/Makefile
+2
-0
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/boards/bxt_da7219_max98357a.c
+460
-0
sound/soc/intel/boards/bxt_rt298.c
sound/soc/intel/boards/bxt_rt298.c
+118
-0
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/cht_bsw_rt5645.c
+19
-1
sound/soc/intel/boards/skl_nau88l25_max98357a.c
sound/soc/intel/boards/skl_nau88l25_max98357a.c
+46
-5
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
+46
-5
sound/soc/intel/boards/skl_rt286.c
sound/soc/intel/boards/skl_rt286.c
+9
-0
sound/soc/intel/common/Makefile
sound/soc/intel/common/Makefile
+2
-2
sound/soc/intel/common/sst-acpi.h
sound/soc/intel/common/sst-acpi.h
+2
-2
sound/soc/intel/common/sst-dsp-priv.h
sound/soc/intel/common/sst-dsp-priv.h
+0
-4
sound/soc/intel/common/sst-dsp.c
sound/soc/intel/common/sst-dsp.c
+1
-68
sound/soc/intel/common/sst-dsp.h
sound/soc/intel/common/sst-dsp.h
+1
-1
sound/soc/intel/common/sst-firmware.c
sound/soc/intel/common/sst-firmware.c
+68
-0
sound/soc/intel/haswell/sst-haswell-pcm.c
sound/soc/intel/haswell/sst-haswell-pcm.c
+0
-1
sound/soc/intel/skylake/Makefile
sound/soc/intel/skylake/Makefile
+1
-1
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/bxt-sst.c
+152
-50
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-messages.c
+42
-11
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl-nhlt.c
+40
-0
sound/soc/intel/skylake/skl-nhlt.h
sound/soc/intel/skylake/skl-nhlt.h
+22
-0
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-pcm.c
+31
-62
sound/soc/intel/skylake/skl-sst-dsp.c
sound/soc/intel/skylake/skl-sst-dsp.c
+186
-74
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst-dsp.h
+70
-32
sound/soc/intel/skylake/skl-sst-ipc.c
sound/soc/intel/skylake/skl-sst-ipc.c
+2
-2
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst-ipc.h
+18
-0
sound/soc/intel/skylake/skl-sst-utils.c
sound/soc/intel/skylake/skl-sst-utils.c
+256
-0
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-sst.c
+90
-34
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.c
+157
-60
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-topology.h
+5
-1
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.c
+32
-7
sound/soc/intel/skylake/skl.h
sound/soc/intel/skylake/skl.h
+10
-0
No files found.
sound/soc/codecs/hdac_hdmi.c
View file @
44d62462
...
...
@@ -1124,8 +1124,10 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
}
hdac_hdmi_parse_eld
(
edev
,
pin
);
print_hex_dump_bytes
(
"ELD: "
,
DUMP_PREFIX_OFFSET
,
pin
->
eld
.
eld_buffer
,
pin
->
eld
.
eld_size
);
print_hex_dump_debug
(
"ELD: "
,
DUMP_PREFIX_OFFSET
,
16
,
1
,
pin
->
eld
.
eld_buffer
,
pin
->
eld
.
eld_size
,
true
);
}
else
{
pin
->
eld
.
monitor_present
=
false
;
pin
->
eld
.
eld_valid
=
false
;
...
...
@@ -1816,6 +1818,7 @@ static const struct dev_pm_ops hdac_hdmi_pm = {
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
),
{}
};
...
...
sound/soc/codecs/rt286.c
View file @
44d62462
...
...
@@ -1100,6 +1100,13 @@ static const struct dmi_system_id force_combo_jack_table[] = {
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Skylake Client platform"
)
}
},
{
.
ident
=
"Intel Kabylake RVP"
,
.
matches
=
{
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Kabylake Client platform"
)
}
},
{
}
};
...
...
sound/soc/intel/Kconfig
View file @
44d62462
...
...
@@ -7,7 +7,7 @@ config SND_MFLD_MACHINE
help
This adds support for ASoC machine driver for Intel(R) MID Medfield platform
used as alsa device in audio substem in Intel(R) MID devices
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SST_MFLD_PLATFORM
...
...
@@ -25,7 +25,6 @@ config SND_SST_IPC_ACPI
tristate
select SND_SST_IPC
select SND_SOC_INTEL_SST
depends on ACPI
config SND_SOC_INTEL_SST
tristate
...
...
@@ -33,6 +32,12 @@ config SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_MATCH if ACPI
depends on (X86 || COMPILE_TEST)
# firmware stuff depends DW_DMAC_CORE; since there is no depends-on from
# the reverse selection, each machine driver needs to select
# SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE
config SND_SOC_INTEL_SST_FIRMWARE
tristate
config SND_SOC_INTEL_SST_ACPI
tristate
...
...
@@ -48,16 +53,33 @@ config SND_SOC_INTEL_BAYTRAIL
config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on DW_DMAC_CORE
=y
depends on DW_DMAC_CORE
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640
help
This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell
Ultrabook platforms.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode"
depends on X86 && ACPI && I2C
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SKYLAKE
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_HDA_DSP_LOADER
help
This adds support for ASoC machine driver for Broxton-P platforms
with DA7219 + MAX98357A I2S audio codec.
Say Y if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_BXT_RT298_MACH
tristate "ASoC Audio driver for Broxton with RT298 I2S mode"
depends on X86 && ACPI && I2C
...
...
@@ -70,26 +92,28 @@ config SND_SOC_INTEL_BXT_RT298_MACH
help
This adds support for ASoC machine driver for Broxton platforms
with RT286 I2S audio codec.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
depends on DW_DMAC_CORE
=y
&& (SND_SST_IPC_ACPI = n)
depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640
help
This adds audio driver for Intel Baytrail platform based boards
with the RT5640 audio codec. This driver is deprecated, use
SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality
SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality
.
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
depends on DW_DMAC_CORE
=y
&& (SND_SST_IPC_ACPI = n)
depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
help
...
...
@@ -100,19 +124,20 @@ config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
I2C_DESIGNWARE_PLATFORM
depends on DW_DMAC_CORE
=y
depends on DW_DMAC_CORE
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT286
help
This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
Ultrabook platforms.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_BYTCR_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
depends on X86 && I2C
depends on X86 && I2C
&& ACPI
select SND_SOC_RT5640
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
...
...
@@ -120,12 +145,12 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH
help
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5640 audio codec.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_BYTCR_RT5651_MACH
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec"
depends on X86 && I2C
depends on X86 && I2C
&& ACPI
select SND_SOC_RT5651
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
...
...
@@ -133,12 +158,12 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
help
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5651 audio codec.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec"
depends on X86_INTEL_LPSS && I2C
depends on X86_INTEL_LPSS && I2C
&& ACPI
select SND_SOC_RT5670
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
...
...
@@ -146,12 +171,12 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with RT5672 audio codec.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec"
depends on X86_INTEL_LPSS && I2C
depends on X86_INTEL_LPSS && I2C
&& ACPI
select SND_SOC_RT5645
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
...
...
@@ -163,16 +188,16 @@ config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with MAX98090 & TI codec"
depends on X86_INTEL_LPSS && I2C
depends on X86_INTEL_LPSS && I2C
&& ACPI
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
select SND_SOC_INTEL_SST_MATCH if ACPI
help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with MAX98090 audio codec it also can support TI jack chip as aux device.
If unsure select "N".
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with MAX98090 audio codec it also can support TI jack chip as aux device.
If unsure select "N".
config SND_SOC_INTEL_SKYLAKE
tristate
...
...
@@ -192,7 +217,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH
help
This adds support for ASoC machine driver for Skylake platforms
with RT286 I2S audio codec.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
...
...
@@ -207,7 +232,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + SSM4567.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
...
...
@@ -222,5 +247,5 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + MAX98357A.
Say Y if you have such a device
Say Y if you have such a device
.
If unsure select "N".
sound/soc/intel/atom/sst/sst_acpi.c
View file @
44d62462
...
...
@@ -28,6 +28,7 @@
#include <linux/firmware.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <asm/platform_sst_audio.h>
#include <sound/core.h>
...
...
@@ -237,6 +238,9 @@ static int sst_acpi_probe(struct platform_device *pdev)
dev_err
(
dev
,
"No matching machine driver found
\n
"
);
return
-
ENODEV
;
}
if
(
mach
->
machine_quirk
)
mach
=
mach
->
machine_quirk
(
mach
);
pdata
=
mach
->
pdata
;
ret
=
kstrtouint
(
id
->
id
,
16
,
&
dev_id
);
...
...
@@ -320,6 +324,44 @@ static int sst_acpi_remove(struct platform_device *pdev)
return
0
;
}
static
unsigned
long
cht_machine_id
;
#define CHT_SURFACE_MACH 1
static
int
cht_surface_quirk_cb
(
const
struct
dmi_system_id
*
id
)
{
cht_machine_id
=
CHT_SURFACE_MACH
;
return
1
;
}
static
const
struct
dmi_system_id
cht_table
[]
=
{
{
.
callback
=
cht_surface_quirk_cb
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Microsoft Corporation"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Surface 3"
),
},
},
};
static
struct
sst_acpi_mach
cht_surface_mach
=
{
"10EC5640"
,
"cht-bsw-rt5645"
,
"intel/fw_sst_22a8.bin"
,
"cht-bsw"
,
NULL
,
&
chv_platform_data
};
static
struct
sst_acpi_mach
*
cht_quirk
(
void
*
arg
)
{
struct
sst_acpi_mach
*
mach
=
arg
;
dmi_check_system
(
cht_table
);
if
(
cht_machine_id
==
CHT_SURFACE_MACH
)
return
&
cht_surface_mach
;
else
return
mach
;
}
static
struct
sst_acpi_mach
sst_acpi_bytcr
[]
=
{
{
"10EC5640"
,
"bytcr_rt5640"
,
"intel/fw_sst_0f28.bin"
,
"bytcr_rt5640"
,
NULL
,
&
byt_rvp_platform_data
},
...
...
@@ -343,7 +385,7 @@ static struct sst_acpi_mach sst_acpi_chv[] = {
{
"193C9890"
,
"cht-bsw-max98090"
,
"intel/fw_sst_22a8.bin"
,
"cht-bsw"
,
NULL
,
&
chv_platform_data
},
/* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
{
"10EC5640"
,
"bytcr_rt5640"
,
"intel/fw_sst_22a8.bin"
,
"bytcr_rt5640"
,
NULL
,
{
"10EC5640"
,
"bytcr_rt5640"
,
"intel/fw_sst_22a8.bin"
,
"bytcr_rt5640"
,
cht_quirk
,
&
chv_platform_data
},
{},
...
...
sound/soc/intel/boards/Makefile
View file @
44d62462
...
...
@@ -2,6 +2,7 @@ snd-soc-sst-haswell-objs := haswell.o
snd-soc-sst-byt-rt5640-mach-objs
:=
byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs
:=
byt-max98090.o
snd-soc-sst-broadwell-objs
:=
broadwell.o
snd-soc-sst-bxt-da7219_max98357a-objs
:=
bxt_da7219_max98357a.o
snd-soc-sst-bxt-rt298-objs
:=
bxt_rt298.o
snd-soc-sst-bytcr-rt5640-objs
:=
bytcr_rt5640.o
snd-soc-sst-bytcr-rt5651-objs
:=
bytcr_rt5651.o
...
...
@@ -15,6 +16,7 @@ snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH)
+=
snd-soc-sst-haswell.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH)
+=
snd-soc-sst-byt-rt5640-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH)
+=
snd-soc-sst-byt-max98090-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH)
+=
snd-soc-sst-bxt-da7219_max98357a.o
obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH)
+=
snd-soc-sst-bxt-rt298.o
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH)
+=
snd-soc-sst-broadwell.o
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH)
+=
snd-soc-sst-bytcr-rt5640.o
...
...
sound/soc/intel/boards/bxt_da7219_max98357a.c
0 → 100644
View file @
44d62462
This diff is collapsed.
Click to expand it.
sound/soc/intel/boards/bxt_rt298.c
View file @
44d62462
...
...
@@ -33,6 +33,7 @@ enum {
BXT_DPCM_AUDIO_PB
=
0
,
BXT_DPCM_AUDIO_CP
,
BXT_DPCM_AUDIO_REF_CP
,
BXT_DPCM_AUDIO_DMIC_CP
,
BXT_DPCM_AUDIO_HDMI1_PB
,
BXT_DPCM_AUDIO_HDMI2_PB
,
BXT_DPCM_AUDIO_HDMI3_PB
,
...
...
@@ -88,6 +89,7 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
/* CODEC BE connections */
{
"AIF1 Playback"
,
NULL
,
"ssp5 Tx"
},
{
"ssp5 Tx"
,
NULL
,
"codec0_out"
},
{
"ssp5 Tx"
,
NULL
,
"codec1_out"
},
{
"codec0_in"
,
NULL
,
"ssp5 Rx"
},
{
"ssp5 Rx"
,
NULL
,
"AIF1 Capture"
},
...
...
@@ -104,6 +106,17 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
};
static
int
broxton_rt298_fe_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_dapm_context
*
dapm
;
struct
snd_soc_component
*
component
=
rtd
->
cpu_dai
->
component
;
dapm
=
snd_soc_component_get_dapm
(
component
);
snd_soc_dapm_ignore_suspend
(
dapm
,
"Reference Capture"
);
return
0
;
}
static
int
broxton_rt298_codec_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
...
...
@@ -118,6 +131,9 @@ static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
return
ret
;
rt298_mic_detect
(
codec
,
&
broxton_headset
);
snd_soc_dapm_ignore_suspend
(
&
rtd
->
card
->
dapm
,
"SoC DMIC"
);
return
0
;
}
...
...
@@ -169,6 +185,89 @@ static struct snd_soc_ops broxton_rt298_ops = {
.
hw_params
=
broxton_rt298_hw_params
,
};
static
unsigned
int
rates
[]
=
{
48000
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_rates
=
{
.
count
=
ARRAY_SIZE
(
rates
),
.
list
=
rates
,
.
mask
=
0
,
};
static
int
broxton_dmic_fixup
(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_interval
*
channels
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
if
(
params_channels
(
params
)
==
2
)
channels
->
min
=
channels
->
max
=
2
;
else
channels
->
min
=
channels
->
max
=
4
;
return
0
;
}
static
unsigned
int
channels_dmic
[]
=
{
2
,
4
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_dmic_channels
=
{
.
count
=
ARRAY_SIZE
(
channels_dmic
),
.
list
=
channels_dmic
,
.
mask
=
0
,
};
static
int
broxton_dmic_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
runtime
->
hw
.
channels_max
=
4
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_dmic_channels
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
}
static
struct
snd_soc_ops
broxton_dmic_ops
=
{
.
startup
=
broxton_dmic_startup
,
};
static
unsigned
int
channels
[]
=
{
2
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_channels
=
{
.
count
=
ARRAY_SIZE
(
channels
),
.
list
=
channels
,
.
mask
=
0
,
};
static
int
bxt_fe_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
/*
* on this platform for PCM device we support:
* 48Khz
* stereo
*/
runtime
->
hw
.
channels_max
=
2
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_channels
);
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
return
0
;
}
static
const
struct
snd_soc_ops
broxton_rt286_fe_ops
=
{
.
startup
=
bxt_fe_startup
,
};
/* broxton digital audio interface glue - connects codec <--> CPU */
static
struct
snd_soc_dai_link
broxton_rt298_dais
[]
=
{
/* Front End DAI links */
...
...
@@ -182,8 +281,10 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
.
dynamic
=
1
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
init
=
broxton_rt298_fe_init
,
.
trigger
=
{
SND_SOC_DPCM_TRIGGER_POST
,
SND_SOC_DPCM_TRIGGER_POST
},
.
dpcm_playback
=
1
,
.
ops
=
&
broxton_rt286_fe_ops
,
},
[
BXT_DPCM_AUDIO_CP
]
{
...
...
@@ -197,6 +298,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
trigger
=
{
SND_SOC_DPCM_TRIGGER_POST
,
SND_SOC_DPCM_TRIGGER_POST
},
.
dpcm_capture
=
1
,
.
ops
=
&
broxton_rt286_fe_ops
,
},
[
BXT_DPCM_AUDIO_REF_CP
]
{
...
...
@@ -211,6 +313,20 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
.
nonatomic
=
1
,
.
dynamic
=
1
,
},
[
BXT_DPCM_AUDIO_DMIC_CP
]
{
.
name
=
"Bxt Audio DMIC cap"
,
.
stream_name
=
"dmiccap"
,
.
cpu_dai_name
=
"DMIC Pin"
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
platform_name
=
"0000:00:0e.0"
,
.
init
=
NULL
,
.
dpcm_capture
=
1
,
.
nonatomic
=
1
,
.
dynamic
=
1
,
.
ops
=
&
broxton_dmic_ops
,
},
[
BXT_DPCM_AUDIO_HDMI1_PB
]
{
.
name
=
"Bxt HDMI Port1"
,
...
...
@@ -276,6 +392,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
.
codec_name
=
"dmic-codec"
,
.
codec_dai_name
=
"dmic-hifi"
,
.
platform_name
=
"0000:00:0e.0"
,
.
be_hw_params_fixup
=
broxton_dmic_fixup
,
.
ignore_suspend
=
1
,
.
dpcm_capture
=
1
,
.
no_pcm
=
1
,
...
...
@@ -341,6 +458,7 @@ static struct platform_driver broxton_audio = {
.
probe
=
broxton_audio_probe
,
.
driver
=
{
.
name
=
"bxt_alc298s_i2s"
,
.
pm
=
&
snd_soc_pm_ops
,
},
};
module_platform_driver
(
broxton_audio
)
...
...
sound/soc/intel/boards/cht_bsw_rt5645.c
View file @
44d62462
...
...
@@ -30,6 +30,7 @@
#include <sound/jack.h>
#include "../../codecs/rt5645.h"
#include "../atom/sst-atom-controls.h"
#include "../common/sst-acpi.h"
#define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI "rt5645-aif1"
...
...
@@ -340,10 +341,13 @@ static struct snd_soc_card snd_soc_card_chtrt5650 = {
};
static
struct
cht_acpi_card
snd_soc_cards
[]
=
{
{
"10EC5640"
,
CODEC_TYPE_RT5645
,
&
snd_soc_card_chtrt5645
},
{
"10EC5645"
,
CODEC_TYPE_RT5645
,
&
snd_soc_card_chtrt5645
},
{
"10EC5650"
,
CODEC_TYPE_RT5650
,
&
snd_soc_card_chtrt5650
},
};
static
char
cht_rt5640_codec_name
[
16
];
/* i2c-<HID>:00 with HID being 8 chars */
static
int
snd_cht_mc_probe
(
struct
platform_device
*
pdev
)
{
int
ret_val
=
0
;
...
...
@@ -351,6 +355,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
struct
cht_mc_private
*
drv
;
struct
snd_soc_card
*
card
=
snd_soc_cards
[
0
].
soc_card
;
char
codec_name
[
16
];
struct
sst_acpi_mach
*
mach
;
const
char
*
i2c_name
=
NULL
;
int
dai_index
=
0
;
drv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
drv
),
GFP_ATOMIC
);
if
(
!
drv
)
...
...
@@ -366,12 +373,23 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
}
}
card
->
dev
=
&
pdev
->
dev
;
mach
=
card
->
dev
->
platform_data
;
sprintf
(
codec_name
,
"i2c-%s:00"
,
drv
->
acpi_card
->
codec_id
);
/* set correct codec name */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cht_dailink
);
i
++
)
if
(
!
strcmp
(
card
->
dai_link
[
i
].
codec_name
,
"i2c-10EC5645:00"
))
if
(
!
strcmp
(
card
->
dai_link
[
i
].
codec_name
,
"i2c-10EC5645:00"
))
{
card
->
dai_link
[
i
].
codec_name
=
kstrdup
(
codec_name
,
GFP_KERNEL
);
dai_index
=
i
;
}
/* fixup codec name based on HID */
i2c_name
=
sst_acpi_find_name_from_hid
(
mach
->
id
);
if
(
i2c_name
!=
NULL
)
{
snprintf
(
cht_rt5640_codec_name
,
sizeof
(
cht_rt5640_codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
cht_dailink
[
dai_index
].
codec_name
=
cht_rt5640_codec_name
;
}
snd_soc_card_set_drvdata
(
card
,
drv
);
ret_val
=
devm_snd_soc_register_card
(
&
pdev
->
dev
,
card
);
...
...
sound/soc/intel/boards/skl_nau88l25_max98357a.c
View file @
44d62462
...
...
@@ -23,12 +23,15 @@
#include <sound/soc.h>
#include "../../codecs/nau8825.h"
#include "../../codecs/hdac_hdmi.h"
#include "../skylake/skl.h"
#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
#define SKL_MAXIM_CODEC_DAI "HiFi"
#define DMIC_CH(p) p->list[p->count-1]
static
struct
snd_soc_jack
skylake_headset
;
static
struct
snd_soc_card
skylake_audio_card
;
static
const
struct
snd_pcm_hw_constraint_list
*
dmic_constraints
;
struct
skl_hdmi_pcm
{
struct
list_head
head
;
...
...
@@ -339,7 +342,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
struct
snd_interval
*
channels
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
if
(
params_channels
(
params
)
==
2
)
if
(
params_channels
(
params
)
==
2
||
DMIC_CH
(
dmic_constraints
)
==
2
)
channels
->
min
=
channels
->
max
=
2
;
else
channels
->
min
=
channels
->
max
=
4
;
...
...
@@ -357,13 +360,23 @@ static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.
mask
=
0
,
};
static
const
unsigned
int
dmic_2ch
[]
=
{
2
,
};
static
const
struct
snd_pcm_hw_constraint_list
constraints_dmic_2ch
=
{
.
count
=
ARRAY_SIZE
(
dmic_2ch
),
.
list
=
dmic_2ch
,
.
mask
=
0
,
};
static
int
skylake_dmic_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
runtime
->
hw
.
channels_max
=
4
;
runtime
->
hw
.
channels_max
=
DMIC_CH
(
dmic_constraints
)
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_dmic_channel
s
);
dmic_constraint
s
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
...
...
@@ -382,8 +395,22 @@ static struct snd_pcm_hw_constraint_list constraints_16000 = {
.
list
=
rates_16000
,
};
static
const
unsigned
int
ch_mono
[]
=
{
1
,
};
static
const
struct
snd_pcm_hw_constraint_list
constraints_refcap
=
{
.
count
=
ARRAY_SIZE
(
ch_mono
),
.
list
=
ch_mono
,
};
static
int
skylake_refcap_startup
(
struct
snd_pcm_substream
*
substream
)
{
substream
->
runtime
->
hw
.
channels_max
=
1
;
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_refcap
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_16000
);
...
...
@@ -610,6 +637,7 @@ static struct snd_soc_card skylake_audio_card = {
static
int
skylake_audio_probe
(
struct
platform_device
*
pdev
)
{
struct
skl_nau8825_private
*
ctx
;
struct
skl_machine_pdata
*
pdata
;
ctx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
ctx
),
GFP_ATOMIC
);
if
(
!
ctx
)
...
...
@@ -620,15 +648,27 @@ static int skylake_audio_probe(struct platform_device *pdev)
skylake_audio_card
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
skylake_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
,
&
skylake_audio_card
);
}
static
const
struct
platform_device_id
skl_board_ids
[]
=
{
{
.
name
=
"skl_n88l25_m98357a"
},
{
.
name
=
"kbl_n88l25_m98357a"
},
{
}
};
static
struct
platform_driver
skylake_audio
=
{
.
probe
=
skylake_audio_probe
,
.
driver
=
{
.
name
=
"skl_n
au88l25_max98357a_i2s
"
,
.
name
=
"skl_n
88l25_m98357a
"
,
.
pm
=
&
snd_soc_pm_ops
,
},
.
id_table
=
skl_board_ids
,
};
module_platform_driver
(
skylake_audio
)
...
...
@@ -637,4 +677,5 @@ module_platform_driver(skylake_audio)
MODULE_DESCRIPTION
(
"Audio Machine driver-NAU88L25 & MAX98357A in I2S mode"
);
MODULE_AUTHOR
(
"Rohit Ainapure <rohit.m.ainapure@intel.com"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:skl_nau88l25_max98357a_i2s"
);
MODULE_ALIAS
(
"platform:skl_n88l25_m98357a"
);
MODULE_ALIAS
(
"platform:kbl_n88l25_m98357a"
);
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
View file @
44d62462
...
...
@@ -27,12 +27,15 @@
#include <sound/pcm_params.h>
#include "../../codecs/nau8825.h"
#include "../../codecs/hdac_hdmi.h"
#include "../skylake/skl.h"
#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
#define SKL_SSM_CODEC_DAI "ssm4567-hifi"
#define DMIC_CH(p) p->list[p->count-1]
static
struct
snd_soc_jack
skylake_headset
;
static
struct
snd_soc_card
skylake_audio_card
;
static
const
struct
snd_pcm_hw_constraint_list
*
dmic_constraints
;
struct
skl_hdmi_pcm
{
struct
list_head
head
;
...
...
@@ -367,7 +370,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct
snd_interval
*
channels
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
if
(
params_channels
(
params
)
==
2
)
if
(
params_channels
(
params
)
==
2
||
DMIC_CH
(
dmic_constraints
)
==
2
)
channels
->
min
=
channels
->
max
=
2
;
else
channels
->
min
=
channels
->
max
=
4
;
...
...
@@ -405,13 +408,23 @@ static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
.
mask
=
0
,
};
static
const
unsigned
int
dmic_2ch
[]
=
{
2
,
};
static
const
struct
snd_pcm_hw_constraint_list
constraints_dmic_2ch
=
{
.
count
=
ARRAY_SIZE
(
dmic_2ch
),
.
list
=
dmic_2ch
,
.
mask
=
0
,
};
static
int
skylake_dmic_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
runtime
->
hw
.
channels_max
=
4
;
runtime
->
hw
.
channels_max
=
DMIC_CH
(
dmic_constraints
)
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_dmic_channel
s
);
dmic_constraint
s
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
...
...
@@ -430,8 +443,22 @@ static struct snd_pcm_hw_constraint_list constraints_16000 = {
.
list
=
rates_16000
,
};
static
const
unsigned
int
ch_mono
[]
=
{
1
,
};
static
const
struct
snd_pcm_hw_constraint_list
constraints_refcap
=
{
.
count
=
ARRAY_SIZE
(
ch_mono
),
.
list
=
ch_mono
,
};
static
int
skylake_refcap_startup
(
struct
snd_pcm_substream
*
substream
)
{
substream
->
runtime
->
hw
.
channels_max
=
1
;
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_refcap
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_16000
);
...
...
@@ -662,6 +689,7 @@ static struct snd_soc_card skylake_audio_card = {
static
int
skylake_audio_probe
(
struct
platform_device
*
pdev
)
{
struct
skl_nau88125_private
*
ctx
;
struct
skl_machine_pdata
*
pdata
;
ctx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
ctx
),
GFP_ATOMIC
);
if
(
!
ctx
)
...
...
@@ -672,15 +700,27 @@ static int skylake_audio_probe(struct platform_device *pdev)
skylake_audio_card
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
skylake_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
,
&
skylake_audio_card
);
}
static
const
struct
platform_device_id
skl_board_ids
[]
=
{
{
.
name
=
"skl_n88l25_s4567"
},
{
.
name
=
"kbl_n88l25_s4567"
},
{
}
};
static
struct
platform_driver
skylake_audio
=
{
.
probe
=
skylake_audio_probe
,
.
driver
=
{
.
name
=
"skl_n
au88l25_ssm4567_i2s
"
,
.
name
=
"skl_n
88l25_s4567
"
,
.
pm
=
&
snd_soc_pm_ops
,
},
.
id_table
=
skl_board_ids
,
};
module_platform_driver
(
skylake_audio
)
...
...
@@ -693,4 +733,5 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
MODULE_AUTHOR
(
"Yong Zhi <yong.zhi@intel.com>"
);
MODULE_DESCRIPTION
(
"Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:skl_nau88l25_ssm4567_i2s"
);
MODULE_ALIAS
(
"platform:skl_n88l25_s4567"
);
MODULE_ALIAS
(
"platform:kbl_n88l25_s4567"
);
sound/soc/intel/boards/skl_rt286.c
View file @
44d62462
...
...
@@ -505,12 +505,20 @@ static int skylake_audio_probe(struct platform_device *pdev)
return
devm_snd_soc_register_card
(
&
pdev
->
dev
,
&
skylake_rt286
);
}
static
const
struct
platform_device_id
skl_board_ids
[]
=
{
{
.
name
=
"skl_alc286s_i2s"
},
{
.
name
=
"kbl_alc286s_i2s"
},
{
}
};
static
struct
platform_driver
skylake_audio
=
{
.
probe
=
skylake_audio_probe
,
.
driver
=
{
.
name
=
"skl_alc286s_i2s"
,
.
pm
=
&
snd_soc_pm_ops
,
},
.
id_table
=
skl_board_ids
,
};
module_platform_driver
(
skylake_audio
)
...
...
@@ -520,3 +528,4 @@ MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>");
MODULE_DESCRIPTION
(
"Intel SST Audio for Skylake"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:skl_alc286s_i2s"
);
MODULE_ALIAS
(
"platform:kbl_alc286s_i2s"
);
sound/soc/intel/common/Makefile
View file @
44d62462
...
...
@@ -2,9 +2,9 @@ snd-soc-sst-dsp-objs := sst-dsp.o
snd-soc-sst-acpi-objs
:=
sst-acpi.o
snd-soc-sst-match-objs
:=
sst-match-acpi.o
snd-soc-sst-ipc-objs
:=
sst-ipc.o
snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE)
+=
sst-firmware.o
snd-soc-sst-firmware-objs
:=
sst-firmware.o
obj-$(CONFIG_SND_SOC_INTEL_SST)
+=
snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI)
+=
snd-soc-sst-acpi.o
obj-$(CONFIG_SND_SOC_INTEL_SST_MATCH)
+=
snd-soc-sst-match.o
obj-$(CONFIG_SND_SOC_INTEL_SST_FIRMWARE)
+=
snd-soc-sst-firmware.o
sound/soc/intel/common/sst-acpi.h
View file @
44d62462
...
...
@@ -20,7 +20,7 @@
#if IS_ENABLED(CONFIG_ACPI)
const
char
*
sst_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
]);
#else
inline
const
char
*
sst_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
static
inline
const
char
*
sst_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
{
return
NULL
;
}
...
...
@@ -40,6 +40,6 @@ struct sst_acpi_mach {
/* board name */
const
char
*
board
;
void
(
*
machine_quirk
)(
void
);
struct
sst_acpi_mach
*
(
*
machine_quirk
)(
void
*
arg
);
void
*
pdata
;
};
sound/soc/intel/common/sst-dsp-priv.h
View file @
44d62462
...
...
@@ -383,10 +383,6 @@ struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
u32
index
,
void
*
private
);
void
sst_mem_block_unregister_all
(
struct
sst_dsp
*
dsp
);
/* Create/Free DMA resources */
int
sst_dma_new
(
struct
sst_dsp
*
sst
);
void
sst_dma_free
(
struct
sst_dma
*
dma
);
u32
sst_dsp_get_offset
(
struct
sst_dsp
*
dsp
,
u32
offset
,
enum
sst_mem_type
type
);
#endif
sound/soc/intel/common/sst-dsp.c
View file @
44d62462
...
...
@@ -285,7 +285,7 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
}
reg
=
sst_dsp_shim_read_unlocked
(
ctx
,
offset
);
dev_
info
(
ctx
->
dev
,
"FW Poll Status: reg=%#x %s %s
\n
"
,
reg
,
operation
,
dev_
dbg
(
ctx
->
dev
,
"FW Poll Status: reg=%#x %s %s
\n
"
,
reg
,
operation
,
(
time
<
timeout
)
?
"successful"
:
"timedout"
);
ret
=
time
<
timeout
?
0
:
-
ETIME
;
...
...
@@ -420,73 +420,6 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
}
EXPORT_SYMBOL_GPL
(
sst_dsp_inbox_read
);
#ifdef CONFIG_DW_DMAC_CORE
struct
sst_dsp
*
sst_dsp_new
(
struct
device
*
dev
,
struct
sst_dsp_device
*
sst_dev
,
struct
sst_pdata
*
pdata
)
{
struct
sst_dsp
*
sst
;
int
err
;
dev_dbg
(
dev
,
"initialising audio DSP id 0x%x
\n
"
,
pdata
->
id
);
sst
=
devm_kzalloc
(
dev
,
sizeof
(
*
sst
),
GFP_KERNEL
);
if
(
sst
==
NULL
)
return
NULL
;
spin_lock_init
(
&
sst
->
spinlock
);
mutex_init
(
&
sst
->
mutex
);
sst
->
dev
=
dev
;
sst
->
dma_dev
=
pdata
->
dma_dev
;
sst
->
thread_context
=
sst_dev
->
thread_context
;
sst
->
sst_dev
=
sst_dev
;
sst
->
id
=
pdata
->
id
;
sst
->
irq
=
pdata
->
irq
;
sst
->
ops
=
sst_dev
->
ops
;
sst
->
pdata
=
pdata
;
INIT_LIST_HEAD
(
&
sst
->
used_block_list
);
INIT_LIST_HEAD
(
&
sst
->
free_block_list
);
INIT_LIST_HEAD
(
&
sst
->
module_list
);
INIT_LIST_HEAD
(
&
sst
->
fw_list
);
INIT_LIST_HEAD
(
&
sst
->
scratch_block_list
);
/* Initialise SST Audio DSP */
if
(
sst
->
ops
->
init
)
{
err
=
sst
->
ops
->
init
(
sst
,
pdata
);
if
(
err
<
0
)
return
NULL
;
}
/* Register the ISR */
err
=
request_threaded_irq
(
sst
->
irq
,
sst
->
ops
->
irq_handler
,
sst_dev
->
thread
,
IRQF_SHARED
,
"AudioDSP"
,
sst
);
if
(
err
)
goto
irq_err
;
err
=
sst_dma_new
(
sst
);
if
(
err
)
dev_warn
(
dev
,
"sst_dma_new failed %d
\n
"
,
err
);
return
sst
;
irq_err:
if
(
sst
->
ops
->
free
)
sst
->
ops
->
free
(
sst
);
return
NULL
;
}
EXPORT_SYMBOL_GPL
(
sst_dsp_new
);
void
sst_dsp_free
(
struct
sst_dsp
*
sst
)
{
free_irq
(
sst
->
irq
,
sst
);
if
(
sst
->
ops
->
free
)
sst
->
ops
->
free
(
sst
);
sst_dma_free
(
sst
->
dma
);
}
EXPORT_SYMBOL_GPL
(
sst_dsp_free
);
#endif
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood"
);
MODULE_DESCRIPTION
(
"Intel SST Core"
);
...
...
sound/soc/intel/common/sst-dsp.h
View file @
44d62462
...
...
@@ -216,7 +216,7 @@ struct sst_pdata {
void
*
dsp
;
};
#if
def CONFIG_DW_DMAC_CORE
#if
IS_ENABLED(CONFIG_DW_DMAC_CORE)
/* Initialization */
struct
sst_dsp
*
sst_dsp_new
(
struct
device
*
dev
,
struct
sst_dsp_device
*
sst_dev
,
struct
sst_pdata
*
pdata
);
...
...
sound/soc/intel/common/sst-firmware.c
View file @
44d62462
...
...
@@ -1211,3 +1211,71 @@ u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset,
}
}
EXPORT_SYMBOL_GPL
(
sst_dsp_get_offset
);
struct
sst_dsp
*
sst_dsp_new
(
struct
device
*
dev
,
struct
sst_dsp_device
*
sst_dev
,
struct
sst_pdata
*
pdata
)
{
struct
sst_dsp
*
sst
;
int
err
;
dev_dbg
(
dev
,
"initialising audio DSP id 0x%x
\n
"
,
pdata
->
id
);
sst
=
devm_kzalloc
(
dev
,
sizeof
(
*
sst
),
GFP_KERNEL
);
if
(
sst
==
NULL
)
return
NULL
;
spin_lock_init
(
&
sst
->
spinlock
);
mutex_init
(
&
sst
->
mutex
);
sst
->
dev
=
dev
;
sst
->
dma_dev
=
pdata
->
dma_dev
;
sst
->
thread_context
=
sst_dev
->
thread_context
;
sst
->
sst_dev
=
sst_dev
;
sst
->
id
=
pdata
->
id
;
sst
->
irq
=
pdata
->
irq
;
sst
->
ops
=
sst_dev
->
ops
;
sst
->
pdata
=
pdata
;
INIT_LIST_HEAD
(
&
sst
->
used_block_list
);
INIT_LIST_HEAD
(
&
sst
->
free_block_list
);
INIT_LIST_HEAD
(
&
sst
->
module_list
);
INIT_LIST_HEAD
(
&
sst
->
fw_list
);
INIT_LIST_HEAD
(
&
sst
->
scratch_block_list
);
/* Initialise SST Audio DSP */
if
(
sst
->
ops
->
init
)
{
err
=
sst
->
ops
->
init
(
sst
,
pdata
);
if
(
err
<
0
)
return
NULL
;
}
/* Register the ISR */
err
=
request_threaded_irq
(
sst
->
irq
,
sst
->
ops
->
irq_handler
,
sst_dev
->
thread
,
IRQF_SHARED
,
"AudioDSP"
,
sst
);
if
(
err
)
goto
irq_err
;
err
=
sst_dma_new
(
sst
);
if
(
err
)
dev_warn
(
dev
,
"sst_dma_new failed %d
\n
"
,
err
);
return
sst
;
irq_err:
if
(
sst
->
ops
->
free
)
sst
->
ops
->
free
(
sst
);
return
NULL
;
}
EXPORT_SYMBOL_GPL
(
sst_dsp_new
);
void
sst_dsp_free
(
struct
sst_dsp
*
sst
)
{
free_irq
(
sst
->
irq
,
sst
);
if
(
sst
->
ops
->
free
)
sst
->
ops
->
free
(
sst
);
sst_dma_free
(
sst
->
dma
);
}
EXPORT_SYMBOL_GPL
(
sst_dsp_free
);
MODULE_DESCRIPTION
(
"Intel SST Firmware Loader"
);
MODULE_LICENSE
(
"GPL v2"
);
sound/soc/intel/haswell/sst-haswell-pcm.c
View file @
44d62462
...
...
@@ -819,7 +819,6 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream)
mutex_lock
(
&
pcm_data
->
mutex
);
pm_runtime_get_sync
(
pdata
->
dev
);
snd_soc_pcm_set_drvdata
(
rtd
,
pcm_data
);
pcm_data
->
substream
=
substream
;
snd_soc_set_runtime_hwparams
(
substream
,
&
hsw_pcm_hardware
);
...
...
sound/soc/intel/skylake/Makefile
View file @
44d62462
...
...
@@ -5,6 +5,6 @@ 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.o bxt-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 @
44d62462
...
...
@@ -37,11 +37,19 @@
#define BXT_ADSP_SRAM1_BASE 0xA0000
#define BXT_INSTANCE_ID 0
#define BXT_BASE_FW_MODULE_ID 0
static
unsigned
int
bxt_get_errorcode
(
struct
sst_dsp
*
ctx
)
{
return
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
);
}
/*
* First boot sequence has some extra steps. Core 0 waits for power
* status on core 1, so power up core 1 also momentarily, keep it in
* reset/stall and then turn it off
*/
static
int
sst_bxt_prepare_fw
(
struct
sst_dsp
*
ctx
,
const
void
*
fwdata
,
u32
fwsize
)
{
...
...
@@ -49,7 +57,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
u32
reg
;
stream_tag
=
ctx
->
dsp_ops
.
prepare
(
ctx
->
dev
,
0x40
,
fwsize
,
&
ctx
->
dmab
);
if
(
stream_tag
<
0
)
{
if
(
stream_tag
<
=
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to prepare DMA FW loading err: %x
\n
"
,
stream_tag
);
return
stream_tag
;
...
...
@@ -58,17 +66,27 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
ctx
->
dsp_ops
.
stream_tag
=
stream_tag
;
memcpy
(
ctx
->
dmab
.
area
,
fwdata
,
fwsize
);
/* Purge FW request */
/* Step 1: Power up core 0 and core1 */
ret
=
skl_dsp_core_power_up
(
ctx
,
SKL_DSP_CORE0_MASK
|
SKL_DSP_CORE_MASK
(
1
));
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp core0/1 power up failed
\n
"
);
goto
base_fw_load_failed
;
}
/* Step 2: Purge FW request */
sst_dsp_shim_write
(
ctx
,
SKL_ADSP_REG_HIPCI
,
SKL_ADSP_REG_HIPCI_BUSY
|
BXT_IPC_PURGE_FW
|
(
stream_tag
-
1
));
(
BXT_IPC_PURGE_FW
|
((
stream_tag
-
1
)
<<
9
)
));
ret
=
skl_dsp_enable_core
(
ctx
);
/* Step 3: Unset core0 reset state & unstall/run core0 */
ret
=
skl_dsp_start_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"
Boo
t dsp core failed ret: %d
\n
"
,
ret
);
dev_err
(
ctx
->
dev
,
"
Star
t dsp core failed ret: %d
\n
"
,
ret
);
ret
=
-
EIO
;
goto
base_fw_load_failed
;
}
/* Step 4: Wait for DONE Bit */
for
(
i
=
BXT_INIT_TIMEOUT
;
i
>
0
;
--
i
)
{
reg
=
sst_dsp_shim_read
(
ctx
,
SKL_ADSP_REG_HIPCIE
);
...
...
@@ -88,10 +106,18 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
SKL_ADSP_REG_HIPCIE_DONE
);
}
/* enable Interrupt */
/* Step 5: power down core1 */
ret
=
skl_dsp_core_power_down
(
ctx
,
SKL_DSP_CORE_MASK
(
1
));
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp core1 power down failed
\n
"
);
goto
base_fw_load_failed
;
}
/* Step 6: Enable Interrupt */
skl_ipc_int_enable
(
ctx
);
skl_ipc_op_int_enable
(
ctx
);
/* Step 7: Wait for ROM init */
for
(
i
=
BXT_INIT_TIMEOUT
;
i
>
0
;
--
i
)
{
if
(
SKL_FW_INIT
==
(
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_FW_STATUS
)
&
...
...
@@ -112,7 +138,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
base_fw_load_failed:
ctx
->
dsp_ops
.
cleanup
(
ctx
->
dev
,
&
ctx
->
dmab
,
stream_tag
);
skl_dsp_disable_core
(
ctx
);
skl_dsp_core_power_down
(
ctx
,
SKL_DSP_CORE_MASK
(
1
));
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
return
ret
;
}
...
...
@@ -130,23 +157,41 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
return
ret
;
}
#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000
static
int
bxt_load_base_firmware
(
struct
sst_dsp
*
ctx
)
{
const
struct
firmware
*
fw
=
NULL
;
struct
firmware
stripped_fw
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
ctx
->
fw_name
,
ctx
->
dev
);
ret
=
request_firmware
(
&
ctx
->
fw
,
ctx
->
fw_name
,
ctx
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Request firmware failed %d
\n
"
,
ret
);
goto
sst_load_base_firmware_failed
;
}
ret
=
sst_bxt_prepare_fw
(
ctx
,
fw
->
data
,
fw
->
size
);
/* check for extended manifest */
if
(
ctx
->
fw
==
NULL
)
goto
sst_load_base_firmware_failed
;
ret
=
snd_skl_parse_uuids
(
ctx
,
BXT_ADSP_FW_BIN_HDR_OFFSET
);
if
(
ret
<
0
)
goto
sst_load_base_firmware_failed
;
stripped_fw
.
data
=
ctx
->
fw
->
data
;
stripped_fw
.
size
=
ctx
->
fw
->
size
;
skl_dsp_strip_extended_manifest
(
&
stripped_fw
);
ret
=
sst_bxt_prepare_fw
(
ctx
,
stripped_fw
.
data
,
stripped_fw
.
size
);
/* Retry Enabling core and ROM load. Retry seemed to help */
if
(
ret
<
0
)
{
ret
=
sst_bxt_prepare_fw
(
ctx
,
fw
->
data
,
fw
->
size
);
ret
=
sst_bxt_prepare_fw
(
ctx
,
stripped_fw
.
data
,
stripped_fw
.
size
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Error code=0x%x: FW status=0x%x
\n
"
,
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
),
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_FW_STATUS
));
dev_err
(
ctx
->
dev
,
"Core En/ROM load fail:%d
\n
"
,
ret
);
goto
sst_load_base_firmware_failed
;
}
...
...
@@ -159,83 +204,135 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
),
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_FW_STATUS
));
skl_dsp_disable_core
(
ctx
);
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
}
else
{
dev_dbg
(
ctx
->
dev
,
"Firmware download successful
\n
"
);
ret
=
wait_event_timeout
(
skl
->
boot_wait
,
skl
->
boot_complete
,
msecs_to_jiffies
(
SKL_IPC_BOOT_MSECS
));
if
(
ret
==
0
)
{
dev_err
(
ctx
->
dev
,
"DSP boot fail, FW Ready timeout
\n
"
);
skl_dsp_disable_core
(
ctx
);
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
ret
=
-
EIO
;
}
else
{
skl_dsp_set_state_locked
(
ctx
,
SKL_DSP_RUNNING
);
ret
=
0
;
skl
->
fw_loaded
=
true
;
}
}
sst_load_base_firmware_failed:
release_firmware
(
fw
);
release_firmware
(
ctx
->
fw
);
return
ret
;
}
static
int
bxt_set_dsp_D0
(
struct
sst_dsp
*
ctx
)
static
int
bxt_set_dsp_D0
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
ret
;
struct
skl_ipc_dxstate_info
dx
;
unsigned
int
core_mask
=
SKL_DSP_CORE_MASK
(
core_id
);
skl
->
boot_complete
=
false
;
ret
=
skl_dsp_enable_co
re
(
ctx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"enable dsp core failed ret
: %d
\n
"
,
ret
);
if
(
skl
->
fw_loaded
==
false
)
{
skl
->
boot_complete
=
false
;
ret
=
bxt_load_base_firmwa
re
(
ctx
);
if
(
ret
<
0
)
dev_err
(
ctx
->
dev
,
"reload fw failed
: %d
\n
"
,
ret
);
return
ret
;
}
/* enable interrupt */
skl_ipc_int_enable
(
ctx
);
skl_ipc_op_int_enable
(
ctx
);
/* If core 0 is being turned on, turn on core 1 as well */
if
(
core_id
==
SKL_DSP_CORE0_ID
)
ret
=
skl_dsp_core_power_up
(
ctx
,
core_mask
|
SKL_DSP_CORE_MASK
(
1
));
else
ret
=
skl_dsp_core_power_up
(
ctx
,
core_mask
);
if
(
ret
<
0
)
goto
err
;
if
(
core_id
==
SKL_DSP_CORE0_ID
)
{
/*
* Enable interrupt after SPA is set and before
* DSP is unstalled
*/
skl_ipc_int_enable
(
ctx
);
skl_ipc_op_int_enable
(
ctx
);
skl
->
boot_complete
=
false
;
}
ret
=
wait_event_timeout
(
skl
->
boot_wait
,
skl
->
boot_complete
,
msecs_to_jiffies
(
SKL_IPC_BOOT_MSECS
));
if
(
ret
==
0
)
{
dev_err
(
ctx
->
dev
,
"ipc: error DSP boot timeout
\n
"
);
dev_err
(
ctx
->
dev
,
"Error code=0x%x: FW status=0x%x
\n
"
,
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
),
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_FW_STATUS
));
return
-
EIO
;
ret
=
skl_dsp_start_core
(
ctx
,
core_mask
);
if
(
ret
<
0
)
goto
err
;
if
(
core_id
==
SKL_DSP_CORE0_ID
)
{
ret
=
wait_event_timeout
(
skl
->
boot_wait
,
skl
->
boot_complete
,
msecs_to_jiffies
(
SKL_IPC_BOOT_MSECS
));
/* If core 1 was turned on for booting core 0, turn it off */
skl_dsp_core_power_down
(
ctx
,
SKL_DSP_CORE_MASK
(
1
));
if
(
ret
==
0
)
{
dev_err
(
ctx
->
dev
,
"%s: DSP boot timeout
\n
"
,
__func__
);
dev_err
(
ctx
->
dev
,
"Error code=0x%x: FW status=0x%x
\n
"
,
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
),
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_FW_STATUS
));
dev_err
(
ctx
->
dev
,
"Failed to set core0 to D0 state
\n
"
);
ret
=
-
EIO
;
goto
err
;
}
}
/* Tell FW if additional core in now On */
if
(
core_id
!=
SKL_DSP_CORE0_ID
)
{
dx
.
core_mask
=
core_mask
;
dx
.
dx_mask
=
core_mask
;
ret
=
skl_ipc_set_dx
(
&
skl
->
ipc
,
BXT_INSTANCE_ID
,
BXT_BASE_FW_MODULE_ID
,
&
dx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"IPC set_dx for core %d fail: %d
\n
"
,
core_id
,
ret
);
goto
err
;
}
}
skl
_dsp_set_state_locked
(
ctx
,
SKL_DSP_RUNNING
)
;
skl
->
cores
.
state
[
core_id
]
=
SKL_DSP_RUNNING
;
return
0
;
err:
if
(
core_id
==
SKL_DSP_CORE0_ID
)
core_mask
|=
SKL_DSP_CORE_MASK
(
1
);
skl_dsp_disable_core
(
ctx
,
core_mask
);
return
ret
;
}
static
int
bxt_set_dsp_D3
(
struct
sst_dsp
*
ctx
)
static
int
bxt_set_dsp_D3
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
int
ret
;
struct
skl_ipc_dxstate_info
dx
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
ret
=
0
;
unsigned
int
core_mask
=
SKL_DSP_CORE_MASK
(
core_id
)
;
if
(
!
is_skl_dsp_running
(
ctx
))
return
ret
;
dx
.
core_mask
=
SKL_DSP_CORE0_MASK
;
dx
.
core_mask
=
core_mask
;
dx
.
dx_mask
=
SKL_IPC_D3_MASK
;
ret
=
skl_ipc_set_dx
(
&
skl
->
ipc
,
SKL_INSTANCE_ID
,
SKL_BASE_FW_MODULE_ID
,
&
dx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to set DSP to D3 state: %d
\n
"
,
ret
);
return
ret
;
}
dev_dbg
(
ctx
->
dev
,
"core mask=%x dx_mask=%x
\n
"
,
dx
.
core_mask
,
dx
.
dx_mask
);
ret
=
skl_ipc_set_dx
(
&
skl
->
ipc
,
BXT_INSTANCE_ID
,
BXT_BASE_FW_MODULE_ID
,
&
dx
);
if
(
ret
<
0
)
dev_err
(
ctx
->
dev
,
"Failed to set DSP to D3:core id = %d;Continue reset
\n
"
,
core_id
);
ret
=
skl_dsp_disable_core
(
ctx
);
ret
=
skl_dsp_disable_core
(
ctx
,
core_mask
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"
disbale dsp core failed: %d
\n
"
,
ret
);
ret
=
-
EIO
;
dev_err
(
ctx
->
dev
,
"
Failed to disable core %d
"
,
ret
);
ret
urn
ret
;
}
skl_dsp_set_state_locked
(
ctx
,
SKL_DSP_RESET
);
skl
->
cores
.
state
[
core_id
]
=
SKL_DSP_RESET
;
return
0
;
}
...
...
@@ -274,6 +371,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
skl
->
dev
=
dev
;
skl_dev
.
thread_context
=
skl
;
INIT_LIST_HEAD
(
&
skl
->
uuid_list
);
skl
->
dsp
=
skl_dsp_ctx_init
(
dev
,
&
skl_dev
,
irq
);
if
(
!
skl
->
dsp
)
{
...
...
@@ -296,6 +394,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if
(
ret
)
return
ret
;
skl
->
cores
.
count
=
2
;
skl
->
boot_complete
=
false
;
init_waitqueue_head
(
&
skl
->
boot_wait
);
...
...
@@ -305,6 +404,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
return
ret
;
}
skl_dsp_init_core_state
(
sst
);
if
(
dsp
)
*
dsp
=
skl
;
...
...
@@ -315,6 +416,7 @@ EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
void
bxt_sst_dsp_cleanup
(
struct
device
*
dev
,
struct
skl_sst
*
ctx
)
{
skl_freeup_uuid_list
(
ctx
);
skl_ipc_free
(
&
ctx
->
ipc
);
ctx
->
dsp
->
cl_dev
.
ops
.
cl_cleanup_controller
(
ctx
->
dsp
);
...
...
sound/soc/intel/skylake/skl-messages.c
View file @
44d62462
...
...
@@ -205,6 +205,12 @@ static const struct skl_dsp_ops dsp_ops[] = {
.
init
=
skl_sst_dsp_init
,
.
cleanup
=
skl_sst_dsp_cleanup
},
{
.
id
=
0x9d71
,
.
loader_ops
=
skl_get_loader_ops
,
.
init
=
skl_sst_dsp_init
,
.
cleanup
=
skl_sst_dsp_cleanup
},
{
.
id
=
0x5a98
,
.
loader_ops
=
bxt_get_loader_ops
,
...
...
@@ -730,7 +736,7 @@ static int skl_set_module_format(struct skl_sst *ctx,
dev_dbg
(
ctx
->
dev
,
"Module type=%d config size: %d bytes
\n
"
,
module_config
->
id
.
module_id
,
param_size
);
print_hex_dump
(
KERN_DEBUG
,
"Module params:"
,
DUMP_PREFIX_OFFSET
,
8
,
4
,
print_hex_dump
_debug
(
"Module params:"
,
DUMP_PREFIX_OFFSET
,
8
,
4
,
*
param_data
,
param_size
,
false
);
return
0
;
}
...
...
@@ -1046,7 +1052,7 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
dev_dbg
(
ctx
->
dev
,
"%s: pipe = %d
\n
"
,
__func__
,
pipe
->
ppl_id
);
/* If pipe is
not started, do not try t
o stop the pipe in FW. */
/* If pipe is
started, d
o stop the pipe in FW. */
if
(
pipe
->
state
>
SKL_PIPE_STARTED
)
{
ret
=
skl_set_pipe_state
(
ctx
,
pipe
,
PPL_PAUSED
);
if
(
ret
<
0
)
{
...
...
@@ -1055,18 +1061,20 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
}
pipe
->
state
=
SKL_PIPE_PAUSED
;
}
else
{
/* If pipe was not created in FW, do not try to delete it */
if
(
pipe
->
state
<
SKL_PIPE_CREATED
)
return
0
;
}
ret
=
skl_ipc_delete_pipeline
(
&
ctx
->
ipc
,
pipe
->
ppl_id
);
if
(
ret
<
0
)
dev_err
(
ctx
->
dev
,
"Failed to delete pipeline
\n
"
)
;
/* If pipe was not created in FW, do not try to delete it */
if
(
pipe
->
state
<
SKL_PIPE_CREATED
)
return
0
;
pipe
->
state
=
SKL_PIPE_INVALID
;
ret
=
skl_ipc_delete_pipeline
(
&
ctx
->
ipc
,
pipe
->
ppl_id
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to delete pipeline
\n
"
);
return
ret
;
}
pipe
->
state
=
SKL_PIPE_INVALID
;
return
ret
;
}
...
...
@@ -1125,7 +1133,30 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
return
ret
;
}
pipe
->
state
=
SKL_PIPE_CREATED
;
pipe
->
state
=
SKL_PIPE_PAUSED
;
return
0
;
}
/*
* Reset the pipeline by sending set pipe state IPC this will reset the DMA
* from the DSP side
*/
int
skl_reset_pipe
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
)
{
int
ret
;
/* If pipe was not created in FW, do not try to pause or delete */
if
(
pipe
->
state
<
SKL_PIPE_PAUSED
)
return
0
;
ret
=
skl_set_pipe_state
(
ctx
,
pipe
,
PPL_RESET
);
if
(
ret
<
0
)
{
dev_dbg
(
ctx
->
dev
,
"Failed to reset pipe ret=%d
\n
"
,
ret
);
return
ret
;
}
pipe
->
state
=
SKL_PIPE_RESET
;
return
0
;
}
...
...
sound/soc/intel/skylake/skl-nhlt.c
View file @
44d62462
...
...
@@ -17,6 +17,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#include <linux/pci.h>
#include "skl.h"
/* Unique identification for getting NHLT blobs */
...
...
@@ -149,6 +150,45 @@ struct nhlt_specific_cfg
return
NULL
;
}
int
skl_get_dmic_geo
(
struct
skl
*
skl
)
{
struct
nhlt_acpi_table
*
nhlt
=
(
struct
nhlt_acpi_table
*
)
skl
->
nhlt
;
struct
nhlt_endpoint
*
epnt
;
struct
nhlt_dmic_array_config
*
cfg
;
struct
device
*
dev
=
&
skl
->
pci
->
dev
;
unsigned
int
dmic_geo
=
0
;
u8
j
;
epnt
=
(
struct
nhlt_endpoint
*
)
nhlt
->
desc
;
for
(
j
=
0
;
j
<
nhlt
->
endpoint_count
;
j
++
)
{
if
(
epnt
->
linktype
==
NHLT_LINK_DMIC
)
{
cfg
=
(
struct
nhlt_dmic_array_config
*
)
(
epnt
->
config
.
caps
);
switch
(
cfg
->
array_type
)
{
case
NHLT_MIC_ARRAY_2CH_SMALL
:
case
NHLT_MIC_ARRAY_2CH_BIG
:
dmic_geo
|=
MIC_ARRAY_2CH
;
break
;
case
NHLT_MIC_ARRAY_4CH_1ST_GEOM
:
case
NHLT_MIC_ARRAY_4CH_L_SHAPED
:
case
NHLT_MIC_ARRAY_4CH_2ND_GEOM
:
dmic_geo
|=
MIC_ARRAY_4CH
;
break
;
default:
dev_warn
(
dev
,
"undefined DMIC array_type 0x%0x
\n
"
,
cfg
->
array_type
);
}
}
epnt
=
(
struct
nhlt_endpoint
*
)((
u8
*
)
epnt
+
epnt
->
length
);
}
return
dmic_geo
;
}
static
void
skl_nhlt_trim_space
(
struct
skl
*
skl
)
{
char
*
s
=
skl
->
tplg_name
;
...
...
sound/soc/intel/skylake/skl-nhlt.h
View file @
44d62462
...
...
@@ -103,4 +103,26 @@ struct nhlt_resource_desc {
u64
length
;
}
__packed
;
#define MIC_ARRAY_2CH 2
#define MIC_ARRAY_4CH 4
struct
nhlt_tdm_config
{
u8
virtual_slot
;
u8
config_type
;
}
__packed
;
struct
nhlt_dmic_array_config
{
struct
nhlt_tdm_config
tdm_config
;
u8
array_type
;
}
__packed
;
enum
{
NHLT_MIC_ARRAY_2CH_SMALL
=
0xa
,
NHLT_MIC_ARRAY_2CH_BIG
=
0xb
,
NHLT_MIC_ARRAY_4CH_1ST_GEOM
=
0xc
,
NHLT_MIC_ARRAY_4CH_L_SHAPED
=
0xd
,
NHLT_MIC_ARRAY_4CH_2ND_GEOM
=
0xe
,
NHLT_MIC_ARRAY_VENDOR_DEFINED
=
0xf
,
};
#endif
sound/soc/intel/skylake/skl-pcm.c
View file @
44d62462
...
...
@@ -227,16 +227,25 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
dai
)
{
struct
hdac_ext_stream
*
stream
=
get_hdac_ext_stream
(
substream
);
struct
skl
*
skl
=
get_skl_ctx
(
dai
->
dev
);
unsigned
int
format_val
;
int
err
;
struct
skl_module_cfg
*
mconfig
;
dev_dbg
(
dai
->
dev
,
"%s: %s
\n
"
,
__func__
,
dai
->
name
);
mconfig
=
skl_tplg_fe_get_cpr_module
(
dai
,
substream
->
stream
);
format_val
=
skl_get_format
(
substream
,
dai
);
dev_dbg
(
dai
->
dev
,
"stream_tag=%d formatvalue=%d
\n
"
,
hdac_stream
(
stream
)
->
stream_tag
,
format_val
);
snd_hdac_stream_reset
(
hdac_stream
(
stream
));
/* In case of XRUN recovery, reset the FW pipe to clean state */
if
(
mconfig
&&
(
substream
->
runtime
->
status
->
state
==
SNDRV_PCM_STATE_XRUN
))
skl_reset_pipe
(
skl
->
skl_sst
,
mconfig
->
pipe
);
err
=
snd_hdac_stream_set_params
(
hdac_stream
(
stream
),
format_val
);
if
(
err
<
0
)
return
err
;
...
...
@@ -521,6 +530,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
struct
skl_dma_params
*
dma_params
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
struct
hdac_ext_link
*
link
;
struct
skl
*
skl
=
get_skl_ctx
(
dai
->
dev
);
struct
skl_module_cfg
*
mconfig
=
NULL
;
dma_params
=
(
struct
skl_dma_params
*
)
snd_soc_dai_get_dma_data
(
codec_dai
,
substream
);
...
...
@@ -535,6 +546,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
snd_hdac_ext_link_stream_reset
(
link_dev
);
/* In case of XRUN recovery, reset the FW pipe to clean state */
mconfig
=
skl_tplg_be_get_cpr_module
(
dai
,
substream
->
stream
);
if
(
mconfig
&&
(
substream
->
runtime
->
status
->
state
==
SNDRV_PCM_STATE_XRUN
))
skl_reset_pipe
(
skl
->
skl_sst
,
mconfig
->
pipe
);
snd_hdac_ext_link_stream_setup
(
link_dev
,
format_val
);
snd_hdac_ext_link_set_stream_id
(
link
,
hdac_stream
(
link_dev
)
->
stream_tag
);
...
...
@@ -1009,51 +1026,11 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
return
0
;
}
/* calculate runtime delay from LPIB */
static
int
skl_get_delay_from_lpib
(
struct
hdac_ext_bus
*
ebus
,
struct
hdac_ext_stream
*
sstream
,
unsigned
int
pos
)
{
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
ebus
);
struct
hdac_stream
*
hstream
=
hdac_stream
(
sstream
);
struct
snd_pcm_substream
*
substream
=
hstream
->
substream
;
int
stream
=
substream
->
stream
;
unsigned
int
lpib_pos
=
snd_hdac_stream_get_pos_lpib
(
hstream
);
int
delay
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
delay
=
pos
-
lpib_pos
;
else
delay
=
lpib_pos
-
pos
;
if
(
delay
<
0
)
{
if
(
delay
>=
hstream
->
delay_negative_threshold
)
delay
=
0
;
else
delay
+=
hstream
->
bufsize
;
}
if
(
hstream
->
bufsize
==
delay
)
delay
=
0
;
if
(
delay
>=
hstream
->
period_bytes
)
{
dev_info
(
bus
->
dev
,
"Unstable LPIB (%d >= %d); disabling LPIB delay counting
\n
"
,
delay
,
hstream
->
period_bytes
);
delay
=
0
;
}
return
bytes_to_frames
(
substream
->
runtime
,
delay
);
}
static
unsigned
int
skl_get_position
(
struct
hdac_ext_stream
*
hstream
,
int
codec_delay
)
static
snd_pcm_uframes_t
skl_platform_pcm_pointer
(
struct
snd_pcm_substream
*
substream
)
{
struct
hdac_stream
*
hstr
=
hdac_stream
(
hstream
);
struct
snd_pcm_substream
*
substream
=
hstr
->
substream
;
struct
hdac_ext_bus
*
ebus
;
struct
hdac_ext_stream
*
hstream
=
get_hdac_ext_stream
(
substream
);
unsigned
int
pos
;
int
delay
;
/* use the position buffer as default */
pos
=
snd_hdac_stream_get_pos_posbuf
(
hdac_stream
(
hstream
));
...
...
@@ -1061,23 +1038,7 @@ static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
if
(
pos
>=
hdac_stream
(
hstream
)
->
bufsize
)
pos
=
0
;
if
(
substream
->
runtime
)
{
ebus
=
get_bus_ctx
(
substream
);
delay
=
skl_get_delay_from_lpib
(
ebus
,
hstream
,
pos
)
+
codec_delay
;
substream
->
runtime
->
delay
+=
delay
;
}
return
pos
;
}
static
snd_pcm_uframes_t
skl_platform_pcm_pointer
(
struct
snd_pcm_substream
*
substream
)
{
struct
hdac_ext_stream
*
hstream
=
get_hdac_ext_stream
(
substream
);
return
bytes_to_frames
(
substream
->
runtime
,
skl_get_position
(
hstream
,
0
));
return
bytes_to_frames
(
substream
->
runtime
,
pos
);
}
static
u64
skl_adjust_codec_delay
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -1180,9 +1141,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
static
int
skl_platform_soc_probe
(
struct
snd_soc_platform
*
platform
)
{
struct
hdac_ext_bus
*
ebus
=
dev_get_drvdata
(
platform
->
dev
);
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
int
ret
;
if
(
ebus
->
ppcap
)
return
skl_tplg_init
(
platform
,
ebus
);
if
(
ebus
->
ppcap
)
{
ret
=
skl_tplg_init
(
platform
,
ebus
);
if
(
ret
<
0
)
{
dev_err
(
platform
->
dev
,
"Failed to init topology!
\n
"
);
return
ret
;
}
skl
->
platform
=
platform
;
}
return
0
;
}
...
...
sound/soc/intel/skylake/skl-sst-dsp.c
View file @
44d62462
This diff is collapsed.
Click to expand it.
sound/soc/intel/skylake/skl-sst-dsp.h
View file @
44d62462
...
...
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <sound/memalloc.h>
#include "skl-sst-cldma.h"
#include "skl-tplg-interface.h"
struct
sst_dsp
;
struct
skl_sst
;
...
...
@@ -76,35 +77,53 @@ struct sst_dsp_device;
#define SKL_ADSPIC_IPC 1
#define SKL_ADSPIS_IPC 1
/* Core ID of core0 */
#define SKL_DSP_CORE0_ID 0
/* Mask for a given core index, c = 0.. number of supported cores - 1 */
#define SKL_DSP_CORE_MASK(c) BIT(c)
/*
* Core 0 mask = SKL_DSP_CORE_MASK(0); Defined separately
* since Core0 is primary core and it is used often
*/
#define SKL_DSP_CORE0_MASK BIT(0)
/*
* Mask for a given number of cores
* nc = number of supported cores
*/
#define SKL_DSP_CORES_MASK(nc) GENMASK((nc - 1), 0)
/* ADSPCS - Audio DSP Control & Status */
#define SKL_DSP_CORES 1
#define SKL_DSP_CORE0_MASK 1
#define SKL_DSP_CORES_MASK ((1 << SKL_DSP_CORES) - 1)
/* Core Reset - asserted high
*/
#define SKL_ADSPCS_CRST_SHIFT 0
#define SKL_ADSPCS_CRST_MASK
(SKL_DSP_CORES_MASK
<< SKL_ADSPCS_CRST_SHIFT)
#define SKL_ADSPCS_CRST(x) ((x << SKL_ADSPCS_CRST_SHIFT) & SKL_ADSPCS_CRST_MASK)
/* Core run/stall - when set to '1' core is stalled */
#define SKL_ADSPCS_CSTALL_SHIFT 8
#define SKL_ADSPCS_CSTALL_MASK (SKL_DSP_CORES_MASK << \
SKL_ADSPCS_CSTALL_SHIFT)
#define SKL_ADSPCS_CSTALL
(x) ((x << SKL_ADSPCS_CSTALL_SHIFT) & \
SKL_ADSPCS_CSTALL_MASK)
/* Set Power Active - when set to '1' turn cores on */
#define SKL_ADSPCS_SPA_SHIFT 16
#define SKL_ADSPCS_SPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_SPA_SHIFT)
#define SKL_ADSPCS_SPA
(x) ((x << SKL_ADSPCS_SPA_SHIFT) & SKL_ADSPCS_SPA_MASK)
/* Current Power Active - power status of cores, set by hardware */
#define SKL_ADSPCS_CPA_SHIFT 24
#define SKL_ADSPCS_CPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT)
#define SKL_ADSPCS_CPA(x) ((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK)
#define S
ST_DSP_POWER_D0 0x0
/* full On */
#define S
ST_DSP_POWER_D3 0x3
/* Off */
/*
* Core Reset - asserted high
* CRST Mask for a given core mask pattern, cm
*/
#define SKL_ADSPCS_CRST_SHIFT
0
#define SKL_ADSPCS_CRST_MASK
(cm) ((cm)
<< SKL_ADSPCS_CRST_SHIFT)
/*
* Core run/stall - when set to '1' core is stalled
* CSTALL Mask for a given core mask pattern, cm
*/
#define SKL_ADSPCS_CSTALL_SHIFT 8
#define SKL_ADSPCS_CSTALL
_MASK(cm) ((cm) << SKL_ADSPCS_CSTALL_SHIFT)
/*
* Set Power Active - when set to '1' turn cores on
* SPA Mask for a given core mask pattern, cm
*/
#define SKL_ADSPCS_SPA
_SHIFT 16
#define SKL_ADSPCS_SPA_MASK(cm) ((cm) << SKL_ADSPCS_SPA_SHIFT)
/*
* Current Power Active - power status of cores, set by hardware
* CPA Mask for a given core mask pattern, cm
*/
#define S
KL_ADSPCS_CPA_SHIFT 24
#define S
KL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT)
enum
skl_dsp_states
{
SKL_DSP_RUNNING
=
1
,
...
...
@@ -115,8 +134,8 @@ struct skl_dsp_fw_ops {
int
(
*
load_fw
)(
struct
sst_dsp
*
ctx
);
/* FW module parser/loader */
int
(
*
parse_fw
)(
struct
sst_dsp
*
ctx
);
int
(
*
set_state_D0
)(
struct
sst_dsp
*
ctx
);
int
(
*
set_state_D3
)(
struct
sst_dsp
*
ctx
);
int
(
*
set_state_D0
)(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
);
int
(
*
set_state_D3
)(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
);
unsigned
int
(
*
get_fw_errcode
)(
struct
sst_dsp
*
ctx
);
int
(
*
load_mod
)(
struct
sst_dsp
*
ctx
,
u16
mod_id
,
u8
*
mod_name
);
int
(
*
unload_mod
)(
struct
sst_dsp
*
ctx
,
u16
mod_id
);
...
...
@@ -157,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
void
skl_dsp_set_state_locked
(
struct
sst_dsp
*
ctx
,
int
state
);
struct
sst_dsp
*
skl_dsp_ctx_init
(
struct
device
*
dev
,
struct
sst_dsp_device
*
sst_dev
,
int
irq
);
int
skl_dsp_enable_core
(
struct
sst_dsp
*
ctx
);
int
skl_dsp_disable_core
(
struct
sst_dsp
*
ctx
);
bool
is_skl_dsp_running
(
struct
sst_dsp
*
ctx
);
unsigned
int
skl_dsp_get_enabled_cores
(
struct
sst_dsp
*
ctx
);
void
skl_dsp_init_core_state
(
struct
sst_dsp
*
ctx
);
int
skl_dsp_enable_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
int
skl_dsp_disable_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
int
skl_dsp_core_power_up
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
int
skl_dsp_core_power_down
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
int
skl_dsp_core_unset_reset_state
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
int
skl_dsp_start_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
);
irqreturn_t
skl_dsp_sst_interrupt
(
int
irq
,
void
*
dev_id
);
int
skl_dsp_wake
(
struct
sst_dsp
*
ctx
);
int
skl_dsp_sleep
(
struct
sst_dsp
*
ctx
);
void
skl_dsp_free
(
struct
sst_dsp
*
dsp
);
int
skl_dsp_get_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
);
int
skl_dsp_put_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
);
int
skl_dsp_boot
(
struct
sst_dsp
*
ctx
);
int
skl_sst_dsp_init
(
struct
device
*
dev
,
void
__iomem
*
mmio_base
,
int
irq
,
const
char
*
fw_name
,
struct
skl_dsp_loader_ops
dsp_ops
,
...
...
@@ -175,4 +206,11 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
void
skl_sst_dsp_cleanup
(
struct
device
*
dev
,
struct
skl_sst
*
ctx
);
void
bxt_sst_dsp_cleanup
(
struct
device
*
dev
,
struct
skl_sst
*
ctx
);
int
snd_skl_get_module_info
(
struct
skl_sst
*
ctx
,
u8
*
uuid
,
struct
skl_dfw_module
*
dfw_config
);
int
snd_skl_parse_uuids
(
struct
sst_dsp
*
ctx
,
unsigned
int
offset
);
void
skl_freeup_uuid_list
(
struct
skl_sst
*
ctx
);
int
skl_dsp_strip_extended_manifest
(
struct
firmware
*
fw
);
#endif
/*__SKL_SST_DSP_H__*/
sound/soc/intel/skylake/skl-sst-ipc.c
View file @
44d62462
...
...
@@ -363,7 +363,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
/* first process the header */
switch
(
reply
)
{
case
IPC_GLB_REPLY_SUCCESS
:
dev_
info
(
ipc
->
dev
,
"ipc FW reply %x: success
\n
"
,
header
.
primary
);
dev_
dbg
(
ipc
->
dev
,
"ipc FW reply %x: success
\n
"
,
header
.
primary
);
/* copy the rx data from the mailbox */
sst_dsp_inbox_read
(
ipc
->
dsp
,
msg
->
rx_data
,
msg
->
rx_size
);
break
;
...
...
@@ -692,7 +692,7 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
/* param_block_size must be in dwords */
u16
param_block_size
=
msg
->
param_data_size
/
sizeof
(
u32
);
print_hex_dump
(
KERN_DEBUG
,
NULL
,
DUMP_PREFIX_NONE
,
print_hex_dump
_debug
(
"Param data:"
,
DUMP_PREFIX_NONE
,
16
,
4
,
buffer
,
param_block_size
,
false
);
header
.
primary
=
IPC_MSG_TARGET
(
IPC_MOD_MSG
);
...
...
sound/soc/intel/skylake/skl-sst-ipc.h
View file @
44d62462
...
...
@@ -45,6 +45,14 @@ 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
];
};
struct
skl_sst
{
struct
device
*
dev
;
struct
sst_dsp
*
dsp
;
...
...
@@ -60,6 +68,15 @@ struct skl_sst {
void
(
*
enable_miscbdcge
)(
struct
device
*
dev
,
bool
enable
);
/*Is CGCTL.MISCBDCGE disabled*/
bool
miscbdcg_disabled
;
/* Populate module information */
struct
list_head
uuid_list
;
/* Is firmware loaded */
bool
fw_loaded
;
/* multi-core */
struct
skl_dsp_cores
cores
;
};
struct
skl_ipc_init_instance_msg
{
...
...
@@ -136,5 +153,6 @@ void skl_ipc_int_disable(struct sst_dsp *dsp);
bool
skl_ipc_int_status
(
struct
sst_dsp
*
dsp
);
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
);
#endif
/* __SKL_IPC_H */
sound/soc/intel/skylake/skl-sst-utils.c
0 → 100644
View file @
44d62462
/*
* skl-sst-utils.c - SKL sst utils functions
*
* Copyright (C) 2016 Intel Corp
*
* 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 <linux/slab.h>
#include <linux/uuid.h>
#include "skl-sst-dsp.h"
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#include "skl-sst-ipc.h"
#define UUID_STR_SIZE 37
#define DEFAULT_HASH_SHA256_LEN 32
/* FW Extended Manifest Header id = $AE1 */
#define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124
struct
skl_dfw_module_mod
{
char
name
[
100
];
struct
skl_dfw_module
skl_dfw_mod
;
};
struct
UUID
{
u8
id
[
16
];
};
union
seg_flags
{
u32
ul
;
struct
{
u32
contents
:
1
;
u32
alloc
:
1
;
u32
load
:
1
;
u32
read_only
:
1
;
u32
code
:
1
;
u32
data
:
1
;
u32
_rsvd0
:
2
;
u32
type
:
4
;
u32
_rsvd1
:
4
;
u32
length
:
16
;
}
r
;
}
__packed
;
struct
segment_desc
{
union
seg_flags
flags
;
u32
v_base_addr
;
u32
file_offset
;
};
struct
module_type
{
u32
load_type
:
4
;
u32
auto_start
:
1
;
u32
domain_ll
:
1
;
u32
domain_dp
:
1
;
u32
rsvd
:
25
;
}
__packed
;
struct
adsp_module_entry
{
u32
struct_id
;
u8
name
[
8
];
struct
UUID
uuid
;
struct
module_type
type
;
u8
hash1
[
DEFAULT_HASH_SHA256_LEN
];
u32
entry_point
;
u16
cfg_offset
;
u16
cfg_count
;
u32
affinity_mask
;
u16
instance_max_count
;
u16
instance_bss_size
;
struct
segment_desc
segments
[
3
];
}
__packed
;
struct
adsp_fw_hdr
{
u32
id
;
u32
len
;
u8
name
[
8
];
u32
preload_page_count
;
u32
fw_image_flags
;
u32
feature_mask
;
u16
major
;
u16
minor
;
u16
hotfix
;
u16
build
;
u32
num_modules
;
u32
hw_buf_base
;
u32
hw_buf_length
;
u32
load_offset
;
}
__packed
;
struct
uuid_module
{
uuid_le
uuid
;
int
id
;
int
is_loadable
;
struct
list_head
list
;
};
struct
skl_ext_manifest_hdr
{
u32
id
;
u32
len
;
u16
version_major
;
u16
version_minor
;
u32
entries
;
};
int
snd_skl_get_module_info
(
struct
skl_sst
*
ctx
,
u8
*
uuid
,
struct
skl_dfw_module
*
dfw_config
)
{
struct
uuid_module
*
module
;
uuid_le
*
uuid_mod
;
uuid_mod
=
(
uuid_le
*
)
uuid
;
list_for_each_entry
(
module
,
&
ctx
->
uuid_list
,
list
)
{
if
(
uuid_le_cmp
(
*
uuid_mod
,
module
->
uuid
)
==
0
)
{
dfw_config
->
module_id
=
module
->
id
;
dfw_config
->
is_loadable
=
module
->
is_loadable
;
return
0
;
}
}
return
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
snd_skl_get_module_info
);
/*
* Parse the firmware binary to get the UUID, module id
* and loadable flags
*/
int
snd_skl_parse_uuids
(
struct
sst_dsp
*
ctx
,
unsigned
int
offset
)
{
struct
adsp_fw_hdr
*
adsp_hdr
;
struct
adsp_module_entry
*
mod_entry
;
int
i
,
num_entry
;
uuid_le
*
uuid_bin
;
const
char
*
buf
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
struct
uuid_module
*
module
;
struct
firmware
stripped_fw
;
unsigned
int
safe_file
;
/* Get the FW pointer to derive ADSP header */
stripped_fw
.
data
=
ctx
->
fw
->
data
;
stripped_fw
.
size
=
ctx
->
fw
->
size
;
skl_dsp_strip_extended_manifest
(
&
stripped_fw
);
buf
=
stripped_fw
.
data
;
/* check if we have enough space in file to move to header */
safe_file
=
sizeof
(
*
adsp_hdr
)
+
offset
;
if
(
stripped_fw
.
size
<=
safe_file
)
{
dev_err
(
ctx
->
dev
,
"Small fw file size, No space for hdr
\n
"
);
return
-
EINVAL
;
}
adsp_hdr
=
(
struct
adsp_fw_hdr
*
)(
buf
+
offset
);
/* check 1st module entry is in file */
safe_file
+=
adsp_hdr
->
len
+
sizeof
(
*
mod_entry
);
if
(
stripped_fw
.
size
<=
safe_file
)
{
dev_err
(
ctx
->
dev
,
"Small fw file size, No module entry
\n
"
);
return
-
EINVAL
;
}
mod_entry
=
(
struct
adsp_module_entry
*
)
(
buf
+
offset
+
adsp_hdr
->
len
);
num_entry
=
adsp_hdr
->
num_modules
;
/* check all entries are in file */
safe_file
+=
num_entry
*
sizeof
(
*
mod_entry
);
if
(
stripped_fw
.
size
<=
safe_file
)
{
dev_err
(
ctx
->
dev
,
"Small fw file size, No modules
\n
"
);
return
-
EINVAL
;
}
/*
* Read the UUID(GUID) from FW Manifest.
*
* The 16 byte UUID format is: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
* Populate the UUID table to store module_id and loadable flags
* for the module.
*/
for
(
i
=
0
;
i
<
num_entry
;
i
++
,
mod_entry
++
)
{
module
=
kzalloc
(
sizeof
(
*
module
),
GFP_KERNEL
);
if
(
!
module
)
return
-
ENOMEM
;
uuid_bin
=
(
uuid_le
*
)
mod_entry
->
uuid
.
id
;
memcpy
(
&
module
->
uuid
,
uuid_bin
,
sizeof
(
module
->
uuid
));
module
->
id
=
i
;
module
->
is_loadable
=
mod_entry
->
type
.
load_type
;
list_add_tail
(
&
module
->
list
,
&
skl
->
uuid_list
);
dev_dbg
(
ctx
->
dev
,
"Adding uuid :%pUL mod id: %d Loadable: %d
\n
"
,
&
module
->
uuid
,
module
->
id
,
module
->
is_loadable
);
}
return
0
;
}
void
skl_freeup_uuid_list
(
struct
skl_sst
*
ctx
)
{
struct
uuid_module
*
uuid
,
*
_uuid
;
list_for_each_entry_safe
(
uuid
,
_uuid
,
&
ctx
->
uuid_list
,
list
)
{
list_del
(
&
uuid
->
list
);
kfree
(
uuid
);
}
}
/*
* some firmware binary contains some extended manifest. This needs
* to be stripped in that case before we load and use that image.
*
* Get the module id for the module by checking
* the table for the UUID for the module
*/
int
skl_dsp_strip_extended_manifest
(
struct
firmware
*
fw
)
{
struct
skl_ext_manifest_hdr
*
hdr
;
/* check if fw file is greater than header we are looking */
if
(
fw
->
size
<
sizeof
(
hdr
))
{
pr_err
(
"%s: Firmware file small, no hdr
\n
"
,
__func__
);
return
-
EINVAL
;
}
hdr
=
(
struct
skl_ext_manifest_hdr
*
)
fw
->
data
;
if
(
hdr
->
id
==
SKL_EXT_MANIFEST_HEADER_MAGIC
)
{
fw
->
size
-=
hdr
->
len
;
fw
->
data
+=
hdr
->
len
;
}
return
0
;
}
sound/soc/intel/skylake/skl-sst.c
View file @
44d62462
...
...
@@ -68,10 +68,13 @@ static int skl_transfer_firmware(struct sst_dsp *ctx,
return
ret
;
}
#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284
static
int
skl_load_base_firmware
(
struct
sst_dsp
*
ctx
)
{
int
ret
=
0
,
i
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
struct
firmware
stripped_fw
;
u32
reg
;
skl
->
boot_complete
=
false
;
...
...
@@ -81,11 +84,25 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
ret
=
request_firmware
(
&
ctx
->
fw
,
ctx
->
fw_name
,
ctx
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Request firmware failed %d
\n
"
,
ret
);
skl_dsp_disable_core
(
ctx
);
return
-
EIO
;
}
}
ret
=
snd_skl_parse_uuids
(
ctx
,
SKL_ADSP_FW_BIN_HDR_OFFSET
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"UUID parsing err: %d
\n
"
,
ret
);
release_firmware
(
ctx
->
fw
);
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
return
ret
;
}
/* check for extended manifest */
stripped_fw
.
data
=
ctx
->
fw
->
data
;
stripped_fw
.
size
=
ctx
->
fw
->
size
;
skl_dsp_strip_extended_manifest
(
&
stripped_fw
);
ret
=
skl_dsp_boot
(
ctx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Boot dsp core failed ret: %d"
,
ret
);
...
...
@@ -119,7 +136,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
goto
transfer_firmware_failed
;
}
ret
=
skl_transfer_firmware
(
ctx
,
ctx
->
fw
->
data
,
ctx
->
fw
->
size
);
ret
=
skl_transfer_firmware
(
ctx
,
stripped_fw
.
data
,
stripped_fw
.
size
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Transfer firmware failed%d
\n
"
,
ret
);
goto
transfer_firmware_failed
;
...
...
@@ -133,67 +150,87 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
}
dev_dbg
(
ctx
->
dev
,
"Download firmware successful%d
\n
"
,
ret
);
skl
_dsp_set_state_locked
(
ctx
,
SKL_DSP_RUNNING
)
;
skl
->
fw_loaded
=
true
;
}
return
0
;
transfer_firmware_failed:
ctx
->
cl_dev
.
ops
.
cl_cleanup_controller
(
ctx
);
skl_load_base_firmware_failed:
skl_dsp_disable_core
(
ctx
);
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
release_firmware
(
ctx
->
fw
);
ctx
->
fw
=
NULL
;
return
ret
;
}
static
int
skl_set_dsp_D0
(
struct
sst_dsp
*
ctx
)
static
int
skl_set_dsp_D0
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
int
ret
;
struct
skl_ipc_dxstate_info
dx
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
unsigned
int
core_mask
=
SKL_DSP_CORE_MASK
(
core_id
);
ret
=
skl_load_base_firmware
(
ctx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"unable to load firmware
\n
"
);
return
ret
;
/* If core0 is being turned on, we need to load the FW */
if
(
core_id
==
SKL_DSP_CORE0_ID
)
{
ret
=
skl_load_base_firmware
(
ctx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"unable to load firmware
\n
"
);
return
ret
;
}
}
skl_dsp_set_state_locked
(
ctx
,
SKL_DSP_RUNNING
);
/*
* If any core other than core 0 is being moved to D0, enable the
* core and send the set dx IPC for the core.
*/
if
(
core_id
!=
SKL_DSP_CORE0_ID
)
{
ret
=
skl_dsp_enable_core
(
ctx
,
core_mask
);
if
(
ret
<
0
)
return
ret
;
dx
.
core_mask
=
core_mask
;
dx
.
dx_mask
=
core_mask
;
ret
=
skl_ipc_set_dx
(
&
skl
->
ipc
,
SKL_INSTANCE_ID
,
SKL_BASE_FW_MODULE_ID
,
&
dx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to set dsp to D0:core id= %d
\n
"
,
core_id
);
skl_dsp_disable_core
(
ctx
,
core_mask
);
}
}
skl
->
cores
.
state
[
core_id
]
=
SKL_DSP_RUNNING
;
return
ret
;
}
static
int
skl_set_dsp_D3
(
struct
sst_dsp
*
ctx
)
static
int
skl_set_dsp_D3
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
int
ret
;
struct
skl_ipc_dxstate_info
dx
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
unsigned
int
core_mask
=
SKL_DSP_CORE_MASK
(
core_id
);
dev_dbg
(
ctx
->
dev
,
"In %s:
\n
"
,
__func__
);
mutex_lock
(
&
ctx
->
mutex
);
if
(
!
is_skl_dsp_running
(
ctx
))
{
mutex_unlock
(
&
ctx
->
mutex
);
return
0
;
}
mutex_unlock
(
&
ctx
->
mutex
);
dx
.
core_mask
=
SKL_DSP_CORE0_MASK
;
dx
.
core_mask
=
core_mask
;
dx
.
dx_mask
=
SKL_IPC_D3_MASK
;
ret
=
skl_ipc_set_dx
(
&
skl
->
ipc
,
SKL_INSTANCE_ID
,
SKL_BASE_FW_MODULE_ID
,
&
dx
);
if
(
ret
<
0
)
dev_err
(
ctx
->
dev
,
"D3 request to FW failed, continuing reset: %d"
,
ret
);
/* disable Interrupt */
ctx
->
cl_dev
.
ops
.
cl_cleanup_controller
(
ctx
);
skl_cldma_int_disable
(
ctx
);
skl_ipc_op_int_disable
(
ctx
);
skl_ipc_int_disable
(
ctx
);
ret
=
skl_dsp_disable_core
(
ctx
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"disable dsp core failed ret: %d
\n
"
,
ret
);
ret
=
-
EIO
;
dev_err
(
ctx
->
dev
,
"set Dx core %d fail: %d
\n
"
,
core_id
,
ret
);
if
(
core_id
==
SKL_DSP_CORE0_ID
)
{
/* disable Interrupt */
ctx
->
cl_dev
.
ops
.
cl_cleanup_controller
(
ctx
);
skl_cldma_int_disable
(
ctx
);
skl_ipc_op_int_disable
(
ctx
);
skl_ipc_int_disable
(
ctx
);
}
skl_dsp_set_state_locked
(
ctx
,
SKL_DSP_RESET
);
ret
=
skl_dsp_disable_core
(
ctx
,
core_mask
);
if
(
ret
<
0
)
return
ret
;
skl
->
cores
.
state
[
core_id
]
=
SKL_DSP_RESET
;
return
ret
;
}
...
...
@@ -360,6 +397,19 @@ static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
return
ret
;
}
void
skl_clear_module_cnt
(
struct
sst_dsp
*
ctx
)
{
struct
skl_module_table
*
module
;
if
(
list_empty
(
&
ctx
->
module_list
))
return
;
list_for_each_entry
(
module
,
&
ctx
->
module_list
,
list
)
{
module
->
usage_cnt
=
0
;
}
}
EXPORT_SYMBOL_GPL
(
skl_clear_module_cnt
);
static
void
skl_clear_module_table
(
struct
sst_dsp
*
ctx
)
{
struct
skl_module_table
*
module
,
*
tmp
;
...
...
@@ -409,6 +459,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
skl
->
dev
=
dev
;
skl_dev
.
thread_context
=
skl
;
INIT_LIST_HEAD
(
&
skl
->
uuid_list
);
skl
->
dsp
=
skl_dsp_ctx_init
(
dev
,
&
skl_dev
,
irq
);
if
(
!
skl
->
dsp
)
{
...
...
@@ -432,12 +483,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if
(
ret
)
return
ret
;
skl
->
cores
.
count
=
2
;
ret
=
sst
->
fw_ops
.
load_fw
(
sst
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Load base fw failed : %d"
,
ret
);
goto
cleanup
;
}
skl_dsp_init_core_state
(
sst
);
if
(
dsp
)
*
dsp
=
skl
;
...
...
@@ -452,6 +507,7 @@ EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
void
skl_sst_dsp_cleanup
(
struct
device
*
dev
,
struct
skl_sst
*
ctx
)
{
skl_clear_module_table
(
ctx
->
dsp
);
skl_freeup_uuid_list
(
ctx
);
skl_ipc_free
(
&
ctx
->
ipc
);
ctx
->
dsp
->
ops
->
free
(
ctx
->
dsp
);
if
(
ctx
->
boot_complete
)
{
...
...
sound/soc/intel/skylake/skl-topology.c
View file @
44d62462
...
...
@@ -378,43 +378,6 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
skl_dump_mconfig
(
ctx
,
m_cfg
);
}
/*
* A pipe can have multiple modules, each of them will be a DAPM widget as
* well. While managing a pipeline we need to get the list of all the
* widgets in a pipelines, so this helper - skl_tplg_get_pipe_widget() helps
* to get the SKL type widgets in that pipeline
*/
static
int
skl_tplg_alloc_pipe_widget
(
struct
device
*
dev
,
struct
snd_soc_dapm_widget
*
w
,
struct
skl_pipe
*
pipe
)
{
struct
skl_module_cfg
*
src_module
=
NULL
;
struct
snd_soc_dapm_path
*
p
=
NULL
;
struct
skl_pipe_module
*
p_module
=
NULL
;
p_module
=
devm_kzalloc
(
dev
,
sizeof
(
*
p_module
),
GFP_KERNEL
);
if
(
!
p_module
)
return
-
ENOMEM
;
p_module
->
w
=
w
;
list_add_tail
(
&
p_module
->
node
,
&
pipe
->
w_list
);
snd_soc_dapm_widget_for_each_sink_path
(
w
,
p
)
{
if
((
p
->
sink
->
priv
==
NULL
)
&&
(
!
is_skl_dsp_widget_type
(
w
)))
continue
;
if
((
p
->
sink
->
priv
!=
NULL
)
&&
p
->
connect
&&
is_skl_dsp_widget_type
(
p
->
sink
))
{
src_module
=
p
->
sink
->
priv
;
if
(
pipe
->
ppl_id
==
src_module
->
pipe
->
ppl_id
)
skl_tplg_alloc_pipe_widget
(
dev
,
p
->
sink
,
pipe
);
}
}
return
0
;
}
/*
* some modules can have multiple params set from user control and
* need to be set after module is initialized. If set_param flag is
...
...
@@ -514,8 +477,6 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
if
(
!
skl_is_pipe_mcps_avail
(
skl
,
mconfig
))
return
-
ENOMEM
;
skl_tplg_alloc_pipe_mcps
(
skl
,
mconfig
);
if
(
mconfig
->
is_loadable
&&
ctx
->
dsp
->
fw_ops
.
load_mod
)
{
ret
=
ctx
->
dsp
->
fw_ops
.
load_mod
(
ctx
->
dsp
,
mconfig
->
id
.
module_id
,
mconfig
->
guid
);
...
...
@@ -539,6 +500,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
if
(
ret
<
0
)
return
ret
;
skl_tplg_alloc_pipe_mcps
(
skl
,
mconfig
);
ret
=
skl_tplg_set_module_params
(
w
,
ctx
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -591,9 +553,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
if
(
!
skl_is_pipe_mem_avail
(
skl
,
mconfig
))
return
-
ENOMEM
;
skl_tplg_alloc_pipe_mem
(
skl
,
mconfig
);
skl_tplg_alloc_pipe_mcps
(
skl
,
mconfig
);
/*
* Create a list of modules for pipe.
* This list contains modules from source to sink
...
...
@@ -602,19 +561,8 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
if
(
ret
<
0
)
return
ret
;
/*
* we create a w_list of all widgets in that pipe. This list is not
* freed on PMD event as widgets within a pipe are static. This
* saves us cycles to get widgets in pipe every time.
*
* So if we have already initialized all the widgets of a pipeline
* we skip, so check for list_empty and create the list if empty
*/
if
(
list_empty
(
&
s_pipe
->
w_list
))
{
ret
=
skl_tplg_alloc_pipe_widget
(
ctx
->
dev
,
w
,
s_pipe
);
if
(
ret
<
0
)
return
ret
;
}
skl_tplg_alloc_pipe_mem
(
skl
,
mconfig
);
skl_tplg_alloc_pipe_mcps
(
skl
,
mconfig
);
/* Init all pipe modules from source to sink */
ret
=
skl_tplg_init_pipe_modules
(
skl
,
s_pipe
);
...
...
@@ -949,13 +897,17 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
struct
skl_pipe
*
s_pipe
=
mconfig
->
pipe
;
int
ret
=
0
;
if
(
s_pipe
->
state
==
SKL_PIPE_INVALID
)
return
-
EINVAL
;
skl_tplg_free_pipe_mcps
(
skl
,
mconfig
);
skl_tplg_free_pipe_mem
(
skl
,
mconfig
);
list_for_each_entry
(
w_module
,
&
s_pipe
->
w_list
,
node
)
{
dst_module
=
w_module
->
w
->
priv
;
skl_tplg_free_pipe_mcps
(
skl
,
dst_module
);
if
(
mconfig
->
m_state
>=
SKL_MODULE_INIT_DONE
)
skl_tplg_free_pipe_mcps
(
skl
,
dst_module
);
if
(
src_module
==
NULL
)
{
src_module
=
dst_module
;
continue
;
...
...
@@ -1162,6 +1114,39 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
return
0
;
}
/*
* Fill the dma id for host and link. In case of passthrough
* pipeline, this will both host and link in the same
* pipeline, so need to copy the link and host based on dev_type
*/
static
void
skl_tplg_fill_dma_id
(
struct
skl_module_cfg
*
mcfg
,
struct
skl_pipe_params
*
params
)
{
struct
skl_pipe
*
pipe
=
mcfg
->
pipe
;
if
(
pipe
->
passthru
)
{
switch
(
mcfg
->
dev_type
)
{
case
SKL_DEVICE_HDALINK
:
pipe
->
p_params
->
link_dma_id
=
params
->
link_dma_id
;
break
;
case
SKL_DEVICE_HDAHOST
:
pipe
->
p_params
->
host_dma_id
=
params
->
host_dma_id
;
break
;
default:
break
;
}
pipe
->
p_params
->
s_fmt
=
params
->
s_fmt
;
pipe
->
p_params
->
ch
=
params
->
ch
;
pipe
->
p_params
->
s_freq
=
params
->
s_freq
;
pipe
->
p_params
->
stream
=
params
->
stream
;
}
else
{
memcpy
(
pipe
->
p_params
,
params
,
sizeof
(
*
params
));
}
}
/*
* The FE params are passed by hw_params of the DAI.
* On hw_params, the params are stored in Gateway module of the FE and we
...
...
@@ -1172,10 +1157,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
struct
skl_module_cfg
*
mconfig
,
struct
skl_pipe_params
*
params
)
{
struct
skl_pipe
*
pipe
=
mconfig
->
pipe
;
struct
skl_module_fmt
*
format
=
NULL
;
memcpy
(
pipe
->
p_params
,
params
,
sizeof
(
*
params
)
);
skl_tplg_fill_dma_id
(
mconfig
,
params
);
if
(
params
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
format
=
&
mconfig
->
in_fmt
[
0
];
...
...
@@ -1362,12 +1346,11 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
struct
skl_module_cfg
*
mconfig
,
struct
skl_pipe_params
*
params
)
{
struct
skl_pipe
*
pipe
=
mconfig
->
pipe
;
struct
nhlt_specific_cfg
*
cfg
;
struct
skl
*
skl
=
get_skl_ctx
(
dai
->
dev
);
int
link_type
=
skl_tplg_be_link_type
(
mconfig
->
dev_type
);
memcpy
(
pipe
->
p_params
,
params
,
sizeof
(
*
params
)
);
skl_tplg_fill_dma_id
(
mconfig
,
params
);
if
(
link_type
==
NHLT_LINK_HDA
)
return
0
;
...
...
@@ -1558,6 +1541,55 @@ static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
}
}
static
void
skl_clear_pin_config
(
struct
snd_soc_platform
*
platform
,
struct
snd_soc_dapm_widget
*
w
)
{
int
i
;
struct
skl_module_cfg
*
mconfig
;
struct
skl_pipe
*
pipe
;
if
(
!
strncmp
(
w
->
dapm
->
component
->
name
,
platform
->
component
.
name
,
strlen
(
platform
->
component
.
name
)))
{
mconfig
=
w
->
priv
;
pipe
=
mconfig
->
pipe
;
for
(
i
=
0
;
i
<
mconfig
->
max_in_queue
;
i
++
)
{
mconfig
->
m_in_pin
[
i
].
in_use
=
false
;
mconfig
->
m_in_pin
[
i
].
pin_state
=
SKL_PIN_UNBIND
;
}
for
(
i
=
0
;
i
<
mconfig
->
max_out_queue
;
i
++
)
{
mconfig
->
m_out_pin
[
i
].
in_use
=
false
;
mconfig
->
m_out_pin
[
i
].
pin_state
=
SKL_PIN_UNBIND
;
}
pipe
->
state
=
SKL_PIPE_INVALID
;
mconfig
->
m_state
=
SKL_MODULE_UNINIT
;
}
}
void
skl_cleanup_resources
(
struct
skl
*
skl
)
{
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
struct
snd_soc_platform
*
soc_platform
=
skl
->
platform
;
struct
snd_soc_dapm_widget
*
w
;
struct
snd_soc_card
*
card
;
if
(
soc_platform
==
NULL
)
return
;
card
=
soc_platform
->
component
.
card
;
if
(
!
card
||
!
card
->
instantiated
)
return
;
skl
->
resource
.
mem
=
0
;
skl
->
resource
.
mcps
=
0
;
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
if
(
is_skl_dsp_widget_type
(
w
)
&&
(
w
->
priv
!=
NULL
))
skl_clear_pin_config
(
soc_platform
,
w
);
}
skl_clear_module_cnt
(
ctx
->
dsp
);
}
/*
* Topology core widget load callback
*
...
...
@@ -1589,6 +1621,10 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
w
->
priv
=
mconfig
;
memcpy
(
&
mconfig
->
guid
,
&
dfw_config
->
uuid
,
16
);
ret
=
snd_skl_get_module_info
(
skl
->
skl_sst
,
mconfig
->
guid
,
dfw_config
);
if
(
ret
<
0
)
return
ret
;
mconfig
->
id
.
module_id
=
dfw_config
->
module_id
;
mconfig
->
id
.
instance_id
=
dfw_config
->
instance_id
;
mconfig
->
mcps
=
dfw_config
->
max_mcps
;
...
...
@@ -1738,6 +1774,60 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
.
bytes_ext_ops_count
=
ARRAY_SIZE
(
skl_tlv_ops
),
};
/*
* A pipe can have multiple modules, each of them will be a DAPM widget as
* well. While managing a pipeline we need to get the list of all the
* widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list()
* helps to get the SKL type widgets in that pipeline
*/
static
int
skl_tplg_create_pipe_widget_list
(
struct
snd_soc_platform
*
platform
)
{
struct
snd_soc_dapm_widget
*
w
;
struct
skl_module_cfg
*
mcfg
=
NULL
;
struct
skl_pipe_module
*
p_module
=
NULL
;
struct
skl_pipe
*
pipe
;
list_for_each_entry
(
w
,
&
platform
->
component
.
card
->
widgets
,
list
)
{
if
(
is_skl_dsp_widget_type
(
w
)
&&
w
->
priv
!=
NULL
)
{
mcfg
=
w
->
priv
;
pipe
=
mcfg
->
pipe
;
p_module
=
devm_kzalloc
(
platform
->
dev
,
sizeof
(
*
p_module
),
GFP_KERNEL
);
if
(
!
p_module
)
return
-
ENOMEM
;
p_module
->
w
=
w
;
list_add_tail
(
&
p_module
->
node
,
&
pipe
->
w_list
);
}
}
return
0
;
}
static
void
skl_tplg_set_pipe_type
(
struct
skl
*
skl
,
struct
skl_pipe
*
pipe
)
{
struct
skl_pipe_module
*
w_module
;
struct
snd_soc_dapm_widget
*
w
;
struct
skl_module_cfg
*
mconfig
;
bool
host_found
=
false
,
link_found
=
false
;
list_for_each_entry
(
w_module
,
&
pipe
->
w_list
,
node
)
{
w
=
w_module
->
w
;
mconfig
=
w
->
priv
;
if
(
mconfig
->
dev_type
==
SKL_DEVICE_HDAHOST
)
host_found
=
true
;
else
if
(
mconfig
->
dev_type
!=
SKL_DEVICE_NONE
)
link_found
=
true
;
}
if
(
host_found
&&
link_found
)
pipe
->
passthru
=
true
;
else
pipe
->
passthru
=
false
;
}
/* This will be read from topology manifest, currently defined here */
#define SKL_MAX_MCPS 30000000
#define SKL_FW_MAX_MEM 1000000
...
...
@@ -1751,6 +1841,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
const
struct
firmware
*
fw
;
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
ebus
);
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
struct
skl_pipeline
*
ppl
;
ret
=
request_firmware
(
&
fw
,
skl
->
tplg_name
,
bus
->
dev
);
if
(
ret
<
0
)
{
...
...
@@ -1780,6 +1871,12 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
skl
->
resource
.
max_mem
=
SKL_FW_MAX_MEM
;
skl
->
tplg
=
fw
;
ret
=
skl_tplg_create_pipe_widget_list
(
platform
);
if
(
ret
<
0
)
return
ret
;
list_for_each_entry
(
ppl
,
&
skl
->
ppl_list
,
node
)
skl_tplg_set_pipe_type
(
skl
,
ppl
->
pipe
);
return
0
;
}
sound/soc/intel/skylake/skl-topology.h
View file @
44d62462
...
...
@@ -244,7 +244,8 @@ enum skl_pipe_state {
SKL_PIPE_INVALID
=
0
,
SKL_PIPE_CREATED
=
1
,
SKL_PIPE_PAUSED
=
2
,
SKL_PIPE_STARTED
=
3
SKL_PIPE_STARTED
=
3
,
SKL_PIPE_RESET
=
4
};
struct
skl_pipe_module
{
...
...
@@ -270,6 +271,7 @@ struct skl_pipe {
struct
skl_pipe_params
*
p_params
;
enum
skl_pipe_state
state
;
struct
list_head
w_list
;
bool
passthru
;
};
enum
skl_module_state
{
...
...
@@ -358,6 +360,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
int
skl_stop_pipe
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
);
int
skl_reset_pipe
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
);
int
skl_init_module
(
struct
skl_sst
*
ctx
,
struct
skl_module_cfg
*
module_config
);
int
skl_bind_modules
(
struct
skl_sst
*
ctx
,
struct
skl_module_cfg
...
...
sound/soc/intel/skylake/skl.c
View file @
44d62462
...
...
@@ -35,6 +35,8 @@
#include "skl-sst-dsp.h"
#include "skl-sst-ipc.h"
static
struct
skl_machine_pdata
skl_dmic_data
;
/*
* initialize the PCI registers
*/
...
...
@@ -184,6 +186,7 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
{
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
ebus
);
struct
pci_dev
*
pci
=
to_pci_dev
(
bus
->
dev
);
int
ret
;
snd_hdac_ext_bus_link_power_down_all
(
ebus
);
...
...
@@ -193,9 +196,12 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
return
ret
;
snd_hdac_bus_stop_chip
(
bus
);
update_pci_dword
(
pci
,
AZX_PCIREG_PGCTL
,
AZX_PGCTL_LSRMD_MASK
,
AZX_PGCTL_LSRMD_MASK
);
skl_enable_miscbdcge
(
bus
->
dev
,
false
);
snd_hdac_bus_enter_link_reset
(
bus
);
skl_enable_miscbdcge
(
bus
->
dev
,
true
);
skl_cleanup_resources
(
skl
);
return
0
;
}
...
...
@@ -242,6 +248,7 @@ static int skl_suspend(struct device *dev)
ret
=
_skl_suspend
(
ebus
);
if
(
ret
<
0
)
return
ret
;
skl
->
skl_sst
->
fw_loaded
=
false
;
}
if
(
IS_ENABLED
(
CONFIG_SND_SOC_HDAC_HDMI
))
{
...
...
@@ -397,6 +404,10 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data)
platform_device_put
(
pdev
);
return
-
EIO
;
}
if
(
mach
->
pdata
)
dev_set_drvdata
(
&
pdev
->
dev
,
mach
->
pdata
);
skl
->
i2s_dev
=
pdev
;
return
0
;
...
...
@@ -657,6 +668,8 @@ static int skl_probe(struct pci_dev *pci,
skl
->
pci_id
=
pci
->
device
;
device_disable_async_suspend
(
bus
->
dev
);
skl
->
nhlt
=
skl_nhlt_init
(
bus
->
dev
);
if
(
skl
->
nhlt
==
NULL
)
...
...
@@ -666,6 +679,8 @@ static int skl_probe(struct pci_dev *pci,
pci_set_drvdata
(
skl
->
pci
,
ebus
);
skl_dmic_data
.
dmic_num
=
skl_get_dmic_geo
(
skl
);
/* check if dsp is there */
if
(
ebus
->
ppcap
)
{
err
=
skl_machine_device_register
(
skl
,
...
...
@@ -713,7 +728,7 @@ static int skl_probe(struct pci_dev *pci,
list_for_each_entry
(
hlink
,
&
ebus
->
hlink_list
,
list
)
snd_hdac_ext_bus_link_put
(
ebus
,
hlink
);
/*configure PM */
/*
configure PM */
pm_runtime_put_noidle
(
bus
->
dev
);
pm_runtime_allow
(
bus
->
dev
);
...
...
@@ -766,8 +781,7 @@ static void skl_remove(struct pci_dev *pci)
struct
hdac_ext_bus
*
ebus
=
pci_get_drvdata
(
pci
);
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
if
(
skl
->
tplg
)
release_firmware
(
skl
->
tplg
);
release_firmware
(
skl
->
tplg
);
if
(
pci_dev_run_wake
(
pci
))
pm_runtime_get_noresume
(
&
pci
->
dev
);
...
...
@@ -786,15 +800,23 @@ static void skl_remove(struct pci_dev *pci)
static
struct
sst_acpi_mach
sst_skl_devdata
[]
=
{
{
"INT343A"
,
"skl_alc286s_i2s"
,
"intel/dsp_fw_release.bin"
,
NULL
,
NULL
,
NULL
},
{
"INT343B"
,
"skl_n
au88l25_ssm4567_i2s
"
,
"intel/dsp_fw_release.bin"
,
NULL
,
NULL
,
NULL
},
{
"MX98357A"
,
"skl_n
au88l25_max98357a_i2s
"
,
"intel/dsp_fw_release.bin"
,
NULL
,
NULL
,
NULL
},
{
"INT343B"
,
"skl_n
88l25_s4567
"
,
"intel/dsp_fw_release.bin"
,
NULL
,
NULL
,
&
skl_dmic_data
},
{
"MX98357A"
,
"skl_n
88l25_m98357a
"
,
"intel/dsp_fw_release.bin"
,
NULL
,
NULL
,
&
skl_dmic_data
},
{}
};
static
struct
sst_acpi_mach
sst_bxtp_devdata
[]
=
{
{
"INT343A"
,
"bxt_alc298s_i2s"
,
"intel/dsp_fw_bxtn.bin"
,
NULL
,
NULL
,
NULL
},
{
"DLGS7219"
,
"bxt_da7219_max98357a_i2s"
,
"intel/dsp_fw_bxtn.bin"
,
NULL
,
NULL
,
NULL
},
};
static
struct
sst_acpi_mach
sst_kbl_devdata
[]
=
{
{
"INT343A"
,
"kbl_alc286s_i2s"
,
"intel/dsp_fw_kbl.bin"
,
NULL
,
NULL
,
NULL
},
{
"INT343B"
,
"kbl_n88l25_s4567"
,
"intel/dsp_fw_kbl.bin"
,
NULL
,
NULL
,
&
skl_dmic_data
},
{
"MX98357A"
,
"kbl_n88l25_m98357a"
,
"intel/dsp_fw_kbl.bin"
,
NULL
,
NULL
,
&
skl_dmic_data
},
{}
};
/* PCI IDs */
...
...
@@ -805,6 +827,9 @@ static const struct pci_device_id skl_ids[] = {
/* BXT-P */
{
PCI_DEVICE
(
0x8086
,
0x5a98
),
.
driver_data
=
(
unsigned
long
)
&
sst_bxtp_devdata
},
/* KBL */
{
PCI_DEVICE
(
0x8086
,
0x9D71
),
.
driver_data
=
(
unsigned
long
)
&
sst_kbl_devdata
},
{
0
,
}
};
MODULE_DEVICE_TABLE
(
pci
,
skl_ids
);
...
...
sound/soc/intel/skylake/skl.h
View file @
44d62462
...
...
@@ -48,6 +48,8 @@
#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
#define AZX_PCIREG_PGCTL 0x44
#define AZX_PGCTL_LSRMD_MASK (1 << 4)
#define AZX_PCIREG_CGCTL 0x48
#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
...
...
@@ -65,6 +67,7 @@ struct skl {
unsigned
int
init_failed
:
1
;
/* delayed init failed */
struct
platform_device
*
dmic_dev
;
struct
platform_device
*
i2s_dev
;
struct
snd_soc_platform
*
platform
;
struct
nhlt_acpi_table
*
nhlt
;
/* nhlt ptr */
struct
skl_sst
*
skl_sst
;
/* sst skl ctx */
...
...
@@ -90,6 +93,11 @@ struct skl_dma_params {
u8
stream_tag
;
};
/* to pass dmic data */
struct
skl_machine_pdata
{
u32
dmic_num
;
};
struct
skl_dsp_ops
{
int
id
;
struct
skl_dsp_loader_ops
(
*
loader_ops
)(
void
);
...
...
@@ -108,9 +116,11 @@ void skl_nhlt_free(struct nhlt_acpi_table *addr);
struct
nhlt_specific_cfg
*
skl_get_ep_blob
(
struct
skl
*
skl
,
u32
instance
,
u8
link_type
,
u8
s_fmt
,
u8
no_ch
,
u32
s_rate
,
u8
dirn
);
int
skl_get_dmic_geo
(
struct
skl
*
skl
);
int
skl_nhlt_update_topology_bin
(
struct
skl
*
skl
);
int
skl_init_dsp
(
struct
skl
*
skl
);
int
skl_free_dsp
(
struct
skl
*
skl
);
int
skl_suspend_dsp
(
struct
skl
*
skl
);
int
skl_resume_dsp
(
struct
skl
*
skl
);
void
skl_cleanup_resources
(
struct
skl
*
skl
);
#endif
/* __SOUND_SOC_SKL_H */
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