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
423a5e0f
Commit
423a5e0f
authored
Apr 23, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/cs4271' into asoc-next
parents
83097a9c
c24a34db
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
96 additions
and
70 deletions
+96
-70
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs4271.c
+96
-70
No files found.
sound/soc/codecs/cs4271.c
View file @
423a5e0f
...
...
@@ -39,17 +39,15 @@
/*
* CS4271 registers
* High byte represents SPI chip address (0x10) + write command (0)
* Low byte - codec register address
*/
#define CS4271_MODE1 0x
20
01
/* Mode Control 1 */
#define CS4271_DACCTL 0x
20
02
/* DAC Control */
#define CS4271_DACVOL 0x
20
03
/* DAC Volume & Mixing Control */
#define CS4271_VOLA 0x
20
04
/* DAC Channel A Volume Control */
#define CS4271_VOLB 0x
20
05
/* DAC Channel B Volume Control */
#define CS4271_ADCCTL 0x
20
06
/* ADC Control */
#define CS4271_MODE2 0x
20
07
/* Mode Control 2 */
#define CS4271_CHIPID 0x
20
08
/* Chip ID */
#define CS4271_MODE1 0x01
/* Mode Control 1 */
#define CS4271_DACCTL 0x02
/* DAC Control */
#define CS4271_DACVOL 0x03
/* DAC Volume & Mixing Control */
#define CS4271_VOLA 0x04
/* DAC Channel A Volume Control */
#define CS4271_VOLB 0x05
/* DAC Channel B Volume Control */
#define CS4271_ADCCTL 0x06
/* ADC Control */
#define CS4271_MODE2 0x07
/* Mode Control 2 */
#define CS4271_CHIPID 0x08
/* Chip ID */
#define CS4271_FIRSTREG CS4271_MODE1
#define CS4271_LASTREG CS4271_MODE2
...
...
@@ -144,23 +142,27 @@
* Array do not include Chip ID, as codec driver does not use
* registers read operations at all
*/
static
const
u8
cs4271_dflt_reg
[
CS4271_NR_REGS
]
=
{
0
,
0
,
CS4271_DACCTL_AMUTE
,
CS4271_DACVOL_SOFT
|
CS4271_DACVOL_ATAPI_AL_BR
,
0
,
0
,
0
,
0
,
static
const
struct
reg_default
cs4271_reg_defaults
[]
=
{
{
CS4271_MODE1
,
0
,
},
{
CS4271_DACCTL
,
CS4271_DACCTL_AMUTE
,
},
{
CS4271_DACVOL
,
CS4271_DACVOL_SOFT
|
CS4271_DACVOL_ATAPI_AL_BR
,
},
{
CS4271_VOLA
,
0
,
},
{
CS4271_VOLB
,
0
,
},
{
CS4271_ADCCTL
,
0
,
},
{
CS4271_MODE2
,
0
,
},
};
static
bool
cs4271_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
return
reg
==
CS4271_CHIPID
;
}
struct
cs4271_private
{
/* SND_SOC_I2C or SND_SOC_SPI */
enum
snd_soc_control_type
bus_type
;
unsigned
int
mclk
;
bool
master
;
bool
deemph
;
struct
regmap
*
regmap
;
/* Current sample rate for de-emphasis control */
int
rate
;
/* GPIO driving Reset pin, if any */
...
...
@@ -210,14 +212,14 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
switch
(
format
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_LEFT_J
:
val
|=
CS4271_MODE1_DAC_DIF_LJ
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_ADCCTL
,
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_ADCCTL
,
CS4271_ADCCTL_ADC_DIF_MASK
,
CS4271_ADCCTL_ADC_DIF_LJ
);
if
(
ret
<
0
)
return
ret
;
break
;
case
SND_SOC_DAIFMT_I2S
:
val
|=
CS4271_MODE1_DAC_DIF_I2S
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_ADCCTL
,
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_ADCCTL
,
CS4271_ADCCTL_ADC_DIF_MASK
,
CS4271_ADCCTL_ADC_DIF_I2S
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -227,7 +229,7 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE1
,
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE1
,
CS4271_MODE1_DAC_DIF_MASK
|
CS4271_MODE1_MASTER
,
val
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -252,7 +254,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec)
val
<<=
4
;
}
ret
=
snd_soc_update_bits
(
codec
,
CS4271_DACCTL
,
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_DACCTL
,
CS4271_DACCTL_DEM_MASK
,
val
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -341,14 +343,14 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
!
dai
->
capture_active
)
||
(
substream
->
stream
==
SNDRV_PCM_STREAM_CAPTURE
&&
!
dai
->
playback_active
))
{
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
CS4271_MODE2_PDN
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
CS4271_MODE2_PDN
);
if
(
ret
<
0
)
return
ret
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -378,7 +380,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
val
|=
cs4271_clk_tab
[
i
].
ratio_mask
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE1
,
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE1
,
CS4271_MODE1_MODE_MASK
|
CS4271_MODE1_DIV_MASK
,
val
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -386,22 +388,29 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
return
cs4271_set_deemph
(
codec
);
}
static
int
cs4271_
digital_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
static
int
cs4271_
mute_stream
(
struct
snd_soc_dai
*
dai
,
int
mute
,
int
stream
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
cs4271_private
*
cs4271
=
snd_soc_codec_get_drvdata
(
codec
);
int
ret
;
int
val_a
=
0
;
int
val_b
=
0
;
if
(
stream
!=
SNDRV_PCM_STREAM_PLAYBACK
)
return
0
;
if
(
mute
)
{
val_a
=
CS4271_VOLA_MUTE
;
val_b
=
CS4271_VOLB_MUTE
;
}
ret
=
snd_soc_update_bits
(
codec
,
CS4271_VOLA
,
CS4271_VOLA_MUTE
,
val_a
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_VOLA
,
CS4271_VOLA_MUTE
,
val_a
);
if
(
ret
<
0
)
return
ret
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_VOLB
,
CS4271_VOLB_MUTE
,
val_b
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_VOLB
,
CS4271_VOLB_MUTE
,
val_b
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -436,7 +445,7 @@ static const struct snd_soc_dai_ops cs4271_dai_ops = {
.
hw_params
=
cs4271_hw_params
,
.
set_sysclk
=
cs4271_set_dai_sysclk
,
.
set_fmt
=
cs4271_set_dai_fmt
,
.
digital_mute
=
cs4271_digital_mute
,
.
mute_stream
=
cs4271_mute_stream
,
};
static
struct
snd_soc_dai_driver
cs4271_dai
=
{
...
...
@@ -463,25 +472,33 @@ static struct snd_soc_dai_driver cs4271_dai = {
static
int
cs4271_soc_suspend
(
struct
snd_soc_codec
*
codec
)
{
int
ret
;
struct
cs4271_private
*
cs4271
=
snd_soc_codec_get_drvdata
(
codec
);
/* Set power-down bit */
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
CS4271_MODE2_PDN
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
CS4271_MODE2_PDN
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
cs4271_soc_resume
(
struct
snd_soc_codec
*
codec
)
{
int
ret
;
struct
cs4271_private
*
cs4271
=
snd_soc_codec_get_drvdata
(
codec
);
/* Restore codec state */
ret
=
snd_soc_cache_sync
(
codec
);
ret
=
regcache_sync
(
cs4271
->
regmap
);
if
(
ret
<
0
)
return
ret
;
/* then disable the power-down bit */
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
#else
...
...
@@ -542,40 +559,22 @@ static int cs4271_probe(struct snd_soc_codec *codec)
cs4271
->
gpio_nreset
=
gpio_nreset
;
/*
* In case of I2C, chip address specified in board data.
* So cache IO operations use 8 bit codec register address.
* In case of SPI, chip address and register address
* passed together as 16 bit value.
* Anyway, register address is masked with 0xFF inside
* soc-cache code.
*/
if
(
cs4271
->
bus_type
==
SND_SOC_SPI
)
ret
=
snd_soc_codec_set_cache_io
(
codec
,
16
,
8
,
cs4271
->
bus_type
);
else
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
8
,
cs4271
->
bus_type
);
if
(
ret
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
|
CS4271_MODE2_CPEN
,
CS4271_MODE2_PDN
|
CS4271_MODE2_CPEN
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
|
CS4271_MODE2_CPEN
,
CS4271_MODE2_PDN
|
CS4271_MODE2_CPEN
);
if
(
ret
<
0
)
return
ret
;
ret
=
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
ret
=
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_PDN
,
0
);
if
(
ret
<
0
)
return
ret
;
/* Power-up sequence requires 85 uS */
udelay
(
85
);
if
(
amutec_eq_bmutec
)
snd_soc_update_bits
(
codec
,
CS4271_MODE2
,
CS4271_MODE2_MUTECAEQUB
,
CS4271_MODE2_MUTECAEQUB
);
regmap_update_bits
(
cs4271
->
regmap
,
CS4271_MODE2
,
CS4271_MODE2_MUTECAEQUB
,
CS4271_MODE2_MUTECAEQUB
);
return
snd_soc_add_codec_controls
(
codec
,
cs4271_snd_controls
,
ARRAY_SIZE
(
cs4271_snd_controls
));
...
...
@@ -597,13 +596,24 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
.
remove
=
cs4271_remove
,
.
suspend
=
cs4271_soc_suspend
,
.
resume
=
cs4271_soc_resume
,
.
reg_cache_default
=
cs4271_dflt_reg
,
.
reg_cache_size
=
ARRAY_SIZE
(
cs4271_dflt_reg
),
.
reg_word_size
=
sizeof
(
cs4271_dflt_reg
[
0
]),
.
compress_type
=
SND_SOC_FLAT_COMPRESSION
,
};
#if defined(CONFIG_SPI_MASTER)
static
const
struct
regmap_config
cs4271_spi_regmap
=
{
.
reg_bits
=
16
,
.
val_bits
=
8
,
.
max_register
=
CS4271_LASTREG
,
.
read_flag_mask
=
0x21
,
.
write_flag_mask
=
0x20
,
.
reg_defaults
=
cs4271_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
cs4271_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
volatile_reg
=
cs4271_volatile_reg
,
};
static
int
cs4271_spi_probe
(
struct
spi_device
*
spi
)
{
struct
cs4271_private
*
cs4271
;
...
...
@@ -613,7 +623,9 @@ static int cs4271_spi_probe(struct spi_device *spi)
return
-
ENOMEM
;
spi_set_drvdata
(
spi
,
cs4271
);
cs4271
->
bus_type
=
SND_SOC_SPI
;
cs4271
->
regmap
=
devm_regmap_init_spi
(
spi
,
&
cs4271_spi_regmap
);
if
(
IS_ERR
(
cs4271
->
regmap
))
return
PTR_ERR
(
cs4271
->
regmap
);
return
snd_soc_register_codec
(
&
spi
->
dev
,
&
soc_codec_dev_cs4271
,
&
cs4271_dai
,
1
);
...
...
@@ -643,6 +655,18 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
};
MODULE_DEVICE_TABLE
(
i2c
,
cs4271_i2c_id
);
static
const
struct
regmap_config
cs4271_i2c_regmap
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
CS4271_LASTREG
,
.
reg_defaults
=
cs4271_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
cs4271_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
volatile_reg
=
cs4271_volatile_reg
,
};
static
int
cs4271_i2c_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
...
...
@@ -653,7 +677,9 @@ static int cs4271_i2c_probe(struct i2c_client *client,
return
-
ENOMEM
;
i2c_set_clientdata
(
client
,
cs4271
);
cs4271
->
bus_type
=
SND_SOC_I2C
;
cs4271
->
regmap
=
devm_regmap_init_i2c
(
client
,
&
cs4271_i2c_regmap
);
if
(
IS_ERR
(
cs4271
->
regmap
))
return
PTR_ERR
(
cs4271
->
regmap
);
return
snd_soc_register_codec
(
&
client
->
dev
,
&
soc_codec_dev_cs4271
,
&
cs4271_dai
,
1
);
...
...
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