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
7c29e706
Commit
7c29e706
authored
Jan 05, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
parents
f827f9a9
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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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 @
7c29e706
...
...
@@ -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