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
2ca5e86c
Commit
2ca5e86c
authored
Dec 10, 2012
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/si476x' into asoc-next
parents
ceb8ef5e
330345eb
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
261 additions
and
0 deletions
+261
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+4
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+2
-0
sound/soc/codecs/si476x.c
sound/soc/codecs/si476x.c
+255
-0
No files found.
sound/soc/codecs/Kconfig
View file @
2ca5e86c
...
@@ -55,6 +55,7 @@ config SND_SOC_ALL_CODECS
...
@@ -55,6 +55,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM3008
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
...
@@ -289,6 +290,9 @@ config SND_SOC_RT5631
...
@@ -289,6 +290,9 @@ config SND_SOC_RT5631
config SND_SOC_SGTL5000
config SND_SOC_SGTL5000
tristate
tristate
config SND_SOC_SI476X
tristate
config SND_SOC_SIGMADSP
config SND_SOC_SIGMADSP
tristate
tristate
select CRC32
select CRC32
...
...
sound/soc/codecs/Makefile
View file @
2ca5e86c
...
@@ -46,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
...
@@ -46,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs
:=
alc5623.o
snd-soc-alc5623-objs
:=
alc5623.o
snd-soc-alc5632-objs
:=
alc5632.o
snd-soc-alc5632-objs
:=
alc5632.o
snd-soc-sigmadsp-objs
:=
sigmadsp.o
snd-soc-sigmadsp-objs
:=
sigmadsp.o
snd-soc-si476x-objs
:=
si476x.o
snd-soc-sn95031-objs
:=
sn95031.o
snd-soc-sn95031-objs
:=
sn95031.o
snd-soc-spdif-tx-objs
:=
spdif_transciever.o
snd-soc-spdif-tx-objs
:=
spdif_transciever.o
snd-soc-spdif-rx-objs
:=
spdif_receiver.o
snd-soc-spdif-rx-objs
:=
spdif_receiver.o
...
@@ -167,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
...
@@ -167,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631)
+=
snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5631)
+=
snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000)
+=
snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SGTL5000)
+=
snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP)
+=
snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SIGMADSP)
+=
snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SI476X)
+=
snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SN95031)
+=
snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SN95031)
+=
snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF)
+=
snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SPDIF)
+=
snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SSM2602)
+=
snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_SSM2602)
+=
snd-soc-ssm2602.o
...
...
sound/soc/codecs/si476x.c
0 → 100644
View file @
2ca5e86c
#include <linux/module.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <linux/i2c.h>
#include <linux/mfd/si476x-core.h>
enum
si476x_audio_registers
{
SI476X_DIGITAL_IO_OUTPUT_FORMAT
=
0x0203
,
SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE
=
0x0202
,
};
enum
si476x_digital_io_output_format
{
SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT
=
11
,
SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT
=
8
,
};
#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
(0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b1111110)
enum
si476x_daudio_formats
{
SI476X_DAUDIO_MODE_I2S
=
(
0x0
<<
1
),
SI476X_DAUDIO_MODE_DSP_A
=
(
0x6
<<
1
),
SI476X_DAUDIO_MODE_DSP_B
=
(
0x7
<<
1
),
SI476X_DAUDIO_MODE_LEFT_J
=
(
0x8
<<
1
),
SI476X_DAUDIO_MODE_RIGHT_J
=
(
0x9
<<
1
),
SI476X_DAUDIO_MODE_IB
=
(
1
<<
5
),
SI476X_DAUDIO_MODE_IF
=
(
1
<<
6
),
};
enum
si476x_pcm_format
{
SI476X_PCM_FORMAT_S8
=
2
,
SI476X_PCM_FORMAT_S16_LE
=
4
,
SI476X_PCM_FORMAT_S20_3LE
=
5
,
SI476X_PCM_FORMAT_S24_LE
=
6
,
};
static
unsigned
int
si476x_codec_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
int
err
;
struct
si476x_core
*
core
=
codec
->
control_data
;
si476x_core_lock
(
core
);
err
=
si476x_core_cmd_get_property
(
core
,
reg
);
si476x_core_unlock
(
core
);
return
err
;
}
static
int
si476x_codec_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
val
)
{
int
err
;
struct
si476x_core
*
core
=
codec
->
control_data
;
si476x_core_lock
(
core
);
err
=
si476x_core_cmd_set_property
(
core
,
reg
,
val
);
si476x_core_unlock
(
core
);
return
err
;
}
static
int
si476x_codec_set_dai_fmt
(
struct
snd_soc_dai
*
codec_dai
,
unsigned
int
fmt
)
{
int
err
;
u16
format
=
0
;
if
((
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
!=
SND_SOC_DAIFMT_CBS_CFS
)
return
-
EINVAL
;
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_DSP_A
:
format
|=
SI476X_DAUDIO_MODE_DSP_A
;
break
;
case
SND_SOC_DAIFMT_DSP_B
:
format
|=
SI476X_DAUDIO_MODE_DSP_B
;
break
;
case
SND_SOC_DAIFMT_I2S
:
format
|=
SI476X_DAUDIO_MODE_I2S
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
format
|=
SI476X_DAUDIO_MODE_RIGHT_J
;
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
format
|=
SI476X_DAUDIO_MODE_LEFT_J
;
break
;
default:
return
-
EINVAL
;
}
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_DSP_A
:
case
SND_SOC_DAIFMT_DSP_B
:
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_NF
:
break
;
case
SND_SOC_DAIFMT_IB_NF
:
format
|=
SI476X_DAUDIO_MODE_IB
;
break
;
default:
return
-
EINVAL
;
}
break
;
case
SND_SOC_DAIFMT_I2S
:
case
SND_SOC_DAIFMT_RIGHT_J
:
case
SND_SOC_DAIFMT_LEFT_J
:
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_NF
:
break
;
case
SND_SOC_DAIFMT_IB_IF
:
format
|=
SI476X_DAUDIO_MODE_IB
|
SI476X_DAUDIO_MODE_IF
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
format
|=
SI476X_DAUDIO_MODE_IB
;
break
;
case
SND_SOC_DAIFMT_NB_IF
:
format
|=
SI476X_DAUDIO_MODE_IF
;
break
;
default:
return
-
EINVAL
;
}
break
;
default:
return
-
EINVAL
;
}
err
=
snd_soc_update_bits
(
codec_dai
->
codec
,
SI476X_DIGITAL_IO_OUTPUT_FORMAT
,
SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK
,
format
);
if
(
err
<
0
)
{
dev_err
(
codec_dai
->
codec
->
dev
,
"Failed to set output format
\n
"
);
return
err
;
}
return
0
;
}
static
int
si476x_codec_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
int
rate
,
width
,
err
;
rate
=
params_rate
(
params
);
if
(
rate
<
32000
||
rate
>
48000
)
{
dev_err
(
dai
->
codec
->
dev
,
"Rate: %d is not supported
\n
"
,
rate
);
return
-
EINVAL
;
}
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S8
:
width
=
SI476X_PCM_FORMAT_S8
;
case
SNDRV_PCM_FORMAT_S16_LE
:
width
=
SI476X_PCM_FORMAT_S16_LE
;
break
;
case
SNDRV_PCM_FORMAT_S20_3LE
:
width
=
SI476X_PCM_FORMAT_S20_3LE
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
width
=
SI476X_PCM_FORMAT_S24_LE
;
break
;
default:
return
-
EINVAL
;
}
err
=
snd_soc_write
(
dai
->
codec
,
SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE
,
rate
);
if
(
err
<
0
)
{
dev_err
(
dai
->
codec
->
dev
,
"Failed to set sample rate
\n
"
);
return
err
;
}
err
=
snd_soc_update_bits
(
dai
->
codec
,
SI476X_DIGITAL_IO_OUTPUT_FORMAT
,
SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK
,
(
width
<<
SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT
)
|
(
width
<<
SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT
));
if
(
err
<
0
)
{
dev_err
(
dai
->
codec
->
dev
,
"Failed to set output width
\n
"
);
return
err
;
}
return
0
;
}
static
int
si476x_codec_probe
(
struct
snd_soc_codec
*
codec
)
{
codec
->
control_data
=
i2c_mfd_cell_to_core
(
codec
->
dev
);
return
0
;
}
static
struct
snd_soc_dai_ops
si476x_dai_ops
=
{
.
hw_params
=
si476x_codec_hw_params
,
.
set_fmt
=
si476x_codec_set_dai_fmt
,
};
static
struct
snd_soc_dai_driver
si476x_dai
=
{
.
name
=
"si476x-codec"
,
.
capture
=
{
.
stream_name
=
"Capture"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_32000
|
SNDRV_PCM_RATE_44100
|
SNDRV_PCM_RATE_48000
,
.
formats
=
SNDRV_PCM_FMTBIT_S8
|
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S20_3LE
|
SNDRV_PCM_FMTBIT_S24_LE
},
.
ops
=
&
si476x_dai_ops
,
};
static
struct
snd_soc_codec_driver
soc_codec_dev_si476x
=
{
.
probe
=
si476x_codec_probe
,
.
read
=
si476x_codec_read
,
.
write
=
si476x_codec_write
,
};
static
int
__devinit
si476x_platform_probe
(
struct
platform_device
*
pdev
)
{
return
snd_soc_register_codec
(
&
pdev
->
dev
,
&
soc_codec_dev_si476x
,
&
si476x_dai
,
1
);
}
static
int
__devexit
si476x_platform_remove
(
struct
platform_device
*
pdev
)
{
snd_soc_unregister_codec
(
&
pdev
->
dev
);
return
0
;
}
MODULE_ALIAS
(
"platform:si476x-codec"
);
static
struct
platform_driver
si476x_platform_driver
=
{
.
driver
=
{
.
name
=
"si476x-codec"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
si476x_platform_probe
,
.
remove
=
__devexit_p
(
si476x_platform_remove
),
};
module_platform_driver
(
si476x_platform_driver
);
MODULE_AUTHOR
(
"Andrey Smirnov <andrey.smirnov@convergeddevices.net>"
);
MODULE_DESCRIPTION
(
"ASoC Si4761/64 codec driver"
);
MODULE_LICENSE
(
"GPL"
);
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