Merge remote-tracking branches 'asoc/topic/rt5645', 'asoc/topic/rt5677', 'asoc/topic/samsung', 'asoc/topic/sgtl5000' and 'asoc/topic/sh' into asoc-next

This commit is contained in:
Mark Brown 2014-10-06 12:49:03 +01:00
12 changed files with 339 additions and 8 deletions

View File

@ -0,0 +1,59 @@
RT5677 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5677".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
Optional properties:
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
- realtek,in1-differential
- realtek,in2-differential
- realtek,lout1-differential
- realtek,lout2-differential
- realtek,lout3-differential
Boolean. Indicate MIC1/2 input and LOUT1/2/3 outputs are differential,
rather than single-ended.
Pins on the device (for linking into audio routes):
* IN1P
* IN1N
* IN2P
* IN2N
* MICBIAS1
* DMIC1
* DMIC2
* DMIC3
* DMIC4
* LOUT1
* LOUT2
* LOUT3
Example:
rt5677 {
compatible = "realtek,rt5677";
reg = <0x2c>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
gpio-controller;
#gpio-cells = <2>;
realtek,pow-ldo2-gpio =
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
realtek,in1-differential = "true";
};

View File

@ -20,6 +20,9 @@ struct rt5645_platform_data {
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
unsigned int dmic2_data_pin;
/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
unsigned int hp_det_gpio;
bool gpio_hp_det_active_high;
};
#endif

View File

@ -19,9 +19,12 @@ enum rt5677_dmic2_clk {
struct rt5677_platform_data {
/* IN1 IN2 can optionally be differential */
/* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */
bool in1_diff;
bool in2_diff;
bool lout1_diff;
bool lout2_diff;
bool lout3_diff;
/* DMIC2 clock source selection */
enum rt5677_dmic2_clk dmic2_clk_pin;
};

View File

@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@ -2103,6 +2104,77 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
static int rt5645_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
int gpio_state, jack_type = 0;
unsigned int val;
gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio);
dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio,
gpio_state);
if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) ||
(!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) {
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1");
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2");
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2");
snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power");
snd_soc_dapm_sync(&codec->dapm);
snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006);
snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0);
snd_soc_update_bits(codec, RT5645_IN1_CTRL2,
RT5645_CBJ_MN_JD, 0);
snd_soc_update_bits(codec, RT5645_IN1_CTRL2,
RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
msleep(400);
val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7;
dev_dbg(codec->dev, "val = %d\n", val);
if (val == 1 || val == 2)
jack_type = SND_JACK_HEADSET;
else
jack_type = SND_JACK_HEADPHONE;
snd_soc_dapm_disable_pin(&codec->dapm, "micbias1");
snd_soc_dapm_disable_pin(&codec->dapm, "micbias2");
snd_soc_dapm_disable_pin(&codec->dapm, "LDO2");
snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
snd_soc_dapm_sync(&codec->dapm);
}
snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET);
return 0;
}
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
rt5645->jack = jack;
rt5645_jack_detect(codec, rt5645->jack);
return 0;
}
EXPORT_SYMBOL_GPL(rt5645_set_jack_detect);
static irqreturn_t rt5645_irq(int irq, void *data)
{
struct rt5645_priv *rt5645 = data;
rt5645_jack_detect(rt5645->codec, rt5645->jack);
return IRQ_HANDLED;
}
static int rt5645_probe(struct snd_soc_codec *codec)
{
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
@ -2250,6 +2322,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
if (rt5645 == NULL)
return -ENOMEM;
rt5645->i2c = i2c;
i2c_set_clientdata(i2c, rt5645);
if (pdata)
@ -2345,12 +2418,38 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
}
if (rt5645->i2c->irq) {
ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5645", rt5645);
if (ret)
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
}
if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) {
ret = gpio_request(rt5645->pdata.hp_det_gpio, "rt5645");
if (ret)
dev_err(&i2c->dev, "Fail gpio_request hp_det_gpio\n");
ret = gpio_direction_input(rt5645->pdata.hp_det_gpio);
if (ret)
dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n");
}
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
rt5645_dai, ARRAY_SIZE(rt5645_dai));
}
static int rt5645_i2c_remove(struct i2c_client *i2c)
{
struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c);
if (i2c->irq)
free_irq(i2c->irq, rt5645);
if (gpio_is_valid(rt5645->pdata.hp_det_gpio))
gpio_free(rt5645->pdata.hp_det_gpio);
snd_soc_unregister_codec(&i2c->dev);
return 0;

View File

@ -2166,6 +2166,8 @@ struct rt5645_priv {
struct snd_soc_codec *codec;
struct rt5645_platform_data pdata;
struct regmap *regmap;
struct i2c_client *i2c;
struct snd_soc_jack *jack;
int sysclk;
int sysclk_src;
@ -2178,4 +2180,7 @@ struct rt5645_priv {
int pll_out;
};
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack);
#endif /* __RT5645_H__ */

View File

