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
647dc469
Commit
647dc469
authored
Dec 03, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/symmetry' into asoc-ssm2602
parents
e42644c6
62e5f676
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
138 additions
and
28 deletions
+138
-28
include/sound/soc-dai.h
include/sound/soc-dai.h
+6
-0
include/sound/soc.h
include/sound/soc.h
+2
-0
sound/soc/soc-pcm.c
sound/soc/soc-pcm.c
+130
-28
No files found.
include/sound/soc-dai.h
View file @
647dc469
...
...
@@ -220,6 +220,8 @@ struct snd_soc_dai_driver {
struct
snd_soc_pcm_stream
capture
;
struct
snd_soc_pcm_stream
playback
;
unsigned
int
symmetric_rates
:
1
;
unsigned
int
symmetric_channels
:
1
;
unsigned
int
symmetric_samplebits
:
1
;
/* probe ordering - for components with runtime dependencies */
int
probe_order
;
...
...
@@ -244,6 +246,8 @@ struct snd_soc_dai {
unsigned
int
capture_active
:
1
;
/* stream is in use */
unsigned
int
playback_active
:
1
;
/* stream is in use */
unsigned
int
symmetric_rates
:
1
;
unsigned
int
symmetric_channels
:
1
;
unsigned
int
symmetric_samplebits
:
1
;
struct
snd_pcm_runtime
*
runtime
;
unsigned
int
active
;
unsigned
char
probed
:
1
;
...
...
@@ -258,6 +262,8 @@ struct snd_soc_dai {
/* Symmetry data - only valid if symmetry is being enforced */
unsigned
int
rate
;
unsigned
int
channels
;
unsigned
int
sample_bits
;
/* parent platform/codec */
struct
snd_soc_platform
*
platform
;
...
...
include/sound/soc.h
View file @
647dc469
...
...
@@ -879,6 +879,8 @@ struct snd_soc_dai_link {
/* Symmetry requirements */
unsigned
int
symmetric_rates
:
1
;
unsigned
int
symmetric_channels
:
1
;
unsigned
int
symmetric_samplebits
:
1
;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned
int
no_pcm
:
1
;
...
...
sound/soc/soc-pcm.c
View file @
647dc469
...
...
@@ -84,35 +84,117 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
int
ret
;
if
(
!
soc_dai
->
driver
->
symmetric_rates
&&
!
rtd
->
dai_link
->
symmetric_rates
)
return
0
;
if
(
soc_dai
->
rate
&&
(
soc_dai
->
driver
->
symmetric_rates
||
rtd
->
dai_link
->
symmetric_rates
))
{
dev_dbg
(
soc_dai
->
dev
,
"ASoC: Symmetry forces %dHz rate
\n
"
,
soc_dai
->
rate
);
/* This can happen if multiple streams are starting simultaneously -
* the second can need to get its constraints before the first has
* picked a rate. Complain and allow the application to carry on.
*/
if
(
!
soc_dai
->
rate
)
{
dev_warn
(
soc_dai
->
dev
,
"ASoC: Not enforcing symmetric_rates due to race
\n
"
);
return
0
;
ret
=
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_RATE
,
soc_dai
->
rate
,
soc_dai
->
rate
);
if
(
ret
<
0
)
{
dev_err
(
soc_dai
->
dev
,
"ASoC: Unable to apply rate constraint: %d
\n
"
,
ret
);
return
ret
;
}
}
dev_dbg
(
soc_dai
->
dev
,
"ASoC: Symmetry forces %dHz rate
\n
"
,
soc_dai
->
rate
);
if
(
soc_dai
->
channels
&&
(
soc_dai
->
driver
->
symmetric_channels
||
rtd
->
dai_link
->
symmetric_channels
))
{
dev_dbg
(
soc_dai
->
dev
,
"ASoC: Symmetry forces %d channel(s)
\n
"
,
soc_dai
->
channels
);
ret
=
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_RATE
,
soc_dai
->
rate
,
soc_dai
->
rate
);
SNDRV_PCM_HW_PARAM_CHANNELS
,
soc_dai
->
channels
,
soc_dai
->
channels
);
if
(
ret
<
0
)
{
dev_err
(
soc_dai
->
dev
,
"ASoC: Unable to apply rate
symmetry constraint: %d
\n
"
,
"ASoC: Unable to apply channel
symmetry constraint: %d
\n
"
,
ret
);
return
ret
;
}
}
if
(
soc_dai
->
sample_bits
&&
(
soc_dai
->
driver
->
symmetric_samplebits
||
rtd
->
dai_link
->
symmetric_samplebits
))
{
dev_dbg
(
soc_dai
->
dev
,
"ASoC: Symmetry forces %d sample bits
\n
"
,
soc_dai
->
sample_bits
);
ret
=
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS
,
soc_dai
->
sample_bits
,
soc_dai
->
sample_bits
);
if
(
ret
<
0
)
{
dev_err
(
soc_dai
->
dev
,
"ASoC: Unable to apply sample bits symmetry constraint: %d
\n
"
,
ret
);
return
ret
;
}
}
return
0
;
}
static
int
soc_pcm_params_symmetry
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
codec_dai
;
unsigned
int
rate
,
channels
,
sample_bits
,
symmetry
;
rate
=
params_rate
(
params
);
channels
=
params_channels
(
params
);
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
params
));
/* reject unmatched parameters when applying symmetry */
symmetry
=
cpu_dai
->
driver
->
symmetric_rates
||
codec_dai
->
driver
->
symmetric_rates
||
rtd
->
dai_link
->
symmetric_rates
;
if
(
symmetry
&&
cpu_dai
->
rate
&&
cpu_dai
->
rate
!=
rate
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched rate symmetry: %d - %d
\n
"
,
cpu_dai
->
rate
,
rate
);
return
-
EINVAL
;
}
symmetry
=
cpu_dai
->
driver
->
symmetric_channels
||
codec_dai
->
driver
->
symmetric_channels
||
rtd
->
dai_link
->
symmetric_channels
;
if
(
symmetry
&&
cpu_dai
->
channels
&&
cpu_dai
->
channels
!=
channels
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched channel symmetry: %d - %d
\n
"
,
cpu_dai
->
channels
,
channels
);
return
-
EINVAL
;
}
symmetry
=
cpu_dai
->
driver
->
symmetric_samplebits
||
codec_dai
->
driver
->
symmetric_samplebits
||
rtd
->
dai_link
->
symmetric_samplebits
;
if
(
symmetry
&&
cpu_dai
->
sample_bits
&&
cpu_dai
->
sample_bits
!=
sample_bits
)
{
dev_err
(
rtd
->
dev
,
"ASoC: unmatched sample bits symmetry: %d - %d
\n
"
,
cpu_dai
->
sample_bits
,
sample_bits
);
return
-
EINVAL
;
}
return
0
;
}
static
bool
soc_pcm_has_symmetry
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai_driver
*
cpu_driver
=
rtd
->
cpu_dai
->
driver
;
struct
snd_soc_dai_driver
*
codec_driver
=
rtd
->
codec_dai
->
driver
;
struct
snd_soc_dai_link
*
link
=
rtd
->
dai_link
;
return
cpu_driver
->
symmetric_rates
||
codec_driver
->
symmetric_rates
||
link
->
symmetric_rates
||
cpu_driver
->
symmetric_channels
||
codec_driver
->
symmetric_channels
||
link
->
symmetric_channels
||
cpu_driver
->
symmetric_samplebits
||
codec_driver
->
symmetric_samplebits
||
link
->
symmetric_samplebits
;
}
/*
* List of sample sizes that might go over the bus for parameter
* application. There ought to be a wildcard sample size for things
...
...
@@ -242,6 +324,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
&
cpu_dai_drv
->
capture
);
}
if
(
soc_pcm_has_symmetry
(
substream
))
runtime
->
hw
.
info
|=
SNDRV_PCM_INFO_JOINT_DUPLEX
;
ret
=
-
EINVAL
;
snd_pcm_limit_hw_rates
(
runtime
);
if
(
!
runtime
->
hw
.
rates
)
{
...
...
@@ -383,13 +468,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
codec_dai
->
active
--
;
codec
->
active
--
;
/* clear the corresponding DAIs rate when inactive */
if
(
!
cpu_dai
->
active
)
cpu_dai
->
rate
=
0
;
if
(
!
codec_dai
->
active
)
codec_dai
->
rate
=
0
;
/* Muting the DAC suppresses artifacts caused during digital
* shutdown, for example from stopping clocks.
*/
...
...
@@ -525,6 +603,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
ret
=
soc_pcm_params_symmetry
(
substream
,
params
);
if
(
ret
)
goto
out
;
if
(
rtd
->
dai_link
->
ops
&&
rtd
->
dai_link
->
ops
->
hw_params
)
{
ret
=
rtd
->
dai_link
->
ops
->
hw_params
(
substream
,
params
);
if
(
ret
<
0
)
{
...
...
@@ -561,9 +643,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}
/* store the
rate
for each DAIs */
/* store the
parameters
for each DAIs */
cpu_dai
->
rate
=
params_rate
(
params
);
cpu_dai
->
channels
=
params_channels
(
params
);
cpu_dai
->
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
params
));
codec_dai
->
rate
=
params_rate
(
params
);
codec_dai
->
channels
=
params_channels
(
params
);
codec_dai
->
sample_bits
=
snd_pcm_format_physical_width
(
params_format
(
params
));
out:
mutex_unlock
(
&
rtd
->
pcm_mutex
);
...
...
@@ -598,6 +687,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock_nested
(
&
rtd
->
pcm_mutex
,
rtd
->
pcm_subclass
);
/* clear the corresponding DAIs parameters when going to be inactive */
if
(
cpu_dai
->
active
==
1
)
{
cpu_dai
->
rate
=
0
;
cpu_dai
->
channels
=
0
;
cpu_dai
->
sample_bits
=
0
;
}
if
(
codec_dai
->
active
==
1
)
{
codec_dai
->
rate
=
0
;
codec_dai
->
channels
=
0
;
codec_dai
->
sample_bits
=
0
;
}
/* apply codec digital mute */
if
(
!
codec
->
active
)
snd_soc_dai_digital_mute
(
codec_dai
,
1
,
substream
->
stream
);
...
...
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