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
0334a537
Commit
0334a537
authored
Mar 28, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/pcm1789' into asoc-next
parents
338f803a
e4fe156a
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
391 additions
and
0 deletions
+391
-0
Documentation/devicetree/bindings/sound/pcm1789.txt
Documentation/devicetree/bindings/sound/pcm1789.txt
+22
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+12
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+4
-0
sound/soc/codecs/pcm1789-i2c.c
sound/soc/codecs/pcm1789-i2c.c
+62
-0
sound/soc/codecs/pcm1789.c
sound/soc/codecs/pcm1789.c
+274
-0
sound/soc/codecs/pcm1789.h
sound/soc/codecs/pcm1789.h
+17
-0
No files found.
Documentation/devicetree/bindings/sound/pcm1789.txt
0 → 100644
View file @
0334a537
Texas Instruments pcm1789 DT bindings
PCM1789 is a simple audio codec that can be connected via
I2C or SPI. Currently, only I2C bus is supported.
Required properties:
- compatible: "ti,pcm1789"
Required properties on I2C:
- reg: the I2C address
- reset-gpios: GPIO to control the RESET pin
Examples:
audio-codec@4c {
compatible = "ti,pcm1789";
reg = <0x4c>;
reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
};
sound/soc/codecs/Kconfig
View file @
0334a537
...
...
@@ -108,6 +108,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_NAU8825 if I2C
select SND_SOC_HDMI_CODEC
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1789_I2C if I2C
select SND_SOC_PCM179X_I2C if I2C
select SND_SOC_PCM179X_SPI if SPI_MASTER
select SND_SOC_PCM186X_I2C if I2C
...
...
@@ -650,6 +651,17 @@ config SND_SOC_PCM1681
tristate "Texas Instruments PCM1681 CODEC"
depends on I2C
config SND_SOC_PCM1789
tristate
config SND_SOC_PCM1789_I2C
tristate "Texas Instruments PCM1789 CODEC (I2C)"
depends on I2C
select SND_SOC_PCM1789
help
Enable support for Texas Instruments PCM1789 CODEC.
Select this if your PCM1789 is connected via an I2C bus.
config SND_SOC_PCM179X
tristate
...
...
sound/soc/codecs/Makefile
View file @
0334a537
...
...
@@ -103,6 +103,8 @@ snd-soc-nau8824-objs := nau8824.o
snd-soc-nau8825-objs
:=
nau8825.o
snd-soc-hdmi-codec-objs
:=
hdmi-codec.o
snd-soc-pcm1681-objs
:=
pcm1681.o
snd-soc-pcm1789-codec-objs
:=
pcm1789.o
snd-soc-pcm1789-i2c-objs
:=
pcm1789-i2c.o
snd-soc-pcm179x-codec-objs
:=
pcm179x.o
snd-soc-pcm179x-i2c-objs
:=
pcm179x-i2c.o
snd-soc-pcm179x-spi-objs
:=
pcm179x-spi.o
...
...
@@ -349,6 +351,8 @@ obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
obj-$(CONFIG_SND_SOC_HDMI_CODEC)
+=
snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM1681)
+=
snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM179X)
+=
snd-soc-pcm179x-codec.o
obj-$(CONFIG_SND_SOC_PCM1789_I2C)
+=
snd-soc-pcm1789-i2c.o
obj-$(CONFIG_SND_SOC_PCM1789)
+=
snd-soc-pcm1789-codec.o
obj-$(CONFIG_SND_SOC_PCM179X_I2C)
+=
snd-soc-pcm179x-i2c.o
obj-$(CONFIG_SND_SOC_PCM179X_SPI)
+=
snd-soc-pcm179x-spi.o
obj-$(CONFIG_SND_SOC_PCM186X)
+=
snd-soc-pcm186x.o
...
...
sound/soc/codecs/pcm1789-i2c.c
0 → 100644
View file @
0334a537
// SPDX-License-Identifier: GPL-2.0
// Audio driver for PCM1789 I2C
// Copyright (C) 2018 Bootlin
// Mylène Josserand <mylene.josserand@bootlin.com>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include "pcm1789.h"
static
int
pcm1789_i2c_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
struct
regmap
*
regmap
;
int
ret
;
regmap
=
devm_regmap_init_i2c
(
client
,
&
pcm1789_regmap_config
);
if
(
IS_ERR
(
regmap
))
{
ret
=
PTR_ERR
(
regmap
);
dev_err
(
&
client
->
dev
,
"Failed to allocate regmap: %d
\n
"
,
ret
);
return
ret
;
}
return
pcm1789_common_init
(
&
client
->
dev
,
regmap
);
}
static
int
pcm1789_i2c_remove
(
struct
i2c_client
*
client
)
{
return
pcm1789_common_exit
(
&
client
->
dev
);
}
static
const
struct
of_device_id
pcm1789_of_match
[]
=
{
{
.
compatible
=
"ti,pcm1789"
,
},
{
}
};
MODULE_DEVICE_TABLE
(
of
,
pcm1789_of_match
);
static
const
struct
i2c_device_id
pcm1789_i2c_ids
[]
=
{
{
"pcm1789"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
pcm1789_i2c_ids
);
static
struct
i2c_driver
pcm1789_i2c_driver
=
{
.
driver
=
{
.
name
=
"pcm1789"
,
.
of_match_table
=
of_match_ptr
(
pcm1789_of_match
),
},
.
id_table
=
pcm1789_i2c_ids
,
.
probe
=
pcm1789_i2c_probe
,
.
remove
=
pcm1789_i2c_remove
,
};
module_i2c_driver
(
pcm1789_i2c_driver
);
MODULE_DESCRIPTION
(
"ASoC PCM1789 I2C driver"
);
MODULE_AUTHOR
(
"Mylène Josserand <mylene.josserand@bootlin.com>"
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/codecs/pcm1789.c
0 → 100644
View file @
0334a537
// SPDX-License-Identifier: GPL-2.0
// Audio driver for PCM1789
// Copyright (C) 2018 Bootlin
// Mylène Josserand <mylene.josserand@bootlin.com>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "pcm1789.h"
#define PCM1789_MUTE_CONTROL 0x10
#define PCM1789_FMT_CONTROL 0x11
#define PCM1789_SOFT_MUTE 0x14
#define PCM1789_DAC_VOL_LEFT 0x18
#define PCM1789_DAC_VOL_RIGHT 0x19
#define PCM1789_FMT_MASK 0x07
#define PCM1789_MUTE_MASK 0x03
#define PCM1789_MUTE_SRET 0x06
struct
pcm1789_private
{
struct
regmap
*
regmap
;
unsigned
int
format
;
unsigned
int
rate
;
struct
gpio_desc
*
reset
;
struct
work_struct
work
;
struct
device
*
dev
;
};
static
const
struct
reg_default
pcm1789_reg_defaults
[]
=
{
{
PCM1789_FMT_CONTROL
,
0x00
},
{
PCM1789_SOFT_MUTE
,
0x00
},
{
PCM1789_DAC_VOL_LEFT
,
0xff
},
{
PCM1789_DAC_VOL_RIGHT
,
0xff
},
};
static
bool
pcm1789_accessible_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
return
reg
>=
PCM1789_MUTE_CONTROL
&&
reg
<=
PCM1789_DAC_VOL_RIGHT
;
}
static
bool
pcm1789_writeable_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
return
pcm1789_accessible_reg
(
dev
,
reg
);
}
static
int
pcm1789_set_dai_fmt
(
struct
snd_soc_dai
*
codec_dai
,
unsigned
int
format
)
{
struct
snd_soc_component
*
component
=
codec_dai
->
component
;
struct
pcm1789_private
*
priv
=
snd_soc_component_get_drvdata
(
component
);
priv
->
format
=
format
;
return
0
;
}
static
int
pcm1789_digital_mute
(
struct
snd_soc_dai
*
codec_dai
,
int
mute
)
{
struct
snd_soc_component
*
component
=
codec_dai
->
component
;
struct
pcm1789_private
*
priv
=
snd_soc_component_get_drvdata
(
component
);
return
regmap_update_bits
(
priv
->
regmap
,
PCM1789_SOFT_MUTE
,
PCM1789_MUTE_MASK
,
mute
?
0
:
PCM1789_MUTE_MASK
);
}
static
int
pcm1789_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
codec_dai
)
{
struct
snd_soc_component
*
component
=
codec_dai
->
component
;
struct
pcm1789_private
*
priv
=
snd_soc_component_get_drvdata
(
component
);
int
val
=
0
,
ret
;
priv
->
rate
=
params_rate
(
params
);
switch
(
priv
->
format
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_RIGHT_J
:
switch
(
params_width
(
params
))
{
case
24
:
val
=
2
;
break
;
case
16
:
val
=
3
;
break
;
default:
return
-
EINVAL
;
}
break
;
case
SND_SOC_DAIFMT_I2S
:
switch
(
params_width
(
params
))
{
case
16
:
case
24
:
case
32
:
val
=
0
;
break
;
default:
return
-
EINVAL
;
}
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
switch
(
params_width
(
params
))
{
case
16
:
case
24
:
case
32
:
val
=
1
;
break
;
default:
return
-
EINVAL
;
}
break
;
default:
dev_err
(
component
->
dev
,
"Invalid DAI format
\n
"
);
return
-
EINVAL
;
}
ret
=
regmap_update_bits
(
priv
->
regmap
,
PCM1789_FMT_CONTROL
,
PCM1789_FMT_MASK
,
val
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
void
pcm1789_work_queue
(
struct
work_struct
*
work
)
{
struct
pcm1789_private
*
priv
=
container_of
(
work
,
struct
pcm1789_private
,
work
);
/* Perform a software reset to remove codec from desynchronized state */
if
(
regmap_update_bits
(
priv
->
regmap
,
PCM1789_MUTE_CONTROL
,
0x3
<<
PCM1789_MUTE_SRET
,
0
)
<
0
)
dev_err
(
priv
->
dev
,
"Error while setting SRET"
);
}
static
int
pcm1789_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_component
*
component
=
dai
->
component
;
struct
pcm1789_private
*
priv
=
snd_soc_component_get_drvdata
(
component
);
int
ret
=
0
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
schedule_work
(
&
priv
->
work
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
break
;
default:
ret
=
-
EINVAL
;
}
return
ret
;
}
static
const
struct
snd_soc_dai_ops
pcm1789_dai_ops
=
{
.
set_fmt
=
pcm1789_set_dai_fmt
,
.
hw_params
=
pcm1789_hw_params
,
.
digital_mute
=
pcm1789_digital_mute
,
.
trigger
=
pcm1789_trigger
,
};
static
const
DECLARE_TLV_DB_SCALE
(
pcm1789_dac_tlv
,
-
12000
,
50
,
1
);
static
const
struct
snd_kcontrol_new
pcm1789_controls
[]
=
{
SOC_DOUBLE_R_RANGE_TLV
(
"DAC Playback Volume"
,
PCM1789_DAC_VOL_LEFT
,
PCM1789_DAC_VOL_RIGHT
,
0
,
0xf
,
0xff
,
0
,
pcm1789_dac_tlv
),
};
static
const
struct
snd_soc_dapm_widget
pcm1789_dapm_widgets
[]
=
{
SND_SOC_DAPM_OUTPUT
(
"IOUTL+"
),
SND_SOC_DAPM_OUTPUT
(
"IOUTL-"
),
SND_SOC_DAPM_OUTPUT
(
"IOUTR+"
),
SND_SOC_DAPM_OUTPUT
(
"IOUTR-"
),
};
static
const
struct
snd_soc_dapm_route
pcm1789_dapm_routes
[]
=
{
{
"IOUTL+"
,
NULL
,
"Playback"
},
{
"IOUTL-"
,
NULL
,
"Playback"
},
{
"IOUTR+"
,
NULL
,
"Playback"
},
{
"IOUTR-"
,
NULL
,
"Playback"
},
};
static
struct
snd_soc_dai_driver
pcm1789_dai
=
{
.
name
=
"pcm1789-hifi"
,
.
playback
=
{
.
stream_name
=
"Playback"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_CONTINUOUS
,
.
rate_min
=
10000
,
.
rate_max
=
200000
,
.
formats
=
PCM1789_FORMATS
,
},
.
ops
=
&
pcm1789_dai_ops
,
};
const
struct
regmap_config
pcm1789_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
PCM1789_DAC_VOL_RIGHT
,
.
reg_defaults
=
pcm1789_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
pcm1789_reg_defaults
),
.
writeable_reg
=
pcm1789_writeable_reg
,
.
readable_reg
=
pcm1789_accessible_reg
,
};
EXPORT_SYMBOL_GPL
(
pcm1789_regmap_config
);
static
const
struct
snd_soc_component_driver
soc_component_dev_pcm1789
=
{
.
controls
=
pcm1789_controls
,
.
num_controls
=
ARRAY_SIZE
(
pcm1789_controls
),
.
dapm_widgets
=
pcm1789_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
pcm1789_dapm_widgets
),
.
dapm_routes
=
pcm1789_dapm_routes
,
.
num_dapm_routes
=
ARRAY_SIZE
(
pcm1789_dapm_routes
),
.
idle_bias_on
=
1
,
.
use_pmdown_time
=
1
,
.
endianness
=
1
,
.
non_legacy_dai_naming
=
1
,
};
int
pcm1789_common_init
(
struct
device
*
dev
,
struct
regmap
*
regmap
)
{
struct
pcm1789_private
*
pcm1789
;
pcm1789
=
devm_kzalloc
(
dev
,
sizeof
(
struct
pcm1789_private
),
GFP_KERNEL
);
if
(
!
pcm1789
)
return
-
ENOMEM
;
pcm1789
->
regmap
=
regmap
;
pcm1789
->
dev
=
dev
;
dev_set_drvdata
(
dev
,
pcm1789
);
pcm1789
->
reset
=
devm_gpiod_get_optional
(
dev
,
"reset"
,
GPIOD_OUT_HIGH
);
if
(
IS_ERR
(
pcm1789
->
reset
))
return
PTR_ERR
(
pcm1789
->
reset
);
gpiod_set_value_cansleep
(
pcm1789
->
reset
,
0
);
msleep
(
300
);
INIT_WORK
(
&
pcm1789
->
work
,
pcm1789_work_queue
);
return
devm_snd_soc_register_component
(
dev
,
&
soc_component_dev_pcm1789
,
&
pcm1789_dai
,
1
);
}
EXPORT_SYMBOL_GPL
(
pcm1789_common_init
);
int
pcm1789_common_exit
(
struct
device
*
dev
)
{
struct
pcm1789_private
*
priv
=
dev_get_drvdata
(
dev
);
if
(
&
priv
->
work
)
flush_work
(
&
priv
->
work
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
pcm1789_common_exit
);
MODULE_DESCRIPTION
(
"ASoC PCM1789 driver"
);
MODULE_AUTHOR
(
"Mylène Josserand <mylene.josserand@free-electrons.com>"
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/codecs/pcm1789.h
0 → 100644
View file @
0334a537
// SPDX-License-Identifier: GPL-2.0
// Definitions for PCM1789 audio driver
// Copyright (C) 2018 Bootlin
// Mylène Josserand <mylene.josserand@bootlin.com>
#ifndef __PCM1789_H__
#define __PCM1789_H__
#define PCM1789_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S16_LE)
extern
const
struct
regmap_config
pcm1789_regmap_config
;
int
pcm1789_common_init
(
struct
device
*
dev
,
struct
regmap
*
regmap
);
int
pcm1789_common_exit
(
struct
device
*
dev
);
#endif
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