@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
@ -541,6 +542,7 @@ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
static unsigned int bst_tlv[] = {
@ -605,6 +607,10 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = {
RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 127, 0,
adc_vol_tlv),
/* Sidetone Control */
SOC_SINGLE_TLV("Sidetone Volume", RT5677_SIDETONE_CTRL,
RT5677_ST_VOL_SFT, 31, 0, st_vol_tlv),
/* ADC Boost Volume Control */
SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST,
RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0,
@ -1993,6 +1999,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
/* Sidetone Mux */
SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
&rt5677_sidetone_mux),
SND_SOC_DAPM_SUPPLY("Sidetone Power", RT5677_SIDETONE_CTRL,
RT5677_ST_EN_SFT, 0, NULL, 0),
/* VAD Mux*/
SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0,
&rt5677_vad_src_mux),
@ -2704,6 +2713,7 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
{ "Sidetone Mux", "DMIC4 L", "DMIC L4" },
{ "Sidetone Mux", "ADC1", "ADC 1" },
{ "Sidetone Mux", "ADC2", "ADC 2" },
{ "Sidetone Mux", NULL, "Sidetone Power" },
{ "Stereo DAC MIXL", "ST L Switch", "Sidetone Mux" },
{ "Stereo DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" },
@ -3107,6 +3117,59 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
return 0;
}
static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_codec *codec = dai->codec;
unsigned int val = 0;
if (rx_mask || tx_mask)
val |= (1 << 12);
switch (slots) {
case 4:
val |= (1 << 10);
break;
case 6:
val |= (2 << 10);
break;
case 8:
val |= (3 << 10);
break;
case 2:
default:
break;
}
switch (slot_width) {
case 20:
val |= (1 << 8);
break;
case 24:
val |= (2 << 8);
break;
case 32:
val |= (3 << 8);
break;
case 16:
default:
break;
}
switch (dai->id) {
case RT5677_AIF1:
snd_soc_update_bits(codec, RT5677_TDM1_CTRL1, 0x1f00, val);
break;
case RT5677_AIF2:
snd_soc_update_bits(codec, RT5677_TDM2_CTRL1, 0x1f00, val);
break;
default:
break;
}
return 0;
}
static int rt5677_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@ -3316,6 +3379,8 @@ static int rt5677_remove(struct snd_soc_codec *codec)
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
if (gpio_is_valid(rt5677->pow_ldo2))
gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
return 0;
}
@ -3327,6 +3392,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
regcache_cache_only(rt5677->regmap, true);
regcache_mark_dirty(rt5677->regmap);
if (gpio_is_valid(rt5677->pow_ldo2))
gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
return 0;
}
@ -3335,6 +3402,10 @@ static int rt5677_resume(struct snd_soc_codec *codec)
{
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
if (gpio_is_valid(rt5677->pow_ldo2)) {
gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
msleep(10);
}
regcache_cache_only(rt5677->regmap, false);
regcache_sync(rt5677->regmap);
@ -3354,6 +3425,7 @@ static struct snd_soc_dai_ops rt5677_aif_dai_ops = {
.set_fmt = rt5677_set_dai_fmt,
.set_sysclk = rt5677_set_dai_sysclk,
.set_pll = rt5677_set_dai_pll,
.set_tdm_slot = rt5677_set_tdm_slot,
};
static struct snd_soc_dai_driver rt5677_dai[] = {
@ -3492,6 +3564,35 @@ static const struct i2c_device_id rt5677_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
{
rt5677->pdata.in1_diff = of_property_read_bool(np,
"realtek,in1-differential");
rt5677->pdata.in2_diff = of_property_read_bool(np,
"realtek,in2-differential");
rt5677->pdata.lout1_diff = of_property_read_bool(np,
"realtek,lout1-differential");
rt5677->pdata.lout2_diff = of_property_read_bool(np,
"realtek,lout2-differential");
rt5677->pdata.lout3_diff = of_property_read_bool(np,
"realtek,lout3-differential");
rt5677->pow_ldo2 = of_get_named_gpio(np,
"realtek,pow-ldo2-gpio", 0);
/*
* POW_LDO2 is optional (it may be statically tied on the board).
* -ENOENT means that the property doesn't exist, i.e. there is no
* GPIO, so is not an error. Any other error code means the property
* exists, but could not be parsed.
*/
if (!gpio_is_valid(rt5677->pow_ldo2) &&
(rt5677->pow_ldo2 != -ENOENT))
return rt5677->pow_ldo2;
return 0;
}
static int rt5677_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -3510,6 +3611,33 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5677->pdata = *pdata;
if (i2c->dev.of_node) {
ret = rt5677_parse_dt(rt5677, i2c->dev.of_node);
if (ret) {
dev_err(&i2c->dev, "Failed to parse device tree: %d\n",
ret);
return ret;
}
} else {
rt5677->pow_ldo2 = -EINVAL;
}
if (gpio_is_valid(rt5677->pow_ldo2)) {
ret = devm_gpio_request_one(&i2c->dev, rt5677->pow_ldo2,
GPIOF_OUT_INIT_HIGH,
"RT5677 POW_LDO2");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request POW_LDO2 %d: %d\n",
rt5677->pow_ldo2, ret);
return ret;
}
/* Wait a while until I2C bus becomes available. The datasheet
* does not specify the exact we should wait but startup
* sequence mentiones at least a few milliseconds.
*/
msleep(10);
}
rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap);
if (IS_ERR(rt5677->regmap)) {
ret = PTR_ERR(rt5677->regmap);
@ -3540,6 +3668,18 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5677->regmap, RT5677_IN1,
RT5677_IN_DF2, RT5677_IN_DF2);
if (rt5677->pdata.lout1_diff)
regmap_update_bits(rt5677->regmap, RT5677_LOUT1,
RT5677_LOUT1_L_DF, RT5677_LOUT1_L_DF);
if (rt5677->pdata.lout2_diff)
regmap_update_bits(rt5677->regmap, RT5677_LOUT1,
RT5677_LOUT2_L_DF, RT5677_LOUT2_L_DF);
if (rt5677->pdata.lout3_diff)
regmap_update_bits(rt5677->regmap, RT5677_LOUT1,
RT5677_LOUT3_L_DF, RT5677_LOUT3_L_DF);
if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) {
regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL2,
RT5677_GPIO5_FUNC_MASK,

View File

@ -382,6 +382,10 @@
#define RT5677_ST_SEL_SFT 9
#define RT5677_ST_EN (0x1 << 6)
#define RT5677_ST_EN_SFT 6
#define RT5677_ST_GAIN (0x1 << 5)
#define RT5677_ST_GAIN_SFT 5
#define RT5677_ST_VOL_MASK (0x1f << 0)
#define RT5677_ST_VOL_SFT 0
/* Analog DAC1/2/3 Source Control (0x15) */
#define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4)
@ -1550,6 +1554,7 @@ struct rt5677_priv {
int pll_src;
int pll_in;
int pll_out;
int pow_ldo2; /* POW_LDO2 pin */
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif

View File

@ -626,6 +626,9 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
} else {
dev_err(codec->dev,
"PLL not supported in slave mode\n");
dev_err(codec->dev, "%d ratio is not supported. "
"SYS_MCLK needs to be 256, 384 or 512 * fs\n",
sgtl5000->sysclk / sys_fs);
return -EINVAL;
}
}
@ -1442,6 +1445,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
{
struct sgtl5000_priv *sgtl5000;
int ret, reg, rev;
unsigned int mclk;
sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv),
GFP_KERNEL);
@ -1465,6 +1469,14 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
return ret;
}
/* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */
mclk = clk_get_rate(sgtl5000->mclk);
if (mclk < 8000000 || mclk > 27000000) {
dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n",
mclk / 1000000, mclk / 1000 % 1000);
return -EINVAL;
}
ret = clk_prepare_enable(sgtl5000->mclk);
if (ret)
return ret;

