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
41caf056
Commit
41caf056
authored
Apr 12, 2015
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'asoc/topic/cx20442' and 'asoc/topic/davinci' into asoc-next
parents
6ca4aba4
32556394
b213b44a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
221 additions
and
26 deletions
+221
-26
sound/soc/codecs/cx20442.c
sound/soc/codecs/cx20442.c
+2
-2
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-evm.c
+3
-4
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.c
+216
-20
No files found.
sound/soc/codecs/cx20442.c
View file @
41caf056
...
...
@@ -420,7 +420,7 @@ static int cx20442_platform_probe(struct platform_device *pdev)
&
cx20442_codec_dev
,
&
cx20442_dai
,
1
);
}
static
int
__exit
cx20442_platform_remove
(
struct
platform_device
*
pdev
)
static
int
cx20442_platform_remove
(
struct
platform_device
*
pdev
)
{
snd_soc_unregister_codec
(
&
pdev
->
dev
);
return
0
;
...
...
@@ -431,7 +431,7 @@ static struct platform_driver cx20442_platform_driver = {
.
name
=
"cx20442-codec"
,
},
.
probe
=
cx20442_platform_probe
,
.
remove
=
__exit_p
(
cx20442_platform_remove
)
,
.
remove
=
cx20442_platform_remove
,
};
module_platform_driver
(
cx20442_platform_driver
);
...
...
sound/soc/davinci/davinci-evm.c
View file @
41caf056
...
...
@@ -117,7 +117,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
static
int
evm_aic3x_init
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_soc_card
*
card
=
rtd
->
card
;
struct
snd_soc_codec
*
codec
=
rtd
->
codec
;
struct
device_node
*
np
=
card
->
dev
->
of_node
;
int
ret
;
...
...
@@ -136,9 +135,9 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
}
/* not connected */
snd_soc_dapm_nc_pin
(
&
c
odec
->
dapm
,
"MONO_LOUT"
);
snd_soc_dapm_nc_pin
(
&
c
odec
->
dapm
,
"HPLCOM"
);
snd_soc_dapm_nc_pin
(
&
c
odec
->
dapm
,
"HPRCOM"
);
snd_soc_dapm_nc_pin
(
&
c
ard
->
dapm
,
"MONO_LOUT"
);
snd_soc_dapm_nc_pin
(
&
c
ard
->
dapm
,
"HPLCOM"
);
snd_soc_dapm_nc_pin
(
&
c
ard
->
dapm
,
"HPRCOM"
);
return
0
;
}
...
...
sound/soc/davinci/davinci-mcasp.c
View file @
41caf056
...
...
@@ -27,6 +27,7 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h>
#include <sound/asoundef.h>
#include <sound/core.h>
...
...
@@ -62,6 +63,12 @@ struct davinci_mcasp_context {
u32
config_regs
[
ARRAY_SIZE
(
context_regs
)];
u32
afifo_regs
[
2
];
/* for read/write fifo control registers */
u32
*
xrsr_regs
;
/* for serializer configuration */
bool
pm_state
;
};
struct
davinci_mcasp_ruledata
{
struct
davinci_mcasp
*
mcasp
;
int
serializers
;
};
struct
davinci_mcasp
{
...
...
@@ -98,6 +105,8 @@ struct davinci_mcasp {
#ifdef CONFIG_PM_SLEEP
struct
davinci_mcasp_context
context
;
#endif
struct
davinci_mcasp_ruledata
ruledata
[
2
];
};
static
inline
void
mcasp_set_bits
(
struct
davinci_mcasp
*
mcasp
,
u32
offset
,
...
...
@@ -519,7 +528,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits
(
mcasp
,
DAVINCI_MCASP_RXFMCTL_REG
,
FSRPOL
);
}
out:
pm_runtime_put
_sync
(
mcasp
->
dev
);
pm_runtime_put
(
mcasp
->
dev
);
return
ret
;
}
...
...
@@ -528,6 +537,7 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
{
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
dai
);
pm_runtime_get_sync
(
mcasp
->
dev
);
switch
(
div_id
)
{
case
0
:
/* MCLK divider */
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
,
...
...
@@ -553,6 +563,7 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
return
-
EINVAL
;
}
pm_runtime_put
(
mcasp
->
dev
);
return
0
;
}
...
...
@@ -567,6 +578,7 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
{
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
dai
);
pm_runtime_get_sync
(
mcasp
->
dev
);
if
(
dir
==
SND_SOC_CLOCK_OUT
)
{
mcasp_set_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
,
AHCLKXE
);
mcasp_set_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKRCTL_REG
,
AHCLKRE
);
...
...
@@ -579,6 +591,7 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
mcasp
->
sysclk_freq
=
freq
;
pm_runtime_put
(
mcasp
->
dev
);
return
0
;
}
...
...
@@ -863,6 +876,30 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
return
0
;
}
static
int
davinci_mcasp_calc_clk_div
(
struct
davinci_mcasp
*
mcasp
,
unsigned
int
bclk_freq
,
int
*
error_ppm
)
{
int
div
=
mcasp
->
sysclk_freq
/
bclk_freq
;
int
rem
=
mcasp
->
sysclk_freq
%
bclk_freq
;
if
(
rem
!=
0
)
{
if
(
div
==
0
||
((
mcasp
->
sysclk_freq
/
div
)
-
bclk_freq
)
>
(
bclk_freq
-
(
mcasp
->
sysclk_freq
/
(
div
+
1
))))
{
div
++
;
rem
=
rem
-
bclk_freq
;
}
}
if
(
error_ppm
)
*
error_ppm
=
(
div
*
1000000
+
(
int
)
div64_long
(
1000000LL
*
rem
,
(
int
)
bclk_freq
))
/
div
-
1000000
;
return
div
;
}
static
int
davinci_mcasp_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
cpu_dai
)
...
...
@@ -878,16 +915,20 @@ 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
)
{
unsigned
int
bclk_freq
=
snd_soc_params_to_bclk
(
params
);
unsigned
int
div
=
mcasp
->
sysclk_freq
/
bclk_freq
;
if
(
mcasp
->
sysclk_freq
%
bclk_freq
!=
0
)
{
if
(((
mcasp
->
sysclk_freq
/
div
)
-
bclk_freq
)
>
(
bclk_freq
-
(
mcasp
->
sysclk_freq
/
(
div
+
1
))))
div
++
;
dev_warn
(
mcasp
->
dev
,
"Inaccurate BCLK: %u Hz / %u != %u Hz
\n
"
,
mcasp
->
sysclk_freq
,
div
,
bclk_freq
);
}
int
channels
=
params_channels
(
params
);
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
,
&
ppm
);
if
(
ppm
)
dev_info
(
mcasp
->
dev
,
"Sample-rate is off by %d PPM
\n
"
,
ppm
);
__davinci_mcasp_set_clkdiv
(
cpu_dai
,
1
,
div
,
0
);
}
...
...
@@ -969,10 +1010,126 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
return
ret
;
}
static
const
unsigned
int
davinci_mcasp_dai_rates
[]
=
{
8000
,
11025
,
16000
,
22050
,
32000
,
44100
,
48000
,
64000
,
88200
,
96000
,
176400
,
192000
,
};
#define DAVINCI_MAX_RATE_ERROR_PPM 1000
static
int
davinci_mcasp_hw_rule_rate
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
struct
davinci_mcasp_ruledata
*
rd
=
rule
->
private
;
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
;
if
(
channels
>
rd
->
mcasp
->
tdm_slots
)
channels
=
rd
->
mcasp
->
tdm_slots
;
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
*
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
];
}
}
dev_dbg
(
rd
->
mcasp
->
dev
,
"%d frequencies (%d-%d) for %d sbits and %d channels
\n
"
,
count
,
ri
->
min
,
ri
->
max
,
sbits
,
channels
);
return
snd_interval_list
(
hw_param_interval
(
params
,
rule
->
var
),
count
,
list
,
0
);
}
static
int
davinci_mcasp_hw_rule_format
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
struct
davinci_mcasp_ruledata
*
rd
=
rule
->
private
;
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
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
)
*
channels
*
rate
;
int
ppm
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
&
ppm
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
snd_mask_set
(
&
nfmt
,
i
);
count
++
;
}
}
}
dev_dbg
(
rd
->
mcasp
->
dev
,
"%d possible sample format for %d Hz and %d channels
\n
"
,
count
,
rate
,
channels
);
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
)
{
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
cpu_dai
);
struct
davinci_mcasp_ruledata
*
ruledata
=
&
mcasp
->
ruledata
[
substream
->
stream
];
u32
max_channels
=
0
;
int
i
,
dir
;
...
...
@@ -994,6 +1151,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
if
(
mcasp
->
serial_dir
[
i
]
==
dir
)
max_channels
++
;
}
ruledata
->
serializers
=
max_channels
;
max_channels
*=
mcasp
->
tdm_slots
;
/*
* If the already active stream has less channels than the calculated
...
...
@@ -1008,6 +1166,42 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
snd_pcm_hw_constraint_minmax
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
2
,
max_channels
);
/*
* If we rely on implicit BCLK divider setting we should
* set constraints based on what we can provide.
*/
if
(
mcasp
->
bclk_master
&&
mcasp
->
bclk_div
==
0
&&
mcasp
->
sysclk_freq
)
{
int
ret
;
ruledata
->
mcasp
=
mcasp
;
ret
=
snd_pcm_hw_rule_add
(
substream
->
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
davinci_mcasp_hw_rule_rate
,
ruledata
,
SNDRV_PCM_HW_PARAM_FORMAT
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
-
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
);
if
(
ret
)
return
ret
;
}
return
0
;
}
...
...
@@ -1053,6 +1247,10 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
u32
reg
;
int
i
;
context
->
pm_state
=
pm_runtime_enabled
(
mcasp
->
dev
);
if
(
!
context
->
pm_state
)
pm_runtime_get_sync
(
mcasp
->
dev
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
context_regs
);
i
++
)
context
->
config_regs
[
i
]
=
mcasp_get_reg
(
mcasp
,
context_regs
[
i
]);
...
...
@@ -1069,6 +1267,8 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
context
->
xrsr_regs
[
i
]
=
mcasp_get_reg
(
mcasp
,
DAVINCI_MCASP_XRSRCTL_REG
(
i
));
pm_runtime_put_sync
(
mcasp
->
dev
);
return
0
;
}
...
...
@@ -1079,6 +1279,8 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
u32
reg
;
int
i
;
pm_runtime_get_sync
(
mcasp
->
dev
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
context_regs
);
i
++
)
mcasp_set_reg
(
mcasp
,
context_regs
[
i
],
context
->
config_regs
[
i
]);
...
...
@@ -1095,6 +1297,9 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
mcasp_set_reg
(
mcasp
,
DAVINCI_MCASP_XRSRCTL_REG
(
i
),
context
->
xrsr_regs
[
i
]);
if
(
!
context
->
pm_state
)
pm_runtime_put_sync
(
mcasp
->
dev
);
return
0
;
}
#else
...
...
@@ -1398,13 +1603,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
pm_runtime_enable
(
&
pdev
->
dev
);
ret
=
pm_runtime_get_sync
(
&
pdev
->
dev
);
if
(
IS_ERR_VALUE
(
ret
))
{
dev_err
(
&
pdev
->
dev
,
"pm_runtime_get_sync() failed
\n
"
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
ret
;
}
mcasp
->
base
=
devm_ioremap
(
&
pdev
->
dev
,
mem
->
start
,
resource_size
(
mem
));
if
(
!
mcasp
->
base
)
{
dev_err
(
&
pdev
->
dev
,
"ioremap failed
\n
"
);
...
...
@@ -1584,14 +1782,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
return
0
;
err:
pm_runtime_put_sync
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
return
ret
;
}
static
int
davinci_mcasp_remove
(
struct
platform_device
*
pdev
)
{
pm_runtime_put_sync
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
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