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
84d30623
Commit
84d30623
authored
Jan 12, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
parents
c5a216c3
2ca69d73
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
197 additions
and
172 deletions
+197
-172
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+11
-4
include/sound/soc.h
include/sound/soc.h
+2
-0
sound/soc/rockchip/rk3399_gru_sound.c
sound/soc/rockchip/rk3399_gru_sound.c
+2
-1
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/core.c
+86
-57
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/dma.c
+0
-18
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/rsnd.h
+12
-3
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssi.c
+74
-89
sound/soc/soc-core.c
sound/soc/soc-core.c
+10
-0
No files found.
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
View file @
84d30623
...
...
@@ -4,7 +4,7 @@ Renesas R-Car sound
* Modules
=============================================
Renesas R-Car sound is constructed from below modules
Renesas R-Car
and RZ/G
sound is constructed from below modules
(for Gen2 or later)
SCU : Sampling Rate Converter Unit
...
...
@@ -197,12 +197,17 @@ Ex)
[MEM] -> [SRC2] -> [CTU03] -+
sound {
#address-cells = <1>;
#size-cells = <0>;
compatible = "simple-scu-audio-card";
...
simple-audio-card,cpu-0 {
simple-audio-card,cpu@0 {
reg = <0>;
sound-dai = <&rcar_sound 0>;
};
simple-audio-card,cpu-1 {
simple-audio-card,cpu@1 {
reg = <1>;
sound-dai = <&rcar_sound 1>;
};
simple-audio-card,codec {
...
...
@@ -334,9 +339,11 @@ Required properties:
- compatible : "renesas,rcar_sound-<soctype>", fallbacks
"renesas,rcar_sound-gen1" if generation1, and
"renesas,rcar_sound-gen2" if generation2
"renesas,rcar_sound-gen2" if generation2
(or RZ/G1)
"renesas,rcar_sound-gen3" if generation3
Examples with soctypes are:
- "renesas,rcar_sound-r8a7743" (RZ/G1M)
- "renesas,rcar_sound-r8a7745" (RZ/G1E)
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
- "renesas,rcar_sound-r8a7779" (R-Car H1)
- "renesas,rcar_sound-r8a7790" (R-Car H2)
...
...
include/sound/soc.h
View file @
84d30623
...
...
@@ -494,6 +494,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
int
snd_soc_new_compress
(
struct
snd_soc_pcm_runtime
*
rtd
,
int
num
);
#endif
void
snd_soc_disconnect_sync
(
struct
device
*
dev
);
struct
snd_pcm_substream
*
snd_soc_get_dai_substream
(
struct
snd_soc_card
*
card
,
const
char
*
dai_link
,
int
stream
);
struct
snd_soc_pcm_runtime
*
snd_soc_get_pcm_runtime
(
struct
snd_soc_card
*
card
,
...
...
sound/soc/rockchip/rk3399_gru_sound.c
View file @
84d30623
...
...
@@ -206,7 +206,8 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
return
ret
;
}
snd_jack_set_key
(
rockchip_sound_jack
.
jack
,
SND_JACK_BTN_0
,
KEY_MEDIA
);
snd_jack_set_key
(
rockchip_sound_jack
.
jack
,
SND_JACK_BTN_0
,
KEY_PLAYPAUSE
);
snd_jack_set_key
(
rockchip_sound_jack
.
jack
,
SND_JACK_BTN_1
,
KEY_VOLUMEUP
);
snd_jack_set_key
(
...
...
sound/soc/sh/rcar/core.c
View file @
84d30623
...
...
@@ -197,16 +197,27 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io)
return
0
;
}
int
rsnd_runtime_channel_original
(
struct
rsnd_dai_stream
*
io
)
int
rsnd_runtime_channel_original_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
return
runtime
->
channels
;
/*
* params will be added when refine
* see
* __rsnd_soc_hw_rule_rate()
* __rsnd_soc_hw_rule_channels()
*/
if
(
params
)
return
params_channels
(
params
);
else
return
runtime
->
channels
;
}
int
rsnd_runtime_channel_after_ctu
(
struct
rsnd_dai_stream
*
io
)
int
rsnd_runtime_channel_after_ctu_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
)
{
int
chan
=
rsnd_runtime_channel_original
(
io
);
int
chan
=
rsnd_runtime_channel_original
_with_params
(
io
,
params
);
struct
rsnd_mod
*
ctu_mod
=
rsnd_io_to_mod_ctu
(
io
);
if
(
ctu_mod
)
{
...
...
@@ -219,12 +230,13 @@ int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io)
return
chan
;
}
int
rsnd_runtime_channel_for_ssi
(
struct
rsnd_dai_stream
*
io
)
int
rsnd_runtime_channel_for_ssi_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
)
{
struct
rsnd_dai
*
rdai
=
rsnd_io_to_rdai
(
io
);
int
chan
=
rsnd_io_is_play
(
io
)
?
rsnd_runtime_channel_after_ctu
(
io
)
:
rsnd_runtime_channel_original
(
io
);
rsnd_runtime_channel_after_ctu
_with_params
(
io
,
params
)
:
rsnd_runtime_channel_original
_with_params
(
io
,
params
);
/* Use Multi SSI */
if
(
rsnd_runtime_is_ssi_multi
(
io
))
...
...
@@ -262,10 +274,10 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
switch
(
runtime
->
sample_bits
)
{
switch
(
snd_pcm_format_width
(
runtime
->
format
)
)
{
case
16
:
return
8
<<
16
;
case
32
:
case
24
:
return
0
<<
16
;
}
...
...
@@ -282,11 +294,12 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
struct
rsnd_mod
*
ssiu
=
rsnd_io_to_mod_ssiu
(
io
);
struct
rsnd_mod
*
target
;
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
u32
val
=
0x76543210
;
u32
mask
=
~
0
;
/*
* *Hardware* L/R and *Software* L/R are inverted.
* *Hardware* L/R and *Software* L/R are inverted for 16bit data.
* 31..16 15...0
* HW: [L ch] [R ch]
* SW: [R ch] [L ch]
* We need to care about inversion timing to control
* Playback/Capture correctly.
* The point is [DVC] needs *Hardware* L/R, [MEM] needs *Software* L/R
...
...
@@ -313,27 +326,13 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
target
=
cmd
?
cmd
:
ssiu
;
}
mask
<<=
runtime
->
channels
*
4
;
val
=
val
&
mask
;
switch
(
runtime
->
sample_bits
)
{
case
16
:
val
|=
0x67452301
&
~
mask
;
break
;
case
32
:
val
|=
0x76543210
&
~
mask
;
break
;
}
/*
* exchange channeles on SRC if possible,
* otherwise, R/L volume settings on DVC
* changes inverted channels
*/
if
(
mod
==
target
)
return
val
;
else
/* Non target mod or 24bit data needs normal DALIGN */
if
((
snd_pcm_format_width
(
runtime
->
format
)
!=
16
)
||
(
mod
!=
target
))
return
0x76543210
;
/* Target mod needs inverted DALIGN when 16bit */
else
return
0x67452301
;
}
u32
rsnd_get_busif_shift
(
struct
rsnd_dai_stream
*
io
,
struct
rsnd_mod
*
mod
)
...
...
@@ -363,12 +362,8 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
* HW 24bit data is located as 0x******00
*
*/
switch
(
runtime
->
sample_bits
)
{
case
16
:
if
(
snd_pcm_format_width
(
runtime
->
format
)
==
16
)
return
0
;
case
32
:
break
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
playback_mods
);
i
++
)
{
tmod
=
rsnd_io_to_mod
(
io
,
mods
[
i
]);
...
...
@@ -616,8 +611,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
rsnd_dai_stream_init
(
io
,
substream
);
ret
=
rsnd_dai_call
(
init
,
io
,
priv
);
if
(
ret
<
0
)
goto
dai_trigger_end
;
...
...
@@ -639,7 +632,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
ret
|=
rsnd_dai_call
(
quit
,
io
,
priv
);
rsnd_dai_stream_quit
(
io
);
break
;
default:
ret
=
-
EINVAL
;
...
...
@@ -784,8 +776,9 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv,
return
snd_interval_refine
(
iv
,
&
p
);
}
static
int
rsnd_soc_hw_rule_rate
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
static
int
__rsnd_soc_hw_rule_rate
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
,
int
is_play
)
{
struct
snd_interval
*
ic_
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
struct
snd_interval
*
ir
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_RATE
);
...
...
@@ -793,25 +786,37 @@ static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
struct
snd_soc_dai
*
dai
=
rule
->
private
;
struct
rsnd_dai
*
rdai
=
rsnd_dai_to_rdai
(
dai
);
struct
rsnd_priv
*
priv
=
rsnd_rdai_to_priv
(
rdai
);
struct
rsnd_dai_stream
*
io
=
is_play
?
&
rdai
->
playback
:
&
rdai
->
capture
;
/*
* possible sampling rate limitation is same as
* 2ch if it supports multi ssi
* and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
*/
ic
=
*
ic_
;
if
(
1
<
rsnd_rdai_ssi_lane_get
(
rdai
))
{
ic
.
min
=
2
;
ic
.
max
=
2
;
}
ic
.
min
=
ic
.
max
=
rsnd_runtime_channel_for_ssi_with_params
(
io
,
params
);
return
rsnd_soc_hw_rule
(
priv
,
rsnd_soc_hw_rate_list
,
ARRAY_SIZE
(
rsnd_soc_hw_rate_list
),
&
ic
,
ir
);
}
static
int
rsnd_soc_hw_rule_rate_playback
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
return
__rsnd_soc_hw_rule_rate
(
params
,
rule
,
1
);
}
static
int
rsnd_soc_hw_rule_rate_capture
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
return
__rsnd_soc_hw_rule_rate
(
params
,
rule
,
0
);
}
static
int
rsnd_soc_hw_rule_channels
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
static
int
__rsnd_soc_hw_rule_channels
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
,
int
is_play
)
{
struct
snd_interval
*
ic_
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_CHANNELS
);
struct
snd_interval
*
ir
=
hw_param_interval
(
params
,
SNDRV_PCM_HW_PARAM_RATE
);
...
...
@@ -819,22 +824,34 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
struct
snd_soc_dai
*
dai
=
rule
->
private
;
struct
rsnd_dai
*
rdai
=
rsnd_dai_to_rdai
(
dai
);
struct
rsnd_priv
*
priv
=
rsnd_rdai_to_priv
(
rdai
);
struct
rsnd_dai_stream
*
io
=
is_play
?
&
rdai
->
playback
:
&
rdai
->
capture
;
/*
* possible sampling rate limitation is same as
* 2ch if it supports multi ssi
* and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
*/
ic
=
*
ic_
;
if
(
1
<
rsnd_rdai_ssi_lane_get
(
rdai
))
{
ic
.
min
=
2
;
ic
.
max
=
2
;
}
ic
.
min
=
ic
.
max
=
rsnd_runtime_channel_for_ssi_with_params
(
io
,
params
);
return
rsnd_soc_hw_rule
(
priv
,
rsnd_soc_hw_channels_list
,
ARRAY_SIZE
(
rsnd_soc_hw_channels_list
),
ir
,
&
ic
);
}
static
int
rsnd_soc_hw_rule_channels_playback
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
return
__rsnd_soc_hw_rule_channels
(
params
,
rule
,
1
);
}
static
int
rsnd_soc_hw_rule_channels_capture
(
struct
snd_pcm_hw_params
*
params
,
struct
snd_pcm_hw_rule
*
rule
)
{
return
__rsnd_soc_hw_rule_channels
(
params
,
rule
,
0
);
}
static
const
struct
snd_pcm_hardware
rsnd_pcm_hardware
=
{
.
info
=
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP
|
...
...
@@ -859,6 +876,8 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
int
ret
;
int
i
;
rsnd_dai_stream_init
(
io
,
substream
);
/*
* Channel Limitation
* It depends on Platform design
...
...
@@ -886,11 +905,17 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
* It depends on Clock Master Mode
*/
if
(
rsnd_rdai_is_clk_master
(
rdai
))
{
int
is_play
=
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
;
snd_pcm_hw_rule_add
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_RATE
,
rsnd_soc_hw_rule_rate
,
dai
,
is_play
?
rsnd_soc_hw_rule_rate_playback
:
rsnd_soc_hw_rule_rate_capture
,
dai
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
-
1
);
snd_pcm_hw_rule_add
(
runtime
,
0
,
SNDRV_PCM_HW_PARAM_CHANNELS
,
rsnd_soc_hw_rule_channels
,
dai
,
is_play
?
rsnd_soc_hw_rule_channels_playback
:
rsnd_soc_hw_rule_channels_capture
,
dai
,
SNDRV_PCM_HW_PARAM_RATE
,
-
1
);
}
...
...
@@ -915,6 +940,8 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
* call rsnd_dai_call without spinlock
*/
rsnd_dai_call
(
nolock_stop
,
io
,
priv
);
rsnd_dai_stream_quit
(
io
);
}
static
const
struct
snd_soc_dai_ops
rsnd_soc_dai_ops
=
{
...
...
@@ -990,7 +1017,7 @@ static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
static
void
__rsnd_dai_probe
(
struct
rsnd_priv
*
priv
,
struct
device_node
*
dai_np
,
int
dai_i
,
int
is_graph
)
int
dai_i
)
{
struct
device_node
*
playback
,
*
capture
;
struct
rsnd_dai_stream
*
io_playback
;
...
...
@@ -1089,13 +1116,13 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
dai_i
=
0
;
if
(
is_graph
)
{
for_each_endpoint_of_node
(
dai_node
,
dai_np
)
{
__rsnd_dai_probe
(
priv
,
dai_np
,
dai_i
,
is_graph
);
__rsnd_dai_probe
(
priv
,
dai_np
,
dai_i
);
rsnd_ssi_parse_hdmi_connection
(
priv
,
dai_np
,
dai_i
);
dai_i
++
;
}
}
else
{
for_each_child_of_node
(
dai_node
,
dai_np
)
__rsnd_dai_probe
(
priv
,
dai_np
,
dai_i
++
,
is_graph
);
__rsnd_dai_probe
(
priv
,
dai_np
,
dai_i
++
);
}
return
0
;
...
...
@@ -1496,6 +1523,8 @@ static int rsnd_remove(struct platform_device *pdev)
};
int
ret
=
0
,
i
;
snd_soc_disconnect_sync
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
...
...
sound/soc/sh/rcar/dma.c
View file @
84d30623
...
...
@@ -71,25 +71,7 @@ static struct rsnd_mod mem = {
static
void
__rsnd_dmaen_complete
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
)
{
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
bool
elapsed
=
false
;
unsigned
long
flags
;
/*
* Renesas sound Gen1 needs 1 DMAC,
* Gen2 needs 2 DMAC.
* In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri.
* But, Audio-DMAC-peri-peri doesn't have interrupt,
* and this driver is assuming that here.
*/
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
if
(
rsnd_io_is_working
(
io
))
elapsed
=
true
;
spin_unlock_irqrestore
(
&
priv
->
lock
,
flags
);
if
(
elapsed
)
rsnd_dai_period_elapsed
(
io
);
}
...
...
sound/soc/sh/rcar/rsnd.h
View file @
84d30623
...
...
@@ -399,9 +399,18 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai,
struct
device_node
*
playback
,
struct
device_node
*
capture
);
int
rsnd_runtime_channel_original
(
struct
rsnd_dai_stream
*
io
);
int
rsnd_runtime_channel_after_ctu
(
struct
rsnd_dai_stream
*
io
);
int
rsnd_runtime_channel_for_ssi
(
struct
rsnd_dai_stream
*
io
);
#define rsnd_runtime_channel_original(io) \
rsnd_runtime_channel_original_with_params(io, NULL)
int
rsnd_runtime_channel_original_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
);
#define rsnd_runtime_channel_after_ctu(io) \
rsnd_runtime_channel_after_ctu_with_params(io, NULL)
int
rsnd_runtime_channel_after_ctu_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
);
#define rsnd_runtime_channel_for_ssi(io) \
rsnd_runtime_channel_for_ssi_with_params(io, NULL)
int
rsnd_runtime_channel_for_ssi_with_params
(
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_hw_params
*
params
);
int
rsnd_runtime_is_ssi_multi
(
struct
rsnd_dai_stream
*
io
);
int
rsnd_runtime_is_ssi_tdm
(
struct
rsnd_dai_stream
*
io
);
...
...
sound/soc/sh/rcar/ssi.c
View file @
84d30623
...
...
@@ -79,8 +79,8 @@ struct rsnd_ssi {
int
irq
;
unsigned
int
usrcnt
;
/* for PIO */
int
byte_pos
;
int
period_pos
;
int
byte_per_period
;
int
next_period_byte
;
};
...
...
@@ -371,11 +371,11 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
if
(
rsnd_io_is_play
(
io
))
cr_own
|=
TRMD
;
switch
(
runtime
->
sample_bits
)
{
switch
(
snd_pcm_format_width
(
runtime
->
format
)
)
{
case
16
:
cr_own
|=
DWL_16
;
break
;
case
32
:
case
24
:
cr_own
|=
DWL_24
;
break
;
}
...
...
@@ -414,63 +414,6 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
ssi
->
cr_en
);
}
static
void
rsnd_ssi_pointer_init
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
)
{
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
ssi
->
byte_pos
=
0
;
ssi
->
period_pos
=
0
;
ssi
->
byte_per_period
=
runtime
->
period_size
*
runtime
->
channels
*
samples_to_bytes
(
runtime
,
1
);
ssi
->
next_period_byte
=
ssi
->
byte_per_period
;
}
static
int
rsnd_ssi_pointer_offset
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
,
int
additional
)
{
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
int
pos
=
ssi
->
byte_pos
+
additional
;
pos
%=
(
runtime
->
periods
*
ssi
->
byte_per_period
);
return
pos
;
}
static
bool
rsnd_ssi_pointer_update
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
,
int
byte
)
{
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
bool
ret
=
false
;
int
byte_pos
;
byte_pos
=
ssi
->
byte_pos
+
byte
;
if
(
byte_pos
>=
ssi
->
next_period_byte
)
{
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
ssi
->
period_pos
++
;
ssi
->
next_period_byte
+=
ssi
->
byte_per_period
;
if
(
ssi
->
period_pos
>=
runtime
->
periods
)
{
byte_pos
=
0
;
ssi
->
period_pos
=
0
;
ssi
->
next_period_byte
=
ssi
->
byte_per_period
;
}
ret
=
true
;
}
WRITE_ONCE
(
ssi
->
byte_pos
,
byte_pos
);
return
ret
;
}
/*
* SSI mod common functions
*/
...
...
@@ -484,8 +427,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
if
(
!
rsnd_ssi_is_run_mods
(
mod
,
io
))
return
0
;
rsnd_ssi_pointer_init
(
mod
,
io
);
ssi
->
usrcnt
++
;
rsnd_mod_power_on
(
mod
);
...
...
@@ -656,6 +597,8 @@ static int rsnd_ssi_irq(struct rsnd_mod *mod,
return
0
;
}
static
bool
rsnd_ssi_pio_interrupt
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
);
static
void
__rsnd_ssi_interrupt
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
)
{
...
...
@@ -674,30 +617,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
status
=
rsnd_ssi_status_get
(
mod
);
/* PIO only */
if
(
!
is_dma
&&
(
status
&
DIRQ
))
{
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
u32
*
buf
=
(
u32
*
)(
runtime
->
dma_area
+
rsnd_ssi_pointer_offset
(
mod
,
io
,
0
));
int
shift
=
0
;
switch
(
runtime
->
sample_bits
)
{
case
32
:
shift
=
8
;
break
;
}
/*
* 8/16/32 data can be assesse to TDR/RDR register
* directly as 32bit data
* see rsnd_ssi_init()
*/
if
(
rsnd_io_is_play
(
io
))
rsnd_mod_write
(
mod
,
SSITDR
,
(
*
buf
)
<<
shift
);
else
*
buf
=
(
rsnd_mod_read
(
mod
,
SSIRDR
)
>>
shift
);
elapsed
=
rsnd_ssi_pointer_update
(
mod
,
io
,
sizeof
(
*
buf
));
}
if
(
!
is_dma
&&
(
status
&
DIRQ
))
elapsed
=
rsnd_ssi_pio_interrupt
(
mod
,
io
);
/* DMA only */
if
(
is_dma
&&
(
status
&
(
UIRQ
|
OIRQ
)))
...
...
@@ -835,7 +756,71 @@ static int rsnd_ssi_common_remove(struct rsnd_mod *mod,
return
0
;
}
static
int
rsnd_ssi_pointer
(
struct
rsnd_mod
*
mod
,
/*
* SSI PIO functions
*/
static
bool
rsnd_ssi_pio_interrupt
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
)
{
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
u32
*
buf
=
(
u32
*
)(
runtime
->
dma_area
+
ssi
->
byte_pos
);
int
shift
=
0
;
int
byte_pos
;
bool
elapsed
=
false
;
if
(
snd_pcm_format_width
(
runtime
->
format
)
==
24
)
shift
=
8
;
/*
* 8/16/32 data can be assesse to TDR/RDR register
* directly as 32bit data
* see rsnd_ssi_init()
*/
if
(
rsnd_io_is_play
(
io
))
rsnd_mod_write
(
mod
,
SSITDR
,
(
*
buf
)
<<
shift
);
else
*
buf
=
(
rsnd_mod_read
(
mod
,
SSIRDR
)
>>
shift
);
byte_pos
=
ssi
->
byte_pos
+
sizeof
(
*
buf
);
if
(
byte_pos
>=
ssi
->
next_period_byte
)
{
int
period_pos
=
byte_pos
/
ssi
->
byte_per_period
;
if
(
period_pos
>=
runtime
->
periods
)
{
byte_pos
=
0
;
period_pos
=
0
;
}
ssi
->
next_period_byte
=
(
period_pos
+
1
)
*
ssi
->
byte_per_period
;
elapsed
=
true
;
}
WRITE_ONCE
(
ssi
->
byte_pos
,
byte_pos
);
return
elapsed
;
}
static
int
rsnd_ssi_pio_init
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
,
struct
rsnd_priv
*
priv
)
{
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
if
(
!
rsnd_ssi_is_parent
(
mod
,
io
))
{
ssi
->
byte_pos
=
0
;
ssi
->
byte_per_period
=
runtime
->
period_size
*
runtime
->
channels
*
samples_to_bytes
(
runtime
,
1
);
ssi
->
next_period_byte
=
ssi
->
byte_per_period
;
}
return
rsnd_ssi_init
(
mod
,
io
,
priv
);
}
static
int
rsnd_ssi_pio_pointer
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai_stream
*
io
,
snd_pcm_uframes_t
*
pointer
)
{
...
...
@@ -851,12 +836,12 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.
name
=
SSI_NAME
,
.
probe
=
rsnd_ssi_common_probe
,
.
remove
=
rsnd_ssi_common_remove
,
.
init
=
rsnd_ssi_init
,
.
init
=
rsnd_ssi_
pio_
init
,
.
quit
=
rsnd_ssi_quit
,
.
start
=
rsnd_ssi_start
,
.
stop
=
rsnd_ssi_stop
,
.
irq
=
rsnd_ssi_irq
,
.
pointer
=
rsnd_ssi
_pointer
,
.
pointer
=
rsnd_ssi_pio
_pointer
,
.
pcm_new
=
rsnd_ssi_pcm_new
,
.
hw_params
=
rsnd_ssi_hw_params
,
};
...
...
sound/soc/soc-core.c
View file @
84d30623
...
...
@@ -1392,6 +1392,16 @@ static int soc_init_dai_link(struct snd_soc_card *card,
return
0
;
}
void
snd_soc_disconnect_sync
(
struct
device
*
dev
)
{
struct
snd_soc_component
*
component
=
snd_soc_lookup_component
(
dev
,
NULL
);
if
(
!
component
||
!
component
->
card
)
return
;
snd_card_disconnect_sync
(
component
->
card
->
snd_card
);
}
/**
* snd_soc_add_dai_link - Add a DAI link dynamically
* @card: The ASoC card to which the DAI link is added
...
...
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