Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
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