Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/cs42l56', 'asoc/topic/cs42…
Browse files Browse the repository at this point in the history
…xx8' and 'asoc/topic/davinci' into asoc-next
  • Loading branch information
Mark Brown committed May 21, 2014
4 parents b03a1c7 + 3bb4061 + 5958de2 + 24fc81d commit 0c5dacf
Show file tree
Hide file tree
Showing 28 changed files with 2,103 additions and 308 deletions.
63 changes: 63 additions & 0 deletions Documentation/devicetree/bindings/sound/cs42l56.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
CS42L52 audio CODEC

Required properties:

- compatible : "cirrus,cs42l56"

- reg : the I2C address of the device for I2C

- VA-supply, VCP-supply, VLDO-supply : power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.

Optional properties:

- cirrus,gpio-nreset : GPIO controller's phandle and the number
of the GPIO used to reset the codec.

- cirrus,chgfreq-divisor : Values used to set the Charge Pump Frequency.
Allowable values of 0x00 through 0x0F. These are raw values written to the
register, not the actual frequency. The frequency is determined by the following.
Frequency = MCLK / 4 * (N+2)
N = chgfreq_val
MCLK = Where MCLK is the frequency of the mclk signal after the MCLKDIV2 circuit.

- cirrus,ain1a-ref-cfg, ain1b-ref-cfg : boolean, If present, AIN1A or AIN1B are configured
as a pseudo-differential input referenced to AIN1REF/AIN3A.

- cirrus,ain2a-ref-cfg, ain2b-ref-cfg : boolean, If present, AIN2A or AIN2B are configured
as a pseudo-differential input referenced to AIN2REF/AIN3B.

- cirrus,micbias-lvl: Set the output voltage level on the MICBIAS Pin.
0 = 0.5 x VA
1 = 0.6 x VA
2 = 0.7 x VA
3 = 0.8 x VA
4 = 0.83 x VA
5 = 0.91 x VA

- cirrus,adaptive-pwr-cfg : Configures how the power to the Headphone and Lineout
Amplifiers adapt to the output signal levels.
0 = Adapt to Volume Mode. Voltage level determined by the sum of the relevant volume settings.
1 = Fixed - Headphone and Line Amp supply = + or - VCP/2.
2 = Fixed - Headphone and Line Amp supply = + or - VCP.
3 = Adapted to Signal; Voltage level is dynamically determined by the output signal.

- cirrus,hpf-left-freq, hpf-right-freq : Sets the corner frequency (-3dB point) for the internal High-Pass
Filter.
0 = 1.8Hz
1 = 119Hz
2 = 236Hz
3 = 464Hz


Example:

codec: codec@4b {
compatible = "cirrus,cs42l56";
reg = <0x4b>;
gpio-reset = <&gpio 10 0>;
cirrus,chgfreq-divisor = <0x05>;
cirrus.ain1_ref_cfg;
cirrus,micbias-lvl = <5>;
VA-supply = <&reg_audio>;
};
48 changes: 48 additions & 0 deletions include/sound/cs42l56.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* linux/sound/cs42l56.h -- Platform data for CS42L56
*
* Copyright (c) 2014 Cirrus Logic Inc.
*
* 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 __CS42L56_H
#define __CS42L56_H

struct cs42l56_platform_data {

/* GPIO for Reset */
unsigned int gpio_nreset;

/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;

/* Analog Input 1A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1a_ref_cfg;

/* Analog Input 2A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2a_ref_cfg;

/* Analog Input 1B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1b_ref_cfg;

/* Analog Input 2B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2b_ref_cfg;

/* Charge Pump Freq. Check datasheet Pg62 */
unsigned int chgfreq;

/* HighPass Filter Right Channel Corner Frequency */
unsigned int hpfb_freq;

/* HighPass Filter Left Channel Corner Frequency */
unsigned int hpfa_freq;

/* Adaptive Power Control for LO/HP */
unsigned int adaptive_pwr;

};

#endif /* __CS42L56_H */
2 changes: 2 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ int snd_soc_resume(struct device *dev);
int snd_soc_poweroff(struct device *dev);
int snd_soc_register_platform(struct device *dev,
const struct snd_soc_platform_driver *platform_drv);
int devm_snd_soc_register_platform(struct device *dev,
const struct snd_soc_platform_driver *platform_drv);
void snd_soc_unregister_platform(struct device *dev);
int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
const struct snd_soc_platform_driver *platform_drv);
Expand Down
19 changes: 14 additions & 5 deletions sound/soc/codecs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ALC5623 if I2C
select SND_SOC_ALC5632 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
select SND_SOC_CS42L52 if I2C
select SND_SOC_CS42L51_I2C if I2C
select SND_SOC_CS42L52 if I2C && INPUT
select SND_SOC_CS42L56 if I2C && INPUT
select SND_SOC_CS42L73 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
Expand Down Expand Up @@ -128,7 +129,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8955 if I2C
select SND_SOC_WM8960 if I2C
select SND_SOC_WM8961 if I2C
select SND_SOC_WM8962 if I2C
select SND_SOC_WM8962 if I2C && INPUT
select SND_SOC_WM8971 if I2C
select SND_SOC_WM8974 if I2C
select SND_SOC_WM8978 if I2C
Expand Down Expand Up @@ -281,9 +282,17 @@ config SND_SOC_CQ0093VC
config SND_SOC_CS42L51
tristate

