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
698803f8
Commit
698803f8
authored
Jun 05, 2015
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'asoc/topic/davinci' and 'asoc/topic/dpcm' into asoc-next
parents
6ba82f91
518f6bab
b073ed4e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
153 additions
and
100 deletions
+153
-100
include/sound/soc.h
include/sound/soc.h
+21
-18
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.c
+90
-77
sound/soc/soc-pcm.c
sound/soc/soc-pcm.c
+42
-5
No files found.
include/sound/soc.h
View file @
698803f8
...
...
@@ -970,6 +970,24 @@ struct snd_soc_dai_link {
enum
snd_soc_dpcm_trigger
trigger
[
2
];
/* trigger type for DPCM */
/* codec/machine specific init - e.g. add machine controls */
int
(
*
init
)(
struct
snd_soc_pcm_runtime
*
rtd
);
/* optional hw_params re-writing for BE and FE sync */
int
(
*
be_hw_params_fixup
)(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_hw_params
*
params
);
/* machine stream operations */
const
struct
snd_soc_ops
*
ops
;
const
struct
snd_soc_compr_ops
*
compr_ops
;
/* For unidirectional dai links */
bool
playback_only
;
bool
capture_only
;
/* Mark this pcm with non atomic ops */
bool
nonatomic
;
/* Keep DAI active over suspend */
unsigned
int
ignore_suspend
:
1
;
...
...
@@ -978,9 +996,6 @@ struct snd_soc_dai_link {
unsigned
int
symmetric_channels
:
1
;
unsigned
int
symmetric_samplebits
:
1
;
/* Mark this pcm with non atomic ops */
bool
nonatomic
;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned
int
no_pcm
:
1
;
...
...
@@ -991,23 +1006,11 @@ struct snd_soc_dai_link {
unsigned
int
dpcm_capture
:
1
;
unsigned
int
dpcm_playback
:
1
;
/* DPCM used FE & BE merged format */
unsigned
int
dpcm_merged_format
:
1
;
/* pmdown_time is ignored at stop */
unsigned
int
ignore_pmdown_time
:
1
;
/* codec/machine specific init - e.g. add machine controls */
int
(
*
init
)(
struct
snd_soc_pcm_runtime
*
rtd
);
/* optional hw_params re-writing for BE and FE sync */
int
(
*
be_hw_params_fixup
)(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_hw_params
*
params
);
/* machine stream operations */
const
struct
snd_soc_ops
*
ops
;
const
struct
snd_soc_compr_ops
*
compr_ops
;
/* For unidirectional dai links */
bool
playback_only
;
bool
capture_only
;
};
struct
snd_soc_codec_conf
{
...
...
sound/soc/davinci/davinci-mcasp.c
View file @
698803f8
...
...
@@ -107,6 +107,7 @@ struct davinci_mcasp {
#endif
struct
davinci_mcasp_ruledata
ruledata
[
2
];
struct
snd_pcm_hw_constraint_list
chconstr
[
2
];
};
static
inline
void
mcasp_set_bits
(
struct
davinci_mcasp
*
mcasp
,
u32
offset
,
...
...
@@ -915,15 +916,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
* the machine driver, we need to calculate the ratio.
*/
if
(
mcasp
->
bclk_master
&&
mcasp
->
bclk_div
==
0
&&
mcasp
->
sysclk_freq
)
{
int
channels
=
params_channels
(
params
)
;
int
slots
=
mcasp
->
tdm_slots
;
int
rate
=
params_rate
(
params
);
int
sbits
=
params_width
(
params
);
int
ppm
,
div
;
if
(
channels
>
mcasp
->
tdm_slots
)
channels
=
mcasp
->
tdm_slots
;
div
=
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
channels
,
div
=
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
slots
,
&
ppm
);
if
(
ppm
)
dev_info
(
mcasp
->
dev
,
"Sample-rate is off by %d PPM
\n
"
,
...
...
@@ -1024,31 +1022,36 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
struct
snd_interval
*
ri
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_RATE
);
int
sbits
=
params_width
(
params
);
int
channels
=
params_channels
(
params
)
;
unsigned
int
list
[
ARRAY_SIZE
(
davinci_mcasp_dai_rates
)]
;
int
i
,
count
=
0
;
int
slots
=
rd
->
mcasp
->
tdm_slots
;
struct
snd_interval
range
;
int
i
;
if
(
channels
>
rd
->
mcasp
->
tdm_slots
)
channels
=
rd
->
mcasp
->
tdm_slots
;
snd_interval_any
(
&
range
);
range
.
empty
=
1
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
davinci_mcasp_dai_rates
);
i
++
)
{
if
(
ri
->
min
<=
davinci_mcasp_dai_rates
[
i
]
&&
ri
->
max
>=
davinci_mcasp_dai_rates
[
i
])
{
uint
bclk_freq
=
sbits
*
channels
*
if
(
snd_interval_test
(
ri
,
davinci_mcasp_dai_rates
[
i
]))
{
uint
bclk_freq
=
sbits
*
slots
*
davinci_mcasp_dai_rates
[
i
];
int
ppm
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
&
ppm
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
list
[
count
++
]
=
davinci_mcasp_dai_rates
[
i
];
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
if
(
range
.
empty
)
{
range
.
min
=
davinci_mcasp_dai_rates
[
i
];
range
.
empty
=
0
;
}
range
.
max
=
davinci_mcasp_dai_rates
[
i
];
}
}
}
dev_dbg
(
rd
->
mcasp
->
dev
,
"
%d frequencies (%d-%d) for %d sbits and %d channel
s
\n
"
,
count
,
ri
->
min
,
ri
->
max
,
sbits
,
channel
s
);
"
Frequencies %d-%d -> %d-%d for %d sbits and %d tdm slot
s
\n
"
,
ri
->
min
,
ri
->
max
,
range
.
min
,
range
.
max
,
sbits
,
slot
s
);
return
snd_interval_
list
(
hw_param_interval
(
params
,
rule
->
var
),
count
,
list
,
0
);
return
snd_interval_
refine
(
hw_param_interval
(
params
,
rule
->
var
),
&
range
);
}
static
int
davinci_mcasp_hw_rule_format
(
struct
snd_pcm_hw_params
*
params
,
...
...
@@ -1058,17 +1061,14 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
struct
snd_mask
*
fmt
=
hw_param_mask
(
params
,
SNDRV_PCM_HW_PARAM_FORMAT
);
struct
snd_mask
nfmt
;
int
rate
=
params_rate
(
params
);
int
channels
=
params_channels
(
params
)
;
int
slots
=
rd
->
mcasp
->
tdm_slots
;
int
i
,
count
=
0
;
snd_mask_none
(
&
nfmt
);
if
(
channels
>
rd
->
mcasp
->
tdm_slots
)
channels
=
rd
->
mcasp
->
tdm_slots
;
for
(
i
=
0
;
i
<
SNDRV_PCM_FORMAT_LAST
;
i
++
)
{
if
(
snd_mask_test
(
fmt
,
i
))
{
uint
bclk_freq
=
snd_pcm_format_width
(
i
)
*
channel
s
*
rate
;
uint
bclk_freq
=
snd_pcm_format_width
(
i
)
*
slot
s
*
rate
;
int
ppm
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
&
ppm
);
...
...
@@ -1079,51 +1079,12 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
}
}
dev_dbg
(
rd
->
mcasp
->
dev
,
"%d possible sample format for %d Hz and %d
channel
s
\n
"
,
count
,
rate
,
channel
s
);
"%d possible sample format for %d Hz and %d
tdm slot
s
\n
"
,
count
,
rate
,
slot
s
);
return
snd_mask_refine
(
fmt
,
&
nfmt
);
}
static
int
davinci_mcasp_hw_rule_channels
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
struct
davinci_mcasp_ruledata
*
rd
=
rule
->
private
;
struct
snd_interval
*
ci
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
int
sbits
=
params_width
(
params
);
int
rate
=
params_rate
(
params
);
int
max_chan_per_wire
=
rd
->
mcasp
->
tdm_slots
<
ci
->
max
?
rd
->
mcasp
->
tdm_slots
:
ci
->
max
;
unsigned
int
list
[
ci
->
max
-
ci
->
min
+
1
];
int
c1
,
c
,
count
=
0
;
for
(
c1
=
ci
->
min
;
c1
<=
max_chan_per_wire
;
c1
++
)
{
uint
bclk_freq
=
c1
*
sbits
*
rate
;
int
ppm
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
&
ppm
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
/* If we can use all tdm_slots, we can put any
amount of channels to remaining wires as
long as they fit in. */
if
(
c1
==
rd
->
mcasp
->
tdm_slots
)
{
for
(
c
=
c1
;
c
<=
rd
->
serializers
*
c1
&&
c
<=
ci
->
max
;
c
++
)
list
[
count
++
]
=
c
;
}
else
{
list
[
count
++
]
=
c1
;
}
}
}
dev_dbg
(
rd
->
mcasp
->
dev
,
"%d possible channel counts (%d-%d) for %d Hz and %d sbits
\n
"
,
count
,
ci
->
min
,
ci
->
max
,
rate
,
sbits
);
return
snd_interval_list
(
hw_param_interval
(
params
,
rule
->
var
),
count
,
list
,
0
);
}
static
int
davinci_mcasp_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
cpu_dai
)
{
...
...
@@ -1167,6 +1128,11 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_CHANNELS
,
2
,
max_channels
);
if
(
mcasp
->
chconstr
[
substream
->
stream
].
count
)
snd_pcm_hw_constraint_list
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
&
mcasp
->
chconstr
[
substream
->
stream
]);
/*
* If we rely on implicit BCLK divider setting we should
* set constraints based on what we can provide.
...
...
@@ -1180,24 +1146,14 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_RATE
,
davinci_mcasp_hw_rule_rate
,
ruledata
,
SNDRV_PCM_HW_PARAM_FORMAT
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
-
1
);
SNDRV_PCM_HW_PARAM_FORMAT
,
-
1
);
if
(
ret
)
return
ret
;
ret
=
snd_pcm_hw_rule_add
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_FORMAT
,
davinci_mcasp_hw_rule_format
,
ruledata
,
SNDRV_PCM_HW_PARAM_RATE
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
-
1
);
if
(
ret
)
return
ret
;
ret
=
snd_pcm_hw_rule_add
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
davinci_mcasp_hw_rule_channels
,
ruledata
,
SNDRV_PCM_HW_PARAM_RATE
,
SNDRV_PCM_HW_PARAM_FORMAT
,
-
1
);
SNDRV_PCM_HW_PARAM_RATE
,
-
1
);
if
(
ret
)
return
ret
;
}
...
...
@@ -1556,6 +1512,59 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
return
pdata
;
}
/* All serializers must have equal number of channels */
static
int
davinci_mcasp_ch_constraint
(
struct
davinci_mcasp
*
mcasp
,
struct
snd_pcm_hw_constraint_list
*
cl
,
int
serializers
)
{
unsigned
int
*
list
;
int
i
,
count
=
0
;
if
(
serializers
<=
1
)
return
0
;
list
=
devm_kzalloc
(
mcasp
->
dev
,
sizeof
(
unsigned
int
)
*
(
mcasp
->
tdm_slots
+
serializers
-
2
),
GFP_KERNEL
);
if
(
!
list
)
return
-
ENOMEM
;
for
(
i
=
2
;
i
<=
mcasp
->
tdm_slots
;
i
++
)
list
[
count
++
]
=
i
;
for
(
i
=
2
;
i
<=
serializers
;
i
++
)
list
[
count
++
]
=
i
*
mcasp
->
tdm_slots
;
cl
->
count
=
count
;
cl
->
list
=
list
;
return
0
;
}
static
int
davinci_mcasp_init_ch_constraints
(
struct
davinci_mcasp
*
mcasp
)
{
int
rx_serializers
=
0
,
tx_serializers
=
0
,
ret
,
i
;
for
(
i
=
0
;
i
<
mcasp
->
num_serializer
;
i
++
)
if
(
mcasp
->
serial_dir
[
i
]
==
TX_MODE
)
tx_serializers
++
;
else
if
(
mcasp
->
serial_dir
[
i
]
==
RX_MODE
)
rx_serializers
++
;
ret
=
davinci_mcasp_ch_constraint
(
mcasp
,
&
mcasp
->
chconstr
[
SNDRV_PCM_STREAM_PLAYBACK
],
tx_serializers
);
if
(
ret
)
return
ret
;
ret
=
davinci_mcasp_ch_constraint
(
mcasp
,
&
mcasp
->
chconstr
[
SNDRV_PCM_STREAM_CAPTURE
],
rx_serializers
);
return
ret
;
}
static
int
davinci_mcasp_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
...
...
@@ -1739,6 +1748,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp
->
fifo_base
=
DAVINCI_MCASP_V3_AFIFO_BASE
;
}
ret
=
davinci_mcasp_init_ch_constraints
(
mcasp
);
if
(
ret
)
goto
err
;
dev_set_drvdata
(
&
pdev
->
dev
,
mcasp
);
mcasp_reparent_fck
(
pdev
);
...
...
sound/soc/soc-pcm.c
View file @
698803f8
...
...
@@ -1485,30 +1485,67 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
}
static
void
dpcm_init_runtime_hw
(
struct
snd_pcm_runtime
*
runtime
,
struct
snd_soc_pcm_stream
*
stream
)
struct
snd_soc_pcm_stream
*
stream
,
u64
formats
)
{
runtime
->
hw
.
rate_min
=
stream
->
rate_min
;
runtime
->
hw
.
rate_max
=
stream
->
rate_max
;
runtime
->
hw
.
channels_min
=
stream
->
channels_min
;
runtime
->
hw
.
channels_max
=
stream
->
channels_max
;
if
(
runtime
->
hw
.
formats
)
runtime
->
hw
.
formats
&=
stream
->
formats
;
runtime
->
hw
.
formats
&=
formats
&
stream
->
formats
;
else
runtime
->
hw
.
formats
=
stream
->
formats
;
runtime
->
hw
.
formats
=
formats
&
stream
->
formats
;
runtime
->
hw
.
rates
=
stream
->
rates
;
}
static
u64
dpcm_runtime_base_format
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
fe
=
substream
->
private_data
;
struct
snd_soc_dpcm
*
dpcm
;
u64
formats
=
ULLONG_MAX
;
int
stream
=
substream
->
stream
;
if
(
!
fe
->
dai_link
->
dpcm_merged_format
)
return
formats
;
/*
* It returns merged BE codec format
* if FE want to use it (= dpcm_merged_format)
*/
list_for_each_entry
(
dpcm
,
&
fe
->
dpcm
[
stream
].
be_clients
,
list_be
)
{
struct
snd_soc_pcm_runtime
*
be
=
dpcm
->
be
;
struct
snd_soc_dai_driver
*
codec_dai_drv
;
struct
snd_soc_pcm_stream
*
codec_stream
;
int
i
;
for
(
i
=
0
;
i
<
be
->
num_codecs
;
i
++
)
{
codec_dai_drv
=
be
->
codec_dais
[
i
]
->
driver
;
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
codec_stream
=
&
codec_dai_drv
->
playback
;
else
codec_stream
=
&
codec_dai_drv
->
capture
;
formats
&=
codec_stream
->
formats
;
}
}
return
formats
;
}
static
void
dpcm_set_fe_runtime
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
snd_soc_dai_driver
*
cpu_dai_drv
=
cpu_dai
->
driver
;
u64
format
=
dpcm_runtime_base_format
(
substream
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
dpcm_init_runtime_hw
(
runtime
,
&
cpu_dai_drv
->
playback
);
dpcm_init_runtime_hw
(
runtime
,
&
cpu_dai_drv
->
playback
,
format
);
else
dpcm_init_runtime_hw
(
runtime
,
&
cpu_dai_drv
->
capture
);
dpcm_init_runtime_hw
(
runtime
,
&
cpu_dai_drv
->
capture
,
format
);
}
static
int
dpcm_fe_dai_do_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
);
...
...
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