Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
3e4555ab
Commit
3e4555ab
authored
Jan 12, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
parents
7c310f16
987da3fe
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
801 additions
and
1712 deletions
+801
-1712
include/sound/soc-acpi.h
include/sound/soc-acpi.h
+0
-3
include/uapi/sound/snd_sst_tokens.h
include/uapi/sound/snd_sst_tokens.h
+16
-1
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+0
-4
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+0
-1
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
+84
-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
+94
-100
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/bytcr_rt5651.c
+43
-3
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
+1
-1
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/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
+64
-0
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-messages.c
+22
-0
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl-nhlt.c
+155
-0
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-pcm.c
+12
-2
sound/soc/intel/skylake/skl-ssp-clk.h
sound/soc/intel/skylake/skl-ssp-clk.h
+79
-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
-1
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
+22
-0
sound/soc/soc-acpi.c
sound/soc/soc-acpi.c
+2
-30
No files found.
include/sound/soc-acpi.h
View file @
3e4555ab
...
...
@@ -50,9 +50,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 @
3e4555ab
...
...
@@ -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/soc/codecs/Kconfig
View file @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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/sn95031.c
deleted
100644 → 0
View file @
7c310f16
/*
* 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 @
7c310f16
/*
* 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 @
3e4555ab
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
select SND_SOC_INTEL_COMMON
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
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 @
3e4555ab
# 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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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
;
...
...
@@ -284,7 +284,7 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
if
(
!
str_info
)
return
-
EINVAL
;
if
(
str_info
->
status
==
STREAM_RUNNING
)
return
0
;
return
0
;
if
(
str_info
->
status
==
STREAM_PAUSED
)
{
retval
=
sst_prepare_and_post_msg
(
sst_drv_ctx
,
str_info
->
task_id
,
IPC_CMD
,
IPC_IA_RESUME_STREAM_MRFLD
,
...
...
sound/soc/intel/boards/Kconfig
View file @
3e4555ab
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
.
If unsure select "N".
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5640 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_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
.
If unsure select "N".
This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
platforms with RT5651 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_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_RT5670
depends on SND_SST_ATOM_HIFI2_PLATFORM
select SND_SST_IPC_ACPI
select SND_SOC_ACPI
select SND_SOC_RT5670
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_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 +184,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 +197,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 +211,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,14 +224,12 @@ 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
...
...
@@ -243,14 +237,13 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
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 +252,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/bytcr_rt5651.c
View file @
3e4555ab
...
...
@@ -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
);
...
...
sound/soc/intel/boards/haswell.c
View file @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -225,7 +225,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/kbl_rt5663_rt5514_max98927.c
View file @
3e4555ab
...
...
@@ -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 @
7c310f16
/*
* 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 @
3e4555ab
...
...
@@ -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/bxt-sst.c
View file @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
/*
* 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)
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_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
;
};
#endif
/* __SOUND_SOC_SKL_I2S_H */
sound/soc/intel/skylake/skl-messages.c
View file @
3e4555ab
...
...
@@ -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
;
}
...
...
sound/soc/intel/skylake/skl-nhlt.c
View file @
3e4555ab
...
...
@@ -19,6 +19,7 @@
*/
#include <linux/pci.h>
#include "skl.h"
#include "skl-i2s.h"
#define NHLT_ACPI_HEADER_SIG "NHLT"
...
...
@@ -277,3 +278,157 @@ 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_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
)
{
/* MCLK Divider Source Select */
i2s_config
=
(
struct
skl_i2s_config_blob_legacy
*
)
fmt
->
fmt_config
[
0
].
config
.
caps
;
clk_src
=
((
i2s_config
->
mclk
.
mdivctrl
)
&
SKL_MNDSS_DIV_CLK_SRC_MASK
)
>>
SKL_SHIFT
(
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_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
=
(
struct
skl_i2s_config_blob_legacy
*
)
fmt_cfg
->
caps
;
/* MCLK Divider Source Select */
clk_src
=
((
i2s_config
->
mclk
.
mdivctrl
)
&
SKL_MCLK_DIV_CLK_SRC_MASK
)
>>
SKL_SHIFT
(
SKL_MCLK_DIV_CLK_SRC_MASK
);
clkdiv
=
i2s_config
->
mclk
.
mdivr
&
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 @
3e4555ab
...
...
@@ -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.h
0 → 100644
View file @
3e4555ab
/*
* 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_clk_rate_cfg_table
{
unsigned
long
rate
;
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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -3056,11 +3056,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 +3095,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 @
3e4555ab
...
...
@@ -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 @
3e4555ab
...
...
@@ -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
...
...
@@ -45,6 +48,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 +69,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 +93,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 +145,8 @@ 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
);
struct
skl_module_cfg
;
...
...
sound/soc/soc-acpi.c
View file @
3e4555ab
...
...
@@ -49,41 +49,13 @@ const char *snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
}
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 +133,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