View File

@ -351,7 +351,7 @@ static void idma_free(struct snd_pcm *pcm)
if (!buf->area)
return;
iounmap(buf->area);
iounmap((void __iomem *)buf->area);
buf->area = NULL;
buf->addr = 0;
@ -369,7 +369,7 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
buf->addr = idma.lp_tx_addr;
buf->bytes = idma_hardware.buffer_bytes_max;
buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes);
buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes);
return 0;
}

View File

@ -66,12 +66,12 @@ static struct snd_soc_card odroidx2 = {
.late_probe = odroidx2_late_probe,
};
struct odroidx2_drv_data odroidx2_drvdata = {
static const struct odroidx2_drv_data odroidx2_drvdata = {
.dapm_widgets = odroidx2_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets),
};
struct odroidx2_drv_data odroidu3_drvdata = {
static const struct odroidx2_drv_data odroidu3_drvdata = {
.dapm_widgets = odroidu3_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets),
};

View File

@ -1297,9 +1297,14 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
struct snd_pcm_substream *substream = io->substream;
struct dma_async_tx_descriptor *desc;
int is_play = fsi_stream_is_play(fsi, io);
enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
enum dma_transfer_direction dir;
int ret = -EIO;
if (is_play)
dir = DMA_MEM_TO_DEV;
else
dir = DMA_DEV_TO_MEM;
desc = dmaengine_prep_dma_cyclic(io->chan,
substream->runtime->dma_addr,
snd_pcm_lib_buffer_bytes(substream),

View File

@ -139,7 +139,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
desc->callback = siu_dma_tx_complete;
desc->callback_param = siu_stream;
cookie = desc->tx_submit(desc);
cookie = dmaengine_submit(desc);
if (cookie < 0) {
dev_err(dev, "Failed to submit a dma transfer\n");
return cookie;
@ -189,7 +189,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
desc->callback = siu_dma_tx_complete;
desc->callback_param = siu_stream;
cookie = desc->tx_submit(desc);
cookie = dmaengine_submit(desc);
if (cookie < 0) {
dev_err(dev, "Failed to submit dma descriptor\n");
return cookie;