Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b114701c
Commit
b114701c
authored
Apr 06, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/asoc' into for-linus
parents
0221c81b
103f211d
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
850 additions
and
64 deletions
+850
-64
Documentation/sound/alsa/soc/jack.txt
Documentation/sound/alsa/soc/jack.txt
+71
-0
sound/arm/pxa2xx-ac97-lib.c
sound/arm/pxa2xx-ac97-lib.c
+10
-5
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl4030.c
+58
-1
sound/soc/codecs/twl4030.h
sound/soc/codecs/twl4030.h
+1
-0
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9705.c
+37
-0
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_dma.c
+17
-0
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.c
+49
-50
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.c
+11
-0
sound/soc/pxa/Kconfig
sound/soc/pxa/Kconfig
+10
-0
sound/soc/pxa/Makefile
sound/soc/pxa/Makefile
+2
-0
sound/soc/pxa/magician.c
sound/soc/pxa/magician.c
+560
-0
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa-ssp.c
+9
-3
sound/soc/soc-core.c
sound/soc/soc-core.c
+15
-5
No files found.
Documentation/sound/alsa/soc/jack.txt
0 → 100644
View file @
b114701c
ASoC jack detection
===================
ALSA has a standard API for representing physical jacks to user space,
the kernel side of which can be seen in include/sound/jack.h. ASoC
provides a version of this API adding two additional features:
- It allows more than one jack detection method to work together on one
user visible jack. In embedded systems it is common for multiple
to be present on a single jack but handled by separate bits of
hardware.
- Integration with DAPM, allowing DAPM endpoints to be updated
automatically based on the detected jack status (eg, turning off the
headphone outputs if no headphones are present).
This is done by splitting the jacks up into three things working
together: the jack itself represented by a struct snd_soc_jack, sets of
snd_soc_jack_pins representing DAPM endpoints to update and blocks of
code providing jack reporting mechanisms.
For example, a system may have a stereo headset jack with two reporting
mechanisms, one for the headphone and one for the microphone. Some
systems won't be able to use their speaker output while a headphone is
connected and so will want to make sure to update both speaker and
headphone when the headphone jack status changes.
The jack - struct snd_soc_jack
==============================
This represents a physical jack on the system and is what is visible to
user space. The jack itself is completely passive, it is set up by the
machine driver and updated by jack detection methods.
Jacks are created by the machine driver calling snd_soc_jack_new().
snd_soc_jack_pin
================
These represent a DAPM pin to update depending on some of the status
bits supported by the jack. Each snd_soc_jack has zero or more of these
which are updated automatically. They are created by the machine driver
and associated with the jack using snd_soc_jack_add_pins(). The status
of the endpoint may configured to be the opposite of the jack status if
required (eg, enabling a built in microphone if a microphone is not
connected via a jack).
Jack detection methods
======================
Actual jack detection is done by code which is able to monitor some
input to the system and update a jack by calling snd_soc_jack_report(),
specifying a subset of bits to update. The jack detection code should
be set up by the machine driver, taking configuration for the jack to
update and the set of things to report when the jack is connected.
Often this is done based on the status of a GPIO - a handler for this is
provided by the snd_soc_jack_add_gpio() function. Other methods are
also available, for example integrated into CODECs. One example of
CODEC integrated jack detection can be see in the WM8350 driver.
Each jack may have multiple reporting mechanisms, though it will need at
least one to be useful.
Machine drivers
===============
These are all hooked together by the machine driver depending on the
system hardware. The machine driver will set up the snd_soc_jack and
the list of pins to update then set up one or more jack detection
mechanisms to update that jack based on their current status.
sound/arm/pxa2xx-ac97-lib.c
View file @
b114701c
...
...
@@ -238,6 +238,8 @@ static inline void pxa_ac97_cold_pxa3xx(void)
bool
pxa2xx_ac97_try_warm_reset
(
struct
snd_ac97
*
ac97
)
{
unsigned
long
gsr
;
#ifdef CONFIG_PXA25x
if
(
cpu_is_pxa25x
())
pxa_ac97_warm_pxa25x
();
...
...
@@ -254,10 +256,10 @@ bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
else
#endif
BUG
();
if
(
!
(
(
GSR
|
gsr_bits
)
&
(
GSR_PCR
|
GSR_SCR
)))
{
gsr
=
GSR
|
gsr_bits
;
if
(
!
(
gsr
&
(
GSR_PCR
|
GSR_SCR
)))
{
printk
(
KERN_INFO
"%s: warm reset timeout (GSR=%#lx)
\n
"
,
__func__
,
gsr
_bits
);
__func__
,
gsr
);
return
false
;
}
...
...
@@ -268,6 +270,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
bool
pxa2xx_ac97_try_cold_reset
(
struct
snd_ac97
*
ac97
)
{
unsigned
long
gsr
;
#ifdef CONFIG_PXA25x
if
(
cpu_is_pxa25x
())
pxa_ac97_cold_pxa25x
();
...
...
@@ -285,9 +289,10 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
#endif
BUG
();
if
(
!
((
GSR
|
gsr_bits
)
&
(
GSR_PCR
|
GSR_SCR
)))
{
gsr
=
GSR
|
gsr_bits
;
if
(
!
(
gsr
&
(
GSR_PCR
|
GSR_SCR
)))
{
printk
(
KERN_INFO
"%s: cold reset timeout (GSR=%#lx)
\n
"
,
__func__
,
gsr
_bits
);
__func__
,
gsr
);
return
false
;
}
...
...
sound/soc/codecs/twl4030.c
View file @
b114701c
...
...
@@ -122,6 +122,9 @@ struct twl4030_priv {
unsigned
int
bypass_state
;
unsigned
int
codec_powered
;
unsigned
int
codec_muted
;
struct
snd_pcm_substream
*
master_substream
;
struct
snd_pcm_substream
*
slave_substream
;
};
/*
...
...
@@ -1217,6 +1220,50 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
return
0
;
}
static
int
twl4030_startup
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
codec
;
struct
twl4030_priv
*
twl4030
=
codec
->
private_data
;
/* If we already have a playback or capture going then constrain
* this substream to match it.
*/
if
(
twl4030
->
master_substream
)
{
struct
snd_pcm_runtime
*
master_runtime
;
master_runtime
=
twl4030
->
master_substream
->
runtime
;
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_RATE
,
master_runtime
->
rate
,
master_runtime
->
rate
);
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS
,
master_runtime
->
sample_bits
,
master_runtime
->
sample_bits
);
twl4030
->
slave_substream
=
substream
;
}
else
twl4030
->
master_substream
=
substream
;
return
0
;
}
static
void
twl4030_shutdown
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
codec
;
struct
twl4030_priv
*
twl4030
=
codec
->
private_data
;
if
(
twl4030
->
master_substream
==
substream
)
twl4030
->
master_substream
=
twl4030
->
slave_substream
;
twl4030
->
slave_substream
=
NULL
;
}
static
int
twl4030_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
...
...
@@ -1224,8 +1271,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
twl4030_priv
*
twl4030
=
codec
->
private_data
;
u8
mode
,
old_mode
,
format
,
old_format
;
if
(
substream
==
twl4030
->
slave_substream
)
/* Ignoring hw_params for slave substream */
return
0
;
/* bit rate */
old_mode
=
twl4030_read_reg_cache
(
codec
,
TWL4030_REG_CODEC_MODE
)
&
~
TWL4030_CODECPDZ
;
...
...
@@ -1259,6 +1311,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
case
48000
:
mode
|=
TWL4030_APLL_RATE_48000
;
break
;
case
96000
:
mode
|=
TWL4030_APLL_RATE_96000
;
break
;
default:
printk
(
KERN_ERR
"TWL4030 hw params: unknown rate %d
\n
"
,
params_rate
(
params
));
...
...
@@ -1384,6 +1439,8 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
static
struct
snd_soc_dai_ops
twl4030_dai_ops
=
{
.
startup
=
twl4030_startup
,
.
shutdown
=
twl4030_shutdown
,
.
hw_params
=
twl4030_hw_params
,
.
set_sysclk
=
twl4030_set_dai_sysclk
,
.
set_fmt
=
twl4030_set_dai_fmt
,
...
...
@@ -1395,7 +1452,7 @@ struct snd_soc_dai twl4030_dai = {
.
stream_name
=
"Playback"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
TWL4030_RATES
,
.
rates
=
TWL4030_RATES
|
SNDRV_PCM_RATE_96000
,
.
formats
=
TWL4030_FORMATS
,},
.
capture
=
{
.
stream_name
=
"Capture"
,
...
...
sound/soc/codecs/twl4030.h
View file @
b114701c
...
...
@@ -109,6 +109,7 @@
#define TWL4030_APLL_RATE_32000 0x80
#define TWL4030_APLL_RATE_44100 0x90
#define TWL4030_APLL_RATE_48000 0xA0
#define TWL4030_APLL_RATE_96000 0xE0
#define TWL4030_SEL_16K 0x04
#define TWL4030_CODECPDZ 0x02
#define TWL4030_OPT_MODE 0x01
...
...
sound/soc/codecs/wm9705.c
View file @
b114701c
...
...
@@ -317,6 +317,41 @@ static int wm9705_reset(struct snd_soc_codec *codec)
return
-
EIO
;
}
#ifdef CONFIG_PM
static
int
wm9705_soc_suspend
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
soc_ac97_ops
.
write
(
codec
->
ac97
,
AC97_POWERDOWN
,
0xffff
);
return
0
;
}
static
int
wm9705_soc_resume
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
i
,
ret
;
u16
*
cache
=
codec
->
reg_cache
;
ret
=
wm9705_reset
(
codec
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"could not reset AC97 codec
\n
"
);
return
ret
;
}
for
(
i
=
2
;
i
<
ARRAY_SIZE
(
wm9705_reg
)
<<
1
;
i
+=
2
)
{
soc_ac97_ops
.
write
(
codec
->
ac97
,
i
,
cache
[
i
>>
1
]);
}
return
0
;
}
#else
#define wm9705_soc_suspend NULL
#define wm9705_soc_resume NULL
#endif
static
int
wm9705_soc_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
...
...
@@ -407,6 +442,8 @@ static int wm9705_soc_remove(struct platform_device *pdev)
struct
snd_soc_codec_device
soc_codec_dev_wm9705
=
{
.
probe
=
wm9705_soc_probe
,
.
remove
=
wm9705_soc_remove
,
.
suspend
=
wm9705_soc_suspend
,
.
resume
=
wm9705_soc_resume
,
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm9705
);
...
...
sound/soc/fsl/fsl_dma.c
View file @
b114701c
...
...
@@ -697,6 +697,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
else
position
=
in_be32
(
&
dma_channel
->
dar
);
/*
* When capture is started, the SSI immediately starts to fill its FIFO.
* This means that the DMA controller is not started until the FIFO is
* full. However, ALSA calls this function before that happens, when
* MR.DAR is still zero. In this case, just return zero to indicate
* that nothing has been received yet.
*/
if
(
!
position
)
return
0
;
if
((
position
<
dma_private
->
dma_buf_phys
)
||
(
position
>
dma_private
->
dma_buf_end
))
{
dev_err
(
substream
->
pcm
->
card
->
dev
,
"dma pointer is out of range, halting stream
\n
"
);
return
SNDRV_PCM_POS_XRUN
;
}
frames
=
bytes_to_frames
(
runtime
,
position
-
dma_private
->
dma_buf_phys
);
/*
...
...
sound/soc/fsl/fsl_ssi.c
View file @
b114701c
...
...
@@ -60,6 +60,13 @@
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
#endif
/* SIER bitflag of interrupts to enable */
#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
/**
* fsl_ssi_private: per-SSI private data
*
...
...
@@ -140,7 +147,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
were interrupted for. We mask it with the Interrupt Enable register
so that we only check for events that we're interested in.
*/
sisr
=
in_be32
(
&
ssi
->
sisr
)
&
in_be32
(
&
ssi
->
sier
)
;
sisr
=
in_be32
(
&
ssi
->
sisr
)
&
SIER_FLAGS
;
if
(
sisr
&
CCSR_SSI_SISR_RFRC
)
{
ssi_private
->
stats
.
rfrc
++
;
...
...
@@ -324,12 +331,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
*/
/* 4. Enable the interrupts and DMA requests */
out_be32
(
&
ssi
->
sier
,
CCSR_SSI_SIER_TFRC_EN
|
CCSR_SSI_SIER_TDMAE
|
CCSR_SSI_SIER_TIE
|
CCSR_SSI_SIER_TUE0_EN
|
CCSR_SSI_SIER_TUE1_EN
|
CCSR_SSI_SIER_RFRC_EN
|
CCSR_SSI_SIER_RDMAE
|
CCSR_SSI_SIER_RIE
|
CCSR_SSI_SIER_ROE0_EN
|
CCSR_SSI_SIER_ROE1_EN
);
out_be32
(
&
ssi
->
sier
,
SIER_FLAGS
);
/*
* Set the watermark for transmit FIFI 0 and receive FIFO 0. We
...
...
@@ -466,28 +468,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
case
SNDRV_PCM_TRIGGER_START
:
clrbits32
(
&
ssi
->
scr
,
CCSR_SSI_SCR_SSIEN
);
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
setbits32
(
&
ssi
->
scr
,
CCSR_SSI_SCR_SSIEN
|
CCSR_SSI_SCR_TE
);
}
else
{
long
timeout
=
jiffies
+
10
;
else
setbits32
(
&
ssi
->
scr
,
CCSR_SSI_SCR_SSIEN
|
CCSR_SSI_SCR_RE
);
/* Wait until the SSI has filled its FIFO. Without this
* delay, ALSA complains about overruns. When the FIFO
* is full, the DMA controller initiates its first
* transfer. Until then, however, the DMA's DAR
* register is zero, which translates to an
* out-of-bounds pointer. This makes ALSA think an
* overrun has occurred.
*/
while
(
!
(
in_be32
(
&
ssi
->
sisr
)
&
CCSR_SSI_SISR_RFF0
)
&&
(
jiffies
<
timeout
));
if
(
!
(
in_be32
(
&
ssi
->
sisr
)
&
CCSR_SSI_SISR_RFF0
))
return
-
EIO
;
}
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
...
...
@@ -606,39 +592,52 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
.
ops
=
&
fsl_ssi_dai_ops
,
};
/* Show the statistics of a flag only if its interrupt is enabled. The
* compiler will optimze this code to a no-op if the interrupt is not
* enabled.
*/
#define SIER_SHOW(flag, name) \
do { \
if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
length += sprintf(buf + length, #name "=%u\n", \
ssi_private->stats.name); \
} while (0)
/**
* fsl_sysfs_ssi_show: display SSI statistics
*
* Display the statistics for the current SSI device.
* Display the statistics for the current SSI device. To avoid confusion,
* we only show those counts that are enabled.
*/
static
ssize_t
fsl_sysfs_ssi_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
fsl_ssi_private
*
ssi_private
=
container_of
(
attr
,
struct
fsl_ssi_private
,
dev_attr
);
ssize_t
length
;
length
=
sprintf
(
buf
,
"rfrc=%u"
,
ssi_private
->
stats
.
rfrc
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tfrc=%u"
,
ssi_private
->
stats
.
tfrc
);
length
+=
sprintf
(
buf
+
length
,
"
\t
cmdau=%u"
,
ssi_private
->
stats
.
cmdau
);
length
+=
sprintf
(
buf
+
length
,
"
\t
cmddu=%u"
,
ssi_private
->
stats
.
cmddu
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rxt=%u"
,
ssi_private
->
stats
.
rxt
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rdr1=%u"
,
ssi_private
->
stats
.
rdr1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rdr0=%u"
,
ssi_private
->
stats
.
rdr0
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tde1=%u"
,
ssi_private
->
stats
.
tde1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tde0=%u"
,
ssi_private
->
stats
.
tde0
);
length
+=
sprintf
(
buf
+
length
,
"
\t
roe1=%u"
,
ssi_private
->
stats
.
roe1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
roe0=%u"
,
ssi_private
->
stats
.
roe0
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tue1=%u"
,
ssi_private
->
stats
.
tue1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tue0=%u"
,
ssi_private
->
stats
.
tue0
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tfs=%u"
,
ssi_private
->
stats
.
tfs
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rfs=%u"
,
ssi_private
->
stats
.
rfs
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tls=%u"
,
ssi_private
->
stats
.
tls
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rls=%u"
,
ssi_private
->
stats
.
rls
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rff1=%u"
,
ssi_private
->
stats
.
rff1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
rff0=%u"
,
ssi_private
->
stats
.
rff0
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tfe1=%u"
,
ssi_private
->
stats
.
tfe1
);
length
+=
sprintf
(
buf
+
length
,
"
\t
tfe0=%u
\n
"
,
ssi_private
->
stats
.
tfe0
);
container_of
(
attr
,
struct
fsl_ssi_private
,
dev_attr
);
ssize_t
length
=
0
;
SIER_SHOW
(
RFRC_EN
,
rfrc
);
SIER_SHOW
(
TFRC_EN
,
tfrc
);
SIER_SHOW
(
CMDAU_EN
,
cmdau
);
SIER_SHOW
(
CMDDU_EN
,
cmddu
);
SIER_SHOW
(
RXT_EN
,
rxt
);
SIER_SHOW
(
RDR1_EN
,
rdr1
);
SIER_SHOW
(
RDR0_EN
,
rdr0
);
SIER_SHOW
(
TDE1_EN
,
tde1
);
SIER_SHOW
(
TDE0_EN
,
tde0
);
SIER_SHOW
(
ROE1_EN
,
roe1
);
SIER_SHOW
(
ROE0_EN
,
roe0
);
SIER_SHOW
(
TUE1_EN
,
tue1
);
SIER_SHOW
(
TUE0_EN
,
tue0
);
SIER_SHOW
(
TFS_EN
,
tfs
);
SIER_SHOW
(
RFS_EN
,
rfs
);
SIER_SHOW
(
TLS_EN
,
tls
);
SIER_SHOW
(
RLS_EN
,
rls
);
SIER_SHOW
(
RFF1_EN
,
rff1
);
SIER_SHOW
(
RFF0_EN
,
rff0
);
SIER_SHOW
(
TFE1_EN
,
tfe1
);
SIER_SHOW
(
TFE0_EN
,
tfe0
);
return
length
;
}
...
...
sound/soc/omap/omap-mcbsp.c
View file @
b114701c
...
...
@@ -146,6 +146,17 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
struct
omap_mcbsp_data
*
mcbsp_data
=
to_mcbsp
(
cpu_dai
->
private_data
);
int
err
=
0
;
if
(
cpu_is_omap343x
()
&&
mcbsp_data
->
bus_id
==
1
)
{
/*
* McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
* Set constraint for minimum buffer size to the same than FIFO
* size in order to avoid underruns in playback startup because
* HW is keeping the DMA request active until FIFO is filled.
*/
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
4096
,
UINT_MAX
);
}
if
(
!
cpu_dai
->
active
)
err
=
omap_mcbsp_request
(
mcbsp_data
->
bus_id
);
...
...
sound/soc/pxa/Kconfig
View file @
b114701c
...
...
@@ -116,6 +116,16 @@ config SND_SOC_ZYLONITE
Say Y if you want to add support for SoC audio on the
Marvell Zylonite reference platform.
config SND_PXA2XX_SOC_MAGICIAN
tristate "SoC Audio support for HTC Magician"
depends on SND_PXA2XX_SOC && MACH_MAGICIAN
select SND_PXA2XX_SOC_I2S
select SND_PXA_SOC_SSP
select SND_SOC_UDA1380
help
Say Y if you want to add support for SoC audio on the
HTC Magician.
config SND_PXA2XX_SOC_MIOA701
tristate "SoC Audio support for MIO A701"
depends on SND_PXA2XX_SOC && MACH_MIOA701
...
...
sound/soc/pxa/Makefile
View file @
b114701c
...
...
@@ -20,6 +20,7 @@ snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs
:=
em-x270.o
snd-soc-palm27x-objs
:=
palm27x.o
snd-soc-zylonite-objs
:=
zylonite.o
snd-soc-magician-objs
:=
magician.o
snd-soc-mioa701-objs
:=
mioa701_wm9713.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI)
+=
snd-soc-corgi.o
...
...
@@ -31,5 +32,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ)
+=
snd-soc-spitz.o
obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270)
+=
snd-soc-em-x270.o
obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X)
+=
snd-soc-palm27x.o
obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN)
+=
snd-soc-magician.o
obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701)
+=
snd-soc-mioa701.o
obj-$(CONFIG_SND_SOC_ZYLONITE)
+=
snd-soc-zylonite.o
sound/soc/pxa/magician.c
0 → 100644
View file @
b114701c
This diff is collapsed.
Click to expand it.
sound/soc/pxa/pxa-ssp.c
View file @
b114701c
...
...
@@ -627,12 +627,18 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
u32
sscr0
;
u32
sspsp
;
int
width
=
snd_pcm_format_physical_width
(
params_format
(
params
));
int
ttsa
=
ssp_read_reg
(
ssp
,
SSTSA
)
&
0xf
;
/* select correct DMA params */
if
(
substream
->
stream
!=
SNDRV_PCM_STREAM_PLAYBACK
)
dma
=
1
;
/* capture DMA offset is 1,3 */
if
(
chn
==
2
)
dma
+=
2
;
/* stereo DMA offset is 2, mono is 0 */
/* Network mode with one active slot (ttsa == 1) can be used
* to force 16-bit frame width on the wire (for S16_LE), even
* with two channels. Use 16-bit DMA transfers for this case.
*/
if
(((
chn
==
2
)
&&
(
ttsa
!=
1
))
||
(
width
==
32
))
dma
+=
2
;
/* 32-bit DMA offset is 2, 16-bit is 0 */
cpu_dai
->
dma_data
=
ssp_dma_params
[
cpu_dai
->
id
][
dma
];
dev_dbg
(
&
ssp
->
pdev
->
dev
,
"pxa_ssp_hw_params: dma %d
\n
"
,
dma
);
...
...
@@ -712,7 +718,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
/* When we use a network mode, we always require TDM slots
* - complain loudly and fail if they've not been set up yet.
*/
if
((
sscr0
&
SSCR0_MOD
)
&&
!
(
ssp_read_reg
(
ssp
,
SSTSA
)
&
0xf
)
)
{
if
((
sscr0
&
SSCR0_MOD
)
&&
!
ttsa
)
{
dev_err
(
&
ssp
->
pdev
->
dev
,
"No TDM timeslot configured
\n
"
);
return
-
EINVAL
;
}
...
...
sound/soc/soc-core.c
View file @
b114701c
...
...
@@ -98,7 +98,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
int
err
;
codec
->
ac97
->
dev
.
bus
=
&
ac97_bus_type
;
codec
->
ac97
->
dev
.
parent
=
NULL
;
codec
->
ac97
->
dev
.
parent
=
codec
->
card
->
dev
;
codec
->
ac97
->
dev
.
release
=
soc_ac97_device_release
;
dev_set_name
(
&
codec
->
ac97
->
dev
,
"%d-%d:%s"
,
...
...
@@ -767,11 +767,21 @@ static int soc_resume(struct platform_device *pdev)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_card
*
card
=
socdev
->
card
;
struct
snd_soc_dai
*
cpu_dai
=
card
->
dai_link
[
0
].
cpu_dai
;
dev_dbg
(
socdev
->
dev
,
"scheduling resume work
\n
"
);
if
(
!
schedule_work
(
&
card
->
deferred_resume_work
))
dev_err
(
socdev
->
dev
,
"resume work item may be lost
\n
"
);
/* AC97 devices might have other drivers hanging off them so
* need to resume immediately. Other drivers don't have that
* problem and may take a substantial amount of time to resume
* due to I/O costs and anti-pop so handle them out of line.
*/
if
(
cpu_dai
->
ac97_control
)
{
dev_dbg
(
socdev
->
dev
,
"Resuming AC97 immediately
\n
"
);
soc_resume_deferred
(
&
card
->
deferred_resume_work
);
}
else
{
dev_dbg
(
socdev
->
dev
,
"Scheduling resume work
\n
"
);
if
(
!
schedule_work
(
&
card
->
deferred_resume_work
))
dev_err
(
socdev
->
dev
,
"resume work item may be lost
\n
"
);
}
return
0
;
}
...
...
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