config SND_SOC_CS42L51_I2C
tristate
select SND_SOC_CS42L51

config SND_SOC_CS42L52
tristate "Cirrus Logic CS42L52 CODEC"
depends on I2C
depends on I2C && INPUT

config SND_SOC_CS42L56
tristate "Cirrus Logic CS42L56 CODEC"
depends on I2C && INPUT

config SND_SOC_CS42L73
tristate "Cirrus Logic CS42L73 CODEC"
Expand Down Expand Up @@ -603,7 +612,7 @@ config SND_SOC_WM8961

config SND_SOC_WM8962
tristate "Wolfson Microelectronics WM8962 CODEC"
depends on I2C
depends on I2C && INPUT

config SND_SOC_WM8971
tristate
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/codecs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ snd-soc-ak5386-objs := ak5386.o
snd-soc-arizona-objs := arizona.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
snd-soc-cs42l56-objs := cs42l56.o
snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
Expand Down Expand Up @@ -178,7 +180,9 @@ obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
Expand Down
59 changes: 59 additions & 0 deletions sound/soc/codecs/cs42l51-i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* cs42l56.c -- CS42L51 ALSA SoC I2C audio driver
*
* Copyright 2014 CirrusLogic, Inc.
*
* Author: Brian Austin <brian.austin@cirrus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/

#include <linux/i2c.h>
#include <linux/module.h>
#include <sound/soc.h>

#include "cs42l51.h"

static struct i2c_device_id cs42l51_i2c_id[] = {
{"cs42l51", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);

static int cs42l51_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regmap_config config;

config = cs42l51_regmap;
config.val_bits = 8;
config.reg_bits = 8;

return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config));
}

static int cs42l51_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);

return 0;
}

static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "cs42l51",
.owner = THIS_MODULE,
},
.probe = cs42l51_i2c_probe,
.remove = cs42l51_i2c_remove,
.id_table = cs42l51_i2c_id,
};

module_i2c_driver(cs42l51_i2c_driver);

MODULE_DESCRIPTION("ASoC CS42L51 I2C Driver");
MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
MODULE_LICENSE("GPL");
76 changes: 20 additions & 56 deletions sound/soc/codecs/cs42l51.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
#include <linux/i2c.h>
#include <linux/regmap.h>

#include "cs42l51.h"
Expand Down Expand Up @@ -483,7 +482,7 @@ static struct snd_soc_dai_driver cs42l51_dai = {
.ops = &cs42l51_dai_ops,
};

static int cs42l51_probe(struct snd_soc_codec *codec)
static int cs42l51_codec_probe(struct snd_soc_codec *codec)
{
int ret, reg;

Expand All @@ -504,7 +503,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
}

static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
.probe = cs42l51_probe,
.probe = cs42l51_codec_probe,

.controls = cs42l51_snd_controls,
.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
Expand All @@ -514,91 +513,56 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
};

static const struct regmap_config cs42l51_regmap = {
.reg_bits = 8,
.val_bits = 8,

const struct regmap_config cs42l51_regmap = {
.max_register = CS42L51_CHARGE_FREQ,
.cache_type = REGCACHE_RBTREE,
};
EXPORT_SYMBOL_GPL(cs42l51_regmap);

static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
int cs42l51_probe(struct device *dev, struct regmap *regmap)
{
struct cs42l51_private *cs42l51;
struct regmap *regmap;
unsigned int val;
int ret;

regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
dev_err(&i2c_client->dev, "Failed to create regmap: %d\n",
ret);
return ret;
}
if (IS_ERR(regmap))
return PTR_ERR(regmap);

cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private),
GFP_KERNEL);
if (!cs42l51)
return -ENOMEM;

dev_set_drvdata(dev, cs42l51);

/* Verify that we have a CS42L51 */
ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
if (ret < 0) {
dev_err(&i2c_client->dev, "failed to read I2C\n");
dev_err(dev, "failed to read I2C\n");
goto error;
}

if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
(val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val);
dev_err(dev, "Invalid chip id: %x\n", val);
ret = -ENODEV;
goto error;
}
dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n",
val & CS42L51_CHIP_REV_MASK);

dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
val & 7);

cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
GFP_KERNEL);
if (!cs42l51)
return -ENOMEM;

i2c_set_clientdata(i2c_client, cs42l51);

ret = snd_soc_register_codec(&i2c_client->dev,
ret = snd_soc_register_codec(dev,
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
error:
return ret;
}

static int cs42l51_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}

static const struct i2c_device_id cs42l51_id[] = {
{"cs42l51", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
EXPORT_SYMBOL_GPL(cs42l51_probe);

static const struct of_device_id cs42l51_of_match[] = {
{ .compatible = "cirrus,cs42l51", },
{ }
};
MODULE_DEVICE_TABLE(of, cs42l51_of_match);

static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "cs42l51-codec",
.owner = THIS_MODULE,
.of_match_table = cs42l51_of_match,
},
.id_table = cs42l51_id,
.probe = cs42l51_i2c_probe,
.remove = cs42l51_i2c_remove,
};

module_i2c_driver(cs42l51_i2c_driver);

MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
Loading

0 comments on commit 0c5dacf

Please sign in to comment.