Commit ab96d9d6 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/fsl-sai', 'asoc/topic/fsl-ssl',...

Merge remote-tracking branches 'asoc/topic/fsl-sai', 'asoc/topic/fsl-ssl', 'asoc/topic/hdac' and 'asoc/topic/max9867' into asoc-next
...@@ -5,15 +5,18 @@ Index Device Endianness properties ...@@ -5,15 +5,18 @@ Index Device Endianness properties
--------------------------------------------------- ---------------------------------------------------
1 BE 'big-endian' 1 BE 'big-endian'
2 LE 'little-endian' 2 LE 'little-endian'
3 Native 'native-endian'
For one device driver, which will run in different scenarios above For one device driver, which will run in different scenarios above
on different SoCs using the devicetree, we need one way to simplify on different SoCs using the devicetree, we need one way to simplify
this. this.
Required properties: Optional properties:
- {big,little}-endian: these are boolean properties, if absent - {big,little,native}-endian: these are boolean properties, if absent
meaning that the CPU and the Device are in the same endianness mode, then the implementation will choose a default based on the device
these properties are for register values and all the buffers only. being controlled. These properties are for register values and all
the buffers only. Native endian means that the CPU and device have
the same endianness.
Examples: Examples:
Scenario 1 : CPU in LE mode & device in LE mode. Scenario 1 : CPU in LE mode & device in LE mode.
......
max9867 codec
This device supports I2C mode only.
Required properties:
- compatible : "maxim,max9867"
- reg : The chip select number on the I2C bus
Example:
&i2c {
max9867: max9867@0x18 {
compatible = "maxim,max9867";
reg = <0x18>;
};
};
max98926 audio CODEC
This device supports I2C.
Required properties:
- compatible : "maxim,max98926"
- vmon-slot-no : slot number used to send voltage information
or in inteleave mode this will be used as
interleave slot.
- imon-slot-no : slot number used to send current information
- interleave-mode : When using two MAX98926 in a system it is
possible to create ADC data that that will
overflow the frame size. Digital Audio Interleave
mode provides a means to output VMON and IMON data
from two devices on a single DOUT line when running
smaller frames sizes such as 32 BCLKS per LRCLK or
48 BCLKS per LRCLK.
- reg : the I2C address of the device for I2C
Example:
codec: max98926@1a {
compatible = "maxim,max98926";
vmon-slot-no = <0>;
imon-slot-no = <2>;
reg = <0x1a>;
};
...@@ -74,7 +74,7 @@ uart0: serial@10000100 { ...@@ -74,7 +74,7 @@ uart0: serial@10000100 {
timer: timer@10000040 { timer: timer@10000040 {
compatible = "syscon"; compatible = "syscon";
reg = <0x10000040 0x2c>; reg = <0x10000040 0x2c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -54,7 +54,7 @@ ubus { ...@@ -54,7 +54,7 @@ ubus {
periph_cntl: syscon@10000000 { periph_cntl: syscon@10000000 {
compatible = "syscon"; compatible = "syscon";
reg = <0x10000000 0x14>; reg = <0x10000000 0x14>;
little-endian; native-endian;
}; };
reboot: syscon-reboot@10000008 { reboot: syscon-reboot@10000008 {
......
...@@ -98,7 +98,7 @@ upg_irq0_intc: upg_irq0_intc@406780 { ...@@ -98,7 +98,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7125-sun-top-ctrl", "syscon";
reg = <0x404000 0x60c>; reg = <0x404000 0x60c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { ...@@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7346-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { ...@@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7358-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { ...@@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7360-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 { ...@@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7362-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -99,7 +99,7 @@ upg_irq0_intc: upg_irq0_intc@406780 { ...@@ -99,7 +99,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7420-sun-top-ctrl", "syscon";
reg = <0x404000 0x60c>; reg = <0x404000 0x60c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -100,7 +100,7 @@ upg_irq0_intc: upg_irq0_intc@406780 { ...@@ -100,7 +100,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -114,7 +114,7 @@ upg_irq0_intc: upg_irq0_intc@406780 { ...@@ -114,7 +114,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
sun_top_ctrl: syscon@404000 { sun_top_ctrl: syscon@404000 {
compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
reg = <0x404000 0x51c>; reg = <0x404000 0x51c>;
little-endian; native-endian;
}; };
reboot { reboot {
......
...@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map) ...@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map)
int i, j; int i, j;
int ret; int ret;
int count; int count;
unsigned int val; unsigned int reg, val;
void *tmp_buf; void *tmp_buf;
if (!map->num_reg_defaults_raw) if (!map->num_reg_defaults_raw)
...@@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map) ...@@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map)
ret = regmap_raw_read(map, 0, tmp_buf, ret = regmap_raw_read(map, 0, tmp_buf,
map->num_reg_defaults_raw); map->num_reg_defaults_raw);
map->cache_bypass = cache_bypass; map->cache_bypass = cache_bypass;
if (ret < 0) if (ret == 0) {
goto err_cache_free; map->reg_defaults_raw = tmp_buf;
map->cache_free = 1;
map->reg_defaults_raw = tmp_buf; } else {
map->cache_free = 1; kfree(tmp_buf);
}
} }
/* fill the reg_defaults */ /* fill the reg_defaults */
for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
if (regmap_volatile(map, i * map->reg_stride)) reg = i * map->reg_stride;
if (!regmap_readable(map, reg))
continue; continue;
val = regcache_get_val(map, map->reg_defaults_raw, i);
map->reg_defaults[j].reg = i * map->reg_stride; if (regmap_volatile(map, reg))
continue;
if (map->reg_defaults_raw) {
val = regcache_get_val(map, map->reg_defaults_raw, i);
} else {
bool cache_bypass = map->cache_bypass;
map->cache_bypass = true;
ret = regmap_read(map, reg, &val);
map->cache_bypass = cache_bypass;
if (ret != 0) {
dev_err(map->dev, "Failed to read %d: %d\n",
reg, ret);
goto err_free;
}
}
map->reg_defaults[j].reg = reg;
map->reg_defaults[j].def = val; map->reg_defaults[j].def = val;
j++; j++;
} }
return 0; return 0;
err_cache_free:
kfree(tmp_buf);
err_free: err_free:
kfree(map->reg_defaults); kfree(map->reg_defaults);
......
...@@ -25,26 +25,14 @@ ...@@ -25,26 +25,14 @@
struct regmap_mmio_context { struct regmap_mmio_context {
void __iomem *regs; void __iomem *regs;
unsigned reg_bytes;
unsigned val_bytes; unsigned val_bytes;
unsigned pad_bytes;
struct clk *clk; struct clk *clk;
};
static inline void regmap_mmio_regsize_check(size_t reg_size) void (*reg_write)(struct regmap_mmio_context *ctx,
{ unsigned int reg, unsigned int val);
switch (reg_size) { unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
case 1: unsigned int reg);
case 2: };
case 4:
#ifdef CONFIG_64BIT
case 8:
#endif
break;
default:
BUG();
}
}
static int regmap_mmio_regbits_check(size_t reg_bits) static int regmap_mmio_regbits_check(size_t reg_bits)
{ {
...@@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits) ...@@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
return min_stride; return min_stride;
} }
static inline void regmap_mmio_count_check(size_t count, u32 offset) static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
unsigned int reg,
unsigned int val)
{
writeb(val, ctx->regs + reg);
}
static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
unsigned int reg,
unsigned int val)
{ {
BUG_ON(count <= offset); writew(val, ctx->regs + reg);
} }
static inline unsigned int static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
regmap_mmio_get_offset(const void *reg, size_t reg_size) unsigned int reg,
unsigned int val)
{ {
switch (reg_size) { iowrite16be(val, ctx->regs + reg);
case 1: }
return *(u8 *)reg;
case 2: static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
return *(u16 *)reg; unsigned int reg,
case 4: unsigned int val)
return *(u32 *)reg; {
writel(val, ctx->regs + reg);
}
static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
unsigned int reg,
unsigned int val)
{
iowrite32be(val, ctx->regs + reg);
}
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
case 8: static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
return *(u64 *)reg; unsigned int reg,
#endif unsigned int val)
default: {
BUG(); writeq(val, ctx->regs + reg);
}
} }
#endif
static int regmap_mmio_gather_write(void *context, static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
const void *reg, size_t reg_size,
const void *val, size_t val_size)
{ {
struct regmap_mmio_context *ctx = context; struct regmap_mmio_context *ctx = context;
unsigned int offset;
int ret; int ret;
regmap_mmio_regsize_check(reg_size);
if (!IS_ERR(ctx->clk)) { if (!IS_ERR(ctx->clk)) {
ret = clk_enable(ctx->clk); ret = clk_enable(ctx->clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
offset = regmap_mmio_get_offset(reg, reg_size); ctx->reg_write(ctx, reg, val);
while (val_size) {
switch (ctx->val_bytes) {
case 1:
writeb(*(u8 *)val, ctx->regs + offset);
break;
case 2:
writew(*(u16 *)val, ctx->regs + offset);
break;
case 4:
writel(*(u32 *)val, ctx->regs + offset);
break;
#ifdef CONFIG_64BIT
case 8:
writeq(*(u64 *)val, ctx->regs + offset);
break;
#endif
default:
/* Should be caught by regmap_mmio_check_config */
BUG();
}
val_size -= ctx->val_bytes;
val += ctx->val_bytes;
offset += ctx->val_bytes;
}
if (!IS_ERR(ctx->clk)) if (!IS_ERR(ctx->clk))
clk_disable(ctx->clk); clk_disable(ctx->clk);
...@@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context, ...@@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context,
return 0; return 0;
} }
static int regmap_mmio_write(void *context, const void *data, size_t count) static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
unsigned int reg)
{ {
struct regmap_mmio_context *ctx = context; return readb(ctx->regs + reg);
unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; }
static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
unsigned int reg)
{
return readw(ctx->regs + reg);
}
static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
unsigned int reg)
{
return ioread16be(ctx->regs + reg);
}
static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
unsigned int reg)
{
return readl(ctx->regs + reg);
}
regmap_mmio_count_check(count, offset); static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
unsigned int reg)
{
return ioread32be(ctx->regs + reg);
}
return regmap_mmio_gather_write(context, data, ctx->reg_bytes, #ifdef CONFIG_64BIT
data + offset, count - offset); static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
unsigned int reg)
{
return readq(ctx->regs + reg);
} }
#endif
static int regmap_mmio_read(void *context, static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
const void *reg, size_t reg_size,
void *val, size_t val_size)
{ {
struct regmap_mmio_context *ctx = context; struct regmap_mmio_context *ctx = context;
unsigned int offset;
int ret; int ret;
regmap_mmio_regsize_check(reg_size);
if (!IS_ERR(ctx->clk)) { if (!IS_ERR(ctx->clk)) {
ret = clk_enable(ctx->clk); ret = clk_enable(ctx->clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
offset = regmap_mmio_get_offset(reg, reg_size); *val = ctx->reg_read(ctx, reg);
while (val_size) {
switch (ctx->val_bytes) {
case 1:
*(u8 *)val = readb(ctx->regs + offset);
break;
case 2:
*(u16 *)val = readw(ctx->regs + offset);
break;
case 4:
*(u32 *)val = readl(ctx->regs + offset);
break;
#ifdef CONFIG_64BIT
case 8:
*(u64 *)val = readq(ctx->regs + offset);
break;
#endif
default:
/* Should be caught by regmap_mmio_check_config */
BUG();
}
val_size -= ctx->val_bytes;
val += ctx->val_bytes;
offset += ctx->val_bytes;
}
if (!IS_ERR(ctx->clk)) if (!IS_ERR(ctx->clk))
clk_disable(ctx->clk); clk_disable(ctx->clk);
...@@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context) ...@@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context)
kfree(context); kfree(context);
} }
static struct regmap_bus regmap_mmio = { static const struct regmap_bus regmap_mmio = {
.fast_io = true, .fast_io = true,
.write = regmap_mmio_write, .reg_write = regmap_mmio_write,
.gather_write = regmap_mmio_gather_write, .reg_read = regmap_mmio_read,
.read = regmap_mmio_read,
.free_context = regmap_mmio_free_context, .free_context = regmap_mmio_free_context,
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
}; };
static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
...@@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, ...@@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
if (config->reg_stride < min_stride) if (config->reg_stride < min_stride)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
switch (config->reg_format_endian) {
case REGMAP_ENDIAN_DEFAULT:
case REGMAP_ENDIAN_NATIVE:
break;
default:
return ERR_PTR(-EINVAL);
}
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) if (!ctx)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ctx->regs = regs; ctx->regs = regs;
ctx->val_bytes = config->val_bits / 8; ctx->val_bytes = config->val_bits / 8;
ctx->reg_bytes = config->reg_bits / 8;
ctx->pad_bytes = config->pad_bits / 8;
ctx->clk = ERR_PTR(-ENODEV); ctx->clk = ERR_PTR(-ENODEV);
switch (config->reg_format_endian) {
case REGMAP_ENDIAN_DEFAULT:
case REGMAP_ENDIAN_LITTLE:
#ifdef __LITTLE_ENDIAN
case REGMAP_ENDIAN_NATIVE:
#endif
switch (config->val_bits) {
case 8:
ctx->reg_read = regmap_mmio_read8;
ctx->reg_write = regmap_mmio_write8;
break;
case 16:
ctx->reg_read = regmap_mmio_read16le;
ctx->reg_write = regmap_mmio_write16le;
break;
case 32:
ctx->reg_read = regmap_mmio_read32le;
ctx->reg_write = regmap_mmio_write32le;
break;
#ifdef CONFIG_64BIT
case 64:
ctx->reg_read = regmap_mmio_read64le;
ctx->reg_write = regmap_mmio_write64le;
break;
#endif
default:
ret = -EINVAL;
goto err_free;
}
break;
case REGMAP_ENDIAN_BIG:
#ifdef __BIG_ENDIAN
case REGMAP_ENDIAN_NATIVE:
#endif
switch (config->val_bits) {
case 8:
ctx->reg_read = regmap_mmio_read8;
ctx->reg_write = regmap_mmio_write8;
break;
case 16:
ctx->reg_read = regmap_mmio_read16be;
ctx->reg_write = regmap_mmio_write16be;
break;
case 32:
ctx->reg_read = regmap_mmio_read32be;
ctx->reg_write = regmap_mmio_write32be;
break;
default:
ret = -EINVAL;
goto err_free;
}
break;
default:
ret = -EINVAL;
goto err_free;
}
if (clk_id == NULL) if (clk_id == NULL)
return ctx; return ctx;
......
...@@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev, ...@@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
endian = REGMAP_ENDIAN_BIG; endian = REGMAP_ENDIAN_BIG;
else if (of_property_read_bool(np, "little-endian")) else if (of_property_read_bool(np, "little-endian"))
endian = REGMAP_ENDIAN_LITTLE; endian = REGMAP_ENDIAN_LITTLE;
else if (of_property_read_bool(np, "native-endian"))
endian = REGMAP_ENDIAN_NATIVE;
/* If the endianness was specified in DT, use that */ /* If the endianness was specified in DT, use that */
if (endian != REGMAP_ENDIAN_DEFAULT) if (endian != REGMAP_ENDIAN_DEFAULT)
...@@ -2253,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -2253,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
WARN_ON(!map->bus); WARN_ON(!map->bus);
if (!map->bus || !map->bus->read)
return -EINVAL;
range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg);
if (range) { if (range) {
ret = _regmap_select_page(map, &reg, range, ret = _regmap_select_page(map, &reg, range,
......
...@@ -79,7 +79,9 @@ config SND_SOC_ALL_CODECS ...@@ -79,7 +79,9 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98090 if I2C select SND_SOC_MAX98090 if I2C
select SND_SOC_MAX98095 if I2C select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX98357A if GPIOLIB select SND_SOC_MAX98357A if GPIOLIB
select SND_SOC_MAX9867 if I2C
select SND_SOC_MAX98925 if I2C select SND_SOC_MAX98925 if I2C
select SND_SOC_MAX98926 if I2C
select SND_SOC_MAX9850 if I2C select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9768 if I2C select SND_SOC_MAX9768 if I2C
select SND_SOC_MAX9877 if I2C select SND_SOC_MAX9877 if I2C
...@@ -518,9 +520,15 @@ config SND_SOC_MAX98095 ...@@ -518,9 +520,15 @@ config SND_SOC_MAX98095
config SND_SOC_MAX98357A config SND_SOC_MAX98357A
tristate tristate
config SND_SOC_MAX9867
tristate
config SND_SOC_MAX98925 config SND_SOC_MAX98925
tristate tristate
config SND_SOC_MAX98926
tristate
config SND_SOC_MAX9850 config SND_SOC_MAX9850
tristate tristate
......
...@@ -74,7 +74,9 @@ snd-soc-max98088-objs := max98088.o ...@@ -74,7 +74,9 @@ snd-soc-max98088-objs := max98088.o
snd-soc-max98090-objs := max98090.o snd-soc-max98090-objs := max98090.o
snd-soc-max98095-objs := max98095.o snd-soc-max98095-objs := max98095.o
snd-soc-max98357a-objs := max98357a.o snd-soc-max98357a-objs := max98357a.o
snd-soc-max9867-objs := max9867.o
snd-soc-max98925-objs := max98925.o snd-soc-max98925-objs := max98925.o
snd-soc-max98926-objs := max98926.o
snd-soc-max9850-objs := max9850.o snd-soc-max9850-objs := max9850.o
snd-soc-mc13783-objs := mc13783.o snd-soc-mc13783-objs := mc13783.o
snd-soc-ml26124-objs := ml26124.o snd-soc-ml26124-objs := ml26124.o
...@@ -280,7 +282,9 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o ...@@ -280,7 +282,9 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o
obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o
obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
......
...@@ -303,7 +303,6 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, ...@@ -303,7 +303,6 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
if (ret < 0) if (ret < 0)
return ret; return ret;
dip = (u8 *)&frame;
break; break;
case DRM_ELD_CONN_TYPE_DP: case DRM_ELD_CONN_TYPE_DP:
...@@ -332,9 +331,9 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, ...@@ -332,9 +331,9 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
/* Fill infoframe. Index auto-incremented */ /* Fill infoframe. Index auto-incremented */
hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
for (i = 0; i < sizeof(frame); i++) for (i = 0; i < sizeof(buffer); i++)
snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
AC_VERB_SET_HDMI_DIP_DATA, dip[i]); AC_VERB_SET_HDMI_DIP_DATA, buffer[i]);
} else { } else {
for (i = 0; i < sizeof(dp_ai); i++) for (i = 0; i < sizeof(dp_ai); i++)
snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
......
/*
* max9867.c -- max9867 ALSA SoC Audio driver
*
* Copyright 2013-15 Maxim Integrated Products
*
* 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.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "max9867.h"
static const char *const max9867_spmode[] = {
"Stereo Diff", "Mono Diff",
"Stereo Cap", "Mono Cap",
"Stereo Single", "Mono Single",
"Stereo Single Fast", "Mono Single Fast"
};
static const char *const max9867_sidetone_text[] = {
"None", "Left", "Right", "LeftRight", "LeftRightDiv2",
};
static const char *const max9867_filter_text[] = {"IIR", "FIR"};
static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7,
max9867_filter_text);
static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0,
max9867_spmode);
static SOC_ENUM_SINGLE_DECL(max9867_sidetone, MAX9867_DACGAIN, 6,
max9867_sidetone_text);
static DECLARE_TLV_DB_SCALE(max9860_capture_tlv, -600, 200, 0);
static DECLARE_TLV_DB_SCALE(max9860_mic_tlv, 2000, 100, 1);
static DECLARE_TLV_DB_SCALE(max9860_adc_left_tlv, -1200, 100, 1);
static DECLARE_TLV_DB_SCALE(max9860_adc_right_tlv, -1200, 100, 1);
static const unsigned int max98088_micboost_tlv[] = {
TLV_DB_RANGE_HEAD(2),
0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
};
static const struct snd_kcontrol_new max9867_snd_controls[] = {
SOC_DOUBLE_R("Master Playback Volume", MAX9867_LEFTVOL,
MAX9867_RIGHTVOL, 0, 63, 1),
SOC_DOUBLE_R_TLV("Capture Volume", MAX9867_LEFTMICGAIN,
MAX9867_RIGHTMICGAIN,
0, 15, 1, max9860_capture_tlv),
SOC_DOUBLE_R_TLV("Mic Volume", MAX9867_LEFTMICGAIN,
MAX9867_RIGHTMICGAIN, 0, 31, 1, max9860_mic_tlv),
SOC_DOUBLE_R_TLV("Mic Boost Volume", MAX9867_LEFTMICGAIN,
MAX9867_RIGHTMICGAIN, 5, 3, 0, max98088_micboost_tlv),
SOC_ENUM("Digital Sidetone Src", max9867_sidetone),
SOC_SINGLE("Sidetone Volume", MAX9867_DACGAIN, 0, 31, 1),
SOC_SINGLE("DAC Volume", MAX9867_DACLEVEL, 4, 3, 0),
SOC_SINGLE("DAC Attenuation", MAX9867_DACLEVEL, 0, 15, 1),
SOC_SINGLE_TLV("ADC Left Volume", MAX9867_ADCLEVEL,
4, 15, 1, max9860_adc_left_tlv),
SOC_SINGLE_TLV("ADC Right Volume", MAX9867_ADCLEVEL,
0, 15, 1, max9860_adc_right_tlv),
SOC_ENUM("Speaker Mode", max9867_spkmode),
SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0),
SOC_SINGLE("ZCD Switch", MAX9867_MODECONFIG, 5, 1, 0),
SOC_ENUM("DSP Filter", max9867_filter),
};
static const char *const max9867_mux[] = {"None", "Mic", "Line", "Mic_Line"};
static SOC_ENUM_SINGLE_DECL(max9867_mux_enum,
MAX9867_INPUTCONFIG, MAX9867_INPUT_SHIFT,
max9867_mux);
static const struct snd_kcontrol_new max9867_dapm_mux_controls =
SOC_DAPM_ENUM("Route", max9867_mux_enum);
static const struct snd_kcontrol_new max9867_left_dapm_control =
SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 6, 1, 0);
static const struct snd_kcontrol_new max9867_right_dapm_control =
SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 5, 1, 0);
static const struct snd_kcontrol_new max9867_line_dapm_control =
SOC_DAPM_SINGLE("Switch", MAX9867_LEFTLINELVL, 6, 1, 1);
static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("Left DAC", NULL, MAX9867_PWRMAN, 3, 0),
SND_SOC_DAPM_DAC("Right DAC", NULL, MAX9867_PWRMAN, 2, 0),
SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("HPOUT"),
SND_SOC_DAPM_AIF_IN("DAI_IN", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture", MAX9867_PWRMAN, 1, 0),
SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture", MAX9867_PWRMAN, 0, 0),
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
&max9867_dapm_mux_controls),
SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SWITCH("Left Line", MAX9867_LEFTLINELVL, 6, 1,
&max9867_left_dapm_control),
SND_SOC_DAPM_SWITCH("Right Line", MAX9867_RIGTHLINELVL, 6, 1,
&max9867_right_dapm_control),
SND_SOC_DAPM_SWITCH("Line Mixer", SND_SOC_NOPM, 0, 0,
&max9867_line_dapm_control),
SND_SOC_DAPM_INPUT("LINE_IN"),
};
static const struct snd_soc_dapm_route max9867_audio_map[] = {
{"Left DAC", NULL, "DAI_OUT"},
{"Right DAC", NULL, "DAI_OUT"},
{"Output Mixer", NULL, "Left DAC"},
{"Output Mixer", NULL, "Right DAC"},
{"HPOUT", NULL, "Output Mixer"},
{"Left ADC", NULL, "DAI_IN"},
{"Right ADC", NULL, "DAI_IN"},
{"Input Mixer", NULL, "Left ADC"},
{"Input Mixer", NULL, "Right ADC"},
{"Input Mux", "Line", "Input Mixer"},
{"Input Mux", "Mic", "Input Mixer"},
{"Input Mux", "Mic_Line", "Input Mixer"},
{"Right Line", "Switch", "Input Mux"},
{"Left Line", "Switch", "Input Mux"},
{"LINE_IN", NULL, "Left Line"},
{"LINE_IN", NULL, "Right Line"},
};
enum rates {
pcm_rate_8, pcm_rate_16, pcm_rate_24,
pcm_rate_32, pcm_rate_44,
pcm_rate_48, max_pcm_rate,
};
struct ni_div_rates {
u32 mclk;
u16 ni[max_pcm_rate];
} ni_div[] = {
{11289600, {0x116A, 0x22D4, 0x343F, 0x45A9, 0x6000, 0x687D} },
{12000000, {0x1062, 0x20C5, 0x3127, 0x4189, 0x5A51, 0x624E} },
{12288000, {0x1000, 0x2000, 0x3000, 0x4000, 0x5833, 0x6000} },
{13000000, {0x0F20, 0x1E3F, 0x2D5F, 0x3C7F, 0x535F, 0x5ABE} },
{19200000, {0x0A3D, 0x147B, 0x1EB8, 0x28F6, 0x3873, 0x3D71} },
{24000000, {0x1062, 0x20C5, 0x1893, 0x4189, 0x5A51, 0x624E} },
{26000000, {0x0F20, 0x1E3F, 0x16AF, 0x3C7F, 0x535F, 0x5ABE} },
{27000000, {0x0E90, 0x1D21, 0x15D8, 0x3A41, 0x5048, 0x5762} },
};
static inline int get_ni_value(int mclk, int rate)
{
int i, ret = 0;
/* find the closest rate index*/
for (i = 0; i < ARRAY_SIZE(ni_div); i++) {
if (ni_div[i].mclk >= mclk)
break;
}
if (i == ARRAY_SIZE(ni_div))
return -EINVAL;
switch (rate) {
case 8000:
return ni_div[i].ni[pcm_rate_8];
case 16000:
return ni_div[i].ni[pcm_rate_16];
case 32000:
return ni_div[i].ni[pcm_rate_32];
case 44100:
return ni_div[i].ni[pcm_rate_44];
case 48000:
return ni_div[i].ni[pcm_rate_48];
default:
pr_err("%s wrong rate %d\n", __func__, rate);
ret = -EINVAL;
}
return ret;
}
static int max9867_dai_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;
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
unsigned int ni_h, ni_l;
int value;
value = get_ni_value(max9867->sysclk, params_rate(params));
if (value < 0)
return value;
ni_h = (0xFF00 & value) >> 8;
ni_l = 0x00FF & value;
/* set up the ni value */
regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
MAX9867_NI_HIGH_MASK, ni_h);
regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
MAX9867_NI_LOW_MASK, ni_l);
if (!max9867->master) {
/*
* digital pll locks on to any externally supplied LRCLK signal
* and also enable rapid lock mode.
*/
regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK);
regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
MAX9867_PLL, MAX9867_PLL);
} else {
unsigned long int bclk_rate, pclk_bclk_ratio;
int bclk_value;
bclk_rate = params_rate(params) * 2 * params_width(params);
pclk_bclk_ratio = max9867->pclk/bclk_rate;
switch (params_width(params)) {
case 8:
case 16:
switch (pclk_bclk_ratio) {
case 2:
bclk_value = MAX9867_IFC1B_PCLK_2;
break;
case 4:
bclk_value = MAX9867_IFC1B_PCLK_4;
break;
case 8:
bclk_value = MAX9867_IFC1B_PCLK_8;
break;
case 16:
bclk_value = MAX9867_IFC1B_PCLK_16;
break;
default:
dev_err(codec->dev,
"unsupported sampling rate\n");
return -EINVAL;
}
break;
case 24:
bclk_value = MAX9867_IFC1B_24BIT;
break;
case 32:
bclk_value = MAX9867_IFC1B_32BIT;
break;
default:
dev_err(codec->dev, "unsupported sampling rate\n");
return -EINVAL;
}
regmap_update_bits(max9867->regmap, MAX9867_IFC1B,
MAX9867_IFC1B_BCLK_MASK, bclk_value);
}
return 0;
}
static int max9867_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK);
return 0;
}
static int max9867_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
if (mute)
regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
MAX9867_DAC_MUTE_MASK, MAX9867_DAC_MUTE_MASK);
else
regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
MAX9867_DAC_MUTE_MASK, 0);
return 0;
}
static int max9867_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
int value = 0;
/* Set the prescaler based on the master clock frequency*/
if (freq >= 10000000 && freq <= 20000000) {
value |= MAX9867_PSCLK_10_20;
max9867->pclk = freq;
} else if (freq >= 20000000 && freq <= 40000000) {
value |= MAX9867_PSCLK_20_40;
max9867->pclk = freq/2;
} else if (freq >= 40000000 && freq <= 60000000) {
value |= MAX9867_PSCLK_40_60;
max9867->pclk = freq/4;
} else {
pr_err("bad clock frequency %d", freq);
return -EINVAL;
}
value = value << MAX9867_PSCLK_SHIFT;
max9867->sysclk = freq;
/* exact integer mode is not supported */
value &= ~MAX9867_FREQ_MASK;
regmap_update_bits(max9867->regmap, MAX9867_SYSCLK,
MAX9867_PSCLK_MASK, value);
return 0;
}
static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
u8 iface1A = 0, iface1B = 0;
int ret;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
max9867->master = 1;
iface1A |= MAX9867_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
max9867->master = 0;
iface1A &= ~MAX9867_MASTER;
break;
default:
return -EINVAL;
}
/* for i2s compatible mode */
iface1A |= MAX9867_I2S_DLY;
/* SDOUT goes to hiz state after all data is transferred */
iface1A |= MAX9867_SDOUT_HIZ;
/* Clock inversion bits, BCI and WCI */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_IF:
iface1A |= MAX9867_WCI_MODE | MAX9867_BCI_MODE;
break;
case SND_SOC_DAIFMT_IB_NF:
iface1A |= MAX9867_BCI_MODE;
break;
case SND_SOC_DAIFMT_NB_IF:
iface1A |= MAX9867_WCI_MODE;
break;
default:
return -EINVAL;
}
ret = regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A);
ret = regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B);
return 0;
}
static struct snd_soc_dai_ops max9867_dai_ops = {
.set_fmt = max9867_dai_set_fmt,
.set_sysclk = max9867_set_dai_sysclk,
.prepare = max9867_prepare,
.digital_mute = max9867_mute,
.hw_params = max9867_dai_hw_params,
};
#define MAX9867_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
#define MAX9867_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
static struct snd_soc_dai_driver max9867_dai[] = {
{
.name = "max9867-aif1",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MAX9867_RATES,
.formats = MAX9867_FORMATS,
},
.capture = {
.stream_name = "HiFi Capture",
.channels_min = 1,
.channels_max = 2,
.rates = MAX9867_RATES,
.formats = MAX9867_FORMATS,
},
.ops = &max9867_dai_ops,
}
};
#ifdef CONFIG_PM_SLEEP
static int max9867_suspend(struct device *dev)
{
struct max9867_priv *max9867 = dev_get_drvdata(dev);
/* Drop down to power saving mode when system is suspended */
regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
MAX9867_SHTDOWN_MASK, ~MAX9867_SHTDOWN_MASK);
return 0;
}
static int max9867_resume(struct device *dev)
{
struct max9867_priv *max9867 = dev_get_drvdata(dev);
regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK);
return 0;
}
#endif
static int max9867_probe(struct snd_soc_codec *codec)
{
struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "max98090_probe\n");
max9867->codec = codec;
return 0;
}
static struct snd_soc_codec_driver max9867_codec = {
.probe = max9867_probe,
.controls = max9867_snd_controls,
.num_controls = ARRAY_SIZE(max9867_snd_controls),
.dapm_routes = max9867_audio_map,
.num_dapm_routes = ARRAY_SIZE(max9867_audio_map),
.dapm_widgets = max9867_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets),
};
static bool max9867_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case MAX9867_STATUS:
case MAX9867_JACKSTATUS:
case MAX9867_AUXHIGH:
case MAX9867_AUXLOW:
return true;
default:
return false;
}
}
static const struct reg_default max9867_reg[] = {
{ 0x04, 0x00 },
{ 0x05, 0x00 },
{ 0x06, 0x00 },
{ 0x07, 0x00 },
{ 0x08, 0x00 },
{ 0x09, 0x00 },
{ 0x0A, 0x00 },
{ 0x0B, 0x00 },
{ 0x0C, 0x00 },
{ 0x0D, 0x00 },
{ 0x0E, 0x00 },
{ 0x0F, 0x00 },
{ 0x10, 0x00 },
{ 0x11, 0x00 },
{ 0x12, 0x00 },
{ 0x13, 0x00 },
{ 0x14, 0x00 },
{ 0x15, 0x00 },
{ 0x16, 0x00 },
{ 0x17, 0x00 },
};
static const struct regmap_config max9867_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX9867_REVISION,
.reg_defaults = max9867_reg,
.num_reg_defaults = ARRAY_SIZE(max9867_reg),
.volatile_reg = max9867_volatile_register,
.cache_type = REGCACHE_RBTREE,
};
static int max9867_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max9867_priv *max9867;
int ret = 0, reg;
max9867 = devm_kzalloc(&i2c->dev,
sizeof(*max9867), GFP_KERNEL);
if (!max9867)
return -ENOMEM;
i2c_set_clientdata(i2c, max9867);
max9867->regmap = devm_regmap_init_i2c(i2c, &max9867_regmap);
if (IS_ERR(max9867->regmap)) {
ret = PTR_ERR(max9867->regmap);
dev_err(&i2c->dev,
"Failed to allocate regmap: %d\n", ret);
return ret;
}
ret = regmap_read(max9867->regmap,
MAX9867_REVISION, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read: %d\n", ret);
return ret;
}
dev_info(&i2c->dev, "device revision: %x\n", reg);
ret = snd_soc_register_codec(&i2c->dev, &max9867_codec,
max9867_dai, ARRAY_SIZE(max9867_dai));
if (ret < 0) {
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
return ret;
}
return ret;
}
static int max9867_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static const struct i2c_device_id max9867_i2c_id[] = {
{ "max9867", 0 },
{ }
};
static const struct of_device_id max9867_of_match[] = {
{ .compatible = "maxim,max9867", },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9867_i2c_id);
static const struct dev_pm_ops max9867_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(max9867_suspend, max9867_resume)
};
static struct i2c_driver max9867_i2c_driver = {
.driver = {
.name = "max9867",
.of_match_table = of_match_ptr(max9867_of_match),
.pm = &max9867_pm_ops,
},
.probe = max9867_i2c_probe,
.remove = max9867_i2c_remove,
.id_table = max9867_i2c_id,
};
module_i2c_driver(max9867_i2c_driver);
MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
MODULE_DESCRIPTION("ALSA SoC MAX9867 driver");
MODULE_LICENSE("GPL");
/*
* max9867.h -- MAX9867 ALSA SoC Audio driver
*
* Copyright 2013-2015 Maxim Integrated Products
*
* 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.
*/
#ifndef _MAX9867_H
#define _MAX9867_H
/* MAX9867 register space */
#define MAX9867_STATUS 0x00
#define MAX9867_JACKSTATUS 0x01
#define MAX9867_AUXHIGH 0x02
#define MAX9867_AUXLOW 0x03
#define MAX9867_INTEN 0x04
#define MAX9867_SYSCLK 0x05
#define MAX9867_FREQ_MASK 0xF
#define MAX9867_PSCLK_SHIFT 0x4
#define MAX9867_PSCLK_WIDTH 0x2
#define MAX9867_PSCLK_MASK (0x03<<MAX9867_PSCLK_SHIFT)
#define MAX9867_PSCLK_10_20 0x1
#define MAX9867_PSCLK_20_40 0x2
#define MAX9867_PSCLK_40_60 0x3
#define MAX9867_AUDIOCLKHIGH 0x06
#define MAX9867_NI_HIGH_WIDTH 0x7
#define MAX9867_NI_HIGH_MASK 0x7F
#define MAX9867_NI_LOW_MASK 0x7F
#define MAX9867_NI_LOW_SHIFT 0x1
#define MAX9867_PLL (1<<7)
#define MAX9867_AUDIOCLKLOW 0x07
#define MAX9867_RAPID_LOCK 0x01
#define MAX9867_IFC1A 0x08
#define MAX9867_MASTER (1<<7)
#define MAX9867_I2S_DLY (1<<4)
#define MAX9867_SDOUT_HIZ (1<<3)
#define MAX9867_TDM_MODE (1<<2)
#define MAX9867_WCI_MODE (1<<6)
#define MAX9867_BCI_MODE (1<<5)
#define MAX9867_IFC1B 0x09
#define MAX9867_IFC1B_BCLK_MASK 7
#define MAX9867_IFC1B_32BIT 0x01
#define MAX9867_IFC1B_24BIT 0x02
#define MAX9867_IFC1B_PCLK_2 4
#define MAX9867_IFC1B_PCLK_4 5
#define MAX9867_IFC1B_PCLK_8 6
#define MAX9867_IFC1B_PCLK_16 7
#define MAX9867_CODECFLTR 0x0a
#define MAX9867_DACGAIN 0x0b
#define MAX9867_DACLEVEL 0x0c
#define MAX9867_DAC_MUTE_SHIFT 0x6
#define MAX9867_DAC_MUTE_WIDTH 0x1
#define MAX9867_DAC_MUTE_MASK (0x1<<MAX9867_DAC_MUTE_SHIFT)
#define MAX9867_ADCLEVEL 0x0d
#define MAX9867_LEFTLINELVL 0x0e
#define MAX9867_RIGTHLINELVL 0x0f
#define MAX9867_LEFTVOL 0x10
#define MAX9867_RIGHTVOL 0x11
#define MAX9867_LEFTMICGAIN 0x12
#define MAX9867_RIGHTMICGAIN 0x13
#define MAX9867_INPUTCONFIG 0x14
#define MAX9867_INPUT_SHIFT 0x6
#define MAX9867_MICCONFIG 0x15
#define MAX9867_MODECONFIG 0x16
#define MAX9867_PWRMAN 0x17
#define MAX9867_SHTDOWN_MASK (1<<7)
#define MAX9867_REVISION 0xff
#define MAX9867_CACHEREGNUM 10
/* codec private data */
struct max9867_priv {
struct regmap *regmap;
struct snd_soc_codec *codec;
unsigned int sysclk;
unsigned int pclk;
unsigned int master;
};
#endif
/*
* max98926.c -- ALSA SoC MAX98926 driver
* Copyright 2013-15 Maxim Integrated Products
* 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.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "max98926.h"
static const char * const max98926_boost_voltage_txt[] = {
"8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V"
};
static const char * const max98926_boost_current_txt[] = {
"0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0",
"2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4"
};
static const char *const max98926_dai_txt[] = {
"Left", "Right", "LeftRight", "LeftRightDiv2",
};
static const char *const max98926_pdm_ch_text[] = {
"Current", "Voltage",
};
static const char *const max98926_hpf_cutoff_txt[] = {
"Disable", "DC Block", "100Hz",
"200Hz", "400Hz", "800Hz",
};
static struct reg_default max98926_reg[] = {
{ 0x0B, 0x00 }, /* IRQ Enable0 */
{ 0x0C, 0x00 }, /* IRQ Enable1 */
{ 0x0D, 0x00 }, /* IRQ Enable2 */
{ 0x0E, 0x00 }, /* IRQ Clear0 */
{ 0x0F, 0x00 }, /* IRQ Clear1 */
{ 0x10, 0x00 }, /* IRQ Clear2 */
{ 0x11, 0xC0 }, /* Map0 */
{ 0x12, 0x00 }, /* Map1 */
{ 0x13, 0x00 }, /* Map2 */
{ 0x14, 0xF0 }, /* Map3 */
{ 0x15, 0x00 }, /* Map4 */
{ 0x16, 0xAB }, /* Map5 */
{ 0x17, 0x89 }, /* Map6 */
{ 0x18, 0x00 }, /* Map7 */
{ 0x19, 0x00 }, /* Map8 */
{ 0x1A, 0x04 }, /* DAI Clock Mode 1 */
{ 0x1B, 0x00 }, /* DAI Clock Mode 2 */
{ 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
{ 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
{ 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
{ 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
{ 0x20, 0x50 }, /* Format */
{ 0x21, 0x00 }, /* TDM Slot Select */
{ 0x22, 0x00 }, /* DOUT Configuration VMON */
{ 0x23, 0x00 }, /* DOUT Configuration IMON */
{ 0x24, 0x00 }, /* DOUT Configuration VBAT */
{ 0x25, 0x00 }, /* DOUT Configuration VBST */
{ 0x26, 0x00 }, /* DOUT Configuration FLAG */
{ 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
{ 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
{ 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
{ 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
{ 0x2B, 0x02 }, /* DOUT Drive Strength */
{ 0x2C, 0x90 }, /* Filters */
{ 0x2D, 0x00 }, /* Gain */
{ 0x2E, 0x02 }, /* Gain Ramping */
{ 0x2F, 0x00 }, /* Speaker Amplifier */
{ 0x30, 0x0A }, /* Threshold */
{ 0x31, 0x00 }, /* ALC Attack */
{ 0x32, 0x80 }, /* ALC Atten and Release */
{ 0x33, 0x00 }, /* ALC Infinite Hold Release */
{ 0x34, 0x92 }, /* ALC Configuration */
{ 0x35, 0x01 }, /* Boost Converter */
{ 0x36, 0x00 }, /* Block Enable */
{ 0x37, 0x00 }, /* Configuration */
{ 0x38, 0x00 }, /* Global Enable */
{ 0x3A, 0x00 }, /* Boost Limiter */
};
static const struct soc_enum max98926_voltage_enum[] = {
SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, 0,
ARRAY_SIZE(max98926_pdm_ch_text),
max98926_pdm_ch_text),
};
static const struct snd_kcontrol_new max98926_voltage_control =
SOC_DAPM_ENUM("Route", max98926_voltage_enum);
static const struct soc_enum max98926_current_enum[] = {
SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS,
MAX98926_PDM_SOURCE_1_SHIFT,
ARRAY_SIZE(max98926_pdm_ch_text),
max98926_pdm_ch_text),
};
static const struct snd_kcontrol_new max98926_current_control =
SOC_DAPM_ENUM("Route", max98926_current_enum);
static const struct snd_kcontrol_new max98926_mixer_controls[] = {
SOC_DAPM_SINGLE("PCM Single Switch", MAX98926_SPK_AMP,
MAX98926_INSELECT_MODE_SHIFT, 0, 0),
SOC_DAPM_SINGLE("PDM Single Switch", MAX98926_SPK_AMP,
MAX98926_INSELECT_MODE_SHIFT, 1, 0),
};
static const struct snd_kcontrol_new max98926_dai_controls[] = {
SOC_DAPM_SINGLE("Left", MAX98926_GAIN,
MAX98926_DAC_IN_SEL_SHIFT, 0, 0),
SOC_DAPM_SINGLE("Right", MAX98926_GAIN,
MAX98926_DAC_IN_SEL_SHIFT, 1, 0),
SOC_DAPM_SINGLE("LeftRight", MAX98926_GAIN,
MAX98926_DAC_IN_SEL_SHIFT, 2, 0),
SOC_DAPM_SINGLE("(Left+Right)/2 Switch", MAX98926_GAIN,
MAX98926_DAC_IN_SEL_SHIFT, 3, 0),
};
static const struct snd_soc_dapm_widget max98926_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0,
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("Amp Enable", NULL, MAX98926_BLOCK_ENABLE,
MAX98926_SPK_EN_SHIFT, 0),
SND_SOC_DAPM_SUPPLY("Global Enable", MAX98926_GLOBAL_ENABLE,
MAX98926_EN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("VI Enable", MAX98926_BLOCK_ENABLE,
MAX98926_ADC_IMON_EN_WIDTH |
MAX98926_ADC_VMON_EN_SHIFT,
0, NULL, 0),
SND_SOC_DAPM_PGA("BST Enable", MAX98926_BLOCK_ENABLE,
MAX98926_BST_EN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_MIXER("PCM Sel", MAX98926_SPK_AMP,
MAX98926_INSELECT_MODE_SHIFT, 0,
&max98926_mixer_controls[0],
ARRAY_SIZE(max98926_mixer_controls)),
SND_SOC_DAPM_MIXER("DAI Sel",
MAX98926_GAIN, MAX98926_DAC_IN_SEL_SHIFT, 0,
&max98926_dai_controls[0],
ARRAY_SIZE(max98926_dai_controls)),
SND_SOC_DAPM_MUX("PDM CH1 Source",
MAX98926_DAI_CLK_DIV_N_LSBS,
MAX98926_PDM_CURRENT_SHIFT,
0, &max98926_current_control),
SND_SOC_DAPM_MUX("PDM CH0 Source",
MAX98926_DAI_CLK_DIV_N_LSBS,
MAX98926_PDM_VOLTAGE_SHIFT,
0, &max98926_voltage_control),
};
static const struct snd_soc_dapm_route max98926_audio_map[] = {
{"VI Enable", NULL, "DAI_OUT"},
{"DAI Sel", "Left", "VI Enable"},
{"DAI Sel", "Right", "VI Enable"},
{"DAI Sel", "LeftRight", "VI Enable"},
{"DAI Sel", "LeftRightDiv2", "VI Enable"},
{"PCM Sel", "PCM", "DAI Sel"},
{"PDM CH1 Source", "Current", "DAI_OUT"},
{"PDM CH1 Source", "Voltage", "DAI_OUT"},
{"PDM CH0 Source", "Current", "DAI_OUT"},
{"PDM CH0 Source", "Voltage", "DAI_OUT"},
{"PCM Sel", "Analog", "PDM CH1 Source"},
{"PCM Sel", "Analog", "PDM CH0 Source"},
{"Amp Enable", NULL, "PCM Sel"},
{"BST Enable", NULL, "Amp Enable"},
{"BE_OUT", NULL, "BST Enable"},
};
static bool max98926_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case MAX98926_VBAT_DATA:
case MAX98926_VBST_DATA:
case MAX98926_LIVE_STATUS0:
case MAX98926_LIVE_STATUS1:
case MAX98926_LIVE_STATUS2:
case MAX98926_STATE0:
case MAX98926_STATE1:
case MAX98926_STATE2:
case MAX98926_FLAG0:
case MAX98926_FLAG1:
case MAX98926_FLAG2:
case MAX98926_VERSION:
return true;
default:
return false;
}
}
static bool max98926_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case MAX98926_IRQ_CLEAR0:
case MAX98926_IRQ_CLEAR1:
case MAX98926_IRQ_CLEAR2:
case MAX98926_ALC_HOLD_RLS:
return false;
default:
return true;
}
};
DECLARE_TLV_DB_SCALE(max98926_spk_tlv, -600, 100, 0);
DECLARE_TLV_DB_RANGE(max98926_current_tlv,
0, 11, TLV_DB_SCALE_ITEM(20, 20, 0),
12, 15, TLV_DB_SCALE_ITEM(320, 40, 0),
);
static SOC_ENUM_SINGLE_DECL(max98926_dac_hpf_cutoff,
MAX98926_FILTERS, MAX98926_DAC_HPF_SHIFT,
max98926_hpf_cutoff_txt);
static SOC_ENUM_SINGLE_DECL(max98926_boost_voltage,
MAX98926_CONFIGURATION, MAX98926_BST_VOUT_SHIFT,
max98926_boost_voltage_txt);
static const struct snd_kcontrol_new max98926_snd_controls[] = {
SOC_SINGLE_TLV("Speaker Volume", MAX98926_GAIN,
MAX98926_SPK_GAIN_SHIFT,
(1<<MAX98926_SPK_GAIN_WIDTH)-1, 0,
max98926_spk_tlv),
SOC_SINGLE("Ramp Switch", MAX98926_GAIN_RAMPING,
MAX98926_SPK_RMP_EN_SHIFT, 1, 0),
SOC_SINGLE("ZCD Switch", MAX98926_GAIN_RAMPING,
MAX98926_SPK_ZCD_EN_SHIFT, 1, 0),
SOC_SINGLE("ALC Switch", MAX98926_THRESHOLD,
MAX98926_ALC_EN_SHIFT, 1, 0),
SOC_SINGLE("ALC Threshold", MAX98926_THRESHOLD,
MAX98926_ALC_TH_SHIFT,
(1<<MAX98926_ALC_TH_WIDTH)-1, 0),
SOC_ENUM("Boost Output Voltage", max98926_boost_voltage),
SOC_SINGLE_TLV("Boost Current Limit", MAX98926_BOOST_LIMITER,
MAX98926_BST_ILIM_SHIFT,
(1<<MAX98926_BST_ILIM_SHIFT)-1, 0,
max98926_current_tlv),
SOC_ENUM("DAC HPF Cutoff", max98926_dac_hpf_cutoff),
SOC_DOUBLE("PDM Channel One", MAX98926_DAI_CLK_DIV_N_LSBS,
MAX98926_PDM_CHANNEL_1_SHIFT,
MAX98926_PDM_CHANNEL_1_HIZ, 1, 0),
SOC_DOUBLE("PDM Channel Zero", MAX98926_DAI_CLK_DIV_N_LSBS,
MAX98926_PDM_CHANNEL_0_SHIFT,
MAX98926_PDM_CHANNEL_0_HIZ, 1, 0),
};
static const struct {
int rate;
int sr;
} rate_table[] = {
{
.rate = 8000,
.sr = 0,
},
{
.rate = 11025,
.sr = 1,
},
{
.rate = 12000,
.sr = 2,
},
{
.rate = 16000,
.sr = 3,
},
{
.rate = 22050,
.sr = 4,
},
{
.rate = 24000,
.sr = 5,
},
{
.rate = 32000,
.sr = 6,
},
{
.rate = 44100,
.sr = 7,
},
{
.rate = 48000,
.sr = 8,
},
};
static void max98926_set_sense_data(struct max98926_priv *max98926)
{
regmap_update_bits(max98926->regmap,
MAX98926_DOUT_CFG_VMON,
MAX98926_DAI_VMON_EN_MASK,
MAX98926_DAI_VMON_EN_MASK);
regmap_update_bits(max98926->regmap,
MAX98926_DOUT_CFG_IMON,
MAX98926_DAI_IMON_EN_MASK,
MAX98926_DAI_IMON_EN_MASK);
if (!max98926->interleave_mode) {
/* set VMON slots */
regmap_update_bits(max98926->regmap,
MAX98926_DOUT_CFG_VMON,
MAX98926_DAI_VMON_SLOT_MASK,
max98926->v_slot);
/* set IMON slots */
regmap_update_bits(max98926->regmap,
MAX98926_DOUT_CFG_IMON,
MAX98926_DAI_IMON_SLOT_MASK,
max98926->i_slot);
} else {
/* enable interleave mode */
regmap_update_bits(max98926->regmap,
MAX98926_FORMAT,
MAX98926_DAI_INTERLEAVE_MASK,
MAX98926_DAI_INTERLEAVE_MASK);
/* set interleave slots */
regmap_update_bits(max98926->regmap,
MAX98926_DOUT_CFG_VBAT,
MAX98926_DAI_INTERLEAVE_SLOT_MASK,
max98926->v_slot);
}
}
static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
unsigned int invert = 0;
dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
max98926_set_sense_data(max98926);
break;
default:
dev_err(codec->dev, "DAI clock mode unsupported");
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_NB_IF:
invert = MAX98926_DAI_WCI_MASK;
break;
case SND_SOC_DAIFMT_IB_NF:
invert = MAX98926_DAI_BCI_MASK;
break;
case SND_SOC_DAIFMT_IB_IF:
invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK;
break;
default:
dev_err(codec->dev, "DAI invert mode unsupported");
return -EINVAL;
}
regmap_write(max98926->regmap,
MAX98926_FORMAT, MAX98926_DAI_DLY_MASK);
regmap_update_bits(max98926->regmap, MAX98926_FORMAT,
MAX98926_DAI_BCI_MASK, invert);
return 0;
}
static int max98926_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
int dai_sr = -EINVAL;
int rate = params_rate(params), i;
struct snd_soc_codec *codec = dai->codec;
struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
int blr_clk_ratio;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
regmap_update_bits(max98926->regmap,
MAX98926_FORMAT,
MAX98926_DAI_CHANSZ_MASK,
MAX98926_DAI_CHANSZ_16);
max98926->ch_size = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
regmap_update_bits(max98926->regmap,
MAX98926_FORMAT,
MAX98926_DAI_CHANSZ_MASK,
MAX98926_DAI_CHANSZ_24);
max98926->ch_size = 24;
break;
case SNDRV_PCM_FORMAT_S32_LE:
regmap_update_bits(max98926->regmap,
MAX98926_FORMAT,
MAX98926_DAI_CHANSZ_MASK,
MAX98926_DAI_CHANSZ_32);
max98926->ch_size = 32;
break;
default:
dev_dbg(codec->dev, "format unsupported %d",
params_format(params));
return -EINVAL;
}
/* BCLK/LRCLK ratio calculation */
blr_clk_ratio = params_channels(params) * max98926->ch_size;
switch (blr_clk_ratio) {
case 32:
regmap_update_bits(max98926->regmap,
MAX98926_DAI_CLK_MODE2,
MAX98926_DAI_BSEL_MASK,
MAX98926_DAI_BSEL_32);
break;
case 48:
regmap_update_bits(max98926->regmap,
MAX98926_DAI_CLK_MODE2,
MAX98926_DAI_BSEL_MASK,
MAX98926_DAI_BSEL_48);
break;
case 64:
regmap_update_bits(max98926->regmap,
MAX98926_DAI_CLK_MODE2,
MAX98926_DAI_BSEL_MASK,
MAX98926_DAI_BSEL_64);
break;
default:
return -EINVAL;
}
/* find the closest rate */
for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
if (rate_table[i].rate >= rate) {
dai_sr = rate_table[i].sr;
break;
}
}
if (dai_sr < 0)
return -EINVAL;
/* set DAI_SR to correct LRCLK frequency */
regmap_update_bits(max98926->regmap,
MAX98926_DAI_CLK_MODE2,
MAX98926_DAI_SR_MASK, dai_sr << MAX98926_DAI_SR_SHIFT);
return 0;
}
#define MAX98926_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_ops max98926_dai_ops = {
.set_fmt = max98926_dai_set_fmt,
.hw_params = max98926_dai_hw_params,
};
static struct snd_soc_dai_driver max98926_dai[] = {
{
.name = "max98926-aif1",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = MAX98926_FORMATS,
},
.capture = {
.stream_name = "HiFi Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = MAX98926_FORMATS,
},
.ops = &max98926_dai_ops,
}
};
static int max98926_probe(struct snd_soc_codec *codec)
{
struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
max98926->codec = codec;
codec->control_data = max98926->regmap;
/* Hi-Z all the slots */
regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_max98926 = {
.probe = max98926_probe,
.controls = max98926_snd_controls,
.num_controls = ARRAY_SIZE(max98926_snd_controls),
.dapm_routes = max98926_audio_map,
.num_dapm_routes = ARRAY_SIZE(max98926_audio_map),
.dapm_widgets = max98926_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets),
};
static struct regmap_config max98926_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX98926_VERSION,
.reg_defaults = max98926_reg,
.num_reg_defaults = ARRAY_SIZE(max98926_reg),
.volatile_reg = max98926_volatile_register,
.readable_reg = max98926_readable_register,
.cache_type = REGCACHE_RBTREE,
};
static int max98926_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
int ret, reg;
u32 value;
struct max98926_priv *max98926;
max98926 = devm_kzalloc(&i2c->dev,
sizeof(*max98926), GFP_KERNEL);
if (!max98926)
return -ENOMEM;
i2c_set_clientdata(i2c, max98926);
max98926->regmap = devm_regmap_init_i2c(i2c, &max98926_regmap);
if (IS_ERR(max98926->regmap)) {
ret = PTR_ERR(max98926->regmap);
dev_err(&i2c->dev,
"Failed to allocate regmap: %d\n", ret);
goto err_out;
}
if (of_property_read_bool(i2c->dev.of_node, "interleave-mode"))
max98926->interleave_mode = true;
if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
if (value > MAX98926_DAI_VMON_SLOT_1E_1F) {
dev_err(&i2c->dev, "vmon slot number is wrong:\n");
return -EINVAL;
}
max98926->v_slot = value;
}
if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) {
if (value > MAX98926_DAI_IMON_SLOT_1E_1F) {
dev_err(&i2c->dev, "imon slot number is wrong:\n");
return -EINVAL;
}
max98926->i_slot = value;
}
ret = regmap_read(max98926->regmap,
MAX98926_VERSION, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read: %x\n", reg);
return ret;
}
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98926,
max98926_dai, ARRAY_SIZE(max98926_dai));
if (ret < 0)
dev_err(&i2c->dev,
"Failed to register codec: %d\n", ret);
dev_info(&i2c->dev, "device version: %x\n", reg);
err_out:
return ret;
}
static int max98926_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static const struct i2c_device_id max98926_i2c_id[] = {
{ "max98926", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98926_i2c_id);
static const struct of_device_id max98926_of_match[] = {
{ .compatible = "maxim,max98926", },
{ }
};
MODULE_DEVICE_TABLE(of, max98926_of_match);
static struct i2c_driver max98926_i2c_driver = {
.driver = {
.name = "max98926",
.of_match_table = of_match_ptr(max98926_of_match),
.pm = NULL,
},
.probe = max98926_i2c_probe,
.remove = max98926_i2c_remove,
.id_table = max98926_i2c_id,
};
module_i2c_driver(max98926_i2c_driver)
MODULE_DESCRIPTION("ALSA SoC MAX98926 driver");
MODULE_AUTHOR("Anish kumar <anish.kumar@maximintegrated.com>");
MODULE_LICENSE("GPL");
/*
* max98926.h -- MAX98926 ALSA SoC Audio driver
* Copyright 2013-2015 Maxim Integrated Products
* 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.
*/
#ifndef _MAX98926_H
#define _MAX98926_H
#define MAX98926_CHIP_VERSION 0x40
#define MAX98926_CHIP_VERSION1 0x50
#define MAX98926_VBAT_DATA 0x00
#define MAX98926_VBST_DATA 0x01
#define MAX98926_LIVE_STATUS0 0x02
#define MAX98926_LIVE_STATUS1 0x03
#define MAX98926_LIVE_STATUS2 0x04
#define MAX98926_STATE0 0x05
#define MAX98926_STATE1 0x06
#define MAX98926_STATE2 0x07
#define MAX98926_FLAG0 0x08
#define MAX98926_FLAG1 0x09
#define MAX98926_FLAG2 0x0A
#define MAX98926_IRQ_ENABLE0 0x0B
#define MAX98926_IRQ_ENABLE1 0x0C
#define MAX98926_IRQ_ENABLE2 0x0D
#define MAX98926_IRQ_CLEAR0 0x0E
#define MAX98926_IRQ_CLEAR1 0x0F
#define MAX98926_IRQ_CLEAR2 0x10
#define MAX98926_MAP0 0x11
#define MAX98926_MAP1 0x12
#define MAX98926_MAP2 0x13
#define MAX98926_MAP3 0x14
#define MAX98926_MAP4 0x15
#define MAX98926_MAP5 0x16
#define MAX98926_MAP6 0x17
#define MAX98926_MAP7 0x18
#define MAX98926_MAP8 0x19
#define MAX98926_DAI_CLK_MODE1 0x1A
#define MAX98926_DAI_CLK_MODE2 0x1B
#define MAX98926_DAI_CLK_DIV_M_MSBS 0x1C
#define MAX98926_DAI_CLK_DIV_M_LSBS 0x1D
#define MAX98926_DAI_CLK_DIV_N_MSBS 0x1E
#define MAX98926_DAI_CLK_DIV_N_LSBS 0x1F
#define MAX98926_FORMAT 0x20
#define MAX98926_TDM_SLOT_SELECT 0x21
#define MAX98926_DOUT_CFG_VMON 0x22
#define MAX98926_DOUT_CFG_IMON 0x23
#define MAX98926_DOUT_CFG_VBAT 0x24
#define MAX98926_DOUT_CFG_VBST 0x25
#define MAX98926_DOUT_CFG_FLAG 0x26
#define MAX98926_DOUT_HIZ_CFG1 0x27
#define MAX98926_DOUT_HIZ_CFG2 0x28
#define MAX98926_DOUT_HIZ_CFG3 0x29
#define MAX98926_DOUT_HIZ_CFG4 0x2A
#define MAX98926_DOUT_DRV_STRENGTH 0x2B
#define MAX98926_FILTERS 0x2C
#define MAX98926_GAIN 0x2D
#define MAX98926_GAIN_RAMPING 0x2E
#define MAX98926_SPK_AMP 0x2F
#define MAX98926_THRESHOLD 0x30
#define MAX98926_ALC_ATTACK 0x31
#define MAX98926_ALC_ATTEN_RLS 0x32
#define MAX98926_ALC_HOLD_RLS 0x33
#define MAX98926_ALC_CONFIGURATION 0x34
#define MAX98926_BOOST_CONVERTER 0x35
#define MAX98926_BLOCK_ENABLE 0x36
#define MAX98926_CONFIGURATION 0x37
#define MAX98926_GLOBAL_ENABLE 0x38
#define MAX98926_BOOST_LIMITER 0x3A
#define MAX98926_VERSION 0xFF
#define MAX98926_REG_CNT (MAX98926_R03A_BOOST_LIMITER+1)
#define MAX98926_PDM_CURRENT_MASK (1<<7)
#define MAX98926_PDM_CURRENT_SHIFT 7
#define MAX98926_PDM_VOLTAGE_MASK (1<<3)
#define MAX98926_PDM_VOLTAGE_SHIFT 3
#define MAX98926_PDM_CHANNEL_0_MASK (1<<2)
#define MAX98926_PDM_CHANNEL_0_SHIFT 2
#define MAX98926_PDM_CHANNEL_1_MASK (1<<6)
#define MAX98926_PDM_CHANNEL_1_SHIFT 6
#define MAX98926_PDM_CHANNEL_1_HIZ 5
#define MAX98926_PDM_CHANNEL_0_HIZ 1
#define MAX98926_PDM_SOURCE_0_SHIFT 0
#define MAX98926_PDM_SOURCE_0_MASK (1<<0)
#define MAX98926_PDM_SOURCE_1_MASK (1<<4)
#define MAX98926_PDM_SOURCE_1_SHIFT 4
/* MAX98926 Register Bit Fields */
/* MAX98926_R002_LIVE_STATUS0 */
#define MAX98926_THERMWARN_STATUS_MASK (1<<3)
#define MAX98926_THERMWARN_STATUS_SHIFT 3
#define MAX98926_THERMWARN_STATUS_WIDTH 1
#define MAX98926_THERMSHDN_STATUS_MASK (1<<1)
#define MAX98926_THERMSHDN_STATUS_SHIFT 1
#define MAX98926_THERMSHDN_STATUS_WIDTH 1
/* MAX98926_R003_LIVE_STATUS1 */
#define MAX98926_SPKCURNT_STATUS_MASK (1<<5)
#define MAX98926_SPKCURNT_STATUS_SHIFT 5
#define MAX98926_SPKCURNT_STATUS_WIDTH 1
#define MAX98926_WATCHFAIL_STATUS_MASK (1<<4)
#define MAX98926_WATCHFAIL_STATUS_SHIFT 4
#define MAX98926_WATCHFAIL_STATUS_WIDTH 1
#define MAX98926_ALCINFH_STATUS_MASK (1<<3)
#define MAX98926_ALCINFH_STATUS_SHIFT 3
#define MAX98926_ALCINFH_STATUS_WIDTH 1
#define MAX98926_ALCACT_STATUS_MASK (1<<2)
#define MAX98926_ALCACT_STATUS_SHIFT 2
#define MAX98926_ALCACT_STATUS_WIDTH 1
#define MAX98926_ALCMUT_STATUS_MASK (1<<1)
#define MAX98926_ALCMUT_STATUS_SHIFT 1
#define MAX98926_ALCMUT_STATUS_WIDTH 1
#define MAX98926_ACLP_STATUS_MASK (1<<0)
#define MAX98926_ACLP_STATUS_SHIFT 0
#define MAX98926_ACLP_STATUS_WIDTH 1
/* MAX98926_R004_LIVE_STATUS2 */
#define MAX98926_SLOTOVRN_STATUS_MASK (1<<6)
#define MAX98926_SLOTOVRN_STATUS_SHIFT 6
#define MAX98926_SLOTOVRN_STATUS_WIDTH 1
#define MAX98926_INVALSLOT_STATUS_MASK (1<<5)
#define MAX98926_INVALSLOT_STATUS_SHIFT 5
#define MAX98926_INVALSLOT_STATUS_WIDTH 1
#define MAX98926_SLOTCNFLT_STATUS_MASK (1<<4)
#define MAX98926_SLOTCNFLT_STATUS_SHIFT 4
#define MAX98926_SLOTCNFLT_STATUS_WIDTH 1
#define MAX98926_VBSTOVFL_STATUS_MASK (1<<3)
#define MAX98926_VBSTOVFL_STATUS_SHIFT 3
#define MAX98926_VBSTOVFL_STATUS_WIDTH 1
#define MAX98926_VBATOVFL_STATUS_MASK (1<<2)
#define MAX98926_VBATOVFL_STATUS_SHIFT 2
#define MAX98926_VBATOVFL_STATUS_WIDTH 1
#define MAX98926_IMONOVFL_STATUS_MASK (1<<1)
#define MAX98926_IMONOVFL_STATUS_SHIFT 1
#define MAX98926_IMONOVFL_STATUS_WIDTH 1
#define MAX98926_VMONOVFL_STATUS_MASK (1<<0)
#define MAX98926_VMONOVFL_STATUS_SHIFT 0
#define MAX98926_VMONOVFL_STATUS_WIDTH 1
/* MAX98926_R005_STATE0 */
#define MAX98926_THERMWARN_END_STATE_MASK (1<<3)
#define MAX98926_THERMWARN_END_STATE_SHIFT 3
#define MAX98926_THERMWARN_END_STATE_WIDTH 1
#define MAX98926_THERMWARN_BGN_STATE_MASK (1<<2)
#define MAX98926_THERMWARN_BGN_STATE_SHIFT 1
#define MAX98926_THERMWARN_BGN_STATE_WIDTH 1
#define MAX98926_THERMSHDN_END_STATE_MASK (1<<1)
#define MAX98926_THERMSHDN_END_STATE_SHIFT 1
#define MAX98926_THERMSHDN_END_STATE_WIDTH 1
#define MAX98926_THERMSHDN_BGN_STATE_MASK (1<<0)
#define MAX98926_THERMSHDN_BGN_STATE_SHIFT 0
#define MAX98926_THERMSHDN_BGN_STATE_WIDTH 1
/* MAX98926_R006_STATE1 */
#define MAX98926_SPRCURNT_STATE_MASK (1<<5)
#define MAX98926_SPRCURNT_STATE_SHIFT 5
#define MAX98926_SPRCURNT_STATE_WIDTH 1
#define MAX98926_WATCHFAIL_STATE_MASK (1<<4)
#define MAX98926_WATCHFAIL_STATE_SHIFT 4
#define MAX98926_WATCHFAIL_STATE_WIDTH 1
#define MAX98926_ALCINFH_STATE_MASK (1<<3)
#define MAX98926_ALCINFH_STATE_SHIFT 3
#define MAX98926_ALCINFH_STATE_WIDTH 1
#define MAX98926_ALCACT_STATE_MASK (1<<2)
#define MAX98926_ALCACT_STATE_SHIFT 2
#define MAX98926_ALCACT_STATE_WIDTH 1
#define MAX98926_ALCMUT_STATE_MASK (1<<1)
#define MAX98926_ALCMUT_STATE_SHIFT 1
#define MAX98926_ALCMUT_STATE_WIDTH 1
#define MAX98926_ALCP_STATE_MASK (1<<0)
#define MAX98926_ALCP_STATE_SHIFT 0
#define MAX98926_ALCP_STATE_WIDTH 1
/* MAX98926_R007_STATE2 */
#define MAX98926_SLOTOVRN_STATE_MASK (1<<6)
#define MAX98926_SLOTOVRN_STATE_SHIFT 6
#define MAX98926_SLOTOVRN_STATE_WIDTH 1
#define MAX98926_INVALSLOT_STATE_MASK (1<<5)
#define MAX98926_INVALSLOT_STATE_SHIFT 5
#define MAX98926_INVALSLOT_STATE_WIDTH 1
#define MAX98926_SLOTCNFLT_STATE_MASK (1<<4)
#define MAX98926_SLOTCNFLT_STATE_SHIFT 4
#define MAX98926_SLOTCNFLT_STATE_WIDTH 1
#define MAX98926_VBSTOVFL_STATE_MASK (1<<3)
#define MAX98926_VBSTOVFL_STATE_SHIFT 3
#define MAX98926_VBSTOVFL_STATE_WIDTH 1
#define MAX98926_VBATOVFL_STATE_MASK (1<<2)
#define MAX98926_VBATOVFL_STATE_SHIFT 2
#define MAX98926_VBATOVFL_STATE_WIDTH 1
#define MAX98926_IMONOVFL_STATE_MASK (1<<1)
#define MAX98926_IMONOVFL_STATE_SHIFT 1
#define MAX98926_IMONOVFL_STATE_WIDTH 1
#define MAX98926_VMONOVFL_STATE_MASK (1<<0)
#define MAX98926_VMONOVFL_STATE_SHIFT 0
#define MAX98926_VMONOVFL_STATE_WIDTH 1
/* MAX98926_R008_FLAG0 */
#define MAX98926_THERMWARN_END_FLAG_MASK (1<<3)
#define MAX98926_THERMWARN_END_FLAG_SHIFT 3
#define MAX98926_THERMWARN_END_FLAG_WIDTH 1
#define MAX98926_THERMWARN_BGN_FLAG_MASK (1<<2)
#define MAX98926_THERMWARN_BGN_FLAG_SHIFT 2
#define MAX98926_THERMWARN_BGN_FLAG_WIDTH 1
#define MAX98926_THERMSHDN_END_FLAG_MASK (1<<1)
#define MAX98926_THERMSHDN_END_FLAG_SHIFT 1
#define MAX98926_THERMSHDN_END_FLAG_WIDTH 1
#define MAX98926_THERMSHDN_BGN_FLAG_MASK (1<<0)
#define MAX98926_THERMSHDN_BGN_FLAG_SHIFT 0
#define MAX98926_THERMSHDN_BGN_FLAG_WIDTH 1
/* MAX98926_R009_FLAG1 */
#define MAX98926_SPKCURNT_FLAG_MASK (1<<5)
#define MAX98926_SPKCURNT_FLAG_SHIFT 5
#define MAX98926_SPKCURNT_FLAG_WIDTH 1
#define MAX98926_WATCHFAIL_FLAG_MASK (1<<4)
#define MAX98926_WATCHFAIL_FLAG_SHIFT 4
#define MAX98926_WATCHFAIL_FLAG_WIDTH 1
#define MAX98926_ALCINFH_FLAG_MASK (1<<3)
#define MAX98926_ALCINFH_FLAG_SHIFT 3
#define MAX98926_ALCINFH_FLAG_WIDTH 1
#define MAX98926_ALCACT_FLAG_MASK (1<<2)
#define MAX98926_ALCACT_FLAG_SHIFT 2
#define MAX98926_ALCACT_FLAG_WIDTH 1
#define MAX98926_ALCMUT_FLAG_MASK (1<<1)
#define MAX98926_ALCMUT_FLAG_SHIFT 1
#define MAX98926_ALCMUT_FLAG_WIDTH 1
#define MAX98926_ALCP_FLAG_MASK (1<<0)
#define MAX98926_ALCP_FLAG_SHIFT 0
#define MAX98926_ALCP_FLAG_WIDTH 1
/* MAX98926_R00A_FLAG2 */
#define MAX98926_SLOTOVRN_FLAG_MASK (1<<6)
#define MAX98926_SLOTOVRN_FLAG_SHIFT 6
#define MAX98926_SLOTOVRN_FLAG_WIDTH 1
#define MAX98926_INVALSLOT_FLAG_MASK (1<<5)
#define MAX98926_INVALSLOT_FLAG_SHIFT 5
#define MAX98926_INVALSLOT_FLAG_WIDTH 1
#define MAX98926_SLOTCNFLT_FLAG_MASK (1<<4)
#define MAX98926_SLOTCNFLT_FLAG_SHIFT 4
#define MAX98926_SLOTCNFLT_FLAG_WIDTH 1
#define MAX98926_VBSTOVFL_FLAG_MASK (1<<3)
#define MAX98926_VBSTOVFL_FLAG_SHIFT 3
#define MAX98926_VBSTOVFL_FLAG_WIDTH 1
#define MAX98926_VBATOVFL_FLAG_MASK (1<<2)
#define MAX98926_VBATOVFL_FLAG_SHIFT 2
#define MAX98926_VBATOVFL_FLAG_WIDTH 1
#define MAX98926_IMONOVFL_FLAG_MASK (1<<1)
#define MAX98926_IMONOVFL_FLAG_SHIFT 1
#define MAX98926_IMONOVFL_FLAG_WIDTH 1
#define MAX98926_VMONOVFL_FLAG_MASK (1<<0)
#define MAX98926_VMONOVFL_FLAG_SHIFT 0
#define MAX98926_VMONOVFL_FLAG_WIDTH 1
/* MAX98926_R00B_IRQ_ENABLE0 */
#define MAX98926_THERMWARN_END_EN_MASK (1<<3)
#define MAX98926_THERMWARN_END_EN_SHIFT 3
#define MAX98926_THERMWARN_END_EN_WIDTH 1
#define MAX98926_THERMWARN_BGN_EN_MASK (1<<2)
#define MAX98926_THERMWARN_BGN_EN_SHIFT 2
#define MAX98926_THERMWARN_BGN_EN_WIDTH 1
#define MAX98926_THERMSHDN_END_EN_MASK (1<<1)
#define MAX98926_THERMSHDN_END_EN_SHIFT 1
#define MAX98926_THERMSHDN_END_EN_WIDTH 1
#define MAX98926_THERMSHDN_BGN_EN_MASK (1<<0)
#define MAX98926_THERMSHDN_BGN_EN_SHIFT 0
#define MAX98926_THERMSHDN_BGN_EN_WIDTH 1
/* MAX98926_R00C_IRQ_ENABLE1 */
#define MAX98926_SPKCURNT_EN_MASK (1<<5)
#define MAX98926_SPKCURNT_EN_SHIFT 5
#define MAX98926_SPKCURNT_EN_WIDTH 1
#define MAX98926_WATCHFAIL_EN_MASK (1<<4)
#define MAX98926_WATCHFAIL_EN_SHIFT 4
#define MAX98926_WATCHFAIL_EN_WIDTH 1
#define MAX98926_ALCINFH_EN_MASK (1<<3)
#define MAX98926_ALCINFH_EN_SHIFT 3
#define MAX98926_ALCINFH_EN_WIDTH 1
#define MAX98926_ALCACT_EN_MASK (1<<2)
#define MAX98926_ALCACT_EN_SHIFT 2
#define MAX98926_ALCACT_EN_WIDTH 1
#define MAX98926_ALCMUT_EN_MASK (1<<1)
#define MAX98926_ALCMUT_EN_SHIFT 1
#define MAX98926_ALCMUT_EN_WIDTH 1
#define MAX98926_ALCP_EN_MASK (1<<0)
#define MAX98926_ALCP_EN_SHIFT 0
#define MAX98926_ALCP_EN_WIDTH 1
/* MAX98926_R00D_IRQ_ENABLE2 */
#define MAX98926_SLOTOVRN_EN_MASK (1<<6)
#define MAX98926_SLOTOVRN_EN_SHIFT 6
#define MAX98926_SLOTOVRN_EN_WIDTH 1
#define MAX98926_INVALSLOT_EN_MASK (1<<5)
#define MAX98926_INVALSLOT_EN_SHIFT 5
#define MAX98926_INVALSLOT_EN_WIDTH 1
#define MAX98926_SLOTCNFLT_EN_MASK (1<<4)
#define MAX98926_SLOTCNFLT_EN_SHIFT 4
#define MAX98926_SLOTCNFLT_EN_WIDTH 1
#define MAX98926_VBSTOVFL_EN_MASK (1<<3)
#define MAX98926_VBSTOVFL_EN_SHIFT 3
#define MAX98926_VBSTOVFL_EN_WIDTH 1
#define MAX98926_VBATOVFL_EN_MASK (1<<2)
#define MAX98926_VBATOVFL_EN_SHIFT 2
#define MAX98926_VBATOVFL_EN_WIDTH 1
#define MAX98926_IMONOVFL_EN_MASK (1<<1)
#define MAX98926_IMONOVFL_EN_SHIFT 1
#define MAX98926_IMONOVFL_EN_WIDTH 1
#define MAX98926_VMONOVFL_EN_MASK (1<<0)
#define MAX98926_VMONOVFL_EN_SHIFT 0
#define MAX98926_VMONOVFL_EN_WIDTH 1
/* MAX98926_R00E_IRQ_CLEAR0 */
#define MAX98926_THERMWARN_END_CLR_MASK (1<<3)
#define MAX98926_THERMWARN_END_CLR_SHIFT 3
#define MAX98926_THERMWARN_END_CLR_WIDTH 1
#define MAX98926_THERMWARN_BGN_CLR_MASK (1<<2)
#define MAX98926_THERMWARN_BGN_CLR_SHIFT 2
#define MAX98926_THERMWARN_BGN_CLR_WIDTH 1
#define MAX98926_THERMSHDN_END_CLR_MASK (1<<1)
#define MAX98926_THERMSHDN_END_CLR_SHIFT 1
#define MAX98926_THERMSHDN_END_CLR_WIDTH 1
#define MAX98926_THERMSHDN_BGN_CLR_MASK (1<<0)
#define MAX98926_THERMSHDN_BGN_CLR_SHIFT 0
#define MAX98926_THERMSHDN_BGN_CLR_WIDTH 1
/* MAX98926_R00F_IRQ_CLEAR1 */
#define MAX98926_SPKCURNT_CLR_MASK (1<<5)
#define MAX98926_SPKCURNT_CLR_SHIFT 5
#define MAX98926_SPKCURNT_CLR_WIDTH 1
#define MAX98926_WATCHFAIL_CLR_MASK (1<<4)
#define MAX98926_WATCHFAIL_CLR_SHIFT 4
#define MAX98926_WATCHFAIL_CLR_WIDTH 1
#define MAX98926_ALCINFH_CLR_MASK (1<<3)
#define MAX98926_ALCINFH_CLR_SHIFT 3
#define MAX98926_ALCINFH_CLR_WIDTH 1
#define MAX98926_ALCACT_CLR_MASK (1<<2)
#define MAX98926_ALCACT_CLR_SHIFT 2
#define MAX98926_ALCACT_CLR_WIDTH 1
#define MAX98926_ALCMUT_CLR_MASK (1<<1)
#define MAX98926_ALCMUT_CLR_SHIFT 1
#define MAX98926_ALCMUT_CLR_WIDTH 1
#define MAX98926_ALCP_CLR_MASK (1<<0)
#define MAX98926_ALCP_CLR_SHIFT 0
#define MAX98926_ALCP_CLR_WIDTH 1
/* MAX98926_R010_IRQ_CLEAR2 */
#define MAX98926_SLOTOVRN_CLR_MASK (1<<6)
#define MAX98926_SLOTOVRN_CLR_SHIFT 6
#define MAX98926_SLOTOVRN_CLR_WIDTH 1
#define MAX98926_INVALSLOT_CLR_MASK (1<<5)
#define MAX98926_INVALSLOT_CLR_SHIFT 5
#define MAX98926_INVALSLOT_CLR_WIDTH 1
#define MAX98926_SLOTCNFLT_CLR_MASK (1<<4)
#define MAX98926_SLOTCNFLT_CLR_SHIFT 4
#define MAX98926_SLOTCNFLT_CLR_WIDTH 1
#define MAX98926_VBSTOVFL_CLR_MASK (1<<3)
#define MAX98926_VBSTOVFL_CLR_SHIFT 3
#define MAX98926_VBSTOVFL_CLR_WIDTH 1
#define MAX98926_VBATOVFL_CLR_MASK (1<<2)
#define MAX98926_VBATOVFL_CLR_SHIFT 2
#define MAX98926_VBATOVFL_CLR_WIDTH 1
#define MAX98926_IMONOVFL_CLR_MASK (1<<1)
#define MAX98926_IMONOVFL_CLR_SHIFT 1
#define MAX98926_IMONOVFL_CLR_WIDTH 1
#define MAX98926_VMONOVFL_CLR_MASK (1<<0)
#define MAX98926_VMONOVFL_CLR_SHIFT 0
#define MAX98926_VMONOVFL_CLR_WIDTH 1
/* MAX98926_R011_MAP0 */
#define MAX98926_ER_THERMWARN_EN_MASK (1<<7)
#define MAX98926_ER_THERMWARN_EN_SHIFT 7
#define MAX98926_ER_THERMWARN_EN_WIDTH 1
#define MAX98926_ER_THERMWARN_MAP_MASK (0x07<<4)
#define MAX98926_ER_THERMWARN_MAP_SHIFT 4
#define MAX98926_ER_THERMWARN_MAP_WIDTH 3
/* MAX98926_R012_MAP1 */
#define MAX98926_ER_ALCMUT_EN_MASK (1<<7)
#define MAX98926_ER_ALCMUT_EN_SHIFT 7
#define MAX98926_ER_ALCMUT_EN_WIDTH 1
#define MAX98926_ER_ALCMUT_MAP_MASK (0x07<<4)
#define MAX98926_ER_ALCMUT_MAP_SHIFT 4
#define MAX98926_ER_ALCMUT_MAP_WIDTH 3
#define MAX98926_ER_ALCP_EN_MASK (1<<3)
#define MAX98926_ER_ALCP_EN_SHIFT 3
#define MAX98926_ER_ALCP_EN_WIDTH 1
#define MAX98926_ER_ALCP_MAP_MASK (0x07<<0)
#define MAX98926_ER_ALCP_MAP_SHIFT 0
#define MAX98926_ER_ALCP_MAP_WIDTH 3
/* MAX98926_R013_MAP2 */
#define MAX98926_ER_ALCINFH_EN_MASK (1<<7)
#define MAX98926_ER_ALCINFH_EN_SHIFT 7
#define MAX98926_ER_ALCINFH_EN_WIDTH 1
#define MAX98926_ER_ALCINFH_MAP_MASK (0x07<<4)
#define MAX98926_ER_ALCINFH_MAP_SHIFT 4
#define MAX98926_ER_ALCINFH_MAP_WIDTH 3
#define MAX98926_ER_ALCACT_EN_MASK (1<<3)
#define MAX98926_ER_ALCACT_EN_SHIFT 3
#define MAX98926_ER_ALCACT_EN_WIDTH 1
#define MAX98926_ER_ALCACT_MAP_MASK (0x07<<0)
#define MAX98926_ER_ALCACT_MAP_SHIFT 0
#define MAX98926_ER_ALCACT_MAP_WIDTH 3
/* MAX98926_R014_MAP3 */
#define MAX98926_ER_SPKCURNT_EN_MASK (1<<7)
#define MAX98926_ER_SPKCURNT_EN_SHIFT 7
#define MAX98926_ER_SPKCURNT_EN_WIDTH 1
#define MAX98926_ER_SPKCURNT_MAP_MASK (0x07<<4)
#define MAX98926_ER_SPKCURNT_MAP_SHIFT 4
#define MAX98926_ER_SPKCURNT_MAP_WIDTH 3
/* MAX98926_R015_MAP4 */
/* RESERVED */
/* MAX98926_R016_MAP5 */
#define MAX98926_ER_IMONOVFL_EN_MASK (1<<7)
#define MAX98926_ER_IMONOVFL_EN_SHIFT 7
#define MAX98926_ER_IMONOVFL_EN_WIDTH 1
#define MAX98926_ER_IMONOVFL_MAP_MASK (0x07<<4)
#define MAX98926_ER_IMONOVFL_MAP_SHIFT 4
#define MAX98926_ER_IMONOVFL_MAP_WIDTH 3
#define MAX98926_ER_VMONOVFL_EN_MASK (1<<3)
#define MAX98926_ER_VMONOVFL_EN_SHIFT 3
#define MAX98926_ER_VMONOVFL_EN_WIDTH 1
#define MAX98926_ER_VMONOVFL_MAP_MASK (0x07<<0)
#define MAX98926_ER_VMONOVFL_MAP_SHIFT 0
#define MAX98926_ER_VMONOVFL_MAP_WIDTH 3
/* MAX98926_R017_MAP6 */
#define MAX98926_ER_VBSTOVFL_EN_MASK (1<<7)
#define MAX98926_ER_VBSTOVFL_EN_SHIFT 7
#define MAX98926_ER_VBSTOVFL_EN_WIDTH 1
#define MAX98926_ER_VBSTOVFL_MAP_MASK (0x07<<4)
#define MAX98926_ER_VBSTOVFL_MAP_SHIFT 4
#define MAX98926_ER_VBSTOVFL_MAP_WIDTH 3
#define MAX98926_ER_VBATOVFL_EN_MASK (1<<3)
#define MAX98926_ER_VBATOVFL_EN_SHIFT 3
#define MAX98926_ER_VBATOVFL_EN_WIDTH 1
#define MAX98926_ER_VBATOVFL_MAP_MASK (0x07<<0)
#define MAX98926_ER_VBATOVFL_MAP_SHIFT 0
#define MAX98926_ER_VBATOVFL_MAP_WIDTH 3
/* MAX98926_R018_MAP7 */
#define MAX98926_ER_INVALSLOT_EN_MASK (1<<7)
#define MAX98926_ER_INVALSLOT_EN_SHIFT 7
#define MAX98926_ER_INVALSLOT_EN_WIDTH 1
#define MAX98926_ER_INVALSLOT_MAP_MASK (0x07<<4)
#define MAX98926_ER_INVALSLOT_MAP_SHIFT 4
#define MAX98926_ER_INVALSLOT_MAP_WIDTH 3
#define MAX98926_ER_SLOTCNFLT_EN_MASK (1<<3)
#define MAX98926_ER_SLOTCNFLT_EN_SHIFT 3
#define MAX98926_ER_SLOTCNFLT_EN_WIDTH 1
#define MAX98926_ER_SLOTCNFLT_MAP_MASK (0x07<<0)
#define MAX98926_ER_SLOTCNFLT_MAP_SHIFT 0
#define MAX98926_ER_SLOTCNFLT_MAP_WIDTH 3
/* MAX98926_R019_MAP8 */
#define MAX98926_ER_SLOTOVRN_EN_MASK (1<<3)
#define MAX98926_ER_SLOTOVRN_EN_SHIFT 3
#define MAX98926_ER_SLOTOVRN_EN_WIDTH 1
#define MAX98926_ER_SLOTOVRN_MAP_MASK (0x07<<0)
#define MAX98926_ER_SLOTOVRN_MAP_SHIFT 0
#define MAX98926_ER_SLOTOVRN_MAP_WIDTH 3
/* MAX98926_R01A_DAI_CLK_MODE1 */
#define MAX98926_DAI_CLK_SOURCE_MASK (1<<6)
#define MAX98926_DAI_CLK_SOURCE_SHIFT 6
#define MAX98926_DAI_CLK_SOURCE_WIDTH 1
#define MAX98926_MDLL_MULT_MASK (0x0F<<0)
#define MAX98926_MDLL_MULT_SHIFT 0
#define MAX98926_MDLL_MULT_WIDTH 4
#define MAX98926_MDLL_MULT_MCLKx8 6
#define MAX98926_MDLL_MULT_MCLKx16 8
/* MAX98926_R01B_DAI_CLK_MODE2 */
#define MAX98926_DAI_SR_MASK (0x0F<<4)
#define MAX98926_DAI_SR_SHIFT 4
#define MAX98926_DAI_SR_WIDTH 4
#define MAX98926_DAI_MAS_MASK (1<<3)
#define MAX98926_DAI_MAS_SHIFT 3
#define MAX98926_DAI_MAS_WIDTH 1
#define MAX98926_DAI_BSEL_MASK (0x07<<0)
#define MAX98926_DAI_BSEL_SHIFT 0
#define MAX98926_DAI_BSEL_WIDTH 3
#define MAX98926_DAI_BSEL_32 (0 << MAX98926_DAI_BSEL_SHIFT)
#define MAX98926_DAI_BSEL_48 (1 << MAX98926_DAI_BSEL_SHIFT)
#define MAX98926_DAI_BSEL_64 (2 << MAX98926_DAI_BSEL_SHIFT)
#define MAX98926_DAI_BSEL_256 (6 << MAX98926_DAI_BSEL_SHIFT)
/* MAX98926_R01C_DAI_CLK_DIV_M_MSBS */
#define MAX98926_DAI_M_MSBS_MASK (0xFF<<0)
#define MAX98926_DAI_M_MSBS_SHIFT 0
#define MAX98926_DAI_M_MSBS_WIDTH 8
/* MAX98926_R01D_DAI_CLK_DIV_M_LSBS */
#define MAX98926_DAI_M_LSBS_MASK (0xFF<<0)
#define MAX98926_DAI_M_LSBS_SHIFT 0
#define MAX98926_DAI_M_LSBS_WIDTH 8
/* MAX98926_R01E_DAI_CLK_DIV_N_MSBS */
#define MAX98926_DAI_N_MSBS_MASK (0x7F<<0)
#define MAX98926_DAI_N_MSBS_SHIFT 0
#define MAX98926_DAI_N_MSBS_WIDTH 7
/* MAX98926_R01F_DAI_CLK_DIV_N_LSBS */
#define MAX98926_DAI_N_LSBS_MASK (0xFF<<0)
#define MAX98926_DAI_N_LSBS_SHIFT 0
#define MAX98926_DAI_N_LSBS_WIDTH 8
/* MAX98926_R020_FORMAT */
#define MAX98926_DAI_CHANSZ_MASK (0x03<<6)
#define MAX98926_DAI_CHANSZ_SHIFT 6
#define MAX98926_DAI_CHANSZ_WIDTH 2
#define MAX98926_DAI_INTERLEAVE_MASK (1<<5)
#define MAX98926_DAI_INTERLEAVE_SHIFT 5
#define MAX98926_DAI_INTERLEAVE_WIDTH 1
#define MAX98926_DAI_EXTBCLK_HIZ_MASK (1<<4)
#define MAX98926_DAI_EXTBCLK_HIZ_SHIFT 4
#define MAX98926_DAI_EXTBCLK_HIZ_WIDTH 1
#define MAX98926_DAI_WCI_MASK (1<<3)
#define MAX98926_DAI_WCI_SHIFT 3
#define MAX98926_DAI_WCI_WIDTH 1
#define MAX98926_DAI_BCI_MASK (1<<2)
#define MAX98926_DAI_BCI_SHIFT 2
#define MAX98926_DAI_BCI_WIDTH 1
#define MAX98926_DAI_DLY_MASK (1<<1)
#define MAX98926_DAI_DLY_SHIFT 1
#define MAX98926_DAI_DLY_WIDTH 1
#define MAX98926_DAI_TDM_MASK (1<<0)
#define MAX98926_DAI_TDM_SHIFT 0
#define MAX98926_DAI_TDM_WIDTH 1
#define MAX98926_DAI_CHANSZ_16 (1 << MAX98926_DAI_CHANSZ_SHIFT)
#define MAX98926_DAI_CHANSZ_24 (2 << MAX98926_DAI_CHANSZ_SHIFT)
#define MAX98926_DAI_CHANSZ_32 (3 << MAX98926_DAI_CHANSZ_SHIFT)
/* MAX98926_R021_TDM_SLOT_SELECT */
#define MAX98926_DAI_DO_EN_MASK (1<<7)
#define MAX98926_DAI_DO_EN_SHIFT 7
#define MAX98926_DAI_DO_EN_WIDTH 1
#define MAX98926_DAI_DIN_EN_MASK (1<<6)
#define MAX98926_DAI_DIN_EN_SHIFT 6
#define MAX98926_DAI_DIN_EN_WIDTH 1
#define MAX98926_DAI_INR_SOURCE_MASK (0x07<<3)
#define MAX98926_DAI_INR_SOURCE_SHIFT 3
#define MAX98926_DAI_INR_SOURCE_WIDTH 3
#define MAX98926_DAI_INL_SOURCE_MASK (0x07<<0)
#define MAX98926_DAI_INL_SOURCE_SHIFT 0
#define MAX98926_DAI_INL_SOURCE_WIDTH 3
/* MAX98926_R022_DOUT_CFG_VMON */
#define MAX98926_DAI_VMON_EN_MASK (1<<5)
#define MAX98926_DAI_VMON_EN_SHIFT 5
#define MAX98926_DAI_VMON_EN_WIDTH 1
#define MAX98926_DAI_VMON_SLOT_MASK (0x1F<<0)
#define MAX98926_DAI_VMON_SLOT_SHIFT 0
#define MAX98926_DAI_VMON_SLOT_WIDTH 5
#define MAX98926_DAI_VMON_SLOT_00_01 (0 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_01_02 (1 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_02_03 (2 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_03_04 (3 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_04_05 (4 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_05_06 (5 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_06_07 (6 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_07_08 (7 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_08_09 (8 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_09_0A (9 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0A_0B (10 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0B_0C (11 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0C_0D (12 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0D_0E (13 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0E_0F (14 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_0F_10 (15 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_10_11 (16 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_11_12 (17 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_12_13 (18 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_13_14 (19 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_14_15 (20 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_15_16 (21 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_16_17 (22 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_17_18 (23 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_18_19 (24 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_19_1A (25 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_1A_1B (26 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_1B_1C (27 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_1C_1D (28 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_1D_1E (29 << MAX98926_DAI_VMON_SLOT_SHIFT)
#define MAX98926_DAI_VMON_SLOT_1E_1F (30 << MAX98926_DAI_VMON_SLOT_SHIFT)
/* MAX98926_R023_DOUT_CFG_IMON */
#define MAX98926_DAI_IMON_EN_MASK (1<<5)
#define MAX98926_DAI_IMON_EN_SHIFT 5
#define MAX98926_DAI_IMON_EN_WIDTH 1
#define MAX98926_DAI_IMON_SLOT_MASK (0x1F<<0)
#define MAX98926_DAI_IMON_SLOT_SHIFT 0
#define MAX98926_DAI_IMON_SLOT_WIDTH 5
#define MAX98926_DAI_IMON_SLOT_00_01 (0 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_01_02 (1 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_02_03 (2 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_03_04 (3 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_04_05 (4 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_05_06 (5 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_06_07 (6 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_07_08 (7 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_08_09 (8 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_09_0A (9 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0A_0B (10 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0B_0C (11 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0C_0D (12 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0D_0E (13 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0E_0F (14 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_0F_10 (15 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_10_11 (16 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_11_12 (17 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_12_13 (18 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_13_14 (19 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_14_15 (20 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_15_16 (21 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_16_17 (22 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_17_18 (23 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_18_19 (24 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_19_1A (25 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_1A_1B (26 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_1B_1C (27 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_1C_1D (28 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_1D_1E (29 << MAX98926_DAI_IMON_SLOT_SHIFT)
#define MAX98926_DAI_IMON_SLOT_1E_1F (30 << MAX98926_DAI_IMON_SLOT_SHIFT)
/* MAX98926_R024_DOUT_CFG_VBAT */
#define MAX98926_DAI_INTERLEAVE_SLOT_MASK (0x1F<<0)
#define MAX98926_DAI_INTERLEAVE_SLOT_SHIFT 0
#define MAX98926_DAI_INTERLEAVE_SLOT_WIDTH 5
/* MAX98926_R025_DOUT_CFG_VBST */
#define MAX98926_DAI_VBST_EN_MASK (1<<5)
#define MAX98926_DAI_VBST_EN_SHIFT 5
#define MAX98926_DAI_VBST_EN_WIDTH 1
#define MAX98926_DAI_VBST_SLOT_MASK (0x1F<<0)
#define MAX98926_DAI_VBST_SLOT_SHIFT 0
#define MAX98926_DAI_VBST_SLOT_WIDTH 5
/* MAX98926_R026_DOUT_CFG_FLAG */
#define MAX98926_DAI_FLAG_EN_MASK (1<<5)
#define MAX98926_DAI_FLAG_EN_SHIFT 5
#define MAX98926_DAI_FLAG_EN_WIDTH 1
#define MAX98926_DAI_FLAG_SLOT_MASK (0x1F<<0)
#define MAX98926_DAI_FLAG_SLOT_SHIFT 0
#define MAX98926_DAI_FLAG_SLOT_WIDTH 5
/* MAX98926_R027_DOUT_HIZ_CFG1 */
#define MAX98926_DAI_SLOT_HIZ_CFG1_MASK (0xFF<<0)
#define MAX98926_DAI_SLOT_HIZ_CFG1_SHIFT 0
#define MAX98926_DAI_SLOT_HIZ_CFG1_WIDTH 8
/* MAX98926_R028_DOUT_HIZ_CFG2 */
#define MAX98926_DAI_SLOT_HIZ_CFG2_MASK (0xFF<<0)
#define MAX98926_DAI_SLOT_HIZ_CFG2_SHIFT 0
#define MAX98926_DAI_SLOT_HIZ_CFG2_WIDTH 8
/* MAX98926_R029_DOUT_HIZ_CFG3 */
#define MAX98926_DAI_SLOT_HIZ_CFG3_MASK (0xFF<<0)
#define MAX98926_DAI_SLOT_HIZ_CFG3_SHIFT 0
#define MAX98926_DAI_SLOT_HIZ_CFG3_WIDTH 8
/* MAX98926_R02A_DOUT_HIZ_CFG4 */
#define MAX98926_DAI_SLOT_HIZ_CFG4_MASK (0xFF<<0)
#define MAX98926_DAI_SLOT_HIZ_CFG4_SHIFT 0
#define MAX98926_DAI_SLOT_HIZ_CFG4_WIDTH 8
/* MAX98926_R02B_DOUT_DRV_STRENGTH */
#define MAX98926_DAI_OUT_DRIVE_MASK (0x03<<0)
#define MAX98926_DAI_OUT_DRIVE_SHIFT 0
#define MAX98926_DAI_OUT_DRIVE_WIDTH 2
/* MAX98926_R02C_FILTERS */
#define MAX98926_ADC_DITHER_EN_MASK (1<<7)
#define MAX98926_ADC_DITHER_EN_SHIFT 7
#define MAX98926_ADC_DITHER_EN_WIDTH 1
#define MAX98926_IV_DCB_EN_MASK (1<<6)
#define MAX98926_IV_DCB_EN_SHIFT 6
#define MAX98926_IV_DCB_EN_WIDTH 1
#define MAX98926_DAC_DITHER_EN_MASK (1<<4)
#define MAX98926_DAC_DITHER_EN_SHIFT 4
#define MAX98926_DAC_DITHER_EN_WIDTH 1
#define MAX98926_DAC_FILTER_MODE_MASK (1<<3)
#define MAX98926_DAC_FILTER_MODE_SHIFT 3
#define MAX98926_DAC_FILTER_MODE_WIDTH 1
#define MAX98926_DAC_HPF_MASK (0x07<<0)
#define MAX98926_DAC_HPF_SHIFT 0
#define MAX98926_DAC_HPF_WIDTH 3
#define MAX98926_DAC_HPF_DISABLE (0 << MAX98926_DAC_HPF_SHIFT)
#define MAX98926_DAC_HPF_DC_BLOCK (1 << MAX98926_DAC_HPF_SHIFT)
#define MAX98926_DAC_HPF_EN_100 (2 << MAX98926_DAC_HPF_SHIFT)
#define MAX98926_DAC_HPF_EN_200 (3 << MAX98926_DAC_HPF_SHIFT)
#define MAX98926_DAC_HPF_EN_400 (4 << MAX98926_DAC_HPF_SHIFT)
#define MAX98926_DAC_HPF_EN_800 (5 << MAX98926_DAC_HPF_SHIFT)
/* MAX98926_R02D_GAIN */
#define MAX98926_DAC_IN_SEL_MASK (0x03<<5)
#define MAX98926_DAC_IN_SEL_SHIFT 5
#define MAX98926_DAC_IN_SEL_WIDTH 2
#define MAX98926_SPK_GAIN_MASK (0x1F<<0)
#define MAX98926_SPK_GAIN_SHIFT 0
#define MAX98926_SPK_GAIN_WIDTH 5
#define MAX98926_DAC_IN_SEL_LEFT_DAI (0 << MAX98926_DAC_IN_SEL_SHIFT)
#define MAX98926_DAC_IN_SEL_RIGHT_DAI (1 << MAX98926_DAC_IN_SEL_SHIFT)
#define MAX98926_DAC_IN_SEL_SUMMED_DAI (2 << MAX98926_DAC_IN_SEL_SHIFT)
#define MAX98926_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << MAX98926_DAC_IN_SEL_SHIFT)
/* MAX98926_R02E_GAIN_RAMPING */
#define MAX98926_SPK_RMP_EN_MASK (1<<1)
#define MAX98926_SPK_RMP_EN_SHIFT 1
#define MAX98926_SPK_RMP_EN_WIDTH 1
#define MAX98926_SPK_ZCD_EN_MASK (1<<0)
#define MAX98926_SPK_ZCD_EN_SHIFT 0
#define MAX98926_SPK_ZCD_EN_WIDTH 1
/* MAX98926_R02F_SPK_AMP */
#define MAX98926_SPK_MODE_MASK (1<<0)
#define MAX98926_SPK_MODE_SHIFT 0
#define MAX98926_SPK_MODE_WIDTH 1
#define MAX98926_INSELECT_MODE_MASK (1<<1)
#define MAX98926_INSELECT_MODE_SHIFT 1
#define MAX98926_INSELECT_MODE_WIDTH 1
/* MAX98926_R030_THRESHOLD */
#define MAX98926_ALC_EN_MASK (1<<5)
#define MAX98926_ALC_EN_SHIFT 5
#define MAX98926_ALC_EN_WIDTH 1
#define MAX98926_ALC_TH_MASK (0x1F<<0)
#define MAX98926_ALC_TH_SHIFT 0
#define MAX98926_ALC_TH_WIDTH 5
/* MAX98926_R031_ALC_ATTACK */
#define MAX98926_ALC_ATK_STEP_MASK (0x0F<<4)
#define MAX98926_ALC_ATK_STEP_SHIFT 4
#define MAX98926_ALC_ATK_STEP_WIDTH 4
#define MAX98926_ALC_ATK_RATE_MASK (0x7<<0)
#define MAX98926_ALC_ATK_RATE_SHIFT 0
#define MAX98926_ALC_ATK_RATE_WIDTH 3
/* MAX98926_R032_ALC_ATTEN_RLS */
#define MAX98926_ALC_MAX_ATTEN_MASK (0x0F<<4)
#define MAX98926_ALC_MAX_ATTEN_SHIFT 4
#define MAX98926_ALC_MAX_ATTEN_WIDTH 4
#define MAX98926_ALC_RLS_RATE_MASK (0x7<<0)
#define MAX98926_ALC_RLS_RATE_SHIFT 0
#define MAX98926_ALC_RLS_RATE_WIDTH 3
/* MAX98926_R033_ALC_HOLD_RLS */
#define MAX98926_ALC_RLS_TGR_MASK (1<<0)
#define MAX98926_ALC_RLS_TGR_SHIFT 0
#define MAX98926_ALC_RLS_TGR_WIDTH 1
/* MAX98926_R034_ALC_CONFIGURATION */
#define MAX98926_ALC_MUTE_EN_MASK (1<<7)
#define MAX98926_ALC_MUTE_EN_SHIFT 7
#define MAX98926_ALC_MUTE_EN_WIDTH 1
#define MAX98926_ALC_MUTE_DLY_MASK (0x07<<4)
#define MAX98926_ALC_MUTE_DLY_SHIFT 4
#define MAX98926_ALC_MUTE_DLY_WIDTH 3
#define MAX98926_ALC_RLS_DBT_MASK (0x07<<0)
#define MAX98926_ALC_RLS_DBT_SHIFT 0
#define MAX98926_ALC_RLS_DBT_WIDTH 3
/* MAX98926_R035_BOOST_CONVERTER */
#define MAX98926_BST_SYNC_MASK (1<<7)
#define MAX98926_BST_SYNC_SHIFT 7
#define MAX98926_BST_SYNC_WIDTH 1
#define MAX98926_BST_PHASE_MASK (0x03<<4)
#define MAX98926_BST_PHASE_SHIFT 4
#define MAX98926_BST_PHASE_WIDTH 2
#define MAX98926_BST_SKIP_MODE_MASK (0x03<<0)
#define MAX98926_BST_SKIP_MODE_SHIFT 0
#define MAX98926_BST_SKIP_MODE_WIDTH 2
/* MAX98926_R036_BLOCK_ENABLE */
#define MAX98926_BST_EN_MASK (1<<7)
#define MAX98926_BST_EN_SHIFT 7
#define MAX98926_BST_EN_WIDTH 1
#define MAX98926_WATCH_EN_MASK (1<<6)
#define MAX98926_WATCH_EN_SHIFT 6
#define MAX98926_WATCH_EN_WIDTH 1
#define MAX98926_CLKMON_EN_MASK (1<<5)
#define MAX98926_CLKMON_EN_SHIFT 5
#define MAX98926_CLKMON_EN_WIDTH 1
#define MAX98926_SPK_EN_MASK (1<<4)
#define MAX98926_SPK_EN_SHIFT 4
#define MAX98926_SPK_EN_WIDTH 1
#define MAX98926_ADC_VBST_EN_MASK (1<<3)
#define MAX98926_ADC_VBST_EN_SHIFT 3
#define MAX98926_ADC_VBST_EN_WIDTH 1
#define MAX98926_ADC_VBAT_EN_MASK (1<<2)
#define MAX98926_ADC_VBAT_EN_SHIFT 2
#define MAX98926_ADC_VBAT_EN_WIDTH 1
#define MAX98926_ADC_IMON_EN_MASK (1<<1)
#define MAX98926_ADC_IMON_EN_SHIFT 1
#define MAX98926_ADC_IMON_EN_WIDTH 1
#define MAX98926_ADC_VMON_EN_MASK (1<<0)
#define MAX98926_ADC_VMON_EN_SHIFT 0
#define MAX98926_ADC_VMON_EN_WIDTH 1
/* MAX98926_R037_CONFIGURATION */
#define MAX98926_BST_VOUT_MASK (0x0F<<4)
#define MAX98926_BST_VOUT_SHIFT 4
#define MAX98926_BST_VOUT_WIDTH 4
#define MAX98926_THERMWARN_LEVEL_MASK (0x03<<2)
#define MAX98926_THERMWARN_LEVEL_SHIFT 2
#define MAX98926_THERMWARN_LEVEL_WIDTH 2
#define MAX98926_WATCH_TIME_MASK (0x03<<0)
#define MAX98926_WATCH_TIME_SHIFT 0
#define MAX98926_WATCH_TIME_WIDTH 2
/* MAX98926_R038_GLOBAL_ENABLE */
#define MAX98926_EN_MASK (1<<7)
#define MAX98926_EN_SHIFT 7
#define MAX98926_EN_WIDTH 1
/* MAX98926_R03A_BOOST_LIMITER */
#define MAX98926_BST_ILIM_MASK (0xF<<4)
#define MAX98926_BST_ILIM_SHIFT 4
#define MAX98926_BST_ILIM_WIDTH 4
/* MAX98926_R0FF_VERSION */
#define MAX98926_REV_ID_MASK (0xFF<<0)
#define MAX98926_REV_ID_SHIFT 0
#define MAX98926_REV_ID_WIDTH 8
struct max98926_priv {
struct regmap *regmap;
struct snd_soc_codec *codec;
unsigned int sysclk;
unsigned int v_slot;
unsigned int i_slot;
unsigned int ch_size;
unsigned int interleave_mode;
};
#endif
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
...@@ -919,7 +920,7 @@ static int fsl_sai_resume(struct device *dev) ...@@ -919,7 +920,7 @@ static int fsl_sai_resume(struct device *dev)
regcache_cache_only(sai->regmap, false); regcache_cache_only(sai->regmap, false);
regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
msleep(1); usleep_range(1000, 2000);
regmap_write(sai->regmap, FSL_SAI_TCSR, 0); regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
regmap_write(sai->regmap, FSL_SAI_RCSR, 0); regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
return regcache_sync(sai->regmap); return regcache_sync(sai->regmap);
......
...@@ -112,20 +112,6 @@ struct fsl_ssi_rxtx_reg_val { ...@@ -112,20 +112,6 @@ struct fsl_ssi_rxtx_reg_val {
struct fsl_ssi_reg_val tx; struct fsl_ssi_reg_val tx;
}; };
static const struct reg_default fsl_ssi_reg_defaults[] = {
{CCSR_SSI_SCR, 0x00000000},
{CCSR_SSI_SIER, 0x00003003},
{CCSR_SSI_STCR, 0x00000200},
{CCSR_SSI_SRCR, 0x00000200},
{CCSR_SSI_STCCR, 0x00040000},
{CCSR_SSI_SRCCR, 0x00040000},
{CCSR_SSI_SACNT, 0x00000000},
{CCSR_SSI_STMSK, 0x00000000},
{CCSR_SSI_SRMSK, 0x00000000},
{CCSR_SSI_SACCEN, 0x00000000},
{CCSR_SSI_SACCDIS, 0x00000000},
};
static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg) static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
...@@ -190,8 +176,7 @@ static const struct regmap_config fsl_ssi_regconfig = { ...@@ -190,8 +176,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.val_format_endian = REGMAP_ENDIAN_NATIVE, .val_format_endian = REGMAP_ENDIAN_NATIVE,
.reg_defaults = fsl_ssi_reg_defaults, .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1,
.num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
.readable_reg = fsl_ssi_readable_reg, .readable_reg = fsl_ssi_readable_reg,
.volatile_reg = fsl_ssi_volatile_reg, .volatile_reg = fsl_ssi_volatile_reg,
.precious_reg = fsl_ssi_precious_reg, .precious_reg = fsl_ssi_precious_reg,
...@@ -201,6 +186,7 @@ static const struct regmap_config fsl_ssi_regconfig = { ...@@ -201,6 +186,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
struct fsl_ssi_soc_data { struct fsl_ssi_soc_data {
bool imx; bool imx;
bool imx21regs; /* imx21-class SSI - no SACC{ST,EN,DIS} regs */
bool offline_config; bool offline_config;
u32 sisr_write_mask; u32 sisr_write_mask;
}; };
...@@ -303,6 +289,7 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = { ...@@ -303,6 +289,7 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
static struct fsl_ssi_soc_data fsl_ssi_imx21 = { static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
.imx = true, .imx = true,
.imx21regs = true,
.offline_config = true, .offline_config = true,
.sisr_write_mask = 0, .sisr_write_mask = 0,
}; };
...@@ -586,8 +573,12 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) ...@@ -586,8 +573,12 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
*/ */
regmap_write(regs, CCSR_SSI_SACNT, regmap_write(regs, CCSR_SSI_SACNT,
CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV); CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
regmap_write(regs, CCSR_SSI_SACCEN, 0x300); /* no SACC{ST,EN,DIS} regs on imx21-class SSI */
if (!ssi_private->soc->imx21regs) {
regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
}
/* /*
* Enable SSI, Transmit and Receive. AC97 has to communicate with the * Enable SSI, Transmit and Receive. AC97 has to communicate with the
...@@ -1397,6 +1388,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -1397,6 +1388,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
void __iomem *iomem; void __iomem *iomem;
char name[64]; char name[64];
struct regmap_config regconfig = fsl_ssi_regconfig;
of_id = of_match_device(fsl_ssi_ids, &pdev->dev); of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
if (!of_id || !of_id->data) if (!of_id || !of_id->data)
...@@ -1444,15 +1436,25 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -1444,15 +1436,25 @@ static int fsl_ssi_probe(struct platform_device *pdev)
return PTR_ERR(iomem); return PTR_ERR(iomem);
ssi_private->ssi_phys = res->start; ssi_private->ssi_phys = res->start;
if (ssi_private->soc->imx21regs) {
/*
* According to datasheet imx21-class SSI
* don't have SACC{ST,EN,DIS} regs.
*/
regconfig.max_register = CCSR_SSI_SRMSK;
regconfig.num_reg_defaults_raw =
CCSR_SSI_SRMSK / sizeof(uint32_t) + 1;
}
ret = of_property_match_string(np, "clock-names", "ipg"); ret = of_property_match_string(np, "clock-names", "ipg");
if (ret < 0) { if (ret < 0) {
ssi_private->has_ipg_clk_name = false; ssi_private->has_ipg_clk_name = false;
ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
&fsl_ssi_regconfig); &regconfig);
} else { } else {
ssi_private->has_ipg_clk_name = true; ssi_private->has_ipg_clk_name = true;
ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev, ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev,
"ipg", iomem, &fsl_ssi_regconfig); "ipg", iomem, &regconfig);
} }
if (IS_ERR(ssi_private->regs)) { if (IS_ERR(ssi_private->regs)) {
dev_err(&pdev->dev, "Failed to init register map\n"); dev_err(&pdev->dev, "Failed to init register map\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment