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
52db65f0
Commit
52db65f0
authored
Mar 12, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/pcm512x' into asoc-next
parents
3b93f059
e97db9ab
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
953 additions
and
0 deletions
+953
-0
Documentation/devicetree/bindings/sound/pcm512x.txt
Documentation/devicetree/bindings/sound/pcm512x.txt
+30
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+17
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+6
-0
sound/soc/codecs/pcm512x-i2c.c
sound/soc/codecs/pcm512x-i2c.c
+71
-0
sound/soc/codecs/pcm512x-spi.c
sound/soc/codecs/pcm512x-spi.c
+69
-0
sound/soc/codecs/pcm512x.c
sound/soc/codecs/pcm512x.c
+589
-0
sound/soc/codecs/pcm512x.h
sound/soc/codecs/pcm512x.h
+171
-0
No files found.
Documentation/devicetree/bindings/sound/pcm512x.txt
0 → 100644
View file @
52db65f0
PCM512x audio CODECs
These devices support both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible : One of "ti,pcm5121" or "ti,pcm5122"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
- AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
device, as covered in bindings/regulator/regulator.txt
Optional properties:
- clocks : A clock specifier for the clock connected as SCLK. If this
is absent the device will be configured to clock from BCLK.
Example:
pcm5122: pcm5122@4c {
compatible = "ti,pcm5122";
reg = <0x4c>;
AVDD-supply = <®_3v3_analog>;
DVDD-supply = <®_1v8>;
CPVDD-supply = <®_3v3>;
};
sound/soc/codecs/Kconfig
View file @
52db65f0
...
@@ -59,6 +59,8 @@ config SND_SOC_ALL_CODECS
...
@@ -59,6 +59,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM3008
select SND_SOC_PCM3008
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SGTL5000 if I2C
...
@@ -313,6 +315,21 @@ config SND_SOC_PCM1792A
...
@@ -313,6 +315,21 @@ config SND_SOC_PCM1792A
config SND_SOC_PCM3008
config SND_SOC_PCM3008
tristate
tristate
config SND_SOC_PCM512x
tristate
config SND_SOC_PCM512x_I2C
tristate "Texas Instruments PCM512x CODECs - I2C"
depends on I2C
select SND_SOC_PCM512x
select REGMAP_I2C
config SND_SOC_PCM512x_SPI
tristate "Texas Instruments PCM512x CODECs - SPI"
depends on SPI_MASTER
select SND_SOC_PCM512x
select REGMAP_SPI
config SND_SOC_RT5631
config SND_SOC_RT5631
tristate
tristate
...
...
sound/soc/codecs/Makefile
View file @
52db65f0
...
@@ -46,6 +46,9 @@ snd-soc-hdmi-codec-objs := hdmi.o
...
@@ -46,6 +46,9 @@ snd-soc-hdmi-codec-objs := hdmi.o
snd-soc-pcm1681-objs
:=
pcm1681.o
snd-soc-pcm1681-objs
:=
pcm1681.o
snd-soc-pcm1792a-codec-objs
:=
pcm1792a.o
snd-soc-pcm1792a-codec-objs
:=
pcm1792a.o
snd-soc-pcm3008-objs
:=
pcm3008.o
snd-soc-pcm3008-objs
:=
pcm3008.o
snd-soc-pcm512x-objs
:=
pcm512x.o
snd-soc-pcm512x-i2c-objs
:=
pcm512x-i2c.o
snd-soc-pcm512x-spi-objs
:=
pcm512x-spi.o
snd-soc-rt5631-objs
:=
rt5631.o
snd-soc-rt5631-objs
:=
rt5631.o
snd-soc-rt5640-objs
:=
rt5640.o
snd-soc-rt5640-objs
:=
rt5640.o
snd-soc-sgtl5000-objs
:=
sgtl5000.o
snd-soc-sgtl5000-objs
:=
sgtl5000.o
...
@@ -179,6 +182,9 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
...
@@ -179,6 +182,9 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM1681)
+=
snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM1681)
+=
snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM1792A)
+=
snd-soc-pcm1792a-codec.o
obj-$(CONFIG_SND_SOC_PCM1792A)
+=
snd-soc-pcm1792a-codec.o
obj-$(CONFIG_SND_SOC_PCM3008)
+=
snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_PCM3008)
+=
snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_PCM512x)
+=
snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C)
+=
snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI)
+=
snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RT5631)
+=
snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5631)
+=
snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640)
+=
snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_RT5640)
+=
snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_SGTL5000)
+=
snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SGTL5000)
+=
snd-soc-sgtl5000.o
...
...
sound/soc/codecs/pcm512x-i2c.c
0 → 100644
View file @
52db65f0
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include "pcm512x.h"
static
int
pcm512x_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
regmap
*
regmap
;
regmap
=
devm_regmap_init_i2c
(
i2c
,
&
pcm512x_regmap
);
if
(
IS_ERR
(
regmap
))
return
PTR_ERR
(
regmap
);
return
pcm512x_probe
(
&
i2c
->
dev
,
regmap
);
}
static
int
pcm512x_i2c_remove
(
struct
i2c_client
*
i2c
)
{
pcm512x_remove
(
&
i2c
->
dev
);
return
0
;
}
static
const
struct
i2c_device_id
pcm512x_i2c_id
[]
=
{
{
"pcm5121"
,
},
{
"pcm5122"
,
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
pcm512x_i2c_id
);
static
const
struct
of_device_id
pcm512x_of_match
[]
=
{
{
.
compatible
=
"ti,pcm5121"
,
},
{
.
compatible
=
"ti,pcm5122"
,
},
{
}
};
MODULE_DEVICE_TABLE
(
of
,
pcm512x_of_match
);
static
struct
i2c_driver
pcm512x_i2c_driver
=
{
.
probe
=
pcm512x_i2c_probe
,
.
remove
=
pcm512x_i2c_remove
,
.
id_table
=
pcm512x_i2c_id
,
.
driver
=
{
.
name
=
"pcm512x"
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
pcm512x_of_match
,
.
pm
=
&
pcm512x_pm_ops
,
},
};
module_i2c_driver
(
pcm512x_i2c_driver
);
MODULE_DESCRIPTION
(
"ASoC PCM512x codec driver - I2C"
);
MODULE_AUTHOR
(
"Mark Brown <broonie@linaro.org>"
);
MODULE_LICENSE
(
"GPL v2"
);
sound/soc/codecs/pcm512x-spi.c
0 → 100644
View file @
52db65f0
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include "pcm512x.h"
static
int
pcm512x_spi_probe
(
struct
spi_device
*
spi
)
{
struct
regmap
*
regmap
;
int
ret
;
regmap
=
devm_regmap_init_spi
(
spi
,
&
pcm512x_regmap
);
if
(
IS_ERR
(
regmap
))
{
ret
=
PTR_ERR
(
regmap
);
return
ret
;
}
return
pcm512x_probe
(
&
spi
->
dev
,
regmap
);
}
static
int
pcm512x_spi_remove
(
struct
spi_device
*
spi
)
{
pcm512x_remove
(
&
spi
->
dev
);
return
0
;
}
static
const
struct
spi_device_id
pcm512x_spi_id
[]
=
{
{
"pcm5121"
,
},
{
"pcm5122"
,
},
{
},
};
MODULE_DEVICE_TABLE
(
spi
,
pcm512x_spi_id
);
static
const
struct
of_device_id
pcm512x_of_match
[]
=
{
{
.
compatible
=
"ti,pcm5121"
,
},
{
.
compatible
=
"ti,pcm5122"
,
},
{
}
};
MODULE_DEVICE_TABLE
(
of
,
pcm512x_of_match
);
static
struct
spi_driver
pcm512x_spi_driver
=
{
.
probe
=
pcm512x_spi_probe
,
.
remove
=
pcm512x_spi_remove
,
.
id_table
=
pcm512x_spi_id
,
.
driver
=
{
.
name
=
"pcm512x"
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
pcm512x_of_match
,
.
pm
=
&
pcm512x_pm_ops
,
},
};
module_spi_driver
(
pcm512x_spi_driver
);
sound/soc/codecs/pcm512x.c
0 → 100644
View file @
52db65f0
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "pcm512x.h"
#define PCM512x_NUM_SUPPLIES 3
static
const
char
*
const
pcm512x_supply_names
[
PCM512x_NUM_SUPPLIES
]
=
{
"AVDD"
,
"DVDD"
,
"CPVDD"
,
};
struct
pcm512x_priv
{
struct
regmap
*
regmap
;
struct
clk
*
sclk
;
struct
regulator_bulk_data
supplies
[
PCM512x_NUM_SUPPLIES
];
struct
notifier_block
supply_nb
[
PCM512x_NUM_SUPPLIES
];
};
/*
* We can't use the same notifier block for more than one supply and
* there's no way I can see to get from a callback to the caller
* except container_of().
*/
#define PCM512x_REGULATOR_EVENT(n) \
static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
unsigned long event, void *data) \
{ \
struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
supply_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
regcache_mark_dirty(pcm512x->regmap); \
regcache_cache_only(pcm512x->regmap, true); \
} \
return 0; \
}
PCM512x_REGULATOR_EVENT
(
0
)
PCM512x_REGULATOR_EVENT
(
1
)
PCM512x_REGULATOR_EVENT
(
2
)
static
const
struct
reg_default
pcm512x_reg_defaults
[]
=
{
{
PCM512x_RESET
,
0x00
},
{
PCM512x_POWER
,
0x00
},
{
PCM512x_MUTE
,
0x00
},
{
PCM512x_DSP
,
0x00
},
{
PCM512x_PLL_REF
,
0x00
},
{
PCM512x_DAC_ROUTING
,
0x11
},
{
PCM512x_DSP_PROGRAM
,
0x01
},
{
PCM512x_CLKDET
,
0x00
},
{
PCM512x_AUTO_MUTE
,
0x00
},
{
PCM512x_ERROR_DETECT
,
0x00
},
{
PCM512x_DIGITAL_VOLUME_1
,
0x00
},
{
PCM512x_DIGITAL_VOLUME_2
,
0x30
},
{
PCM512x_DIGITAL_VOLUME_3
,
0x30
},
{
PCM512x_DIGITAL_MUTE_1
,
0x22
},
{
PCM512x_DIGITAL_MUTE_2
,
0x00
},
{
PCM512x_DIGITAL_MUTE_3
,
0x07
},
{
PCM512x_OUTPUT_AMPLITUDE
,
0x00
},
{
PCM512x_ANALOG_GAIN_CTRL
,
0x00
},
{
PCM512x_UNDERVOLTAGE_PROT
,
0x00
},
{
PCM512x_ANALOG_MUTE_CTRL
,
0x00
},
{
PCM512x_ANALOG_GAIN_BOOST
,
0x00
},
{
PCM512x_VCOM_CTRL_1
,
0x00
},
{
PCM512x_VCOM_CTRL_2
,
0x01
},
};
static
bool
pcm512x_readable
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
PCM512x_RESET
:
case
PCM512x_POWER
:
case
PCM512x_MUTE
:
case
PCM512x_PLL_EN
:
case
PCM512x_SPI_MISO_FUNCTION
:
case
PCM512x_DSP
:
case
PCM512x_GPIO_EN
:
case
PCM512x_BCLK_LRCLK_CFG
:
case
PCM512x_DSP_GPIO_INPUT
:
case
PCM512x_MASTER_MODE
:
case
PCM512x_PLL_REF
:
case
PCM512x_PLL_COEFF_0
:
case
PCM512x_PLL_COEFF_1
:
case
PCM512x_PLL_COEFF_2
:
case
PCM512x_PLL_COEFF_3
:
case
PCM512x_PLL_COEFF_4
:
case
PCM512x_DSP_CLKDIV
:
case
PCM512x_DAC_CLKDIV
:
case
PCM512x_NCP_CLKDIV
:
case
PCM512x_OSR_CLKDIV
:
case
PCM512x_MASTER_CLKDIV_1
:
case
PCM512x_MASTER_CLKDIV_2
:
case
PCM512x_FS_SPEED_MODE
:
case
PCM512x_IDAC_1
:
case
PCM512x_IDAC_2
:
case
PCM512x_ERROR_DETECT
:
case
PCM512x_I2S_1
:
case
PCM512x_I2S_2
:
case
PCM512x_DAC_ROUTING
:
case
PCM512x_DSP_PROGRAM
:
case
PCM512x_CLKDET
:
case
PCM512x_AUTO_MUTE
:
case
PCM512x_DIGITAL_VOLUME_1
:
case
PCM512x_DIGITAL_VOLUME_2
:
case
PCM512x_DIGITAL_VOLUME_3
:
case
PCM512x_DIGITAL_MUTE_1
:
case
PCM512x_DIGITAL_MUTE_2
:
case
PCM512x_DIGITAL_MUTE_3
:
case
PCM512x_GPIO_OUTPUT_1
:
case
PCM512x_GPIO_OUTPUT_2
:
case
PCM512x_GPIO_OUTPUT_3
:
case
PCM512x_GPIO_OUTPUT_4
:
case
PCM512x_GPIO_OUTPUT_5
:
case
PCM512x_GPIO_OUTPUT_6
:
case
PCM512x_GPIO_CONTROL_1
:
case
PCM512x_GPIO_CONTROL_2
:
case
PCM512x_OVERFLOW
:
case
PCM512x_RATE_DET_1
:
case
PCM512x_RATE_DET_2
:
case
PCM512x_RATE_DET_3
:
case
PCM512x_RATE_DET_4
:
case
PCM512x_ANALOG_MUTE_DET
:
case
PCM512x_GPIN
:
case
PCM512x_DIGITAL_MUTE_DET
:
case
PCM512x_OUTPUT_AMPLITUDE
:
case
PCM512x_ANALOG_GAIN_CTRL
:
case
PCM512x_UNDERVOLTAGE_PROT
:
case
PCM512x_ANALOG_MUTE_CTRL
:
case
PCM512x_ANALOG_GAIN_BOOST
:
case
PCM512x_VCOM_CTRL_1
:
case
PCM512x_VCOM_CTRL_2
:
case
PCM512x_CRAM_CTRL
:
return
true
;
default:
/* There are 256 raw register addresses */
return
reg
<
0xff
;
}
}
static
bool
pcm512x_volatile
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
PCM512x_PLL_EN
:
case
PCM512x_OVERFLOW
:
case
PCM512x_RATE_DET_1
:
case
PCM512x_RATE_DET_2
:
case
PCM512x_RATE_DET_3
:
case
PCM512x_RATE_DET_4
:
case
PCM512x_ANALOG_MUTE_DET
:
case
PCM512x_GPIN
:
case
PCM512x_DIGITAL_MUTE_DET
:
case
PCM512x_CRAM_CTRL
:
return
true
;
default:
/* There are 256 raw register addresses */
return
reg
<
0xff
;
}
}
static
const
DECLARE_TLV_DB_SCALE
(
digital_tlv
,
-
10350
,
50
,
1
);
static
const
DECLARE_TLV_DB_SCALE
(
analog_tlv
,
-
600
,
600
,
0
);
static
const
DECLARE_TLV_DB_SCALE
(
boost_tlv
,
0
,
80
,
0
);
static
const
char
*
const
pcm512x_dsp_program_texts
[]
=
{
"FIR interpolation with de-emphasis"
,
"Low latency IIR with de-emphasis"
,
"Fixed process flow"
,
"High attenuation with de-emphasis"
,
"Ringing-less low latency FIR"
,
};
static
const
unsigned
int
pcm512x_dsp_program_values
[]
=
{
1
,
2
,
3
,
5
,
7
,
};
static
SOC_VALUE_ENUM_SINGLE_DECL
(
pcm512x_dsp_program
,
PCM512x_DSP_PROGRAM
,
0
,
0x1f
,
pcm512x_dsp_program_texts
,
pcm512x_dsp_program_values
);
static
const
char
*
const
pcm512x_clk_missing_text
[]
=
{
"1s"
,
"2s"
,
"3s"
,
"4s"
,
"5s"
,
"6s"
,
"7s"
,
"8s"
};
static
const
struct
soc_enum
pcm512x_clk_missing
=
SOC_ENUM_SINGLE
(
PCM512x_CLKDET
,
0
,
8
,
pcm512x_clk_missing_text
);
static
const
char
*
const
pcm512x_autom_text
[]
=
{
"21ms"
,
"106ms"
,
"213ms"
,
"533ms"
,
"1.07s"
,
"2.13s"
,
"5.33s"
,
"10.66s"
};
static
const
struct
soc_enum
pcm512x_autom_l
=
SOC_ENUM_SINGLE
(
PCM512x_AUTO_MUTE
,
PCM512x_ATML_SHIFT
,
8
,
pcm512x_autom_text
);
static
const
struct
soc_enum
pcm512x_autom_r
=
SOC_ENUM_SINGLE
(
PCM512x_AUTO_MUTE
,
PCM512x_ATMR_SHIFT
,
8
,
pcm512x_autom_text
);
static
const
char
*
const
pcm512x_ramp_rate_text
[]
=
{
"1 sample/update"
,
"2 samples/update"
,
"4 samples/update"
,
"Immediate"
};
static
const
struct
soc_enum
pcm512x_vndf
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_1
,
PCM512x_VNDF_SHIFT
,
4
,
pcm512x_ramp_rate_text
);
static
const
struct
soc_enum
pcm512x_vnuf
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_1
,
PCM512x_VNUF_SHIFT
,
4
,
pcm512x_ramp_rate_text
);
static
const
struct
soc_enum
pcm512x_vedf
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_2
,
PCM512x_VEDF_SHIFT
,
4
,
pcm512x_ramp_rate_text
);
static
const
char
*
const
pcm512x_ramp_step_text
[]
=
{
"4dB/step"
,
"2dB/step"
,
"1dB/step"
,
"0.5dB/step"
};
static
const
struct
soc_enum
pcm512x_vnds
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_1
,
PCM512x_VNDS_SHIFT
,
4
,
pcm512x_ramp_step_text
);
static
const
struct
soc_enum
pcm512x_vnus
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_1
,
PCM512x_VNUS_SHIFT
,
4
,
pcm512x_ramp_step_text
);
static
const
struct
soc_enum
pcm512x_veds
=
SOC_ENUM_SINGLE
(
PCM512x_DIGITAL_MUTE_2
,
PCM512x_VEDS_SHIFT
,
4
,
pcm512x_ramp_step_text
);
static
const
struct
snd_kcontrol_new
pcm512x_controls
[]
=
{
SOC_DOUBLE_R_TLV
(
"Playback Digital Volume"
,
PCM512x_DIGITAL_VOLUME_2
,
PCM512x_DIGITAL_VOLUME_3
,
0
,
255
,
1
,
digital_tlv
),
SOC_DOUBLE_TLV
(
"Playback Volume"
,
PCM512x_ANALOG_GAIN_CTRL
,
PCM512x_LAGN_SHIFT
,
PCM512x_RAGN_SHIFT
,
1
,
1
,
analog_tlv
),
SOC_DOUBLE_TLV
(
"Playback Boost Volume"
,
PCM512x_ANALOG_GAIN_BOOST
,
PCM512x_AGBL_SHIFT
,
PCM512x_AGBR_SHIFT
,
1
,
0
,
boost_tlv
),
SOC_DOUBLE
(
"Playback Digital Switch"
,
PCM512x_MUTE
,
PCM512x_RQML_SHIFT
,
PCM512x_RQMR_SHIFT
,
1
,
1
),
SOC_SINGLE
(
"Deemphasis Switch"
,
PCM512x_DSP
,
PCM512x_DEMP_SHIFT
,
1
,
1
),
SOC_VALUE_ENUM
(
"DSP Program"
,
pcm512x_dsp_program
),
SOC_ENUM
(
"Clock Missing Period"
,
pcm512x_clk_missing
),
SOC_ENUM
(
"Auto Mute Time Left"
,
pcm512x_autom_l
),
SOC_ENUM
(
"Auto Mute Time Right"
,
pcm512x_autom_r
),
SOC_SINGLE
(
"Auto Mute Mono Switch"
,
PCM512x_DIGITAL_MUTE_3
,
PCM512x_ACTL_SHIFT
,
1
,
0
),
SOC_DOUBLE
(
"Auto Mute Switch"
,
PCM512x_DIGITAL_MUTE_3
,
PCM512x_AMLE_SHIFT
,
PCM512x_AMLR_SHIFT
,
1
,
0
),
SOC_ENUM
(
"Volume Ramp Down Rate"
,
pcm512x_vndf
),
SOC_ENUM
(
"Volume Ramp Down Step"
,
pcm512x_vnds
),
SOC_ENUM
(
"Volume Ramp Up Rate"
,
pcm512x_vnuf
),
SOC_ENUM
(
"Volume Ramp Up Step"
,
pcm512x_vnus
),
SOC_ENUM
(
"Volume Ramp Down Emergency Rate"
,
pcm512x_vedf
),
SOC_ENUM
(
"Volume Ramp Down Emergency Step"
,
pcm512x_veds
),
};
static
const
struct
snd_soc_dapm_widget
pcm512x_dapm_widgets
[]
=
{
SND_SOC_DAPM_DAC
(
"DACL"
,
NULL
,
SND_SOC_NOPM
,
0
,
0
),
SND_SOC_DAPM_DAC
(
"DACR"
,
NULL
,
SND_SOC_NOPM
,
0
,
0
),
SND_SOC_DAPM_OUTPUT
(
"OUTL"
),
SND_SOC_DAPM_OUTPUT
(
"OUTR"
),
};
static
const
struct
snd_soc_dapm_route
pcm512x_dapm_routes
[]
=
{
{
"DACL"
,
NULL
,
"Playback"
},
{
"DACR"
,
NULL
,
"Playback"
},
{
"OUTL"
,
NULL
,
"DACL"
},
{
"OUTR"
,
NULL
,
"DACR"
},
};
static
int
pcm512x_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
struct
pcm512x_priv
*
pcm512x
=
dev_get_drvdata
(
codec
->
dev
);
int
ret
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
case
SND_SOC_BIAS_PREPARE
:
break
;
case
SND_SOC_BIAS_STANDBY
:
ret
=
regmap_update_bits
(
pcm512x
->
regmap
,
PCM512x_POWER
,
PCM512x_RQST
,
0
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to remove standby: %d
\n
"
,
ret
);
return
ret
;
}
break
;
case
SND_SOC_BIAS_OFF
:
ret
=
regmap_update_bits
(
pcm512x
->
regmap
,
PCM512x_POWER
,
PCM512x_RQST
,
PCM512x_RQST
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to request standby: %d
\n
"
,
ret
);
return
ret
;
}
break
;
}
codec
->
dapm
.
bias_level
=
level
;
return
0
;
}
static
struct
snd_soc_dai_driver
pcm512x_dai
=
{
.
name
=
"pcm512x-hifi"
,
.
playback
=
{
.
stream_name
=
"Playback"
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_8000_192000
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S24_LE
|
SNDRV_PCM_FMTBIT_S32_LE
},
};
static
struct
snd_soc_codec_driver
pcm512x_codec_driver
=
{
.
set_bias_level
=
pcm512x_set_bias_level
,
.
idle_bias_off
=
true
,
.
controls
=
pcm512x_controls
,
.
num_controls
=
ARRAY_SIZE
(
pcm512x_controls
),
.
dapm_widgets
=
pcm512x_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
pcm512x_dapm_widgets
),
.
dapm_routes
=
pcm512x_dapm_routes
,
.
num_dapm_routes
=
ARRAY_SIZE
(
pcm512x_dapm_routes
),
};
static
const
struct
regmap_range_cfg
pcm512x_range
=
{
.
name
=
"Pages"
,
.
range_min
=
PCM512x_VIRT_BASE
,
.
range_max
=
PCM512x_MAX_REGISTER
,
.
selector_reg
=
PCM512x_PAGE
,
.
selector_mask
=
0xff
,
.
window_start
=
0
,
.
window_len
=
0x100
,
};
const
struct
regmap_config
pcm512x_regmap
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
readable_reg
=
pcm512x_readable
,
.
volatile_reg
=
pcm512x_volatile
,
.
ranges
=
&
pcm512x_range
,
.
num_ranges
=
1
,
.
max_register
=
PCM512x_MAX_REGISTER
,
.
reg_defaults
=
pcm512x_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
pcm512x_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
};
EXPORT_SYMBOL_GPL
(
pcm512x_regmap
);
int
pcm512x_probe
(
struct
device
*
dev
,
struct
regmap
*
regmap
)
{
struct
pcm512x_priv
*
pcm512x
;
int
i
,
ret
;
pcm512x
=
devm_kzalloc
(
dev
,
sizeof
(
struct
pcm512x_priv
),
GFP_KERNEL
);
if
(
!
pcm512x
)
return
-
ENOMEM
;
dev_set_drvdata
(
dev
,
pcm512x
);
pcm512x
->
regmap
=
regmap
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pcm512x
->
supplies
);
i
++
)
pcm512x
->
supplies
[
i
].
supply
=
pcm512x_supply_names
[
i
];
ret
=
devm_regulator_bulk_get
(
dev
,
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to get supplies: %d
\n
"
,
ret
);
return
ret
;
}
pcm512x
->
supply_nb
[
0
].
notifier_call
=
pcm512x_regulator_event_0
;
pcm512x
->
supply_nb
[
1
].
notifier_call
=
pcm512x_regulator_event_1
;
pcm512x
->
supply_nb
[
2
].
notifier_call
=
pcm512x_regulator_event_2
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pcm512x
->
supplies
);
i
++
)
{
ret
=
regulator_register_notifier
(
pcm512x
->
supplies
[
i
].
consumer
,
&
pcm512x
->
supply_nb
[
i
]);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to register regulator notifier: %d
\n
"
,
ret
);
}
}
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to enable supplies: %d
\n
"
,
ret
);
return
ret
;
}
/* Reset the device, verifying I/O in the process for I2C */
ret
=
regmap_write
(
regmap
,
PCM512x_RESET
,
PCM512x_RSTM
|
PCM512x_RSTR
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to reset device: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
regmap_write
(
regmap
,
PCM512x_RESET
,
0
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to reset device: %d
\n
"
,
ret
);
goto
err
;
}
pcm512x
->
sclk
=
devm_clk_get
(
dev
,
NULL
);
if
(
IS_ERR
(
pcm512x
->
sclk
))
{
if
(
PTR_ERR
(
pcm512x
->
sclk
)
==
-
EPROBE_DEFER
)
return
-
EPROBE_DEFER
;
dev_info
(
dev
,
"No SCLK, using BCLK: %ld
\n
"
,
PTR_ERR
(
pcm512x
->
sclk
));
/* Disable reporting of missing SCLK as an error */
regmap_update_bits
(
regmap
,
PCM512x_ERROR_DETECT
,
PCM512x_IDCH
,
PCM512x_IDCH
);
/* Switch PLL input to BCLK */
regmap_update_bits
(
regmap
,
PCM512x_PLL_REF
,
PCM512x_SREF
,
PCM512x_SREF
);
}
else
{
ret
=
clk_prepare_enable
(
pcm512x
->
sclk
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to enable SCLK: %d
\n
"
,
ret
);
return
ret
;
}
}
/* Default to standby mode */
ret
=
regmap_update_bits
(
pcm512x
->
regmap
,
PCM512x_POWER
,
PCM512x_RQST
,
PCM512x_RQST
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to request standby: %d
\n
"
,
ret
);
goto
err_clk
;
}
pm_runtime_set_active
(
dev
);
pm_runtime_enable
(
dev
);
pm_runtime_idle
(
dev
);
ret
=
snd_soc_register_codec
(
dev
,
&
pcm512x_codec_driver
,
&
pcm512x_dai
,
1
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to register CODEC: %d
\n
"
,
ret
);
goto
err_pm
;
}
return
0
;
err_pm:
pm_runtime_disable
(
dev
);
err_clk:
if
(
!
IS_ERR
(
pcm512x
->
sclk
))
clk_disable_unprepare
(
pcm512x
->
sclk
);
err:
regulator_bulk_disable
(
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
pcm512x_probe
);
void
pcm512x_remove
(
struct
device
*
dev
)
{
struct
pcm512x_priv
*
pcm512x
=
dev_get_drvdata
(
dev
);
snd_soc_unregister_codec
(
dev
);
pm_runtime_disable
(
dev
);
if
(
!
IS_ERR
(
pcm512x
->
sclk
))
clk_disable_unprepare
(
pcm512x
->
sclk
);
regulator_bulk_disable
(
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
}
EXPORT_SYMBOL_GPL
(
pcm512x_remove
);
static
int
pcm512x_suspend
(
struct
device
*
dev
)
{
struct
pcm512x_priv
*
pcm512x
=
dev_get_drvdata
(
dev
);
int
ret
;
ret
=
regmap_update_bits
(
pcm512x
->
regmap
,
PCM512x_POWER
,
PCM512x_RQPD
,
PCM512x_RQPD
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to request power down: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
regulator_bulk_disable
(
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to disable supplies: %d
\n
"
,
ret
);
return
ret
;
}
if
(
!
IS_ERR
(
pcm512x
->
sclk
))
clk_disable_unprepare
(
pcm512x
->
sclk
);
return
0
;
}
static
int
pcm512x_resume
(
struct
device
*
dev
)
{
struct
pcm512x_priv
*
pcm512x
=
dev_get_drvdata
(
dev
);
int
ret
;
if
(
!
IS_ERR
(
pcm512x
->
sclk
))
{
ret
=
clk_prepare_enable
(
pcm512x
->
sclk
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to enable SCLK: %d
\n
"
,
ret
);
return
ret
;
}
}
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
pcm512x
->
supplies
),
pcm512x
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to enable supplies: %d
\n
"
,
ret
);
return
ret
;
}
regcache_cache_only
(
pcm512x
->
regmap
,
false
);
ret
=
regcache_sync
(
pcm512x
->
regmap
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to sync cache: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
regmap_update_bits
(
pcm512x
->
regmap
,
PCM512x_POWER
,
PCM512x_RQPD
,
0
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Failed to remove power down: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
const
struct
dev_pm_ops
pcm512x_pm_ops
=
{
SET_RUNTIME_PM_OPS
(
pcm512x_suspend
,
pcm512x_resume
,
NULL
)
};
EXPORT_SYMBOL_GPL
(
pcm512x_pm_ops
);
MODULE_DESCRIPTION
(
"ASoC PCM512x codec driver"
);
MODULE_AUTHOR
(
"Mark Brown <broonie@linaro.org>"
);
MODULE_LICENSE
(
"GPL v2"
);
sound/soc/codecs/pcm512x.h
0 → 100644
View file @
52db65f0
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef _SND_SOC_PCM512X
#define _SND_SOC_PCM512X
#include <linux/pm.h>
#include <linux/regmap.h>
#define PCM512x_VIRT_BASE 0x100
#define PCM512x_PAGE_LEN 0x100
#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n))
#define PCM512x_PAGE 0
#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1)
#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2)
#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3)
#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4)
#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6)
#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7)
#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8)
#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9)
#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10)
#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12)
#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13)
#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20)
#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21)
#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22)
#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23)
#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24)
#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27)
#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28)
#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29)
#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30)
#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32)
#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33)
#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34)
#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35)
#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36)
#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37)
#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40)
#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41)
#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42)
#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43)
#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44)
#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59)
#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60)
#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61)
#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62)
#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63)
#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64)
#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65)
#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80)
#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81)
#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82)
#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83)
#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84)
#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85)
#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86)
#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87)
#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90)
#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91)
#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92)
#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93)
#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94)
#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108)
#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119)
#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120)
#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1)
#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2)
#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5)
#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6)
#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7)
#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8)
#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9)
#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1)
#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1)
/* Page 0, Register 1 - reset */
#define PCM512x_RSTR (1 << 0)
#define PCM512x_RSTM (1 << 4)
/* Page 0, Register 2 - power */
#define PCM512x_RQPD (1 << 0)
#define PCM512x_RQPD_SHIFT 0
#define PCM512x_RQST (1 << 4)
#define PCM512x_RQST_SHIFT 4
/* Page 0, Register 3 - mute */
#define PCM512x_RQMR_SHIFT 0
#define PCM512x_RQML_SHIFT 4
/* Page 0, Register 4 - PLL */
#define PCM512x_PLCE (1 << 0)
#define PCM512x_RLCE_SHIFT 0
#define PCM512x_PLCK (1 << 4)
#define PCM512x_PLCK_SHIFT 4
/* Page 0, Register 7 - DSP */
#define PCM512x_SDSL (1 << 0)
#define PCM512x_SDSL_SHIFT 0
#define PCM512x_DEMP (1 << 4)
#define PCM512x_DEMP_SHIFT 4
/* Page 0, Register 13 - PLL reference */
#define PCM512x_SREF (1 << 4)
/* Page 0, Register 37 - Error detection */
#define PCM512x_IPLK (1 << 0)
#define PCM512x_DCAS (1 << 1)
#define PCM512x_IDCM (1 << 2)
#define PCM512x_IDCH (1 << 3)
#define PCM512x_IDSK (1 << 4)
#define PCM512x_IDBK (1 << 5)
#define PCM512x_IDFS (1 << 6)
/* Page 0, Register 42 - DAC routing */
#define PCM512x_AUPR_SHIFT 0
#define PCM512x_AUPL_SHIFT 4
/* Page 0, Register 59 - auto mute */
#define PCM512x_ATMR_SHIFT 0
#define PCM512x_ATML_SHIFT 4
/* Page 0, Register 63 - ramp rates */
#define PCM512x_VNDF_SHIFT 6
#define PCM512x_VNDS_SHIFT 4
#define PCM512x_VNUF_SHIFT 2
#define PCM512x_VNUS_SHIFT 0
/* Page 0, Register 64 - emergency ramp rates */
#define PCM512x_VEDF_SHIFT 6
#define PCM512x_VEDS_SHIFT 4
/* Page 0, Register 65 - Digital mute enables */
#define PCM512x_ACTL_SHIFT 2
#define PCM512x_AMLE_SHIFT 1
#define PCM512x_AMLR_SHIFT 0
/* Page 1, Register 2 - analog volume control */
#define PCM512x_RAGN_SHIFT 0
#define PCM512x_LAGN_SHIFT 4
/* Page 1, Register 7 - analog boost control */
#define PCM512x_AGBR_SHIFT 0
#define PCM512x_AGBL_SHIFT 4
extern
const
struct
dev_pm_ops
pcm512x_pm_ops
;
extern
const
struct
regmap_config
pcm512x_regmap
;
int
pcm512x_probe
(
struct
device
*
dev
,
struct
regmap
*
regmap
);
void
pcm512x_remove
(
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