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
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
...
...
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
return
mod
->
ops
->
name
;
}
char
*
rsnd_mod_dma_name
(
struct
rsnd_mod
*
mod
)
{
if
(
!
mod
||
!
mod
->
ops
)
return
"unknown"
;
if
(
!
mod
->
ops
->
dma_name
)
return
mod
->
ops
->
name
;
return
mod
->
ops
->
dma_name
(
mod
);
}
void
rsnd_mod_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod_ops
*
ops
,
...
...
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv,
/*
* rsnd_dma functions
*/
static
void
__rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
static
void
rsnd_dma_continue
(
struct
rsnd_dma
*
dma
)
{
/* push next A or B plane */
dma
->
submit_loop
=
1
;
schedule_work
(
&
dma
->
work
);
}
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
{
/* push both A and B plane*/
dma
->
offset
=
0
;
dma
->
submit_loop
=
2
;
__rsnd_dma_start
(
dma
);
}
void
rsnd_dma_stop
(
struct
rsnd_dma
*
dma
)
{
dma
->
submit_loop
=
0
;
cancel_work_sync
(
&
dma
->
work
);
dmaengine_terminate_all
(
dma
->
chan
);
}
...
...
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data)
{
struct
rsnd_dma
*
dma
=
(
struct
rsnd_dma
*
)
data
;
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
rsnd_dma_to_mod
(
dma
));
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
unsigned
long
flags
;
rsnd_lock
(
priv
,
flags
);
/*
* Renesas sound Gen1 needs 1 DMAC,
...
...
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data)
* rsnd_dai_pointer_update() will be called twice,
* ant it will breaks io->byte_pos
*/
if
(
dma
->
submit_loop
)
rsnd_dma_continue
(
dma
);
rsnd_unlock
(
priv
,
flags
);
rsnd_dai_pointer_update
(
io
,
io
->
byte_per_period
);
}
static
void
__
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
{
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
snd_pcm_
runtime
*
runtime
=
rsnd_io_to_runtime
(
io
)
;
struct
snd_pcm_
substream
*
substream
=
io
->
substream
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
dma_async_tx_descriptor
*
desc
;
dma_addr_t
buf
;
size_t
len
=
io
->
byte_per_period
;
int
i
;
for
(
i
=
0
;
i
<
dma
->
submit_loop
;
i
++
)
{
buf
=
runtime
->
dma_addr
+
rsnd_dai_pointer_offset
(
io
,
dma
->
offset
+
len
);
dma
->
offset
=
len
;
desc
=
dmaengine_prep_slave_single
(
dma
->
chan
,
buf
,
len
,
dma
->
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
desc
=
dmaengine_prep_dma_cyclic
(
dma
->
chan
,
(
dma
->
addr
)
?
dma
->
addr
:
substream
->
runtime
->
dma_addr
,
snd_pcm_lib_buffer_bytes
(
substream
),
snd_pcm_lib_period_bytes
(
substream
),
dma
->
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
desc
->
callback
=
rsnd_dma_complete
;
desc
->
callback_param
=
dma
;
if
(
!
desc
)
{
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dev
,
"dmaengine_submit() fail
\n
"
);
return
;
}
desc
->
callback
=
rsnd_dma_complete
;
desc
->
callback_param
=
dma
;
dma_async_issue_pending
(
dma
->
chan
);
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dev
,
"dmaengine_submit() fail
\n
"
);
return
;
}
}
static
void
rsnd_dma_do_work
(
struct
work_struct
*
work
)
{
struct
rsnd_dma
*
dma
=
container_of
(
work
,
struct
rsnd_dma
,
work
);
__rsnd_dma_start
(
dma
);
dma_async_issue_pending
(
dma
->
chan
);
}
int
rsnd_dma_available
(
struct
rsnd_dma
*
dma
)
...
...
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
{
if
(
mod
)
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"%s%d"
,
rsnd_mod_name
(
mod
),
rsnd_mod_id
(
mod
));
rsnd_mod_
dma_
name
(
mod
),
rsnd_mod_id
(
mod
));
else
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"mem"
);
}
static
void
rsnd_dma_of_name
(
struct
rsnd_dma
*
dma
,
int
is_play
,
char
*
dma_name
)
static
void
rsnd_dma_of_name
(
struct
rsnd_mod
*
mod_from
,
struct
rsnd_mod
*
mod_to
,
char
*
dma_name
)
{
int
index
=
0
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
mod_from
);
*
(
dma_name
+
index
++
)
=
'_'
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
mod_to
);
}
static
void
rsnd_dma_of_path
(
struct
rsnd_dma
*
dma
,
int
is_play
,
struct
rsnd_mod
**
mod_from
,
struct
rsnd_mod
**
mod_to
)
{
struct
rsnd_mod
*
this
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
this
);
...
...
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
struct
rsnd_mod
*
src
=
rsnd_io_to_mod_src
(
io
);
struct
rsnd_mod
*
dvc
=
rsnd_io_to_mod_dvc
(
io
);
struct
rsnd_mod
*
mod
[
MOD_MAX
];
struct
rsnd_mod
*
src_mod
,
*
dst_mod
;
int
i
,
index
;
...
...
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
mod
[
i
]
=
src
;
src
=
NULL
;
}
else
{
mod
[
i
]
=
dvc
;
if
((
!
is_play
)
&&
(
this
==
src
))
this
=
dvc
;
mod
[
i
]
=
(
is_play
)
?
src
:
dvc
;
i
++
;
mod
[
i
]
=
(
is_play
)
?
dvc
:
src
;
src
=
NULL
;
dvc
=
NULL
;
}
...
...
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
}
if
(
is_play
)
{
src_mod
=
mod
[
index
-
1
];
dst_mod
=
mod
[
index
];
*
mod_from
=
mod
[
index
-
1
];
*
mod_to
=
mod
[
index
];
}
else
{
src_mod
=
mod
[
index
];
dst_mod
=
mod
[
index
-
1
];
*
mod_from
=
mod
[
index
];
*
mod_to
=
mod
[
index
-
1
];
}
index
=
0
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
src_mod
);
*
(
dma_name
+
index
++
)
=
'_'
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
dst_mod
);
}
int
rsnd_dma_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
...
...
@@ -331,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
dma_slave_config
cfg
;
struct
rsnd_mod
*
mod_from
;
struct
rsnd_mod
*
mod_to
;
char
dma_name
[
DMA_NAME_SIZE
];
dma_cap_mask_t
mask
;
int
ret
;
...
...
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
if
(
dev
->
of_node
)
rsnd_dma_of_name
(
dma
,
is_play
,
dma_name
);
else
snprintf
(
dma_name
,
DMA_NAME_SIZE
,
is_play
?
"tx"
:
"rx"
);
rsnd_dma_of_path
(
dma
,
is_play
,
&
mod_from
,
&
mod_to
);
rsnd_dma_of_name
(
mod_from
,
mod_to
,
dma_name
);
cfg
.
slave_id
=
id
;
cfg
.
direction
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
cfg
.
src_addr
=
rsnd_gen_dma_addr
(
priv
,
mod_from
,
is_play
,
1
);
cfg
.
dst_addr
=
rsnd_gen_dma_addr
(
priv
,
mod_to
,
is_play
,
0
);
cfg
.
src_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
cfg
.
dst_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
dev_dbg
(
dev
,
"dma name : %s
\n
"
,
dma_name
);
dev_dbg
(
dev
,
"dma : %s %pad -> %pad
\n
"
,
dma_name
,
&
cfg
.
src_addr
,
&
cfg
.
dst_addr
);
dma
->
chan
=
dma_request_slave_channel_compat
(
mask
,
shdma_chan_filter
,
(
void
*
)
id
,
dev
,
...
...
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
return
-
EIO
;
}
rsnd_gen_dma_addr
(
priv
,
dma
,
&
cfg
,
is_play
,
id
);
ret
=
dmaengine_slave_config
(
dma
->
chan
,
&
cfg
);
if
(
ret
<
0
)
goto
rsnd_dma_init_err
;
dma
->
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
INIT_WORK
(
&
dma
->
work
,
rsnd_dma_do_work
)
;
dma
->
addr
=
is_play
?
cfg
.
src_addr
:
cfg
.
dst_addr
;
dma
->
dir
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
return
0
;
...
...
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return
-
EINVAL
;
}
/* set clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_IF
:
rdai
->
bit_clk_inv
=
0
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
rdai
->
bit_clk_inv
=
1
;
rdai
->
frm_clk_inv
=
0
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
rdai
->
bit_clk_inv
=
1
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_NB_NF
:
default:
rdai
->
bit_clk_inv
=
0
;
rdai
->
frm_clk_inv
=
0
;
break
;
}
/* set format */
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
rdai
->
sys_delay
=
0
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
0
;
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
rdai
->
sys_delay
=
1
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
rdai
->
sys_delay
=
1
;
rdai
->
data_alignment
=
1
;
rdai
->
frm_clk_inv
=
1
;
break
;
}
/* set clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_IF
:
rdai
->
bit_clk_inv
=
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
!
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
rdai
->
bit_clk_inv
=
!
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
rdai
->
bit_clk_inv
=
!
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
!
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_NB_NF
:
default:
break
;
}
...
...
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
struct
device_node
*
dai_node
,
*
dai_np
;
struct
device_node
*
ssi_node
,
*
ssi_np
;
struct
device_node
*
src_node
,
*
src_np
;
struct
device_node
*
dvc_node
,
*
dvc_np
;
struct
device_node
*
playback
,
*
capture
;
struct
rsnd_dai_platform_info
*
dai_info
;
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
device
*
dev
=
&
pdev
->
dev
;
int
nr
,
i
;
int
dai_i
,
ssi_i
,
src_i
;
int
dai_i
,
ssi_i
,
src_i
,
dvc_i
;
if
(
!
of_data
)
return
;
...
...
@@ -767,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
ssi_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,ssi"
);
src_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,src"
);
dvc_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,dvc"
);
#define mod_parse(name) \
if (name##_node) { \
...
...
@@ -802,6 +796,7 @@ if (name##_node) { \
mod_parse
(
ssi
);
mod_parse
(
src
);
mod_parse
(
dvc
);
if
(
playback
)
of_node_put
(
playback
);
...
...
@@ -950,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
static
int
rsnd_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
rsnd_priv
*
priv
=
snd_soc_dai_get_drvdata
(
rtd
->
cpu_dai
)
;
struct
rsnd_dai
*
rdai
;
int
i
,
ret
;
struct
snd_soc_dai
*
dai
=
rtd
->
cpu_dai
;
struct
rsnd_dai
*
rdai
=
rsnd_dai_to_rdai
(
dai
)
;
int
ret
;
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
}
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
return
snd_pcm_lib_preallocate_pages_for_all
(
rtd
->
pcm
,
...
...
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev)
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
}
/*
...
...
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev)
exit_snd_soc:
snd_soc_unregister_platform
(
dev
);
exit_snd_probe:
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
}
return
ret
;
}
...
...
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev)
{
struct
rsnd_priv
*
priv
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
rsnd_dai
*
rdai
;
int
ret
,
i
;
int
ret
=
0
,
i
;
pm_runtime_disable
(
&
pdev
->
dev
);
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
return
ret
;
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
}
return
0
;
return
ret
;
}
static
struct
platform_driver
rsnd_driver
=
{
...
...
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
...
...
@@ -15,63 +15,35 @@ struct rsnd_gen {
struct
rsnd_gen_ops
*
ops
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap
[
RSND_BASE_MAX
]
;
struct
regmap_field
*
regs
[
RSND_REG_MAX
];
};
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
[id] = { \
.reg = (unsigned int)gen->base[reg_id] + offset, \
.lsb = 0, \
.msb = 31, \
.id_size = _id_size, \
.id_offset = _id_offset, \
}
/*
* basic function
*/
static
int
rsnd_regmap_write32
(
void
*
context
,
const
void
*
_data
,
size_t
count
)
{
struct
rsnd_priv
*
priv
=
context
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
*
data
=
(
u32
*
)
_data
;
u32
val
=
data
[
1
];
void
__iomem
*
reg
=
(
void
*
)
data
[
0
];
iowrite32
(
val
,
reg
);
dev_dbg
(
dev
,
"w %p : %08x
\n
"
,
reg
,
val
);
return
0
;
}
static
int
rsnd_regmap_read32
(
void
*
context
,
const
void
*
_data
,
size_t
reg_size
,
void
*
_val
,
size_t
val_size
)
{
struct
rsnd_priv
*
priv
=
context
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
*
data
=
(
u32
*
)
_data
;
u32
*
val
=
(
u32
*
)
_val
;
void
__iomem
*
reg
=
(
void
*
)
data
[
0
];
*
val
=
ioread32
(
reg
);
dev_dbg
(
dev
,
"r %p : %08x
\n
"
,
reg
,
*
val
);
struct
rsnd_regmap_field_conf
{
int
idx
;
unsigned
int
reg_offset
;
unsigned
int
id_offset
;
};
return
0
;
#define RSND_REG_SET(id, offset, _id_offset) \
{ \
.idx = id, \
.reg_offset = offset, \
.id_offset = _id_offset, \
}
/* single address mapping */
#define RSND_GEN_S_REG(id, offset) \
RSND_REG_SET(RSND_REG_##id, offset, 0)
static
struct
regmap_bus
rsnd_regmap_bus
=
{
.
write
=
rsnd_regmap_write32
,
.
read
=
rsnd_regmap_read32
,
.
reg_format_endian_default
=
REGMAP_ENDIAN_NATIVE
,
.
val_format_endian_default
=
REGMAP_ENDIAN_NATIVE
,
};
/* multi address mapping */
#define RSND_GEN_M_REG(id, offset, _id_offset) \
RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
/*
* basic function
*/
static
int
rsnd_is_accessible_reg
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
,
enum
rsnd_reg
reg
)
{
...
...
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
u32
val
;
...
...
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv,
regmap_fields_read
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
&
val
);
dev_dbg
(
dev
,
"r %s - 0x%04d : %08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
val
);
return
val
;
}
...
...
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
data
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
return
;
regmap_fields_write
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
data
);
dev_dbg
(
dev
,
"w %s - 0x%04d : %08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
data
);
}
void
rsnd_bset
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
mask
,
u32
data
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
...
...
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
regmap_fields_update_bits
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
mask
,
data
);
dev_dbg
(
dev
,
"b %s - 0x%04d : %08x/%08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
data
,
mask
);
}
static
int
rsnd_gen_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
,
struct
reg_field
*
regf
)
#define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \
_rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf))
static
int
_rsnd_gen_regmap_init
(
struct
rsnd_priv
*
priv
,
int
id_size
,
int
reg_id
,
struct
rsnd_regmap_field_conf
*
conf
,
int
conf_size
)
{
int
i
;
struct
platform_device
*
pdev
=
rsnd_priv_to_pdev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
resource
*
res
;
struct
regmap_config
regc
;
struct
regmap_field
*
regs
;
struct
regmap
*
regmap
;
struct
reg_field
regf
;
void
__iomem
*
base
;
int
i
;
memset
(
&
regc
,
0
,
sizeof
(
regc
));
regc
.
reg_bits
=
32
;
regc
.
val_bits
=
32
;
regc
.
reg_stride
=
4
;
gen
->
regmap
=
devm_regmap_init
(
dev
,
&
rsnd_regmap_bus
,
priv
,
&
regc
);
if
(
IS_ERR
(
gen
->
regmap
))
{
dev_err
(
dev
,
"regmap error %ld
\n
"
,
PTR_ERR
(
gen
->
regmap
));
return
PTR_ERR
(
gen
->
regmap
);
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
reg_id
);
if
(
!
res
)
return
-
ENODEV
;
base
=
devm_ioremap_resource
(
dev
,
res
);
if
(
IS_ERR
(
base
))
return
PTR_ERR
(
base
);
regmap
=
devm_regmap_init_mmio
(
dev
,
base
,
&
regc
);
if
(
IS_ERR
(
regmap
))
return
PTR_ERR
(
regmap
);
gen
->
base
[
reg_id
]
=
base
;
gen
->
regmap
[
reg_id
]
=
regmap
;
for
(
i
=
0
;
i
<
RSND_REG_MAX
;
i
++
)
{
gen
->
regs
[
i
]
=
NULL
;
if
(
!
regf
[
i
].
reg
)
continue
;
for
(
i
=
0
;
i
<
conf_size
;
i
++
)
{
gen
->
regs
[
i
]
=
devm_regmap_field_alloc
(
dev
,
gen
->
regmap
,
regf
[
i
]);
if
(
IS_ERR
(
gen
->
regs
[
i
]))
return
PTR_ERR
(
gen
->
regs
[
i
]);
regf
.
reg
=
conf
[
i
].
reg_offset
;
regf
.
id_offset
=
conf
[
i
].
id_offset
;
regf
.
lsb
=
0
;
regf
.
msb
=
31
;
regf
.
id_size
=
id_size
;
regs
=
devm_regmap_field_alloc
(
dev
,
regmap
,
regf
);
if
(
IS_ERR
(
regs
))
return
PTR_ERR
(
regs
);
gen
->
regs
[
conf
[
i
].
idx
]
=
regs
;
}
return
0
;
...
...
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
*
* ex) R-Car H2 case
* mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
* SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000
* SSI : 0xec541000 / 0xec241008 / 0xec24100c
* SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
* SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
* CMD : 0xec500000 /
0xec008000
0xec308000
* CMD : 0xec500000 /
/ 0xec008000
0xec308000
*/
#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
#define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
...
...
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
static
void
rsnd_gen2_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
struct
dma_slave_config
*
cfg
,
int
is_play
,
int
slave_id
)
static
dma_addr_t
rsnd_gen2_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
int
is_play
,
int
is_from
)
{
struct
platform_device
*
pdev
=
rsnd_priv_to_pdev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
dma_addr_t
ssi_reg
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSI
)
->
start
;
...
...
@@ -202,179 +212,152 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
int
use_dvc
=
!!
rsnd_io_to_mod_dvc
(
io
);
int
id
=
rsnd_mod_id
(
mod
);
struct
dma_addr
{
dma_addr_t
src_addr
;
dma_addr_t
dst_addr
;
}
dma_addrs
[
2
][
2
][
3
]
=
{
{
/* SRC */
/* Capture */
{{
0
,
0
},
{
RDMA_SRC_O_N
(
src
,
id
),
0
},
{
RDMA_CMD_O_N
(
src
,
id
),
0
}},
/* Playback */
{{
0
,
0
,
},
{
0
,
RDMA_SRC_I_N
(
src
,
id
)
},
{
0
,
RDMA_SRC_I_N
(
src
,
id
)
}}
},
{
/* SSI */
/* Capture */
{{
RDMA_SSI_O_N
(
ssi
,
id
),
0
},
{
RDMA_SSI_O_P
(
ssi
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
},
{
RDMA_SSI_O_P
(
ssi
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
}},
/* Playback */
{{
0
,
RDMA_SSI_I_N
(
ssi
,
id
)
},
{
RDMA_SRC_O_P
(
src
,
id
),
RDMA_SSI_I_P
(
ssi
,
id
)
},
{
RDMA_CMD_O_P
(
src
,
id
),
RDMA_SSI_I_P
(
ssi
,
id
)
}}
}
dma_addr_t
out_addr
;
dma_addr_t
in_addr
;
}
dma_addrs
[
3
][
2
][
3
]
=
{
/* SRC */
{{{
0
,
0
},
/* Capture */
{
RDMA_SRC_O_N
(
src
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
},
{
RDMA_CMD_O_N
(
src
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
}
},
/* Playback */
{{
0
,
0
,
},
{
RDMA_SRC_O_P
(
src
,
id
),
RDMA_SRC_I_N
(
src
,
id
)
},
{
RDMA_CMD_O_P
(
src
,
id
),
RDMA_SRC_I_N
(
src
,
id
)
}
}
},
/* SSI */
/* Capture */
{{{
RDMA_SSI_O_N
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
}
},
/* Playback */
{{
0
,
RDMA_SSI_I_N
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
}
}
},
/* SSIU */
/* Capture */
{{{
RDMA_SSIU_O_N
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
}
},
/* Playback */
{{
0
,
RDMA_SSIU_I_N
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
}
}
},
};
/* it shouldn't happen */
if
(
use_dvc
&
!
use_src
)
{
if
(
use_dvc
&
!
use_src
)
dev_err
(
dev
,
"DVC is selected without SRC
\n
"
);
return
;
}
cfg
->
src_addr
=
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
src_addr
;
cfg
->
dst_addr
=
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
dst_addr
;
/* use SSIU or SSI ? */
if
(
is_ssi
&&
(
0
==
strcmp
(
rsnd_mod_dma_name
(
mod
),
"ssiu"
)))
is_ssi
++
;
dev_dbg
(
dev
,
"dma%d addr - src : %x / dst : %x
\n
"
,
id
,
cfg
->
src_addr
,
cfg
->
dst_addr
);
return
(
is_from
)
?
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
out_addr
:
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
in_addr
;
}
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
)
{
cfg
->
slave_id
=
slave_id
;
cfg
->
src_addr
=
0
;
cfg
->
dst_addr
=
0
;
cfg
->
direction
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
/*
* gen1 uses default DMA addr
*/
if
(
rsnd_is_gen1
(
priv
))
return
;
return
0
;
rsnd_gen2_dma_addr
(
priv
,
dma
,
cfg
,
is_play
,
slave_id
);
}
if
(
!
mod
)
return
0
;
return
rsnd_gen2_dma_addr
(
priv
,
mod
,
is_play
,
is_from
);
}
/*
* Gen2
*/
/* single address mapping */
#define RSND_GEN2_S_REG(gen, reg, id, offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
/* multi address mapping */
#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
static
int
rsnd_gen2_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
)
{
struct
reg_field
regf
[
RSND_REG_MAX
]
=
{
RSND_GEN2_S_REG
(
gen
,
SSIU
,
SSI_MODE0
,
0x800
),
RSND_GEN2_S_REG
(
gen
,
SSIU
,
SSI_MODE1
,
0x804
),
/* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_BUSIF_MODE
,
0x0
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_BUSIF_ADINR
,
0x4
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_CTRL
,
0x10
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
INT_ENABLE
,
0x18
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BUSIF_MODE
,
0x0
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_ROUTE_MODE0
,
0xc
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_CTRL
,
0x10
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
CMD_ROUTE_SLCT
,
0x18c
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
CMD_CTRL
,
0x190
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BSDSR
,
0x22c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BSISR
,
0x238
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_SWRSR
,
0xe00
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUIR
,
0xe04
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_ADINR
,
0xe08
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUCR
,
0xe10
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_ZCMCR
,
0xe14
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_VOL0R
,
0xe28
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_VOL1R
,
0xe2c
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUER
,
0xe48
,
0x100
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
BRRA
,
0x00
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
BRRB
,
0x04
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SSICKR
,
0x08
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL2
,
0x14
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
DIV_EN
,
0x30
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL0
,
0x34
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL1
,
0x38
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL2
,
0x3c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL3
,
0x40
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL4
,
0x44
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL0
,
0x48
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL1
,
0x4c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL2
,
0x50
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL3
,
0x54
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL4
,
0x58
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
CMDOUT_TIMSEL
,
0x5c
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSICR
,
0x00
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSISR
,
0x04
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSITDR
,
0x08
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSIWSR
,
0x20
,
0x40
),
};
return
rsnd_gen_regmap_init
(
priv
,
gen
,
regf
);
}
static
int
rsnd_gen2_probe
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
resource
*
scu_res
;
struct
resource
*
adg_res
;
struct
resource
*
ssiu_res
;
struct
resource
*
ssi_res
;
int
ret
;
/*
* map address
*/
scu_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SCU
);
adg_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_ADG
);
ssiu_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSIU
);
ssi_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSI
);
gen
->
base
[
RSND_GEN2_SCU
]
=
devm_ioremap_resource
(
dev
,
scu_res
);
gen
->
base
[
RSND_GEN2_ADG
]
=
devm_ioremap_resource
(
dev
,
adg_res
);
gen
->
base
[
RSND_GEN2_SSIU
]
=
devm_ioremap_resource
(
dev
,
ssiu_res
);
gen
->
base
[
RSND_GEN2_SSI
]
=
devm_ioremap_resource
(
dev
,
ssi_res
);
if
(
IS_ERR
(
gen
->
base
[
RSND_GEN2_SCU
])
||
IS_ERR
(
gen
->
base
[
RSND_GEN2_ADG
])
||
IS_ERR
(
gen
->
base
[
RSND_GEN2_SSIU
])
||
IS_ERR
(
gen
->
base
[
RSND_GEN2_SSI
]))
return
-
ENODEV
;
ret
=
rsnd_gen2_regmap_init
(
priv
,
gen
);
if
(
ret
<
0
)
return
ret
;
dev_dbg
(
dev
,
"Gen2 device probed
\n
"
);
dev_dbg
(
dev
,
"SCU : %pap => %p
\n
"
,
&
scu_res
->
start
,
gen
->
base
[
RSND_GEN2_SCU
]);
dev_dbg
(
dev
,
"ADG : %pap => %p
\n
"
,
&
adg_res
->
start
,
gen
->
base
[
RSND_GEN2_ADG
]);
dev_dbg
(
dev
,
"SSIU : %pap => %p
\n
"
,
&
ssiu_res
->
start
,
gen
->
base
[
RSND_GEN2_SSIU
]);
dev_dbg
(
dev
,
"SSI : %pap => %p
\n
"
,
&
ssi_res
->
start
,
gen
->
base
[
RSND_GEN2_SSI
]);
struct
rsnd_regmap_field_conf
conf_ssiu
[]
=
{
RSND_GEN_S_REG
(
SSI_MODE0
,
0x800
),
RSND_GEN_S_REG
(
SSI_MODE1
,
0x804
),
/* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN_M_REG
(
SSI_BUSIF_MODE
,
0x0
,
0x80
),
RSND_GEN_M_REG
(
SSI_BUSIF_ADINR
,
0x4
,
0x80
),
RSND_GEN_M_REG
(
BUSIF_DALIGN
,
0x8
,
0x80
),
RSND_GEN_M_REG
(
SSI_CTRL
,
0x10
,
0x80
),
RSND_GEN_M_REG
(
INT_ENABLE
,
0x18
,
0x80
),
};
struct
rsnd_regmap_field_conf
conf_scu
[]
=
{
RSND_GEN_M_REG
(
SRC_BUSIF_MODE
,
0x0
,
0x20
),
RSND_GEN_M_REG
(
SRC_ROUTE_MODE0
,
0xc
,
0x20
),
RSND_GEN_M_REG
(
SRC_CTRL
,
0x10
,
0x20
),
RSND_GEN_M_REG
(
CMD_ROUTE_SLCT
,
0x18c
,
0x20
),
RSND_GEN_M_REG
(
CMD_CTRL
,
0x190
,
0x20
),
RSND_GEN_M_REG
(
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN_M_REG
(
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN_M_REG
(
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN_M_REG
(
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN_M_REG
(
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN_M_REG
(
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN_M_REG
(
SRC_BSDSR
,
0x22c
,
0x40
),
RSND_GEN_M_REG
(
SRC_BSISR
,
0x238
,
0x40
),
RSND_GEN_M_REG
(
DVC_SWRSR
,
0xe00
,
0x100
),
RSND_GEN_M_REG
(
DVC_DVUIR
,
0xe04
,
0x100
),
RSND_GEN_M_REG
(
DVC_ADINR
,
0xe08
,
0x100
),
RSND_GEN_M_REG
(
DVC_DVUCR
,
0xe10
,
0x100
),
RSND_GEN_M_REG
(
DVC_ZCMCR
,
0xe14
,
0x100
),
RSND_GEN_M_REG
(
DVC_VOL0R
,
0xe28
,
0x100
),
RSND_GEN_M_REG
(
DVC_VOL1R
,
0xe2c
,
0x100
),
RSND_GEN_M_REG
(
DVC_DVUER
,
0xe48
,
0x100
),
};
struct
rsnd_regmap_field_conf
conf_adg
[]
=
{
RSND_GEN_S_REG
(
BRRA
,
0x00
),
RSND_GEN_S_REG
(
BRRB
,
0x04
),
RSND_GEN_S_REG
(
SSICKR
,
0x08
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL2
,
0x14
),
RSND_GEN_S_REG
(
DIV_EN
,
0x30
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL0
,
0x34
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL1
,
0x38
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL2
,
0x3c
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL3
,
0x40
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL4
,
0x44
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL0
,
0x48
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL1
,
0x4c
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL2
,
0x50
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL3
,
0x54
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL4
,
0x58
),
RSND_GEN_S_REG
(
CMDOUT_TIMSEL
,
0x5c
),
};
struct
rsnd_regmap_field_conf
conf_ssi
[]
=
{
RSND_GEN_M_REG
(
SSICR
,
0x00
,
0x40
),
RSND_GEN_M_REG
(
SSISR
,
0x04
,
0x40
),
RSND_GEN_M_REG
(
SSITDR
,
0x08
,
0x40
),
RSND_GEN_M_REG
(
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN_M_REG
(
SSIWSR
,
0x20
,
0x40
),
};
int
ret_ssiu
;
int
ret_scu
;
int
ret_adg
;
int
ret_ssi
;
ret_ssiu
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SSIU
,
conf_ssiu
);
ret_scu
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SCU
,
conf_scu
);
ret_adg
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_ADG
,
conf_adg
);
ret_ssi
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SSI
,
conf_ssi
);
if
(
ret_ssiu
<
0
||
ret_scu
<
0
||
ret_adg
<
0
||
ret_ssi
<
0
)
return
ret_ssiu
|
ret_scu
|
ret_adg
|
ret_ssi
;
dev_dbg
(
dev
,
"Gen2 is probed
\n
"
);
return
0
;
}
...
...
@@ -383,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
* Gen1
*/
/* single address mapping */
#define RSND_GEN1_S_REG(gen, reg, id, offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
/* multi address mapping */
#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
static
int
rsnd_gen1_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
)
{
struct
reg_field
regf
[
RSND_REG_MAX
]
=
{
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_ROUTE_SEL
,
0x00
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL0
,
0x08
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL1
,
0x0c
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL2
,
0x10
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_ROUTE_CTRL
,
0xc0
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SSI_MODE0
,
0xD0
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SSI_MODE1
,
0xD4
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_BUSIF_MODE
,
0x20
,
0x4
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_ROUTE_MODE0
,
0x50
,
0x8
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_MNFSR
,
0x228
,
0x40
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
BRRA
,
0x00
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
BRRB
,
0x04
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
SSICKR
,
0x08
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL3
,
0x18
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL4
,
0x1c
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL5
,
0x20
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSICR
,
0x00
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSISR
,
0x04
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSITDR
,
0x08
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSIWSR
,
0x20
,
0x40
),
};
return
rsnd_gen_regmap_init
(
priv
,
gen
,
regf
);
}
static
int
rsnd_gen1_probe
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
resource
*
sru_res
;
struct
resource
*
adg_res
;
struct
resource
*
ssi_res
;
int
ret
;
/*
* map address
*/
sru_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_SRU
);
adg_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_ADG
);
ssi_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_SSI
);
gen
->
base
[
RSND_GEN1_SRU
]
=
devm_ioremap_resource
(
dev
,
sru_res
);
gen
->
base
[
RSND_GEN1_ADG
]
=
devm_ioremap_resource
(
dev
,
adg_res
);
gen
->
base
[
RSND_GEN1_SSI
]
=
devm_ioremap_resource
(
dev
,
ssi_res
);
if
(
IS_ERR
(
gen
->
base
[
RSND_GEN1_SRU
])
||
IS_ERR
(
gen
->
base
[
RSND_GEN1_ADG
])
||
IS_ERR
(
gen
->
base
[
RSND_GEN1_SSI
]))
return
-
ENODEV
;
struct
rsnd_regmap_field_conf
conf_sru
[]
=
{
RSND_GEN_S_REG
(
SRC_ROUTE_SEL
,
0x00
),
RSND_GEN_S_REG
(
SRC_TMG_SEL0
,
0x08
),
RSND_GEN_S_REG
(
SRC_TMG_SEL1
,
0x0c
),
RSND_GEN_S_REG
(
SRC_TMG_SEL2
,
0x10
),
RSND_GEN_S_REG
(
SRC_ROUTE_CTRL
,
0xc0
),
RSND_GEN_S_REG
(
SSI_MODE0
,
0xD0
),
RSND_GEN_S_REG
(
SSI_MODE1
,
0xD4
),
RSND_GEN_M_REG
(
SRC_BUSIF_MODE
,
0x20
,
0x4
),
RSND_GEN_M_REG
(
SRC_ROUTE_MODE0
,
0x50
,
0x8
),
RSND_GEN_M_REG
(
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN_M_REG
(
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN_M_REG
(
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN_M_REG
(
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN_M_REG
(
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN_M_REG
(
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN_M_REG
(
SRC_MNFSR
,
0x228
,
0x40
),
};
struct
rsnd_regmap_field_conf
conf_adg
[]
=
{
RSND_GEN_S_REG
(
BRRA
,
0x00
),
RSND_GEN_S_REG
(
BRRB
,
0x04
),
RSND_GEN_S_REG
(
SSICKR
,
0x08
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL3
,
0x18
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL4
,
0x1c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL5
,
0x20
),
};
struct
rsnd_regmap_field_conf
conf_ssi
[]
=
{
RSND_GEN_M_REG
(
SSICR
,
0x00
,
0x40
),
RSND_GEN_M_REG
(
SSISR
,
0x04
,
0x40
),
RSND_GEN_M_REG
(
SSITDR
,
0x08
,
0x40
),
RSND_GEN_M_REG
(
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN_M_REG
(
SSIWSR
,
0x20
,
0x40
),
};
int
ret_sru
;
int
ret_adg
;
int
ret_ssi
;
ret
=
rsnd_gen1_regmap_init
(
priv
,
gen
);
if
(
ret
<
0
)
return
ret
;
ret_sru
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_SRU
,
conf_sru
);
ret_adg
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_ADG
,
conf_adg
);
ret_ssi
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_SSI
,
conf_ssi
);
if
(
ret_sru
<
0
||
ret_adg
<
0
||
ret_ssi
<
0
)
return
ret_sru
|
ret_adg
|
ret_ssi
;
dev_dbg
(
dev
,
"Gen1 device probed
\n
"
);
dev_dbg
(
dev
,
"SRU : %pap => %p
\n
"
,
&
sru_res
->
start
,
gen
->
base
[
RSND_GEN1_SRU
]);
dev_dbg
(
dev
,
"ADG : %pap => %p
\n
"
,
&
adg_res
->
start
,
gen
->
base
[
RSND_GEN1_ADG
]);
dev_dbg
(
dev
,
"SSI : %pap => %p
\n
"
,
&
ssi_res
->
start
,
gen
->
base
[
RSND_GEN1_SSI
]);
dev_dbg
(
dev
,
"Gen1 is probed
\n
"
);
return
0
;
}
/*
...
...
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