Commit 828006de authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into topic/asoc

Linus decided to go for another week so here's a few more updates - a
mixed bag here, a few minor diagnostic tweaks, some driver enhancements
and the dmaengine conversion for ep93xx drivers which was tested a while
ago and just waiting for a signoff.
parents d0f47ff1 5ec65ee5
......@@ -263,6 +263,7 @@ static void __init visstrim_m10_board_init(void)
imx27_add_fec(NULL);
imx_add_gpio_keys(&visstrim_gpio_keys_platform_data);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0);
}
static void __init visstrim_m10_timer_init(void)
......
......@@ -718,6 +718,7 @@ struct snd_soc_platform {
int id;
struct device *dev;
struct snd_soc_platform_driver *driver;
struct mutex mutex;
unsigned int suspended:1; /* platform is suspended */
unsigned int probed:1;
......
......@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/pcm.h>
......@@ -626,41 +627,82 @@ static const struct snd_soc_dapm_route da7210_audio_map[] = {
/* Codec private data */
struct da7210_priv {
enum snd_soc_control_type control_type;
struct regmap *regmap;
};
/*
* Register cache
*/
static const u8 da7210_reg[] = {
0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R0 - R7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, /* R8 - RF */
0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54, /* R10 - R17 */
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R18 - R1F */
0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, /* R20 - R27 */
0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00, /* R28 - R2F */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, /* R30 - R37 */
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* R38 - R3F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R40 - R4F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R48 - R4F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R50 - R57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R58 - R5F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R60 - R67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R68 - R6F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R70 - R77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, /* R78 - R7F */
0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, /* R80 - R87 */
0x00, /* R88 */
static struct reg_default da7210_reg_defaults[] = {
{ 0x01, 0x11 },
{ 0x03, 0x00 },
{ 0x04, 0x00 },
{ 0x05, 0x00 },
{ 0x06, 0x00 },
{ 0x07, 0x00 },
{ 0x08, 0x00 },
{ 0x09, 0x00 },
{ 0x0a, 0x00 },
{ 0x0b, 0x00 },
{ 0x0c, 0x00 },
{ 0x0d, 0x00 },
{ 0x0e, 0x00 },
{ 0x0f, 0x08 },
{ 0x10, 0x00 },
{ 0x11, 0x00 },
{ 0x12, 0x00 },
{ 0x13, 0x00 },
{ 0x14, 0x08 },
{ 0x15, 0x10 },
{ 0x16, 0x10 },
{ 0x17, 0x54 },
{ 0x18, 0x40 },
{ 0x19, 0x00 },
{ 0x1a, 0x00 },
{ 0x1b, 0x00 },
{ 0x1c, 0x00 },
{ 0x1d, 0x00 },
{ 0x1e, 0x00 },
{ 0x1f, 0x00 },
{ 0x20, 0x00 },
{ 0x21, 0x00 },
{ 0x22, 0x00 },
{ 0x23, 0x02 },
{ 0x24, 0x00 },
{ 0x25, 0x76 },
{ 0x26, 0x00 },
{ 0x27, 0x00 },
{ 0x28, 0x04 },
{ 0x29, 0x00 },
{ 0x2a, 0x00 },
{ 0x2b, 0x30 },
{ 0x2c, 0x2A },
{ 0x83, 0x00 },
{ 0x84, 0x00 },
{ 0x85, 0x00 },
{ 0x86, 0x00 },
{ 0x87, 0x00 },
{ 0x88, 0x00 },
};
static int da7210_volatile_register(struct snd_soc_codec *codec,
static bool da7210_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case DA7210_A_HID_UNLOCK:
case DA7210_A_TEST_UNLOCK:
case DA7210_A_PLL1:
case DA7210_A_CP_MODE:
return false;
default:
return true;
}
}
static bool da7210_volatile_register(struct device *dev,
unsigned int reg)
{
switch (reg) {
case DA7210_STATUS:
return 1;
return true;
default:
return 0;
return false;
}
}
......@@ -866,7 +908,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
codec->control_data = da7210->regmap;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
......@@ -983,12 +1026,14 @@ static int da7210_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
/* As suggested by Dialog */
snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
snd_soc_write(codec, DA7210_A_PLL1, 0x01);
snd_soc_write(codec, DA7210_A_CP_MODE, 0x7C);
snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
/* unlock */
regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B);
regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4);
regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01);
regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C);
/* re-lock */
regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00);
regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00);
/* Activate all enabled subsystem */
snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
......@@ -1000,10 +1045,6 @@ static int da7210_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.probe = da7210_probe,
.reg_cache_size = ARRAY_SIZE(da7210_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = da7210_reg,
.volatile_register = da7210_volatile_register,
.controls = da7210_snd_controls,
.num_controls = ARRAY_SIZE(da7210_snd_controls),
......@@ -1014,6 +1055,17 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
};
static struct regmap_config da7210_regmap = {
.reg_bits = 8,
.val_bits = 8,
.reg_defaults = da7210_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
.volatile_reg = da7210_volatile_register,
.readable_reg = da7210_readable_register,
.cache_type = REGCACHE_RBTREE,
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
......@@ -1027,16 +1079,34 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, da7210);
da7210->control_type = SND_SOC_I2C;
da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
if (IS_ERR(da7210->regmap)) {
ret = PTR_ERR(da7210->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
goto err_regmap;
}
return ret;
err_regmap:
regmap_exit(da7210->regmap);
return ret;
}
static int __devexit da7210_i2c_remove(struct i2c_client *client)
{
struct da7210_priv *da7210 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
regmap_exit(da7210->regmap);
return 0;
}
......
......@@ -3166,9 +3166,16 @@ static void wm8958_default_micdet(u16 status, void *data)
/* If we have jackdet that will detect removal */
if (wm8994->jackdet) {
mutex_lock(&wm8994->accdet_lock);
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
wm1811_jackdet_set_mode(codec,
WM1811_JACKDET_MODE_JACK);
mutex_unlock(&wm8994->accdet_lock);
if (wm8994->pdata->jd_ext_cap) {
mutex_lock(&codec->mutex);
snd_soc_dapm_disable_pin(&codec->dapm,
......@@ -3176,9 +3183,6 @@ static void wm8958_default_micdet(u16 status, void *data)
snd_soc_dapm_sync(&codec->dapm);
mutex_unlock(&codec->mutex);
}
wm1811_jackdet_set_mode(codec,
WM1811_JACKDET_MODE_JACK);
}
}
......@@ -3213,6 +3217,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
struct wm8994_priv *wm8994 = data;
struct snd_soc_codec *codec = wm8994->codec;
int reg;
bool present;
mutex_lock(&wm8994->accdet_lock);
......@@ -3225,11 +3230,10 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
dev_dbg(codec->dev, "JACKDET %x\n", reg);
if (reg & WM1811_JACKDET_LVL) {
dev_dbg(codec->dev, "Jack detected\n");
present = reg & WM1811_JACKDET_LVL;
snd_soc_jack_report(wm8994->micdet[0].jack,
SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
if (present) {
dev_dbg(codec->dev, "Jack detected\n");
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, 0);
......@@ -3247,32 +3251,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, WM8958_MICD_ENA);
/* If required for an external cap force MICBIAS on */
if (wm8994->pdata->jd_ext_cap) {
mutex_lock(&codec->mutex);
snd_soc_dapm_force_enable_pin(&codec->dapm,
"MICBIAS2");
snd_soc_dapm_sync(&codec->dapm);
mutex_unlock(&codec->mutex);
}
} else {
dev_dbg(codec->dev, "Jack not detected\n");
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
if (wm8994->pdata->jd_ext_cap) {
mutex_lock(&codec->mutex);
snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
snd_soc_dapm_sync(&codec->dapm);
mutex_unlock(&codec->mutex);
}
snd_soc_jack_report(wm8994->micdet[0].jack, 0,
SND_JACK_MECHANICAL | SND_JACK_HEADSET |
wm8994->btn_mask);
/* Enable debounce while removed */
snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
WM1811_JACKDET_DB, WM1811_JACKDET_DB);
......@@ -3286,6 +3270,28 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
mutex_unlock(&wm8994->accdet_lock);
/* If required for an external cap force MICBIAS on */
if (wm8994->pdata->jd_ext_cap) {
mutex_lock(&codec->mutex);
if (present)
snd_soc_dapm_force_enable_pin(&codec->dapm,
"MICBIAS2");
else
snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
snd_soc_dapm_sync(&codec->dapm);
mutex_unlock(&codec->mutex);
}
if (present)
snd_soc_jack_report(wm8994->micdet[0].jack,
SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
else
snd_soc_jack_report(wm8994->micdet[0].jack, 0,
SND_JACK_MECHANICAL | SND_JACK_HEADSET |
wm8994->btn_mask);
return IRQ_HANDLED;
}
......@@ -3389,17 +3395,13 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
struct snd_soc_codec *codec = wm8994->codec;
int reg, count;
mutex_lock(&wm8994->accdet_lock);
/*
* Jack detection may have detected a removal simulataneously
* with an update of the MICDET status; if so it will have
* stopped detection and we can ignore this interrupt.
*/
if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) {
mutex_unlock(&wm8994->accdet_lock);
if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
return IRQ_HANDLED;
}
/* We may occasionally read a detection without an impedence
* range being provided - if that happens loop again.
......@@ -3408,7 +3410,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
do {
reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
if (reg < 0) {
mutex_unlock(&wm8994->accdet_lock);
dev_err(codec->dev,
"Failed to read mic detect status: %d\n",
reg);
......@@ -3439,8 +3440,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
dev_warn(codec->dev, "Accessory detection with no callback\n");
out:
mutex_unlock(&wm8994->accdet_lock);
return IRQ_HANDLED;
}
......
......@@ -118,7 +118,6 @@ WM8996_REGULATOR_EVENT(1)
WM8996_REGULATOR_EVENT(2)
static struct reg_default wm8996_reg[] = {
{ WM8996_SOFTWARE_RESET, 0x8996 },
{ WM8996_POWER_MANAGEMENT_1, 0x0 },
{ WM8996_POWER_MANAGEMENT_2, 0x0 },
{ WM8996_POWER_MANAGEMENT_3, 0x0 },
......@@ -153,7 +152,6 @@ static struct reg_default wm8996_reg[] = {
{ WM8996_CHARGE_PUMP_1, 0x1f25 },
{ WM8996_CHARGE_PUMP_2, 0xab19 },
{ WM8996_DC_SERVO_1, 0x0 },
{ WM8996_DC_SERVO_2, 0x0 },
{ WM8996_DC_SERVO_3, 0x0 },
{ WM8996_DC_SERVO_5, 0x2a2a },
{ WM8996_DC_SERVO_6, 0x0 },
......@@ -892,8 +890,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT1L) {
val |= WM8996_HPOUT1L_RMV_SHORT;
mask |= WM8996_HPOUT1L_RMV_SHORT;
val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
} else {
mask |= WM8996_HPOUT1L_RMV_SHORT |
WM8996_HPOUT1L_OUTP |
......@@ -901,8 +899,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT1R) {
val |= WM8996_HPOUT1R_RMV_SHORT;
mask |= WM8996_HPOUT1R_RMV_SHORT;
val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
} else {
mask |= WM8996_HPOUT1R_RMV_SHORT |
WM8996_HPOUT1R_OUTP |
......@@ -914,8 +912,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT2L) {
val |= WM8996_HPOUT2L_RMV_SHORT;
mask |= WM8996_HPOUT2L_RMV_SHORT;
val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
} else {
mask |= WM8996_HPOUT2L_RMV_SHORT |
WM8996_HPOUT2L_OUTP |
......@@ -923,8 +921,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT2R) {
val |= WM8996_HPOUT2R_RMV_SHORT;
mask |= WM8996_HPOUT2R_RMV_SHORT;
val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
} else {
mask |= WM8996_HPOUT2R_RMV_SHORT |
WM8996_HPOUT2R_OUTP |
......@@ -1216,7 +1214,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
......@@ -1225,7 +1222,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
......@@ -1234,7 +1230,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
......@@ -1243,7 +1238,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
......@@ -1436,32 +1430,28 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "HPOUT2L PGA", NULL, "DAC2L" },
{ "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
{ "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
{ "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
{ "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
{ "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" },
{ "HPOUT2R PGA", NULL, "Charge Pump" },
{ "HPOUT2R PGA", NULL, "Bandgap" },
{ "HPOUT2R PGA", NULL, "DAC2R" },
{ "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
{ "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
{ "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
{ "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
{ "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" },
{ "HPOUT1L PGA", NULL, "Charge Pump" },
{ "HPOUT1L PGA", NULL, "Bandgap" },
{ "HPOUT1L PGA", NULL, "DAC1L" },
{ "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
{ "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
{ "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
{ "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
{ "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" },
{ "HPOUT1R PGA", NULL, "Charge Pump" },
{ "HPOUT1R PGA", NULL, "Bandgap" },
{ "HPOUT1R PGA", NULL, "DAC1R" },
{ "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
{ "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
{ "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
{ "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
{ "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" },
{ "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
{ "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
......
config SND_EP93XX_SOC
tristate "SoC Audio support for the Cirrus Logic EP93xx series"
depends on ARCH_EP93XX && SND_SOC
select SND_SOC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the EP93xx I2S or AC97 interfaces.
......
......@@ -23,6 +23,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include <mach/hardware.h>
......@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
.fifo_size = 32,
};
struct ep93xx_runtime_data
{
int pointer_bytes;
int periods;
int period_bytes;
struct dma_chan *dma_chan;
struct ep93xx_dma_data dma_data;
};
static void ep93xx_pcm_dma_callback(void *data)
{
struct snd_pcm_substream *substream = data;
struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
rtd->pointer_bytes += rtd->period_bytes;
rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
snd_pcm_period_elapsed(substream);
}
static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
{
struct ep93xx_dma_data *data = filter_param;
......@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct ep93xx_pcm_dma_params *dma_params;
struct ep93xx_runtime_data *rtd;
dma_cap_mask_t mask;
struct ep93xx_dma_data *dma_data;
int ret;
ret = snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
return ret;
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
if (!rtd)
dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
if (!dma_data)
return -ENOMEM;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_CYCLIC, mask);
dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
rtd->dma_data.port = dma_params->dma_port;
rtd->dma_data.name = dma_params->name;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
rtd->dma_data.direction = DMA_MEM_TO_DEV;
else
rtd->dma_data.direction = DMA_DEV_TO_MEM;
rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
&rtd->dma_data);
if (!rtd->dma_chan) {
kfree(rtd);
return -EINVAL;
dma_data->port = dma_params->dma_port;
dma_data->name = dma_params->name;
dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
if (ret) {
kfree(dma_data);
return ret;
}
substream->runtime->private_data = rtd;
snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
{
struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
dma_release_channel(rtd->dma_chan);
kfree(rtd);
return 0;
}
struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct ep93xx_runtime_data *rtd = runtime->private_data;
struct dma_chan *chan = rtd->dma_chan;
struct dma_device *dma_dev = chan->device;
struct dma_async_tx_descriptor *desc;
rtd->pointer_bytes = 0;
desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
rtd->period_bytes * rtd->periods,
rtd->period_bytes,
rtd->dma_data.direction);
if (!desc)
return -EINVAL;
desc->callback = ep93xx_pcm_dma_callback;
desc->callback_param = substream;
dmaengine_submit(desc);
snd_dmaengine_pcm_close(substream);
kfree(dma_data);
return 0;
}
static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct ep93xx_runtime_data *rtd = runtime->private_data;
dmaengine_terminate_all(rtd->dma_chan);
}
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct ep93xx_runtime_data *rtd = runtime->private_data;
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
rtd->periods = params_periods(params);
rtd->period_bytes = params_period_bytes(params);
return 0;
}
......@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret;
ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = ep93xx_pcm_dma_submit(substream);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ep93xx_pcm_dma_flush(substream);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
/* FIXME: implement this with sub-period granularity */
return bytes_to_frames(runtime, rtd->pointer_bytes);
}
static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
......@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free,
.trigger = ep93xx_pcm_trigger,
.pointer = ep93xx_pcm_pointer,
.trigger = snd_dmaengine_pcm_trigger,
.pointer = snd_dmaengine_pcm_pointer,
.mmap = ep93xx_pcm_mmap,
};
......
......@@ -716,12 +716,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
}
/* Trigger the machine driver's probe function. The platform driver
* name of the machine driver is taken from the /model property of the
* name of the machine driver is taken from /compatible property of the
* device tree. We also pass the address of the CPU DAI driver
* structure.
*/
sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
/* Sometimes the model name has a "fsl," prefix, so we strip that. */
sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
/* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
p = strrchr(sprop, ',');
if (p)
sprop = p + 1;
......
......@@ -546,7 +546,7 @@ static struct platform_driver mpc8610_hpcd_driver = {
.probe = mpc8610_hpcd_probe,
.remove = __devexit_p(mpc8610_hpcd_remove),
.driver = {
/* The name must match the 'model' property in the device tree,
/* The name must match 'compatible' property in the device tree,
* in lowercase letters.
*/
.name = "snd-soc-mpc8610hpcd",
......
......@@ -543,6 +543,11 @@ static struct platform_driver p1022_ds_driver = {
.probe = p1022_ds_probe,
.remove = __devexit_p(p1022_ds_remove),
.driver = {
/*
* The name must match 'compatible' property in the device tree,
* in lowercase letters.
*/
.name = "snd-soc-p1022ds",
.owner = THIS_MODULE,
},
};
......@@ -556,33 +561,6 @@ static int __init p1022_ds_init(void)
{
struct device_node *guts_np;
struct resource res;
const char *sprop;
/*
* Check if we're actually running on a P1022DS. Older device trees
* have a model of "fsl,P1022" and newer ones use "fsl,P1022DS", so we
* need to support both. The SSI driver uses that property to link to
* the machine driver, so have to match it.
*/
sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
if (!sprop) {
pr_err("snd-soc-p1022ds: missing /model node");
return -ENODEV;
}
pr_debug("snd-soc-p1022ds: board model name is %s\n", sprop);
/*
* The name of this board, taken from the device tree. Normally, this is a*
* fixed string, but some P1022DS device trees have a /model property of
* "fsl,P1022", and others have "fsl,P1022DS".
*/
if (strcasecmp(sprop, "fsl,p1022ds") == 0)
p1022_ds_driver.driver.name = "snd-soc-p1022ds";
else if (strcasecmp(sprop, "fsl,p1022") == 0)
p1022_ds_driver.driver.name = "snd-soc-p1022";
else
return -ENODEV;
/* Get the physical address of the global utilities registers */
guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
......
......@@ -167,7 +167,7 @@ static void __init audmux_debugfs_init(void)
}
}
static void __exit audmux_debugfs_remove(void)
static void __devexit audmux_debugfs_remove(void)
{
debugfs_remove_recursive(audmux_debugfs_root);
}
......@@ -249,7 +249,7 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
}
EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
static int __init imx_audmux_probe(struct platform_device *pdev)
static int __devinit imx_audmux_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *of_id =
......@@ -276,7 +276,7 @@ static int __init imx_audmux_probe(struct platform_device *pdev)
return 0;
}
static int __exit imx_audmux_remove(struct platform_device *pdev)
static int __devexit imx_audmux_remove(struct platform_device *pdev)
{
if (audmux_type == IMX31_AUDMUX)
audmux_debugfs_remove();
......@@ -287,7 +287,7 @@ static int __exit imx_audmux_remove(struct platform_device *pdev)
static struct platform_driver imx_audmux_driver = {
.probe = imx_audmux_probe,
.remove = __exit_p(imx_audmux_remove),
.remove = __devexit_p(imx_audmux_remove),
.id_table = imx_audmux_ids,
.driver = {
.name = DRIVER_NAME,
......
......@@ -188,22 +188,16 @@ static struct snd_soc_card mx27vis_aic32x4 = {
.num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
static struct platform_device *mx27vis_aic32x4_snd_device;
static int __init mx27vis_aic32x4_init(void)
static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
{
int ret;
mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1);
if (!mx27vis_aic32x4_snd_device)
return -ENOMEM;
platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4);
ret = platform_device_add(mx27vis_aic32x4_snd_device);
mx27vis_aic32x4.dev = &pdev->dev;
ret = snd_soc_register_card(&mx27vis_aic32x4);
if (ret) {
printk(KERN_ERR "ASoC: Platform device allocation failed\n");
platform_device_put(mx27vis_aic32x4_snd_device);
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
return ret;
}
/* Connect SSI0 as clock slave to SSI1 external pins */
......@@ -221,22 +215,31 @@ static int __init mx27vis_aic32x4_init(void)
ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP");
if (ret) {
if (ret)
printk(KERN_ERR "ASoC: unable to setup gpios\n");
platform_device_put(mx27vis_aic32x4_snd_device);
}
return ret;
}
static void __exit mx27vis_aic32x4_exit(void)
static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
{
platform_device_unregister(mx27vis_aic32x4_snd_device);
snd_soc_unregister_card(&mx27vis_aic32x4);
return 0;
}
module_init(mx27vis_aic32x4_init);
module_exit(mx27vis_aic32x4_exit);
static struct platform_driver mx27vis_aic32x4_audio_driver = {
.driver = {
.name = "mx27vis",
.owner = THIS_MODULE,
},
.probe = mx27vis_aic32x4_probe,
.remove = __devexit_p(mx27vis_aic32x4_remove),
};
module_platform_driver(mx27vis_aic32x4_audio_driver);
MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:mx27vis");
......@@ -764,7 +764,8 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai)
#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
......
......@@ -1531,14 +1531,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
if (dai_link->dai_fmt) {
ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
dai_link->dai_fmt);
if (ret != 0)
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].codec_dai->dev,
"Failed to set DAI format: %d\n",
ret);
ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
dai_link->dai_fmt);
if (ret != 0)
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].cpu_dai->dev,
"Failed to set DAI format: %d\n",
ret);
......@@ -2971,10 +2971,11 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
if (dai->driver && dai->driver->ops->set_fmt)
return dai->driver->ops->set_fmt(dai, fmt);
else
if (dai->driver == NULL)
return -EINVAL;
if (dai->driver->ops->set_fmt == NULL)
return -ENOTSUPP;
return dai->driver->ops->set_fmt(dai, fmt);
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
......@@ -3382,6 +3383,7 @@ int snd_soc_register_platform(struct device *dev,
platform->dapm.dev = dev;
platform->dapm.platform = platform;
platform->dapm.stream_event = platform_drv->stream_event;
mutex_init(&platform->mutex);
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
......
......@@ -1667,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
if (!dapm->debugfs_dapm) {
printk(KERN_WARNING
dev_warn(dapm->dev,
"Failed to create DAPM debugfs directory\n");
return;
}
......
......@@ -142,6 +142,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
direction = snd_pcm_substream_to_dma_direction(substream);
prtd->pos = 0;
desc = chan->device->device_prep_dma_cyclic(chan,
substream->runtime->dma_addr,
snd_pcm_lib_buffer_bytes(substream),
......
......@@ -115,7 +115,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct device_node *np = codec->card->dev->of_node;
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
int ret;
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
&tegra_alc5632_hs_jack);
......
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