Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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