Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
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
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
/*
* Intel Broxton-P I2S Machine Driver
*
* Copyright (C) 2016, Intel Corporation. All rights reserved.
*
* Modified from:
* Intel Skylake I2S Machine driver
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "../../codecs/hdac_hdmi.h"
#include "../../codecs/da7219.h"
#include "../../codecs/da7219-aad.h"
#define BXT_DIALOG_CODEC_DAI "da7219-hifi"
#define BXT_MAXIM_CODEC_DAI "HiFi"
#define DUAL_CHANNEL 2
static
struct
snd_soc_jack
broxton_headset
;
enum
{
BXT_DPCM_AUDIO_PB
=
0
,
BXT_DPCM_AUDIO_CP
,
BXT_DPCM_AUDIO_REF_CP
,
BXT_DPCM_AUDIO_HDMI1_PB
,
BXT_DPCM_AUDIO_HDMI2_PB
,
BXT_DPCM_AUDIO_HDMI3_PB
,
};
static
const
struct
snd_kcontrol_new
broxton_controls
[]
=
{
SOC_DAPM_PIN_SWITCH
(
"Headphone Jack"
),
SOC_DAPM_PIN_SWITCH
(
"Headset Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Spk"
),
};
static
const
struct
snd_soc_dapm_widget
broxton_widgets
[]
=
{
SND_SOC_DAPM_HP
(
"Headphone Jack"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Headset Mic"
,
NULL
),
SND_SOC_DAPM_SPK
(
"Spk"
,
NULL
),
SND_SOC_DAPM_MIC
(
"SoC DMIC"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI1"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI2"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI3"
,
NULL
),
};
static
const
struct
snd_soc_dapm_route
broxton_map
[]
=
{
/* HP jack connectors - unknown if we have jack detection */
{
"Headphone Jack"
,
NULL
,
"HPL"
},
{
"Headphone Jack"
,
NULL
,
"HPR"
},
/* speaker */
{
"Spk"
,
NULL
,
"Speaker"
},
/* other jacks */
{
"MIC"
,
NULL
,
"Headset Mic"
},
/* digital mics */
{
"DMic"
,
NULL
,
"SoC DMIC"
},
/* CODEC BE connections */
{
"HiFi Playback"
,
NULL
,
"ssp5 Tx"
},
{
"ssp5 Tx"
,
NULL
,
"codec0_out"
},
{
"Playback"
,
NULL
,
"ssp1 Tx"
},
{
"ssp1 Tx"
,
NULL
,
"codec1_out"
},
{
"codec0_in"
,
NULL
,
"ssp1 Rx"
},
{
"ssp1 Rx"
,
NULL
,
"Capture"
},
{
"HDMI1"
,
NULL
,
"hif5 Output"
},
{
"HDMI2"
,
NULL
,
"hif6 Output"
},
{
"HDMI3"
,
NULL
,
"hif7 Output"
},
{
"hifi3"
,
NULL
,
"iDisp3 Tx"
},
{
"iDisp3 Tx"
,
NULL
,
"iDisp3_out"
},
{
"hifi2"
,
NULL
,
"iDisp2 Tx"
},
{
"iDisp2 Tx"
,
NULL
,
"iDisp2_out"
},
{
"hifi1"
,
NULL
,
"iDisp1 Tx"
},
{
"iDisp1 Tx"
,
NULL
,
"iDisp1_out"
},
/* DMIC */
{
"dmic01_hifi"
,
NULL
,
"DMIC01 Rx"
},
{
"DMIC01 Rx"
,
NULL
,
"DMIC AIF"
},
};
static
int
broxton_ssp_fixup
(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_interval
*
rate
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_RATE
);
struct
snd_interval
*
channels
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
struct
snd_mask
*
fmt
=
hw_param_mask
(
params
,
SNDRV_PCM_HW_PARAM_FORMAT
);
/* The ADSP will convert the FE rate to 48k, stereo */
rate
->
min
=
rate
->
max
=
48000
;
channels
->
min
=
channels
->
max
=
DUAL_CHANNEL
;
/* set SSP to 24 bit */
snd_mask_none
(
fmt
);
snd_mask_set
(
fmt
,
SNDRV_PCM_FORMAT_S24_LE
);
return
0
;
}
static
int
broxton_da7219_codec_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
int
ret
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
/*
* Headset buttons map to the google Reference headset.
* These can be configured by userspace.
*/
ret
=
snd_soc_card_jack_new
(
rtd
->
card
,
"Headset Jack"
,
SND_JACK_HEADSET
|
SND_JACK_BTN_0
|
SND_JACK_BTN_1
|
SND_JACK_BTN_2
|
SND_JACK_BTN_3
,
&
broxton_headset
,
NULL
,
0
);
if
(
ret
)
{
dev_err
(
rtd
->
dev
,
"Headset Jack creation failed: %d
\n
"
,
ret
);
return
ret
;
}
da7219_aad_jack_det
(
codec
,
&
broxton_headset
);
snd_soc_dapm_ignore_suspend
(
&
rtd
->
card
->
dapm
,
"SoC DMIC"
);
return
ret
;
}
static
int
broxton_hdmi_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_dai
*
dai
=
rtd
->
codec_dai
;
return
hdac_hdmi_jack_init
(
dai
,
BXT_DPCM_AUDIO_HDMI1_PB
+
dai
->
id
);
}
static
int
broxton_da7219_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
unsigned
int
rates
[]
=
{
48000
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_rates
=
{
.
count
=
ARRAY_SIZE
(
rates
),
.
list
=
rates
,
.
mask
=
0
,
};
static
unsigned
int
channels
[]
=
{
DUAL_CHANNEL
,
};
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
* 16 bit audio
*/
runtime
->
hw
.
channels_max
=
DUAL_CHANNEL
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_channels
);
runtime
->
hw
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
;
snd_pcm_hw_constraint_msbits
(
runtime
,
0
,
16
,
16
);
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
return
0
;
}
static
const
struct
snd_soc_ops
broxton_da7219_fe_ops
=
{
.
startup
=
bxt_fe_startup
,
};
static
int
broxton_da7219_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
;
ret
=
snd_soc_dai_set_sysclk
(
codec_dai
,
DA7219_CLKSRC_MCLK
,
19200000
,
SND_SOC_CLOCK_IN
);
if
(
ret
<
0
)
dev_err
(
codec_dai
->
dev
,
"can't set codec sysclk configuration
\n
"
);
ret
=
snd_soc_dai_set_pll
(
codec_dai
,
0
,
DA7219_SYSCLK_PLL_SRM
,
0
,
DA7219_PLL_FREQ_OUT_98304
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"failed to start PLL: %d
\n
"
,
ret
);
return
-
EIO
;
}
return
ret
;
}
static
int
broxton_da7219_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
int
ret
;
ret
=
snd_soc_dai_set_pll
(
codec_dai
,
0
,
DA7219_SYSCLK_MCLK
,
0
,
0
);
if
(
ret
<
0
)
{
dev_err
(
codec_dai
->
dev
,
"failed to stop PLL: %d
\n
"
,
ret
);
return
-
EIO
;
}
return
ret
;
}
static
struct
snd_soc_ops
broxton_da7219_ops
=
{
.
hw_params
=
broxton_da7219_hw_params
,
.
hw_free
=
broxton_da7219_hw_free
,
};
/* broxton digital audio interface glue - connects codec <--> CPU */
static
struct
snd_soc_dai_link
broxton_dais
[]
=
{
/* Front End DAI links */
[
BXT_DPCM_AUDIO_PB
]
{
.
name
=
"Bxt Audio Port"
,
.
stream_name
=
"Audio"
,
.
cpu_dai_name
=
"System Pin"
,
.
platform_name
=
"0000:00:0e.0"
,
.
dynamic
=
1
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
nonatomic
=
1
,
.
init
=
broxton_da7219_fe_init
,
.
trigger
=
{
SND_SOC_DPCM_TRIGGER_POST
,
SND_SOC_DPCM_TRIGGER_POST
},
.
dpcm_playback
=
1
,
.
ops
=
&
broxton_da7219_fe_ops
,
},
[
BXT_DPCM_AUDIO_CP
]
{
.
name
=
"Bxt Audio Capture Port"
,
.
stream_name
=
"Audio Record"
,
.
cpu_dai_name
=
"System Pin"
,
.
platform_name
=
"0000:00:0e.0"
,
.
dynamic
=
1
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
nonatomic
=
1
,
.
trigger
=
{
SND_SOC_DPCM_TRIGGER_POST
,
SND_SOC_DPCM_TRIGGER_POST
},
.
dpcm_capture
=
1
,
.
ops
=
&
broxton_da7219_fe_ops
,
},
[
BXT_DPCM_AUDIO_REF_CP
]
{
.
name
=
"Bxt Audio Reference cap"
,
.
stream_name
=
"Refcap"
,
.
cpu_dai_name
=
"Reference Pin"
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
platform_name
=
"0000:00:0e.0"
,
.
init
=
NULL
,
.
dpcm_capture
=
1
,
.
ignore_suspend
=
1
,
.
nonatomic
=
1
,
.
dynamic
=
1
,
},
[
BXT_DPCM_AUDIO_HDMI1_PB
]
{
.
name
=
"Bxt HDMI Port1"
,
.
stream_name
=
"Hdmi1"
,
.
cpu_dai_name
=
"HDMI1 Pin"
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
platform_name
=
"0000:00:0e.0"
,
.
dpcm_playback
=
1
,
.
init
=
NULL
,
.
nonatomic
=
1
,
.
dynamic
=
1
,
},
[
BXT_DPCM_AUDIO_HDMI2_PB
]
{
.
name
=
"Bxt HDMI Port2"
,
.
stream_name
=
"Hdmi2"
,
.
cpu_dai_name
=
"HDMI2 Pin"
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
platform_name
=
"0000:00:0e.0"
,
.
dpcm_playback
=
1
,
.
init
=
NULL
,
.
nonatomic
=
1
,
.
dynamic
=
1
,
},
[
BXT_DPCM_AUDIO_HDMI3_PB
]
{
.
name
=
"Bxt HDMI Port3"
,
.
stream_name
=
"Hdmi3"
,
.
cpu_dai_name
=
"HDMI3 Pin"
,
.
codec_name
=
"snd-soc-dummy"
,
.
codec_dai_name
=
"snd-soc-dummy-dai"
,
.
platform_name
=
"0000:00:0e.0"
,
.
dpcm_playback
=
1
,
.
init
=
NULL
,
.
nonatomic
=
1
,
.
dynamic
=
1
,
},
/* Back End DAI links */
{
/* SSP5 - Codec */
.
name
=
"SSP5-Codec"
,
.
id
=
0
,
.
cpu_dai_name
=
"SSP5 Pin"
,
.
platform_name
=
"0000:00:0e.0"
,
.
no_pcm
=
1
,
.
codec_name
=
"MX98357A:00"
,
.
codec_dai_name
=
BXT_MAXIM_CODEC_DAI
,
.
dai_fmt
=
SND_SOC_DAIFMT_I2S
|
SND_SOC_DAIFMT_NB_NF
|
SND_SOC_DAIFMT_CBS_CFS
,
.
ignore_pmdown_time
=
1
,
.
be_hw_params_fixup
=
broxton_ssp_fixup
,
.
dpcm_playback
=
1
,
},
{
/* SSP1 - Codec */
.
name
=
"SSP1-Codec"
,
.
id
=
1
,
.
cpu_dai_name
=
"SSP1 Pin"
,
.
platform_name
=
"0000:00:0e.0"
,
.
no_pcm
=
1
,
.
codec_name
=
"i2c-DLGS7219:00"
,
.
codec_dai_name
=
BXT_DIALOG_CODEC_DAI
,
.
init
=
broxton_da7219_codec_init
,
.
dai_fmt
=
SND_SOC_DAIFMT_I2S
|
SND_SOC_DAIFMT_NB_NF
|
SND_SOC_DAIFMT_CBS_CFS
,
.
ignore_pmdown_time
=
1
,
.
be_hw_params_fixup
=
broxton_ssp_fixup
,
.
ops
=
&
broxton_da7219_ops
,
.
dpcm_playback
=
1
,
.
dpcm_capture
=
1
,
},
{
.
name
=
"dmic01"
,
.
id
=
2
,
.
cpu_dai_name
=
"DMIC01 Pin"
,
.
codec_name
=
"dmic-codec"
,
.
codec_dai_name
=
"dmic-hifi"
,
.
platform_name
=
"0000:00:0e.0"
,
.
ignore_suspend
=
1
,
.
dpcm_capture
=
1
,
.
no_pcm
=
1
,
},
{
.
name
=
"iDisp1"
,
.
id
=
3
,
.
cpu_dai_name
=
"iDisp1 Pin"
,
.
codec_name
=
"ehdaudio0D2"
,
.
codec_dai_name
=
"intel-hdmi-hifi1"
,
.
platform_name
=
"0000:00:0e.0"
,
.
init
=
broxton_hdmi_init
,
.
dpcm_playback
=
1
,
.
no_pcm
=
1
,
},
{
.
name
=
"iDisp2"
,
.
id
=
4
,
.
cpu_dai_name
=
"iDisp2 Pin"
,
.
codec_name
=
"ehdaudio0D2"
,
.
codec_dai_name
=
"intel-hdmi-hifi2"
,
.
platform_name
=
"0000:00:0e.0"
,
.
init
=
broxton_hdmi_init
,
.
dpcm_playback
=
1
,
.
no_pcm
=
1
,
},
{
.
name
=
"iDisp3"
,
.
id
=
5
,
.
cpu_dai_name
=
"iDisp3 Pin"
,
.
codec_name
=
"ehdaudio0D2"
,
.
codec_dai_name
=
"intel-hdmi-hifi3"
,
.
platform_name
=
"0000:00:0e.0"
,
.
init
=
broxton_hdmi_init
,
.
dpcm_playback
=
1
,
.
no_pcm
=
1
,
},
};
/* broxton audio machine driver for SPT + da7219 */
static
struct
snd_soc_card
broxton_audio_card
=
{
.
name
=
"bxtda7219max"
,
.
owner
=
THIS_MODULE
,
.
dai_link
=
broxton_dais
,
.
num_links
=
ARRAY_SIZE
(
broxton_dais
),
.
controls
=
broxton_controls
,
.
num_controls
=
ARRAY_SIZE
(
broxton_controls
),
.
dapm_widgets
=
broxton_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
broxton_widgets
),
.
dapm_routes
=
broxton_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
broxton_map
),
.
fully_routed
=
true
,
};
static
int
broxton_audio_probe
(
struct
platform_device
*
pdev
)
{
broxton_audio_card
.
dev
=
&
pdev
->
dev
;
return
devm_snd_soc_register_card
(
&
pdev
->
dev
,
&
broxton_audio_card
);
}
static
struct
platform_driver
broxton_audio
=
{
.
probe
=
broxton_audio_probe
,
.
driver
=
{
.
name
=
"bxt_da7219_max98357a_i2s"
,
.
pm
=
&
snd_soc_pm_ops
,
},
};
module_platform_driver
(
broxton_audio
)
/* Module information */
MODULE_DESCRIPTION
(
"Audio Machine driver-DA7219 & MAX98357A in I2S mode"
);
MODULE_AUTHOR
(
"Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>"
);
MODULE_AUTHOR
(
"Rohit Ainapure <rohit.m.ainapure@intel.com>"
);
MODULE_AUTHOR
(
"Harsha Priya <harshapriya.n@intel.com>"
);
MODULE_AUTHOR
(
"Conrad Cooke <conrad.cooke@intel.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:bxt_da7219_max98357a_i2s"
);
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
...
...
@@ -34,33 +34,84 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
mutex_unlock
(
&
ctx
->
mutex
);
}
static
int
skl_dsp_core_set_reset_state
(
struct
sst_dsp
*
ctx
)
/*
* Initialize core power state and usage count. To be called after
* successful first boot. Hence core 0 will be running and other cores
* will be reset
*/
void
skl_dsp_init_core_state
(
struct
sst_dsp
*
ctx
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
i
;
skl
->
cores
.
state
[
SKL_DSP_CORE0_ID
]
=
SKL_DSP_RUNNING
;
skl
->
cores
.
usage_count
[
SKL_DSP_CORE0_ID
]
=
1
;
for
(
i
=
SKL_DSP_CORE0_ID
+
1
;
i
<
SKL_DSP_CORES_MAX
;
i
++
)
{
skl
->
cores
.
state
[
i
]
=
SKL_DSP_RESET
;
skl
->
cores
.
usage_count
[
i
]
=
0
;
}
}
/* Get the mask for all enabled cores */
unsigned
int
skl_dsp_get_enabled_cores
(
struct
sst_dsp
*
ctx
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
unsigned
int
core_mask
,
en_cores_mask
;
u32
val
;
core_mask
=
SKL_DSP_CORES_MASK
(
skl
->
cores
.
count
);
val
=
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
);
/* Cores having CPA bit set */
en_cores_mask
=
(
val
&
SKL_ADSPCS_CPA_MASK
(
core_mask
))
>>
SKL_ADSPCS_CPA_SHIFT
;
/* And cores having CRST bit cleared */
en_cores_mask
&=
(
~
val
&
SKL_ADSPCS_CRST_MASK
(
core_mask
))
>>
SKL_ADSPCS_CRST_SHIFT
;
/* And cores having CSTALL bit cleared */
en_cores_mask
&=
(
~
val
&
SKL_ADSPCS_CSTALL_MASK
(
core_mask
))
>>
SKL_ADSPCS_CSTALL_SHIFT
;
en_cores_mask
&=
core_mask
;
dev_dbg
(
ctx
->
dev
,
"DSP enabled cores mask = %x
\n
"
,
en_cores_mask
);
return
en_cores_mask
;
}
static
int
skl_dsp_core_set_reset_state
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
/* update bits */
sst_dsp_shim_update_bits_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CRST_MASK
,
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
));
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CRST_MASK
(
core_mask
)
,
SKL_ADSPCS_CRST
_MASK
(
core_mask
));
/* poll with timeout to check if operation successful */
ret
=
sst_dsp_register_poll
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CRST_MASK
,
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
),
SKL_ADSPCS_CRST_MASK
(
core_mask
)
,
SKL_ADSPCS_CRST
_MASK
(
core_mask
),
SKL_DSP_RESET_TO
,
"Set reset"
);
if
((
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
)
&
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
))
!=
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
))
{
dev_err
(
ctx
->
dev
,
"Set reset state failed
\n
"
);
SKL_ADSPCS_CRST_MASK
(
core_mask
))
!=
SKL_ADSPCS_CRST_MASK
(
core_mask
))
{
dev_err
(
ctx
->
dev
,
"Set reset state failed: core_mask %x
\n
"
,
core_mask
);
ret
=
-
EIO
;
}
return
ret
;
}
static
int
skl_dsp_core_unset_reset_state
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_core_unset_reset_state
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
...
...
@@ -68,152 +119,160 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
/* update bits */
sst_dsp_shim_update_bits_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CRST_MASK
,
0
);
SKL_ADSPCS_CRST_MASK
(
core_mask
)
,
0
);
/* poll with timeout to check if operation successful */
ret
=
sst_dsp_register_poll
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CRST_MASK
,
SKL_ADSPCS_CRST_MASK
(
core_mask
)
,
0
,
SKL_DSP_RESET_TO
,
"Unset reset"
);
if
((
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
)
&
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
))
!=
0
)
{
dev_err
(
ctx
->
dev
,
"Unset reset state failed
\n
"
);
SKL_ADSPCS_CRST_MASK
(
core_mask
))
!=
0
)
{
dev_err
(
ctx
->
dev
,
"Unset reset state failed: core_mask %x
\n
"
,
core_mask
);
ret
=
-
EIO
;
}
return
ret
;
}
static
bool
is_skl_dsp_core_enable
(
struct
sst_dsp
*
ctx
)
static
bool
is_skl_dsp_core_enable
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
val
;
bool
is_enable
;
val
=
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
);
is_enable
=
((
val
&
SKL_ADSPCS_CPA
(
SKL_DSP_CORES_MASK
))
&&
(
val
&
SKL_ADSPCS_SPA
(
SKL_DSP_CORES_MASK
))
&&
!
(
val
&
SKL_ADSPCS_CRST
(
SKL_DSP_CORES_MASK
))
&&
!
(
val
&
SKL_ADSPCS_CSTALL
(
SKL_DSP_CORES_MASK
)));
is_enable
=
((
val
&
SKL_ADSPCS_CPA_MASK
(
core_mask
))
&&
(
val
&
SKL_ADSPCS_SPA_MASK
(
core_mask
))
&&
!
(
val
&
SKL_ADSPCS_CRST_MASK
(
core_mask
))
&&
!
(
val
&
SKL_ADSPCS_CSTALL_MASK
(
core_mask
)));
dev_dbg
(
ctx
->
dev
,
"DSP core(s) enabled? %d : core_mask %x
\n
"
,
is_enable
,
core_mask
);
dev_dbg
(
ctx
->
dev
,
"DSP core is enabled=%d
\n
"
,
is_enable
);
return
is_enable
;
}
static
int
skl_dsp_reset_core
(
struct
sst_dsp
*
ctx
)
static
int
skl_dsp_reset_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
/* stall core */
sst_dsp_shim_
write
_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
)
&
SKL_ADSPCS_CSTALL
(
SKL_DSP_CORES_MASK
));
sst_dsp_shim_
update_bits
_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CSTALL_MASK
(
core_mask
),
SKL_ADSPCS_CSTALL_MASK
(
core_mask
));
/* set reset state */
return
skl_dsp_core_set_reset_state
(
ctx
);
return
skl_dsp_core_set_reset_state
(
ctx
,
core_mask
);
}
static
int
skl_dsp_start_core
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_start_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
/* unset reset state */
ret
=
skl_dsp_core_unset_reset_state
(
ctx
);
if
(
ret
<
0
)
{
dev_dbg
(
ctx
->
dev
,
"dsp unset reset fails
\n
"
);
ret
=
skl_dsp_core_unset_reset_state
(
ctx
,
core_mask
);
if
(
ret
<
0
)
return
ret
;
}
/* run core */
dev_dbg
(
ctx
->
dev
,
"
run core...
\n
"
);
sst_dsp_shim_
write
_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
)
&
~
SKL_ADSPCS_CSTALL
(
SKL_DSP_CORES_MASK
));
if
(
!
is_skl_dsp_core_enable
(
ctx
))
{
skl_dsp_reset_core
(
ctx
);
dev_err
(
ctx
->
dev
,
"DSP core enable failed
\n
"
);
dev_dbg
(
ctx
->
dev
,
"
unstall/run core: core_mask = %x
\n
"
,
core_mask
);
sst_dsp_shim_
update_bits
_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CSTALL_MASK
(
core_mask
),
0
);
if
(
!
is_skl_dsp_core_enable
(
ctx
,
core_mask
))
{
skl_dsp_reset_core
(
ctx
,
core_mask
);
dev_err
(
ctx
->
dev
,
"DSP start core failed: core_mask %x
\n
"
,
core_mask
);
ret
=
-
EIO
;
}
return
ret
;
}
static
int
skl_dsp_core_power_up
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_core_power_up
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
/* update bits */
sst_dsp_shim_update_bits_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_SPA_MASK
,
SKL_ADSPCS_SPA
(
SKL_DSP_CORES_MASK
));
SKL_ADSPCS_SPA_MASK
(
core_mask
),
SKL_ADSPCS_SPA_MASK
(
core_mask
));
/* poll with timeout to check if operation successful */
ret
=
sst_dsp_register_poll
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CPA_MASK
,
SKL_ADSPCS_CPA
(
SKL_DSP_CORES_MASK
),
SKL_ADSPCS_CPA_MASK
(
core_mask
)
,
SKL_ADSPCS_CPA
_MASK
(
core_mask
),
SKL_DSP_PU_TO
,
"Power up"
);
if
((
sst_dsp_shim_read_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
)
&
SKL_ADSPCS_CPA
(
SKL_DSP_CORES_MASK
))
!=
SKL_ADSPCS_CPA
(
SKL_DSP_CORES_MASK
))
{
dev_err
(
ctx
->
dev
,
"DSP core power up failed
\n
"
);
SKL_ADSPCS_CPA_MASK
(
core_mask
))
!=
SKL_ADSPCS_CPA_MASK
(
core_mask
))
{
dev_err
(
ctx
->
dev
,
"DSP core power up failed: core_mask %x
\n
"
,
core_mask
);
ret
=
-
EIO
;
}
return
ret
;
}
static
int
skl_dsp_core_power_down
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_core_power_down
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
/* update bits */
sst_dsp_shim_update_bits_unlocked
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_SPA_MASK
,
0
);
SKL_ADSPCS_SPA_MASK
(
core_mask
)
,
0
);
/* poll with timeout to check if operation successful */
return
sst_dsp_register_poll
(
ctx
,
SKL_ADSP_REG_ADSPCS
,
SKL_ADSPCS_CPA_MASK
,
SKL_ADSPCS_CPA_MASK
(
core_mask
)
,
0
,
SKL_DSP_PD_TO
,
"Power down"
);
}
int
skl_dsp_enable_core
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_enable_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
/* power up */
ret
=
skl_dsp_core_power_up
(
ctx
);
ret
=
skl_dsp_core_power_up
(
ctx
,
core_mask
);
if
(
ret
<
0
)
{
dev_dbg
(
ctx
->
dev
,
"dsp core power up failed
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp core power up failed: core_mask %x
\n
"
,
core_mask
);
return
ret
;
}
return
skl_dsp_start_core
(
ctx
);
return
skl_dsp_start_core
(
ctx
,
core_mask
);
}
int
skl_dsp_disable_core
(
struct
sst_dsp
*
ctx
)
int
skl_dsp_disable_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_mask
)
{
int
ret
;
ret
=
skl_dsp_reset_core
(
ctx
);
ret
=
skl_dsp_reset_core
(
ctx
,
core_mask
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp core reset failed
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp core reset failed: core_mask %x
\n
"
,
core_mask
);
return
ret
;
}
/* power down core*/
ret
=
skl_dsp_core_power_down
(
ctx
);
ret
=
skl_dsp_core_power_down
(
ctx
,
core_mask
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp core power down failed
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp core power down fail mask %x: %d
\n
"
,
core_mask
,
ret
);
return
ret
;
}
if
(
is_skl_dsp_core_enable
(
ctx
))
{
dev_err
(
ctx
->
dev
,
"DSP core disable failed
\n
"
);
if
(
is_skl_dsp_core_enable
(
ctx
,
core_mask
))
{
dev_err
(
ctx
->
dev
,
"dsp core disable fail mask %x: %d
\n
"
,
core_mask
,
ret
);
ret
=
-
EIO
;
}
...
...
@@ -224,28 +283,25 @@ int skl_dsp_boot(struct sst_dsp *ctx)
{
int
ret
;
if
(
is_skl_dsp_core_enable
(
ctx
))
{
dev_dbg
(
ctx
->
dev
,
"dsp core is already enabled, so reset the dap core
\n
"
);
ret
=
skl_dsp_reset_core
(
ctx
);
if
(
is_skl_dsp_core_enable
(
ctx
,
SKL_DSP_CORE0_MASK
))
{
ret
=
skl_dsp_reset_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp
reset failed
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp
core0 reset fail: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
skl_dsp_start_core
(
ctx
);
ret
=
skl_dsp_start_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp
start failed
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp
core0 start fail: %d
\n
"
,
ret
);
return
ret
;
}
}
else
{
dev_dbg
(
ctx
->
dev
,
"disable and enable to make sure DSP is invalid state
\n
"
);
ret
=
skl_dsp_disable_core
(
ctx
);
ret
=
skl_dsp_disable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"dsp
disable core failes
\n
"
);
dev_err
(
ctx
->
dev
,
"dsp
core0 disable fail: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
skl_dsp_enable_core
(
ctx
);
ret
=
skl_dsp_enable_core
(
ctx
,
SKL_DSP_CORE0_MASK
);
}
return
ret
;
...
...
@@ -281,16 +337,74 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
return
result
;
}
/*
* skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
* within the dapm mutex. Hence no separate lock is used.
*/
int
skl_dsp_get_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
ret
=
0
;
if
(
core_id
>=
skl
->
cores
.
count
)
{
dev_err
(
ctx
->
dev
,
"invalid core id: %d
\n
"
,
core_id
);
return
-
EINVAL
;
}
if
(
skl
->
cores
.
state
[
core_id
]
==
SKL_DSP_RESET
)
{
ret
=
ctx
->
fw_ops
.
set_state_D0
(
ctx
,
core_id
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"unable to get core%d
\n
"
,
core_id
);
return
ret
;
}
}
skl
->
cores
.
usage_count
[
core_id
]
++
;
dev_dbg
(
ctx
->
dev
,
"core id %d state %d usage_count %d
\n
"
,
core_id
,
skl
->
cores
.
state
[
core_id
],
skl
->
cores
.
usage_count
[
core_id
]);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
skl_dsp_get_core
);
int
skl_dsp_put_core
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
int
ret
=
0
;
if
(
core_id
>=
skl
->
cores
.
count
)
{
dev_err
(
ctx
->
dev
,
"invalid core id: %d
\n
"
,
core_id
);
return
-
EINVAL
;
}
if
(
--
skl
->
cores
.
usage_count
[
core_id
]
==
0
)
{
ret
=
ctx
->
fw_ops
.
set_state_D3
(
ctx
,
core_id
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"unable to put core %d: %d
\n
"
,
core_id
,
ret
);
skl
->
cores
.
usage_count
[
core_id
]
++
;
}
}
dev_dbg
(
ctx
->
dev
,
"core id %d state %d usage_count %d
\n
"
,
core_id
,
skl
->
cores
.
state
[
core_id
],
skl
->
cores
.
usage_count
[
core_id
]);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
skl_dsp_put_core
);
int
skl_dsp_wake
(
struct
sst_dsp
*
ctx
)
{
return
ctx
->
fw_ops
.
set_state_D0
(
ctx
);
return
skl_dsp_get_core
(
ctx
,
SKL_DSP_CORE0_ID
);
}
EXPORT_SYMBOL_GPL
(
skl_dsp_wake
);
int
skl_dsp_sleep
(
struct
sst_dsp
*
ctx
)
{
return
ctx
->
fw_ops
.
set_state_D3
(
ctx
);
return
skl_dsp_put_core
(
ctx
,
SKL_DSP_CORE0_ID
);
}
EXPORT_SYMBOL_GPL
(
skl_dsp_sleep
);
...
...
@@ -337,9 +451,7 @@ void skl_dsp_free(struct sst_dsp *dsp)
free_irq
(
dsp
->
irq
,
dsp
);
skl_ipc_op_int_disable
(
dsp
);
skl_ipc_int_disable
(
dsp
);
skl_dsp_disable_core
(
dsp
);
skl_dsp_disable_core
(
dsp
,
SKL_DSP_CORE0_MASK
);
}
EXPORT_SYMBOL_GPL
(
skl_dsp_free
);
...
...
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