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
52708d05
Commit
52708d05
authored
Dec 12, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
parents
14eec477
c1aee1d8
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
750 additions
and
98 deletions
+750
-98
Documentation/ABI/testing/sysfs-platform-sst-atom
Documentation/ABI/testing/sysfs-platform-sst-atom
+17
-0
include/uapi/sound/snd_sst_tokens.h
include/uapi/sound/snd_sst_tokens.h
+7
-1
sound/soc/intel/atom/sst-atom-controls.c
sound/soc/intel/atom/sst-atom-controls.c
+1
-1
sound/soc/intel/atom/sst/sst.c
sound/soc/intel/atom/sst/sst.c
+39
-0
sound/soc/intel/atom/sst/sst.h
sound/soc/intel/atom/sst/sst.h
+1
-0
sound/soc/intel/atom/sst/sst_ipc.c
sound/soc/intel/atom/sst/sst_ipc.c
+11
-0
sound/soc/intel/atom/sst/sst_stream.c
sound/soc/intel/atom/sst/sst_stream.c
+2
-2
sound/soc/intel/baytrail/sst-baytrail-ipc.c
sound/soc/intel/baytrail/sst-baytrail-ipc.c
+1
-2
sound/soc/intel/boards/broadwell.c
sound/soc/intel/boards/broadwell.c
+1
-1
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/boards/bxt_da7219_max98357a.c
+18
-4
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/bytcr_rt5640.c
+59
-5
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/intel/boards/cht_bsw_rt5672.c
+26
-0
sound/soc/intel/boards/mfld_machine.c
sound/soc/intel/boards/mfld_machine.c
+2
-2
sound/soc/intel/common/sst-acpi.h
sound/soc/intel/common/sst-acpi.h
+16
-1
sound/soc/intel/common/sst-ipc.c
sound/soc/intel/common/sst-ipc.c
+46
-39
sound/soc/intel/common/sst-ipc.h
sound/soc/intel/common/sst-ipc.h
+5
-3
sound/soc/intel/common/sst-match-acpi.c
sound/soc/intel/common/sst-match-acpi.c
+57
-0
sound/soc/intel/haswell/sst-haswell-ipc.c
sound/soc/intel/haswell/sst-haswell-ipc.c
+1
-2
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/bxt-sst.c
+145
-0
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-messages.c
+32
-7
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-pcm.c
+26
-2
sound/soc/intel/skylake/skl-sst-cldma.c
sound/soc/intel/skylake/skl-sst-cldma.c
+0
-1
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst-dsp.h
+12
-0
sound/soc/intel/skylake/skl-sst-ipc.c
sound/soc/intel/skylake/skl-sst-ipc.c
+68
-3
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst-ipc.h
+35
-2
sound/soc/intel/skylake/skl-sst-utils.c
sound/soc/intel/skylake/skl-sst-utils.c
+1
-1
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.c
+47
-0
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-topology.h
+11
-17
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.c
+57
-2
sound/soc/intel/skylake/skl.h
sound/soc/intel/skylake/skl.h
+6
-0
No files found.
Documentation/ABI/testing/sysfs-platform-sst-atom
0 → 100644
View file @
52708d05
What: /sys/devices/platform/8086%x:00/firmware_version
Date: November 2016
KernelVersion: 4.10
Contact: "Sebastien Guiriec" <sebastien.guiriec@intel.com>
Description:
LPE Firmware version for SST driver on all atom
plaforms (BYT/CHT/Merrifield/BSW).
If the FW has never been loaded it will display:
"FW not yet loaded"
If FW has been loaded it will display:
"v01.aa.bb.cc"
aa: Major version is reflecting SoC version:
0d: BYT FW
0b: BSW FW
07: Merrifield FW
bb: Minor version
cc: Build version
include/uapi/sound/snd_sst_tokens.h
View file @
52708d05
...
...
@@ -157,6 +157,10 @@
*
* %SKL_TKN_STR_LIB_NAME: Specifies the library name
*
* %SKL_TKN_U32_PMODE: Specifies the power mode for pipe
*
* %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module
*
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*/
...
...
@@ -208,7 +212,9 @@ enum SKL_TKNS {
SKL_TKN_U32_PROC_DOMAIN
,
SKL_TKN_U32_LIB_COUNT
,
SKL_TKN_STR_LIB_NAME
,
SKL_TKN_MAX
=
SKL_TKN_STR_LIB_NAME
,
SKL_TKN_U32_PMODE
,
SKL_TKL_U32_D0I3_CAPS
,
SKL_TKN_MAX
=
SKL_TKL_U32_D0I3_CAPS
,
};
#endif
sound/soc/intel/atom/sst-atom-controls.c
View file @
52708d05
...
...
@@ -937,7 +937,7 @@ int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable)
struct
sst_data
*
drv
=
snd_soc_dai_get_drvdata
(
dai
);
int
ssp_id
;
dev_
info
(
dai
->
dev
,
"Enter: enable=%d port_name=%s
\n
"
,
enable
,
id
);
dev_
dbg
(
dai
->
dev
,
"Enter: enable=%d port_name=%s
\n
"
,
enable
,
id
);
if
(
strcmp
(
id
,
"ssp0-port"
)
==
0
)
ssp_id
=
SSP_MODEM
;
...
...
sound/soc/intel/atom/sst/sst.c
View file @
52708d05
...
...
@@ -27,6 +27,7 @@
#include <linux/pm_qos.h>
#include <linux/async.h>
#include <linux/acpi.h>
#include <linux/sysfs.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <asm/platform_sst_audio.h>
...
...
@@ -242,6 +243,32 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx,
}
EXPORT_SYMBOL_GPL
(
sst_alloc_drv_context
);
static
ssize_t
firmware_version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
intel_sst_drv
*
ctx
=
dev_get_drvdata
(
dev
);
if
(
ctx
->
fw_version
.
type
==
0
&&
ctx
->
fw_version
.
major
==
0
&&
ctx
->
fw_version
.
minor
==
0
&&
ctx
->
fw_version
.
build
==
0
)
return
sprintf
(
buf
,
"FW not yet loaded
\n
"
);
else
return
sprintf
(
buf
,
"v%02x.%02x.%02x.%02x
\n
"
,
ctx
->
fw_version
.
type
,
ctx
->
fw_version
.
major
,
ctx
->
fw_version
.
minor
,
ctx
->
fw_version
.
build
);
}
DEVICE_ATTR_RO
(
firmware_version
);
static
const
struct
attribute
*
sst_fw_version_attrs
[]
=
{
&
dev_attr_firmware_version
.
attr
,
NULL
,
};
static
const
struct
attribute_group
sst_fw_version_attr_group
=
{
.
attrs
=
(
struct
attribute
**
)
sst_fw_version_attrs
,
};
int
sst_context_init
(
struct
intel_sst_drv
*
ctx
)
{
int
ret
=
0
,
i
;
...
...
@@ -315,8 +342,19 @@ int sst_context_init(struct intel_sst_drv *ctx)
dev_err
(
ctx
->
dev
,
"Firmware download failed:%d
\n
"
,
ret
);
goto
do_free_mem
;
}
ret
=
sysfs_create_group
(
&
ctx
->
dev
->
kobj
,
&
sst_fw_version_attr_group
);
if
(
ret
)
{
dev_err
(
ctx
->
dev
,
"Unable to create sysfs
\n
"
);
goto
err_sysfs
;
}
sst_register
(
ctx
->
dev
);
return
0
;
err_sysfs:
sysfs_remove_group
(
&
ctx
->
dev
->
kobj
,
&
sst_fw_version_attr_group
);
do_free_mem:
destroy_workqueue
(
ctx
->
post_msg_wq
);
...
...
@@ -330,6 +368,7 @@ void sst_context_cleanup(struct intel_sst_drv *ctx)
pm_runtime_disable
(
ctx
->
dev
);
sst_unregister
(
ctx
->
dev
);
sst_set_fw_state_locked
(
ctx
,
SST_SHUTDOWN
);
sysfs_remove_group
(
&
ctx
->
dev
->
kobj
,
&
sst_fw_version_attr_group
);
flush_scheduled_work
();
destroy_workqueue
(
ctx
->
post_msg_wq
);
pm_qos_remove_request
(
ctx
->
qos
);
...
...
sound/soc/intel/atom/sst/sst.h
View file @
52708d05
...
...
@@ -436,6 +436,7 @@ struct intel_sst_drv {
*/
char
firmware_name
[
FW_NAME_SIZE
];
struct
snd_sst_fw_version
fw_version
;
struct
sst_fw_save
*
fw_save
;
};
...
...
sound/soc/intel/atom/sst/sst_ipc.c
View file @
52708d05
...
...
@@ -236,6 +236,17 @@ static void process_fw_init(struct intel_sst_drv *sst_drv_ctx,
retval
=
init
->
result
;
goto
ret
;
}
dev_info
(
sst_drv_ctx
->
dev
,
"FW Version %02x.%02x.%02x.%02x
\n
"
,
init
->
fw_version
.
type
,
init
->
fw_version
.
major
,
init
->
fw_version
.
minor
,
init
->
fw_version
.
build
);
dev_dbg
(
sst_drv_ctx
->
dev
,
"Build date %s Time %s
\n
"
,
init
->
build_info
.
date
,
init
->
build_info
.
time
);
/* Save FW version */
sst_drv_ctx
->
fw_version
.
type
=
init
->
fw_version
.
type
;
sst_drv_ctx
->
fw_version
.
major
=
init
->
fw_version
.
major
;
sst_drv_ctx
->
fw_version
.
minor
=
init
->
fw_version
.
minor
;
sst_drv_ctx
->
fw_version
.
build
=
init
->
fw_version
.
build
;
ret:
sst_wake_up_block
(
sst_drv_ctx
,
retval
,
FW_DWNL_ID
,
0
,
NULL
,
0
);
...
...
sound/soc/intel/atom/sst/sst_stream.c
View file @
52708d05
...
...
@@ -104,7 +104,7 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
sst_init_stream
(
&
sst_drv_ctx
->
streams
[
str_id
],
alloc_param
.
codec_type
,
str_id
,
alloc_param
.
operation
,
0
);
dev_
info
(
sst_drv_ctx
->
dev
,
"Alloc for str %d pipe %#x
\n
"
,
dev_
dbg
(
sst_drv_ctx
->
dev
,
"Alloc for str %d pipe %#x
\n
"
,
str_id
,
pipe_id
);
ret
=
sst_prepare_and_post_msg
(
sst_drv_ctx
,
task_id
,
IPC_CMD
,
IPC_IA_ALLOC_STREAM_MRFLD
,
pipe_id
,
sizeof
(
alloc_param
),
...
...
@@ -415,7 +415,7 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
str_info
->
status
=
STREAM_UN_INIT
;
mutex_unlock
(
&
str_info
->
lock
);
dev_
info
(
sst_drv_ctx
->
dev
,
"Free for str %d pipe %#x
\n
"
,
dev_
dbg
(
sst_drv_ctx
->
dev
,
"Free for str %d pipe %#x
\n
"
,
str_id
,
str_info
->
pipe_id
);
retval
=
sst_prepare_and_post_msg
(
sst_drv_ctx
,
str_info
->
task_id
,
IPC_CMD
,
IPC_IA_FREE_STREAM_MRFLD
,
str_info
->
pipe_id
,
0
,
...
...
sound/soc/intel/baytrail/sst-baytrail-ipc.c
View file @
52708d05
...
...
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <asm/div64.h>
...
...
@@ -338,7 +337,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context)
spin_unlock_irqrestore
(
&
sst
->
spinlock
,
flags
);
/* continue to send any remaining messages... */
kthread_queue_work
(
&
ipc
->
kworker
,
&
ipc
->
kwork
);
schedule_work
(
&
ipc
->
kwork
);
return
IRQ_HANDLED
;
}
...
...
sound/soc/intel/boards/broadwell.c
View file @
52708d05
...
...
@@ -126,7 +126,7 @@ static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream,
return
ret
;
}
static
struct
snd_soc_ops
broadwell_rt286_ops
=
{
static
const
struct
snd_soc_ops
broadwell_rt286_ops
=
{
.
hw_params
=
broadwell_rt286_hw_params
,
};
...
...
sound/soc/intel/boards/bxt_da7219_max98357a.c
View file @
52708d05
...
...
@@ -30,6 +30,7 @@
#define BXT_DIALOG_CODEC_DAI "da7219-hifi"
#define BXT_MAXIM_CODEC_DAI "HiFi"
#define DUAL_CHANNEL 2
#define QUAD_CHANNEL 4
static
struct
snd_soc_jack
broxton_headset
;
...
...
@@ -182,6 +183,16 @@ static struct snd_pcm_hw_constraint_list constraints_channels = {
.
mask
=
0
,
};
static
unsigned
int
channels_quad
[]
=
{
QUAD_CHANNEL
,
};
static
struct
snd_pcm_hw_constraint_list
constraints_channels_quad
=
{
.
count
=
ARRAY_SIZE
(
channels_quad
),
.
list
=
channels_quad
,
.
mask
=
0
,
};
static
int
bxt_fe_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
...
...
@@ -258,7 +269,10 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct
snd_interval
*
channels
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
channels
->
min
=
channels
->
max
=
DUAL_CHANNEL
;
if
(
params_channels
(
params
)
==
2
)
channels
->
min
=
channels
->
max
=
2
;
else
channels
->
min
=
channels
->
max
=
4
;
return
0
;
}
...
...
@@ -267,9 +281,9 @@ static int broxton_dmic_startup(struct snd_pcm_substream *substream)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
runtime
->
hw
.
channels_m
ax
=
DUAL
_CHANNEL
;
runtime
->
hw
.
channels_m
in
=
runtime
->
hw
.
channels_max
=
QUAD
_CHANNEL
;
snd_pcm_hw_constraint_list
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
constraints_channels
);
&
constraints_channels
_quad
);
return
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
&
constraints_rates
);
...
...
@@ -348,7 +362,7 @@ static struct snd_soc_dai_link broxton_dais[] = {
.
dynamic
=
1
,
.
ops
=
&
broxton_refcap_ops
,
},
[
BXT_DPCM_AUDIO_DMIC_CP
]
[
BXT_DPCM_AUDIO_DMIC_CP
]
=
{
.
name
=
"Bxt Audio DMIC cap"
,
.
stream_name
=
"dmiccap"
,
...
...
sound/soc/intel/boards/bytcr_rt5640.c
View file @
52708d05
...
...
@@ -57,9 +57,7 @@ struct byt_rt5640_private {
struct
clk
*
mclk
;
};
static
unsigned
long
byt_rt5640_quirk
=
BYT_RT5640_DMIC1_MAP
|
BYT_RT5640_DMIC_EN
|
BYT_RT5640_MCLK_EN
;
static
unsigned
long
byt_rt5640_quirk
=
BYT_RT5640_MCLK_EN
;
static
void
log_quirks
(
struct
device
*
dev
)
{
...
...
@@ -689,6 +687,10 @@ static bool is_valleyview(void)
return
true
;
}
struct
acpi_chan_package
{
/* ACPICA seems to require 64 bit integers */
u64
aif_value
;
/* 1: AIF1, 2: AIF2 */
u64
mclock_value
;
/* usually 25MHz (0x17d7940), ignored */
};
static
int
snd_byt_rt5640_mc_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -698,6 +700,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
int
i
;
int
dai_index
;
struct
byt_rt5640_private
*
priv
;
bool
is_bytcr
=
false
;
priv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
priv
),
GFP_ATOMIC
);
if
(
!
priv
)
...
...
@@ -734,10 +737,61 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
struct
sst_platform_info
*
p_info
=
mach
->
pdata
;
const
struct
sst_res_info
*
res_info
=
p_info
->
res_info
;
/* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */
if
(
res_info
->
acpi_ipc_irq_index
==
0
)
{
if
(
res_info
->
acpi_ipc_irq_index
==
0
)
is_bytcr
=
true
;
}
if
(
is_bytcr
)
{
/*
* Baytrail CR platforms may have CHAN package in BIOS, try
* to find relevant routing quirk based as done on Windows
* platforms. We have to read the information directly from the
* BIOS, at this stage the card is not created and the links
* with the codec driver/pdata are non-existent
*/
struct
acpi_chan_package
chan_package
;
/* format specified: 2 64-bit integers */
struct
acpi_buffer
format
=
{
sizeof
(
"NN"
),
"NN"
};
struct
acpi_buffer
state
=
{
0
,
NULL
};
struct
sst_acpi_package_context
pkg_ctx
;
bool
pkg_found
=
false
;
state
.
length
=
sizeof
(
chan_package
);
state
.
pointer
=
&
chan_package
;
pkg_ctx
.
name
=
"CHAN"
;
pkg_ctx
.
length
=
2
;
pkg_ctx
.
format
=
&
format
;
pkg_ctx
.
state
=
&
state
;
pkg_ctx
.
data_valid
=
false
;
pkg_found
=
sst_acpi_find_package_from_hid
(
mach
->
id
,
&
pkg_ctx
);
if
(
pkg_found
)
{
if
(
chan_package
.
aif_value
==
1
)
{
dev_info
(
&
pdev
->
dev
,
"BIOS Routing: AIF1 connected
\n
"
);
byt_rt5640_quirk
|=
BYT_RT5640_SSP0_AIF1
;
}
else
if
(
chan_package
.
aif_value
==
2
)
{
dev_info
(
&
pdev
->
dev
,
"BIOS Routing: AIF2 connected
\n
"
);
byt_rt5640_quirk
|=
BYT_RT5640_SSP0_AIF2
;
}
else
{
dev_info
(
&
pdev
->
dev
,
"BIOS Routing isn't valid, ignored
\n
"
);
pkg_found
=
false
;
}
}
if
(
!
pkg_found
)
{
/* no BIOS indications, assume SSP0-AIF2 connection */
byt_rt5640_quirk
|=
BYT_RT5640_SSP0_AIF2
;
}
/* change defaults for Baytrail-CR capture */
byt_rt5640_quirk
|=
BYT_RT5640_IN1_MAP
;
byt_rt5640_quirk
|=
BYT_RT5640_DIFF_MIC
;
}
else
{
byt_rt5640_quirk
|=
(
BYT_RT5640_DMIC1_MAP
|
BYT_RT5640_DMIC_EN
);
}
/* check quirks before creating card */
...
...
sound/soc/intel/boards/cht_bsw_rt5672.c
View file @
52708d05
...
...
@@ -25,12 +25,14 @@
#include <sound/jack.h>
#include "../../codecs/rt5670.h"
#include "../atom/sst-atom-controls.h"
#include "../common/sst-acpi.h"
/* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
#define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI "rt5670-aif1"
static
struct
snd_soc_jack
cht_bsw_headset
;
static
char
cht_bsw_codec_name
[
16
];
/* Headset jack detection DAPM pins */
static
struct
snd_soc_jack_pin
cht_bsw_headset_pins
[]
=
{
...
...
@@ -339,9 +341,33 @@ static struct snd_soc_card snd_soc_card_cht = {
.
resume_post
=
cht_resume_post
,
};
#define RT5672_I2C_DEFAULT "i2c-10EC5670:00"
static
int
snd_cht_mc_probe
(
struct
platform_device
*
pdev
)
{
int
ret_val
=
0
;
struct
sst_acpi_mach
*
mach
=
pdev
->
dev
.
platform_data
;
const
char
*
i2c_name
;
int
i
;
strcpy
(
cht_bsw_codec_name
,
RT5672_I2C_DEFAULT
);
/* fixup codec name based on HID */
if
(
mach
)
{
i2c_name
=
sst_acpi_find_name_from_hid
(
mach
->
id
);
if
(
i2c_name
)
{
snprintf
(
cht_bsw_codec_name
,
sizeof
(
cht_bsw_codec_name
),
"i2c-%s"
,
i2c_name
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cht_dailink
);
i
++
)
{
if
(
!
strcmp
(
cht_dailink
[
i
].
codec_name
,
RT5672_I2C_DEFAULT
))
{
cht_dailink
[
i
].
codec_name
=
cht_bsw_codec_name
;
break
;
}
}
}
}
/* register the soc card */
snd_soc_card_cht
.
dev
=
&
pdev
->
dev
;
...
...
sound/soc/intel/boards/mfld_machine.c
View file @
52708d05
...
...
@@ -81,9 +81,9 @@ static struct snd_soc_jack_zone mfld_zones[] = {
};
/* sound card controls */
static
const
char
*
headset_switch_text
[]
=
{
"Earpiece"
,
"Headset"
};
static
const
char
*
const
headset_switch_text
[]
=
{
"Earpiece"
,
"Headset"
};
static
const
char
*
lo_text
[]
=
{
"Vibra"
,
"Headset"
,
"IHF"
,
"None"
};
static
const
char
*
const
lo_text
[]
=
{
"Vibra"
,
"Headset"
,
"IHF"
,
"None"
};
static
const
struct
soc_enum
headset_enum
=
SOC_ENUM_SINGLE_EXT
(
2
,
headset_switch_text
);
...
...
sound/soc/intel/common/sst-acpi.h
View file @
52708d05
...
...
@@ -15,14 +15,29 @@
#include <linux/stddef.h>
#include <linux/acpi.h>
/* translation fron HID to I2C name, needed for DAI codec_name */
struct
sst_acpi_package_context
{
char
*
name
;
/* package name */
int
length
;
/* number of elements */
struct
acpi_buffer
*
format
;
struct
acpi_buffer
*
state
;
bool
data_valid
;
};
#if IS_ENABLED(CONFIG_ACPI)
/* translation fron HID to I2C name, needed for DAI codec_name */
const
char
*
sst_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
]);
bool
sst_acpi_find_package_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
],
struct
sst_acpi_package_context
*
ctx
);
#else
static
inline
const
char
*
sst_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
{
return
NULL
;
}
static
inline
bool
sst_acpi_find_package_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
],
struct
sst_acpi_package_context
*
ctx
)
{
return
false
;
}
#endif
/* acpi match */
...
...
sound/soc/intel/common/sst-ipc.c
View file @
52708d05
...
...
@@ -26,7 +26,6 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <sound/asound.h>
#include "sst-dsp.h"
...
...
@@ -109,10 +108,9 @@ static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
ipc
->
ops
.
tx_data_copy
(
msg
,
tx_data
,
tx_bytes
);
list_add_tail
(
&
msg
->
list
,
&
ipc
->
tx_list
);
schedule_work
(
&
ipc
->
kwork
);
spin_unlock_irqrestore
(
&
ipc
->
dsp
->
spinlock
,
flags
);
kthread_queue_work
(
&
ipc
->
kworker
,
&
ipc
->
kwork
);
if
(
wait
)
return
tx_wait_done
(
ipc
,
msg
,
rx_data
);
else
...
...
@@ -156,42 +154,56 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc)
return
-
ENOMEM
;
}
static
void
ipc_tx_msgs
(
struct
kthread_work
*
work
)
static
void
ipc_tx_msgs
(
struct
work_struct
*
work
)
{
struct
sst_generic_ipc
*
ipc
=
container_of
(
work
,
struct
sst_generic_ipc
,
kwork
);
struct
ipc_message
*
msg
;
unsigned
long
flags
;
spin_lock_irq
save
(
&
ipc
->
dsp
->
spinlock
,
flags
);
spin_lock_irq
(
&
ipc
->
dsp
->
spinlock
);
if
(
list_empty
(
&
ipc
->
tx_list
)
||
ipc
->
pending
)
{
spin_unlock_irqrestore
(
&
ipc
->
dsp
->
spinlock
,
flags
);
return
;
}
/* if the DSP is busy, we will TX messages after IRQ.
* also postpone if we are in the middle of procesing completion irq*/
if
(
ipc
->
ops
.
is_dsp_busy
&&
ipc
->
ops
.
is_dsp_busy
(
ipc
->
dsp
))
{
dev_dbg
(
ipc
->
dev
,
"ipc_tx_msgs dsp busy
\n
"
);
spin_unlock_irqrestore
(
&
ipc
->
dsp
->
spinlock
,
flags
);
return
;
}
while
(
!
list_empty
(
&
ipc
->
tx_list
)
&&
!
ipc
->
pending
)
{
/* if the DSP is busy, we will TX messages after IRQ.
* also postpone if we are in the middle of processing
* completion irq
*/
if
(
ipc
->
ops
.
is_dsp_busy
&&
ipc
->
ops
.
is_dsp_busy
(
ipc
->
dsp
))
{
dev_dbg
(
ipc
->
dev
,
"ipc_tx_msgs dsp busy
\n
"
);
break
;
}
msg
=
list_first_entry
(
&
ipc
->
tx_list
,
struct
ipc_message
,
list
);
list_move
(
&
msg
->
list
,
&
ipc
->
rx_list
);
msg
=
list_first_entry
(
&
ipc
->
tx_list
,
struct
ipc_message
,
list
);
list_move
(
&
msg
->
list
,
&
ipc
->
rx_list
);
if
(
ipc
->
ops
.
tx_msg
!=
NULL
)
ipc
->
ops
.
tx_msg
(
ipc
,
msg
);
if
(
ipc
->
ops
.
tx_msg
!=
NULL
)
ipc
->
ops
.
tx_msg
(
ipc
,
msg
);
}
spin_unlock_irq
restore
(
&
ipc
->
dsp
->
spinlock
,
flags
);
spin_unlock_irq
(
&
ipc
->
dsp
->
spinlock
);
}
int
sst_ipc_tx_message_wait
(
struct
sst_generic_ipc
*
ipc
,
u64
header
,
void
*
tx_data
,
size_t
tx_bytes
,
void
*
rx_data
,
size_t
rx_bytes
)
{
return
ipc_tx_message
(
ipc
,
header
,
tx_data
,
tx_bytes
,
int
ret
;
/*
* DSP maybe in lower power active state, so
* check if the DSP supports DSP lp On method
* if so invoke that before sending IPC
*/
if
(
ipc
->
ops
.
check_dsp_lp_on
)
if
(
ipc
->
ops
.
check_dsp_lp_on
(
ipc
->
dsp
,
true
))
return
-
EIO
;
ret
=
ipc_tx_message
(
ipc
,
header
,
tx_data
,
tx_bytes
,
rx_data
,
rx_bytes
,
1
);
if
(
ipc
->
ops
.
check_dsp_lp_on
)
if
(
ipc
->
ops
.
check_dsp_lp_on
(
ipc
->
dsp
,
false
))
return
-
EIO
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
sst_ipc_tx_message_wait
);
...
...
@@ -203,6 +215,14 @@ int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
}
EXPORT_SYMBOL_GPL
(
sst_ipc_tx_message_nowait
);
int
sst_ipc_tx_message_nopm
(
struct
sst_generic_ipc
*
ipc
,
u64
header
,
void
*
tx_data
,
size_t
tx_bytes
,
void
*
rx_data
,
size_t
rx_bytes
)
{
return
ipc_tx_message
(
ipc
,
header
,
tx_data
,
tx_bytes
,
rx_data
,
rx_bytes
,
1
);
}
EXPORT_SYMBOL_GPL
(
sst_ipc_tx_message_nopm
);
struct
ipc_message
*
sst_ipc_reply_find_msg
(
struct
sst_generic_ipc
*
ipc
,
u64
header
)
{
...
...
@@ -280,19 +300,7 @@ int sst_ipc_init(struct sst_generic_ipc *ipc)
if
(
ret
<
0
)
return
-
ENOMEM
;
/* start the IPC message thread */
kthread_init_worker
(
&
ipc
->
kworker
);
ipc
->
tx_thread
=
kthread_run
(
kthread_worker_fn
,
&
ipc
->
kworker
,
"%s"
,
dev_name
(
ipc
->
dev
));
if
(
IS_ERR
(
ipc
->
tx_thread
))
{
dev_err
(
ipc
->
dev
,
"error: failed to create message TX task
\n
"
);
ret
=
PTR_ERR
(
ipc
->
tx_thread
);
kfree
(
ipc
->
msg
);
return
ret
;
}
kthread_init_work
(
&
ipc
->
kwork
,
ipc_tx_msgs
);
INIT_WORK
(
&
ipc
->
kwork
,
ipc_tx_msgs
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
sst_ipc_init
);
...
...
@@ -301,8 +309,7 @@ void sst_ipc_fini(struct sst_generic_ipc *ipc)
{
int
i
;
if
(
ipc
->
tx_thread
)
kthread_stop
(
ipc
->
tx_thread
);
cancel_work_sync
(
&
ipc
->
kwork
);
if
(
ipc
->
msg
)
{
for
(
i
=
0
;
i
<
IPC_EMPTY_LIST_SIZE
;
i
++
)
{
...
...
sound/soc/intel/common/sst-ipc.h
View file @
52708d05
...
...
@@ -23,7 +23,6 @@
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#define IPC_MAX_MAILBOX_BYTES 256
...
...
@@ -52,6 +51,7 @@ struct sst_plat_ipc_ops {
void
(
*
tx_data_copy
)(
struct
ipc_message
*
,
char
*
,
size_t
);
u64
(
*
reply_msg_match
)(
u64
header
,
u64
*
mask
);
bool
(
*
is_dsp_busy
)(
struct
sst_dsp
*
dsp
);
int
(
*
check_dsp_lp_on
)(
struct
sst_dsp
*
dsp
,
bool
state
);
};
/* SST generic IPC data */
...
...
@@ -65,8 +65,7 @@ struct sst_generic_ipc {
struct
list_head
empty_list
;
wait_queue_head_t
wait_txq
;
struct
task_struct
*
tx_thread
;
struct
kthread_worker
kworker
;
struct
kthread_work
kwork
;
struct
work_struct
kwork
;
bool
pending
;
struct
ipc_message
*
msg
;
int
tx_data_max_size
;
...
...
@@ -81,6 +80,9 @@ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
int
sst_ipc_tx_message_nowait
(
struct
sst_generic_ipc
*
ipc
,
u64
header
,
void
*
tx_data
,
size_t
tx_bytes
);
int
sst_ipc_tx_message_nopm
(
struct
sst_generic_ipc
*
ipc
,
u64
header
,
void
*
tx_data
,
size_t
tx_bytes
,
void
*
rx_data
,
size_t
rx_bytes
);
struct
ipc_message
*
sst_ipc_reply_find_msg
(
struct
sst_generic_ipc
*
ipc
,
u64
header
);
...
...
sound/soc/intel/common/sst-match-acpi.c
View file @
52708d05
...
...
@@ -77,5 +77,62 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
}
EXPORT_SYMBOL_GPL
(
sst_acpi_find_machine
);
static
acpi_status
sst_acpi_find_package
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
ret
)
{
struct
acpi_device
*
adev
;
acpi_status
status
=
AE_OK
;
struct
sst_acpi_package_context
*
pkg_ctx
=
context
;
pkg_ctx
->
data_valid
=
false
;
if
(
acpi_bus_get_device
(
handle
,
&
adev
))
return
AE_OK
;
if
(
adev
->
status
.
present
&&
adev
->
status
.
functional
)
{
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
myobj
=
NULL
;
status
=
acpi_evaluate_object_typed
(
handle
,
pkg_ctx
->
name
,
NULL
,
&
buffer
,
ACPI_TYPE_PACKAGE
);
if
(
ACPI_FAILURE
(
status
))
return
AE_OK
;
myobj
=
buffer
.
pointer
;
if
(
!
myobj
||
myobj
->
package
.
count
!=
pkg_ctx
->
length
)
{
kfree
(
buffer
.
pointer
);
return
AE_OK
;
}
status
=
acpi_extract_package
(
myobj
,
pkg_ctx
->
format
,
pkg_ctx
->
state
);
if
(
ACPI_FAILURE
(
status
))
{
kfree
(
buffer
.
pointer
);
return
AE_OK
;
}
kfree
(
buffer
.
pointer
);
pkg_ctx
->
data_valid
=
true
;
return
AE_CTRL_TERMINATE
;
}
return
AE_OK
;
}
bool
sst_acpi_find_package_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
],
struct
sst_acpi_package_context
*
ctx
)
{
acpi_status
status
;
status
=
acpi_get_devices
(
hid
,
sst_acpi_find_package
,
ctx
,
NULL
);
if
(
ACPI_FAILURE
(
status
)
||
!
ctx
->
data_valid
)
return
false
;
return
true
;
}
EXPORT_SYMBOL_GPL
(
sst_acpi_find_package_from_hid
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_DESCRIPTION
(
"Intel Common ACPI Match module"
);
sound/soc/intel/haswell/sst-haswell-ipc.c
View file @
52708d05
...
...
@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
...
...
@@ -818,7 +817,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context)
spin_unlock_irqrestore
(
&
sst
->
spinlock
,
flags
);
/* continue to send any remaining messages... */
kthread_queue_work
(
&
ipc
->
kworker
,
&
ipc
->
kwork
);
schedule_work
(
&
ipc
->
kwork
);
return
IRQ_HANDLED
;
}
...
...
sound/soc/intel/skylake/bxt-sst.c
View file @
52708d05
...
...
@@ -43,6 +43,9 @@
#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000
/* Delay before scheduling D0i3 entry */
#define BXT_D0I3_DELAY 5000
static
unsigned
int
bxt_get_errorcode
(
struct
sst_dsp
*
ctx
)
{
return
sst_dsp_shim_read
(
ctx
,
BXT_ADSP_ERROR_CODE
);
...
...
@@ -288,6 +291,141 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
return
ret
;
}
/*
* Decide the D0i3 state that can be targeted based on the usecase
* ref counts and DSP state
*
* Decision Matrix: (X= dont care; state = target state)
*
* DSP state != SKL_DSP_RUNNING ; state = no d0i3
*
* DSP state == SKL_DSP_RUNNING , the following matrix applies
* non_d0i3 >0; streaming =X; non_streaming =X; state = no d0i3
* non_d0i3 =X; streaming =0; non_streaming =0; state = no d0i3
* non_d0i3 =0; streaming >0; non_streaming =X; state = streaming d0i3
* non_d0i3 =0; streaming =0; non_streaming =X; state = non-streaming d0i3
*/
static
int
bxt_d0i3_target_state
(
struct
sst_dsp
*
ctx
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
d0i3
;
if
(
skl
->
cores
.
state
[
SKL_DSP_CORE0_ID
]
!=
SKL_DSP_RUNNING
)
return
SKL_DSP_D0I3_NONE
;
if
(
d0i3
->
non_d0i3
)
return
SKL_DSP_D0I3_NONE
;
else
if
(
d0i3
->
streaming
)
return
SKL_DSP_D0I3_STREAMING
;
else
if
(
d0i3
->
non_streaming
)
return
SKL_DSP_D0I3_NON_STREAMING
;
else
return
SKL_DSP_D0I3_NONE
;
}
static
void
bxt_set_dsp_D0i3
(
struct
work_struct
*
work
)
{
int
ret
;
struct
skl_ipc_d0ix_msg
msg
;
struct
skl_sst
*
skl
=
container_of
(
work
,
struct
skl_sst
,
d0i3
.
work
.
work
);
struct
sst_dsp
*
ctx
=
skl
->
dsp
;
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
d0i3
;
int
target_state
;
dev_dbg
(
ctx
->
dev
,
"In %s:
\n
"
,
__func__
);
/* D0i3 entry allowed only if core 0 alone is running */
if
(
skl_dsp_get_enabled_cores
(
ctx
)
!=
SKL_DSP_CORE0_MASK
)
{
dev_warn
(
ctx
->
dev
,
"D0i3 allowed when only core0 running:Exit
\n
"
);
return
;
}
target_state
=
bxt_d0i3_target_state
(
ctx
);
if
(
target_state
==
SKL_DSP_D0I3_NONE
)
return
;
msg
.
instance_id
=
0
;
msg
.
module_id
=
0
;
msg
.
wake
=
1
;
msg
.
streaming
=
0
;
if
(
target_state
==
SKL_DSP_D0I3_STREAMING
)
msg
.
streaming
=
1
;
ret
=
skl_ipc_set_d0ix
(
&
skl
->
ipc
,
&
msg
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to set DSP to D0i3 state
\n
"
);
return
;
}
/* Set Vendor specific register D0I3C.I3 to enable D0i3*/
if
(
skl
->
update_d0i3c
)
skl
->
update_d0i3c
(
skl
->
dev
,
true
);
d0i3
->
state
=
target_state
;
skl
->
cores
.
state
[
SKL_DSP_CORE0_ID
]
=
SKL_DSP_RUNNING_D0I3
;
}
static
int
bxt_schedule_dsp_D0i3
(
struct
sst_dsp
*
ctx
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
d0i3
;
/* Schedule D0i3 only if the usecase ref counts are appropriate */
if
(
bxt_d0i3_target_state
(
ctx
)
!=
SKL_DSP_D0I3_NONE
)
{
dev_dbg
(
ctx
->
dev
,
"%s: Schedule D0i3
\n
"
,
__func__
);
schedule_delayed_work
(
&
d0i3
->
work
,
msecs_to_jiffies
(
BXT_D0I3_DELAY
));
}
return
0
;
}
static
int
bxt_set_dsp_D0i0
(
struct
sst_dsp
*
ctx
)
{
int
ret
;
struct
skl_ipc_d0ix_msg
msg
;
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
dev_dbg
(
ctx
->
dev
,
"In %s:
\n
"
,
__func__
);
/* First Cancel any pending attempt to put DSP to D0i3 */
cancel_delayed_work_sync
(
&
skl
->
d0i3
.
work
);
/* If DSP is currently in D0i3, bring it to D0i0 */
if
(
skl
->
cores
.
state
[
SKL_DSP_CORE0_ID
]
!=
SKL_DSP_RUNNING_D0I3
)
return
0
;
dev_dbg
(
ctx
->
dev
,
"Set DSP to D0i0
\n
"
);
msg
.
instance_id
=
0
;
msg
.
module_id
=
0
;
msg
.
streaming
=
0
;
msg
.
wake
=
0
;
if
(
skl
->
d0i3
.
state
==
SKL_DSP_D0I3_STREAMING
)
msg
.
streaming
=
1
;
/* Clear Vendor specific register D0I3C.I3 to disable D0i3*/
if
(
skl
->
update_d0i3c
)
skl
->
update_d0i3c
(
skl
->
dev
,
false
);
ret
=
skl_ipc_set_d0ix
(
&
skl
->
ipc
,
&
msg
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to set DSP to D0i0
\n
"
);
return
ret
;
}
skl
->
cores
.
state
[
SKL_DSP_CORE0_ID
]
=
SKL_DSP_RUNNING
;
skl
->
d0i3
.
state
=
SKL_DSP_D0I3_NONE
;
return
0
;
}
static
int
bxt_set_dsp_D0
(
struct
sst_dsp
*
ctx
,
unsigned
int
core_id
)
{
struct
skl_sst
*
skl
=
ctx
->
thread_context
;
...
...
@@ -414,6 +552,8 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
static
struct
skl_dsp_fw_ops
bxt_fw_ops
=
{
.
set_state_D0
=
bxt_set_dsp_D0
,
.
set_state_D3
=
bxt_set_dsp_D3
,
.
set_state_D0i3
=
bxt_schedule_dsp_D0i3
,
.
set_state_D0i0
=
bxt_set_dsp_D0i0
,
.
load_fw
=
bxt_load_base_firmware
,
.
get_fw_errcode
=
bxt_get_errorcode
,
.
load_library
=
bxt_load_library
,
...
...
@@ -470,10 +610,15 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if
(
ret
)
return
ret
;
/* set the D0i3 check */
skl
->
ipc
.
ops
.
check_dsp_lp_on
=
skl_ipc_check_D0i0
;
skl
->
cores
.
count
=
2
;
skl
->
boot_complete
=
false
;
init_waitqueue_head
(
&
skl
->
boot_wait
);
skl
->
is_first_boot
=
true
;
INIT_DELAYED_WORK
(
&
skl
->
d0i3
.
work
,
bxt_set_dsp_D0i3
);
skl
->
d0i3
.
state
=
SKL_DSP_D0I3_NONE
;
if
(
dsp
)
*
dsp
=
skl
;
...
...
sound/soc/intel/skylake/skl-messages.c
View file @
52708d05
...
...
@@ -294,6 +294,33 @@ int skl_free_dsp(struct skl *skl)
return
0
;
}
/*
* In the case of "suspend_active" i.e, the Audio IP being active
* during system suspend, immediately excecute any pending D0i3 work
* before suspending. This is needed for the IP to work in low power
* mode during system suspend. In the case of normal suspend, cancel
* any pending D0i3 work.
*/
int
skl_suspend_late_dsp
(
struct
skl
*
skl
)
{
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
struct
delayed_work
*
dwork
;
if
(
!
ctx
)
return
0
;
dwork
=
&
ctx
->
d0i3
.
work
;
if
(
dwork
->
work
.
func
)
{
if
(
skl
->
supend_active
)
flush_delayed_work
(
dwork
);
else
cancel_delayed_work_sync
(
dwork
);
}
return
0
;
}
int
skl_suspend_dsp
(
struct
skl
*
skl
)
{
struct
skl_sst
*
ctx
=
skl
->
skl_sst
;
...
...
@@ -500,16 +527,14 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
int
skl_dsp_set_dma_control
(
struct
skl_sst
*
ctx
,
struct
skl_module_cfg
*
mconfig
)
{
struct
skl_dma_control
*
dma_ctrl
;
struct
skl_i2s_config_blob
config_blob
;
struct
skl_ipc_large_config_msg
msg
=
{
0
};
int
err
=
0
;
/*
* if blob size is same as capablity size, then no dma control
* present so return
* if blob size zero, then return
*/
if
(
mconfig
->
formats_config
.
caps_size
==
sizeof
(
config_blob
)
)
if
(
mconfig
->
formats_config
.
caps_size
==
0
)
return
0
;
msg
.
large_param_id
=
DMA_CONTROL_ID
;
...
...
@@ -523,7 +548,7 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
dma_ctrl
->
node_id
=
skl_get_node_id
(
ctx
,
mconfig
);
/* size in dwords */
dma_ctrl
->
config_length
=
sizeof
(
config_blob
)
/
4
;
dma_ctrl
->
config_length
=
mconfig
->
formats_config
.
caps_size
/
4
;
memcpy
(
dma_ctrl
->
config_data
,
mconfig
->
formats_config
.
caps
,
mconfig
->
formats_config
.
caps_size
);
...
...
@@ -531,7 +556,6 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
err
=
skl_ipc_set_large_config
(
&
ctx
->
ipc
,
&
msg
,
(
u32
*
)
dma_ctrl
);
kfree
(
dma_ctrl
);
return
err
;
}
...
...
@@ -1042,7 +1066,8 @@ int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe)
dev_dbg
(
ctx
->
dev
,
"%s: pipe_id = %d
\n
"
,
__func__
,
pipe
->
ppl_id
);
ret
=
skl_ipc_create_pipeline
(
&
ctx
->
ipc
,
pipe
->
memory_pages
,
pipe
->
pipe_priority
,
pipe
->
ppl_id
);
pipe
->
pipe_priority
,
pipe
->
ppl_id
,
pipe
->
lp_mode
);
if
(
ret
<
0
)
{
dev_err
(
ctx
->
dev
,
"Failed to create pipeline
\n
"
);
return
ret
;
...
...
sound/soc/intel/skylake/skl-pcm.c
View file @
52708d05
...
...
@@ -144,6 +144,8 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
struct
hdac_ext_stream
*
stream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
skl_dma_params
*
dma_params
;
struct
skl
*
skl
=
get_skl_ctx
(
dai
->
dev
);
struct
skl_module_cfg
*
mconfig
;
dev_dbg
(
dai
->
dev
,
"%s: %s
\n
"
,
__func__
,
dai
->
name
);
...
...
@@ -177,6 +179,9 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
skl_set_suspend_active
(
substream
,
dai
,
true
);
snd_pcm_set_sync
(
substream
);
mconfig
=
skl_tplg_fe_get_cpr_module
(
dai
,
substream
->
stream
);
skl_tplg_d0i3_get
(
skl
,
mconfig
->
d0i3_caps
);
return
0
;
}
...
...
@@ -302,6 +307,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
struct
hdac_ext_bus
*
ebus
=
dev_get_drvdata
(
dai
->
dev
);
struct
skl_dma_params
*
dma_params
=
NULL
;
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
struct
skl_module_cfg
*
mconfig
;
dev_dbg
(
dai
->
dev
,
"%s: %s
\n
"
,
__func__
,
dai
->
name
);
...
...
@@ -325,6 +331,9 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
skl
->
skl_sst
->
miscbdcg_disabled
=
false
;
}
mconfig
=
skl_tplg_fe_get_cpr_module
(
dai
,
substream
->
stream
);
skl_tplg_d0i3_put
(
skl
,
mconfig
->
d0i3_caps
);
kfree
(
dma_params
);
}
...
...
@@ -1031,10 +1040,24 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer
(
struct
snd_pcm_substream
*
substream
)
{
struct
hdac_ext_stream
*
hstream
=
get_hdac_ext_stream
(
substream
);
struct
hdac_ext_bus
*
ebus
=
get_bus_ctx
(
substream
);
unsigned
int
pos
;
/* use the position buffer as default */
pos
=
snd_hdac_stream_get_pos_posbuf
(
hdac_stream
(
hstream
));
/*
* Use DPIB for Playback stream as the periodic DMA Position-in-
* Buffer Writes may be scheduled at the same time or later than
* the MSI and does not guarantee to reflect the Position of the
* last buffer that was transferred. Whereas DPIB register in
* HAD space reflects the actual data that is transferred.
* Use the position buffer for capture, as DPIB write gets
* completed earlier than the actual data written to the DDR.
*/
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
pos
=
readl
(
ebus
->
bus
.
remap_addr
+
AZX_REG_VS_SDXDPIB_XBASE
+
(
AZX_REG_VS_SDXDPIB_XINTERVAL
*
hdac_stream
(
hstream
)
->
index
));
else
pos
=
snd_hdac_stream_get_pos_posbuf
(
hdac_stream
(
hstream
));
if
(
pos
>=
hdac_stream
(
hstream
)
->
bufsize
)
pos
=
0
;
...
...
@@ -1197,6 +1220,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
return
ret
;
}
skl_populate_modules
(
skl
);
skl
->
skl_sst
->
update_d0i3c
=
skl_update_d0i3c
;
}
pm_runtime_mark_last_busy
(
platform
->
dev
);
pm_runtime_put_autosuspend
(
platform
->
dev
);
...
...
sound/soc/intel/skylake/skl-sst-cldma.c
View file @
52708d05
...
...
@@ -17,7 +17,6 @@
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
...
...
sound/soc/intel/skylake/skl-sst-dsp.h
View file @
52708d05
...
...
@@ -126,11 +126,21 @@ struct sst_dsp_device;
#define SKL_ADSPCS_CPA_SHIFT 24
#define SKL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT)
/* DSP Core state */
enum
skl_dsp_states
{
SKL_DSP_RUNNING
=
1
,
/* Running in D0i3 state; can be in streaming or non-streaming D0i3 */
SKL_DSP_RUNNING_D0I3
,
/* Running in D0i3 state*/
SKL_DSP_RESET
,
};
/* D0i3 substates */
enum
skl_dsp_d0i3_states
{
SKL_DSP_D0I3_NONE
=
-
1
,
/* No D0i3 */
SKL_DSP_D0I3_NON_STREAMING
=
0
,
SKL_DSP_D0I3_STREAMING
=
1
,
};
struct
skl_dsp_fw_ops
{
int
(
*
load_fw
)(
struct
sst_dsp
*
ctx
);
/* FW module parser/loader */
...
...
@@ -139,6 +149,8 @@ struct skl_dsp_fw_ops {
int
(
*
parse_fw
)(
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
);
int
(
*
set_state_D0i3
)(
struct
sst_dsp
*
ctx
);
int
(
*
set_state_D0i0
)(
struct
sst_dsp
*
ctx
);
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
);
...
...
sound/soc/intel/skylake/skl-sst-ipc.c
View file @
52708d05
...
...
@@ -81,6 +81,11 @@
#define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \
<< IPC_INSTANCE_ID_SHIFT)
#define IPC_PPL_LP_MODE_SHIFT 0
#define IPC_PPL_LP_MODE_MASK 0x1
#define IPC_PPL_LP_MODE(x) (((x) & IPC_PPL_LP_MODE_MASK) \
<< IPC_PPL_LP_MODE_SHIFT)
/* Set pipeline state message */
#define IPC_PPL_STATE_SHIFT 0
#define IPC_PPL_STATE_MASK 0x1F
...
...
@@ -172,6 +177,17 @@
<< IPC_INITIAL_BLOCK_SHIFT)
#define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \
<< IPC_INITIAL_BLOCK_SHIFT)
/* Set D0ix IPC extension register */
#define IPC_D0IX_WAKE_SHIFT 0
#define IPC_D0IX_WAKE_MASK 0x1
#define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \
<< IPC_D0IX_WAKE_SHIFT)
#define IPC_D0IX_STREAMING_SHIFT 1
#define IPC_D0IX_STREAMING_MASK 0x1
#define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \
<< IPC_D0IX_STREAMING_SHIFT)
enum
skl_ipc_msg_target
{
IPC_FW_GEN_MSG
=
0
,
...
...
@@ -258,7 +274,8 @@ enum skl_ipc_module_msg {
IPC_MOD_LARGE_CONFIG_SET
=
4
,
IPC_MOD_BIND
=
5
,
IPC_MOD_UNBIND
=
6
,
IPC_MOD_SET_DX
=
7
IPC_MOD_SET_DX
=
7
,
IPC_MOD_SET_D0IX
=
8
};
static
void
skl_ipc_tx_data_copy
(
struct
ipc_message
*
msg
,
char
*
tx_data
,
...
...
@@ -289,6 +306,23 @@ static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
header
->
primary
|
SKL_ADSP_REG_HIPCI_BUSY
);
}
int
skl_ipc_check_D0i0
(
struct
sst_dsp
*
dsp
,
bool
state
)
{
int
ret
;
/* check D0i3 support */
if
(
!
dsp
->
fw_ops
.
set_state_D0i0
)
return
0
;
/* Attempt D0i0 or D0i3 based on state */
if
(
state
)
ret
=
dsp
->
fw_ops
.
set_state_D0i0
(
dsp
);
else
ret
=
dsp
->
fw_ops
.
set_state_D0i3
(
dsp
);
return
ret
;
}
static
struct
ipc_message
*
skl_ipc_reply_get_msg
(
struct
sst_generic_ipc
*
ipc
,
u64
ipc_header
)
{
...
...
@@ -464,7 +498,7 @@ irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
skl_ipc_int_enable
(
dsp
);
/* continue to send any remaining messages... */
kthread_queue_work
(
&
ipc
->
kworker
,
&
ipc
->
kwork
);
schedule_work
(
&
ipc
->
kwork
);
return
IRQ_HANDLED
;
}
...
...
@@ -547,7 +581,7 @@ void skl_ipc_free(struct sst_generic_ipc *ipc)
}
int
skl_ipc_create_pipeline
(
struct
sst_generic_ipc
*
ipc
,
u16
ppl_mem_size
,
u8
ppl_type
,
u8
instance_id
)
u16
ppl_mem_size
,
u8
ppl_type
,
u8
instance_id
,
u8
lp_mode
)
{
struct
skl_ipc_header
header
=
{
0
};
u64
*
ipc_header
=
(
u64
*
)(
&
header
);
...
...
@@ -560,6 +594,8 @@ int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
header
.
primary
|=
IPC_PPL_TYPE
(
ppl_type
);
header
.
primary
|=
IPC_PPL_MEM_SIZE
(
ppl_mem_size
);
header
.
extension
=
IPC_PPL_LP_MODE
(
lp_mode
);
dev_dbg
(
ipc
->
dev
,
"In %s header=%d
\n
"
,
__func__
,
header
.
primary
);
ret
=
sst_ipc_tx_message_wait
(
ipc
,
*
ipc_header
,
NULL
,
0
,
NULL
,
0
);
if
(
ret
<
0
)
{
...
...
@@ -931,3 +967,32 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
return
ret
;
}
EXPORT_SYMBOL_GPL
(
skl_sst_ipc_load_library
);
int
skl_ipc_set_d0ix
(
struct
sst_generic_ipc
*
ipc
,
struct
skl_ipc_d0ix_msg
*
msg
)
{
struct
skl_ipc_header
header
=
{
0
};
u64
*
ipc_header
=
(
u64
*
)(
&
header
);
int
ret
;
header
.
primary
=
IPC_MSG_TARGET
(
IPC_MOD_MSG
);
header
.
primary
|=
IPC_MSG_DIR
(
IPC_MSG_REQUEST
);
header
.
primary
|=
IPC_GLB_TYPE
(
IPC_MOD_SET_D0IX
);
header
.
primary
|=
IPC_MOD_INSTANCE_ID
(
msg
->
instance_id
);
header
.
primary
|=
IPC_MOD_ID
(
msg
->
module_id
);
header
.
extension
=
IPC_D0IX_WAKE
(
msg
->
wake
);
header
.
extension
|=
IPC_D0IX_STREAMING
(
msg
->
streaming
);
dev_dbg
(
ipc
->
dev
,
"In %s primary=%x ext=%x
\n
"
,
__func__
,
header
.
primary
,
header
.
extension
);
/*
* Use the nopm IPC here as we dont want it checking for D0iX
*/
ret
=
sst_ipc_tx_message_nopm
(
ipc
,
*
ipc_header
,
NULL
,
0
,
NULL
,
0
);
if
(
ret
<
0
)
dev_err
(
ipc
->
dev
,
"ipc: set d0ix failed, err %d
\n
"
,
ret
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
skl_ipc_set_d0ix
);
sound/soc/intel/skylake/skl-sst-ipc.h
View file @
52708d05
...
...
@@ -16,7 +16,6 @@
#ifndef __SKL_IPC_H
#define __SKL_IPC_H
#include <linux/kthread.h>
#include <linux/irqreturn.h>
#include "../common/sst-ipc.h"
...
...
@@ -53,6 +52,23 @@ struct skl_dsp_cores {
int
usage_count
[
SKL_DSP_CORES_MAX
];
};
/**
* skl_d0i3_data: skl D0i3 counters data struct
*
* @streaming: Count of usecases that can attempt streaming D0i3
* @non_streaming: Count of usecases that can attempt non-streaming D0i3
* @non_d0i3: Count of usecases that cannot attempt D0i3
* @state: current state
* @work: D0i3 worker thread
*/
struct
skl_d0i3_data
{
int
streaming
;
int
non_streaming
;
int
non_d0i3
;
enum
skl_dsp_d0i3_states
state
;
struct
delayed_work
work
;
};
struct
skl_sst
{
struct
device
*
dev
;
struct
sst_dsp
*
dsp
;
...
...
@@ -83,6 +99,11 @@ struct skl_sst {
/* tplg manifest */
struct
skl_dfw_manifest
manifest
;
/* Callback to update D0i3C register */
void
(
*
update_d0i3c
)(
struct
device
*
dev
,
bool
enable
);
struct
skl_d0i3_data
d0i3
;
};
struct
skl_ipc_init_instance_msg
{
...
...
@@ -111,6 +132,13 @@ struct skl_ipc_large_config_msg {
u32
param_data_size
;
};
struct
skl_ipc_d0ix_msg
{
u32
module_id
;
u32
instance_id
;
u8
streaming
;
u8
wake
;
};
#define SKL_IPC_BOOT_MSECS 3000
#define SKL_IPC_D3_MASK 0
...
...
@@ -119,7 +147,7 @@ struct skl_ipc_large_config_msg {
irqreturn_t
skl_dsp_irq_thread_handler
(
int
irq
,
void
*
context
);
int
skl_ipc_create_pipeline
(
struct
sst_generic_ipc
*
sst_ipc
,
u16
ppl_mem_size
,
u8
ppl_type
,
u8
instance_id
);
u16
ppl_mem_size
,
u8
ppl_type
,
u8
instance_id
,
u8
lp_mode
);
int
skl_ipc_delete_pipeline
(
struct
sst_generic_ipc
*
sst_ipc
,
u8
instance_id
);
...
...
@@ -155,6 +183,11 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
int
skl_sst_ipc_load_library
(
struct
sst_generic_ipc
*
ipc
,
u8
dma_id
,
u8
table_id
);
int
skl_ipc_set_d0ix
(
struct
sst_generic_ipc
*
ipc
,
struct
skl_ipc_d0ix_msg
*
msg
);
int
skl_ipc_check_D0i0
(
struct
sst_dsp
*
dsp
,
bool
state
);
void
skl_ipc_int_enable
(
struct
sst_dsp
*
dsp
);
void
skl_ipc_op_int_enable
(
struct
sst_dsp
*
ctx
);
void
skl_ipc_op_int_disable
(
struct
sst_dsp
*
ctx
);
...
...
sound/soc/intel/skylake/skl-sst-utils.c
View file @
52708d05
...
...
@@ -179,7 +179,7 @@ static inline int skl_getid_32(struct uuid_module *module, u64 *val,
index
=
ffz
(
mask_val
);
pvt_id
=
index
+
word1_mask
+
word2_mask
;
if
(
pvt_id
<=
(
max_inst
-
1
))
{
*
val
|=
1
<<
(
index
+
word1_mask
);
*
val
|=
1
ULL
<<
(
index
+
word1_mask
);
return
pvt_id
;
}
}
...
...
sound/soc/intel/skylake/skl-topology.c
View file @
52708d05
...
...
@@ -36,6 +36,44 @@
#define SKL_IN_DIR_BIT_MASK BIT(0)
#define SKL_PIN_COUNT_MASK GENMASK(7, 4)
void
skl_tplg_d0i3_get
(
struct
skl
*
skl
,
enum
d0i3_capability
caps
)
{
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
skl_sst
->
d0i3
;
switch
(
caps
)
{
case
SKL_D0I3_NONE
:
d0i3
->
non_d0i3
++
;
break
;
case
SKL_D0I3_STREAMING
:
d0i3
->
streaming
++
;
break
;
case
SKL_D0I3_NON_STREAMING
:
d0i3
->
non_streaming
++
;
break
;
}
}
void
skl_tplg_d0i3_put
(
struct
skl
*
skl
,
enum
d0i3_capability
caps
)
{
struct
skl_d0i3_data
*
d0i3
=
&
skl
->
skl_sst
->
d0i3
;
switch
(
caps
)
{
case
SKL_D0I3_NONE
:
d0i3
->
non_d0i3
--
;
break
;
case
SKL_D0I3_STREAMING
:
d0i3
->
streaming
--
;
break
;
case
SKL_D0I3_NON_STREAMING
:
d0i3
->
non_streaming
--
;
break
;
}
}
/*
* SKL DSP driver modelling uses only few DAPM widgets so for rest we will
* ignore. This helpers checks if the SKL driver handles this widget type
...
...
@@ -1519,6 +1557,10 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev,
pipe
->
memory_pages
=
tkn_val
;
break
;
case
SKL_TKN_U32_PMODE
:
pipe
->
lp_mode
=
tkn_val
;
break
;
default:
dev_err
(
dev
,
"Token not handled %d
\n
"
,
tkn
);
return
-
EINVAL
;
...
...
@@ -1826,6 +1868,10 @@ static int skl_tplg_get_token(struct device *dev,
mconfig
->
converter
=
tkn_elem
->
value
;
break
;
case
SKL_TKL_U32_D0I3_CAPS
:
mconfig
->
d0i3_caps
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_PIPE_ID
:
ret
=
skl_tplg_add_pipe
(
dev
,
mconfig
,
skl
,
tkn_elem
);
...
...
@@ -1841,6 +1887,7 @@ static int skl_tplg_get_token(struct device *dev,
case
SKL_TKN_U32_PIPE_CONN_TYPE
:
case
SKL_TKN_U32_PIPE_PRIORITY
:
case
SKL_TKN_U32_PIPE_MEM_PGS
:
case
SKL_TKN_U32_PMODE
:
if
(
is_pipe_exists
)
{
ret
=
skl_tplg_fill_pipe_tkn
(
dev
,
mconfig
->
pipe
,
tkn_elem
->
token
,
tkn_elem
->
value
);
...
...
sound/soc/intel/skylake/skl-topology.h
View file @
52708d05
...
...
@@ -113,23 +113,6 @@ struct skl_cpr_gtw_cfg {
u32
config_data
[
1
];
}
__packed
;
struct
skl_i2s_config_blob
{
u32
gateway_attrib
;
u32
tdm_ts_group
[
8
];
u32
ssc0
;
u32
ssc1
;
u32
sscto
;
u32
sspsp
;
u32
sstsa
;
u32
ssrsa
;
u32
ssc2
;
u32
sspsp2
;
u32
ssc3
;
u32
ssioc
;
u32
mdivc
;
u32
mdivr
;
}
__packed
;
struct
skl_dma_control
{
u32
node_id
;
u32
config_length
;
...
...
@@ -279,6 +262,7 @@ struct skl_pipe {
u8
pipe_priority
;
u16
conn_type
;
u32
memory_pages
;
u8
lp_mode
;
struct
skl_pipe_params
*
p_params
;
enum
skl_pipe_state
state
;
struct
list_head
w_list
;
...
...
@@ -293,6 +277,12 @@ enum skl_module_state {
SKL_MODULE_UNLOADED
=
4
,
};
enum
d0i3_capability
{
SKL_D0I3_NONE
=
0
,
SKL_D0I3_STREAMING
=
1
,
SKL_D0I3_NON_STREAMING
=
2
,
};
struct
skl_module_cfg
{
u8
guid
[
16
];
struct
skl_module_inst_id
id
;
...
...
@@ -319,6 +309,7 @@ struct skl_module_cfg {
u32
converter
;
u32
vbus_id
;
u32
mem_pages
;
enum
d0i3_capability
d0i3_caps
;
struct
skl_module_pin
*
m_in_pin
;
struct
skl_module_pin
*
m_out_pin
;
enum
skl_module_type
m_type
;
...
...
@@ -361,6 +352,9 @@ struct skl_module_cfg *skl_tplg_fe_get_cpr_module(
int
skl_tplg_update_pipe_params
(
struct
device
*
dev
,
struct
skl_module_cfg
*
mconfig
,
struct
skl_pipe_params
*
params
);
void
skl_tplg_d0i3_get
(
struct
skl
*
skl
,
enum
d0i3_capability
caps
);
void
skl_tplg_d0i3_put
(
struct
skl
*
skl
,
enum
d0i3_capability
caps
);
int
skl_create_pipeline
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
);
int
skl_run_pipe
(
struct
skl_sst
*
ctx
,
struct
skl_pipe
*
pipe
);
...
...
sound/soc/intel/skylake/skl.c
View file @
52708d05
...
...
@@ -26,6 +26,7 @@
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
#include <sound/pcm.h>
#include "../common/sst-acpi.h"
#include <sound/hda_register.h>
...
...
@@ -109,6 +110,52 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
return
ret
;
}
void
skl_update_d0i3c
(
struct
device
*
dev
,
bool
enable
)
{
struct
pci_dev
*
pci
=
to_pci_dev
(
dev
);
struct
hdac_ext_bus
*
ebus
=
pci_get_drvdata
(
pci
);
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
ebus
);
u8
reg
;
int
timeout
=
50
;
reg
=
snd_hdac_chip_readb
(
bus
,
VS_D0I3C
);
/* Do not write to D0I3C until command in progress bit is cleared */
while
((
reg
&
AZX_REG_VS_D0I3C_CIP
)
&&
--
timeout
)
{
udelay
(
10
);
reg
=
snd_hdac_chip_readb
(
bus
,
VS_D0I3C
);
}
/* Highly unlikely. But if it happens, flag error explicitly */
if
(
!
timeout
)
{
dev_err
(
bus
->
dev
,
"Before D0I3C update: D0I3C CIP timeout
\n
"
);
return
;
}
if
(
enable
)
reg
=
reg
|
AZX_REG_VS_D0I3C_I3
;
else
reg
=
reg
&
(
~
AZX_REG_VS_D0I3C_I3
);
snd_hdac_chip_writeb
(
bus
,
VS_D0I3C
,
reg
);
timeout
=
50
;
/* Wait for cmd in progress to be cleared before exiting the function */
reg
=
snd_hdac_chip_readb
(
bus
,
VS_D0I3C
);
while
((
reg
&
AZX_REG_VS_D0I3C_CIP
)
&&
--
timeout
)
{
udelay
(
10
);
reg
=
snd_hdac_chip_readb
(
bus
,
VS_D0I3C
);
}
/* Highly unlikely. But if it happens, flag error explicitly */
if
(
!
timeout
)
{
dev_err
(
bus
->
dev
,
"After D0I3C update: D0I3C CIP timeout
\n
"
);
return
;
}
dev_dbg
(
bus
->
dev
,
"D0I3C register = 0x%x
\n
"
,
snd_hdac_chip_readb
(
bus
,
VS_D0I3C
));
}
/* called from IRQ */
static
void
skl_stream_update
(
struct
hdac_bus
*
bus
,
struct
hdac_stream
*
hstr
)
{
...
...
@@ -181,6 +228,15 @@ static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect)
return
0
;
}
static
int
skl_suspend_late
(
struct
device
*
dev
)
{
struct
pci_dev
*
pci
=
to_pci_dev
(
dev
);
struct
hdac_ext_bus
*
ebus
=
pci_get_drvdata
(
pci
);
struct
skl
*
skl
=
ebus_to_skl
(
ebus
);
return
skl_suspend_late_dsp
(
skl
);
}
#ifdef CONFIG_PM
static
int
_skl_suspend
(
struct
hdac_ext_bus
*
ebus
)
{
...
...
@@ -243,7 +299,6 @@ static int skl_suspend(struct device *dev)
enable_irq_wake
(
bus
->
irq
);
pci_save_state
(
pci
);
pci_disable_device
(
pci
);
}
else
{
ret
=
_skl_suspend
(
ebus
);
if
(
ret
<
0
)
...
...
@@ -286,7 +341,6 @@ static int skl_resume(struct device *dev)
*/
if
(
skl
->
supend_active
)
{
pci_restore_state
(
pci
);
ret
=
pci_enable_device
(
pci
);
snd_hdac_ext_bus_link_power_up_all
(
ebus
);
disable_irq_wake
(
bus
->
irq
);
/*
...
...
@@ -345,6 +399,7 @@ static int skl_runtime_resume(struct device *dev)
static
const
struct
dev_pm_ops
skl_pm
=
{
SET_SYSTEM_SLEEP_PM_OPS
(
skl_suspend
,
skl_resume
)
SET_RUNTIME_PM_OPS
(
skl_runtime_suspend
,
skl_runtime_resume
,
NULL
)
.
suspend_late
=
skl_suspend_late
,
};
/*
...
...
sound/soc/intel/skylake/skl.h
View file @
52708d05
...
...
@@ -52,6 +52,9 @@
#define AZX_PGCTL_LSRMD_MASK (1 << 4)
#define AZX_PCIREG_CGCTL 0x48
#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
/* D0I3C Register fields */
#define AZX_REG_VS_D0I3C_CIP 0x1
/* Command in progress */
#define AZX_REG_VS_D0I3C_I3 0x4
/* D0i3 enable */
struct
skl_dsp_resource
{
u32
max_mcps
;
...
...
@@ -121,8 +124,11 @@ 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_late_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
);
const
struct
skl_dsp_ops
*
skl_get_dsp_ops
(
int
pci_id
);
void
skl_update_d0i3c
(
struct
device
*
dev
,
bool
enable
);
#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