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
aaa36d3a
Commit
aaa36d3a
authored
May 27, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/tas5270' into asoc-next
parents
4c1c16d9
bd023ada
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
905 additions
and
15 deletions
+905
-15
Documentation/devicetree/bindings/sound/tas571x.txt
Documentation/devicetree/bindings/sound/tas571x.txt
+8
-2
Documentation/devicetree/bindings/sound/tas5720.txt
Documentation/devicetree/bindings/sound/tas5720.txt
+25
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+9
-1
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+2
-0
sound/soc/codecs/tas571x.c
sound/soc/codecs/tas571x.c
+129
-12
sound/soc/codecs/tas571x.h
sound/soc/codecs/tas571x.h
+22
-0
sound/soc/codecs/tas5720.c
sound/soc/codecs/tas5720.c
+620
-0
sound/soc/codecs/tas5720.h
sound/soc/codecs/tas5720.h
+90
-0
No files found.
Documentation/devicetree/bindings/sound/tas571x.txt
View file @
aaa36d3a
Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
Texas Instruments TAS5711/TAS5717/TAS5719
/TAS5721
stereo power amplifiers
The codec is controlled through an I2C interface. It also has two other
signals that can be wired up to GPIOs: reset (strongly recommended), and
...
...
@@ -6,7 +6,11 @@ powerdown (optional).
Required properties:
- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
- compatible: should be one of the following:
- "ti,tas5711",
- "ti,tas5717",
- "ti,tas5719",
- "ti,tas5721"
- reg: The I2C address of the device
- #sound-dai-cells: must be equal to 0
...
...
@@ -25,6 +29,8 @@ Optional properties:
- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
- DRVDD-supply: regulator phandle for the DRVDD supply (5721)
- PVDD-supply: regulator phandle for the PVDD supply (5721)
Example:
...
...
Documentation/devicetree/bindings/sound/tas5720.txt
0 → 100644
View file @
aaa36d3a
Texas Instruments TAS5720 Mono Audio amplifier
The TAS5720 serial control bus communicates through the I2C protocol only. The
serial bus is also used for periodic codec fault checking/reporting during
audio playback. For more product information please see the links below:
http://www.ti.com/product/TAS5720L
http://www.ti.com/product/TAS5720M
Required properties:
- compatible : "ti,tas5720"
- reg : I2C slave address
- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry
- pvdd-supply : phandle to a supply used for the Class-D amp and the analog
Example:
tas5720: tas5720@6c {
status = "okay";
compatible = "ti,tas5720";
reg = <0x6c>;
dvdd-supply = <&vdd_3v3_reg>;
pvdd-supply = <&_supply_reg>;
};
sound/soc/codecs/Kconfig
View file @
aaa36d3a
...
...
@@ -127,6 +127,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
select SND_SOC_TAS571X if I2C
select SND_SOC_TAS5720 if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
...
...
@@ -753,9 +754,16 @@ config SND_SOC_TAS5086
depends on I2C
config SND_SOC_TAS571X
tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
tristate "Texas Instruments TAS5711/TAS5717/TAS5719
/TAS5721
power amplifiers"
depends on I2C
config SND_SOC_TAS5720
tristate "Texas Instruments TAS5720 Mono Audio amplifier"
depends on I2C
help
Enable support for Texas Instruments TAS5720L/M high-efficiency mono
Class-D audio power amplifiers.
config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
...
...
sound/soc/codecs/Makefile
View file @
aaa36d3a
...
...
@@ -132,6 +132,7 @@ snd-soc-stac9766-objs := stac9766.o
snd-soc-sti-sas-objs
:=
sti-sas.o
snd-soc-tas5086-objs
:=
tas5086.o
snd-soc-tas571x-objs
:=
tas571x.o
snd-soc-tas5720-objs
:=
tas5720.o
snd-soc-tfa9879-objs
:=
tfa9879.o
snd-soc-tlv320aic23-objs
:=
tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs
:=
tlv320aic23-i2c.o
...
...
@@ -342,6 +343,7 @@ obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
obj-$(CONFIG_SND_SOC_TAS2552)
+=
snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS5086)
+=
snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X)
+=
snd-soc-tas571x.o
obj-$(CONFIG_SND_SOC_TAS5720)
+=
snd-soc-tas5720.o
obj-$(CONFIG_SND_SOC_TFA9879)
+=
snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TLV320AIC23)
+=
snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)
+=
snd-soc-tlv320aic23-i2c.o
...
...
sound/soc/codecs/tas571x.c
View file @
aaa36d3a
...
...
@@ -4,6 +4,9 @@
* Copyright (C) 2015 Google, Inc.
* Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
*
* TAS5721 support:
* Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
...
...
@@ -57,6 +60,10 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
case
TAS571X_CH1_VOL_REG
:
case
TAS571X_CH2_VOL_REG
:
return
priv
->
chip
->
vol_reg_size
;
case
TAS571X_INPUT_MUX_REG
:
case
TAS571X_CH4_SRC_SELECT_REG
:
case
TAS571X_PWM_MUX_REG
:
return
4
;
default:
return
1
;
}
...
...
@@ -167,6 +174,23 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream,
TAS571X_SDI_FMT_MASK
,
val
);
}
static
int
tas571x_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u8
sysctl2
;
int
ret
;
sysctl2
=
mute
?
TAS571X_SYS_CTRL_2_SDN_MASK
:
0
;
ret
=
snd_soc_update_bits
(
codec
,
TAS571X_SYS_CTRL_2_REG
,
TAS571X_SYS_CTRL_2_SDN_MASK
,
sysctl2
);
usleep_range
(
1000
,
2000
);
return
ret
;
}
static
int
tas571x_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
...
...
@@ -214,6 +238,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec,
static
const
struct
snd_soc_dai_ops
tas571x_dai_ops
=
{
.
set_fmt
=
tas571x_set_dai_fmt
,
.
hw_params
=
tas571x_hw_params
,
.
digital_mute
=
tas571x_mute
,
};
static
const
char
*
const
tas5711_supply_names
[]
=
{
...
...
@@ -241,6 +266,26 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
1
,
1
),
};
static
const
struct
regmap_range
tas571x_readonly_regs_range
[]
=
{
regmap_reg_range
(
TAS571X_CLK_CTRL_REG
,
TAS571X_DEV_ID_REG
),
};
static
const
struct
regmap_range
tas571x_volatile_regs_range
[]
=
{
regmap_reg_range
(
TAS571X_CLK_CTRL_REG
,
TAS571X_ERR_STATUS_REG
),
regmap_reg_range
(
TAS571X_OSC_TRIM_REG
,
TAS571X_OSC_TRIM_REG
),
};
static
const
struct
regmap_access_table
tas571x_write_regs
=
{
.
no_ranges
=
tas571x_readonly_regs_range
,
.
n_no_ranges
=
ARRAY_SIZE
(
tas571x_readonly_regs_range
),
};
static
const
struct
regmap_access_table
tas571x_volatile_regs
=
{
.
yes_ranges
=
tas571x_volatile_regs_range
,
.
n_yes_ranges
=
ARRAY_SIZE
(
tas571x_volatile_regs_range
),
};
static
const
struct
reg_default
tas5711_reg_defaults
[]
=
{
{
0x04
,
0x05
},
{
0x05
,
0x40
},
...
...
@@ -260,6 +305,8 @@ static const struct regmap_config tas5711_regmap_config = {
.
reg_defaults
=
tas5711_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
tas5711_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
wr_table
=
&
tas571x_write_regs
,
.
volatile_table
=
&
tas571x_volatile_regs
,
};
static
const
struct
tas571x_chip
tas5711_chip
=
{
...
...
@@ -314,6 +361,8 @@ static const struct regmap_config tas5717_regmap_config = {
.
reg_defaults
=
tas5717_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
tas5717_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
wr_table
=
&
tas571x_write_regs
,
.
volatile_table
=
&
tas571x_volatile_regs
,
};
/* This entry is reused for tas5719 as the software interface is identical. */
...
...
@@ -326,6 +375,77 @@ static const struct tas571x_chip tas5717_chip = {
.
vol_reg_size
=
2
,
};
static
const
char
*
const
tas5721_supply_names
[]
=
{
"AVDD"
,
"DVDD"
,
"DRVDD"
,
"PVDD"
,
};
static
const
struct
snd_kcontrol_new
tas5721_controls
[]
=
{
SOC_SINGLE_TLV
(
"Master Volume"
,
TAS571X_MVOL_REG
,
0
,
0xff
,
1
,
tas5711_volume_tlv
),
SOC_DOUBLE_R_TLV
(
"Speaker Volume"
,
TAS571X_CH1_VOL_REG
,
TAS571X_CH2_VOL_REG
,
0
,
0xff
,
1
,
tas5711_volume_tlv
),
SOC_DOUBLE
(
"Speaker Switch"
,
TAS571X_SOFT_MUTE_REG
,
TAS571X_SOFT_MUTE_CH1_SHIFT
,
TAS571X_SOFT_MUTE_CH2_SHIFT
,
1
,
1
),
};
static
const
struct
reg_default
tas5721_reg_defaults
[]
=
{
{
TAS571X_CLK_CTRL_REG
,
0x6c
},
{
TAS571X_DEV_ID_REG
,
0x00
},
{
TAS571X_ERR_STATUS_REG
,
0x00
},
{
TAS571X_SYS_CTRL_1_REG
,
0xa0
},
{
TAS571X_SDI_REG
,
0x05
},
{
TAS571X_SYS_CTRL_2_REG
,
0x40
},
{
TAS571X_SOFT_MUTE_REG
,
0x00
},
{
TAS571X_MVOL_REG
,
0xff
},
{
TAS571X_CH1_VOL_REG
,
0x30
},
{
TAS571X_CH2_VOL_REG
,
0x30
},
{
TAS571X_CH3_VOL_REG
,
0x30
},
{
TAS571X_VOL_CFG_REG
,
0x91
},
{
TAS571X_MODULATION_LIMIT_REG
,
0x02
},
{
TAS571X_IC_DELAY_CH1_REG
,
0xac
},
{
TAS571X_IC_DELAY_CH2_REG
,
0x54
},
{
TAS571X_IC_DELAY_CH3_REG
,
0xac
},
{
TAS571X_IC_DELAY_CH4_REG
,
0x54
},
{
TAS571X_PWM_CH_SDN_GROUP_REG
,
0x30
},
{
TAS571X_START_STOP_PERIOD_REG
,
0x0f
},
{
TAS571X_OSC_TRIM_REG
,
0x82
},
{
TAS571X_BKND_ERR_REG
,
0x02
},
{
TAS571X_INPUT_MUX_REG
,
0x17772
},
{
TAS571X_CH4_SRC_SELECT_REG
,
0x4303
},
{
TAS571X_PWM_MUX_REG
,
0x1021345
},
};
static
const
struct
regmap_config
tas5721_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
32
,
.
max_register
=
0xff
,
.
reg_read
=
tas571x_reg_read
,
.
reg_write
=
tas571x_reg_write
,
.
reg_defaults
=
tas5721_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
tas5721_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
wr_table
=
&
tas571x_write_regs
,
.
volatile_table
=
&
tas571x_volatile_regs
,
};
static
const
struct
tas571x_chip
tas5721_chip
=
{
.
supply_names
=
tas5721_supply_names
,
.
num_supply_names
=
ARRAY_SIZE
(
tas5721_supply_names
),
.
controls
=
tas5711_controls
,
.
num_controls
=
ARRAY_SIZE
(
tas5711_controls
),
.
regmap_config
=
&
tas5721_regmap_config
,
.
vol_reg_size
=
1
,
};
static
const
struct
snd_soc_dapm_widget
tas571x_dapm_widgets
[]
=
{
SND_SOC_DAPM_DAC
(
"DACL"
,
NULL
,
SND_SOC_NOPM
,
0
,
0
),
SND_SOC_DAPM_DAC
(
"DACR"
,
NULL
,
SND_SOC_NOPM
,
0
,
0
),
...
...
@@ -386,11 +506,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
i2c_set_clientdata
(
client
,
priv
);
of_id
=
of_match_device
(
tas571x_of_match
,
dev
);
if
(
!
of_id
)
{
dev_err
(
dev
,
"Unknown device type
\n
"
);
return
-
EINVAL
;
}
priv
->
chip
=
of_id
->
data
;
if
(
of_id
)
priv
->
chip
=
of_id
->
data
;
else
priv
->
chip
=
(
void
*
)
id
->
driver_data
;
priv
->
mclk
=
devm_clk_get
(
dev
,
"mclk"
);
if
(
IS_ERR
(
priv
->
mclk
)
&&
PTR_ERR
(
priv
->
mclk
)
!=
-
ENOENT
)
{
...
...
@@ -445,10 +564,6 @@ static int tas571x_i2c_probe(struct i2c_client *client,
if
(
ret
)
return
ret
;
ret
=
regmap_update_bits
(
priv
->
regmap
,
TAS571X_SYS_CTRL_2_REG
,
TAS571X_SYS_CTRL_2_SDN_MASK
,
0
);
if
(
ret
)
return
ret
;
memcpy
(
&
priv
->
codec_driver
,
&
tas571x_codec
,
sizeof
(
priv
->
codec_driver
));
priv
->
codec_driver
.
controls
=
priv
->
chip
->
controls
;
...
...
@@ -486,14 +601,16 @@ static const struct of_device_id tas571x_of_match[] = {
{
.
compatible
=
"ti,tas5711"
,
.
data
=
&
tas5711_chip
,
},
{
.
compatible
=
"ti,tas5717"
,
.
data
=
&
tas5717_chip
,
},
{
.
compatible
=
"ti,tas5719"
,
.
data
=
&
tas5717_chip
,
},
{
.
compatible
=
"ti,tas5721"
,
.
data
=
&
tas5721_chip
,
},
{
}
};
MODULE_DEVICE_TABLE
(
of
,
tas571x_of_match
);
static
const
struct
i2c_device_id
tas571x_i2c_id
[]
=
{
{
"tas5711"
,
0
},
{
"tas5717"
,
0
},
{
"tas5719"
,
0
},
{
"tas5711"
,
(
kernel_ulong_t
)
&
tas5711_chip
},
{
"tas5717"
,
(
kernel_ulong_t
)
&
tas5717_chip
},
{
"tas5719"
,
(
kernel_ulong_t
)
&
tas5717_chip
},
{
"tas5721"
,
(
kernel_ulong_t
)
&
tas5721_chip
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
tas571x_i2c_id
);
...
...
sound/soc/codecs/tas571x.h
View file @
aaa36d3a
...
...
@@ -13,6 +13,10 @@
#define _TAS571X_H
/* device registers */
#define TAS571X_CLK_CTRL_REG 0x00
#define TAS571X_DEV_ID_REG 0x01
#define TAS571X_ERR_STATUS_REG 0x02
#define TAS571X_SYS_CTRL_1_REG 0x03
#define TAS571X_SDI_REG 0x04
#define TAS571X_SDI_FMT_MASK 0x0f
...
...
@@ -27,7 +31,25 @@
#define TAS571X_MVOL_REG 0x07
#define TAS571X_CH1_VOL_REG 0x08
#define TAS571X_CH2_VOL_REG 0x09
#define TAS571X_CH3_VOL_REG 0x0a
#define TAS571X_VOL_CFG_REG 0x0e
#define TAS571X_MODULATION_LIMIT_REG 0x10
#define TAS571X_IC_DELAY_CH1_REG 0x11
#define TAS571X_IC_DELAY_CH2_REG 0x12
#define TAS571X_IC_DELAY_CH3_REG 0x13
#define TAS571X_IC_DELAY_CH4_REG 0x14
#define TAS571X_PWM_CH_SDN_GROUP_REG 0x19
/* N/A on TAS5717, TAS5719 */
#define TAS571X_PWM_CH1_SDN_MASK (1<<0)
#define TAS571X_PWM_CH2_SDN_SHIFT (1<<1)
#define TAS571X_PWM_CH3_SDN_SHIFT (1<<2)
#define TAS571X_PWM_CH4_SDN_SHIFT (1<<3)
#define TAS571X_START_STOP_PERIOD_REG 0x1a
#define TAS571X_OSC_TRIM_REG 0x1b
#define TAS571X_BKND_ERR_REG 0x1c
#define TAS571X_INPUT_MUX_REG 0x20
#define TAS571X_CH4_SRC_SELECT_REG 0x21
#define TAS571X_PWM_MUX_REG 0x25
#endif
/* _TAS571X_H */
sound/soc/codecs/tas5720.c
0 → 100644
View file @
aaa36d3a
/*
* tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier
*
* Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Andreas Dannenberg <dannenberg@ti.com>
*
* 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/module.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "tas5720.h"
/* Define how often to check (and clear) the fault status register (in ms) */
#define TAS5720_FAULT_CHECK_INTERVAL 200
static
const
char
*
const
tas5720_supply_names
[]
=
{
"dvdd"
,
/* Digital power supply. Connect to 3.3-V supply. */
"pvdd"
,
/* Class-D amp and analog power supply (connected). */
};
#define TAS5720_NUM_SUPPLIES ARRAY_SIZE(tas5720_supply_names)
struct
tas5720_data
{
struct
snd_soc_codec
*
codec
;
struct
regmap
*
regmap
;
struct
i2c_client
*
tas5720_client
;
struct
regulator_bulk_data
supplies
[
TAS5720_NUM_SUPPLIES
];
struct
delayed_work
fault_check_work
;
unsigned
int
last_fault
;
};
static
int
tas5720_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
unsigned
int
rate
=
params_rate
(
params
);
bool
ssz_ds
;
int
ret
;
switch
(
rate
)
{
case
44100
:
case
48000
:
ssz_ds
=
false
;
break
;
case
88200
:
case
96000
:
ssz_ds
=
true
;
break
;
default:
dev_err
(
codec
->
dev
,
"unsupported sample rate: %u
\n
"
,
rate
);
return
-
EINVAL
;
}
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL1_REG
,
TAS5720_SSZ_DS
,
ssz_ds
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"error setting sample rate: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
tas5720_set_dai_fmt
(
struct
snd_soc_dai
*
dai
,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u8
serial_format
;
int
ret
;
if
((
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
!=
SND_SOC_DAIFMT_CBS_CFS
)
{
dev_vdbg
(
codec
->
dev
,
"DAI Format master is not found
\n
"
);
return
-
EINVAL
;
}
switch
(
fmt
&
(
SND_SOC_DAIFMT_FORMAT_MASK
|
SND_SOC_DAIFMT_INV_MASK
))
{
case
(
SND_SOC_DAIFMT_I2S
|
SND_SOC_DAIFMT_NB_NF
):
/* 1st data bit occur one BCLK cycle after the frame sync */
serial_format
=
TAS5720_SAIF_I2S
;
break
;
case
(
SND_SOC_DAIFMT_DSP_A
|
SND_SOC_DAIFMT_NB_NF
):
/*
* Note that although the TAS5720 does not have a dedicated DSP
* mode it doesn't care about the LRCLK duty cycle during TDM
* operation. Therefore we can use the device's I2S mode with
* its delaying of the 1st data bit to receive DSP_A formatted
* data. See device datasheet for additional details.
*/
serial_format
=
TAS5720_SAIF_I2S
;
break
;
case
(
SND_SOC_DAIFMT_DSP_B
|
SND_SOC_DAIFMT_NB_NF
):
/*
* Similar to DSP_A, we can use the fact that the TAS5720 does
* not care about the LRCLK duty cycle during TDM to receive
* DSP_B formatted data in LEFTJ mode (no delaying of the 1st
* data bit).
*/
serial_format
=
TAS5720_SAIF_LEFTJ
;
break
;
case
(
SND_SOC_DAIFMT_LEFT_J
|
SND_SOC_DAIFMT_NB_NF
):
/* No delay after the frame sync */
serial_format
=
TAS5720_SAIF_LEFTJ
;
break
;
default:
dev_vdbg
(
codec
->
dev
,
"DAI Format is not found
\n
"
);
return
-
EINVAL
;
}
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL1_REG
,
TAS5720_SAIF_FORMAT_MASK
,
serial_format
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"error setting SAIF format: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
tas5720_set_dai_tdm_slot
(
struct
snd_soc_dai
*
dai
,
unsigned
int
tx_mask
,
unsigned
int
rx_mask
,
int
slots
,
int
slot_width
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
unsigned
int
first_slot
;
int
ret
;
if
(
!
tx_mask
)
{
dev_err
(
codec
->
dev
,
"tx masks must not be 0
\n
"
);
return
-
EINVAL
;
}
/*
* Determine the first slot that is being requested. We will only
* use the first slot that is found since the TAS5720 is a mono
* amplifier.
*/
first_slot
=
__ffs
(
tx_mask
);
if
(
first_slot
>
7
)
{
dev_err
(
codec
->
dev
,
"slot selection out of bounds (%u)
\n
"
,
first_slot
);
return
-
EINVAL
;
}
/* Enable manual TDM slot selection (instead of I2C ID based) */
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL1_REG
,
TAS5720_TDM_CFG_SRC
,
TAS5720_TDM_CFG_SRC
);
if
(
ret
<
0
)
goto
error_snd_soc_update_bits
;
/* Configure the TDM slot to process audio from */
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL2_REG
,
TAS5720_TDM_SLOT_SEL_MASK
,
first_slot
);
if
(
ret
<
0
)
goto
error_snd_soc_update_bits
;
return
0
;
error_snd_soc_update_bits:
dev_err
(
codec
->
dev
,
"error configuring TDM mode: %d
\n
"
,
ret
);
return
ret
;
}
static
int
tas5720_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
int
ret
;
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL2_REG
,
TAS5720_MUTE
,
mute
?
TAS5720_MUTE
:
0
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"error (un-)muting device: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
void
tas5720_fault_check_work
(
struct
work_struct
*
work
)
{
struct
tas5720_data
*
tas5720
=
container_of
(
work
,
struct
tas5720_data
,
fault_check_work
.
work
);
struct
device
*
dev
=
tas5720
->
codec
->
dev
;
unsigned
int
curr_fault
;
int
ret
;
ret
=
regmap_read
(
tas5720
->
regmap
,
TAS5720_FAULT_REG
,
&
curr_fault
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"failed to read FAULT register: %d
\n
"
,
ret
);
goto
out
;
}
/* Check/handle all errors except SAIF clock errors */
curr_fault
&=
TAS5720_OCE
|
TAS5720_DCE
|
TAS5720_OTE
;
/*
* Only flag errors once for a given occurrence. This is needed as
* the TAS5720 will take time clearing the fault condition internally
* during which we don't want to bombard the system with the same
* error message over and over.
*/
if
((
curr_fault
&
TAS5720_OCE
)
&&
!
(
tas5720
->
last_fault
&
TAS5720_OCE
))
dev_crit
(
dev
,
"experienced an over current hardware fault
\n
"
);
if
((
curr_fault
&
TAS5720_DCE
)
&&
!
(
tas5720
->
last_fault
&
TAS5720_DCE
))
dev_crit
(
dev
,
"experienced a DC detection fault
\n
"
);
if
((
curr_fault
&
TAS5720_OTE
)
&&
!
(
tas5720
->
last_fault
&
TAS5720_OTE
))
dev_crit
(
dev
,
"experienced an over temperature fault
\n
"
);
/* Store current fault value so we can detect any changes next time */
tas5720
->
last_fault
=
curr_fault
;
if
(
!
curr_fault
)
goto
out
;
/*
* Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching
* faults as long as a fault condition persists. Always going through
* the full sequence no matter the first return value to minimizes
* chances for the device to end up in shutdown mode.
*/
ret
=
regmap_write_bits
(
tas5720
->
regmap
,
TAS5720_POWER_CTRL_REG
,
TAS5720_SDZ
,
0
);
if
(
ret
<
0
)
dev_err
(
dev
,
"failed to write POWER_CTRL register: %d
\n
"
,
ret
);
ret
=
regmap_write_bits
(
tas5720
->
regmap
,
TAS5720_POWER_CTRL_REG
,
TAS5720_SDZ
,
TAS5720_SDZ
);
if
(
ret
<
0
)
dev_err
(
dev
,
"failed to write POWER_CTRL register: %d
\n
"
,
ret
);
out:
/* Schedule the next fault check at the specified interval */
schedule_delayed_work
(
&
tas5720
->
fault_check_work
,
msecs_to_jiffies
(
TAS5720_FAULT_CHECK_INTERVAL
));
}
static
int
tas5720_codec_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
tas5720_data
*
tas5720
=
snd_soc_codec_get_drvdata
(
codec
);
unsigned
int
device_id
;
int
ret
;
tas5720
->
codec
=
codec
;
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
tas5720
->
supplies
),
tas5720
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"failed to enable supplies: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
regmap_read
(
tas5720
->
regmap
,
TAS5720_DEVICE_ID_REG
,
&
device_id
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to read device ID register: %d
\n
"
,
ret
);
goto
probe_fail
;
}
if
(
device_id
!=
TAS5720_DEVICE_ID
)
{
dev_err
(
codec
->
dev
,
"wrong device ID. expected: %u read: %u
\n
"
,
TAS5720_DEVICE_ID
,
device_id
);
ret
=
-
ENODEV
;
goto
probe_fail
;
}
/* Set device to mute */
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_DIGITAL_CTRL2_REG
,
TAS5720_MUTE
,
TAS5720_MUTE
);
if
(
ret
<
0
)
goto
error_snd_soc_update_bits
;
/*
* Enter shutdown mode - our default when not playing audio - to
* minimize current consumption. On the TAS5720 there is no real down
* side doing so as all device registers are preserved and the wakeup
* of the codec is rather quick which we do using a dapm widget.
*/
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_POWER_CTRL_REG
,
TAS5720_SDZ
,
0
);
if
(
ret
<
0
)
goto
error_snd_soc_update_bits
;
INIT_DELAYED_WORK
(
&
tas5720
->
fault_check_work
,
tas5720_fault_check_work
);
return
0
;
error_snd_soc_update_bits:
dev_err
(
codec
->
dev
,
"error configuring device registers: %d
\n
"
,
ret
);
probe_fail:
regulator_bulk_disable
(
ARRAY_SIZE
(
tas5720
->
supplies
),
tas5720
->
supplies
);
return
ret
;
}
static
int
tas5720_codec_remove
(
struct
snd_soc_codec
*
codec
)
{
struct
tas5720_data
*
tas5720
=
snd_soc_codec_get_drvdata
(
codec
);
int
ret
;
cancel_delayed_work_sync
(
&
tas5720
->
fault_check_work
);
ret
=
regulator_bulk_disable
(
ARRAY_SIZE
(
tas5720
->
supplies
),
tas5720
->
supplies
);
if
(
ret
<
0
)
dev_err
(
codec
->
dev
,
"failed to disable supplies: %d
\n
"
,
ret
);
return
ret
;
};
static
int
tas5720_dac_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_to_codec
(
w
->
dapm
);
struct
tas5720_data
*
tas5720
=
snd_soc_codec_get_drvdata
(
codec
);
int
ret
;
if
(
event
&
SND_SOC_DAPM_POST_PMU
)
{
/* Take TAS5720 out of shutdown mode */
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_POWER_CTRL_REG
,
TAS5720_SDZ
,
TAS5720_SDZ
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"error waking codec: %d
\n
"
,
ret
);
return
ret
;
}
/*
* Observe codec shutdown-to-active time. The datasheet only
* lists a nominal value however just use-it as-is without
* additional padding to minimize the delay introduced in
* starting to play audio (actually there is other setup done
* by the ASoC framework that will provide additional delays,
* so we should always be safe).
*/
msleep
(
25
);
/* Turn on TAS5720 periodic fault checking/handling */
tas5720
->
last_fault
=
0
;
schedule_delayed_work
(
&
tas5720
->
fault_check_work
,
msecs_to_jiffies
(
TAS5720_FAULT_CHECK_INTERVAL
));
}
else
if
(
event
&
SND_SOC_DAPM_PRE_PMD
)
{
/* Disable TAS5720 periodic fault checking/handling */
cancel_delayed_work_sync
(
&
tas5720
->
fault_check_work
);
/* Place TAS5720 in shutdown mode to minimize current draw */
ret
=
snd_soc_update_bits
(
codec
,
TAS5720_POWER_CTRL_REG
,
TAS5720_SDZ
,
0
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"error shutting down codec: %d
\n
"
,
ret
);
return
ret
;
}
}
return
0
;
}
#ifdef CONFIG_PM
static
int
tas5720_suspend
(
struct
snd_soc_codec
*
codec
)
{
struct
tas5720_data
*
tas5720
=
snd_soc_codec_get_drvdata
(
codec
);
int
ret
;
regcache_cache_only
(
tas5720
->
regmap
,
true
);
regcache_mark_dirty
(
tas5720
->
regmap
);
ret
=
regulator_bulk_disable
(
ARRAY_SIZE
(
tas5720
->
supplies
),
tas5720
->
supplies
);
if
(
ret
<
0
)
dev_err
(
codec
->
dev
,
"failed to disable supplies: %d
\n
"
,
ret
);
return
ret
;
}
static
int
tas5720_resume
(
struct
snd_soc_codec
*
codec
)
{
struct
tas5720_data
*
tas5720
=
snd_soc_codec_get_drvdata
(
codec
);
int
ret
;
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
tas5720
->
supplies
),
tas5720
->
supplies
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to enable supplies: %d
\n
"
,
ret
);
return
ret
;
}
regcache_cache_only
(
tas5720
->
regmap
,
false
);
ret
=
regcache_sync
(
tas5720
->
regmap
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to sync regcache: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
#else
#define tas5720_suspend NULL
#define tas5720_resume NULL
#endif
static
bool
tas5720_is_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
TAS5720_DEVICE_ID_REG
:
case
TAS5720_FAULT_REG
:
return
true
;
default:
return
false
;
}
}
static
const
struct
regmap_config
tas5720_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
TAS5720_MAX_REG
,
.
cache_type
=
REGCACHE_RBTREE
,
.
volatile_reg
=
tas5720_is_volatile_reg
,
};
/*
* DAC analog gain. There are four discrete values to select from, ranging
* from 19.2 dB to 26.3dB.
*/
static
const
DECLARE_TLV_DB_RANGE
(
dac_analog_tlv
,
0x0
,
0x0
,
TLV_DB_SCALE_ITEM
(
1920
,
0
,
0
),
0x1
,
0x1
,
TLV_DB_SCALE_ITEM
(
2070
,
0
,
0
),
0x2
,
0x2
,
TLV_DB_SCALE_ITEM
(
2350
,
0
,
0
),
0x3
,
0x3
,
TLV_DB_SCALE_ITEM
(
2630
,
0
,
0
),
);
/*
* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that
* setting the gain below -100 dB (register value <0x7) is effectively a MUTE
* as per device datasheet.
*/
static
DECLARE_TLV_DB_SCALE
(
dac_tlv
,
-
10350
,
50
,
0
);
static
const
struct
snd_kcontrol_new
tas5720_snd_controls
[]
=
{
SOC_SINGLE_TLV
(
"Speaker Driver Playback Volume"
,
TAS5720_VOLUME_CTRL_REG
,
0
,
0xff
,
0
,
dac_tlv
),
SOC_SINGLE_TLV
(
"Speaker Driver Analog Gain"
,
TAS5720_ANALOG_CTRL_REG
,
TAS5720_ANALOG_GAIN_SHIFT
,
3
,
0
,
dac_analog_tlv
),
};
static
const
struct
snd_soc_dapm_widget
tas5720_dapm_widgets
[]
=
{
SND_SOC_DAPM_AIF_IN
(
"DAC IN"
,
"Playback"
,
0
,
SND_SOC_NOPM
,
0
,
0
),
SND_SOC_DAPM_DAC_E
(
"DAC"
,
NULL
,
SND_SOC_NOPM
,
0
,
0
,
tas5720_dac_event
,
SND_SOC_DAPM_POST_PMU
|
SND_SOC_DAPM_PRE_PMD
),
SND_SOC_DAPM_OUTPUT
(
"OUT"
)
};
static
const
struct
snd_soc_dapm_route
tas5720_audio_map
[]
=
{
{
"DAC"
,
NULL
,
"DAC IN"
},
{
"OUT"
,
NULL
,
"DAC"
},
};
static
struct
snd_soc_codec_driver
soc_codec_dev_tas5720
=
{
.
probe
=
tas5720_codec_probe
,
.
remove
=
tas5720_codec_remove
,
.
suspend
=
tas5720_suspend
,
.
resume
=
tas5720_resume
,
.
controls
=
tas5720_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
tas5720_snd_controls
),
.
dapm_widgets
=
tas5720_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
tas5720_dapm_widgets
),
.
dapm_routes
=
tas5720_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
tas5720_audio_map
),
};
/* PCM rates supported by the TAS5720 driver */
#define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
/* Formats supported by TAS5720 driver */
#define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
static
struct
snd_soc_dai_ops
tas5720_speaker_dai_ops
=
{
.
hw_params
=
tas5720_hw_params
,
.
set_fmt
=
tas5720_set_dai_fmt
,
.
set_tdm_slot
=
tas5720_set_dai_tdm_slot
,
.
digital_mute
=
tas5720_mute
,
};
/*
* TAS5720 DAI structure
*
* Note that were are advertising .playback.channels_max = 2 despite this being
* a mono amplifier. The reason for that is that some serial ports such as TI's
* McASP module have a minimum number of channels (2) that they can output.
* Advertising more channels than we have will allow us to interface with such
* a serial port without really any negative side effects as the TAS5720 will
* simply ignore any extra channel(s) asides from the one channel that is
* configured to be played back.
*/
static
struct
snd_soc_dai_driver
tas5720_dai
[]
=
{
{
.
name
=
"tas5720-amplifier"
,
.
playback
=
{
.
stream_name
=
"Playback"
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
TAS5720_RATES
,
.
formats
=
TAS5720_FORMATS
,
},
.
ops
=
&
tas5720_speaker_dai_ops
,
},
};
static
int
tas5720_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
struct
device
*
dev
=
&
client
->
dev
;
struct
tas5720_data
*
data
;
int
ret
;
int
i
;
data
=
devm_kzalloc
(
dev
,
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
!
data
)
return
-
ENOMEM
;
data
->
tas5720_client
=
client
;
data
->
regmap
=
devm_regmap_init_i2c
(
client
,
&
tas5720_regmap_config
);
if
(
IS_ERR
(
data
->
regmap
))
{
ret
=
PTR_ERR
(
data
->
regmap
);
dev_err
(
dev
,
"failed to allocate register map: %d
\n
"
,
ret
);
return
ret
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
data
->
supplies
);
i
++
)
data
->
supplies
[
i
].
supply
=
tas5720_supply_names
[
i
];
ret
=
devm_regulator_bulk_get
(
dev
,
ARRAY_SIZE
(
data
->
supplies
),
data
->
supplies
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"failed to request supplies: %d
\n
"
,
ret
);
return
ret
;
}
dev_set_drvdata
(
dev
,
data
);
ret
=
snd_soc_register_codec
(
&
client
->
dev
,
&
soc_codec_dev_tas5720
,
tas5720_dai
,
ARRAY_SIZE
(
tas5720_dai
));
if
(
ret
<
0
)
{
dev_err
(
dev
,
"failed to register codec: %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
tas5720_remove
(
struct
i2c_client
*
client
)
{
struct
device
*
dev
=
&
client
->
dev
;
snd_soc_unregister_codec
(
dev
);
return
0
;
}
static
const
struct
i2c_device_id
tas5720_id
[]
=
{
{
"tas5720"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
tas5720_id
);
#if IS_ENABLED(CONFIG_OF)
static
const
struct
of_device_id
tas5720_of_match
[]
=
{
{
.
compatible
=
"ti,tas5720"
,
},
{
},
};
MODULE_DEVICE_TABLE
(
of
,
tas5720_of_match
);
#endif
static
struct
i2c_driver
tas5720_i2c_driver
=
{
.
driver
=
{
.
name
=
"tas5720"
,
.
of_match_table
=
of_match_ptr
(
tas5720_of_match
),
},
.
probe
=
tas5720_probe
,
.
remove
=
tas5720_remove
,
.
id_table
=
tas5720_id
,
};
module_i2c_driver
(
tas5720_i2c_driver
);
MODULE_AUTHOR
(
"Andreas Dannenberg <dannenberg@ti.com>"
);
MODULE_DESCRIPTION
(
"TAS5720 Audio amplifier driver"
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/codecs/tas5720.h
0 → 100644
View file @
aaa36d3a
/*
* tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier
*
* Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Andreas Dannenberg <dannenberg@ti.com>
*
* 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 __TAS5720_H__
#define __TAS5720_H__
/* Register Address Map */
#define TAS5720_DEVICE_ID_REG 0x00
#define TAS5720_POWER_CTRL_REG 0x01
#define TAS5720_DIGITAL_CTRL1_REG 0x02
#define TAS5720_DIGITAL_CTRL2_REG 0x03
#define TAS5720_VOLUME_CTRL_REG 0x04
#define TAS5720_ANALOG_CTRL_REG 0x06
#define TAS5720_FAULT_REG 0x08
#define TAS5720_DIGITAL_CLIP2_REG 0x10
#define TAS5720_DIGITAL_CLIP1_REG 0x11
#define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG
/* TAS5720_DEVICE_ID_REG */
#define TAS5720_DEVICE_ID 0x01
/* TAS5720_POWER_CTRL_REG */
#define TAS5720_DIG_CLIP_MASK GENMASK(7, 2)
#define TAS5720_SLEEP BIT(1)
#define TAS5720_SDZ BIT(0)
/* TAS5720_DIGITAL_CTRL1_REG */
#define TAS5720_HPF_BYPASS BIT(7)
#define TAS5720_TDM_CFG_SRC BIT(6)
#define TAS5720_SSZ_DS BIT(3)
#define TAS5720_SAIF_RIGHTJ_24BIT (0x0)
#define TAS5720_SAIF_RIGHTJ_20BIT (0x1)
#define TAS5720_SAIF_RIGHTJ_18BIT (0x2)
#define TAS5720_SAIF_RIGHTJ_16BIT (0x3)
#define TAS5720_SAIF_I2S (0x4)
#define TAS5720_SAIF_LEFTJ (0x5)
#define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0)
/* TAS5720_DIGITAL_CTRL2_REG */
#define TAS5720_MUTE BIT(4)
#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0)
/* TAS5720_ANALOG_CTRL_REG */
#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4)
#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4)
#define TAS5720_PWM_RATE_10_5_FSYNC (0x2 << 4)
#define TAS5720_PWM_RATE_12_6_FSYNC (0x3 << 4)
#define TAS5720_PWM_RATE_14_7_FSYNC (0x4 << 4)
#define TAS5720_PWM_RATE_16_8_FSYNC (0x5 << 4)
#define TAS5720_PWM_RATE_20_10_FSYNC (0x6 << 4)
#define TAS5720_PWM_RATE_24_12_FSYNC (0x7 << 4)
#define TAS5720_PWM_RATE_MASK GENMASK(6, 4)
#define TAS5720_ANALOG_GAIN_19_2DBV (0x0 << 2)
#define TAS5720_ANALOG_GAIN_20_7DBV (0x1 << 2)
#define TAS5720_ANALOG_GAIN_23_5DBV (0x2 << 2)
#define TAS5720_ANALOG_GAIN_26_3DBV (0x3 << 2)
#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2)
#define TAS5720_ANALOG_GAIN_SHIFT (0x2)
/* TAS5720_FAULT_REG */
#define TAS5720_OC_THRESH_100PCT (0x0 << 4)
#define TAS5720_OC_THRESH_75PCT (0x1 << 4)
#define TAS5720_OC_THRESH_50PCT (0x2 << 4)
#define TAS5720_OC_THRESH_25PCT (0x3 << 4)
#define TAS5720_OC_THRESH_MASK GENMASK(5, 4)
#define TAS5720_CLKE BIT(3)
#define TAS5720_OCE BIT(2)
#define TAS5720_DCE BIT(1)
#define TAS5720_OTE BIT(0)
#define TAS5720_FAULT_MASK GENMASK(3, 0)
/* TAS5720_DIGITAL_CLIP1_REG */
#define TAS5720_CLIP1_MASK GENMASK(7, 2)
#define TAS5720_CLIP1_SHIFT (0x2)
#endif
/* __TAS5720_H__ */
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