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
2fd53734
Commit
2fd53734
authored
Aug 04, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
parents
0e76ee41
cd2b6574
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
668 additions
and
621 deletions
+668
-621
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+9
-0
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-armadillo800eva.c
+4
-0
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-kzm9g.c
+2
-0
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-mackerel.c
+4
-0
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-ecovec24/setup.c
+2
-0
include/sound/rcar_snd.h
include/sound/rcar_snd.h
+1
-0
sound/soc/sh/Kconfig
sound/soc/sh/Kconfig
+1
-1
sound/soc/sh/fsi.c
sound/soc/sh/fsi.c
+52
-137
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/core.c
+118
-125
sound/soc/sh/rcar/dvc.c
sound/soc/sh/rcar/dvc.c
+101
-34
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/gen.c
+252
-301
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/rsnd.h
+15
-11
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/src.c
+76
-10
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssi.c
+31
-2
No files found.
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
View file @
2fd53734
...
...
@@ -13,6 +13,9 @@ Required properties:
- rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW.
see below for detail.
- rcar_sound,dvc : Should contain DVC feature.
The number of DVC subnode should be same as HW.
see below for detail.
- rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW.
see below for detail.
...
...
@@ -21,6 +24,7 @@ SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin
- pio-transfer : use PIO transfer mode
- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
SRC subnode properties:
no properties at this point
...
...
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec541000 0 0x1280>; /* SSI */
rcar_sound,dvc {
dvc0: dvc@0 { };
dvc1: dvc@1 { };
};
rcar_sound,src {
src0: src@0 { };
src1: src@1 { };
...
...
arch/arm/mach-shmobile/board-armadillo800eva.c
View file @
2fd53734
...
...
@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
.
id
=
0
,
.
dev
=
{
.
platform_data
=
&
fsi_wm8978_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_wm8978_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
@@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
.
id
=
1
,
.
dev
=
{
.
platform_data
=
&
fsi2_hdmi_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_hdmi_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
arch/arm/mach-shmobile/board-kzm9g.c
View file @
2fd53734
...
...
@@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
platform_data
=
&
fsi2_ak4648_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_ak4648_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
arch/arm/mach-shmobile/board-mackerel.c
View file @
2fd53734
...
...
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
.
id
=
1
,
.
dev
=
{
.
platform_data
=
&
fsi2_hdmi_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_hdmi_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
platform_data
=
&
fsi2_ak4643_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_ak4643_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
arch/sh/boards/mach-ecovec24/setup.c
View file @
2fd53734
...
...
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
platform_data
=
&
fsi_da7210_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_da7210_device
.
dev
.
coherent_dma_mask
,
},
};
...
...
include/sound/rcar_snd.h
View file @
2fd53734
...
...
@@ -34,6 +34,7 @@
* B : SSI direction
*/
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_NO_BUSIF (1 << 30)
/* SSI+DMA without BUSIF */
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
...
...
sound/soc/sh/Kconfig
View file @
2fd53734
...
...
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
select SND_SIMPLE_CARD
select REGMAP
select REGMAP
_MMIO
help
This option enables R-Car SUR/SCU/SSIU/SSI sound support
...
...
sound/soc/sh/fsi.c
View file @
2fd53734
...
...
@@ -232,11 +232,7 @@ struct fsi_stream {
* these are for DMAEngine
*/
struct
dma_chan
*
chan
;
struct
work_struct
work
;
dma_addr_t
dma
;
int
dma_id
;
int
loop_cnt
;
int
additional_pos
;
};
struct
fsi_clk
{
...
...
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
return
ret
;
}
static
void
fsi_pointer_update
(
struct
fsi_stream
*
io
,
int
size
)
{
io
->
buff_sample_pos
+=
size
;
if
(
io
->
buff_sample_pos
>=
io
->
period_samples
*
(
io
->
period_pos
+
1
))
{
struct
snd_pcm_substream
*
substream
=
io
->
substream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
io
->
period_pos
++
;
if
(
io
->
period_pos
>=
runtime
->
periods
)
{
io
->
buff_sample_pos
=
0
;
io
->
period_pos
=
0
;
}
snd_pcm_period_elapsed
(
substream
);
}
}
/*
* pio data transfer handler
*/
...
...
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
void
(
*
run32
)(
struct
fsi_priv
*
fsi
,
u8
*
buf
,
int
samples
),
int
samples
)
{
struct
snd_pcm_runtime
*
runtime
;
struct
snd_pcm_substream
*
substream
;
u8
*
buf
;
int
over_period
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
return
-
EINVAL
;
over_period
=
0
;
substream
=
io
->
substream
;
runtime
=
substream
->
runtime
;
/* FSI FIFO has limit.
* So, this driver can not send periods data at a time
*/
if
(
io
->
buff_sample_pos
>=
io
->
period_samples
*
(
io
->
period_pos
+
1
))
{
over_period
=
1
;
io
->
period_pos
=
(
io
->
period_pos
+
1
)
%
runtime
->
periods
;
if
(
0
==
io
->
period_pos
)
io
->
buff_sample_pos
=
0
;
}
buf
=
fsi_pio_get_area
(
fsi
,
io
);
switch
(
io
->
sample_width
)
{
...
...
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
return
-
EINVAL
;
}
/* update buff_sample_pos */
io
->
buff_sample_pos
+=
samples
;
if
(
over_period
)
snd_pcm_period_elapsed
(
substream
);
fsi_pointer_update
(
io
,
samples
);
return
0
;
}
...
...
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
*/
static
int
fsi_dma_init
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
/*
* 24bit data : 24bit bus / package in back
* 16bit data : 16bit bus / stream mode
...
...
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
io
->
bus_option
=
BUSOP_SET
(
24
,
PACKAGE_24BITBUS_BACK
)
|
BUSOP_SET
(
16
,
PACKAGE_16BITBUS_STREAM
);
io
->
loop_cnt
=
2
;
/* push 1st, 2nd period first, then 3rd, 4th... */
io
->
additional_pos
=
0
;
io
->
dma
=
dma_map_single
(
dai
->
dev
,
runtime
->
dma_area
,
snd_pcm_lib_buffer_bytes
(
io
->
substream
),
dir
);
return
0
;
}
static
int
fsi_dma_quit
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma_unmap_single
(
dai
->
dev
,
io
->
dma
,
snd_pcm_lib_buffer_bytes
(
io
->
substream
),
dir
);
return
0
;
}
static
dma_addr_t
fsi_dma_get_area
(
struct
fsi_stream
*
io
,
int
additional
)
{
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
int
period
=
io
->
period_pos
+
additional
;
if
(
period
>=
runtime
->
periods
)
period
=
0
;
return
io
->
dma
+
samples_to_bytes
(
runtime
,
period
*
io
->
period_samples
);
}
static
void
fsi_dma_complete
(
void
*
data
)
{
struct
fsi_stream
*
io
=
(
struct
fsi_stream
*
)
data
;
struct
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma_sync_single_for_cpu
(
dai
->
dev
,
fsi_dma_get_area
(
io
,
0
),
samples_to_bytes
(
runtime
,
io
->
period_samples
),
dir
);
io
->
buff_sample_pos
+=
io
->
period_samples
;
io
->
period_pos
++
;
if
(
io
->
period_pos
>=
runtime
->
periods
)
{
io
->
period_pos
=
0
;
io
->
buff_sample_pos
=
0
;
}
fsi_pointer_update
(
io
,
io
->
period_samples
);
fsi_count_fifo_err
(
fsi
);
fsi_stream_transfer
(
io
);
snd_pcm_period_elapsed
(
io
->
substream
);
}
static
void
fsi_dma_do_work
(
struct
work_struct
*
work
)
static
int
fsi_dma_transfer
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
struct
fsi_stream
*
io
=
container_of
(
work
,
struct
fsi_stream
,
work
);
struct
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
snd_soc_dai
*
dai
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
struct
snd_pcm_substream
*
substream
=
io
->
substream
;
struct
dma_async_tx_descriptor
*
desc
;
struct
snd_pcm_runtime
*
runtime
;
enum
dma_data_direction
dir
;
int
is_play
=
fsi_stream_is_play
(
fsi
,
io
);
int
len
,
i
;
dma_addr_t
buf
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
return
;
dai
=
fsi_get_dai
(
io
->
substream
);
runtime
=
io
->
substream
->
runtime
;
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
len
=
samples_to_bytes
(
runtime
,
io
->
period_samples
);
for
(
i
=
0
;
i
<
io
->
loop_cnt
;
i
++
)
{
buf
=
fsi_dma_get_area
(
io
,
io
->
additional_pos
);
dma_sync_single_for_device
(
dai
->
dev
,
buf
,
len
,
dir
);
desc
=
dmaengine_prep_slave_single
(
io
->
chan
,
buf
,
len
,
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
dev_err
(
dai
->
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
desc
->
callback
=
fsi_dma_complete
;
desc
->
callback_param
=
io
;
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
return
;
}
enum
dma_data_direction
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
int
ret
=
-
EIO
;
desc
=
dmaengine_prep_dma_cyclic
(
io
->
chan
,
substream
->
runtime
->
dma_addr
,
snd_pcm_lib_buffer_bytes
(
substream
),
snd_pcm_lib_period_bytes
(
substream
),
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
dev_err
(
dai
->
dev
,
"dmaengine_prep_dma_cyclic() fail
\n
"
);
goto
fsi_dma_transfer_err
;
}
dma_async_issue_pending
(
io
->
chan
);
desc
->
callback
=
fsi_dma_complete
;
desc
->
callback_param
=
io
;
io
->
additional_pos
=
1
;
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
goto
fsi_dma_transfer_err
;
}
io
->
loop_cnt
=
1
;
dma_async_issue_pending
(
io
->
chan
)
;
/*
* FIXME
...
...
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
fsi_reg_write
(
fsi
,
DIFF_ST
,
0
);
}
}
}
static
int
fsi_dma_transfer
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
schedule_work
(
&
io
->
work
);
ret
=
0
;
return
0
;
fsi_dma_transfer_err:
return
ret
;
}
static
int
fsi_dma_push_start_stop
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
,
...
...
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
return
fsi_stream_probe
(
fsi
,
dev
);
}
INIT_WORK
(
&
io
->
work
,
fsi_dma_do_work
);
return
0
;
}
static
int
fsi_dma_remove
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
cancel_work_sync
(
&
io
->
work
);
fsi_stream_stop
(
fsi
,
io
);
if
(
io
->
chan
)
...
...
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
static
struct
fsi_stream_handler
fsi_dma_push_handler
=
{
.
init
=
fsi_dma_init
,
.
quit
=
fsi_dma_quit
,
.
probe
=
fsi_dma_probe
,
.
transfer
=
fsi_dma_transfer
,
.
remove
=
fsi_dma_remove
,
...
...
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if
(
!
ret
)
ret
=
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
if
(
!
ret
)
ret
=
fsi_stream_
transfer
(
io
);
ret
=
fsi_stream_
start
(
fsi
,
io
);
if
(
!
ret
)
fsi_stream_start
(
fsi
,
io
);
ret
=
fsi_stream_transfer
(
io
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
if
(
!
ret
)
...
...
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
static
int
fsi_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_pcm
*
pcm
=
rtd
->
pcm
;
/*
* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
* in MMAP mode (i.e. aplay -M)
*/
return
snd_pcm_lib_preallocate_pages_for_all
(
pcm
,
SNDRV_DMA_TYPE_
CONTINUOUS
,
snd_dma_continuous_data
(
GFP_KERNEL
)
,
rtd
->
pcm
,
SNDRV_DMA_TYPE_
DEV
,
rtd
->
card
->
snd_card
->
dev
,
PREALLOC_BUFFER
,
PREALLOC_BUFFER_MAX
);
}
...
...
sound/soc/sh/rcar/core.c
View file @
2fd53734
This diff is collapsed.
Click to expand it.
sound/soc/sh/rcar/dvc.c
View file @
2fd53734
...
...
@@ -20,7 +20,8 @@ struct rsnd_dvc {
struct
rsnd_dvc_platform_info
*
info
;
/* rcar_snd.h */
struct
rsnd_mod
mod
;
struct
clk
*
clk
;
long
volume
[
RSND_DVC_VOLUME_NUM
];
u8
volume
[
RSND_DVC_VOLUME_NUM
];
u8
mute
[
RSND_DVC_VOLUME_NUM
];
};
#define rsnd_mod_to_dvc(_mod) \
...
...
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u32
max
=
(
0x00800000
-
1
);
u32
vol
[
RSND_DVC_VOLUME_NUM
];
u32
mute
=
0
;
int
i
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
vol
[
i
]
=
max
/
RSND_DVC_VOLUME_MAX
*
dvc
->
volume
[
i
];
mute
|=
(
!!
dvc
->
mute
[
i
])
<<
i
;
}
rsnd_mod_write
(
mod
,
DVC_VOL0R
,
vol
[
0
]);
rsnd_mod_write
(
mod
,
DVC_VOL1R
,
vol
[
1
]);
rsnd_mod_write
(
mod
,
DVC_ZCMCR
,
mute
);
}
static
int
rsnd_dvc_probe_gen2
(
struct
rsnd_mod
*
mod
,
...
...
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
rsnd_mod_write
(
dvc_mod
,
DVC_ADINR
,
rsnd_get_adinr
(
dvc_mod
));
/* enable Volume */
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
0
);
/* enable Volume
/ Mute
*/
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
1
);
/* ch0/ch1 Volume */
rsnd_dvc_volume_update
(
dvc_mod
);
...
...
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
static
int
rsnd_dvc_volume_info
(
struct
snd_kcontrol
*
kctrl
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
uinfo
->
count
=
RSND_DVC_VOLUME_NUM
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
if
(
val
==
dvc
->
volume
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
}
else
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
uinfo
->
value
.
integer
.
max
=
1
;
}
return
0
;
}
...
...
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
static
int
rsnd_dvc_volume_get
(
struct
snd_kcontrol
*
kctrl
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
int
i
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
ucontrol
->
value
.
integer
.
value
[
i
]
=
dvc
->
volume
[
i
];
ucontrol
->
value
.
integer
.
value
[
i
]
=
val
[
i
];
return
0
;
}
...
...
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
)
;
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
int
i
,
change
=
0
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
if
(
ucontrol
->
value
.
integer
.
value
[
i
]
<
0
||
ucontrol
->
value
.
integer
.
value
[
i
]
>
RSND_DVC_VOLUME_MAX
)
return
-
EINVAL
;
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
dvc
->
volume
[
i
]);
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
val
[
i
]);
val
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
}
if
(
change
)
{
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
dvc
->
volume
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
if
(
change
)
rsnd_dvc_volume_update
(
mod
);
}
return
change
;
}
static
int
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
__rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
,
const
unsigned
char
*
name
,
u8
*
private
)
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
snd_card
*
card
=
rtd
->
card
->
snd_card
;
struct
snd_kcontrol
*
kctrl
;
st
atic
st
ruct
snd_kcontrol_new
knew
=
{
struct
snd_kcontrol_new
knew
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Playback Volume"
,
.
name
=
name
,
.
info
=
rsnd_dvc_volume_info
,
.
get
=
rsnd_dvc_volume_get
,
.
put
=
rsnd_dvc_volume_put
,
.
private_value
=
(
unsigned
long
)
private
,
};
int
ret
;
if
(
!
rsnd_dai_is_play
(
rdai
,
io
))
{
dev_err
(
dev
,
"DVC%d is connected to Capture DAI
\n
"
,
rsnd_mod_id
(
mod
));
return
-
EINVAL
;
}
kctrl
=
snd_ctl_new1
(
&
knew
,
mod
);
if
(
!
kctrl
)
return
-
ENOMEM
;
...
...
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
return
0
;
}
static
int
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
int
ret
;
/* Volume */
ret
=
__rsnd_dvc_pcm_new
(
mod
,
rdai
,
rtd
,
rsnd_dai_is_play
(
rdai
,
io
)
?
"DVC Out Playback Volume"
:
"DVC In Capture Volume"
,
dvc
->
volume
);
if
(
ret
<
0
)
return
ret
;
/* Mute */
ret
=
__rsnd_dvc_pcm_new
(
mod
,
rdai
,
rtd
,
rsnd_dai_is_play
(
rdai
,
io
)
?
"DVC Out Mute Switch"
:
"DVC In Mute Switch"
,
dvc
->
mute
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
struct
rsnd_mod_ops
rsnd_dvc_ops
=
{
.
name
=
DVC_NAME
,
.
probe
=
rsnd_dvc_probe_gen2
,
...
...
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
return
&
((
struct
rsnd_dvc
*
)(
priv
->
dvc
)
+
id
)
->
mod
;
}
static
void
rsnd_of_parse_dvc
(
struct
platform_device
*
pdev
,
const
struct
rsnd_of_data
*
of_data
,
struct
rsnd_priv
*
priv
)
{
struct
device_node
*
node
;
struct
rsnd_dvc_platform_info
*
dvc_info
;
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
device
*
dev
=
&
pdev
->
dev
;
int
nr
;
if
(
!
of_data
)
return
;
node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,dvc"
);
if
(
!
node
)
return
;
nr
=
of_get_child_count
(
node
);
if
(
!
nr
)
goto
rsnd_of_parse_dvc_end
;
dvc_info
=
devm_kzalloc
(
dev
,
sizeof
(
struct
rsnd_dvc_platform_info
)
*
nr
,
GFP_KERNEL
);
if
(
!
dvc_info
)
{
dev_err
(
dev
,
"dvc info allocation error
\n
"
);
goto
rsnd_of_parse_dvc_end
;
}
info
->
dvc_info
=
dvc_info
;
info
->
dvc_info_nr
=
nr
;
rsnd_of_parse_dvc_end:
of_node_put
(
node
);
}
int
rsnd_dvc_probe
(
struct
platform_device
*
pdev
,
const
struct
rsnd_of_data
*
of_data
,
struct
rsnd_priv
*
priv
)
...
...
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev,
char
name
[
RSND_DVC_NAME_SIZE
];
int
i
,
nr
;
rsnd_of_parse_dvc
(
pdev
,
of_data
,
priv
);
nr
=
info
->
dvc_info_nr
;
if
(
!
nr
)
return
0
;
...
...
sound/soc/sh/rcar/gen.c
View file @
2fd53734
This diff is collapsed.
Click to expand it.
sound/soc/sh/rcar/rsnd.h
View file @
2fd53734
...
...
@@ -90,6 +90,7 @@ enum rsnd_reg {
RSND_REG_SHARE19
,
RSND_REG_SHARE20
,
RSND_REG_SHARE21
,
RSND_REG_SHARE22
,
RSND_REG_MAX
,
};
...
...
@@ -127,6 +128,7 @@ enum rsnd_reg {
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22
struct
rsnd_of_data
;
struct
rsnd_priv
;
...
...
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod);
*/
struct
rsnd_dma
{
struct
sh_dmae_slave
slave
;
struct
work_struct
work
;
struct
dma_chan
*
chan
;
enum
dma_data_direction
dir
;
int
submit_loop
;
int
offset
;
/* it cares A/B plane */
enum
dma_transfer_direction
dir
;
dma_addr_t
addr
;
};
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
...
...
@@ -185,6 +184,7 @@ enum rsnd_mod_type {
struct
rsnd_mod_ops
{
char
*
name
;
char
*
(
*
dma_name
)(
struct
rsnd_mod
*
mod
);
int
(
*
probe
)(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
);
int
(
*
remove
)(
struct
rsnd_mod
*
mod
,
...
...
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
enum
rsnd_mod_type
type
,
int
id
);
char
*
rsnd_mod_name
(
struct
rsnd_mod
*
mod
);
char
*
rsnd_mod_dma_name
(
struct
rsnd_mod
*
mod
);
/*
* R-Car sound DAI
...
...
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
void
__iomem
*
rsnd_gen_reg_get
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
);
void
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
struct
dma_slave_config
*
cfg
,
int
is_play
,
int
slave_id
);
dma_addr_t
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
int
is_play
,
int
is_from
);
#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
#define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
...
...
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
unsigned
int
rsnd_src_get_ssi_rate
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_runtime
*
runtime
);
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
);
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
);
int
rsnd_src_ssiu_stop
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
);
int
rsnd_src_enable_ssi_irq
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
);
...
...
sound/soc/sh/rcar/src.c
View file @
2fd53734
...
...
@@ -106,18 +106,19 @@ struct rsnd_src {
/*
* Gen1/Gen2 common functions
*/
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
)
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
)
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
ssi_mod
);
struct
rsnd_mod
*
src_mod
=
rsnd_io_to_mod_src
(
io
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
int
ssi_id
=
rsnd_mod_id
(
ssi_mod
);
/*
* SSI_MODE0
*/
rsnd_mod_bset
(
ssi_mod
,
SSI_MODE0
,
(
1
<<
ssi_id
),
src_mod
?
0
:
(
1
<<
ssi_id
)
);
!
use_busif
<<
ssi_id
);
/*
* SSI_MODE1
...
...
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
0x2
<<
shift
:
0x1
<<
shift
);
}
/*
* DMA settings for SSIU
*/
if
(
use_busif
)
{
u32
val
=
0x76543210
;
u32
mask
=
~
0
;
rsnd_mod_write
(
ssi_mod
,
SSI_BUSIF_ADINR
,
rsnd_get_adinr
(
ssi_mod
));
rsnd_mod_write
(
ssi_mod
,
SSI_BUSIF_MODE
,
1
);
rsnd_mod_write
(
ssi_mod
,
SSI_CTRL
,
0x1
);
mask
<<=
runtime
->
channels
*
4
;
val
=
val
&
mask
;
switch
(
runtime
->
sample_bits
)
{
case
16
:
val
|=
0x67452301
&
~
mask
;
break
;
case
32
:
val
|=
0x76543210
&
~
mask
;
break
;
}
rsnd_mod_write
(
ssi_mod
,
BUSIF_DALIGN
,
val
);
}
return
0
;
}
int
rsnd_src_ssiu_stop
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
)
{
/*
* DMA settings for SSIU
*/
if
(
use_busif
)
rsnd_mod_write
(
ssi_mod
,
SSI_CTRL
,
0
);
return
0
;
}
...
...
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
static
int
rsnd_src_set_convert_rate_gen2
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
)
{
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
struct
rsnd_src
*
src
=
rsnd_mod_to_src
(
mod
);
uint
ratio
;
int
ret
;
/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
if
(
!
rsnd_src_convert_rate
(
src
))
ratio
=
0
;
else
if
(
rsnd_src_convert_rate
(
src
)
>
runtime
->
rate
)
ratio
=
100
*
rsnd_src_convert_rate
(
src
)
/
runtime
->
rate
;
else
ratio
=
100
*
runtime
->
rate
/
rsnd_src_convert_rate
(
src
);
if
(
ratio
>
600
)
{
dev_err
(
dev
,
"FSO/FSI ratio error
\n
"
);
return
-
EINVAL
;
}
ret
=
rsnd_src_set_convert_rate
(
mod
,
rdai
);
if
(
ret
<
0
)
return
ret
;
rsnd_mod_write
(
mod
,
SSI_BUSIF_ADINR
,
rsnd_get_adinr
(
mod
));
rsnd_mod_write
(
mod
,
SSI_BUSIF_MODE
,
1
);
rsnd_mod_write
(
mod
,
SRC_SRCCR
,
0x00011110
);
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x01800000
);
switch
(
rsnd_mod_id
(
mod
))
{
case
5
:
case
6
:
case
7
:
case
8
:
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x02400000
);
break
;
default:
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x01800000
);
break
;
}
rsnd_mod_write
(
mod
,
SRC_BSISR
,
0x00100060
);
return
0
;
...
...
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
rsnd_dma_start
(
rsnd_mod_to_dma
(
&
src
->
mod
));
rsnd_mod_write
(
mod
,
SSI_CTRL
,
0x1
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
val
);
return
rsnd_src_start
(
mod
,
rdai
);
...
...
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
{
struct
rsnd_src
*
src
=
rsnd_mod_to_src
(
mod
);
rsnd_mod_write
(
mod
,
SSI_CTRL
,
0
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
0
);
rsnd_dma_stop
(
rsnd_mod_to_dma
(
&
src
->
mod
));
...
...
sound/soc/sh/rcar/ssi.c
View file @
2fd53734
...
...
@@ -90,6 +90,20 @@ struct rsnd_ssi {
#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
static
int
rsnd_ssi_use_busif
(
struct
rsnd_mod
*
mod
)
{
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
int
use_busif
=
0
;
if
(
!
(
rsnd_ssi_mode_flags
(
ssi
)
&
RSND_SSI_NO_BUSIF
))
use_busif
=
1
;
if
(
rsnd_io_to_mod_src
(
io
))
use_busif
=
1
;
return
use_busif
;
}
static
void
rsnd_ssi_status_check
(
struct
rsnd_mod
*
mod
,
u32
bit
)
{
...
...
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
ssi
->
cr_own
=
cr
;
ssi
->
err
=
-
1
;
/* ignore 1st error */
rsnd_src_ssi_mode_init
(
mod
,
rdai
);
return
0
;
}
...
...
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
/* enable PIO IRQ */
ssi
->
cr_etc
=
UIEN
|
OIEN
|
DIEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
0
);
rsnd_src_enable_ssi_irq
(
mod
,
rdai
);
rsnd_ssi_hw_start
(
ssi
,
rdai
,
io
);
...
...
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
rsnd_ssi_hw_stop
(
ssi
,
rdai
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
0
);
return
0
;
}
...
...
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
/* enable DMA transfer */
ssi
->
cr_etc
=
DMEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
rsnd_ssi_use_busif
(
mod
));
rsnd_dma_start
(
dma
);
rsnd_ssi_hw_start
(
ssi
,
ssi
->
rdai
,
io
);
...
...
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
rsnd_dma_stop
(
dma
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
1
);
return
0
;
}
static
char
*
rsnd_ssi_dma_name
(
struct
rsnd_mod
*
mod
)
{
return
rsnd_ssi_use_busif
(
mod
)
?
"ssiu"
:
SSI_NAME
;
}
static
struct
rsnd_mod_ops
rsnd_ssi_dma_ops
=
{
.
name
=
SSI_NAME
,
.
dma_name
=
rsnd_ssi_dma_name
,
.
probe
=
rsnd_ssi_dma_probe
,
.
remove
=
rsnd_ssi_dma_remove
,
.
init
=
rsnd_ssi_init
,
...
...
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev,
*/
ssi_info
->
dma_id
=
of_get_property
(
np
,
"pio-transfer"
,
NULL
)
?
0
:
1
;
if
(
of_get_property
(
np
,
"no-busif"
,
NULL
))
ssi_info
->
flags
|=
RSND_SSI_NO_BUSIF
;
}
rsnd_of_parse_ssi_end:
...
...
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