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
9686e4b2
Commit
9686e4b2
authored
Nov 08, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
parents
469cb928
a2b4f8a4
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
346 additions
and
197 deletions
+346
-197
drivers/base/regmap/internal.h
drivers/base/regmap/internal.h
+3
-0
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+103
-0
include/linux/regmap.h
include/linux/regmap.h
+13
-0
include/sound/rcar_snd.h
include/sound/rcar_snd.h
+0
-1
sound/soc/sh/Kconfig
sound/soc/sh/Kconfig
+0
-1
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/adg.c
+7
-4
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/core.c
+24
-57
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/gen.c
+165
-96
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/rsnd.h
+1
-4
sound/soc/sh/rcar/scu.c
sound/soc/sh/rcar/scu.c
+9
-3
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssi.c
+21
-31
No files found.
drivers/base/regmap/internal.h
View file @
9686e4b2
...
...
@@ -179,6 +179,9 @@ struct regmap_field {
/* lsb */
unsigned
int
shift
;
unsigned
int
reg
;
unsigned
int
id_size
;
unsigned
int
id_offset
;
};
#ifdef CONFIG_DEBUG_FS
...
...
drivers/base/regmap/regmap.c
View file @
9686e4b2
...
...
@@ -821,6 +821,8 @@ static void regmap_field_init(struct regmap_field *rm_field,
rm_field
->
reg
=
reg_field
.
reg
;
rm_field
->
shift
=
reg_field
.
lsb
;
rm_field
->
mask
=
((
BIT
(
field_bits
)
-
1
)
<<
reg_field
.
lsb
);
rm_field
->
id_size
=
reg_field
.
id_size
;
rm_field
->
id_offset
=
reg_field
.
id_offset
;
}
/**
...
...
@@ -1369,6 +1371,74 @@ int regmap_field_write(struct regmap_field *field, unsigned int val)
}
EXPORT_SYMBOL_GPL
(
regmap_field_write
);
/**
* regmap_field_update_bits(): Perform a read/modify/write cycle
* on the register field
*
* @field: Register field to write to
* @mask: Bitmask to change
* @val: Value to be written
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int
regmap_field_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
)
{
mask
=
(
mask
<<
field
->
shift
)
&
field
->
mask
;
return
regmap_update_bits
(
field
->
regmap
,
field
->
reg
,
mask
,
val
<<
field
->
shift
);
}
EXPORT_SYMBOL_GPL
(
regmap_field_update_bits
);
/**
* regmap_fields_write(): Write a value to a single register field with port ID
*
* @field: Register field to write to
* @id: port ID
* @val: Value to be written
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int
regmap_fields_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
)
{
if
(
id
>=
field
->
id_size
)
return
-
EINVAL
;
return
regmap_update_bits
(
field
->
regmap
,
field
->
reg
+
(
field
->
id_offset
*
id
),
field
->
mask
,
val
<<
field
->
shift
);
}
EXPORT_SYMBOL_GPL
(
regmap_fields_write
);
/**
* regmap_fields_update_bits(): Perform a read/modify/write cycle
* on the register field
*
* @field: Register field to write to
* @id: port ID
* @mask: Bitmask to change
* @val: Value to be written
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int
regmap_fields_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
)
{
if
(
id
>=
field
->
id_size
)
return
-
EINVAL
;
mask
=
(
mask
<<
field
->
shift
)
&
field
->
mask
;
return
regmap_update_bits
(
field
->
regmap
,
field
->
reg
+
(
field
->
id_offset
*
id
),
mask
,
val
<<
field
->
shift
);
}
EXPORT_SYMBOL_GPL
(
regmap_fields_update_bits
);
/*
* regmap_bulk_write(): Write multiple registers to the device
*
...
...
@@ -1676,6 +1746,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val)
}
EXPORT_SYMBOL_GPL
(
regmap_field_read
);
/**
* regmap_fields_read(): Read a value to a single register field with port ID
*
* @field: Register field to read from
* @id: port ID
* @val: Pointer to store read value
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int
regmap_fields_read
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
*
val
)
{
int
ret
;
unsigned
int
reg_val
;
if
(
id
>=
field
->
id_size
)
return
-
EINVAL
;
ret
=
regmap_read
(
field
->
regmap
,
field
->
reg
+
(
field
->
id_offset
*
id
),
&
reg_val
);
if
(
ret
!=
0
)
return
ret
;
reg_val
&=
field
->
mask
;
reg_val
>>=
field
->
shift
;
*
val
=
reg_val
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
regmap_fields_read
);
/**
* regmap_bulk_read(): Read multiple registers from the device
*
...
...
include/linux/regmap.h
View file @
9686e4b2
...
...
@@ -425,11 +425,15 @@ bool regmap_reg_in_ranges(unsigned int reg,
* @reg: Offset of the register within the regmap bank
* @lsb: lsb of the register field.
* @reg: msb of the register field.
* @id_size: port size if it has some ports
* @id_offset: address offset for each ports
*/
struct
reg_field
{
unsigned
int
reg
;
unsigned
int
lsb
;
unsigned
int
msb
;
unsigned
int
id_size
;
unsigned
int
id_offset
;
};
#define REG_FIELD(_reg, _lsb, _msb) { \
...
...
@@ -448,6 +452,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
int
regmap_field_read
(
struct
regmap_field
*
field
,
unsigned
int
*
val
);
int
regmap_field_write
(
struct
regmap_field
*
field
,
unsigned
int
val
);
int
regmap_field_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
);
int
regmap_fields_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
);
int
regmap_fields_read
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
*
val
);
int
regmap_fields_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
);
/**
* Description of an IRQ for the generic regmap irq_chip.
...
...
include/sound/rcar_snd.h
View file @
9686e4b2
...
...
@@ -36,7 +36,6 @@
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_CLK_FROM_ADG (1 << 30)
/* clock parent is master */
#define RSND_SSI_SYNC (1 << 29)
/* SSI34_sync etc */
#define RSND_SSI_DEPENDENT (1 << 28)
/* SSI needs SRU/SCU */
#define RSND_SSI_PLAY (1 << 24)
...
...
sound/soc/sh/Kconfig
View file @
9686e4b2
...
...
@@ -37,7 +37,6 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
select SND_SIMPLE_CARD
select RCAR_CLK_ADG
help
This option enables R-Car SUR/SCU/SSIU/SSI sound support
...
...
sound/soc/sh/rcar/adg.c
View file @
9686e4b2
...
...
@@ -8,7 +8,6 @@
* for more details.
*/
#include <linux/sh_clk.h>
#include <mach/clock.h>
#include "rsnd.h"
#define CLKA 0
...
...
@@ -22,6 +21,7 @@ struct rsnd_adg {
int
rate_of_441khz_div_6
;
int
rate_of_48khz_div_6
;
u32
ckr
;
};
#define for_each_rsnd_clk(pos, adg, i) \
...
...
@@ -116,6 +116,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
found_clock:
/* see rsnd_adg_ssi_clk_init() */
rsnd_mod_bset
(
mod
,
SSICKR
,
0x00FF0000
,
adg
->
ckr
);
rsnd_mod_write
(
mod
,
BRRA
,
0x00000002
);
/* 1/6 */
rsnd_mod_write
(
mod
,
BRRB
,
0x00000002
);
/* 1/6 */
/*
* This "mod" = "ssi" here.
* we can get "ssi id" from mod
...
...
@@ -182,9 +187,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
}
}
rsnd_priv_bset
(
priv
,
SSICKR
,
0x00FF0000
,
ckr
);
rsnd_priv_write
(
priv
,
BRRA
,
0x00000002
);
/* 1/6 */
rsnd_priv_write
(
priv
,
BRRB
,
0x00000002
);
/* 1/6 */
adg
->
ckr
=
ckr
;
}
int
rsnd_adg_probe
(
struct
platform_device
*
pdev
,
...
...
sound/soc/sh/rcar/core.c
View file @
9686e4b2
...
...
@@ -94,6 +94,7 @@
*
*/
#include <linux/pm_runtime.h>
#include <linux/shdma-base.h>
#include "rsnd.h"
#define RSND_RATES SNDRV_PCM_RATE_8000_96000
...
...
@@ -103,54 +104,9 @@
* rsnd_platform functions
*/
#define rsnd_platform_call(priv, dai, func, param...) \
(!(priv->info->func) ?
-ENODEV
: \
(!(priv->info->func) ?
0
: \
priv->info->func(param))
/*
* basic function
*/
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
{
void
__iomem
*
base
=
rsnd_gen_reg_get
(
priv
,
mod
,
reg
);
BUG_ON
(
!
base
);
return
ioread32
(
base
);
}
void
rsnd_write
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
data
)
{
void
__iomem
*
base
=
rsnd_gen_reg_get
(
priv
,
mod
,
reg
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
BUG_ON
(
!
base
);
dev_dbg
(
dev
,
"w %p : %08x
\n
"
,
base
,
data
);
iowrite32
(
data
,
base
);
}
void
rsnd_bset
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
mask
,
u32
data
)
{
void
__iomem
*
base
=
rsnd_gen_reg_get
(
priv
,
mod
,
reg
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
val
;
BUG_ON
(
!
base
);
val
=
ioread32
(
base
);
val
&=
~
mask
;
val
|=
data
&
mask
;
iowrite32
(
val
,
base
);
dev_dbg
(
dev
,
"s %p : %08x
\n
"
,
base
,
val
);
}
/*
* rsnd_mod functions
*/
...
...
@@ -254,13 +210,6 @@ int rsnd_dma_available(struct rsnd_dma *dma)
return
!!
dma
->
chan
;
}
static
bool
rsnd_dma_filter
(
struct
dma_chan
*
chan
,
void
*
param
)
{
chan
->
private
=
param
;
return
true
;
}
int
rsnd_dma_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
int
is_play
,
int
id
,
int
(
*
inquiry
)(
struct
rsnd_dma
*
dma
,
...
...
@@ -268,7 +217,9 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
int
(
*
complete
)(
struct
rsnd_dma
*
dma
))
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
dma_slave_config
cfg
;
dma_cap_mask_t
mask
;
int
ret
;
if
(
dma
->
chan
)
{
dev_err
(
dev
,
"it already has dma channel
\n
"
);
...
...
@@ -278,15 +229,23 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
dma
->
slave
.
shdma_slave
.
slave_id
=
id
;
dma
->
chan
=
dma_request_channel
(
mask
,
rsnd_dma_filter
,
&
dma
->
slave
.
shdma_slave
);
dma
->
chan
=
dma_request_slave_channel_compat
(
mask
,
shdma_chan_filter
,
(
void
*
)
id
,
dev
,
is_play
?
"tx"
:
"rx"
);
if
(
!
dma
->
chan
)
{
dev_err
(
dev
,
"can't get dma channel
\n
"
);
return
-
EIO
;
}
cfg
.
slave_id
=
id
;
cfg
.
dst_addr
=
0
;
/* use default addr when playback */
cfg
.
src_addr
=
0
;
/* use default addr when capture */
cfg
.
direction
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
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
;
dma
->
priv
=
priv
;
dma
->
inquiry
=
inquiry
;
...
...
@@ -294,6 +253,11 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
INIT_WORK
(
&
dma
->
work
,
rsnd_dma_do_work
);
return
0
;
rsnd_dma_init_err:
rsnd_dma_quit
(
priv
,
dma
);
return
ret
;
}
void
rsnd_dma_quit
(
struct
rsnd_priv
*
priv
,
...
...
@@ -363,6 +327,9 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
struct
rsnd_dai
*
rsnd_dai_get
(
struct
rsnd_priv
*
priv
,
int
id
)
{
if
((
id
<
0
)
||
(
id
>=
rsnd_dai_nr
(
priv
)))
return
NULL
;
return
priv
->
rdai
+
id
;
}
...
...
sound/soc/sh/rcar/gen.c
View file @
9686e4b2
...
...
@@ -11,6 +11,11 @@
#include "rsnd.h"
struct
rsnd_gen_ops
{
int
(
*
probe
)(
struct
platform_device
*
pdev
,
struct
rcar_snd_info
*
info
,
struct
rsnd_priv
*
priv
);
void
(
*
remove
)(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
);
int
(
*
path_init
)(
struct
rsnd_priv
*
priv
,
struct
rsnd_dai
*
rdai
,
struct
rsnd_dai_stream
*
io
);
...
...
@@ -19,21 +24,97 @@ struct rsnd_gen_ops {
struct
rsnd_dai_stream
*
io
);
};
struct
rsnd_gen_reg_map
{
int
index
;
/* -1 : not supported */
u32
offset_id
;
/* offset of ssi0, ssi1, ssi2... */
u32
offset_adr
;
/* offset of SSICR, SSISR, ... */
};
struct
rsnd_gen
{
void
__iomem
*
base
[
RSND_BASE_MAX
];
struct
rsnd_gen_reg_map
reg_map
[
RSND_REG_MAX
];
struct
rsnd_gen_ops
*
ops
;
struct
regmap
*
regmap
;
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
);
return
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
,
};
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
{
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
u32
val
;
regmap_fields_read
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
&
val
);
return
val
;
}
void
rsnd_write
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
data
)
{
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
regmap_fields_write
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
data
);
}
void
rsnd_bset
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
mask
,
u32
data
)
{
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
regmap_fields_update_bits
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
mask
,
data
);
}
/*
* Gen2
* will be filled in the future
...
...
@@ -98,44 +179,64 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
return
ret
;
}
static
struct
rsnd_gen_ops
rsnd_gen1_ops
=
{
.
path_init
=
rsnd_gen1_path_init
,
.
path_exit
=
rsnd_gen1_path_exit
,
};
/* 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)
#define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
do { \
(g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \
(g)->reg_map[RSND_REG_##i].offset_id = oi; \
(g)->reg_map[RSND_REG_##i].offset_adr = oa; \
} while (0)
/* 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
void
rsnd_gen1_reg_map_init
(
struct
rsnd_gen
*
gen
)
static
int
rsnd_gen1_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
)
{
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SRC_ROUTE_SEL
,
0x0
,
0x00
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SRC_TMG_SEL0
,
0x0
,
0x08
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SRC_TMG_SEL1
,
0x0
,
0x0c
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SRC_TMG_SEL2
,
0x0
,
0x10
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SRC_CTRL
,
0x0
,
0xc0
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SSI_MODE0
,
0x0
,
0xD0
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
SSI_MODE1
,
0x0
,
0xD4
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
BUSIF_MODE
,
0x4
,
0x20
);
RSND_GEN1_REG_MAP
(
gen
,
SRU
,
BUSIF_ADINR
,
0x40
,
0x214
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
BRRA
,
0x0
,
0x00
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
BRRB
,
0x0
,
0x04
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
SSICKR
,
0x0
,
0x08
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
AUDIO_CLK_SEL0
,
0x0
,
0x0c
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
AUDIO_CLK_SEL1
,
0x0
,
0x10
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
AUDIO_CLK_SEL3
,
0x0
,
0x18
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
AUDIO_CLK_SEL4
,
0x0
,
0x1c
);
RSND_GEN1_REG_MAP
(
gen
,
ADG
,
AUDIO_CLK_SEL5
,
0x0
,
0x20
);
RSND_GEN1_REG_MAP
(
gen
,
SSI
,
SSICR
,
0x40
,
0x00
);
RSND_GEN1_REG_MAP
(
gen
,
SSI
,
SSISR
,
0x40
,
0x04
);
RSND_GEN1_REG_MAP
(
gen
,
SSI
,
SSITDR
,
0x40
,
0x08
);
RSND_GEN1_REG_MAP
(
gen
,
SSI
,
SSIRDR
,
0x40
,
0x0c
);
RSND_GEN1_REG_MAP
(
gen
,
SSI
,
SSIWSR
,
0x40
,
0x20
);
int
i
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
regmap_config
regc
;
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_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
,
BUSIF_MODE
,
0x20
,
0x4
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
BUSIF_ADINR
,
0x214
,
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
),
};
memset
(
&
regc
,
0
,
sizeof
(
regc
));
regc
.
reg_bits
=
32
;
regc
.
val_bits
=
32
;
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
);
}
for
(
i
=
0
;
i
<
RSND_REG_MAX
;
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
]);
}
return
0
;
}
static
int
rsnd_gen1_probe
(
struct
platform_device
*
pdev
,
...
...
@@ -147,6 +248,7 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
struct
resource
*
sru_res
;
struct
resource
*
adg_res
;
struct
resource
*
ssi_res
;
int
ret
;
/*
* map address
...
...
@@ -163,8 +265,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
IS_ERR
(
gen
->
base
[
RSND_GEN1_SSI
]))
return
-
ENODEV
;
gen
->
ops
=
&
rsnd_gen1_ops
;
rsnd_gen1_reg_map_init
(
gen
);
ret
=
rsnd_gen1_regmap_init
(
priv
,
gen
);
if
(
ret
<
0
)
return
ret
;
dev_dbg
(
dev
,
"Gen1 device probed
\n
"
);
dev_dbg
(
dev
,
"SRU : %08x => %p
\n
"
,
sru_res
->
start
,
...
...
@@ -183,6 +286,13 @@ static void rsnd_gen1_remove(struct platform_device *pdev,
{
}
static
struct
rsnd_gen_ops
rsnd_gen1_ops
=
{
.
probe
=
rsnd_gen1_probe
,
.
remove
=
rsnd_gen1_remove
,
.
path_init
=
rsnd_gen1_path_init
,
.
path_exit
=
rsnd_gen1_path_exit
,
};
/*
* Gen
*/
...
...
@@ -204,46 +314,12 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv,
return
gen
->
ops
->
path_exit
(
priv
,
rdai
,
io
);
}
void
__iomem
*
rsnd_gen_reg_get
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
{
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
int
index
;
u32
offset_id
,
offset_adr
;
if
(
reg
>=
RSND_REG_MAX
)
{
dev_err
(
dev
,
"rsnd_reg reg error
\n
"
);
return
NULL
;
}
index
=
gen
->
reg_map
[
reg
].
index
;
offset_id
=
gen
->
reg_map
[
reg
].
offset_id
;
offset_adr
=
gen
->
reg_map
[
reg
].
offset_adr
;
if
(
index
<
0
)
{
dev_err
(
dev
,
"unsupported reg access %d
\n
"
,
reg
);
return
NULL
;
}
if
(
offset_id
&&
mod
)
offset_id
*=
rsnd_mod_id
(
mod
);
/*
* index/offset were set on gen1/gen2
*/
return
gen
->
base
[
index
]
+
offset_id
+
offset_adr
;
}
int
rsnd_gen_probe
(
struct
platform_device
*
pdev
,
struct
rcar_snd_info
*
info
,
struct
rsnd_priv
*
priv
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
;
int
i
;
gen
=
devm_kzalloc
(
dev
,
sizeof
(
*
gen
),
GFP_KERNEL
);
if
(
!
gen
)
{
...
...
@@ -251,30 +327,23 @@ int rsnd_gen_probe(struct platform_device *pdev,
return
-
ENOMEM
;
}
priv
->
gen
=
gen
;
/*
* see
* rsnd_reg_get()
* rsnd_gen_probe()
*/
for
(
i
=
0
;
i
<
RSND_REG_MAX
;
i
++
)
gen
->
reg_map
[
i
].
index
=
-
1
;
/*
* init each module
*/
if
(
rsnd_is_gen1
(
priv
))
return
rsnd_gen1_probe
(
pdev
,
info
,
priv
)
;
gen
->
ops
=
&
rsnd_gen1_ops
;
dev_err
(
dev
,
"unknown generation R-Car sound device
\n
"
);
if
(
!
gen
->
ops
)
{
dev_err
(
dev
,
"unknown generation R-Car sound device
\n
"
);
return
-
ENODEV
;
}
return
-
ENODEV
;
priv
->
gen
=
gen
;
return
gen
->
ops
->
probe
(
pdev
,
info
,
priv
);
}
void
rsnd_gen_remove
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
)
{
if
(
rsnd_is_gen1
(
priv
))
rsnd_gen1_remove
(
pdev
,
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
gen
->
ops
->
remove
(
pdev
,
priv
);
}
sound/soc/sh/rcar/rsnd.h
View file @
9686e4b2
...
...
@@ -78,10 +78,6 @@ struct rsnd_dai_stream;
#define rsnd_mod_bset(m, r, s, d) \
rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r)
#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d)
#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d)
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
);
void
rsnd_write
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
data
);
...
...
@@ -285,6 +281,7 @@ int rsnd_scu_probe(struct platform_device *pdev,
void
rsnd_scu_remove
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
);
struct
rsnd_mod
*
rsnd_scu_mod_get
(
struct
rsnd_priv
*
priv
,
int
id
);
bool
rsnd_scu_hpbif_is_enable
(
struct
rsnd_mod
*
mod
);
#define rsnd_scu_nr(priv) ((priv)->scu_nr)
/*
...
...
sound/soc/sh/rcar/scu.c
View file @
9686e4b2
...
...
@@ -146,20 +146,26 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
return
0
;
}
bool
rsnd_scu_hpbif_is_enable
(
struct
rsnd_mod
*
mod
)
{
struct
rsnd_scu
*
scu
=
rsnd_mod_to_scu
(
mod
);
u32
flags
=
rsnd_scu_mode_flags
(
scu
);
return
!!
(
flags
&
RSND_SCU_USE_HPBIF
);
}
static
int
rsnd_scu_start
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
rsnd_dai_stream
*
io
)
{
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
rsnd_scu
*
scu
=
rsnd_mod_to_scu
(
mod
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
flags
=
rsnd_scu_mode_flags
(
scu
);
int
ret
;
/*
* SCU will be used if it has RSND_SCU_USE_HPBIF flags
*/
if
(
!
(
flags
&
RSND_SCU_USE_HPBIF
))
{
if
(
!
rsnd_scu_hpbif_is_enable
(
mod
))
{
/* it use PIO transter */
dev_dbg
(
dev
,
"%s%d is not used
\n
"
,
rsnd_mod_name
(
mod
),
rsnd_mod_id
(
mod
));
...
...
sound/soc/sh/rcar/ssi.c
View file @
9686e4b2
...
...
@@ -101,29 +101,30 @@ struct rsnd_ssiu {
#define rsnd_ssi_to_ssiu(ssi)\
(((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
static
void
rsnd_ssi_mode_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_ssiu
*
ssiu
)
static
void
rsnd_ssi_mode_set
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dai
*
rdai
,
struct
rsnd_ssi
*
ssi
)
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_ssi
*
ssi
;
struct
rsnd_mod
*
scu
;
struct
rsnd_ssiu
*
ssiu
=
rsnd_ssi_to_ssiu
(
ssi
);
int
id
=
rsnd_mod_id
(
&
ssi
->
mod
);
u32
flags
;
u32
val
;
int
i
;
scu
=
rsnd_scu_mod_get
(
priv
,
rsnd_mod_id
(
&
ssi
->
mod
));
/*
* SSI_MODE0
*/
ssiu
->
ssi_mode0
=
0
;
for_each_rsnd_ssi
(
ssi
,
priv
,
i
)
{
flags
=
rsnd_ssi_mode_flags
(
ssi
);
/* see also BUSIF_MODE */
if
(
!
(
flags
&
RSND_SSI_DEPENDENT
))
{
ssiu
->
ssi_mode0
|=
(
1
<<
i
);
dev_dbg
(
dev
,
"SSI%d uses INDEPENDENT mode
\n
"
,
i
);
}
else
{
dev_dbg
(
dev
,
"SSI%d uses DEPENDENT mode
\n
"
,
i
);
}
/* see also BUSIF_MODE */
if
(
rsnd_scu_hpbif_is_enable
(
scu
))
{
ssiu
->
ssi_mode0
&=
~
(
1
<<
id
);
dev_dbg
(
dev
,
"SSI%d uses DEPENDENT mode
\n
"
,
id
);
}
else
{
ssiu
->
ssi_mode0
|=
(
1
<<
id
);
dev_dbg
(
dev
,
"SSI%d uses INDEPENDENT mode
\n
"
,
id
);
}
/*
...
...
@@ -132,7 +133,7 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
#define ssi_parent_set(p, sync, adg, ext) \
do { \
ssi->parent = ssiu->ssi + p; \
if (
flags & RSND_SSI_CLK_FROM_ADG
) \
if (
rsnd_rdai_is_clk_master(rdai)
) \
val = adg; \
else \
val = ext; \
...
...
@@ -140,15 +141,11 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
val |= sync; \
} while (0)
ssiu
->
ssi_mode1
=
0
;
for_each_rsnd_ssi
(
ssi
,
priv
,
i
)
{
flags
=
rsnd_ssi_mode_flags
(
ssi
);
if
(
!
(
flags
&
RSND_SSI_CLK_PIN_SHARE
))
continue
;
flags
=
rsnd_ssi_mode_flags
(
ssi
);
if
(
flags
&
RSND_SSI_CLK_PIN_SHARE
)
{
val
=
0
;
switch
(
i
)
{
switch
(
i
d
)
{
case
1
:
ssi_parent_set
(
0
,
(
1
<<
4
),
(
0x2
<<
0
),
(
0x1
<<
0
));
break
;
...
...
@@ -165,11 +162,6 @@ static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
ssiu
->
ssi_mode1
|=
val
;
}
}
static
void
rsnd_ssi_mode_set
(
struct
rsnd_ssi
*
ssi
)
{
struct
rsnd_ssiu
*
ssiu
=
rsnd_ssi_to_ssiu
(
ssi
);
rsnd_mod_write
(
&
ssi
->
mod
,
SSI_MODE0
,
ssiu
->
ssi_mode0
);
rsnd_mod_write
(
&
ssi
->
mod
,
SSI_MODE1
,
ssiu
->
ssi_mode1
);
...
...
@@ -379,7 +371,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
ssi
->
cr_own
=
cr
;
ssi
->
err
=
-
1
;
/* ignore 1st error */
rsnd_ssi_mode_set
(
ssi
);
rsnd_ssi_mode_set
(
priv
,
rdai
,
ssi
);
dev_dbg
(
dev
,
"%s.%d init
\n
"
,
rsnd_mod_name
(
mod
),
rsnd_mod_id
(
mod
));
...
...
@@ -706,8 +698,6 @@ int rsnd_ssi_probe(struct platform_device *pdev,
rsnd_mod_init
(
priv
,
&
ssi
->
mod
,
ops
,
i
);
}
rsnd_ssi_mode_init
(
priv
,
ssiu
);
dev_dbg
(
dev
,
"ssi probed
\n
"
);
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment