Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
70fff743
Commit
70fff743
authored
Jan 26, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
parents
5b813eca
f7f61e08
Changes
46
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
1696 additions
and
1958 deletions
+1696
-1958
drivers/acpi/utils.c
drivers/acpi/utils.c
+34
-7
drivers/gpio/gpio-merrifield.c
drivers/gpio/gpio-merrifield.c
+10
-1
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+3
-0
include/linux/acpi.h
include/linux/acpi.h
+6
-0
include/sound/hdaudio_ext.h
include/sound/hdaudio_ext.h
+2
-2
include/sound/soc-acpi.h
include/sound/soc-acpi.h
+3
-10
include/uapi/sound/snd_sst_tokens.h
include/uapi/sound/snd_sst_tokens.h
+16
-1
sound/hda/ext/hdac_ext_bus.c
sound/hda/ext/hdac_ext_bus.c
+1
-1
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+0
-4
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+0
-1
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdac_hdmi.c
+175
-181
sound/soc/codecs/sn95031.c
sound/soc/codecs/sn95031.c
+0
-936
sound/soc/codecs/sn95031.h
sound/soc/codecs/sn95031.h
+0
-133
sound/soc/intel/Kconfig
sound/soc/intel/Kconfig
+86
-32
sound/soc/intel/Makefile
sound/soc/intel/Makefile
+1
-1
sound/soc/intel/atom/sst/sst_acpi.c
sound/soc/intel/atom/sst/sst_acpi.c
+3
-0
sound/soc/intel/atom/sst/sst_stream.c
sound/soc/intel/atom/sst/sst_stream.c
+4
-4
sound/soc/intel/boards/Kconfig
sound/soc/intel/boards/Kconfig
+96
-100
sound/soc/intel/boards/bytcht_da7213.c
sound/soc/intel/boards/bytcht_da7213.c
+2
-2
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/bytcht_es8316.c
+25
-1
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/bytcr_rt5640.c
+2
-2
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/bytcr_rt5651.c
+45
-5
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/cht_bsw_rt5645.c
+3
-3
sound/soc/intel/boards/cht_bsw_rt5672.c
sound/soc/intel/boards/cht_bsw_rt5672.c
+2
-2
sound/soc/intel/boards/haswell.c
sound/soc/intel/boards/haswell.c
+1
-1
sound/soc/intel/boards/kbl_rt5663_max98927.c
sound/soc/intel/boards/kbl_rt5663_max98927.c
+95
-2
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+1
-1
sound/soc/intel/boards/mfld_machine.c
sound/soc/intel/boards/mfld_machine.c
+0
-428
sound/soc/intel/common/sst-dsp.c
sound/soc/intel/common/sst-dsp.c
+1
-3
sound/soc/intel/skylake/Makefile
sound/soc/intel/skylake/Makefile
+5
-0
sound/soc/intel/skylake/bxt-sst.c
sound/soc/intel/skylake/bxt-sst.c
+1
-1
sound/soc/intel/skylake/cnl-sst.c
sound/soc/intel/skylake/cnl-sst.c
+1
-1
sound/soc/intel/skylake/skl-i2s.h
sound/soc/intel/skylake/skl-i2s.h
+95
-0
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-messages.c
+23
-0
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl-nhlt.c
+172
-0
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-pcm.c
+12
-2
sound/soc/intel/skylake/skl-ssp-clk.c
sound/soc/intel/skylake/skl-ssp-clk.c
+429
-0
sound/soc/intel/skylake/skl-ssp-clk.h
sound/soc/intel/skylake/skl-ssp-clk.h
+117
-0
sound/soc/intel/skylake/skl-sst-dsp.c
sound/soc/intel/skylake/skl-sst-dsp.c
+10
-4
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst-dsp.h
+4
-0
sound/soc/intel/skylake/skl-sst-utils.c
sound/soc/intel/skylake/skl-sst-utils.c
+4
-2
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-sst.c
+1
-1
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.c
+43
-2
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.c
+132
-18
sound/soc/intel/skylake/skl.h
sound/soc/intel/skylake/skl.h
+28
-0
sound/soc/soc-acpi.c
sound/soc/soc-acpi.c
+2
-63
No files found.
drivers/acpi/utils.c
View file @
70fff743
...
...
@@ -737,16 +737,17 @@ bool acpi_dev_found(const char *hid)
}
EXPORT_SYMBOL
(
acpi_dev_found
);
struct
acpi_dev_present_info
{
struct
acpi_dev_match_info
{
const
char
*
dev_name
;
struct
acpi_device_id
hid
[
2
];
const
char
*
uid
;
s64
hrv
;
};
static
int
acpi_dev_
present
_cb
(
struct
device
*
dev
,
void
*
data
)
static
int
acpi_dev_
match
_cb
(
struct
device
*
dev
,
void
*
data
)
{
struct
acpi_device
*
adev
=
to_acpi_device
(
dev
);
struct
acpi_dev_
present
_info
*
match
=
data
;
struct
acpi_dev_
match
_info
*
match
=
data
;
unsigned
long
long
hrv
;
acpi_status
status
;
...
...
@@ -757,6 +758,8 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
strcmp
(
adev
->
pnp
.
unique_id
,
match
->
uid
)))
return
0
;
match
->
dev_name
=
acpi_dev_name
(
adev
);
if
(
match
->
hrv
==
-
1
)
return
1
;
...
...
@@ -789,20 +792,44 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
*/
bool
acpi_dev_present
(
const
char
*
hid
,
const
char
*
uid
,
s64
hrv
)
{
struct
acpi_dev_
present
_info
match
=
{};
struct
acpi_dev_
match
_info
match
=
{};
struct
device
*
dev
;
strlcpy
(
match
.
hid
[
0
].
id
,
hid
,
sizeof
(
match
.
hid
[
0
].
id
));
match
.
uid
=
uid
;
match
.
hrv
=
hrv
;
dev
=
bus_find_device
(
&
acpi_bus_type
,
NULL
,
&
match
,
acpi_dev_present_cb
);
dev
=
bus_find_device
(
&
acpi_bus_type
,
NULL
,
&
match
,
acpi_dev_match_cb
);
return
!!
dev
;
}
EXPORT_SYMBOL
(
acpi_dev_present
);
/**
* acpi_dev_get_first_match_name - Return name of first match of ACPI device
* @hid: Hardware ID of the device.
* @uid: Unique ID of the device, pass NULL to not check _UID
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
*
* Return device name if a matching device was present
* at the moment of invocation, or NULL otherwise.
*
* See additional information in acpi_dev_present() as well.
*/
const
char
*
acpi_dev_get_first_match_name
(
const
char
*
hid
,
const
char
*
uid
,
s64
hrv
)
{
struct
acpi_dev_match_info
match
=
{};
struct
device
*
dev
;
strlcpy
(
match
.
hid
[
0
].
id
,
hid
,
sizeof
(
match
.
hid
[
0
].
id
));
match
.
uid
=
uid
;
match
.
hrv
=
hrv
;
dev
=
bus_find_device
(
&
acpi_bus_type
,
NULL
,
&
match
,
acpi_dev_match_cb
);
return
dev
?
match
.
dev_name
:
NULL
;
}
EXPORT_SYMBOL
(
acpi_dev_get_first_match_name
);
/*
* acpi_backlight= handling, this is done here rather then in video_detect.c
* because __setup cannot be used in modules.
...
...
drivers/gpio/gpio-merrifield.c
View file @
70fff743
...
...
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
...
...
@@ -380,9 +381,16 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
}
}
static
const
char
*
mrfld_gpio_get_pinctrl_dev_name
(
void
)
{
const
char
*
dev_name
=
acpi_dev_get_first_match_name
(
"INTC1002"
,
NULL
,
-
1
);
return
dev_name
?
dev_name
:
"pinctrl-merrifield"
;
}
static
int
mrfld_gpio_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
{
const
struct
mrfld_gpio_pinrange
*
range
;
const
char
*
pinctrl_dev_name
;
struct
mrfld_gpio
*
priv
;
u32
gpio_base
,
irq_base
;
void
__iomem
*
base
;
...
...
@@ -439,10 +447,11 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
return
retval
;
}
pinctrl_dev_name
=
mrfld_gpio_get_pinctrl_dev_name
();
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mrfld_gpio_ranges
);
i
++
)
{
range
=
&
mrfld_gpio_ranges
[
i
];
retval
=
gpiochip_add_pin_range
(
&
priv
->
chip
,
"pinctrl-merrifield"
,
pinctrl_dev_name
,
range
->
gpio_base
,
range
->
pin_base
,
range
->
npins
);
...
...
include/acpi/acpi_bus.h
View file @
70fff743
...
...
@@ -91,6 +91,9 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
bool
acpi_dev_found
(
const
char
*
hid
);
bool
acpi_dev_present
(
const
char
*
hid
,
const
char
*
uid
,
s64
hrv
);
const
char
*
acpi_dev_get_first_match_name
(
const
char
*
hid
,
const
char
*
uid
,
s64
hrv
);
#ifdef CONFIG_ACPI
#include <linux/proc_fs.h>
...
...
include/linux/acpi.h
View file @
70fff743
...
...
@@ -640,6 +640,12 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
return
false
;
}
static
inline
const
char
*
acpi_dev_get_first_match_name
(
const
char
*
hid
,
const
char
*
uid
,
s64
hrv
)
{
return
NULL
;
}
static
inline
bool
is_acpi_node
(
struct
fwnode_handle
*
fwnode
)
{
return
false
;
...
...
include/sound/hdaudio_ext.h
View file @
70fff743
...
...
@@ -193,7 +193,7 @@ struct hda_dai_map {
* @pvt_data - private data, for asoc contains asoc codec object
*/
struct
hdac_ext_device
{
struct
hdac_device
hd
ac
;
struct
hdac_device
hd
ev
;
struct
hdac_ext_bus
*
ebus
;
/* soc-dai to nid map */
...
...
@@ -213,7 +213,7 @@ struct hdac_ext_dma_params {
u8
stream_tag
;
};
#define to_ehdac_device(dev) (container_of((dev), \
struct hdac_ext_device, hd
ac
))
struct hdac_ext_device, hd
ev
))
/*
* HD-audio codec base driver
*/
...
...
include/sound/soc-acpi.h
View file @
70fff743
...
...
@@ -27,17 +27,13 @@ struct snd_soc_acpi_package_context {
bool
data_valid
;
};
/* codec name is used in DAIs is i2c-<HID>:00 with HID being 8 chars */
#define SND_ACPI_I2C_ID_LEN (4 + ACPI_ID_LEN + 3 + 1)
#if IS_ENABLED(CONFIG_ACPI)
/* translation fron HID to I2C name, needed for DAI codec_name */
const
char
*
snd_soc_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
]);
bool
snd_soc_acpi_find_package_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
],
struct
snd_soc_acpi_package_context
*
ctx
);
#else
static
inline
const
char
*
snd_soc_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
{
return
NULL
;
}
static
inline
bool
snd_soc_acpi_find_package_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
],
struct
snd_soc_acpi_package_context
*
ctx
)
...
...
@@ -50,9 +46,6 @@ snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct
snd_soc_acpi_mach
*
snd_soc_acpi_find_machine
(
struct
snd_soc_acpi_mach
*
machines
);
/* acpi check hid */
bool
snd_soc_acpi_check_hid
(
const
u8
hid
[
ACPI_ID_LEN
]);
/**
* snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are
* related to the hardware, except for the firmware and topology file names.
...
...
include/uapi/sound/snd_sst_tokens.h
View file @
70fff743
...
...
@@ -222,6 +222,17 @@
* %SKL_TKN_MM_U32_NUM_IN_FMT: Number of input formats
* %SKL_TKN_MM_U32_NUM_OUT_FMT: Number of output formats
*
* %SKL_TKN_U32_ASTATE_IDX: Table Index for the A-State entry to be filled
* with kcps and clock source
*
* %SKL_TKN_U32_ASTATE_COUNT: Number of valid entries in A-State table
*
* %SKL_TKN_U32_ASTATE_KCPS: Specifies the core load threshold (in kilo
* cycles per second) below which DSP is clocked
* from source specified by clock source.
*
* %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
*
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*
...
...
@@ -309,7 +320,11 @@ enum SKL_TKNS {
SKL_TKN_MM_U32_NUM_IN_FMT
,
SKL_TKN_MM_U32_NUM_OUT_FMT
,
SKL_TKN_MAX
=
SKL_TKN_MM_U32_NUM_OUT_FMT
,
SKL_TKN_U32_ASTATE_IDX
,
SKL_TKN_U32_ASTATE_COUNT
,
SKL_TKN_U32_ASTATE_KCPS
,
SKL_TKN_U32_ASTATE_CLK_SRC
,
SKL_TKN_MAX
=
SKL_TKN_U32_ASTATE_CLK_SRC
,
};
#endif
sound/hda/ext/hdac_ext_bus.c
View file @
70fff743
...
...
@@ -146,7 +146,7 @@ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr)
edev
=
kzalloc
(
sizeof
(
*
edev
),
GFP_KERNEL
);
if
(
!
edev
)
return
-
ENOMEM
;
hdev
=
&
edev
->
hd
ac
;
hdev
=
&
edev
->
hd
ev
;
edev
->
ebus
=
ebus
;
snprintf
(
name
,
sizeof
(
name
),
"ehdaudio%dD%d"
,
ebus
->
idx
,
addr
);
...
...
sound/soc/codecs/Kconfig
View file @
70fff743
...
...
@@ -133,7 +133,6 @@ config SND_SOC_ALL_CODECS
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SIRF_AUDIO_CODEC
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2518 if I2C
select SND_SOC_SSM2602_SPI if SPI_MASTER
...
...
@@ -818,9 +817,6 @@ config SND_SOC_SIRF_AUDIO_CODEC
tristate "SiRF SoC internal audio codec"
select REGMAP_MMIO
config SND_SOC_SN95031
tristate
config SND_SOC_SPDIF
tristate "S/PDIF CODEC"
...
...
sound/soc/codecs/Makefile
View file @
70fff743
...
...
@@ -140,7 +140,6 @@ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-objs
:=
sigmadsp-regmap.o
snd-soc-si476x-objs
:=
si476x.o
snd-soc-sirf-audio-codec-objs
:=
sirf-audio-codec.o
snd-soc-sn95031-objs
:=
sn95031.o
snd-soc-spdif-tx-objs
:=
spdif_transmitter.o
snd-soc-spdif-rx-objs
:=
spdif_receiver.o
snd-soc-ssm2518-objs
:=
ssm2518.o
...
...
sound/soc/codecs/hdac_hdmi.c
View file @
70fff743
...
...
@@ -136,8 +136,11 @@ struct hdac_hdmi_priv {
struct
mutex
pin_mutex
;
struct
hdac_chmap
chmap
;
struct
hdac_hdmi_drv_data
*
drv_data
;
struct
snd_soc_dai_driver
*
dai_drv
;
};
#define hdev_to_hdmi_priv(_hdev) ((to_ehdac_device(_hdev))->private_data)
static
struct
hdac_hdmi_pcm
*
hdac_hdmi_get_pcm_from_cvt
(
struct
hdac_hdmi_priv
*
hdmi
,
struct
hdac_hdmi_cvt
*
cvt
)
...
...
@@ -169,7 +172,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
* ports.
*/
if
(
pcm
->
jack_event
==
0
)
{
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"jack report for pcm=%d
\n
"
,
pcm
->
pcm_id
);
snd_soc_jack_report
(
pcm
->
jack
,
SND_JACK_AVOUT
,
...
...
@@ -195,18 +198,18 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
/*
* Get the no devices that can be connected to a port on the Pin widget.
*/
static
int
hdac_hdmi_get_port_len
(
struct
hdac_ext_device
*
hdac
,
hda_nid_t
nid
)
static
int
hdac_hdmi_get_port_len
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
nid
)
{
unsigned
int
caps
;
unsigned
int
type
,
param
;
caps
=
get_wcaps
(
&
hdac
->
hdac
,
nid
);
caps
=
get_wcaps
(
&
edev
->
hdev
,
nid
);
type
=
get_wcaps_type
(
caps
);
if
(
!
(
caps
&
AC_WCAP_DIGITAL
)
||
(
type
!=
AC_WID_PIN
))
return
0
;
param
=
snd_hdac_read_parm_uncached
(
&
hdac
->
hdac
,
nid
,
param
=
snd_hdac_read_parm_uncached
(
&
edev
->
hdev
,
nid
,
AC_PAR_DEVLIST_LEN
);
if
(
param
==
-
1
)
return
param
;
...
...
@@ -219,10 +222,10 @@ static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid)
* id selected on the pin. Return 0 means the first port entry
* is selected or MST is not supported.
*/
static
int
hdac_hdmi_port_select_get
(
struct
hdac_ext_device
*
hdac
,
static
int
hdac_hdmi_port_select_get
(
struct
hdac_ext_device
*
edev
,
struct
hdac_hdmi_port
*
port
)
{
return
snd_hdac_codec_read
(
&
hdac
->
hdac
,
port
->
pin
->
nid
,
return
snd_hdac_codec_read
(
&
edev
->
hdev
,
port
->
pin
->
nid
,
0
,
AC_VERB_GET_DEVICE_SEL
,
0
);
}
...
...
@@ -230,7 +233,7 @@ static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac,
* Sets the selected port entry for the configuring Pin widget verb.
* returns error if port set is not equal to port get otherwise success
*/
static
int
hdac_hdmi_port_select_set
(
struct
hdac_ext_device
*
hdac
,
static
int
hdac_hdmi_port_select_set
(
struct
hdac_ext_device
*
edev
,
struct
hdac_hdmi_port
*
port
)
{
int
num_ports
;
...
...
@@ -239,7 +242,7 @@ static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac,
return
0
;
/* AC_PAR_DEVLIST_LEN is 0 based. */
num_ports
=
hdac_hdmi_get_port_len
(
hdac
,
port
->
pin
->
nid
);
num_ports
=
hdac_hdmi_get_port_len
(
edev
,
port
->
pin
->
nid
);
if
(
num_ports
<
0
)
return
-
EIO
;
...
...
@@ -250,13 +253,13 @@ static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac,
if
(
num_ports
+
1
<
port
->
id
)
return
0
;
snd_hdac_codec_write
(
&
hdac
->
hdac
,
port
->
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hdev
,
port
->
pin
->
nid
,
0
,
AC_VERB_SET_DEVICE_SEL
,
port
->
id
);
if
(
port
->
id
!=
hdac_hdmi_port_select_get
(
hdac
,
port
))
if
(
port
->
id
!=
hdac_hdmi_port_select_get
(
edev
,
port
))
return
-
EIO
;
dev_dbg
(
&
hdac
->
hdac
.
dev
,
"Selected the port=%d
\n
"
,
port
->
id
);
dev_dbg
(
&
edev
->
hdev
.
dev
,
"Selected the port=%d
\n
"
,
port
->
id
);
return
0
;
}
...
...
@@ -276,9 +279,9 @@ static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi,
static
inline
struct
hdac_ext_device
*
to_hda_ext_device
(
struct
device
*
dev
)
{
struct
hdac_device
*
hd
ac
=
dev_to_hdac_dev
(
dev
);
struct
hdac_device
*
hd
ev
=
dev_to_hdac_dev
(
dev
);
return
to_ehdac_device
(
hd
ac
);
return
to_ehdac_device
(
hd
ev
);
}
static
unsigned
int
sad_format
(
const
u8
*
sad
)
...
...
@@ -321,14 +324,14 @@ static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
}
static
void
hdac_hdmi_set_dip_index
(
struct
hdac_ext_device
*
hdac
,
hda_nid_t
pin_nid
,
hdac_hdmi_set_dip_index
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
pin_nid
,
int
packet_index
,
int
byte_index
)
{
int
val
;
val
=
(
packet_index
<<
5
)
|
(
byte_index
&
0x1f
);
snd_hdac_codec_write
(
&
hdac
->
hdac
,
pin_nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hdev
,
pin_nid
,
0
,
AC_VERB_SET_HDMI_DIP_INDEX
,
val
);
}
...
...
@@ -344,14 +347,14 @@ struct dp_audio_infoframe {
u8
LFEPBL01_LSV36_DM_INH7
;
};
static
int
hdac_hdmi_setup_audio_infoframe
(
struct
hdac_ext_device
*
hdac
,
static
int
hdac_hdmi_setup_audio_infoframe
(
struct
hdac_ext_device
*
edev
,
struct
hdac_hdmi_pcm
*
pcm
,
struct
hdac_hdmi_port
*
port
)
{
uint8_t
buffer
[
HDMI_INFOFRAME_HEADER_SIZE
+
HDMI_AUDIO_INFOFRAME_SIZE
];
struct
hdmi_audio_infoframe
frame
;
struct
hdac_hdmi_pin
*
pin
=
port
->
pin
;
struct
dp_audio_infoframe
dp_ai
;
struct
hdac_hdmi_priv
*
hdmi
=
hd
ac
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hd
ev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_cvt
*
cvt
=
pcm
->
cvt
;
u8
*
dip
;
int
ret
;
...
...
@@ -360,11 +363,11 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
u8
conn_type
;
int
channels
,
ca
;
ca
=
snd_hdac_channel_allocation
(
&
hdac
->
hdac
,
port
->
eld
.
info
.
spk_alloc
,
ca
=
snd_hdac_channel_allocation
(
&
edev
->
hdev
,
port
->
eld
.
info
.
spk_alloc
,
pcm
->
channels
,
pcm
->
chmap_set
,
true
,
pcm
->
chmap
);
channels
=
snd_hdac_get_active_channels
(
ca
);
hdmi
->
chmap
.
ops
.
set_channel_count
(
&
hdac
->
hdac
,
cvt
->
nid
,
channels
);
hdmi
->
chmap
.
ops
.
set_channel_count
(
&
edev
->
hdev
,
cvt
->
nid
,
channels
);
snd_hdac_setup_channel_mapping
(
&
hdmi
->
chmap
,
pin
->
nid
,
false
,
ca
,
pcm
->
channels
,
pcm
->
chmap
,
pcm
->
chmap_set
);
...
...
@@ -397,32 +400,32 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
break
;
default:
dev_err
(
&
hdac
->
hdac
.
dev
,
"Invalid connection type: %d
\n
"
,
dev_err
(
&
edev
->
hdev
.
dev
,
"Invalid connection type: %d
\n
"
,
conn_type
);
return
-
EIO
;
}
/* stop infoframe transmission */
hdac_hdmi_set_dip_index
(
hdac
,
pin
->
nid
,
0x0
,
0x0
);
snd_hdac_codec_write
(
&
hdac
->
hdac
,
pin
->
nid
,
0
,
hdac_hdmi_set_dip_index
(
edev
,
pin
->
nid
,
0x0
,
0x0
);
snd_hdac_codec_write
(
&
edev
->
hdev
,
pin
->
nid
,
0
,
AC_VERB_SET_HDMI_DIP_XMIT
,
AC_DIPXMIT_DISABLE
);
/* Fill infoframe. Index auto-incremented */
hdac_hdmi_set_dip_index
(
hdac
,
pin
->
nid
,
0x0
,
0x0
);
hdac_hdmi_set_dip_index
(
edev
,
pin
->
nid
,
0x0
,
0x0
);
if
(
conn_type
==
DRM_ELD_CONN_TYPE_HDMI
)
{
for
(
i
=
0
;
i
<
sizeof
(
buffer
);
i
++
)
snd_hdac_codec_write
(
&
hdac
->
hdac
,
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hdev
,
pin
->
nid
,
0
,
AC_VERB_SET_HDMI_DIP_DATA
,
buffer
[
i
]);
}
else
{
for
(
i
=
0
;
i
<
sizeof
(
dp_ai
);
i
++
)
snd_hdac_codec_write
(
&
hdac
->
hdac
,
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hdev
,
pin
->
nid
,
0
,
AC_VERB_SET_HDMI_DIP_DATA
,
dip
[
i
]);
}
/* Start infoframe */
hdac_hdmi_set_dip_index
(
hdac
,
pin
->
nid
,
0x0
,
0x0
);
snd_hdac_codec_write
(
&
hdac
->
hdac
,
pin
->
nid
,
0
,
hdac_hdmi_set_dip_index
(
edev
,
pin
->
nid
,
0x0
,
0x0
);
snd_hdac_codec_write
(
&
edev
->
hdev
,
pin
->
nid
,
0
,
AC_VERB_SET_HDMI_DIP_XMIT
,
AC_DIPXMIT_BEST
);
return
0
;
...
...
@@ -433,11 +436,11 @@ static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
int
slots
,
int
slot_width
)
{
struct
hdac_ext_device
*
edev
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_dai_port_map
*
dai_map
;
struct
hdac_hdmi_pcm
*
pcm
;
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
"%s: strm_tag: %d
\n
"
,
__func__
,
tx_mask
);
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"%s: strm_tag: %d
\n
"
,
__func__
,
tx_mask
);
dai_map
=
&
hdmi
->
dai_map
[
dai
->
id
];
...
...
@@ -452,8 +455,8 @@ static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
static
int
hdac_hdmi_set_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hparams
,
struct
snd_soc_dai
*
dai
)
{
struct
hdac_ext_device
*
hdac
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ac
->
private_data
;
struct
hdac_ext_device
*
edev
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_dai_port_map
*
dai_map
;
struct
hdac_hdmi_port
*
port
;
struct
hdac_hdmi_pcm
*
pcm
;
...
...
@@ -466,7 +469,7 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
return
-
ENODEV
;
if
((
!
port
->
eld
.
monitor_present
)
||
(
!
port
->
eld
.
eld_valid
))
{
dev_err
(
&
hdac
->
hdac
.
dev
,
dev_err
(
&
edev
->
hdev
.
dev
,
"device is not configured for this pin:port%d:%d
\n
"
,
port
->
pin
->
nid
,
port
->
id
);
return
-
ENODEV
;
...
...
@@ -486,28 +489,28 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
return
0
;
}
static
int
hdac_hdmi_query_port_connlist
(
struct
hdac_ext_device
*
hdac
,
static
int
hdac_hdmi_query_port_connlist
(
struct
hdac_ext_device
*
edev
,
struct
hdac_hdmi_pin
*
pin
,
struct
hdac_hdmi_port
*
port
)
{
if
(
!
(
get_wcaps
(
&
hdac
->
hdac
,
pin
->
nid
)
&
AC_WCAP_CONN_LIST
))
{
dev_warn
(
&
hdac
->
hdac
.
dev
,
if
(
!
(
get_wcaps
(
&
edev
->
hdev
,
pin
->
nid
)
&
AC_WCAP_CONN_LIST
))
{
dev_warn
(
&
edev
->
hdev
.
dev
,
"HDMI: pin %d wcaps %#x does not support connection list
\n
"
,
pin
->
nid
,
get_wcaps
(
&
hdac
->
hdac
,
pin
->
nid
));
pin
->
nid
,
get_wcaps
(
&
edev
->
hdev
,
pin
->
nid
));
return
-
EINVAL
;
}
if
(
hdac_hdmi_port_select_set
(
hdac
,
port
)
<
0
)
if
(
hdac_hdmi_port_select_set
(
edev
,
port
)
<
0
)
return
-
EIO
;
port
->
num_mux_nids
=
snd_hdac_get_connections
(
&
hdac
->
hdac
,
pin
->
nid
,
port
->
num_mux_nids
=
snd_hdac_get_connections
(
&
edev
->
hdev
,
pin
->
nid
,
port
->
mux_nids
,
HDA_MAX_CONNECTIONS
);
if
(
port
->
num_mux_nids
==
0
)
dev_warn
(
&
hdac
->
hdac
.
dev
,
dev_warn
(
&
edev
->
hdev
.
dev
,
"No connections found for pin:port %d:%d
\n
"
,
pin
->
nid
,
port
->
id
);
dev_dbg
(
&
hdac
->
hdac
.
dev
,
"num_mux_nids %d for pin:port %d:%d
\n
"
,
dev_dbg
(
&
edev
->
hdev
.
dev
,
"num_mux_nids %d for pin:port %d:%d
\n
"
,
port
->
num_mux_nids
,
pin
->
nid
,
port
->
id
);
return
port
->
num_mux_nids
;
...
...
@@ -565,8 +568,8 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
static
int
hdac_hdmi_pcm_open
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
hdac_ext_device
*
hdac
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ac
->
private_data
;
struct
hdac_ext_device
*
edev
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_dai_port_map
*
dai_map
;
struct
hdac_hdmi_cvt
*
cvt
;
struct
hdac_hdmi_port
*
port
;
...
...
@@ -575,7 +578,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
dai_map
=
&
hdmi
->
dai_map
[
dai
->
id
];
cvt
=
dai_map
->
cvt
;
port
=
hdac_hdmi_get_port_from_cvt
(
hdac
,
hdmi
,
cvt
);
port
=
hdac_hdmi_get_port_from_cvt
(
edev
,
hdmi
,
cvt
);
/*
* To make PA and other userland happy.
...
...
@@ -586,7 +589,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
if
((
!
port
->
eld
.
monitor_present
)
||
(
!
port
->
eld
.
eld_valid
))
{
dev_warn
(
&
hdac
->
hdac
.
dev
,
dev_warn
(
&
edev
->
hdev
.
dev
,
"Failed: present?:%d ELD valid?:%d pin:port: %d:%d
\n
"
,
port
->
eld
.
monitor_present
,
port
->
eld
.
eld_valid
,
port
->
pin
->
nid
,
port
->
id
);
...
...
@@ -608,8 +611,8 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
static
void
hdac_hdmi_pcm_close
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
hdac_ext_device
*
hdac
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ac
->
private_data
;
struct
hdac_ext_device
*
edev
=
snd_soc_dai_get_drvdata
(
dai
);
struct
hdac_hdmi_priv
*
hdmi
=
hd
ev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_dai_port_map
*
dai_map
;
struct
hdac_hdmi_pcm
*
pcm
;
...
...
@@ -630,14 +633,13 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
}
static
int
hdac_hdmi_query_cvt_params
(
struct
hdac_device
*
hd
ac
,
struct
hdac_hdmi_cvt
*
cvt
)
hdac_hdmi_query_cvt_params
(
struct
hdac_device
*
hd
ev
,
struct
hdac_hdmi_cvt
*
cvt
)
{
unsigned
int
chans
;
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
int
err
;
chans
=
get_wcaps
(
hd
ac
,
cvt
->
nid
);
chans
=
get_wcaps
(
hd
ev
,
cvt
->
nid
);
chans
=
get_wcaps_channels
(
chans
);
cvt
->
params
.
channels_min
=
2
;
...
...
@@ -646,12 +648,12 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
if
(
chans
>
hdmi
->
chmap
.
channels_max
)
hdmi
->
chmap
.
channels_max
=
chans
;
err
=
snd_hdac_query_supported_pcm
(
hd
ac
,
cvt
->
nid
,
err
=
snd_hdac_query_supported_pcm
(
hd
ev
,
cvt
->
nid
,
&
cvt
->
params
.
rates
,
&
cvt
->
params
.
formats
,
&
cvt
->
params
.
maxbps
);
if
(
err
<
0
)
dev_err
(
&
hd
ac
->
dev
,
dev_err
(
&
hd
ev
->
dev
,
"Failed to query pcm params for nid %d: %d
\n
"
,
cvt
->
nid
,
err
);
...
...
@@ -696,7 +698,7 @@ static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
static
struct
hdac_hdmi_pcm
*
hdac_hdmi_get_pcm
(
struct
hdac_ext_device
*
edev
,
struct
hdac_hdmi_port
*
port
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
=
NULL
;
struct
hdac_hdmi_port
*
p
;
...
...
@@ -716,9 +718,9 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
static
void
hdac_hdmi_set_power_state
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
nid
,
unsigned
int
pwr_state
)
{
if
(
get_wcaps
(
&
edev
->
hd
ac
,
nid
)
&
AC_WCAP_POWER
)
{
if
(
!
snd_hdac_check_power_state
(
&
edev
->
hd
ac
,
nid
,
pwr_state
))
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
nid
,
0
,
if
(
get_wcaps
(
&
edev
->
hd
ev
,
nid
)
&
AC_WCAP_POWER
)
{
if
(
!
snd_hdac_check_power_state
(
&
edev
->
hd
ev
,
nid
,
pwr_state
))
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
nid
,
0
,
AC_VERB_SET_POWER_STATE
,
pwr_state
);
}
}
...
...
@@ -726,8 +728,8 @@ static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
static
void
hdac_hdmi_set_amp
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
nid
,
int
val
)
{
if
(
get_wcaps
(
&
edev
->
hd
ac
,
nid
)
&
AC_WCAP_OUT_AMP
)
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
nid
,
0
,
if
(
get_wcaps
(
&
edev
->
hd
ev
,
nid
)
&
AC_WCAP_OUT_AMP
)
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
nid
,
0
,
AC_VERB_SET_AMP_GAIN_MUTE
,
val
);
}
...
...
@@ -739,7 +741,7 @@ static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
w
->
dapm
->
dev
);
struct
hdac_hdmi_pcm
*
pcm
;
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
"%s: widget: %s event: %x
\n
"
,
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"%s: widget: %s event: %x
\n
"
,
__func__
,
w
->
name
,
event
);
pcm
=
hdac_hdmi_get_pcm
(
edev
,
port
);
...
...
@@ -755,7 +757,7 @@ static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
hdac_hdmi_set_power_state
(
edev
,
port
->
pin
->
nid
,
AC_PWRST_D0
);
/* Enable out path for this pin widget */
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
port
->
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
port
->
pin
->
nid
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
PIN_OUT
);
hdac_hdmi_set_amp
(
edev
,
port
->
pin
->
nid
,
AMP_OUT_UNMUTE
);
...
...
@@ -766,7 +768,7 @@ static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w,
hdac_hdmi_set_amp
(
edev
,
port
->
pin
->
nid
,
AMP_OUT_MUTE
);
/* Disable out path for this pin widget */
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
port
->
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
port
->
pin
->
nid
,
0
,
AC_VERB_SET_PIN_WIDGET_CONTROL
,
0
);
hdac_hdmi_set_power_state
(
edev
,
port
->
pin
->
nid
,
AC_PWRST_D3
);
...
...
@@ -782,10 +784,10 @@ static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w,
{
struct
hdac_hdmi_cvt
*
cvt
=
w
->
priv
;
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
w
->
dapm
->
dev
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
;
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
"%s: widget: %s event: %x
\n
"
,
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"%s: widget: %s event: %x
\n
"
,
__func__
,
w
->
name
,
event
);
pcm
=
hdac_hdmi_get_pcm_from_cvt
(
hdmi
,
cvt
);
...
...
@@ -797,23 +799,23 @@ static int hdac_hdmi_cvt_output_widget_event(struct snd_soc_dapm_widget *w,
hdac_hdmi_set_power_state
(
edev
,
cvt
->
nid
,
AC_PWRST_D0
);
/* Enable transmission */
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_DIGI_CONVERT_1
,
1
);
/* Category Code (CC) to zero */
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_DIGI_CONVERT_2
,
0
);
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_CHANNEL_STREAMID
,
pcm
->
stream_tag
);
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_STREAM_FORMAT
,
pcm
->
format
);
break
;
case
SND_SOC_DAPM_POST_PMD
:
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_CHANNEL_STREAMID
,
0
);
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
cvt
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
cvt
->
nid
,
0
,
AC_VERB_SET_STREAM_FORMAT
,
0
);
hdac_hdmi_set_power_state
(
edev
,
cvt
->
nid
,
AC_PWRST_D3
);
...
...
@@ -831,7 +833,7 @@ static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w,
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
w
->
dapm
->
dev
);
int
mux_idx
;
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
"%s: widget: %s event: %x
\n
"
,
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"%s: widget: %s event: %x
\n
"
,
__func__
,
w
->
name
,
event
);
if
(
!
kc
)
...
...
@@ -844,7 +846,7 @@ static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w,
return
-
EIO
;
if
(
mux_idx
>
0
)
{
snd_hdac_codec_write
(
&
edev
->
hd
ac
,
port
->
pin
->
nid
,
0
,
snd_hdac_codec_write
(
&
edev
->
hd
ev
,
port
->
pin
->
nid
,
0
,
AC_VERB_SET_CONNECT_SEL
,
(
mux_idx
-
1
));
}
...
...
@@ -864,7 +866,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
struct
hdac_hdmi_port
*
port
=
w
->
priv
;
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dapm
->
dev
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
=
NULL
;
const
char
*
cvt_name
=
e
->
texts
[
ucontrol
->
value
.
enumerated
.
item
[
0
]];
...
...
@@ -922,7 +924,7 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
struct
snd_soc_dapm_widget
*
widget
,
const
char
*
widget_name
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pin
*
pin
=
port
->
pin
;
struct
snd_kcontrol_new
*
kc
;
struct
hdac_hdmi_cvt
*
cvt
;
...
...
@@ -934,17 +936,17 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
int
i
=
0
;
int
num_items
=
hdmi
->
num_cvt
+
1
;
kc
=
devm_kzalloc
(
&
edev
->
hd
ac
.
dev
,
sizeof
(
*
kc
),
GFP_KERNEL
);
kc
=
devm_kzalloc
(
&
edev
->
hd
ev
.
dev
,
sizeof
(
*
kc
),
GFP_KERNEL
);
if
(
!
kc
)
return
-
ENOMEM
;
se
=
devm_kzalloc
(
&
edev
->
hd
ac
.
dev
,
sizeof
(
*
se
),
GFP_KERNEL
);
se
=
devm_kzalloc
(
&
edev
->
hd
ev
.
dev
,
sizeof
(
*
se
),
GFP_KERNEL
);
if
(
!
se
)
return
-
ENOMEM
;
snprintf
(
kc_name
,
NAME_SIZE
,
"Pin %d port %d Input"
,
pin
->
nid
,
port
->
id
);
kc
->
name
=
devm_kstrdup
(
&
edev
->
hd
ac
.
dev
,
kc_name
,
GFP_KERNEL
);
kc
->
name
=
devm_kstrdup
(
&
edev
->
hd
ev
.
dev
,
kc_name
,
GFP_KERNEL
);
if
(
!
kc
->
name
)
return
-
ENOMEM
;
...
...
@@ -962,24 +964,24 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_ext_device *edev,
se
->
mask
=
roundup_pow_of_two
(
se
->
items
)
-
1
;
sprintf
(
mux_items
,
"NONE"
);
items
[
i
]
=
devm_kstrdup
(
&
edev
->
hd
ac
.
dev
,
mux_items
,
GFP_KERNEL
);
items
[
i
]
=
devm_kstrdup
(
&
edev
->
hd
ev
.
dev
,
mux_items
,
GFP_KERNEL
);
if
(
!
items
[
i
])
return
-
ENOMEM
;
list_for_each_entry
(
cvt
,
&
hdmi
->
cvt_list
,
head
)
{
i
++
;
sprintf
(
mux_items
,
"cvt %d"
,
cvt
->
nid
);
items
[
i
]
=
devm_kstrdup
(
&
edev
->
hd
ac
.
dev
,
mux_items
,
GFP_KERNEL
);
items
[
i
]
=
devm_kstrdup
(
&
edev
->
hd
ev
.
dev
,
mux_items
,
GFP_KERNEL
);
if
(
!
items
[
i
])
return
-
ENOMEM
;
}
se
->
texts
=
devm_kmemdup
(
&
edev
->
hd
ac
.
dev
,
items
,
se
->
texts
=
devm_kmemdup
(
&
edev
->
hd
ev
.
dev
,
items
,
(
num_items
*
sizeof
(
char
*
)),
GFP_KERNEL
);
if
(
!
se
->
texts
)
return
-
ENOMEM
;
return
hdac_hdmi_fill_widget_info
(
&
edev
->
hd
ac
.
dev
,
widget
,
return
hdac_hdmi_fill_widget_info
(
&
edev
->
hd
ev
.
dev
,
widget
,
snd_soc_dapm_mux
,
port
,
widget_name
,
NULL
,
kc
,
1
,
hdac_hdmi_pin_mux_widget_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_REG
);
...
...
@@ -990,7 +992,7 @@ static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
struct
snd_soc_dapm_widget
*
widgets
,
struct
snd_soc_dapm_route
*
route
,
int
rindex
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
const
struct
snd_kcontrol_new
*
kc
;
struct
soc_enum
*
se
;
int
mux_index
=
hdmi
->
num_cvt
+
hdmi
->
num_ports
;
...
...
@@ -1033,8 +1035,8 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
struct
snd_soc_dapm_widget
*
widgets
;
struct
snd_soc_dapm_route
*
route
;
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dapm
->
dev
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
snd_soc_dai_driver
*
dai_drv
=
dapm
->
component
->
dai_drv
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
snd_soc_dai_driver
*
dai_drv
=
hdmi
->
dai_drv
;
char
widget_name
[
NAME_SIZE
];
struct
hdac_hdmi_cvt
*
cvt
;
struct
hdac_hdmi_pin
*
pin
;
...
...
@@ -1134,7 +1136,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
static
int
hdac_hdmi_init_dai_map
(
struct
hdac_ext_device
*
edev
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_dai_port_map
*
dai_map
;
struct
hdac_hdmi_cvt
*
cvt
;
int
dai_id
=
0
;
...
...
@@ -1150,7 +1152,7 @@ static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
dai_id
++
;
if
(
dai_id
==
HDA_MAX_CVTS
)
{
dev_warn
(
&
edev
->
hd
ac
.
dev
,
dev_warn
(
&
edev
->
hd
ev
.
dev
,
"Max dais supported: %d
\n
"
,
dai_id
);
break
;
}
...
...
@@ -1161,7 +1163,7 @@ static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
static
int
hdac_hdmi_add_cvt
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
nid
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_cvt
*
cvt
;
char
name
[
NAME_SIZE
];
...
...
@@ -1176,7 +1178,7 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
list_add_tail
(
&
cvt
->
head
,
&
hdmi
->
cvt_list
);
hdmi
->
num_cvt
++
;
return
hdac_hdmi_query_cvt_params
(
&
edev
->
hd
ac
,
cvt
);
return
hdac_hdmi_query_cvt_params
(
&
edev
->
hd
ev
,
cvt
);
}
static
int
hdac_hdmi_parse_eld
(
struct
hdac_ext_device
*
edev
,
...
...
@@ -1188,7 +1190,7 @@ static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
>>
DRM_ELD_VER_SHIFT
;
if
(
ver
!=
ELD_VER_CEA_861D
&&
ver
!=
ELD_VER_PARTIAL
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"HDMI: Unknown ELD version %d
\n
"
,
ver
);
dev_err
(
&
edev
->
hd
ev
.
dev
,
"HDMI: Unknown ELD version %d
\n
"
,
ver
);
return
-
EINVAL
;
}
...
...
@@ -1196,7 +1198,7 @@ static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev,
DRM_ELD_MNL_MASK
)
>>
DRM_ELD_MNL_SHIFT
;
if
(
mnl
>
ELD_MAX_MNL
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"HDMI: MNL Invalid %d
\n
"
,
mnl
);
dev_err
(
&
edev
->
hd
ev
.
dev
,
"HDMI: MNL Invalid %d
\n
"
,
mnl
);
return
-
EINVAL
;
}
...
...
@@ -1209,7 +1211,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
struct
hdac_hdmi_port
*
port
)
{
struct
hdac_ext_device
*
edev
=
pin
->
edev
;
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
;
int
size
=
0
;
int
port_id
=
-
1
;
...
...
@@ -1227,7 +1229,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
if
(
pin
->
mst_capable
)
port_id
=
port
->
id
;
size
=
snd_hdac_acomp_get_eld
(
&
edev
->
hd
ac
,
pin
->
nid
,
port_id
,
size
=
snd_hdac_acomp_get_eld
(
&
edev
->
hd
ev
,
pin
->
nid
,
port_id
,
&
port
->
eld
.
monitor_present
,
port
->
eld
.
eld_buffer
,
ELD_MAX_SIZE
);
...
...
@@ -1250,7 +1252,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
if
(
!
port
->
eld
.
monitor_present
||
!
port
->
eld
.
eld_valid
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"%s: disconnect for pin:port %d:%d
\n
"
,
dev_err
(
&
edev
->
hd
ev
.
dev
,
"%s: disconnect for pin:port %d:%d
\n
"
,
__func__
,
pin
->
nid
,
port
->
id
);
/*
...
...
@@ -1304,7 +1306,7 @@ static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
static
int
hdac_hdmi_add_pin
(
struct
hdac_ext_device
*
edev
,
hda_nid_t
nid
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pin
*
pin
;
int
ret
;
...
...
@@ -1333,40 +1335,38 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
#define INTEL_EN_DP12 0x02
/* enable DP 1.2 features */
#define INTEL_EN_ALL_PIN_CVTS 0x01
/* enable 2nd & 3rd pins and convertors */
static
void
hdac_hdmi_skl_enable_all_pins
(
struct
hdac_device
*
hd
ac
)
static
void
hdac_hdmi_skl_enable_all_pins
(
struct
hdac_device
*
hd
ev
)
{
unsigned
int
vendor_param
;
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
unsigned
int
vendor_nid
=
hdmi
->
drv_data
->
vendor_nid
;
vendor_param
=
snd_hdac_codec_read
(
hd
ac
,
vendor_nid
,
0
,
vendor_param
=
snd_hdac_codec_read
(
hd
ev
,
vendor_nid
,
0
,
INTEL_GET_VENDOR_VERB
,
0
);
if
(
vendor_param
==
-
1
||
vendor_param
&
INTEL_EN_ALL_PIN_CVTS
)
return
;
vendor_param
|=
INTEL_EN_ALL_PIN_CVTS
;
vendor_param
=
snd_hdac_codec_read
(
hd
ac
,
vendor_nid
,
0
,
vendor_param
=
snd_hdac_codec_read
(
hd
ev
,
vendor_nid
,
0
,
INTEL_SET_VENDOR_VERB
,
vendor_param
);
if
(
vendor_param
==
-
1
)
return
;
}
static
void
hdac_hdmi_skl_enable_dp12
(
struct
hdac_device
*
hd
ac
)
static
void
hdac_hdmi_skl_enable_dp12
(
struct
hdac_device
*
hd
ev
)
{
unsigned
int
vendor_param
;
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
unsigned
int
vendor_nid
=
hdmi
->
drv_data
->
vendor_nid
;
vendor_param
=
snd_hdac_codec_read
(
hd
ac
,
vendor_nid
,
0
,
vendor_param
=
snd_hdac_codec_read
(
hd
ev
,
vendor_nid
,
0
,
INTEL_GET_VENDOR_VERB
,
0
);
if
(
vendor_param
==
-
1
||
vendor_param
&
INTEL_EN_DP12
)
return
;
/* enable DP1.2 mode */
vendor_param
|=
INTEL_EN_DP12
;
vendor_param
=
snd_hdac_codec_read
(
hd
ac
,
vendor_nid
,
0
,
vendor_param
=
snd_hdac_codec_read
(
hd
ev
,
vendor_nid
,
0
,
INTEL_SET_VENDOR_VERB
,
vendor_param
);
if
(
vendor_param
==
-
1
)
return
;
...
...
@@ -1384,7 +1384,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
* Each converter can support a stream independently. So a dai is created
* based on the number of converter queried.
*/
static
int
hdac_hdmi_create_dais
(
struct
hdac_device
*
hd
ac
,
static
int
hdac_hdmi_create_dais
(
struct
hdac_device
*
hd
ev
,
struct
snd_soc_dai_driver
**
dais
,
struct
hdac_hdmi_priv
*
hdmi
,
int
num_dais
)
{
...
...
@@ -1397,20 +1397,20 @@ static int hdac_hdmi_create_dais(struct hdac_device *hdac,
u64
formats
;
int
ret
;
hdmi_dais
=
devm_kzalloc
(
&
hd
ac
->
dev
,
hdmi_dais
=
devm_kzalloc
(
&
hd
ev
->
dev
,
(
sizeof
(
*
hdmi_dais
)
*
num_dais
),
GFP_KERNEL
);
if
(
!
hdmi_dais
)
return
-
ENOMEM
;
list_for_each_entry
(
cvt
,
&
hdmi
->
cvt_list
,
head
)
{
ret
=
snd_hdac_query_supported_pcm
(
hd
ac
,
cvt
->
nid
,
ret
=
snd_hdac_query_supported_pcm
(
hd
ev
,
cvt
->
nid
,
&
rates
,
&
formats
,
&
bps
);
if
(
ret
)
return
ret
;
sprintf
(
dai_name
,
"intel-hdmi-hifi%d"
,
i
+
1
);
hdmi_dais
[
i
].
name
=
devm_kstrdup
(
&
hd
ac
->
dev
,
hdmi_dais
[
i
].
name
=
devm_kstrdup
(
&
hd
ev
->
dev
,
dai_name
,
GFP_KERNEL
);
if
(
!
hdmi_dais
[
i
].
name
)
...
...
@@ -1418,7 +1418,7 @@ static int hdac_hdmi_create_dais(struct hdac_device *hdac,
snprintf
(
name
,
sizeof
(
name
),
"hifi%d"
,
i
+
1
);
hdmi_dais
[
i
].
playback
.
stream_name
=
devm_kstrdup
(
&
hd
ac
->
dev
,
name
,
GFP_KERNEL
);
devm_kstrdup
(
&
hd
ev
->
dev
,
name
,
GFP_KERNEL
);
if
(
!
hdmi_dais
[
i
].
playback
.
stream_name
)
return
-
ENOMEM
;
...
...
@@ -1438,6 +1438,7 @@ static int hdac_hdmi_create_dais(struct hdac_device *hdac,
}
*
dais
=
hdmi_dais
;
hdmi
->
dai_drv
=
hdmi_dais
;
return
0
;
}
...
...
@@ -1451,29 +1452,26 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
{
hda_nid_t
nid
;
int
i
,
num_nodes
;
struct
hdac_device
*
hdac
=
&
edev
->
hdac
;
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_cvt
*
temp_cvt
,
*
cvt_next
;
struct
hdac_hdmi_pin
*
temp_pin
,
*
pin_next
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
);
struct
hdac_device
*
hdev
=
&
edev
->
hdev
;
int
ret
;
hdac_hdmi_skl_enable_all_pins
(
hd
ac
);
hdac_hdmi_skl_enable_dp12
(
hd
ac
);
hdac_hdmi_skl_enable_all_pins
(
hd
ev
);
hdac_hdmi_skl_enable_dp12
(
hd
ev
);
num_nodes
=
snd_hdac_get_sub_nodes
(
hd
ac
,
hdac
->
afg
,
&
nid
);
num_nodes
=
snd_hdac_get_sub_nodes
(
hd
ev
,
hdev
->
afg
,
&
nid
);
if
(
!
nid
||
num_nodes
<=
0
)
{
dev_warn
(
&
hd
ac
->
dev
,
"HDMI: failed to get afg sub nodes
\n
"
);
dev_warn
(
&
hd
ev
->
dev
,
"HDMI: failed to get afg sub nodes
\n
"
);
return
-
EINVAL
;
}
hdac
->
num_nodes
=
num_nodes
;
hdac
->
start_nid
=
nid
;
for
(
i
=
0
;
i
<
hdac
->
num_nodes
;
i
++
,
nid
++
)
{
for
(
i
=
0
;
i
<
num_nodes
;
i
++
,
nid
++
)
{
unsigned
int
caps
;
unsigned
int
type
;
caps
=
get_wcaps
(
hd
ac
,
nid
);
caps
=
get_wcaps
(
hd
ev
,
nid
);
type
=
get_wcaps_type
(
caps
);
if
(
!
(
caps
&
AC_WCAP_DIGITAL
))
...
...
@@ -1495,16 +1493,14 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
}
}
hdac
->
end_nid
=
nid
;
if
(
!
hdmi
->
num_pin
||
!
hdmi
->
num_cvt
)
{
ret
=
-
EIO
;
goto
free_widgets
;
}
ret
=
hdac_hdmi_create_dais
(
hd
ac
,
dais
,
hdmi
,
hdmi
->
num_cvt
);
ret
=
hdac_hdmi_create_dais
(
hd
ev
,
dais
,
hdmi
,
hdmi
->
num_cvt
);
if
(
ret
)
{
dev_err
(
&
hd
ac
->
dev
,
"Failed to create dais with err: %d
\n
"
,
dev_err
(
&
hd
ev
->
dev
,
"Failed to create dais with err: %d
\n
"
,
ret
);
goto
free_widgets
;
}
...
...
@@ -1537,7 +1533,7 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
static
void
hdac_hdmi_eld_notify_cb
(
void
*
aptr
,
int
port
,
int
pipe
)
{
struct
hdac_ext_device
*
edev
=
aptr
;
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pin
*
pin
=
NULL
;
struct
hdac_hdmi_port
*
hport
=
NULL
;
struct
snd_soc_codec
*
codec
=
edev
->
scodec
;
...
...
@@ -1546,7 +1542,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
/* Don't know how this mapping is derived */
hda_nid_t
pin_nid
=
port
+
0x04
;
dev_dbg
(
&
edev
->
hd
ac
.
dev
,
"%s: for pin:%d port=%d
\n
"
,
__func__
,
dev_dbg
(
&
edev
->
hd
ev
.
dev
,
"%s: for pin:%d port=%d
\n
"
,
__func__
,
pin_nid
,
pipe
);
/*
...
...
@@ -1559,7 +1555,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
SNDRV_CTL_POWER_D0
)
return
;
if
(
atomic_read
(
&
edev
->
hd
ac
.
in_pm
))
if
(
atomic_read
(
&
edev
->
hd
ev
.
in_pm
))
return
;
list_for_each_entry
(
pin
,
&
hdmi
->
pin_list
,
head
)
{
...
...
@@ -1614,7 +1610,7 @@ static int create_fill_jack_kcontrols(struct snd_soc_card *card,
char
*
name
;
int
i
=
0
,
j
;
struct
snd_soc_codec
*
codec
=
edev
->
scodec
;
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
kc
=
devm_kcalloc
(
codec
->
dev
,
hdmi
->
num_ports
,
sizeof
(
*
kc
),
GFP_KERNEL
);
...
...
@@ -1652,7 +1648,7 @@ int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec,
struct
snd_soc_dapm_context
*
dapm
)
{
struct
hdac_ext_device
*
edev
=
snd_soc_codec_get_drvdata
(
codec
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pin
*
pin
;
struct
snd_soc_dapm_widget
*
widgets
;
struct
snd_soc_dapm_route
*
route
;
...
...
@@ -1728,7 +1724,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
hdac_ext_device
*
edev
=
snd_soc_codec_get_drvdata
(
codec
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
;
struct
snd_pcm
*
snd_pcm
;
int
err
;
...
...
@@ -1750,7 +1746,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
if
(
snd_pcm
)
{
err
=
snd_hdac_add_chmap_ctls
(
snd_pcm
,
device
,
&
hdmi
->
chmap
);
if
(
err
<
0
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
dev_err
(
&
edev
->
hd
ev
.
dev
,
"chmap control add failed with err: %d for pcm: %d
\n
"
,
err
,
device
);
kfree
(
pcm
);
...
...
@@ -1791,7 +1787,7 @@ static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev,
static
int
hdmi_codec_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
hdac_ext_device
*
edev
=
snd_soc_codec_get_drvdata
(
codec
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
snd_soc_dapm_context
*
dapm
=
snd_soc_component_get_dapm
(
&
codec
->
component
);
struct
hdac_ext_link
*
hlink
=
NULL
;
...
...
@@ -1803,9 +1799,9 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
* hold the ref while we probe, also no need to drop the ref on
* exit, we call pm_runtime_suspend() so that will do for us
*/
hlink
=
snd_hdac_ext_bus_get_link
(
edev
->
ebus
,
dev_name
(
&
edev
->
hd
ac
.
dev
));
hlink
=
snd_hdac_ext_bus_get_link
(
edev
->
ebus
,
dev_name
(
&
edev
->
hd
ev
.
dev
));
if
(
!
hlink
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"hdac link not found
\n
"
);
dev_err
(
&
edev
->
hd
ev
.
dev
,
"hdac link not found
\n
"
);
return
-
EIO
;
}
...
...
@@ -1818,7 +1814,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
aops
.
audio_ptr
=
edev
;
ret
=
snd_hdac_i915_register_notifier
(
&
aops
);
if
(
ret
<
0
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"notifier register failed: err: %d
\n
"
,
dev_err
(
&
edev
->
hd
ev
.
dev
,
"notifier register failed: err: %d
\n
"
,
ret
);
return
ret
;
}
...
...
@@ -1831,9 +1827,9 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
* hdac_device core already sets the state to active and calls
* get_noresume. So enable runtime and set the device to suspend.
*/
pm_runtime_enable
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_put
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_suspend
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_enable
(
&
edev
->
hd
ev
.
dev
);
pm_runtime_put
(
&
edev
->
hd
ev
.
dev
);
pm_runtime_suspend
(
&
edev
->
hd
ev
.
dev
);
return
0
;
}
...
...
@@ -1842,7 +1838,7 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
{
struct
hdac_ext_device
*
edev
=
snd_soc_codec_get_drvdata
(
codec
);
pm_runtime_disable
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_disable
(
&
edev
->
hd
ev
.
dev
);
return
0
;
}
...
...
@@ -1850,9 +1846,9 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
static
int
hdmi_codec_prepare
(
struct
device
*
dev
)
{
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dev
);
struct
hdac_device
*
hd
ac
=
&
edev
->
hdac
;
struct
hdac_device
*
hd
ev
=
&
edev
->
hdev
;
pm_runtime_get_sync
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_get_sync
(
&
edev
->
hd
ev
.
dev
);
/*
* Power down afg.
...
...
@@ -1861,7 +1857,7 @@ static int hdmi_codec_prepare(struct device *dev)
* is received. So setting power state is ensured without using loop
* to read the state.
*/
snd_hdac_codec_read
(
hd
ac
,
hdac
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
snd_hdac_codec_read
(
hd
ev
,
hdev
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D3
);
return
0
;
...
...
@@ -1870,15 +1866,15 @@ static int hdmi_codec_prepare(struct device *dev)
static
void
hdmi_codec_complete
(
struct
device
*
dev
)
{
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dev
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_device
*
hd
ac
=
&
edev
->
hdac
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_device
*
hd
ev
=
&
edev
->
hdev
;
/* Power up afg */
snd_hdac_codec_read
(
hd
ac
,
hdac
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
snd_hdac_codec_read
(
hd
ev
,
hdev
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D0
);
hdac_hdmi_skl_enable_all_pins
(
&
edev
->
hd
ac
);
hdac_hdmi_skl_enable_dp12
(
&
edev
->
hd
ac
);
hdac_hdmi_skl_enable_all_pins
(
&
edev
->
hd
ev
);
hdac_hdmi_skl_enable_dp12
(
&
edev
->
hd
ev
);
/*
* As the ELD notify callback request is not entertained while the
...
...
@@ -1888,7 +1884,7 @@ static void hdmi_codec_complete(struct device *dev)
*/
hdac_hdmi_present_sense_all_pins
(
edev
,
hdmi
,
false
);
pm_runtime_put_sync
(
&
edev
->
hd
ac
.
dev
);
pm_runtime_put_sync
(
&
edev
->
hd
ev
.
dev
);
}
#else
#define hdmi_codec_prepare NULL
...
...
@@ -1901,21 +1897,20 @@ static const struct snd_soc_codec_driver hdmi_hda_codec = {
.
idle_bias_off
=
true
,
};
static
void
hdac_hdmi_get_chmap
(
struct
hdac_device
*
hd
ac
,
int
pcm_idx
,
static
void
hdac_hdmi_get_chmap
(
struct
hdac_device
*
hd
ev
,
int
pcm_idx
,
unsigned
char
*
chmap
)
{
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
struct
hdac_hdmi_pcm
*
pcm
=
get_hdmi_pcm_from_id
(
hdmi
,
pcm_idx
);
memcpy
(
chmap
,
pcm
->
chmap
,
ARRAY_SIZE
(
pcm
->
chmap
));
}
static
void
hdac_hdmi_set_chmap
(
struct
hdac_device
*
hd
ac
,
int
pcm_idx
,
static
void
hdac_hdmi_set_chmap
(
struct
hdac_device
*
hd
ev
,
int
pcm_idx
,
unsigned
char
*
chmap
,
int
prepared
)
{
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hd
ac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hd
ev
);
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
)
;
struct
hdac_hdmi_pcm
*
pcm
=
get_hdmi_pcm_from_id
(
hdmi
,
pcm_idx
);
struct
hdac_hdmi_port
*
port
;
...
...
@@ -1934,10 +1929,9 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
mutex_unlock
(
&
pcm
->
lock
);
}
static
bool
is_hdac_hdmi_pcm_attached
(
struct
hdac_device
*
hd
ac
,
int
pcm_idx
)
static
bool
is_hdac_hdmi_pcm_attached
(
struct
hdac_device
*
hd
ev
,
int
pcm_idx
)
{
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
struct
hdac_hdmi_pcm
*
pcm
=
get_hdmi_pcm_from_id
(
hdmi
,
pcm_idx
);
if
(
!
pcm
)
...
...
@@ -1949,10 +1943,9 @@ static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
return
true
;
}
static
int
hdac_hdmi_get_spk_alloc
(
struct
hdac_device
*
hd
ac
,
int
pcm_idx
)
static
int
hdac_hdmi_get_spk_alloc
(
struct
hdac_device
*
hd
ev
,
int
pcm_idx
)
{
struct
hdac_ext_device
*
edev
=
to_ehdac_device
(
hdac
);
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
hdev
);
struct
hdac_hdmi_pcm
*
pcm
=
get_hdmi_pcm_from_id
(
hdmi
,
pcm_idx
);
struct
hdac_hdmi_port
*
port
;
...
...
@@ -1983,30 +1976,30 @@ static struct hdac_hdmi_drv_data intel_drv_data = {
static
int
hdac_hdmi_dev_probe
(
struct
hdac_ext_device
*
edev
)
{
struct
hdac_device
*
codec
=
&
edev
->
hdac
;
struct
hdac_device
*
hdev
=
&
edev
->
hdev
;
struct
hdac_hdmi_priv
*
hdmi_priv
;
struct
snd_soc_dai_driver
*
hdmi_dais
=
NULL
;
struct
hdac_ext_link
*
hlink
=
NULL
;
int
num_dais
=
0
;
int
ret
=
0
;
struct
hdac_driver
*
hdrv
=
drv_to_hdac_driver
(
codec
->
dev
.
driver
);
const
struct
hda_device_id
*
hdac_id
=
hdac_get_device_id
(
codec
,
hdrv
);
struct
hdac_driver
*
hdrv
=
drv_to_hdac_driver
(
hdev
->
dev
.
driver
);
const
struct
hda_device_id
*
hdac_id
=
hdac_get_device_id
(
hdev
,
hdrv
);
/* hold the ref while we probe */
hlink
=
snd_hdac_ext_bus_get_link
(
edev
->
ebus
,
dev_name
(
&
edev
->
hd
ac
.
dev
));
hlink
=
snd_hdac_ext_bus_get_link
(
edev
->
ebus
,
dev_name
(
&
edev
->
hd
ev
.
dev
));
if
(
!
hlink
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
"hdac link not found
\n
"
);
dev_err
(
&
edev
->
hd
ev
.
dev
,
"hdac link not found
\n
"
);
return
-
EIO
;
}
snd_hdac_ext_bus_link_get
(
edev
->
ebus
,
hlink
);
hdmi_priv
=
devm_kzalloc
(
&
codec
->
dev
,
sizeof
(
*
hdmi_priv
),
GFP_KERNEL
);
hdmi_priv
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
*
hdmi_priv
),
GFP_KERNEL
);
if
(
hdmi_priv
==
NULL
)
return
-
ENOMEM
;
edev
->
private_data
=
hdmi_priv
;
snd_hdac_register_chmap_ops
(
codec
,
&
hdmi_priv
->
chmap
);
snd_hdac_register_chmap_ops
(
hdev
,
&
hdmi_priv
->
chmap
);
hdmi_priv
->
chmap
.
ops
.
get_chmap
=
hdac_hdmi_get_chmap
;
hdmi_priv
->
chmap
.
ops
.
set_chmap
=
hdac_hdmi_set_chmap
;
hdmi_priv
->
chmap
.
ops
.
is_pcm_attached
=
is_hdac_hdmi_pcm_attached
;
...
...
@@ -2021,7 +2014,7 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
else
hdmi_priv
->
drv_data
=
&
intel_drv_data
;
dev_set_drvdata
(
&
codec
->
dev
,
edev
);
dev_set_drvdata
(
&
hdev
->
dev
,
edev
);
INIT_LIST_HEAD
(
&
hdmi_priv
->
pin_list
);
INIT_LIST_HEAD
(
&
hdmi_priv
->
cvt_list
);
...
...
@@ -2032,9 +2025,9 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
* Turned off in the runtime_suspend during the first explicit
* pm_runtime_suspend call.
*/
ret
=
snd_hdac_display_power
(
edev
->
hd
ac
.
bus
,
true
);
ret
=
snd_hdac_display_power
(
edev
->
hd
ev
.
bus
,
true
);
if
(
ret
<
0
)
{
dev_err
(
&
edev
->
hd
ac
.
dev
,
dev_err
(
&
edev
->
hd
ev
.
dev
,
"Cannot turn on display power on i915 err: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -2042,13 +2035,14 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
ret
=
hdac_hdmi_parse_and_map_nid
(
edev
,
&
hdmi_dais
,
&
num_dais
);
if
(
ret
<
0
)
{
dev_err
(
&
codec
->
dev
,
dev_err
(
&
hdev
->
dev
,
"Failed in parse and map nid with err: %d
\n
"
,
ret
);
return
ret
;
}
snd_hdac_refresh_widgets
(
hdev
,
true
);
/* ASoC specific initialization */
ret
=
snd_soc_register_codec
(
&
codec
->
dev
,
&
hdmi_hda_codec
,
ret
=
snd_soc_register_codec
(
&
hdev
->
dev
,
&
hdmi_hda_codec
,
hdmi_dais
,
num_dais
);
snd_hdac_ext_bus_link_put
(
edev
->
ebus
,
hlink
);
...
...
@@ -2058,14 +2052,14 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
static
int
hdac_hdmi_dev_remove
(
struct
hdac_ext_device
*
edev
)
{
struct
hdac_hdmi_priv
*
hdmi
=
edev
->
private_data
;
struct
hdac_hdmi_priv
*
hdmi
=
hdev_to_hdmi_priv
(
&
edev
->
hdev
)
;
struct
hdac_hdmi_pin
*
pin
,
*
pin_next
;
struct
hdac_hdmi_cvt
*
cvt
,
*
cvt_next
;
struct
hdac_hdmi_pcm
*
pcm
,
*
pcm_next
;
struct
hdac_hdmi_port
*
port
,
*
port_next
;
int
i
;
snd_soc_unregister_codec
(
&
edev
->
hd
ac
.
dev
);
snd_soc_unregister_codec
(
&
edev
->
hd
ev
.
dev
);
list_for_each_entry_safe
(
pcm
,
pcm_next
,
&
hdmi
->
pcm_list
,
head
)
{
pcm
->
cvt
=
NULL
;
...
...
@@ -2101,8 +2095,8 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
static
int
hdac_hdmi_runtime_suspend
(
struct
device
*
dev
)
{
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dev
);
struct
hdac_device
*
hd
ac
=
&
edev
->
hdac
;
struct
hdac_bus
*
bus
=
hd
ac
->
bus
;
struct
hdac_device
*
hd
ev
=
&
edev
->
hdev
;
struct
hdac_bus
*
bus
=
hd
ev
->
bus
;
struct
hdac_ext_bus
*
ebus
=
hbus_to_ebus
(
bus
);
struct
hdac_ext_link
*
hlink
=
NULL
;
int
err
;
...
...
@@ -2120,7 +2114,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
* is received. So setting power state is ensured without using loop
* to read the state.
*/
snd_hdac_codec_read
(
hd
ac
,
hdac
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
snd_hdac_codec_read
(
hd
ev
,
hdev
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D3
);
err
=
snd_hdac_display_power
(
bus
,
false
);
if
(
err
<
0
)
{
...
...
@@ -2142,8 +2136,8 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
static
int
hdac_hdmi_runtime_resume
(
struct
device
*
dev
)
{
struct
hdac_ext_device
*
edev
=
to_hda_ext_device
(
dev
);
struct
hdac_device
*
hd
ac
=
&
edev
->
hdac
;
struct
hdac_bus
*
bus
=
hd
ac
->
bus
;
struct
hdac_device
*
hd
ev
=
&
edev
->
hdev
;
struct
hdac_bus
*
bus
=
hd
ev
->
bus
;
struct
hdac_ext_bus
*
ebus
=
hbus_to_ebus
(
bus
);
struct
hdac_ext_link
*
hlink
=
NULL
;
int
err
;
...
...
@@ -2168,11 +2162,11 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
return
err
;
}
hdac_hdmi_skl_enable_all_pins
(
&
edev
->
hd
ac
);
hdac_hdmi_skl_enable_dp12
(
&
edev
->
hd
ac
);
hdac_hdmi_skl_enable_all_pins
(
&
edev
->
hd
ev
);
hdac_hdmi_skl_enable_dp12
(
&
edev
->
hd
ev
);
/* Power up afg */
snd_hdac_codec_read
(
hd
ac
,
hdac
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
snd_hdac_codec_read
(
hd
ev
,
hdev
->
afg
,
0
,
AC_VERB_SET_POWER_STATE
,
AC_PWRST_D0
);
return
0
;
...
...
sound/soc/codecs/sn95031.c
deleted
100644 → 0
View file @
5b813eca
/*
* sn95031.c - TI sn95031 Codec driver
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <asm/intel_scu_ipc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/jack.h>
#include "sn95031.h"
#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
#define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
/* adc helper functions */
/* enables mic bias voltage */
static
void
sn95031_enable_mic_bias
(
struct
snd_soc_codec
*
codec
)
{
snd_soc_write
(
codec
,
SN95031_VAUD
,
BIT
(
2
)
|
BIT
(
1
)
|
BIT
(
0
));
snd_soc_update_bits
(
codec
,
SN95031_MICBIAS
,
BIT
(
2
),
BIT
(
2
));
}
/* Enable/Disable the ADC depending on the argument */
static
void
configure_adc
(
struct
snd_soc_codec
*
sn95031_codec
,
int
val
)
{
int
value
=
snd_soc_read
(
sn95031_codec
,
SN95031_ADC1CNTL1
);
if
(
val
)
{
/* Enable and start the ADC */
value
|=
(
SN95031_ADC_ENBL
|
SN95031_ADC_START
);
value
&=
(
~
SN95031_ADC_NO_LOOP
);
}
else
{
/* Just stop the ADC */
value
&=
(
~
SN95031_ADC_START
);
}
snd_soc_write
(
sn95031_codec
,
SN95031_ADC1CNTL1
,
value
);
}
/*
* finds an empty channel for conversion
* If the ADC is not enabled then start using 0th channel
* itself. Otherwise find an empty channel by looking for a
* channel in which the stopbit is set to 1. returns the index
* of the first free channel if succeeds or an error code.
*
* Context: can sleep
*
*/
static
int
find_free_channel
(
struct
snd_soc_codec
*
sn95031_codec
)
{
int
i
,
value
;
/* check whether ADC is enabled */
value
=
snd_soc_read
(
sn95031_codec
,
SN95031_ADC1CNTL1
);
if
((
value
&
SN95031_ADC_ENBL
)
==
0
)
return
0
;
/* ADC is already enabled; Looking for an empty channel */
for
(
i
=
0
;
i
<
SN95031_ADC_CHANLS_MAX
;
i
++
)
{
value
=
snd_soc_read
(
sn95031_codec
,
SN95031_ADC_CHNL_START_ADDR
+
i
);
if
(
value
&
SN95031_STOPBIT_MASK
)
break
;
}
return
(
i
==
SN95031_ADC_CHANLS_MAX
)
?
(
-
EINVAL
)
:
i
;
}
/* Initialize the ADC for reading micbias values. Can sleep. */
static
int
sn95031_initialize_adc
(
struct
snd_soc_codec
*
sn95031_codec
)
{
int
base_addr
,
chnl_addr
;
int
value
;
int
channel_index
;
/* Index of the first channel in which the stop bit is set */
channel_index
=
find_free_channel
(
sn95031_codec
);
if
(
channel_index
<
0
)
{
pr_err
(
"No free ADC channels"
);
return
channel_index
;
}
base_addr
=
SN95031_ADC_CHNL_START_ADDR
+
channel_index
;
if
(
!
(
channel_index
==
0
||
channel_index
==
SN95031_ADC_LOOP_MAX
))
{
/* Reset stop bit for channels other than 0 and 12 */
value
=
snd_soc_read
(
sn95031_codec
,
base_addr
);
/* Set the stop bit to zero */
snd_soc_write
(
sn95031_codec
,
base_addr
,
value
&
0xEF
);
/* Index of the first free channel */
base_addr
++
;
channel_index
++
;
}
/* Since this is the last channel, set the stop bit
to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
snd_soc_write
(
sn95031_codec
,
base_addr
,
SN95031_AUDIO_DETECT_CODE
|
0x10
);
chnl_addr
=
SN95031_ADC_DATA_START_ADDR
+
2
*
channel_index
;
pr_debug
(
"mid_initialize : %x"
,
chnl_addr
);
configure_adc
(
sn95031_codec
,
1
);
return
chnl_addr
;
}
/* reads the ADC registers and gets the mic bias value in mV. */
static
unsigned
int
sn95031_get_mic_bias
(
struct
snd_soc_codec
*
codec
)
{
u16
adc_adr
=
sn95031_initialize_adc
(
codec
);
u16
adc_val1
,
adc_val2
;
unsigned
int
mic_bias
;
sn95031_enable_mic_bias
(
codec
);
/* Enable the sound card for conversion before reading */
snd_soc_write
(
codec
,
SN95031_ADC1CNTL3
,
0x05
);
/* Re-toggle the RRDATARD bit */
snd_soc_write
(
codec
,
SN95031_ADC1CNTL3
,
0x04
);
/* Read the higher bits of data */
msleep
(
1000
);
adc_val1
=
snd_soc_read
(
codec
,
adc_adr
);
adc_adr
++
;
adc_val2
=
snd_soc_read
(
codec
,
adc_adr
);
/* Adding lower two bits to the higher bits */
mic_bias
=
(
adc_val1
<<
2
)
+
(
adc_val2
&
3
);
mic_bias
=
(
mic_bias
*
SN95031_ADC_ONE_LSB_MULTIPLIER
)
/
1000
;
pr_debug
(
"mic bias = %dmV
\n
"
,
mic_bias
);
return
mic_bias
;
}
/*end - adc helper functions */
static
int
sn95031_read
(
void
*
ctx
,
unsigned
int
reg
,
unsigned
int
*
val
)
{
u8
value
=
0
;
int
ret
;
ret
=
intel_scu_ipc_ioread8
(
reg
,
&
value
);
if
(
ret
==
0
)
*
val
=
value
;
return
ret
;
}
static
int
sn95031_write
(
void
*
ctx
,
unsigned
int
reg
,
unsigned
int
value
)
{
return
intel_scu_ipc_iowrite8
(
reg
,
value
);
}
static
const
struct
regmap_config
sn95031_regmap
=
{
.
reg_read
=
sn95031_read
,
.
reg_write
=
sn95031_write
,
};
static
int
sn95031_set_vaud_bias
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
break
;
case
SND_SOC_BIAS_PREPARE
:
if
(
snd_soc_codec_get_bias_level
(
codec
)
==
SND_SOC_BIAS_STANDBY
)
{
pr_debug
(
"vaud_bias powering up pll
\n
"
);
/* power up the pll */
snd_soc_write
(
codec
,
SN95031_AUDPLLCTRL
,
BIT
(
5
));
/* enable pcm 2 */
snd_soc_update_bits
(
codec
,
SN95031_PCM2C2
,
BIT
(
0
),
BIT
(
0
));
}
break
;
case
SND_SOC_BIAS_STANDBY
:
switch
(
snd_soc_codec_get_bias_level
(
codec
))
{
case
SND_SOC_BIAS_OFF
:
pr_debug
(
"vaud_bias power up rail
\n
"
);
/* power up the rail */
snd_soc_write
(
codec
,
SN95031_VAUD
,
BIT
(
2
)
|
BIT
(
1
)
|
BIT
(
0
));
msleep
(
1
);
break
;
case
SND_SOC_BIAS_PREPARE
:
/* turn off pcm */
pr_debug
(
"vaud_bias power dn pcm
\n
"
);
snd_soc_update_bits
(
codec
,
SN95031_PCM2C2
,
BIT
(
0
),
0
);
snd_soc_write
(
codec
,
SN95031_AUDPLLCTRL
,
0
);
break
;
default:
break
;
}
break
;
case
SND_SOC_BIAS_OFF
:
pr_debug
(
"vaud_bias _OFF doing rail shutdown
\n
"
);
snd_soc_write
(
codec
,
SN95031_VAUD
,
BIT
(
3
));
break
;
}
return
0
;
}
static
int
sn95031_vhs_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
pr_debug
(
"VHS SND_SOC_DAPM_EVENT_ON doing rail startup now
\n
"
);
/* power up the rail */
snd_soc_write
(
codec
,
SN95031_VHSP
,
0x3D
);
snd_soc_write
(
codec
,
SN95031_VHSN
,
0x3F
);
msleep
(
1
);
}
else
if
(
SND_SOC_DAPM_EVENT_OFF
(
event
))
{
pr_debug
(
"VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown
\n
"
);
snd_soc_write
(
codec
,
SN95031_VHSP
,
0xC4
);
snd_soc_write
(
codec
,
SN95031_VHSN
,
0x04
);
}
return
0
;
}
static
int
sn95031_vihf_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
pr_debug
(
"VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now
\n
"
);
/* power up the rail */
snd_soc_write
(
codec
,
SN95031_VIHF
,
0x27
);
msleep
(
1
);
}
else
if
(
SND_SOC_DAPM_EVENT_OFF
(
event
))
{
pr_debug
(
"VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown
\n
"
);
snd_soc_write
(
codec
,
SN95031_VIHF
,
0x24
);
}
return
0
;
}
static
int
sn95031_dmic12_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
unsigned
int
ldo
=
0
,
clk_dir
=
0
,
data_dir
=
0
;
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
ldo
=
BIT
(
5
)
|
BIT
(
4
);
clk_dir
=
BIT
(
0
);
data_dir
=
BIT
(
7
);
}
/* program DMIC LDO, clock and set clock */
snd_soc_update_bits
(
codec
,
SN95031_MICBIAS
,
BIT
(
5
)
|
BIT
(
4
),
ldo
);
snd_soc_update_bits
(
codec
,
SN95031_DMICBUF0123
,
BIT
(
0
),
clk_dir
);
snd_soc_update_bits
(
codec
,
SN95031_DMICBUF0123
,
BIT
(
7
),
data_dir
);
return
0
;
}
static
int
sn95031_dmic34_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
unsigned
int
ldo
=
0
,
clk_dir
=
0
,
data_dir
=
0
;
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
ldo
=
BIT
(
5
)
|
BIT
(
4
);
clk_dir
=
BIT
(
2
);
data_dir
=
BIT
(
1
);
}
/* program DMIC LDO, clock and set clock */
snd_soc_update_bits
(
codec
,
SN95031_MICBIAS
,
BIT
(
5
)
|
BIT
(
4
),
ldo
);
snd_soc_update_bits
(
codec
,
SN95031_DMICBUF0123
,
BIT
(
2
),
clk_dir
);
snd_soc_update_bits
(
codec
,
SN95031_DMICBUF45
,
BIT
(
1
),
data_dir
);
return
0
;
}
static
int
sn95031_dmic56_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
unsigned
int
ldo
=
0
;
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
ldo
=
BIT
(
7
)
|
BIT
(
6
);
/* program DMIC LDO */
snd_soc_update_bits
(
codec
,
SN95031_MICBIAS
,
BIT
(
7
)
|
BIT
(
6
),
ldo
);
return
0
;
}
/* mux controls */
static
const
char
*
sn95031_mic_texts
[]
=
{
"AMIC"
,
"LineIn"
};
static
SOC_ENUM_SINGLE_DECL
(
sn95031_micl_enum
,
SN95031_ADCCONFIG
,
1
,
sn95031_mic_texts
);
static
const
struct
snd_kcontrol_new
sn95031_micl_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_micl_enum
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_micr_enum
,
SN95031_ADCCONFIG
,
3
,
sn95031_mic_texts
);
static
const
struct
snd_kcontrol_new
sn95031_micr_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_micr_enum
);
static
const
char
*
sn95031_input_texts
[]
=
{
"DMIC1"
,
"DMIC2"
,
"DMIC3"
,
"DMIC4"
,
"DMIC5"
,
"DMIC6"
,
"ADC Left"
,
"ADC Right"
};
static
SOC_ENUM_SINGLE_DECL
(
sn95031_input1_enum
,
SN95031_AUDIOMUX12
,
0
,
sn95031_input_texts
);
static
const
struct
snd_kcontrol_new
sn95031_input1_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_input1_enum
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_input2_enum
,
SN95031_AUDIOMUX12
,
4
,
sn95031_input_texts
);
static
const
struct
snd_kcontrol_new
sn95031_input2_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_input2_enum
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_input3_enum
,
SN95031_AUDIOMUX34
,
0
,
sn95031_input_texts
);
static
const
struct
snd_kcontrol_new
sn95031_input3_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_input3_enum
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_input4_enum
,
SN95031_AUDIOMUX34
,
4
,
sn95031_input_texts
);
static
const
struct
snd_kcontrol_new
sn95031_input4_mux_control
=
SOC_DAPM_ENUM
(
"Route"
,
sn95031_input4_enum
);
/* capture path controls */
static
const
char
*
sn95031_micmode_text
[]
=
{
"Single Ended"
,
"Differential"
};
/* 0dB to 30dB in 10dB steps */
static
const
DECLARE_TLV_DB_SCALE
(
mic_tlv
,
0
,
10
,
0
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_micmode1_enum
,
SN95031_MICAMP1
,
1
,
sn95031_micmode_text
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_micmode2_enum
,
SN95031_MICAMP2
,
1
,
sn95031_micmode_text
);
static
const
char
*
sn95031_dmic_cfg_text
[]
=
{
"GPO"
,
"DMIC"
};
static
SOC_ENUM_SINGLE_DECL
(
sn95031_dmic12_cfg_enum
,
SN95031_DMICMUX
,
0
,
sn95031_dmic_cfg_text
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_dmic34_cfg_enum
,
SN95031_DMICMUX
,
1
,
sn95031_dmic_cfg_text
);
static
SOC_ENUM_SINGLE_DECL
(
sn95031_dmic56_cfg_enum
,
SN95031_DMICMUX
,
2
,
sn95031_dmic_cfg_text
);
static
const
struct
snd_kcontrol_new
sn95031_snd_controls
[]
=
{
SOC_ENUM
(
"Mic1Mode Capture Route"
,
sn95031_micmode1_enum
),
SOC_ENUM
(
"Mic2Mode Capture Route"
,
sn95031_micmode2_enum
),
SOC_ENUM
(
"DMIC12 Capture Route"
,
sn95031_dmic12_cfg_enum
),
SOC_ENUM
(
"DMIC34 Capture Route"
,
sn95031_dmic34_cfg_enum
),
SOC_ENUM
(
"DMIC56 Capture Route"
,
sn95031_dmic56_cfg_enum
),
SOC_SINGLE_TLV
(
"Mic1 Capture Volume"
,
SN95031_MICAMP1
,
2
,
4
,
0
,
mic_tlv
),
SOC_SINGLE_TLV
(
"Mic2 Capture Volume"
,
SN95031_MICAMP2
,
2
,
4
,
0
,
mic_tlv
),
};
/* DAPM widgets */
static
const
struct
snd_soc_dapm_widget
sn95031_dapm_widgets
[]
=
{
/* all end points mic, hs etc */
SND_SOC_DAPM_OUTPUT
(
"HPOUTL"
),
SND_SOC_DAPM_OUTPUT
(
"HPOUTR"
),
SND_SOC_DAPM_OUTPUT
(
"EPOUT"
),
SND_SOC_DAPM_OUTPUT
(
"IHFOUTL"
),
SND_SOC_DAPM_OUTPUT
(
"IHFOUTR"
),
SND_SOC_DAPM_OUTPUT
(
"LINEOUTL"
),
SND_SOC_DAPM_OUTPUT
(
"LINEOUTR"
),
SND_SOC_DAPM_OUTPUT
(
"VIB1OUT"
),
SND_SOC_DAPM_OUTPUT
(
"VIB2OUT"
),
SND_SOC_DAPM_INPUT
(
"AMIC1"
),
/* headset mic */
SND_SOC_DAPM_INPUT
(
"AMIC2"
),
SND_SOC_DAPM_INPUT
(
"DMIC1"
),
SND_SOC_DAPM_INPUT
(
"DMIC2"
),
SND_SOC_DAPM_INPUT
(
"DMIC3"
),
SND_SOC_DAPM_INPUT
(
"DMIC4"
),
SND_SOC_DAPM_INPUT
(
"DMIC5"
),
SND_SOC_DAPM_INPUT
(
"DMIC6"
),
SND_SOC_DAPM_INPUT
(
"LINEINL"
),
SND_SOC_DAPM_INPUT
(
"LINEINR"
),
SND_SOC_DAPM_MICBIAS
(
"AMIC1Bias"
,
SN95031_MICBIAS
,
2
,
0
),
SND_SOC_DAPM_MICBIAS
(
"AMIC2Bias"
,
SN95031_MICBIAS
,
3
,
0
),
SND_SOC_DAPM_MICBIAS
(
"DMIC12Bias"
,
SN95031_DMICMUX
,
3
,
0
),
SND_SOC_DAPM_MICBIAS
(
"DMIC34Bias"
,
SN95031_DMICMUX
,
4
,
0
),
SND_SOC_DAPM_MICBIAS
(
"DMIC56Bias"
,
SN95031_DMICMUX
,
5
,
0
),
SND_SOC_DAPM_SUPPLY
(
"DMIC12supply"
,
SN95031_DMICLK
,
0
,
0
,
sn95031_dmic12_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
SND_SOC_DAPM_SUPPLY
(
"DMIC34supply"
,
SN95031_DMICLK
,
1
,
0
,
sn95031_dmic34_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
SND_SOC_DAPM_SUPPLY
(
"DMIC56supply"
,
SN95031_DMICLK
,
2
,
0
,
sn95031_dmic56_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
SND_SOC_DAPM_AIF_OUT
(
"PCM_Out"
,
"Capture"
,
0
,
SND_SOC_NOPM
,
0
,
0
),
SND_SOC_DAPM_SUPPLY
(
"Headset Rail"
,
SND_SOC_NOPM
,
0
,
0
,
sn95031_vhs_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
SND_SOC_DAPM_SUPPLY
(
"Speaker Rail"
,
SND_SOC_NOPM
,
0
,
0
,
sn95031_vihf_event
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
/* playback path driver enables */
SND_SOC_DAPM_PGA
(
"Headset Left Playback"
,
SN95031_DRIVEREN
,
0
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Headset Right Playback"
,
SN95031_DRIVEREN
,
1
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Speaker Left Playback"
,
SN95031_DRIVEREN
,
2
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Speaker Right Playback"
,
SN95031_DRIVEREN
,
3
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Vibra1 Playback"
,
SN95031_DRIVEREN
,
4
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Vibra2 Playback"
,
SN95031_DRIVEREN
,
5
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Earpiece Playback"
,
SN95031_DRIVEREN
,
6
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Lineout Left Playback"
,
SN95031_LOCTL
,
0
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Lineout Right Playback"
,
SN95031_LOCTL
,
4
,
0
,
NULL
,
0
),
/* playback path filter enable */
SND_SOC_DAPM_PGA
(
"Headset Left Filter"
,
SN95031_HSEPRXCTRL
,
4
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Headset Right Filter"
,
SN95031_HSEPRXCTRL
,
5
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Speaker Left Filter"
,
SN95031_IHFRXCTRL
,
0
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Speaker Right Filter"
,
SN95031_IHFRXCTRL
,
1
,
0
,
NULL
,
0
),
/* DACs */
SND_SOC_DAPM_DAC
(
"HSDAC Left"
,
"Headset"
,
SN95031_DACCONFIG
,
0
,
0
),
SND_SOC_DAPM_DAC
(
"HSDAC Right"
,
"Headset"
,
SN95031_DACCONFIG
,
1
,
0
),
SND_SOC_DAPM_DAC
(
"IHFDAC Left"
,
"Speaker"
,
SN95031_DACCONFIG
,
2
,
0
),
SND_SOC_DAPM_DAC
(
"IHFDAC Right"
,
"Speaker"
,
SN95031_DACCONFIG
,
3
,
0
),
SND_SOC_DAPM_DAC
(
"Vibra1 DAC"
,
"Vibra1"
,
SN95031_VIB1C5
,
1
,
0
),
SND_SOC_DAPM_DAC
(
"Vibra2 DAC"
,
"Vibra2"
,
SN95031_VIB2C5
,
1
,
0
),
/* capture widgets */
SND_SOC_DAPM_PGA
(
"LineIn Enable Left"
,
SN95031_MICAMP1
,
7
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"LineIn Enable Right"
,
SN95031_MICAMP2
,
7
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"MIC1 Enable"
,
SN95031_MICAMP1
,
0
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"MIC2 Enable"
,
SN95031_MICAMP2
,
0
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"TX1 Enable"
,
SN95031_AUDIOTXEN
,
2
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"TX2 Enable"
,
SN95031_AUDIOTXEN
,
3
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"TX3 Enable"
,
SN95031_AUDIOTXEN
,
4
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"TX4 Enable"
,
SN95031_AUDIOTXEN
,
5
,
0
,
NULL
,
0
),
/* ADC have null stream as they will be turned ON by TX path */
SND_SOC_DAPM_ADC
(
"ADC Left"
,
NULL
,
SN95031_ADCCONFIG
,
0
,
0
),
SND_SOC_DAPM_ADC
(
"ADC Right"
,
NULL
,
SN95031_ADCCONFIG
,
2
,
0
),
SND_SOC_DAPM_MUX
(
"Mic_InputL Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_micl_mux_control
),
SND_SOC_DAPM_MUX
(
"Mic_InputR Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_micr_mux_control
),
SND_SOC_DAPM_MUX
(
"Txpath1 Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_input1_mux_control
),
SND_SOC_DAPM_MUX
(
"Txpath2 Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_input2_mux_control
),
SND_SOC_DAPM_MUX
(
"Txpath3 Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_input3_mux_control
),
SND_SOC_DAPM_MUX
(
"Txpath4 Capture Route"
,
SND_SOC_NOPM
,
0
,
0
,
&
sn95031_input4_mux_control
),
};
static
const
struct
snd_soc_dapm_route
sn95031_audio_map
[]
=
{
/* headset and earpiece map */
{
"HPOUTL"
,
NULL
,
"Headset Rail"
},
{
"HPOUTR"
,
NULL
,
"Headset Rail"
},
{
"HPOUTL"
,
NULL
,
"Headset Left Playback"
},
{
"HPOUTR"
,
NULL
,
"Headset Right Playback"
},
{
"EPOUT"
,
NULL
,
"Earpiece Playback"
},
{
"Headset Left Playback"
,
NULL
,
"Headset Left Filter"
},
{
"Headset Right Playback"
,
NULL
,
"Headset Right Filter"
},
{
"Earpiece Playback"
,
NULL
,
"Headset Left Filter"
},
{
"Headset Left Filter"
,
NULL
,
"HSDAC Left"
},
{
"Headset Right Filter"
,
NULL
,
"HSDAC Right"
},
/* speaker map */
{
"IHFOUTL"
,
NULL
,
"Speaker Rail"
},
{
"IHFOUTR"
,
NULL
,
"Speaker Rail"
},
{
"IHFOUTL"
,
NULL
,
"Speaker Left Playback"
},
{
"IHFOUTR"
,
NULL
,
"Speaker Right Playback"
},
{
"Speaker Left Playback"
,
NULL
,
"Speaker Left Filter"
},
{
"Speaker Right Playback"
,
NULL
,
"Speaker Right Filter"
},
{
"Speaker Left Filter"
,
NULL
,
"IHFDAC Left"
},
{
"Speaker Right Filter"
,
NULL
,
"IHFDAC Right"
},
/* vibra map */
{
"VIB1OUT"
,
NULL
,
"Vibra1 Playback"
},
{
"Vibra1 Playback"
,
NULL
,
"Vibra1 DAC"
},
{
"VIB2OUT"
,
NULL
,
"Vibra2 Playback"
},
{
"Vibra2 Playback"
,
NULL
,
"Vibra2 DAC"
},
/* lineout */
{
"LINEOUTL"
,
NULL
,
"Lineout Left Playback"
},
{
"LINEOUTR"
,
NULL
,
"Lineout Right Playback"
},
{
"Lineout Left Playback"
,
NULL
,
"Headset Left Filter"
},
{
"Lineout Left Playback"
,
NULL
,
"Speaker Left Filter"
},
{
"Lineout Left Playback"
,
NULL
,
"Vibra1 DAC"
},
{
"Lineout Right Playback"
,
NULL
,
"Headset Right Filter"
},
{
"Lineout Right Playback"
,
NULL
,
"Speaker Right Filter"
},
{
"Lineout Right Playback"
,
NULL
,
"Vibra2 DAC"
},
/* Headset (AMIC1) mic */
{
"AMIC1Bias"
,
NULL
,
"AMIC1"
},
{
"MIC1 Enable"
,
NULL
,
"AMIC1Bias"
},
{
"Mic_InputL Capture Route"
,
"AMIC"
,
"MIC1 Enable"
},
/* AMIC2 */
{
"AMIC2Bias"
,
NULL
,
"AMIC2"
},
{
"MIC2 Enable"
,
NULL
,
"AMIC2Bias"
},
{
"Mic_InputR Capture Route"
,
"AMIC"
,
"MIC2 Enable"
},
/* Linein */
{
"LineIn Enable Left"
,
NULL
,
"LINEINL"
},
{
"LineIn Enable Right"
,
NULL
,
"LINEINR"
},
{
"Mic_InputL Capture Route"
,
"LineIn"
,
"LineIn Enable Left"
},
{
"Mic_InputR Capture Route"
,
"LineIn"
,
"LineIn Enable Right"
},
/* ADC connection */
{
"ADC Left"
,
NULL
,
"Mic_InputL Capture Route"
},
{
"ADC Right"
,
NULL
,
"Mic_InputR Capture Route"
},
/*DMIC connections */
{
"DMIC1"
,
NULL
,
"DMIC12supply"
},
{
"DMIC2"
,
NULL
,
"DMIC12supply"
},
{
"DMIC3"
,
NULL
,
"DMIC34supply"
},
{
"DMIC4"
,
NULL
,
"DMIC34supply"
},
{
"DMIC5"
,
NULL
,
"DMIC56supply"
},
{
"DMIC6"
,
NULL
,
"DMIC56supply"
},
{
"DMIC12Bias"
,
NULL
,
"DMIC1"
},
{
"DMIC12Bias"
,
NULL
,
"DMIC2"
},
{
"DMIC34Bias"
,
NULL
,
"DMIC3"
},
{
"DMIC34Bias"
,
NULL
,
"DMIC4"
},
{
"DMIC56Bias"
,
NULL
,
"DMIC5"
},
{
"DMIC56Bias"
,
NULL
,
"DMIC6"
},
/*TX path inputs*/
{
"Txpath1 Capture Route"
,
"ADC Left"
,
"ADC Left"
},
{
"Txpath2 Capture Route"
,
"ADC Left"
,
"ADC Left"
},
{
"Txpath3 Capture Route"
,
"ADC Left"
,
"ADC Left"
},
{
"Txpath4 Capture Route"
,
"ADC Left"
,
"ADC Left"
},
{
"Txpath1 Capture Route"
,
"ADC Right"
,
"ADC Right"
},
{
"Txpath2 Capture Route"
,
"ADC Right"
,
"ADC Right"
},
{
"Txpath3 Capture Route"
,
"ADC Right"
,
"ADC Right"
},
{
"Txpath4 Capture Route"
,
"ADC Right"
,
"ADC Right"
},
{
"Txpath1 Capture Route"
,
"DMIC1"
,
"DMIC1"
},
{
"Txpath2 Capture Route"
,
"DMIC1"
,
"DMIC1"
},
{
"Txpath3 Capture Route"
,
"DMIC1"
,
"DMIC1"
},
{
"Txpath4 Capture Route"
,
"DMIC1"
,
"DMIC1"
},
{
"Txpath1 Capture Route"
,
"DMIC2"
,
"DMIC2"
},
{
"Txpath2 Capture Route"
,
"DMIC2"
,
"DMIC2"
},
{
"Txpath3 Capture Route"
,
"DMIC2"
,
"DMIC2"
},
{
"Txpath4 Capture Route"
,
"DMIC2"
,
"DMIC2"
},
{
"Txpath1 Capture Route"
,
"DMIC3"
,
"DMIC3"
},
{
"Txpath2 Capture Route"
,
"DMIC3"
,
"DMIC3"
},
{
"Txpath3 Capture Route"
,
"DMIC3"
,
"DMIC3"
},
{
"Txpath4 Capture Route"
,
"DMIC3"
,
"DMIC3"
},
{
"Txpath1 Capture Route"
,
"DMIC4"
,
"DMIC4"
},
{
"Txpath2 Capture Route"
,
"DMIC4"
,
"DMIC4"
},
{
"Txpath3 Capture Route"
,
"DMIC4"
,
"DMIC4"
},
{
"Txpath4 Capture Route"
,
"DMIC4"
,
"DMIC4"
},
{
"Txpath1 Capture Route"
,
"DMIC5"
,
"DMIC5"
},
{
"Txpath2 Capture Route"
,
"DMIC5"
,
"DMIC5"
},
{
"Txpath3 Capture Route"
,
"DMIC5"
,
"DMIC5"
},
{
"Txpath4 Capture Route"
,
"DMIC5"
,
"DMIC5"
},
{
"Txpath1 Capture Route"
,
"DMIC6"
,
"DMIC6"
},
{
"Txpath2 Capture Route"
,
"DMIC6"
,
"DMIC6"
},
{
"Txpath3 Capture Route"
,
"DMIC6"
,
"DMIC6"
},
{
"Txpath4 Capture Route"
,
"DMIC6"
,
"DMIC6"
},
/* tx path */
{
"TX1 Enable"
,
NULL
,
"Txpath1 Capture Route"
},
{
"TX2 Enable"
,
NULL
,
"Txpath2 Capture Route"
},
{
"TX3 Enable"
,
NULL
,
"Txpath3 Capture Route"
},
{
"TX4 Enable"
,
NULL
,
"Txpath4 Capture Route"
},
{
"PCM_Out"
,
NULL
,
"TX1 Enable"
},
{
"PCM_Out"
,
NULL
,
"TX2 Enable"
},
{
"PCM_Out"
,
NULL
,
"TX3 Enable"
},
{
"PCM_Out"
,
NULL
,
"TX4 Enable"
},
};
/* speaker and headset mutes, for audio pops and clicks */
static
int
sn95031_pcm_hs_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
snd_soc_update_bits
(
dai
->
codec
,
SN95031_HSLVOLCTRL
,
BIT
(
7
),
(
!
mute
<<
7
));
snd_soc_update_bits
(
dai
->
codec
,
SN95031_HSRVOLCTRL
,
BIT
(
7
),
(
!
mute
<<
7
));
return
0
;
}
static
int
sn95031_pcm_spkr_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
snd_soc_update_bits
(
dai
->
codec
,
SN95031_IHFLVOLCTRL
,
BIT
(
7
),
(
!
mute
<<
7
));
snd_soc_update_bits
(
dai
->
codec
,
SN95031_IHFRVOLCTRL
,
BIT
(
7
),
(
!
mute
<<
7
));
return
0
;
}
static
int
sn95031_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
unsigned
int
format
,
rate
;
switch
(
params_width
(
params
))
{
case
16
:
format
=
BIT
(
4
)
|
BIT
(
5
);
break
;
case
24
:
format
=
0
;
break
;
default:
return
-
EINVAL
;
}
snd_soc_update_bits
(
dai
->
codec
,
SN95031_PCM2C2
,
BIT
(
4
)
|
BIT
(
5
),
format
);
switch
(
params_rate
(
params
))
{
case
48000
:
pr_debug
(
"RATE_48000
\n
"
);
rate
=
0
;
break
;
case
44100
:
pr_debug
(
"RATE_44100
\n
"
);
rate
=
BIT
(
7
);
break
;
default:
pr_err
(
"ERR rate %d
\n
"
,
params_rate
(
params
));
return
-
EINVAL
;
}
snd_soc_update_bits
(
dai
->
codec
,
SN95031_PCM1C1
,
BIT
(
7
),
rate
);
return
0
;
}
/* Codec DAI section */
static
const
struct
snd_soc_dai_ops
sn95031_headset_dai_ops
=
{
.
digital_mute
=
sn95031_pcm_hs_mute
,
.
hw_params
=
sn95031_pcm_hw_params
,
};
static
const
struct
snd_soc_dai_ops
sn95031_speaker_dai_ops
=
{
.
digital_mute
=
sn95031_pcm_spkr_mute
,
.
hw_params
=
sn95031_pcm_hw_params
,
};
static
const
struct
snd_soc_dai_ops
sn95031_vib1_dai_ops
=
{
.
hw_params
=
sn95031_pcm_hw_params
,
};
static
const
struct
snd_soc_dai_ops
sn95031_vib2_dai_ops
=
{
.
hw_params
=
sn95031_pcm_hw_params
,
};
static
struct
snd_soc_dai_driver
sn95031_dais
[]
=
{
{
.
name
=
"SN95031 Headset"
,
.
playback
=
{
.
stream_name
=
"Headset"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SN95031_RATES
,
.
formats
=
SN95031_FORMATS
,
},
.
capture
=
{
.
stream_name
=
"Capture"
,
.
channels_min
=
1
,
.
channels_max
=
5
,
.
rates
=
SN95031_RATES
,
.
formats
=
SN95031_FORMATS
,
},
.
ops
=
&
sn95031_headset_dai_ops
,
},
{
.
name
=
"SN95031 Speaker"
,
.
playback
=
{
.
stream_name
=
"Speaker"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SN95031_RATES
,
.
formats
=
SN95031_FORMATS
,
},
.
ops
=
&
sn95031_speaker_dai_ops
,
},
{
.
name
=
"SN95031 Vibra1"
,
.
playback
=
{
.
stream_name
=
"Vibra1"
,
.
channels_min
=
1
,
.
channels_max
=
1
,
.
rates
=
SN95031_RATES
,
.
formats
=
SN95031_FORMATS
,
},
.
ops
=
&
sn95031_vib1_dai_ops
,
},
{
.
name
=
"SN95031 Vibra2"
,
.
playback
=
{
.
stream_name
=
"Vibra2"
,
.
channels_min
=
1
,
.
channels_max
=
1
,
.
rates
=
SN95031_RATES
,
.
formats
=
SN95031_FORMATS
,
},
.
ops
=
&
sn95031_vib2_dai_ops
,
},
};
static
inline
void
sn95031_disable_jack_btn
(
struct
snd_soc_codec
*
codec
)
{
snd_soc_write
(
codec
,
SN95031_BTNCTRL2
,
0x00
);
}
static
inline
void
sn95031_enable_jack_btn
(
struct
snd_soc_codec
*
codec
)
{
snd_soc_write
(
codec
,
SN95031_BTNCTRL1
,
0x77
);
snd_soc_write
(
codec
,
SN95031_BTNCTRL2
,
0x01
);
}
static
int
sn95031_get_headset_state
(
struct
snd_soc_codec
*
codec
,
struct
snd_soc_jack
*
mfld_jack
)
{
int
micbias
=
sn95031_get_mic_bias
(
codec
);
int
jack_type
=
snd_soc_jack_get_type
(
mfld_jack
,
micbias
);
pr_debug
(
"jack type detected = %d
\n
"
,
jack_type
);
if
(
jack_type
==
SND_JACK_HEADSET
)
sn95031_enable_jack_btn
(
codec
);
return
jack_type
;
}
void
sn95031_jack_detection
(
struct
snd_soc_codec
*
codec
,
struct
mfld_jack_data
*
jack_data
)
{
unsigned
int
status
;
unsigned
int
mask
=
SND_JACK_BTN_0
|
SND_JACK_BTN_1
|
SND_JACK_HEADSET
;
pr_debug
(
"interrupt id read in sram = 0x%x
\n
"
,
jack_data
->
intr_id
);
if
(
jack_data
->
intr_id
&
0x1
)
{
pr_debug
(
"short_push detected
\n
"
);
status
=
SND_JACK_HEADSET
|
SND_JACK_BTN_0
;
}
else
if
(
jack_data
->
intr_id
&
0x2
)
{
pr_debug
(
"long_push detected
\n
"
);
status
=
SND_JACK_HEADSET
|
SND_JACK_BTN_1
;
}
else
if
(
jack_data
->
intr_id
&
0x4
)
{
pr_debug
(
"headset or headphones inserted
\n
"
);
status
=
sn95031_get_headset_state
(
codec
,
jack_data
->
mfld_jack
);
}
else
if
(
jack_data
->
intr_id
&
0x8
)
{
pr_debug
(
"headset or headphones removed
\n
"
);
status
=
0
;
sn95031_disable_jack_btn
(
codec
);
}
else
{
pr_err
(
"unidentified interrupt
\n
"
);
return
;
}
snd_soc_jack_report
(
jack_data
->
mfld_jack
,
status
,
mask
);
/*button pressed and released so we send explicit button release */
if
((
status
&
SND_JACK_BTN_0
)
|
(
status
&
SND_JACK_BTN_1
))
snd_soc_jack_report
(
jack_data
->
mfld_jack
,
SND_JACK_HEADSET
,
mask
);
}
EXPORT_SYMBOL_GPL
(
sn95031_jack_detection
);
/* codec registration */
static
int
sn95031_codec_probe
(
struct
snd_soc_codec
*
codec
)
{
pr_debug
(
"codec_probe called
\n
"
);
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
*/
snd_soc_write
(
codec
,
SN95031_PCM2RXSLOT01
,
0x10
);
snd_soc_write
(
codec
,
SN95031_PCM2RXSLOT23
,
0x32
);
snd_soc_write
(
codec
,
SN95031_PCM2RXSLOT45
,
0x54
);
snd_soc_write
(
codec
,
SN95031_PCM2TXSLOT01
,
0x10
);
snd_soc_write
(
codec
,
SN95031_PCM2TXSLOT23
,
0x32
);
/* pcm port setting
* This sets the pcm port to slave and clock at 19.2Mhz which
* can support 6slots, sampling rate set per stream in hw-params
*/
snd_soc_write
(
codec
,
SN95031_PCM1C1
,
0x00
);
snd_soc_write
(
codec
,
SN95031_PCM2C1
,
0x01
);
snd_soc_write
(
codec
,
SN95031_PCM2C2
,
0x0A
);
snd_soc_write
(
codec
,
SN95031_HSMIXER
,
BIT
(
0
)
|
BIT
(
4
));
/* vendor vibra workround, the vibras are muted by
* custom register so unmute them
*/
snd_soc_write
(
codec
,
SN95031_SSR5
,
0x80
);
snd_soc_write
(
codec
,
SN95031_SSR6
,
0x80
);
snd_soc_write
(
codec
,
SN95031_VIB1C5
,
0x00
);
snd_soc_write
(
codec
,
SN95031_VIB2C5
,
0x00
);
/* configure vibras for pcm port */
snd_soc_write
(
codec
,
SN95031_VIB1C3
,
0x00
);
snd_soc_write
(
codec
,
SN95031_VIB2C3
,
0x00
);
/* soft mute ramp time */
snd_soc_write
(
codec
,
SN95031_SOFTMUTE
,
0x3
);
/* fix the initial volume at 1dB,
* default in +9dB,
* 1dB give optimal swing on DAC, amps
*/
snd_soc_write
(
codec
,
SN95031_HSLVOLCTRL
,
0x08
);
snd_soc_write
(
codec
,
SN95031_HSRVOLCTRL
,
0x08
);
snd_soc_write
(
codec
,
SN95031_IHFLVOLCTRL
,
0x08
);
snd_soc_write
(
codec
,
SN95031_IHFRVOLCTRL
,
0x08
);
/* dac mode and lineout workaround */
snd_soc_write
(
codec
,
SN95031_SSR2
,
0x10
);
snd_soc_write
(
codec
,
SN95031_SSR3
,
0x40
);
return
0
;
}
static
const
struct
snd_soc_codec_driver
sn95031_codec
=
{
.
probe
=
sn95031_codec_probe
,
.
set_bias_level
=
sn95031_set_vaud_bias
,
.
idle_bias_off
=
true
,
.
component_driver
=
{
.
controls
=
sn95031_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
sn95031_snd_controls
),
.
dapm_widgets
=
sn95031_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
sn95031_dapm_widgets
),
.
dapm_routes
=
sn95031_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
sn95031_audio_map
),
},
};
static
int
sn95031_device_probe
(
struct
platform_device
*
pdev
)
{
struct
regmap
*
regmap
;
pr_debug
(
"codec device probe called for %s
\n
"
,
dev_name
(
&
pdev
->
dev
));
regmap
=
devm_regmap_init
(
&
pdev
->
dev
,
NULL
,
NULL
,
&
sn95031_regmap
);
if
(
IS_ERR
(
regmap
))
return
PTR_ERR
(
regmap
);
return
snd_soc_register_codec
(
&
pdev
->
dev
,
&
sn95031_codec
,
sn95031_dais
,
ARRAY_SIZE
(
sn95031_dais
));
}
static
int
sn95031_device_remove
(
struct
platform_device
*
pdev
)
{
pr_debug
(
"codec device remove called
\n
"
);
snd_soc_unregister_codec
(
&
pdev
->
dev
);
return
0
;
}
static
struct
platform_driver
sn95031_codec_driver
=
{
.
driver
=
{
.
name
=
"sn95031"
,
},
.
probe
=
sn95031_device_probe
,
.
remove
=
sn95031_device_remove
,
};
module_platform_driver
(
sn95031_codec_driver
);
MODULE_DESCRIPTION
(
"ASoC TI SN95031 codec driver"
);
MODULE_AUTHOR
(
"Vinod Koul <vinod.koul@intel.com>"
);
MODULE_AUTHOR
(
"Harsha Priya <priya.harsha@intel.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:sn95031"
);
sound/soc/codecs/sn95031.h
deleted
100644 → 0
View file @
5b813eca
/*
* sn95031.h - TI sn95031 Codec driver
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*/
#ifndef _SN95031_H
#define _SN95031_H
/*register map*/
#define SN95031_VAUD 0xDB
#define SN95031_VHSP 0xDC
#define SN95031_VHSN 0xDD
#define SN95031_VIHF 0xC9
#define SN95031_AUDPLLCTRL 0x240
#define SN95031_DMICBUF0123 0x241
#define SN95031_DMICBUF45 0x242
#define SN95031_DMICGPO 0x244
#define SN95031_DMICMUX 0x245
#define SN95031_DMICLK 0x246
#define SN95031_MICBIAS 0x247
#define SN95031_ADCCONFIG 0x248
#define SN95031_MICAMP1 0x249
#define SN95031_MICAMP2 0x24A
#define SN95031_NOISEMUX 0x24B
#define SN95031_AUDIOMUX12 0x24C
#define SN95031_AUDIOMUX34 0x24D
#define SN95031_AUDIOSINC 0x24E
#define SN95031_AUDIOTXEN 0x24F
#define SN95031_HSEPRXCTRL 0x250
#define SN95031_IHFRXCTRL 0x251
#define SN95031_HSMIXER 0x256
#define SN95031_DACCONFIG 0x257
#define SN95031_SOFTMUTE 0x258
#define SN95031_HSLVOLCTRL 0x259
#define SN95031_HSRVOLCTRL 0x25A
#define SN95031_IHFLVOLCTRL 0x25B
#define SN95031_IHFRVOLCTRL 0x25C
#define SN95031_DRIVEREN 0x25D
#define SN95031_LOCTL 0x25E
#define SN95031_VIB1C1 0x25F
#define SN95031_VIB1C2 0x260
#define SN95031_VIB1C3 0x261
#define SN95031_VIB1SPIPCM1 0x262
#define SN95031_VIB1SPIPCM2 0x263
#define SN95031_VIB1C5 0x264
#define SN95031_VIB2C1 0x265
#define SN95031_VIB2C2 0x266
#define SN95031_VIB2C3 0x267
#define SN95031_VIB2SPIPCM1 0x268
#define SN95031_VIB2SPIPCM2 0x269
#define SN95031_VIB2C5 0x26A
#define SN95031_BTNCTRL1 0x26B
#define SN95031_BTNCTRL2 0x26C
#define SN95031_PCM1TXSLOT01 0x26D
#define SN95031_PCM1TXSLOT23 0x26E
#define SN95031_PCM1TXSLOT45 0x26F
#define SN95031_PCM1RXSLOT0_3 0x270
#define SN95031_PCM1RXSLOT45 0x271
#define SN95031_PCM2TXSLOT01 0x272
#define SN95031_PCM2TXSLOT23 0x273
#define SN95031_PCM2TXSLOT45 0x274
#define SN95031_PCM2RXSLOT01 0x275
#define SN95031_PCM2RXSLOT23 0x276
#define SN95031_PCM2RXSLOT45 0x277
#define SN95031_PCM1C1 0x278
#define SN95031_PCM1C2 0x279
#define SN95031_PCM1C3 0x27A
#define SN95031_PCM2C1 0x27B
#define SN95031_PCM2C2 0x27C
/*end codec register defn*/
/*vendor defn these are not part of avp*/
#define SN95031_SSR2 0x381
#define SN95031_SSR3 0x382
#define SN95031_SSR5 0x384
#define SN95031_SSR6 0x385
/* ADC registers */
#define SN95031_ADC1CNTL1 0x1C0
#define SN95031_ADC_ENBL 0x10
#define SN95031_ADC_START 0x08
#define SN95031_ADC1CNTL3 0x1C2
#define SN95031_ADCTHERM_ENBL 0x04
#define SN95031_ADCRRDATA_ENBL 0x05
#define SN95031_STOPBIT_MASK 16
#define SN95031_ADCTHERM_MASK 4
#define SN95031_ADC_CHANLS_MAX 15
/* Number of ADC channels */
#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
#define SN95031_ADC_NO_LOOP 0x07
#define SN95031_AUDIO_GPIO_CTRL 0x070
/* ADC channel code values */
#define SN95031_AUDIO_DETECT_CODE 0x06
/* ADC base addresses */
#define SN95031_ADC_CHNL_START_ADDR 0x1C5
/* increments by 1 */
#define SN95031_ADC_DATA_START_ADDR 0x1D4
/* increments by 2 */
/* multipier to convert to mV */
#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
struct
mfld_jack_data
{
int
intr_id
;
int
micbias_vol
;
struct
snd_soc_jack
*
mfld_jack
;
};
extern
void
sn95031_jack_detection
(
struct
snd_soc_codec
*
codec
,
struct
mfld_jack_data
*
jack_data
);
#endif
sound/soc/intel/Kconfig
View file @
70fff743
config SND_SOC_INTEL_SST_TOPLEVEL
bool "Intel ASoC SST drivers"
default y
depends on X86 || COMPILE_TEST
select SND_SOC_INTEL_MACH
help
Intel ASoC SST Platform Drivers. If you have a Intel machine that
has an audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Intel SST drivers.
if SND_SOC_INTEL_SST_TOPLEVEL
config SND_SST_IPC
tristate
# This option controls the IPC core for HiFi2 platforms
config SND_SST_IPC_PCI
tristate
select SND_SST_IPC
# This option controls the PCI-based IPC for HiFi2 platforms
# (Medfield, Merrifield).
config SND_SST_IPC_ACPI
tristate
select SND_SST_IPC
select SND_SOC_INTEL_SST
select IOSF_MBI
# This option controls the ACPI-based IPC for HiFi2 platforms
# (Baytrail, Cherrytrail)
config SND_SOC_INTEL_
COMMON
config SND_SOC_INTEL_
SST_ACPI
tristate
# This option controls ACPI-based probing on
# Haswell/Broadwell/Baytrail legacy and will be set
# when these platforms are enabled
config SND_SOC_INTEL_SST
tristate
select SND_SOC_INTEL_SST_ACPI if ACPI
config SND_SOC_INTEL_SST_FIRMWARE
tristate
select DW_DMAC_CORE
config SND_SOC_INTEL_SST_ACPI
tristate
config SND_SOC_ACPI_INTEL_MATCH
tristate
select SND_SOC_ACPI if ACPI
config SND_SOC_INTEL_SST_TOPLEVEL
tristate "Intel ASoC SST drivers"
depends on X86 || COMPILE_TEST
select SND_SOC_INTEL_MACH
select SND_SOC_INTEL_COMMON
help
Intel ASoC Audio Drivers. If you have a Intel machine that
has audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y or M
If unsure select "N".
# This option controls firmware download on
# Haswell/Broadwell/Baytrail legacy and will be set
# when these platforms are enabled
config SND_SOC_INTEL_HASWELL
tristate "
Intel ASoC SST driver for Haswell/Broadwell
"
depends on SND_
SOC_INTEL_SST_TOPLEVEL && SND_
DMA_SGBUF
depends on DMADEVICES
tristate "
Haswell/Broadwell Platforms
"
depends on SND_DMA_SGBUF
depends on DMADEVICES
&& ACPI
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_ACPI
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Haswell or Broadwell platform connected to
an I2S codec, then enable this option by saying Y or m. This is
typically used for Chromebooks. This is a recommended option.
config SND_SOC_INTEL_BAYTRAIL
tristate "Intel ASoC SST driver for Baytrail (legacy)"
depends on SND_SOC_INTEL_SST_TOPLEVEL
depends on DMADEVICES
tristate "Baytrail (legacy) Platforms"
depends on DMADEVICES && ACPI
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_ACPI
select SND_SOC_INTEL_SST_FIRMWARE
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Baytrail platform connected to an I2S codec,
then enable this option by saying Y or m. This was typically used
for Baytrail Chromebooks but this option is now deprecated and is
not recommended, use SND_SST_ATOM_HIFI2_PLATFORM instead.
config SND_SST_ATOM_HIFI2_PLATFORM_PCI
tristate "PCI HiFi2 (Medfield, Merrifield) Platforms"
depends on X86 && PCI
select SND_SST_IPC_PCI
select SND_SOC_COMPRESS
help
If you have a Intel Medfield or Merrifield/Edison platform, then
enable this option by saying Y or m. Distros will typically not
enable this option: Medfield devices are not available to
developers and while Merrifield/Edison can run a mainline kernel with
limited functionality it will require a firmware file which
is not in the standard firmware tree
config SND_SST_ATOM_HIFI2_PLATFORM
tristate "Intel ASoC SST driver for HiFi2 platforms (*field, *trail)"
depends on SND_SOC_INTEL_SST_TOPLEVEL && X86
tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
depends on X86 && ACPI
select SND_SST_IPC_ACPI
select SND_SOC_COMPRESS
select SND_SOC_ACPI_INTEL_MATCH
select IOSF_MBI
help
If you have a Intel Baytrail or Cherrytrail platform with an I2S
codec, then enable this option by saying Y or m. This is a
recommended option
config SND_SOC_INTEL_SKYLAKE_SSP_CLK
tristate
config SND_SOC_INTEL_SKYLAKE
tristate "
Intel ASoC SST driver for SKL/BXT/KBL/GLK/CNL
"
depends on
SND_SOC_INTEL_SST_TOPLEVEL &&
PCI && ACPI
tristate "
SKL/BXT/KBL/GLK/CNL... Platforms
"
depends on PCI && ACPI
select SND_HDA_EXT_CORE
select SND_HDA_DSP_LOADER
select SND_SOC_TOPOLOGY
select SND_SOC_INTEL_SST
select SND_SOC_ACPI_INTEL_MATCH
help
If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
GeminiLake or CannonLake platform with the DSP enabled in the BIOS
then enable this option by saying Y or m.
config SND_SOC_ACPI_INTEL_MATCH
tristate
select SND_SOC_ACPI if ACPI
# this option controls the compilation of ACPI matching tables and
# helpers and is not meant to be selected by the user.
endif ## SND_SOC_INTEL_SST_TOPLEVEL
# ASoC codec drivers
source "sound/soc/intel/boards/Kconfig"
sound/soc/intel/Makefile
View file @
70fff743
# SPDX-License-Identifier: GPL-2.0
# Core support
obj-$(CONFIG_SND_SOC
_INTEL_COMMON
)
+=
common/
obj-$(CONFIG_SND_SOC)
+=
common/
# Platform Support
obj-$(CONFIG_SND_SOC_INTEL_HASWELL)
+=
haswell/
...
...
sound/soc/intel/atom/sst/sst_acpi.c
View file @
70fff743
...
...
@@ -236,6 +236,9 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx)
/* Find the IRQ */
ctx
->
irq_num
=
platform_get_irq
(
pdev
,
ctx
->
pdata
->
res_info
->
acpi_ipc_irq_index
);
if
(
ctx
->
irq_num
<=
0
)
return
ctx
->
irq_num
<
0
?
ctx
->
irq_num
:
-
EIO
;
return
0
;
}
...
...
sound/soc/intel/atom/sst/sst_stream.c
View file @
70fff743
...
...
@@ -220,10 +220,10 @@ int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
sst_free_block
(
sst_drv_ctx
,
block
);
out:
test_and_clear_bit
(
pvt_id
,
&
sst_drv_ctx
->
pvt_id
);
return
0
;
return
ret
;
}
/*
/*
*
* sst_pause_stream - Send msg for a pausing stream
* @str_id: stream ID
*
...
...
@@ -261,7 +261,7 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
}
}
else
{
retval
=
-
EBADRQC
;
dev_dbg
(
sst_drv_ctx
->
dev
,
"SST DBG:BADRQC for stream
\n
"
);
dev_dbg
(
sst_drv_ctx
->
dev
,
"SST DBG:BADRQC for stream
\n
"
);
}
return
retval
;
...
...
sound/soc/intel/boards/Kconfig
View file @
70fff743
config SND_SOC_INTEL_MACH
tristate "Intel Audio m
achine drivers"
menu
config SND_SOC_INTEL_MACH
bool "Intel M
achine drivers"
depends on SND_SOC_INTEL_SST_TOPLEVEL
select SND_SOC_ACPI_INTEL_MATCH if ACPI
help
Intel ASoC Machine Drivers. If you have a Intel machine that
has an audio controller with a DSP and I2S or DMIC port, then
enable this option by saying Y
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Intel ASoC machine drivers.
if SND_SOC_INTEL_MACH
config SND_MFLD_MACHINE
tristate "SOC Machine Audio driver for Intel Medfield MID platform"
depends on INTEL_SCU_IPC
select SND_SOC_SN95031
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_PCI
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.
If unsure select "N".
if SND_SOC_INTEL_HASWELL
config SND_SOC_INTEL_HASWELL_MACH
tristate "
ASoC Audio DSP support for Intel
Haswell Lynxpoint"
tristate "Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on 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.
Ultrabook platforms.
This is a recommended option.
Say Y
or m
if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_BDW_RT5677_MACH
tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec"
depends on X86_INTEL_LPSS && GPIOLIB && I2C
depends on SND_SOC_INTEL_HASWELL
tristate "Broadwell with RT5677 codec"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM && GPIOLIB
select SND_SOC_RT5677
help
This adds support for Intel Broadwell platform based boards with
the RT5677 audio codec.
the RT5677 audio codec. This is a recommended option.
Say Y or m if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_BROADWELL_MACH
tristate "
ASoC Audio DSP support for Intel
Broadwell Wildcatpoint"
tristate "Broadwell Wildcatpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
depends on 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
or m if you have such a device. This is a recommended option
.
If unsure select "N".
endif ## SND_SOC_INTEL_HASWELL
if SND_SOC_INTEL_BAYTRAIL
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "
ASoC Audio driver for Intel
Baytrail with MAX98090 codec"
tristate "Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
depends on SND_SST_IPC_ACPI = n
depends on SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
help
This adds audio driver for Intel Baytrail platform based boards
with the MAX98090 audio codec.
with the MAX98090 audio codec. This driver is deprecated, use
SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH instead for better
functionality.
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "
ASoC Audio driver for Intel
Baytrail with RT5640 codec"
tristate "Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
depends on SND_SST_IPC_ACPI = n
depends on 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.
endif ## SND_SOC_INTEL_BAYTRAIL
if SND_SST_ATOM_HIFI2_PLATFORM
config SND_SOC_INTEL_BYTCR_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
depends on X86 && I2C && ACPI
tristate "Baytrail and Baytrail-CR with RT5640 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5640
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
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 or m if you have such a device. This is a recommended option
.
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 && ACPI
tristate "Baytrail and Baytrail-CR with RT5651 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5651
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
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 or m if you have such a device. This is a recommended option
.
If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
tristate "ASoC Audio driver for Intel
Cherrytrail & Braswell with RT5672 codec"
tristate "
Cherrytrail & Braswell with RT5672 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5670
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
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
or m if you have such a device. This is a recommended option
.
If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
tristate "
ASoC Audio driver for Intel
Cherrytrail & Braswell with RT5645/5650 codec"
tristate "Cherrytrail & Braswell with RT5645/5650 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_RT5645
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help
This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
platforms with RT5645/5650 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
tristate "
ASoC Audio driver for Intel
Cherrytrail & Braswell with MAX98090 & TI codec"
tristate "Cherrytrail & Braswell with MAX98090 & TI codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_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.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
tristate "
ASoC Audio driver for Intel
Baytrail & Cherrytrail with DA7212/7213 codec"
tristate "Baytrail & Cherrytrail with DA7212/7213 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_DA7213
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help
This adds support for ASoC machine driver for Intel(R) Baytrail & CherryTrail
platforms with DA7212/7213 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
tristate "
ASoC Audio driver for Intel
Baytrail & Cherrytrail with ES8316 codec"
tristate "Baytrail & Cherrytrail with ES8316 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_ES8316
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help
This adds support for ASoC machine driver for Intel(R) Baytrail &
Cherrytrail platforms with ES8316 audio codec.
Say Y or m if you have such a device. This is a recommended option.
If unsure select "N".
config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
tristate "
ASoC Audio driver for Intel
Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)"
tristate "Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)"
depends on X86_INTEL_LPSS && I2C && ACPI
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
help
This adds support for ASoC machine driver for the MinnowBoard Max or
Up boards and provides access to I2S signals on the Low-Speed
connector
connector. This is not a recommended option outside of these cases.
It is not intended to be enabled by distros by default.
Say Y or m if you have such a device.
If unsure select "N".
endif ## SND_SST_ATOM_HIFI2_PLATFORM
if SND_SOC_INTEL_SKYLAKE
config SND_SOC_INTEL_SKL_RT286_MACH
tristate "ASoC Audio driver for SKL with RT286 I2S mode"
depends on X86 && ACPI && I2C
depends on SND_SOC_INTEL_SKYLAKE
tristate "SKL with RT286 I2S mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_RT286
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
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
or m
if you have such a device.
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode"
depends on X86_INTEL_LPSS && I2C
depends on SND_SOC_INTEL_SKYLAKE
tristate "SKL with NAU88L25 and SSM4567 in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_NAU8825
select SND_SOC_SSM4567
select SND_SOC_DMIC
...
...
@@ -185,13 +185,12 @@ 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
or m if you have such a device. This is a recommended option
.
If unsure select "N".
config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode"
depends on X86_INTEL_LPSS && I2C
depends on SND_SOC_INTEL_SKYLAKE
tristate "SKL with NAU88L25 and MAX98357A in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_NAU8825
select SND_SOC_MAX98357A
select SND_SOC_DMIC
...
...
@@ -199,13 +198,12 @@ 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
or m if you have such a device. This is a recommended option
.
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
depends on SND_SOC_INTEL_SKYLAKE
tristate "Broxton with DA7219 and MAX98357A in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_DMIC
...
...
@@ -214,13 +212,12 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
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
.
Say Y
or m if you have such a device. This is a recommended option
.
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
depends on SND_SOC_INTEL_SKYLAKE
tristate "Broxton with RT298 I2S mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_RT298
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
...
...
@@ -228,29 +225,27 @@ 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
or m if you have such a device. This is a recommended option
.
If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_SST
depends on SND_SOC_INTEL_SKYLAKE
tristate "KBL with RT5663 and MAX98927 in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
select SND_SOC_RT5663
select SND_SOC_MAX98927
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_SKYLAKE_SSP_CLK
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + MAX98927.
Say Y
if you have such a device
.
Say Y
or m if you have such a device. This is a recommended option
.
If unsure select "N".
config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
depends on X86_INTEL_LPSS && I2C && SPI
select SND_SOC_INTEL_SST
depends on SND_SOC_INTEL_SKYLAKE
tristate "KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
depends on MFD_INTEL_LPSS && I2C && ACPI
depends on SPI
select SND_SOC_RT5663
select SND_SOC_RT5514
select SND_SOC_RT5514_SPI
...
...
@@ -259,7 +254,8 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + RT5514 + MAX98927.
Say Y
if you have such a device
.
Say Y
or m if you have such a device. This is a recommended option
.
If unsure select "N".
endif ## SND_SOC_INTEL_SKYLAKE
endif
endif
## SND_SOC_INTEL_MACH
sound/soc/intel/boards/bytcht_da7213.c
View file @
70fff743
...
...
@@ -219,7 +219,7 @@ static struct snd_soc_card bytcht_da7213_card = {
.
num_dapm_routes
=
ARRAY_SIZE
(
audio_map
),
};
static
char
codec_name
[
16
];
/* i2c-<HID>:00 with HID being 8 chars */
static
char
codec_name
[
SND_ACPI_I2C_ID_LEN
];
static
int
bytcht_da7213_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -243,7 +243,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
}
/* fixup codec name based on HID */
i2c_name
=
snd_soc_acpi_find_name_from_hid
(
mach
->
id
);
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
codec_name
,
sizeof
(
codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
...
...
sound/soc/intel/boards/bytcht_es8316.c
View file @
70fff743
...
...
@@ -232,15 +232,39 @@ static struct snd_soc_card byt_cht_es8316_card = {
.
fully_routed
=
true
,
};
static
char
codec_name
[
SND_ACPI_I2C_ID_LEN
];
static
int
snd_byt_cht_es8316_mc_probe
(
struct
platform_device
*
pdev
)
{
int
ret
=
0
;
struct
byt_cht_es8316_private
*
priv
;
struct
snd_soc_acpi_mach
*
mach
;
const
char
*
i2c_name
=
NULL
;
int
dai_index
=
0
;
int
i
;
int
ret
=
0
;
priv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
priv
),
GFP_ATOMIC
);
if
(
!
priv
)
return
-
ENOMEM
;
mach
=
(
&
pdev
->
dev
)
->
platform_data
;
/* fix index of codec dai */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
byt_cht_es8316_dais
);
i
++
)
{
if
(
!
strcmp
(
byt_cht_es8316_dais
[
i
].
codec_name
,
"i2c-ESSX8316:00"
))
{
dai_index
=
i
;
break
;
}
}
/* fixup codec name based on HID */
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
codec_name
,
sizeof
(
codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
byt_cht_es8316_dais
[
dai_index
].
codec_name
=
codec_name
;
}
/* register the soc card */
byt_cht_es8316_card
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
byt_cht_es8316_card
,
priv
);
...
...
sound/soc/intel/boards/bytcr_rt5640.c
View file @
70fff743
...
...
@@ -713,7 +713,7 @@ static struct snd_soc_card byt_rt5640_card = {
.
fully_routed
=
true
,
};
static
char
byt_rt5640_codec_name
[
16
];
/* i2c-<HID>:00 with HID being 8 chars */
static
char
byt_rt5640_codec_name
[
SND_ACPI_I2C_ID_LEN
];
static
char
byt_rt5640_codec_aif_name
[
12
];
/* = "rt5640-aif[1|2]" */
static
char
byt_rt5640_cpu_dai_name
[
10
];
/* = "ssp[0|2]-port" */
...
...
@@ -762,7 +762,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
}
/* fixup codec name based on HID */
i2c_name
=
snd_soc_acpi_find_name_from_hid
(
mach
->
id
);
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
byt_rt5640_codec_name
,
sizeof
(
byt_rt5640_codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
...
...
sound/soc/intel/boards/bytcr_rt5651.c
View file @
70fff743
...
...
@@ -38,6 +38,8 @@ enum {
BYT_RT5651_DMIC_MAP
,
BYT_RT5651_IN1_MAP
,
BYT_RT5651_IN2_MAP
,
BYT_RT5651_IN1_IN2_MAP
,
BYT_RT5651_IN3_MAP
,
};
#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(7, 0))
...
...
@@ -62,6 +64,8 @@ static void log_quirks(struct device *dev)
dev_info
(
dev
,
"quirk IN1_MAP enabled"
);
if
(
BYT_RT5651_MAP
(
byt_rt5651_quirk
)
==
BYT_RT5651_IN2_MAP
)
dev_info
(
dev
,
"quirk IN2_MAP enabled"
);
if
(
BYT_RT5651_MAP
(
byt_rt5651_quirk
)
==
BYT_RT5651_IN3_MAP
)
dev_info
(
dev
,
"quirk IN3_MAP enabled"
);
if
(
byt_rt5651_quirk
&
BYT_RT5651_DMIC_EN
)
dev_info
(
dev
,
"quirk DMIC enabled"
);
if
(
byt_rt5651_quirk
&
BYT_RT5651_MCLK_EN
)
...
...
@@ -127,6 +131,7 @@ static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
SND_SOC_DAPM_MIC
(
"Headset Mic"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Internal Mic"
,
NULL
),
SND_SOC_DAPM_SPK
(
"Speaker"
,
NULL
),
SND_SOC_DAPM_LINE
(
"Line In"
,
NULL
),
SND_SOC_DAPM_SUPPLY
(
"Platform Clock"
,
SND_SOC_NOPM
,
0
,
0
,
platform_clock_control
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
...
...
@@ -138,6 +143,7 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
{
"Headset Mic"
,
NULL
,
"Platform Clock"
},
{
"Internal Mic"
,
NULL
,
"Platform Clock"
},
{
"Speaker"
,
NULL
,
"Platform Clock"
},
{
"Line In"
,
NULL
,
"Platform Clock"
},
{
"AIF1 Playback"
,
NULL
,
"ssp2 Tx"
},
{
"ssp2 Tx"
,
NULL
,
"codec_out0"
},
...
...
@@ -151,6 +157,9 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
{
"Headphone"
,
NULL
,
"HPOR"
},
{
"Speaker"
,
NULL
,
"LOUTL"
},
{
"Speaker"
,
NULL
,
"LOUTR"
},
{
"IN2P"
,
NULL
,
"Line In"
},
{
"IN2N"
,
NULL
,
"Line In"
},
};
static
const
struct
snd_soc_dapm_route
byt_rt5651_intmic_dmic_map
[]
=
{
...
...
@@ -171,11 +180,25 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
{
"IN2P"
,
NULL
,
"Internal Mic"
},
};
static
const
struct
snd_soc_dapm_route
byt_rt5651_intmic_in1_in2_map
[]
=
{
{
"Internal Mic"
,
NULL
,
"micbias1"
},
{
"IN1P"
,
NULL
,
"Internal Mic"
},
{
"IN2P"
,
NULL
,
"Internal Mic"
},
{
"IN3P"
,
NULL
,
"Headset Mic"
},
};
static
const
struct
snd_soc_dapm_route
byt_rt5651_intmic_in3_map
[]
=
{
{
"Internal Mic"
,
NULL
,
"micbias1"
},
{
"IN3P"
,
NULL
,
"Headset Mic"
},
{
"IN1P"
,
NULL
,
"Internal Mic"
},
};
static
const
struct
snd_kcontrol_new
byt_rt5651_controls
[]
=
{
SOC_DAPM_PIN_SWITCH
(
"Headphone"
),
SOC_DAPM_PIN_SWITCH
(
"Headset Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Internal Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Speaker"
),
SOC_DAPM_PIN_SWITCH
(
"Line In"
),
};
static
struct
snd_soc_jack_pin
bytcr_jack_pins
[]
=
{
...
...
@@ -247,8 +270,16 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Circuitco"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Minnowboard Max B3 PLATFORM"
),
},
.
driver_data
=
(
void
*
)(
BYT_RT5651_DMIC_MAP
|
BYT_RT5651_DMIC_EN
),
.
driver_data
=
(
void
*
)(
BYT_RT5651_IN3_MAP
),
},
{
.
callback
=
byt_rt5651_quirk_cb
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"ADI"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Minnowboard Turbot"
),
},
.
driver_data
=
(
void
*
)(
BYT_RT5651_MCLK_EN
|
BYT_RT5651_IN3_MAP
),
},
{
.
callback
=
byt_rt5651_quirk_cb
,
...
...
@@ -256,7 +287,8 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
DMI_MATCH
(
DMI_SYS_VENDOR
,
"KIANO"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"KIANO SlimNote 14.2"
),
},
.
driver_data
=
(
void
*
)(
BYT_RT5651_IN2_MAP
),
.
driver_data
=
(
void
*
)(
BYT_RT5651_MCLK_EN
|
BYT_RT5651_IN1_IN2_MAP
),
},
{}
};
...
...
@@ -281,6 +313,14 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
custom_map
=
byt_rt5651_intmic_in2_map
;
num_routes
=
ARRAY_SIZE
(
byt_rt5651_intmic_in2_map
);
break
;
case
BYT_RT5651_IN1_IN2_MAP
:
custom_map
=
byt_rt5651_intmic_in1_in2_map
;
num_routes
=
ARRAY_SIZE
(
byt_rt5651_intmic_in1_in2_map
);
break
;
case
BYT_RT5651_IN3_MAP
:
custom_map
=
byt_rt5651_intmic_in3_map
;
num_routes
=
ARRAY_SIZE
(
byt_rt5651_intmic_in3_map
);
break
;
default:
custom_map
=
byt_rt5651_intmic_dmic_map
;
num_routes
=
ARRAY_SIZE
(
byt_rt5651_intmic_dmic_map
);
...
...
@@ -469,7 +509,7 @@ static struct snd_soc_card byt_rt5651_card = {
.
fully_routed
=
true
,
};
static
char
byt_rt5651_codec_name
[
16
];
/* i2c-<HID>:00 with HID being 8 chars */
static
char
byt_rt5651_codec_name
[
SND_ACPI_I2C_ID_LEN
];
static
int
snd_byt_rt5651_mc_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -499,7 +539,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
}
/* fixup codec name based on HID */
i2c_name
=
snd_soc_acpi_find_name_from_hid
(
mach
->
id
);
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
byt_rt5651_codec_name
,
sizeof
(
byt_rt5651_codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
...
...
sound/soc/intel/boards/cht_bsw_rt5645.c
View file @
70fff743
...
...
@@ -49,7 +49,7 @@ struct cht_acpi_card {
struct
cht_mc_private
{
struct
snd_soc_jack
jack
;
struct
cht_acpi_card
*
acpi_card
;
char
codec_name
[
16
];
char
codec_name
[
SND_ACPI_I2C_ID_LEN
];
struct
clk
*
mclk
;
};
...
...
@@ -499,7 +499,7 @@ static struct cht_acpi_card snd_soc_cards[] = {
{
"10EC5650"
,
CODEC_TYPE_RT5650
,
&
snd_soc_card_chtrt5650
},
};
static
char
cht_rt5645_codec_name
[
16
];
/* i2c-<HID>:00 with HID being 8 chars */
static
char
cht_rt5645_codec_name
[
SND_ACPI_I2C_ID_LEN
];
static
char
cht_rt5645_codec_aif_name
[
12
];
/* = "rt5645-aif[1|2]" */
static
char
cht_rt5645_cpu_dai_name
[
10
];
/* = "ssp[0|2]-port" */
...
...
@@ -566,7 +566,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
}
/* fixup codec name based on HID */
i2c_name
=
snd_soc_acpi_find_name_from_hid
(
mach
->
id
);
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
cht_rt5645_codec_name
,
sizeof
(
cht_rt5645_codec_name
),
"%s%s"
,
"i2c-"
,
i2c_name
);
...
...
sound/soc/intel/boards/cht_bsw_rt5672.c
View file @
70fff743
...
...
@@ -35,7 +35,7 @@
struct
cht_mc_private
{
struct
snd_soc_jack
headset
;
char
codec_name
[
16
];
char
codec_name
[
SND_ACPI_I2C_ID_LEN
];
struct
clk
*
mclk
;
};
...
...
@@ -396,7 +396,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
/* fixup codec name based on HID */
if
(
mach
)
{
i2c_name
=
snd_soc_acpi_find_name_from_hid
(
mach
->
id
);
i2c_name
=
acpi_dev_get_first_match_name
(
mach
->
id
,
NULL
,
-
1
);
if
(
i2c_name
)
{
snprintf
(
drv
->
codec_name
,
sizeof
(
drv
->
codec_name
),
"i2c-%s"
,
i2c_name
);
...
...
sound/soc/intel/boards/haswell.c
View file @
70fff743
...
...
@@ -76,7 +76,7 @@ static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream,
}
/* set correct codec filter for DAI format and clock config */
snd_soc_
update_bits
(
rtd
->
codec
,
0x83
,
0xffff
,
0x8000
);
snd_soc_
component_update_bits
(
codec_dai
->
component
,
0x83
,
0xffff
,
0x8000
);
return
ret
;
}
...
...
sound/soc/intel/boards/kbl_rt5663_max98927.c
View file @
70fff743
...
...
@@ -28,6 +28,9 @@
#include "../../codecs/rt5663.h"
#include "../../codecs/hdac_hdmi.h"
#include "../skylake/skl.h"
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
#define KBL_MAXIM_CODEC_DAI "max98927-aif1"
...
...
@@ -48,6 +51,8 @@ struct kbl_hdmi_pcm {
struct
kbl_rt5663_private
{
struct
snd_soc_jack
kabylake_headset
;
struct
list_head
hdmi_pcm_list
;
struct
clk
*
mclk
;
struct
clk
*
sclk
;
};
enum
{
...
...
@@ -69,6 +74,61 @@ static const struct snd_kcontrol_new kabylake_controls[] = {
SOC_DAPM_PIN_SWITCH
(
"Right Spk"
),
};
static
int
platform_clock_control
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
kbl_rt5663_private
*
priv
=
snd_soc_card_get_drvdata
(
card
);
int
ret
=
0
;
/*
* MCLK/SCLK need to be ON early for a successful synchronization of
* codec internal clock. And the clocks are turned off during
* POST_PMD after the stream is stopped.
*/
switch
(
event
)
{
case
SND_SOC_DAPM_PRE_PMU
:
/* Enable MCLK */
ret
=
clk_set_rate
(
priv
->
mclk
,
24000000
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"Can't set rate for mclk, err: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
clk_prepare_enable
(
priv
->
mclk
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"Can't enable mclk, err: %d
\n
"
,
ret
);
return
ret
;
}
/* Enable SCLK */
ret
=
clk_set_rate
(
priv
->
sclk
,
3072000
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"Can't set rate for sclk, err: %d
\n
"
,
ret
);
clk_disable_unprepare
(
priv
->
mclk
);
return
ret
;
}
ret
=
clk_prepare_enable
(
priv
->
sclk
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"Can't enable sclk, err: %d
\n
"
,
ret
);
clk_disable_unprepare
(
priv
->
mclk
);
}
break
;
case
SND_SOC_DAPM_POST_PMD
:
clk_disable_unprepare
(
priv
->
mclk
);
clk_disable_unprepare
(
priv
->
sclk
);
break
;
default:
return
0
;
}
return
0
;
}
static
const
struct
snd_soc_dapm_widget
kabylake_widgets
[]
=
{
SND_SOC_DAPM_HP
(
"Headphone Jack"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Headset Mic"
,
NULL
),
...
...
@@ -78,11 +138,14 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
SND_SOC_DAPM_SPK
(
"HDMI1"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI2"
,
NULL
),
SND_SOC_DAPM_SPK
(
"HDMI3"
,
NULL
),
SND_SOC_DAPM_SUPPLY
(
"Platform Clock"
,
SND_SOC_NOPM
,
0
,
0
,
platform_clock_control
,
SND_SOC_DAPM_PRE_PMU
|
SND_SOC_DAPM_POST_PMD
),
};
static
const
struct
snd_soc_dapm_route
kabylake_map
[]
=
{
/* HP jack connectors - unknown if we have jack detection */
{
"Headphone Jack"
,
NULL
,
"Platform Clock"
},
{
"Headphone Jack"
,
NULL
,
"HPOL"
},
{
"Headphone Jack"
,
NULL
,
"HPOR"
},
...
...
@@ -91,6 +154,7 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
{
"Right Spk"
,
NULL
,
"Right BE_OUT"
},
/* other jacks */
{
"Headset Mic"
,
NULL
,
"Platform Clock"
},
{
"IN1P"
,
NULL
,
"Headset Mic"
},
{
"IN1N"
,
NULL
,
"Headset Mic"
},
{
"DMic"
,
NULL
,
"SoC DMIC"
},
...
...
@@ -225,7 +289,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
}
jack
=
&
ctx
->
kabylake_headset
;
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_0
,
KEY_
MEDIA
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_0
,
KEY_
PLAYPAUSE
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_1
,
KEY_VOICECOMMAND
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_2
,
KEY_VOLUMEUP
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_3
,
KEY_VOLUMEDOWN
);
...
...
@@ -901,6 +965,7 @@ static int kabylake_audio_probe(struct platform_device *pdev)
{
struct
kbl_rt5663_private
*
ctx
;
struct
skl_machine_pdata
*
pdata
;
int
ret
;
ctx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
ctx
),
GFP_ATOMIC
);
if
(
!
ctx
)
...
...
@@ -919,6 +984,34 @@ static int kabylake_audio_probe(struct platform_device *pdev)
dmic_constraints
=
pdata
->
dmic_num
==
2
?
&
constraints_dmic_2ch
:
&
constraints_dmic_channels
;
ctx
->
mclk
=
devm_clk_get
(
&
pdev
->
dev
,
"ssp1_mclk"
);
if
(
IS_ERR
(
ctx
->
mclk
))
{
ret
=
PTR_ERR
(
ctx
->
mclk
);
if
(
ret
==
-
ENOENT
)
{
dev_info
(
&
pdev
->
dev
,
"Failed to get ssp1_sclk, defer probe
\n
"
);
return
-
EPROBE_DEFER
;
}
dev_err
(
&
pdev
->
dev
,
"Failed to get ssp1_mclk with err:%d
\n
"
,
ret
);
return
ret
;
}
ctx
->
sclk
=
devm_clk_get
(
&
pdev
->
dev
,
"ssp1_sclk"
);
if
(
IS_ERR
(
ctx
->
sclk
))
{
ret
=
PTR_ERR
(
ctx
->
sclk
);
if
(
ret
==
-
ENOENT
)
{
dev_info
(
&
pdev
->
dev
,
"Failed to get ssp1_sclk, defer probe
\n
"
);
return
-
EPROBE_DEFER
;
}
dev_err
(
&
pdev
->
dev
,
"Failed to get ssp1_sclk with err:%d
\n
"
,
ret
);
return
ret
;
}
return
devm_snd_soc_register_card
(
&
pdev
->
dev
,
kabylake_audio_card
);
}
...
...
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
View file @
70fff743
...
...
@@ -195,7 +195,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
}
jack
=
&
ctx
->
kabylake_headset
;
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_0
,
KEY_
MEDIA
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_0
,
KEY_
PLAYPAUSE
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_1
,
KEY_VOICECOMMAND
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_2
,
KEY_VOLUMEUP
);
snd_jack_set_key
(
jack
->
jack
,
SND_JACK_BTN_3
,
KEY_VOLUMEDOWN
);
...
...
sound/soc/intel/boards/mfld_machine.c
deleted
100644 → 0
View file @
5b813eca
/*
* mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
*
* Copyright (C) 2010 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include "../codecs/sn95031.h"
#define MID_MONO 1
#define MID_STEREO 2
#define MID_MAX_CAP 5
#define MFLD_JACK_INSERT 0x04
enum
soc_mic_bias_zones
{
MFLD_MV_START
=
0
,
/* mic bias volutage range for Headphones*/
MFLD_MV_HP
=
400
,
/* mic bias volutage range for American Headset*/
MFLD_MV_AM_HS
=
650
,
/* mic bias volutage range for Headset*/
MFLD_MV_HS
=
2000
,
MFLD_MV_UNDEFINED
,
};
static
unsigned
int
hs_switch
;
static
unsigned
int
lo_dac
;
static
struct
snd_soc_codec
*
mfld_codec
;
struct
mfld_mc_private
{
void
__iomem
*
int_base
;
u8
interrupt_status
;
};
struct
snd_soc_jack
mfld_jack
;
/*Headset jack detection DAPM pins */
static
struct
snd_soc_jack_pin
mfld_jack_pins
[]
=
{
{
.
pin
=
"Headphones"
,
.
mask
=
SND_JACK_HEADPHONE
,
},
{
.
pin
=
"AMIC1"
,
.
mask
=
SND_JACK_MICROPHONE
,
},
};
/* jack detection voltage zones */
static
struct
snd_soc_jack_zone
mfld_zones
[]
=
{
{
MFLD_MV_START
,
MFLD_MV_AM_HS
,
SND_JACK_HEADPHONE
},
{
MFLD_MV_AM_HS
,
MFLD_MV_HS
,
SND_JACK_HEADSET
},
};
/* sound card controls */
static
const
char
*
const
headset_switch_text
[]
=
{
"Earpiece"
,
"Headset"
};
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
);
static
const
struct
soc_enum
lo_enum
=
SOC_ENUM_SINGLE_EXT
(
4
,
lo_text
);
static
int
headset_get_switch
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
hs_switch
;
return
0
;
}
static
int
headset_set_switch
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_card
*
card
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_context
*
dapm
=
&
card
->
dapm
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
==
hs_switch
)
return
0
;
snd_soc_dapm_mutex_lock
(
dapm
);
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
])
{
pr_debug
(
"hs_set HS path
\n
"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"Headphones"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"EPOUT"
);
}
else
{
pr_debug
(
"hs_set EP path
\n
"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"Headphones"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"EPOUT"
);
}
snd_soc_dapm_sync_unlocked
(
dapm
);
snd_soc_dapm_mutex_unlock
(
dapm
);
hs_switch
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
return
0
;
}
static
void
lo_enable_out_pins
(
struct
snd_soc_dapm_context
*
dapm
)
{
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"IHFOUTL"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"IHFOUTR"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"LINEOUTL"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"LINEOUTR"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"VIB1OUT"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"VIB2OUT"
);
if
(
hs_switch
)
{
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"Headphones"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"EPOUT"
);
}
else
{
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"Headphones"
);
snd_soc_dapm_enable_pin_unlocked
(
dapm
,
"EPOUT"
);
}
}
static
int
lo_get_switch
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
lo_dac
;
return
0
;
}
static
int
lo_set_switch
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_card
*
card
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_context
*
dapm
=
&
card
->
dapm
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
==
lo_dac
)
return
0
;
snd_soc_dapm_mutex_lock
(
dapm
);
/* we dont want to work with last state of lineout so just enable all
* pins and then disable pins not required
*/
lo_enable_out_pins
(
dapm
);
switch
(
ucontrol
->
value
.
enumerated
.
item
[
0
])
{
case
0
:
pr_debug
(
"set vibra path
\n
"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"VIB1OUT"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"VIB2OUT"
);
snd_soc_update_bits
(
mfld_codec
,
SN95031_LOCTL
,
0x66
,
0
);
break
;
case
1
:
pr_debug
(
"set hs path
\n
"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"Headphones"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"EPOUT"
);
snd_soc_update_bits
(
mfld_codec
,
SN95031_LOCTL
,
0x66
,
0x22
);
break
;
case
2
:
pr_debug
(
"set spkr path
\n
"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"IHFOUTL"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"IHFOUTR"
);
snd_soc_update_bits
(
mfld_codec
,
SN95031_LOCTL
,
0x66
,
0x44
);
break
;
case
3
:
pr_debug
(
"set null path
\n
"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"LINEOUTL"
);
snd_soc_dapm_disable_pin_unlocked
(
dapm
,
"LINEOUTR"
);
snd_soc_update_bits
(
mfld_codec
,
SN95031_LOCTL
,
0x66
,
0x66
);
break
;
}
snd_soc_dapm_sync_unlocked
(
dapm
);
snd_soc_dapm_mutex_unlock
(
dapm
);
lo_dac
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
return
0
;
}
static
const
struct
snd_kcontrol_new
mfld_snd_controls
[]
=
{
SOC_ENUM_EXT
(
"Playback Switch"
,
headset_enum
,
headset_get_switch
,
headset_set_switch
),
SOC_ENUM_EXT
(
"Lineout Mux"
,
lo_enum
,
lo_get_switch
,
lo_set_switch
),
};
static
const
struct
snd_soc_dapm_widget
mfld_widgets
[]
=
{
SND_SOC_DAPM_HP
(
"Headphones"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Mic"
,
NULL
),
};
static
const
struct
snd_soc_dapm_route
mfld_map
[]
=
{
{
"Headphones"
,
NULL
,
"HPOUTR"
},
{
"Headphones"
,
NULL
,
"HPOUTL"
},
{
"Mic"
,
NULL
,
"AMIC1"
},
};
static
void
mfld_jack_check
(
unsigned
int
intr_status
)
{
struct
mfld_jack_data
jack_data
;
if
(
!
mfld_codec
)
return
;
jack_data
.
mfld_jack
=
&
mfld_jack
;
jack_data
.
intr_id
=
intr_status
;
sn95031_jack_detection
(
mfld_codec
,
&
jack_data
);
/* TODO: add american headset detection post gpiolib support */
}
static
int
mfld_init
(
struct
snd_soc_pcm_runtime
*
runtime
)
{
struct
snd_soc_dapm_context
*
dapm
=
&
runtime
->
card
->
dapm
;
int
ret_val
;
/* default is earpiece pin, userspace sets it explcitly */
snd_soc_dapm_disable_pin
(
dapm
,
"Headphones"
);
/* default is lineout NC, userspace sets it explcitly */
snd_soc_dapm_disable_pin
(
dapm
,
"LINEOUTL"
);
snd_soc_dapm_disable_pin
(
dapm
,
"LINEOUTR"
);
lo_dac
=
3
;
hs_switch
=
0
;
/* we dont use linein in this so set to NC */
snd_soc_dapm_disable_pin
(
dapm
,
"LINEINL"
);
snd_soc_dapm_disable_pin
(
dapm
,
"LINEINR"
);
/* Headset and button jack detection */
ret_val
=
snd_soc_card_jack_new
(
runtime
->
card
,
"Intel(R) MID Audio Jack"
,
SND_JACK_HEADSET
|
SND_JACK_BTN_0
|
SND_JACK_BTN_1
,
&
mfld_jack
,
mfld_jack_pins
,
ARRAY_SIZE
(
mfld_jack_pins
));
if
(
ret_val
)
{
pr_err
(
"jack creation failed
\n
"
);
return
ret_val
;
}
ret_val
=
snd_soc_jack_add_zones
(
&
mfld_jack
,
ARRAY_SIZE
(
mfld_zones
),
mfld_zones
);
if
(
ret_val
)
{
pr_err
(
"adding jack zones failed
\n
"
);
return
ret_val
;
}
mfld_codec
=
runtime
->
codec
;
/* we want to check if anything is inserted at boot,
* so send a fake event to codec and it will read adc
* to find if anything is there or not */
mfld_jack_check
(
MFLD_JACK_INSERT
);
return
ret_val
;
}
static
struct
snd_soc_dai_link
mfld_msic_dailink
[]
=
{
{
.
name
=
"Medfield Headset"
,
.
stream_name
=
"Headset"
,
.
cpu_dai_name
=
"Headset-cpu-dai"
,
.
codec_dai_name
=
"SN95031 Headset"
,
.
codec_name
=
"sn95031"
,
.
platform_name
=
"sst-platform"
,
.
init
=
mfld_init
,
},
{
.
name
=
"Medfield Speaker"
,
.
stream_name
=
"Speaker"
,
.
cpu_dai_name
=
"Speaker-cpu-dai"
,
.
codec_dai_name
=
"SN95031 Speaker"
,
.
codec_name
=
"sn95031"
,
.
platform_name
=
"sst-platform"
,
.
init
=
NULL
,
},
{
.
name
=
"Medfield Vibra"
,
.
stream_name
=
"Vibra1"
,
.
cpu_dai_name
=
"Vibra1-cpu-dai"
,
.
codec_dai_name
=
"SN95031 Vibra1"
,
.
codec_name
=
"sn95031"
,
.
platform_name
=
"sst-platform"
,
.
init
=
NULL
,
},
{
.
name
=
"Medfield Haptics"
,
.
stream_name
=
"Vibra2"
,
.
cpu_dai_name
=
"Vibra2-cpu-dai"
,
.
codec_dai_name
=
"SN95031 Vibra2"
,
.
codec_name
=
"sn95031"
,
.
platform_name
=
"sst-platform"
,
.
init
=
NULL
,
},
{
.
name
=
"Medfield Compress"
,
.
stream_name
=
"Speaker"
,
.
cpu_dai_name
=
"Compress-cpu-dai"
,
.
codec_dai_name
=
"SN95031 Speaker"
,
.
codec_name
=
"sn95031"
,
.
platform_name
=
"sst-platform"
,
.
init
=
NULL
,
},
};
/* SoC card */
static
struct
snd_soc_card
snd_soc_card_mfld
=
{
.
name
=
"medfield_audio"
,
.
owner
=
THIS_MODULE
,
.
dai_link
=
mfld_msic_dailink
,
.
num_links
=
ARRAY_SIZE
(
mfld_msic_dailink
),
.
controls
=
mfld_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
mfld_snd_controls
),
.
dapm_widgets
=
mfld_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
mfld_widgets
),
.
dapm_routes
=
mfld_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
mfld_map
),
};
static
irqreturn_t
snd_mfld_jack_intr_handler
(
int
irq
,
void
*
dev
)
{
struct
mfld_mc_private
*
mc_private
=
(
struct
mfld_mc_private
*
)
dev
;
memcpy_fromio
(
&
mc_private
->
interrupt_status
,
((
void
*
)(
mc_private
->
int_base
)),
sizeof
(
u8
));
return
IRQ_WAKE_THREAD
;
}
static
irqreturn_t
snd_mfld_jack_detection
(
int
irq
,
void
*
data
)
{
struct
mfld_mc_private
*
mc_drv_ctx
=
(
struct
mfld_mc_private
*
)
data
;
mfld_jack_check
(
mc_drv_ctx
->
interrupt_status
);
return
IRQ_HANDLED
;
}
static
int
snd_mfld_mc_probe
(
struct
platform_device
*
pdev
)
{
int
ret_val
=
0
,
irq
;
struct
mfld_mc_private
*
mc_drv_ctx
;
struct
resource
*
irq_mem
;
pr_debug
(
"snd_mfld_mc_probe called
\n
"
);
/* retrive the irq number */
irq
=
platform_get_irq
(
pdev
,
0
);
/* audio interrupt base of SRAM location where
* interrupts are stored by System FW */
mc_drv_ctx
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
mc_drv_ctx
),
GFP_ATOMIC
);
if
(
!
mc_drv_ctx
)
return
-
ENOMEM
;
irq_mem
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"IRQ_BASE"
);
if
(
!
irq_mem
)
{
pr_err
(
"no mem resource given
\n
"
);
return
-
ENODEV
;
}
mc_drv_ctx
->
int_base
=
devm_ioremap_nocache
(
&
pdev
->
dev
,
irq_mem
->
start
,
resource_size
(
irq_mem
));
if
(
!
mc_drv_ctx
->
int_base
)
{
pr_err
(
"Mapping of cache failed
\n
"
);
return
-
ENOMEM
;
}
/* register for interrupt */
ret_val
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
irq
,
snd_mfld_jack_intr_handler
,
snd_mfld_jack_detection
,
IRQF_SHARED
,
pdev
->
dev
.
driver
->
name
,
mc_drv_ctx
);
if
(
ret_val
)
{
pr_err
(
"cannot register IRQ
\n
"
);
return
ret_val
;
}
/* register the soc card */
snd_soc_card_mfld
.
dev
=
&
pdev
->
dev
;
ret_val
=
devm_snd_soc_register_card
(
&
pdev
->
dev
,
&
snd_soc_card_mfld
);
if
(
ret_val
)
{
pr_debug
(
"snd_soc_register_card failed %d
\n
"
,
ret_val
);
return
ret_val
;
}
platform_set_drvdata
(
pdev
,
mc_drv_ctx
);
pr_debug
(
"successfully exited probe
\n
"
);
return
0
;
}
static
struct
platform_driver
snd_mfld_mc_driver
=
{
.
driver
=
{
.
name
=
"msic_audio"
,
},
.
probe
=
snd_mfld_mc_probe
,
};
module_platform_driver
(
snd_mfld_mc_driver
);
MODULE_DESCRIPTION
(
"ASoC Intel(R) MID Machine driver"
);
MODULE_AUTHOR
(
"Vinod Koul <vinod.koul@intel.com>"
);
MODULE_AUTHOR
(
"Harsha Priya <priya.harsha@intel.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:msic-audio"
);
sound/soc/intel/common/sst-dsp.c
View file @
70fff743
...
...
@@ -269,7 +269,7 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
*/
timeout
=
jiffies
+
msecs_to_jiffies
(
time
);
while
(((
sst_dsp_shim_read_unlocked
(
ctx
,
offset
)
&
mask
)
!=
target
)
while
(((
(
reg
=
sst_dsp_shim_read_unlocked
(
ctx
,
offset
)
)
&
mask
)
!=
target
)
&&
time_before
(
jiffies
,
timeout
))
{
k
++
;
if
(
k
>
10
)
...
...
@@ -278,8 +278,6 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
usleep_range
(
s
,
2
*
s
);
}
reg
=
sst_dsp_shim_read_unlocked
(
ctx
,
offset
);
if
((
reg
&
mask
)
==
target
)
{
dev_dbg
(
ctx
->
dev
,
"FW Poll Status: reg=%#x %s successful
\n
"
,
reg
,
operation
);
...
...
sound/soc/intel/skylake/Makefile
View file @
70fff743
...
...
@@ -14,3 +14,8 @@ snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \
skl-sst-utils.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE)
+=
snd-soc-skl-ipc.o
#Skylake Clock device support
snd-soc-skl-ssp-clk-objs
:=
skl-ssp-clk.o
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK)
+=
snd-soc-skl-ssp-clk.o
sound/soc/intel/skylake/bxt-sst.c
View file @
70fff743
...
...
@@ -595,7 +595,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
INIT_DELAYED_WORK
(
&
skl
->
d0i3
.
work
,
bxt_set_dsp_D0i3
);
skl
->
d0i3
.
state
=
SKL_DSP_D0I3_NONE
;
return
0
;
return
skl_dsp_acquire_irq
(
sst
)
;
}
EXPORT_SYMBOL_GPL
(
bxt_sst_dsp_init
);
...
...
sound/soc/intel/skylake/cnl-sst.c
View file @
70fff743
...
...
@@ -458,7 +458,7 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
cnl
->
boot_complete
=
false
;
init_waitqueue_head
(
&
cnl
->
boot_wait
);
return
0
;
return
skl_dsp_acquire_irq
(
sst
)
;
}
EXPORT_SYMBOL_GPL
(
cnl_sst_dsp_init
);
...
...
sound/soc/intel/skylake/skl-i2s.h
0 → 100644
View file @
70fff743
/*
* skl-i2s.h - i2s blob mapping
*
* Copyright (C) 2017 Intel Corp
* Author: Subhransu S. Prusty < subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef __SOUND_SOC_SKL_I2S_H
#define __SOUND_SOC_SKL_I2S_H
#define SKL_I2S_MAX_TIME_SLOTS 8
#define SKL_MCLK_DIV_CLK_SRC_MASK GENMASK(17, 16)
#define SKL_MNDSS_DIV_CLK_SRC_MASK GENMASK(21, 20)
#define SKL_SHIFT(x) (ffs(x) - 1)
#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0)
#define is_legacy_blob(x) (x.signature != 0xEE)
#define ext_to_legacy_blob(i2s_config_blob_ext) \
((struct skl_i2s_config_blob_legacy *) i2s_config_blob_ext)
#define get_clk_src(mclk, mask) \
((mclk.mdivctrl & mask) >> SKL_SHIFT(mask))
struct
skl_i2s_config
{
u32
ssc0
;
u32
ssc1
;
u32
sscto
;
u32
sspsp
;
u32
sstsa
;
u32
ssrsa
;
u32
ssc2
;
u32
sspsp2
;
u32
ssc3
;
u32
ssioc
;
}
__packed
;
struct
skl_i2s_config_mclk
{
u32
mdivctrl
;
u32
mdivr
;
};
struct
skl_i2s_config_mclk_ext
{
u32
mdivctrl
;
u32
mdivr_count
;
u32
mdivr
[
0
];
}
__packed
;
struct
skl_i2s_config_blob_signature
{
u32
minor_ver
:
8
;
u32
major_ver
:
8
;
u32
resvdz
:
8
;
u32
signature
:
8
;
}
__packed
;
struct
skl_i2s_config_blob_header
{
struct
skl_i2s_config_blob_signature
sig
;
u32
size
;
};
/**
* struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway
* configuration legacy blob
*
* @gtw_attr: Gateway attribute for the I2S Gateway
* @tdm_ts_group: TDM slot mapping against channels in the Gateway.
* @i2s_cfg: I2S HW registers
* @mclk: MCLK clock source and divider values
*/
struct
skl_i2s_config_blob_legacy
{
u32
gtw_attr
;
u32
tdm_ts_group
[
SKL_I2S_MAX_TIME_SLOTS
];
struct
skl_i2s_config
i2s_cfg
;
struct
skl_i2s_config_mclk
mclk
;
};
struct
skl_i2s_config_blob_ext
{
u32
gtw_attr
;
struct
skl_i2s_config_blob_header
hdr
;
u32
tdm_ts_group
[
SKL_I2S_MAX_TIME_SLOTS
];
struct
skl_i2s_config
i2s_cfg
;
struct
skl_i2s_config_mclk_ext
mclk
;
}
__packed
;
#endif
/* __SOUND_SOC_SKL_I2S_H */
sound/soc/intel/skylake/skl-messages.c
View file @
70fff743
...
...
@@ -55,6 +55,19 @@ static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
return
0
;
}
#define SKL_ASTATE_PARAM_ID 4
void
skl_dsp_set_astate_cfg
(
struct
skl_sst
*
ctx
,
u32
cnt
,
void
*
data
)
{
struct
skl_ipc_large_config_msg
msg
=
{
0
};
msg
.
large_param_id
=
SKL_ASTATE_PARAM_ID
;
msg
.
param_data_size
=
(
cnt
*
sizeof
(
struct
skl_astate_param
)
+
sizeof
(
cnt
));
skl_ipc_set_large_config
(
&
ctx
->
ipc
,
&
msg
,
data
);
}
#define NOTIFICATION_PARAM_ID 3
#define NOTIFICATION_MASK 0xf
...
...
@@ -404,11 +417,20 @@ int skl_resume_dsp(struct skl *skl)
if
(
skl
->
skl_sst
->
is_first_boot
==
true
)
return
0
;
/* disable dynamic clock gating during fw and lib download */
ctx
->
enable_miscbdcge
(
ctx
->
dev
,
false
);
ret
=
skl_dsp_wake
(
ctx
->
dsp
);
ctx
->
enable_miscbdcge
(
ctx
->
dev
,
true
);
if
(
ret
<
0
)
return
ret
;
skl_dsp_enable_notification
(
skl
->
skl_sst
,
false
);
if
(
skl
->
cfg
.
astate_cfg
!=
NULL
)
{
skl_dsp_set_astate_cfg
(
skl
->
skl_sst
,
skl
->
cfg
.
astate_cfg
->
count
,
skl
->
cfg
.
astate_cfg
);
}
return
ret
;
}
...
...
@@ -653,6 +675,7 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps,
kfree
(
dma_ctrl
);
return
err
;
}
EXPORT_SYMBOL_GPL
(
skl_dsp_set_dma_control
);
static
void
skl_setup_out_format
(
struct
skl_sst
*
ctx
,
struct
skl_module_cfg
*
mconfig
,
...
...
sound/soc/intel/skylake/skl-nhlt.c
View file @
70fff743
...
...
@@ -19,6 +19,7 @@
*/
#include <linux/pci.h>
#include "skl.h"
#include "skl-i2s.h"
#define NHLT_ACPI_HEADER_SIG "NHLT"
...
...
@@ -27,6 +28,7 @@ static guid_t osc_guid =
GUID_INIT
(
0xA69F886E
,
0x6CEB
,
0x4594
,
0xA4
,
0x1F
,
0x7B
,
0x5D
,
0xCE
,
0x24
,
0xC5
,
0x53
);
struct
nhlt_acpi_table
*
skl_nhlt_init
(
struct
device
*
dev
)
{
acpi_handle
handle
;
...
...
@@ -277,3 +279,173 @@ void skl_nhlt_remove_sysfs(struct skl *skl)
sysfs_remove_file
(
&
dev
->
kobj
,
&
dev_attr_platform_id
.
attr
);
}
/*
* Queries NHLT for all the fmt configuration for a particular endpoint and
* stores all possible rates supported in a rate table for the corresponding
* sclk/sclkfs.
*/
static
void
skl_get_ssp_clks
(
struct
skl
*
skl
,
struct
skl_ssp_clk
*
ssp_clks
,
struct
nhlt_fmt
*
fmt
,
u8
id
)
{
struct
skl_i2s_config_blob_ext
*
i2s_config_ext
;
struct
skl_i2s_config_blob_legacy
*
i2s_config
;
struct
skl_clk_parent_src
*
parent
;
struct
skl_ssp_clk
*
sclk
,
*
sclkfs
;
struct
nhlt_fmt_cfg
*
fmt_cfg
;
struct
wav_fmt_ext
*
wav_fmt
;
unsigned
long
rate
=
0
;
bool
present
=
false
;
int
rate_index
=
0
;
u16
channels
,
bps
;
u8
clk_src
;
int
i
,
j
;
u32
fs
;
sclk
=
&
ssp_clks
[
SKL_SCLK_OFS
];
sclkfs
=
&
ssp_clks
[
SKL_SCLKFS_OFS
];
if
(
fmt
->
fmt_count
==
0
)
return
;
for
(
i
=
0
;
i
<
fmt
->
fmt_count
;
i
++
)
{
fmt_cfg
=
&
fmt
->
fmt_config
[
i
];
wav_fmt
=
&
fmt_cfg
->
fmt_ext
;
channels
=
wav_fmt
->
fmt
.
channels
;
bps
=
wav_fmt
->
fmt
.
bits_per_sample
;
fs
=
wav_fmt
->
fmt
.
samples_per_sec
;
/*
* In case of TDM configuration on a ssp, there can
* be more than one blob in which channel masks are
* different for each usecase for a specific rate and bps.
* But the sclk rate will be generated for the total
* number of channels used for that endpoint.
*
* So for the given fs and bps, choose blob which has
* the superset of all channels for that endpoint and
* derive the rate.
*/
for
(
j
=
i
;
j
<
fmt
->
fmt_count
;
j
++
)
{
fmt_cfg
=
&
fmt
->
fmt_config
[
j
];
wav_fmt
=
&
fmt_cfg
->
fmt_ext
;
if
((
fs
==
wav_fmt
->
fmt
.
samples_per_sec
)
&&
(
bps
==
wav_fmt
->
fmt
.
bits_per_sample
))
channels
=
max_t
(
u16
,
channels
,
wav_fmt
->
fmt
.
channels
);
}
rate
=
channels
*
bps
*
fs
;
/* check if the rate is added already to the given SSP's sclk */
for
(
j
=
0
;
(
j
<
SKL_MAX_CLK_RATES
)
&&
(
sclk
[
id
].
rate_cfg
[
j
].
rate
!=
0
);
j
++
)
{
if
(
sclk
[
id
].
rate_cfg
[
j
].
rate
==
rate
)
{
present
=
true
;
break
;
}
}
/* Fill rate and parent for sclk/sclkfs */
if
(
!
present
)
{
i2s_config_ext
=
(
struct
skl_i2s_config_blob_ext
*
)
fmt
->
fmt_config
[
0
].
config
.
caps
;
/* MCLK Divider Source Select */
if
(
is_legacy_blob
(
i2s_config_ext
->
hdr
.
sig
))
{
i2s_config
=
ext_to_legacy_blob
(
i2s_config_ext
);
clk_src
=
get_clk_src
(
i2s_config
->
mclk
,
SKL_MNDSS_DIV_CLK_SRC_MASK
);
}
else
{
clk_src
=
get_clk_src
(
i2s_config_ext
->
mclk
,
SKL_MNDSS_DIV_CLK_SRC_MASK
);
}
parent
=
skl_get_parent_clk
(
clk_src
);
/*
* Do not copy the config data if there is no parent
* clock available for this clock source select
*/
if
(
!
parent
)
continue
;
sclk
[
id
].
rate_cfg
[
rate_index
].
rate
=
rate
;
sclk
[
id
].
rate_cfg
[
rate_index
].
config
=
fmt_cfg
;
sclkfs
[
id
].
rate_cfg
[
rate_index
].
rate
=
rate
;
sclkfs
[
id
].
rate_cfg
[
rate_index
].
config
=
fmt_cfg
;
sclk
[
id
].
parent_name
=
parent
->
name
;
sclkfs
[
id
].
parent_name
=
parent
->
name
;
rate_index
++
;
}
}
}
static
void
skl_get_mclk
(
struct
skl
*
skl
,
struct
skl_ssp_clk
*
mclk
,
struct
nhlt_fmt
*
fmt
,
u8
id
)
{
struct
skl_i2s_config_blob_ext
*
i2s_config_ext
;
struct
skl_i2s_config_blob_legacy
*
i2s_config
;
struct
nhlt_specific_cfg
*
fmt_cfg
;
struct
skl_clk_parent_src
*
parent
;
u32
clkdiv
,
div_ratio
;
u8
clk_src
;
fmt_cfg
=
&
fmt
->
fmt_config
[
0
].
config
;
i2s_config_ext
=
(
struct
skl_i2s_config_blob_ext
*
)
fmt_cfg
->
caps
;
/* MCLK Divider Source Select and divider */
if
(
is_legacy_blob
(
i2s_config_ext
->
hdr
.
sig
))
{
i2s_config
=
ext_to_legacy_blob
(
i2s_config_ext
);
clk_src
=
get_clk_src
(
i2s_config
->
mclk
,
SKL_MCLK_DIV_CLK_SRC_MASK
);
clkdiv
=
i2s_config
->
mclk
.
mdivr
&
SKL_MCLK_DIV_RATIO_MASK
;
}
else
{
clk_src
=
get_clk_src
(
i2s_config_ext
->
mclk
,
SKL_MCLK_DIV_CLK_SRC_MASK
);
clkdiv
=
i2s_config_ext
->
mclk
.
mdivr
[
0
]
&
SKL_MCLK_DIV_RATIO_MASK
;
}
/* bypass divider */
div_ratio
=
1
;
if
(
clkdiv
!=
SKL_MCLK_DIV_RATIO_MASK
)
/* Divider is 2 + clkdiv */
div_ratio
=
clkdiv
+
2
;
/* Calculate MCLK rate from source using div value */
parent
=
skl_get_parent_clk
(
clk_src
);
if
(
!
parent
)
return
;
mclk
[
id
].
rate_cfg
[
0
].
rate
=
parent
->
rate
/
div_ratio
;
mclk
[
id
].
rate_cfg
[
0
].
config
=
&
fmt
->
fmt_config
[
0
];
mclk
[
id
].
parent_name
=
parent
->
name
;
}
void
skl_get_clks
(
struct
skl
*
skl
,
struct
skl_ssp_clk
*
ssp_clks
)
{
struct
nhlt_acpi_table
*
nhlt
=
(
struct
nhlt_acpi_table
*
)
skl
->
nhlt
;
struct
nhlt_endpoint
*
epnt
;
struct
nhlt_fmt
*
fmt
;
int
i
;
u8
id
;
epnt
=
(
struct
nhlt_endpoint
*
)
nhlt
->
desc
;
for
(
i
=
0
;
i
<
nhlt
->
endpoint_count
;
i
++
)
{
if
(
epnt
->
linktype
==
NHLT_LINK_SSP
)
{
id
=
epnt
->
virtual_bus_id
;
fmt
=
(
struct
nhlt_fmt
*
)(
epnt
->
config
.
caps
+
epnt
->
config
.
size
);
skl_get_ssp_clks
(
skl
,
ssp_clks
,
fmt
,
id
);
skl_get_mclk
(
skl
,
ssp_clks
,
fmt
,
id
);
}
epnt
=
(
struct
nhlt_endpoint
*
)((
u8
*
)
epnt
+
epnt
->
length
);
}
}
sound/soc/intel/skylake/skl-pcm.c
View file @
70fff743
...
...
@@ -537,7 +537,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
snd_soc_dai_set_dma_data
(
dai
,
substream
,
(
void
*
)
link_dev
);
link
=
snd_hdac_ext_bus_get_link
(
ebus
,
rtd
->
codec
->
component
.
name
);
link
=
snd_hdac_ext_bus_get_link
(
ebus
,
codec_dai
->
component
->
name
);
if
(
!
link
)
return
-
EINVAL
;
...
...
@@ -620,7 +620,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
link_dev
->
link_prepared
=
0
;
link
=
snd_hdac_ext_bus_get_link
(
ebus
,
rtd
->
codec
->
component
.
name
);
link
=
snd_hdac_ext_bus_get_link
(
ebus
,
rtd
->
codec
_dai
->
component
->
name
);
if
(
!
link
)
return
-
EINVAL
;
...
...
@@ -1343,7 +1343,11 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
return
-
EIO
;
}
/* disable dynamic clock gating during fw and lib download */
skl
->
skl_sst
->
enable_miscbdcge
(
platform
->
dev
,
false
);
ret
=
ops
->
init_fw
(
platform
->
dev
,
skl
->
skl_sst
);
skl
->
skl_sst
->
enable_miscbdcge
(
platform
->
dev
,
true
);
if
(
ret
<
0
)
{
dev_err
(
platform
->
dev
,
"Failed to boot first fw: %d
\n
"
,
ret
);
return
ret
;
...
...
@@ -1351,6 +1355,12 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform)
skl_populate_modules
(
skl
);
skl
->
skl_sst
->
update_d0i3c
=
skl_update_d0i3c
;
skl_dsp_enable_notification
(
skl
->
skl_sst
,
false
);
if
(
skl
->
cfg
.
astate_cfg
!=
NULL
)
{
skl_dsp_set_astate_cfg
(
skl
->
skl_sst
,
skl
->
cfg
.
astate_cfg
->
count
,
skl
->
cfg
.
astate_cfg
);
}
}
pm_runtime_mark_last_busy
(
platform
->
dev
);
pm_runtime_put_autosuspend
(
platform
->
dev
);
...
...
sound/soc/intel/skylake/skl-ssp-clk.c
0 → 100644
View file @
70fff743
// SPDX-License-Identifier: GPL-2.0
// Copyright(c) 2015-17 Intel Corporation
/*
* skl-ssp-clk.c - ASoC skylake ssp clock driver
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include "skl.h"
#include "skl-ssp-clk.h"
#include "skl-topology.h"
#define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw)
struct
skl_clk_parent
{
struct
clk_hw
*
hw
;
struct
clk_lookup
*
lookup
;
};
struct
skl_clk
{
struct
clk_hw
hw
;
struct
clk_lookup
*
lookup
;
unsigned
long
rate
;
struct
skl_clk_pdata
*
pdata
;
u32
id
;
};
struct
skl_clk_data
{
struct
skl_clk_parent
parent
[
SKL_MAX_CLK_SRC
];
struct
skl_clk
*
clk
[
SKL_MAX_CLK_CNT
];
u8
avail_clk_cnt
;
};
static
int
skl_get_clk_type
(
u32
index
)
{
switch
(
index
)
{
case
0
...
(
SKL_SCLK_OFS
-
1
):
return
SKL_MCLK
;
case
SKL_SCLK_OFS
...
(
SKL_SCLKFS_OFS
-
1
):
return
SKL_SCLK
;
case
SKL_SCLKFS_OFS
...
(
SKL_MAX_CLK_CNT
-
1
):
return
SKL_SCLK_FS
;
default:
return
-
EINVAL
;
}
}
static
int
skl_get_vbus_id
(
u32
index
,
u8
clk_type
)
{
switch
(
clk_type
)
{
case
SKL_MCLK
:
return
index
;
case
SKL_SCLK
:
return
index
-
SKL_SCLK_OFS
;
case
SKL_SCLK_FS
:
return
index
-
SKL_SCLKFS_OFS
;
default:
return
-
EINVAL
;
}
}
static
void
skl_fill_clk_ipc
(
struct
skl_clk_rate_cfg_table
*
rcfg
,
u8
clk_type
)
{
struct
nhlt_fmt_cfg
*
fmt_cfg
;
union
skl_clk_ctrl_ipc
*
ipc
;
struct
wav_fmt
*
wfmt
;
if
(
!
rcfg
)
return
;
ipc
=
&
rcfg
->
dma_ctl_ipc
;
if
(
clk_type
==
SKL_SCLK_FS
)
{
fmt_cfg
=
(
struct
nhlt_fmt_cfg
*
)
rcfg
->
config
;
wfmt
=
&
fmt_cfg
->
fmt_ext
.
fmt
;
/* Remove TLV Header size */
ipc
->
sclk_fs
.
hdr
.
size
=
sizeof
(
struct
skl_dmactrl_sclkfs_cfg
)
-
sizeof
(
struct
skl_tlv_hdr
);
ipc
->
sclk_fs
.
sampling_frequency
=
wfmt
->
samples_per_sec
;
ipc
->
sclk_fs
.
bit_depth
=
wfmt
->
bits_per_sample
;
ipc
->
sclk_fs
.
valid_bit_depth
=
fmt_cfg
->
fmt_ext
.
sample
.
valid_bits_per_sample
;
ipc
->
sclk_fs
.
number_of_channels
=
wfmt
->
channels
;
}
else
{
ipc
->
mclk
.
hdr
.
type
=
DMA_CLK_CONTROLS
;
/* Remove TLV Header size */
ipc
->
mclk
.
hdr
.
size
=
sizeof
(
struct
skl_dmactrl_mclk_cfg
)
-
sizeof
(
struct
skl_tlv_hdr
);
}
}
/* Sends dma control IPC to turn the clock ON/OFF */
static
int
skl_send_clk_dma_control
(
struct
skl
*
skl
,
struct
skl_clk_rate_cfg_table
*
rcfg
,
u32
vbus_id
,
u8
clk_type
,
bool
enable
)
{
struct
nhlt_specific_cfg
*
sp_cfg
;
u32
i2s_config_size
,
node_id
=
0
;
struct
nhlt_fmt_cfg
*
fmt_cfg
;
union
skl_clk_ctrl_ipc
*
ipc
;
void
*
i2s_config
=
NULL
;
u8
*
data
,
size
;
int
ret
;
if
(
!
rcfg
)
return
-
EIO
;
ipc
=
&
rcfg
->
dma_ctl_ipc
;
fmt_cfg
=
(
struct
nhlt_fmt_cfg
*
)
rcfg
->
config
;
sp_cfg
=
&
fmt_cfg
->
config
;
if
(
clk_type
==
SKL_SCLK_FS
)
{
ipc
->
sclk_fs
.
hdr
.
type
=
enable
?
DMA_TRANSMITION_START
:
DMA_TRANSMITION_STOP
;
data
=
(
u8
*
)
&
ipc
->
sclk_fs
;
size
=
sizeof
(
struct
skl_dmactrl_sclkfs_cfg
);
}
else
{
/* 1 to enable mclk, 0 to enable sclk */
if
(
clk_type
==
SKL_SCLK
)
ipc
->
mclk
.
mclk
=
0
;
else
ipc
->
mclk
.
mclk
=
1
;
ipc
->
mclk
.
keep_running
=
enable
;
ipc
->
mclk
.
warm_up_over
=
enable
;
ipc
->
mclk
.
clk_stop_over
=
!
enable
;
data
=
(
u8
*
)
&
ipc
->
mclk
;
size
=
sizeof
(
struct
skl_dmactrl_mclk_cfg
);
}
i2s_config_size
=
sp_cfg
->
size
+
size
;
i2s_config
=
kzalloc
(
i2s_config_size
,
GFP_KERNEL
);
if
(
!
i2s_config
)
return
-
ENOMEM
;
/* copy blob */
memcpy
(
i2s_config
,
sp_cfg
->
caps
,
sp_cfg
->
size
);
/* copy additional dma controls information */
memcpy
(
i2s_config
+
sp_cfg
->
size
,
data
,
size
);
node_id
=
((
SKL_DMA_I2S_LINK_INPUT_CLASS
<<
8
)
|
(
vbus_id
<<
4
));
ret
=
skl_dsp_set_dma_control
(
skl
->
skl_sst
,
(
u32
*
)
i2s_config
,
i2s_config_size
,
node_id
);
kfree
(
i2s_config
);
return
ret
;
}
static
struct
skl_clk_rate_cfg_table
*
skl_get_rate_cfg
(
struct
skl_clk_rate_cfg_table
*
rcfg
,
unsigned
long
rate
)
{
int
i
;
for
(
i
=
0
;
(
i
<
SKL_MAX_CLK_RATES
)
&&
rcfg
[
i
].
rate
;
i
++
)
{
if
(
rcfg
[
i
].
rate
==
rate
)
return
&
rcfg
[
i
];
}
return
NULL
;
}
static
int
skl_clk_change_status
(
struct
skl_clk
*
clkdev
,
bool
enable
)
{
struct
skl_clk_rate_cfg_table
*
rcfg
;
int
vbus_id
,
clk_type
;
clk_type
=
skl_get_clk_type
(
clkdev
->
id
);
if
(
clk_type
<
0
)
return
clk_type
;
vbus_id
=
skl_get_vbus_id
(
clkdev
->
id
,
clk_type
);
if
(
vbus_id
<
0
)
return
vbus_id
;
rcfg
=
skl_get_rate_cfg
(
clkdev
->
pdata
->
ssp_clks
[
clkdev
->
id
].
rate_cfg
,
clkdev
->
rate
);
if
(
!
rcfg
)
return
-
EINVAL
;
return
skl_send_clk_dma_control
(
clkdev
->
pdata
->
pvt_data
,
rcfg
,
vbus_id
,
clk_type
,
enable
);
}
static
int
skl_clk_prepare
(
struct
clk_hw
*
hw
)
{
struct
skl_clk
*
clkdev
=
to_skl_clk
(
hw
);
return
skl_clk_change_status
(
clkdev
,
true
);
}
static
void
skl_clk_unprepare
(
struct
clk_hw
*
hw
)
{
struct
skl_clk
*
clkdev
=
to_skl_clk
(
hw
);
skl_clk_change_status
(
clkdev
,
false
);
}
static
int
skl_clk_set_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
unsigned
long
parent_rate
)
{
struct
skl_clk
*
clkdev
=
to_skl_clk
(
hw
);
struct
skl_clk_rate_cfg_table
*
rcfg
;
int
clk_type
;
if
(
!
rate
)
return
-
EINVAL
;
rcfg
=
skl_get_rate_cfg
(
clkdev
->
pdata
->
ssp_clks
[
clkdev
->
id
].
rate_cfg
,
rate
);
if
(
!
rcfg
)
return
-
EINVAL
;
clk_type
=
skl_get_clk_type
(
clkdev
->
id
);
if
(
clk_type
<
0
)
return
clk_type
;
skl_fill_clk_ipc
(
rcfg
,
clk_type
);
clkdev
->
rate
=
rate
;
return
0
;
}
static
unsigned
long
skl_clk_recalc_rate
(
struct
clk_hw
*
hw
,
unsigned
long
parent_rate
)
{
struct
skl_clk
*
clkdev
=
to_skl_clk
(
hw
);
if
(
clkdev
->
rate
)
return
clkdev
->
rate
;
return
0
;
}
/* Not supported by clk driver. Implemented to satisfy clk fw */
long
skl_clk_round_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
unsigned
long
*
parent_rate
)
{
return
rate
;
}
/*
* prepare/unprepare are used instead of enable/disable as IPC will be sent
* in non-atomic context.
*/
static
const
struct
clk_ops
skl_clk_ops
=
{
.
prepare
=
skl_clk_prepare
,
.
unprepare
=
skl_clk_unprepare
,
.
set_rate
=
skl_clk_set_rate
,
.
round_rate
=
skl_clk_round_rate
,
.
recalc_rate
=
skl_clk_recalc_rate
,
};
static
void
unregister_parent_src_clk
(
struct
skl_clk_parent
*
pclk
,
unsigned
int
id
)
{
while
(
id
--
)
{
clkdev_drop
(
pclk
[
id
].
lookup
);
clk_hw_unregister_fixed_rate
(
pclk
[
id
].
hw
);
}
}
static
void
unregister_src_clk
(
struct
skl_clk_data
*
dclk
)
{
u8
cnt
=
dclk
->
avail_clk_cnt
;
while
(
cnt
--
)
clkdev_drop
(
dclk
->
clk
[
cnt
]
->
lookup
);
}
static
int
skl_register_parent_clks
(
struct
device
*
dev
,
struct
skl_clk_parent
*
parent
,
struct
skl_clk_parent_src
*
pclk
)
{
int
i
,
ret
;
for
(
i
=
0
;
i
<
SKL_MAX_CLK_SRC
;
i
++
)
{
/* Register Parent clock */
parent
[
i
].
hw
=
clk_hw_register_fixed_rate
(
dev
,
pclk
[
i
].
name
,
pclk
[
i
].
parent_name
,
0
,
pclk
[
i
].
rate
);
if
(
IS_ERR
(
parent
[
i
].
hw
))
{
ret
=
PTR_ERR
(
parent
[
i
].
hw
);
goto
err
;
}
parent
[
i
].
lookup
=
clkdev_hw_create
(
parent
[
i
].
hw
,
pclk
[
i
].
name
,
NULL
);
if
(
!
parent
[
i
].
lookup
)
{
clk_hw_unregister_fixed_rate
(
parent
[
i
].
hw
);
ret
=
-
ENOMEM
;
goto
err
;
}
}
return
0
;
err:
unregister_parent_src_clk
(
parent
,
i
);
return
ret
;
}
/* Assign fmt_config to clk_data */
static
struct
skl_clk
*
register_skl_clk
(
struct
device
*
dev
,
struct
skl_ssp_clk
*
clk
,
struct
skl_clk_pdata
*
clk_pdata
,
int
id
)
{
struct
clk_init_data
init
;
struct
skl_clk
*
clkdev
;
int
ret
;
clkdev
=
devm_kzalloc
(
dev
,
sizeof
(
*
clkdev
),
GFP_KERNEL
);
if
(
!
clkdev
)
return
ERR_PTR
(
-
ENOMEM
);
init
.
name
=
clk
->
name
;
init
.
ops
=
&
skl_clk_ops
;
init
.
flags
=
CLK_SET_RATE_GATE
;
init
.
parent_names
=
&
clk
->
parent_name
;
init
.
num_parents
=
1
;
clkdev
->
hw
.
init
=
&
init
;
clkdev
->
pdata
=
clk_pdata
;
clkdev
->
id
=
id
;
ret
=
devm_clk_hw_register
(
dev
,
&
clkdev
->
hw
);
if
(
ret
)
{
clkdev
=
ERR_PTR
(
ret
);
return
clkdev
;
}
clkdev
->
lookup
=
clkdev_hw_create
(
&
clkdev
->
hw
,
init
.
name
,
NULL
);
if
(
!
clkdev
->
lookup
)
clkdev
=
ERR_PTR
(
-
ENOMEM
);
return
clkdev
;
}
static
int
skl_clk_dev_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
parent_dev
=
dev
->
parent
;
struct
skl_clk_parent_src
*
parent_clks
;
struct
skl_clk_pdata
*
clk_pdata
;
struct
skl_clk_data
*
data
;
struct
skl_ssp_clk
*
clks
;
int
ret
,
i
;
clk_pdata
=
dev_get_platdata
(
&
pdev
->
dev
);
parent_clks
=
clk_pdata
->
parent_clks
;
clks
=
clk_pdata
->
ssp_clks
;
if
(
!
parent_clks
||
!
clks
)
return
-
EIO
;
data
=
devm_kzalloc
(
dev
,
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
!
data
)
return
-
ENOMEM
;
/* Register Parent clock */
ret
=
skl_register_parent_clks
(
parent_dev
,
data
->
parent
,
parent_clks
);
if
(
ret
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
clk_pdata
->
num_clks
;
i
++
)
{
/*
* Only register valid clocks
* i.e. for which nhlt entry is present.
*/
if
(
clks
[
i
].
rate_cfg
[
0
].
rate
==
0
)
continue
;
data
->
clk
[
i
]
=
register_skl_clk
(
dev
,
&
clks
[
i
],
clk_pdata
,
i
);
if
(
IS_ERR
(
data
->
clk
[
i
]))
{
ret
=
PTR_ERR
(
data
->
clk
[
i
]);
goto
err_unreg_skl_clk
;
}
data
->
avail_clk_cnt
++
;
}
platform_set_drvdata
(
pdev
,
data
);
return
0
;
err_unreg_skl_clk:
unregister_src_clk
(
data
);
unregister_parent_src_clk
(
data
->
parent
,
SKL_MAX_CLK_SRC
);
return
ret
;
}
static
int
skl_clk_dev_remove
(
struct
platform_device
*
pdev
)
{
struct
skl_clk_data
*
data
;
data
=
platform_get_drvdata
(
pdev
);
unregister_src_clk
(
data
);
unregister_parent_src_clk
(
data
->
parent
,
SKL_MAX_CLK_SRC
);
return
0
;
}
static
struct
platform_driver
skl_clk_driver
=
{
.
driver
=
{
.
name
=
"skl-ssp-clk"
,
},
.
probe
=
skl_clk_dev_probe
,
.
remove
=
skl_clk_dev_remove
,
};
module_platform_driver
(
skl_clk_driver
);
MODULE_DESCRIPTION
(
"Skylake clock driver"
);
MODULE_AUTHOR
(
"Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>"
);
MODULE_AUTHOR
(
"Subhransu S. Prusty <subhransu.s.prusty@intel.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:skl-ssp-clk"
);
sound/soc/intel/skylake/skl-ssp-clk.h
0 → 100644
View file @
70fff743
/*
* skl-ssp-clk.h - Skylake ssp clock information and ipc structure
*
* Copyright (C) 2017 Intel Corp
* Author: Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>
* Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef SOUND_SOC_SKL_SSP_CLK_H
#define SOUND_SOC_SKL_SSP_CLK_H
#define SKL_MAX_SSP 6
/* xtal/cardinal/pll, parent of ssp clocks and mclk */
#define SKL_MAX_CLK_SRC 3
#define SKL_MAX_SSP_CLK_TYPES 3
/* mclk, sclk, sclkfs */
#define SKL_MAX_CLK_CNT (SKL_MAX_SSP * SKL_MAX_SSP_CLK_TYPES)
/* Max number of configurations supported for each clock */
#define SKL_MAX_CLK_RATES 10
#define SKL_SCLK_OFS SKL_MAX_SSP
#define SKL_SCLKFS_OFS (SKL_SCLK_OFS + SKL_MAX_SSP)
enum
skl_clk_type
{
SKL_MCLK
,
SKL_SCLK
,
SKL_SCLK_FS
,
};
enum
skl_clk_src_type
{
SKL_XTAL
,
SKL_CARDINAL
,
SKL_PLL
,
};
struct
skl_clk_parent_src
{
u8
clk_id
;
const
char
*
name
;
unsigned
long
rate
;
const
char
*
parent_name
;
};
struct
skl_tlv_hdr
{
u32
type
;
u32
size
;
};
struct
skl_dmactrl_mclk_cfg
{
struct
skl_tlv_hdr
hdr
;
/* DMA Clk TLV params */
u32
clk_warm_up
:
16
;
u32
mclk
:
1
;
u32
warm_up_over
:
1
;
u32
rsvd0
:
14
;
u32
clk_stop_delay
:
16
;
u32
keep_running
:
1
;
u32
clk_stop_over
:
1
;
u32
rsvd1
:
14
;
};
struct
skl_dmactrl_sclkfs_cfg
{
struct
skl_tlv_hdr
hdr
;
/* DMA SClk&FS TLV params */
u32
sampling_frequency
;
u32
bit_depth
;
u32
channel_map
;
u32
channel_config
;
u32
interleaving_style
;
u32
number_of_channels
:
8
;
u32
valid_bit_depth
:
8
;
u32
sample_type
:
8
;
u32
reserved
:
8
;
};
union
skl_clk_ctrl_ipc
{
struct
skl_dmactrl_mclk_cfg
mclk
;
struct
skl_dmactrl_sclkfs_cfg
sclk_fs
;
};
struct
skl_clk_rate_cfg_table
{
unsigned
long
rate
;
union
skl_clk_ctrl_ipc
dma_ctl_ipc
;
void
*
config
;
};
/*
* rate for mclk will be in rates[0]. For sclk and sclkfs, rates[] store
* all possible clocks ssp can generate for that platform.
*/
struct
skl_ssp_clk
{
const
char
*
name
;
const
char
*
parent_name
;
struct
skl_clk_rate_cfg_table
rate_cfg
[
SKL_MAX_CLK_RATES
];
};
struct
skl_clk_pdata
{
struct
skl_clk_parent_src
*
parent_clks
;
int
num_clks
;
struct
skl_ssp_clk
*
ssp_clks
;
void
*
pvt_data
;
};
#endif
/* SOUND_SOC_SKL_SSP_CLK_H */
sound/soc/intel/skylake/skl-sst-dsp.c
View file @
70fff743
...
...
@@ -435,16 +435,22 @@ struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
return
NULL
;
}
return
sst
;
}
int
skl_dsp_acquire_irq
(
struct
sst_dsp
*
sst
)
{
struct
sst_dsp_device
*
sst_dev
=
sst
->
sst_dev
;
int
ret
;
/* Register the ISR */
ret
=
request_threaded_irq
(
sst
->
irq
,
sst
->
ops
->
irq_handler
,
sst_dev
->
thread
,
IRQF_SHARED
,
"AudioDSP"
,
sst
);
if
(
ret
)
{
if
(
ret
)
dev_err
(
sst
->
dev
,
"unable to grab threaded IRQ %d, disabling device
\n
"
,
sst
->
irq
);
return
NULL
;
}
return
ss
t
;
return
re
t
;
}
void
skl_dsp_free
(
struct
sst_dsp
*
dsp
)
...
...
sound/soc/intel/skylake/skl-sst-dsp.h
View file @
70fff743
...
...
@@ -206,6 +206,7 @@ int skl_cldma_wait_interruptible(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_acquire_irq
(
struct
sst_dsp
*
sst
);
bool
is_skl_dsp_running
(
struct
sst_dsp
*
ctx
);
unsigned
int
skl_dsp_get_enabled_cores
(
struct
sst_dsp
*
ctx
);
...
...
@@ -251,6 +252,9 @@ void skl_freeup_uuid_list(struct skl_sst *ctx);
int
skl_dsp_strip_extended_manifest
(
struct
firmware
*
fw
);
void
skl_dsp_enable_notification
(
struct
skl_sst
*
ctx
,
bool
enable
);
void
skl_dsp_set_astate_cfg
(
struct
skl_sst
*
ctx
,
u32
cnt
,
void
*
data
);
int
skl_sst_ctx_init
(
struct
device
*
dev
,
int
irq
,
const
char
*
fw_name
,
struct
skl_dsp_loader_ops
dsp_ops
,
struct
skl_sst
**
dsp
,
struct
sst_dsp_device
*
skl_dev
);
...
...
sound/soc/intel/skylake/skl-sst-utils.c
View file @
70fff743
...
...
@@ -178,7 +178,8 @@ static inline int skl_pvtid_128(struct uuid_module *module)
* skl_get_pvt_id: generate a private id for use as module id
*
* @ctx: driver context
* @mconfig: module configuration data
* @uuid_mod: module's uuid
* @instance_id: module's instance id
*
* This generates a 128 bit private unique id for a module TYPE so that
* module instance is unique
...
...
@@ -208,7 +209,8 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id);
* skl_put_pvt_id: free up the private id allocated
*
* @ctx: driver context
* @mconfig: module configuration data
* @uuid_mod: module's uuid
* @pvt_id: module pvt id
*
* This frees a 128 bit private unique id previously generated
*/
...
...
sound/soc/intel/skylake/skl-sst.c
View file @
70fff743
...
...
@@ -569,7 +569,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst
->
fw_ops
=
skl_fw_ops
;
return
0
;
return
skl_dsp_acquire_irq
(
sst
)
;
}
EXPORT_SYMBOL_GPL
(
skl_sst_dsp_init
);
...
...
sound/soc/intel/skylake/skl-topology.c
View file @
70fff743
...
...
@@ -190,7 +190,6 @@ skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig)
u8
res_idx
=
mconfig
->
res_idx
;
struct
skl_module_res
*
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
res
=
&
mconfig
->
module
->
resources
[
res_idx
];
skl
->
resource
.
mcps
-=
res
->
cps
;
}
...
...
@@ -3056,11 +3055,13 @@ static int skl_tplg_get_int_tkn(struct device *dev,
struct
snd_soc_tplg_vendor_value_elem
*
tkn_elem
,
struct
skl
*
skl
)
{
int
tkn_count
=
0
,
ret
;
int
tkn_count
=
0
,
ret
,
size
;
static
int
mod_idx
,
res_val_idx
,
intf_val_idx
,
dir
,
pin_idx
;
struct
skl_module_res
*
res
=
NULL
;
struct
skl_module_iface
*
fmt
=
NULL
;
struct
skl_module
*
mod
=
NULL
;
static
struct
skl_astate_param
*
astate_table
;
static
int
astate_cfg_idx
,
count
;
int
i
;
if
(
skl
->
modules
)
{
...
...
@@ -3093,6 +3094,46 @@ static int skl_tplg_get_int_tkn(struct device *dev,
mod_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_ASTATE_COUNT
:
if
(
astate_table
!=
NULL
)
{
dev_err
(
dev
,
"More than one entry for A-State count"
);
return
-
EINVAL
;
}
if
(
tkn_elem
->
value
>
SKL_MAX_ASTATE_CFG
)
{
dev_err
(
dev
,
"Invalid A-State count %d
\n
"
,
tkn_elem
->
value
);
return
-
EINVAL
;
}
size
=
tkn_elem
->
value
*
sizeof
(
struct
skl_astate_param
)
+
sizeof
(
count
);
skl
->
cfg
.
astate_cfg
=
devm_kzalloc
(
dev
,
size
,
GFP_KERNEL
);
if
(
!
skl
->
cfg
.
astate_cfg
)
return
-
ENOMEM
;
astate_table
=
skl
->
cfg
.
astate_cfg
->
astate_table
;
count
=
skl
->
cfg
.
astate_cfg
->
count
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_ASTATE_IDX
:
if
(
tkn_elem
->
value
>=
count
)
{
dev_err
(
dev
,
"Invalid A-State index %d
\n
"
,
tkn_elem
->
value
);
return
-
EINVAL
;
}
astate_cfg_idx
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_ASTATE_KCPS
:
astate_table
[
astate_cfg_idx
].
kcps
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U32_ASTATE_CLK_SRC
:
astate_table
[
astate_cfg_idx
].
clk_src
=
tkn_elem
->
value
;
break
;
case
SKL_TKN_U8_IN_PIN_TYPE
:
case
SKL_TKN_U8_OUT_PIN_TYPE
:
case
SKL_TKN_U8_IN_QUEUE_COUNT
:
...
...
sound/soc/intel/skylake/skl.c
View file @
70fff743
...
...
@@ -355,6 +355,7 @@ static int skl_resume(struct device *dev)
if
(
ebus
->
cmd_dma_state
)
snd_hdac_bus_init_cmd_io
(
&
ebus
->
bus
);
ret
=
0
;
}
else
{
ret
=
_skl_resume
(
ebus
);
...
...
@@ -435,19 +436,51 @@ static int skl_free(struct hdac_ext_bus *ebus)
return
0
;
}
static
int
skl_machine_device_register
(
struct
skl
*
skl
,
void
*
driver_data
)
/*
* For each ssp there are 3 clocks (mclk/sclk/sclkfs).
* e.g. for ssp0, clocks will be named as
* "ssp0_mclk", "ssp0_sclk", "ssp0_sclkfs"
* So for skl+, there are 6 ssps, so 18 clocks will be created.
*/
static
struct
skl_ssp_clk
skl_ssp_clks
[]
=
{
{.
name
=
"ssp0_mclk"
},
{.
name
=
"ssp1_mclk"
},
{.
name
=
"ssp2_mclk"
},
{.
name
=
"ssp3_mclk"
},
{.
name
=
"ssp4_mclk"
},
{.
name
=
"ssp5_mclk"
},
{.
name
=
"ssp0_sclk"
},
{.
name
=
"ssp1_sclk"
},
{.
name
=
"ssp2_sclk"
},
{.
name
=
"ssp3_sclk"
},
{.
name
=
"ssp4_sclk"
},
{.
name
=
"ssp5_sclk"
},
{.
name
=
"ssp0_sclkfs"
},
{.
name
=
"ssp1_sclkfs"
},
{.
name
=
"ssp2_sclkfs"
},
{.
name
=
"ssp3_sclkfs"
},
{.
name
=
"ssp4_sclkfs"
},
{.
name
=
"ssp5_sclkfs"
},
};
static
int
skl_find_machine
(
struct
skl
*
skl
,
void
*
driver_data
)
{
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
&
skl
->
ebus
);
struct
platform_device
*
pdev
;
struct
snd_soc_acpi_mach
*
mach
=
driver_data
;
int
ret
;
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
&
skl
->
ebus
);
struct
skl_machine_pdata
*
pdata
;
mach
=
snd_soc_acpi_find_machine
(
mach
);
if
(
mach
==
NULL
)
{
dev_err
(
bus
->
dev
,
"No matching machine driver found
\n
"
);
return
-
ENODEV
;
}
skl
->
mach
=
mach
;
skl
->
fw_name
=
mach
->
fw_filename
;
pdata
=
skl
->
mach
->
pdata
;
if
(
mach
->
pdata
)
skl
->
use_tplg_pcm
=
pdata
->
use_tplg_pcm
;
return
0
;
}
static
int
skl_machine_device_register
(
struct
skl
*
skl
)
{
struct
hdac_bus
*
bus
=
ebus_to_hbus
(
&
skl
->
ebus
);
struct
snd_soc_acpi_mach
*
mach
=
skl
->
mach
;
struct
platform_device
*
pdev
;
int
ret
;
pdev
=
platform_device_alloc
(
mach
->
drv_name
,
-
1
);
if
(
pdev
==
NULL
)
{
...
...
@@ -462,11 +495,8 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data)
return
-
EIO
;
}
if
(
mach
->
pdata
)
{
skl
->
use_tplg_pcm
=
((
struct
skl_machine_pdata
*
)
mach
->
pdata
)
->
use_tplg_pcm
;
if
(
mach
->
pdata
)
dev_set_drvdata
(
&
pdev
->
dev
,
mach
->
pdata
);
}
skl
->
i2s_dev
=
pdev
;
...
...
@@ -509,6 +539,74 @@ static void skl_dmic_device_unregister(struct skl *skl)
platform_device_unregister
(
skl
->
dmic_dev
);
}
static
struct
skl_clk_parent_src
skl_clk_src
[]
=
{
{
.
clk_id
=
SKL_XTAL
,
.
name
=
"xtal"
},
{
.
clk_id
=
SKL_CARDINAL
,
.
name
=
"cardinal"
,
.
rate
=
24576000
},
{
.
clk_id
=
SKL_PLL
,
.
name
=
"pll"
,
.
rate
=
96000000
},
};
struct
skl_clk_parent_src
*
skl_get_parent_clk
(
u8
clk_id
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
skl_clk_src
);
i
++
)
{
if
(
skl_clk_src
[
i
].
clk_id
==
clk_id
)
return
&
skl_clk_src
[
i
];
}
return
NULL
;
}
static
void
init_skl_xtal_rate
(
int
pci_id
)
{
switch
(
pci_id
)
{
case
0x9d70
:
case
0x9d71
:
skl_clk_src
[
0
].
rate
=
24000000
;
return
;
default:
skl_clk_src
[
0
].
rate
=
19200000
;
return
;
}
}
static
int
skl_clock_device_register
(
struct
skl
*
skl
)
{
struct
platform_device_info
pdevinfo
=
{
NULL
};
struct
skl_clk_pdata
*
clk_pdata
;
clk_pdata
=
devm_kzalloc
(
&
skl
->
pci
->
dev
,
sizeof
(
*
clk_pdata
),
GFP_KERNEL
);
if
(
!
clk_pdata
)
return
-
ENOMEM
;
init_skl_xtal_rate
(
skl
->
pci
->
device
);
clk_pdata
->
parent_clks
=
skl_clk_src
;
clk_pdata
->
ssp_clks
=
skl_ssp_clks
;
clk_pdata
->
num_clks
=
ARRAY_SIZE
(
skl_ssp_clks
);
/* Query NHLT to fill the rates and parent */
skl_get_clks
(
skl
,
clk_pdata
->
ssp_clks
);
clk_pdata
->
pvt_data
=
skl
;
/* Register Platform device */
pdevinfo
.
parent
=
&
skl
->
pci
->
dev
;
pdevinfo
.
id
=
-
1
;
pdevinfo
.
name
=
"skl-ssp-clk"
;
pdevinfo
.
data
=
clk_pdata
;
pdevinfo
.
size_data
=
sizeof
(
*
clk_pdata
);
skl
->
clk_dev
=
platform_device_register_full
(
&
pdevinfo
);
return
PTR_ERR_OR_ZERO
(
skl
->
clk_dev
);
}
static
void
skl_clock_device_unregister
(
struct
skl
*
skl
)
{
if
(
skl
->
clk_dev
)
platform_device_unregister
(
skl
->
clk_dev
);
}
/*
* Probe the given codec address
*/
...
...
@@ -615,18 +713,30 @@ static void skl_probe_work(struct work_struct *work)
/* create codec instances */
skl_codec_create
(
ebus
);
/* register platform dai and controls */
err
=
skl_platform_register
(
bus
->
dev
);
if
(
err
<
0
)
{
dev_err
(
bus
->
dev
,
"platform register failed: %d
\n
"
,
err
);
return
;
}
if
(
bus
->
ppcap
)
{
err
=
skl_machine_device_register
(
skl
);
if
(
err
<
0
)
{
dev_err
(
bus
->
dev
,
"machine register failed: %d
\n
"
,
err
);
goto
out_err
;
}
}
if
(
IS_ENABLED
(
CONFIG_SND_SOC_HDAC_HDMI
))
{
err
=
snd_hdac_display_power
(
bus
,
false
);
if
(
err
<
0
)
{
dev_err
(
bus
->
dev
,
"Cannot turn off display power on i915
\n
"
);
skl_machine_device_unregister
(
skl
);
return
;
}
}
/* register platform dai and controls */
err
=
skl_platform_register
(
bus
->
dev
);
if
(
err
<
0
)
return
;
/*
* we are done probing so decrement link counts
*/
...
...
@@ -791,18 +901,21 @@ static int skl_probe(struct pci_dev *pci,
/* check if dsp is there */
if
(
bus
->
ppcap
)
{
err
=
skl_machine_device_register
(
skl
,
(
void
*
)
pci_id
->
driver_data
);
/* create device for dsp clk */
err
=
skl_clock_device_register
(
skl
);
if
(
err
<
0
)
goto
out_clk_free
;
err
=
skl_find_machine
(
skl
,
(
void
*
)
pci_id
->
driver_data
);
if
(
err
<
0
)
goto
out_nhlt_free
;
err
=
skl_init_dsp
(
skl
);
if
(
err
<
0
)
{
dev_dbg
(
bus
->
dev
,
"error failed to register dsp
\n
"
);
goto
out_
mach
_free
;
goto
out_
nhlt
_free
;
}
skl
->
skl_sst
->
enable_miscbdcge
=
skl_enable_miscbdcge
;
}
if
(
bus
->
mlcap
)
snd_hdac_ext_bus_get_ml_capabilities
(
ebus
);
...
...
@@ -820,8 +933,8 @@ static int skl_probe(struct pci_dev *pci,
out_dsp_free:
skl_free_dsp
(
skl
);
out_
mach
_free:
skl_
machine
_device_unregister
(
skl
);
out_
clk
_free:
skl_
clock
_device_unregister
(
skl
);
out_nhlt_free:
skl_nhlt_free
(
skl
->
nhlt
);
out_free:
...
...
@@ -872,6 +985,7 @@ static void skl_remove(struct pci_dev *pci)
skl_free_dsp
(
skl
);
skl_machine_device_unregister
(
skl
);
skl_dmic_device_unregister
(
skl
);
skl_clock_device_unregister
(
skl
);
skl_nhlt_remove_sysfs
(
skl
);
skl_nhlt_free
(
skl
->
nhlt
);
skl_free
(
ebus
);
...
...
sound/soc/intel/skylake/skl.h
View file @
70fff743
...
...
@@ -25,9 +25,12 @@
#include <sound/hdaudio_ext.h>
#include <sound/soc.h>
#include "skl-nhlt.h"
#include "skl-ssp-clk.h"
#define SKL_SUSPEND_DELAY 2000
#define SKL_MAX_ASTATE_CFG 3
#define AZX_PCIREG_PGCTL 0x44
#define AZX_PGCTL_LSRMD_MASK (1 << 4)
#define AZX_PCIREG_CGCTL 0x48
...
...
@@ -35,6 +38,10 @@
/* D0I3C Register fields */
#define AZX_REG_VS_D0I3C_CIP 0x1
/* Command in progress */
#define AZX_REG_VS_D0I3C_I3 0x4
/* D0i3 enable */
#define SKL_MAX_DMACTRL_CFG 18
#define DMA_CLK_CONTROLS 1
#define DMA_TRANSMITION_START 2
#define DMA_TRANSMITION_STOP 3
struct
skl_dsp_resource
{
u32
max_mcps
;
...
...
@@ -45,6 +52,20 @@ struct skl_dsp_resource {
struct
skl_debug
;
struct
skl_astate_param
{
u32
kcps
;
u32
clk_src
;
};
struct
skl_astate_config
{
u32
count
;
struct
skl_astate_param
astate_table
[
0
];
};
struct
skl_fw_config
{
struct
skl_astate_config
*
astate_cfg
;
};
struct
skl
{
struct
hdac_ext_bus
ebus
;
struct
pci_dev
*
pci
;
...
...
@@ -52,6 +73,7 @@ struct skl {
unsigned
int
init_done
:
1
;
/* delayed init status */
struct
platform_device
*
dmic_dev
;
struct
platform_device
*
i2s_dev
;
struct
platform_device
*
clk_dev
;
struct
snd_soc_platform
*
platform
;
struct
snd_soc_dai_driver
*
dais
;
...
...
@@ -75,6 +97,8 @@ struct skl {
u8
nr_modules
;
struct
skl_module
**
modules
;
bool
use_tplg_pcm
;
struct
skl_fw_config
cfg
;
struct
snd_soc_acpi_mach
*
mach
;
};
#define skl_to_ebus(s) (&(s)->ebus)
...
...
@@ -125,6 +149,10 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id);
void
skl_update_d0i3c
(
struct
device
*
dev
,
bool
enable
);
int
skl_nhlt_create_sysfs
(
struct
skl
*
skl
);
void
skl_nhlt_remove_sysfs
(
struct
skl
*
skl
);
void
skl_get_clks
(
struct
skl
*
skl
,
struct
skl_ssp_clk
*
ssp_clks
);
struct
skl_clk_parent_src
*
skl_get_parent_clk
(
u8
clk_id
);
int
skl_dsp_set_dma_control
(
struct
skl_sst
*
ctx
,
u32
*
caps
,
u32
caps_size
,
u32
node_id
);
struct
skl_module_cfg
;
...
...
sound/soc/soc-acpi.c
View file @
70fff743
...
...
@@ -16,74 +16,13 @@
#include <sound/soc-acpi.h>
static
acpi_status
snd_soc_acpi_find_name
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
ret
)
{
struct
acpi_device
*
adev
;
const
char
*
name
=
NULL
;
if
(
acpi_bus_get_device
(
handle
,
&
adev
))
return
AE_OK
;
if
(
adev
->
status
.
present
&&
adev
->
status
.
functional
)
{
name
=
acpi_dev_name
(
adev
);
*
(
const
char
**
)
ret
=
name
;
return
AE_CTRL_TERMINATE
;
}
return
AE_OK
;
}
const
char
*
snd_soc_acpi_find_name_from_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
{
const
char
*
name
=
NULL
;
acpi_status
status
;
status
=
acpi_get_devices
(
hid
,
snd_soc_acpi_find_name
,
NULL
,
(
void
**
)
&
name
);
if
(
ACPI_FAILURE
(
status
)
||
name
[
0
]
==
'\0'
)
return
NULL
;
return
name
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_acpi_find_name_from_hid
);
static
acpi_status
snd_soc_acpi_mach_match
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
ret
)
{
unsigned
long
long
sta
;
acpi_status
status
;
*
(
bool
*
)
context
=
true
;
status
=
acpi_evaluate_integer
(
handle
,
"_STA"
,
NULL
,
&
sta
);
if
(
ACPI_FAILURE
(
status
)
||
!
(
sta
&
ACPI_STA_DEVICE_PRESENT
))
*
(
bool
*
)
context
=
false
;
return
AE_OK
;
}
bool
snd_soc_acpi_check_hid
(
const
u8
hid
[
ACPI_ID_LEN
])
{
acpi_status
status
;
bool
found
=
false
;
status
=
acpi_get_devices
(
hid
,
snd_soc_acpi_mach_match
,
&
found
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
return
false
;
return
found
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_acpi_check_hid
);
struct
snd_soc_acpi_mach
*
snd_soc_acpi_find_machine
(
struct
snd_soc_acpi_mach
*
machines
)
{
struct
snd_soc_acpi_mach
*
mach
;
for
(
mach
=
machines
;
mach
->
id
[
0
];
mach
++
)
{
if
(
snd_soc_acpi_check_hid
(
mach
->
id
)
==
true
)
{
if
(
acpi_dev_present
(
mach
->
id
,
NULL
,
-
1
)
)
{
if
(
mach
->
machine_quirk
)
mach
=
mach
->
machine_quirk
(
mach
);
return
mach
;
...
...
@@ -161,7 +100,7 @@ struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
return
mach
;
for
(
i
=
0
;
i
<
codec_list
->
num_codecs
;
i
++
)
{
if
(
snd_soc_acpi_check_hid
(
codec_list
->
codecs
[
i
])
!=
true
)
if
(
!
acpi_dev_present
(
codec_list
->
codecs
[
i
],
NULL
,
-
1
)
)
return
NULL
;
}
...
...
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