summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/aoa/soundbus/soundbus.h2
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c12
-rw-r--r--sound/core/init.c6
-rw-r--r--sound/core/jack.c3
-rw-r--r--sound/core/pcm_lib.c48
-rw-r--r--sound/core/pcm_misc.c1
-rw-r--r--sound/core/pcm_native.c24
-rw-r--r--sound/core/sound.c5
-rw-r--r--sound/drivers/dummy.c2
-rw-r--r--sound/i2c/other/tea575x-tuner.c23
-rw-r--r--sound/oss/ac97_codec.c2
-rw-r--r--sound/oss/sh_dac_audio.c2
-rw-r--r--sound/oss/soundcard.c15
-rw-r--r--sound/pci/ac97/ac97_patch.c2
-rw-r--r--sound/pci/ca0106/ca0106_main.c1
-rw-r--r--sound/pci/hda/patch_nvhdmi.c1
-rw-r--r--sound/pci/hda/patch_realtek.c88
-rw-r--r--sound/pci/hda/patch_sigmatel.c52
-rw-r--r--sound/ppc/snd_ps3.c96
-rw-r--r--sound/ppc/snd_ps3.h1
-rw-r--r--sound/soc/at32/playpaq_wm8510.c12
-rw-r--r--sound/soc/at91/Kconfig17
-rw-r--r--sound/soc/at91/Makefile5
-rw-r--r--sound/soc/at91/at91-ssc.c2
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c349
-rw-r--r--sound/soc/blackfin/Kconfig16
-rw-r--r--sound/soc/blackfin/Makefile3
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c42
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c240
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c47
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/codecs/Kconfig13
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1980.c1
-rw-r--r--sound/soc/codecs/ad73311.c107
-rw-r--r--sound/soc/codecs/ad73311.h90
-rw-r--r--sound/soc/codecs/ak4535.c1
-rw-r--r--sound/soc/codecs/ssm2602.c1
-rw-r--r--sound/soc/codecs/tlv320aic23.c714
-rw-r--r--sound/soc/codecs/tlv320aic23.h122
-rw-r--r--sound/soc/codecs/tlv320aic3x.c5
-rw-r--r--sound/soc/codecs/uda1380.c1
-rw-r--r--sound/soc/codecs/wm8510.c111
-rw-r--r--sound/soc/codecs/wm8510.h1
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8731.c1
-rw-r--r--sound/soc/codecs/wm8750.c1
-rw-r--r--sound/soc/codecs/wm8753.c75
-rw-r--r--sound/soc/codecs/wm8753.h4
-rw-r--r--sound/soc/codecs/wm8900.c1
-rw-r--r--sound/soc/codecs/wm8903.c4
-rw-r--r--sound/soc/codecs/wm8971.c1
-rw-r--r--sound/soc/codecs/wm8990.c1
-rw-r--r--sound/soc/codecs/wm9712.c3
-rw-r--r--sound/soc/codecs/wm9713.c3
-rw-r--r--sound/soc/omap/Kconfig8
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/n810.c6
-rw-r--r--sound/soc/omap/omap-mcbsp.c205
-rw-r--r--sound/soc/omap/omap-mcbsp.h16
-rw-r--r--sound/soc/omap/omap-pcm.c4
-rw-r--r--sound/soc/omap/osk5912.c232
-rw-r--r--sound/soc/pxa/corgi.c6
-rw-r--r--sound/soc/pxa/em-x270.c2
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c4
-rw-r--r--sound/soc/pxa/spitz.c16
-rw-r--r--sound/soc/pxa/tosa.c6
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c72
-rw-r--r--sound/soc/soc-core.c5
-rw-r--r--sound/soc/soc-dapm.c27
-rw-r--r--sound/sound_core.c5
-rw-r--r--sound/usb/usx2y/us122l.c13
75 files changed, 2307 insertions, 720 deletions
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h
index 622cd37a011..a0f223c13f6 100644
--- a/sound/aoa/soundbus/soundbus.h
+++ b/sound/aoa/soundbus/soundbus.h
@@ -8,7 +8,7 @@
#ifndef __SOUNDBUS_H
#define __SOUNDBUS_H
-#include <asm/of_device.h>
+#include <linux/of_device.h>
#include <sound/pcm.h>
#include <linux/list.h>
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 99026dfb81e..34c1d94f921 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -50,7 +50,7 @@ unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
mutex_lock(&car_mutex);
/* set up primary or secondary codec space */
- if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
else
reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
@@ -90,7 +90,7 @@ void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
mutex_lock(&car_mutex);
/* set up primary or secondary codec space */
- if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
else
reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
@@ -200,7 +200,7 @@ static inline void pxa_ac97_cold_pxa3xx(void)
bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
{
#ifdef CONFIG_PXA25x
- if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ if (cpu_is_pxa25x())
pxa_ac97_warm_pxa25x();
else
#endif
@@ -230,7 +230,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
{
#ifdef CONFIG_PXA25x
- if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ if (cpu_is_pxa25x())
pxa_ac97_cold_pxa25x();
else
#endif
@@ -301,7 +301,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
int pxa2xx_ac97_hw_resume(void)
{
- if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+ if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
@@ -325,7 +325,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
if (ret < 0)
goto err;
- if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+ if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
diff --git a/sound/core/init.c b/sound/core/init.c
index 8af467df924..ef2352c2e45 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -549,9 +549,9 @@ int snd_card_register(struct snd_card *card)
return -EINVAL;
#ifndef CONFIG_SYSFS_DEPRECATED
if (!card->card_dev) {
- card->card_dev = device_create_drvdata(sound_class, card->dev,
- MKDEV(0, 0), NULL,
- "card%i", card->number);
+ card->card_dev = device_create(sound_class, card->dev,
+ MKDEV(0, 0), NULL,
+ "card%i", card->number);
if (IS_ERR(card->card_dev))
card->card_dev = NULL;
}
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 8133a2b173a..bd2d9e6b55e 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -147,6 +147,9 @@ EXPORT_SYMBOL(snd_jack_set_parent);
*/
void snd_jack_report(struct snd_jack *jack, int status)
{
+ if (!jack)
+ return;
+
if (jack->type & SND_JACK_HEADPHONE)
input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
status & SND_JACK_HEADPHONE);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 6ea5cfb8399..921691080f3 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -908,12 +908,12 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
EXPORT_SYMBOL(snd_pcm_hw_rule_add);
/**
- * snd_pcm_hw_constraint_mask
+ * snd_pcm_hw_constraint_mask - apply the given bitmap mask constraint
* @runtime: PCM runtime instance
* @var: hw_params variable to apply the mask
* @mask: the bitmap mask
*
- * Apply the constraint of the given bitmap mask to a mask parameter.
+ * Apply the constraint of the given bitmap mask to a 32-bit mask parameter.
*/
int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int32_t mask)
@@ -928,12 +928,12 @@ int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param
}
/**
- * snd_pcm_hw_constraint_mask64
+ * snd_pcm_hw_constraint_mask64 - apply the given bitmap mask constraint
* @runtime: PCM runtime instance
* @var: hw_params variable to apply the mask
* @mask: the 64bit bitmap mask
*
- * Apply the constraint of the given bitmap mask to a mask parameter.
+ * Apply the constraint of the given bitmap mask to a 64-bit mask parameter.
*/
int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int64_t mask)
@@ -949,7 +949,7 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
}
/**
- * snd_pcm_hw_constraint_integer
+ * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval
* @runtime: PCM runtime instance
* @var: hw_params variable to apply the integer constraint
*
@@ -964,7 +964,7 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
/**
- * snd_pcm_hw_constraint_minmax
+ * snd_pcm_hw_constraint_minmax - apply a min/max range constraint to an interval
* @runtime: PCM runtime instance
* @var: hw_params variable to apply the range
* @min: the minimal value
@@ -995,7 +995,7 @@ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
/**
- * snd_pcm_hw_constraint_list
+ * snd_pcm_hw_constraint_list - apply a list of constraints to a parameter
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the list constraint
@@ -1031,7 +1031,7 @@ static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
}
/**
- * snd_pcm_hw_constraint_ratnums
+ * snd_pcm_hw_constraint_ratnums - apply ratnums constraint to a parameter
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the ratnums constraint
@@ -1064,7 +1064,7 @@ static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
}
/**
- * snd_pcm_hw_constraint_ratdens
+ * snd_pcm_hw_constraint_ratdens - apply ratdens constraint to a parameter
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the ratdens constraint
@@ -1095,7 +1095,7 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
}
/**
- * snd_pcm_hw_constraint_msbits
+ * snd_pcm_hw_constraint_msbits - add a hw constraint msbits rule
* @runtime: PCM runtime instance
* @cond: condition bits
* @width: sample bits width
@@ -1123,7 +1123,7 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
}
/**
- * snd_pcm_hw_constraint_step
+ * snd_pcm_hw_constraint_step - add a hw constraint step rule
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the step constraint
@@ -1154,7 +1154,7 @@ static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm
}
/**
- * snd_pcm_hw_constraint_pow2
+ * snd_pcm_hw_constraint_pow2 - add a hw constraint power-of-2 rule
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the power-of-2 constraint
@@ -1202,13 +1202,13 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
EXPORT_SYMBOL(_snd_pcm_hw_params_any);
/**
- * snd_pcm_hw_param_value
+ * snd_pcm_hw_param_value - return @params field @var value
* @params: the hw_params instance
* @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
+ * @dir: pointer to the direction (-1,0,1) or %NULL
*
- * Return the value for field PAR if it's fixed in configuration space
- * defined by PARAMS. Return -EINVAL otherwise
+ * Return the value for field @var if it's fixed in configuration space
+ * defined by @params. Return -%EINVAL otherwise.
*/
int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
@@ -1271,13 +1271,13 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
/**
- * snd_pcm_hw_param_first
+ * snd_pcm_hw_param_first - refine config space and return minimum value
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
+ * @dir: pointer to the direction (-1,0,1) or %NULL
*
- * Inside configuration space defined by PARAMS remove from PAR all
+ * Inside configuration space defined by @params remove from @var all
* values > minimum. Reduce configuration space accordingly.
* Return the minimum.
*/
@@ -1317,13 +1317,13 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
/**
- * snd_pcm_hw_param_last
+ * snd_pcm_hw_param_last - refine config space and return maximum value
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
+ * @dir: pointer to the direction (-1,0,1) or %NULL
*
- * Inside configuration space defined by PARAMS remove from PAR all
+ * Inside configuration space defined by @params remove from @var all
* values < maximum. Reduce configuration space accordingly.
* Return the maximum.
*/
@@ -1345,11 +1345,11 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
EXPORT_SYMBOL(snd_pcm_hw_param_last);
/**
- * snd_pcm_hw_param_choose
+ * snd_pcm_hw_param_choose - choose a configuration defined by @params
* @pcm: PCM instance
* @params: the hw_params instance
*
- * Choose one configuration from configuration space defined by PARAMS
+ * Choose one configuration from configuration space defined by @params.
* The configuration chosen is that obtained fixing in this order:
* first access, first format, first subformat, min channels,
* min rate, min period time, max buffer size, min tick time
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 89b7f549beb..ea2bf82c937 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -319,6 +319,7 @@ EXPORT_SYMBOL(snd_pcm_format_physical_width);
/**
* snd_pcm_format_size - return the byte size of samples on the given format
* @format: the format to check
+ * @samples: sampling rate
*
* Returns the byte size of the given samples for the format, or a
* negative error code if unknown format.
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index e61e12506de..aef18682c03 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -875,10 +875,8 @@ static struct action_ops snd_pcm_action_start = {
};
/**
- * snd_pcm_start
+ * snd_pcm_start - start all linked streams
* @substream: the PCM substream instance
- *
- * Start all linked streams.
*/
int snd_pcm_start(struct snd_pcm_substream *substream)
{
@@ -926,12 +924,11 @@ static struct action_ops snd_pcm_action_stop = {
};
/**
- * snd_pcm_stop
+ * snd_pcm_stop - try to stop all running streams in the substream group
* @substream: the PCM substream instance
* @state: PCM state after stopping the stream
*
- * Try to stop all running streams in the substream group.
- * The state of each stream is changed to the given value after that unconditionally.
+ * The state of each stream is then changed to the given state unconditionally.
*/
int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
{
@@ -941,11 +938,10 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
EXPORT_SYMBOL(snd_pcm_stop);
/**
- * snd_pcm_drain_done
+ * snd_pcm_drain_done - stop the DMA only when the given stream is playback
* @substream: the PCM substream
*
- * Stop the DMA only when the given stream is playback.
- * The state is changed to SETUP.
+ * After stopping, the state is changed to SETUP.
* Unlike snd_pcm_stop(), this affects only the given stream.
*/
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
@@ -1065,10 +1061,9 @@ static struct action_ops snd_pcm_action_suspend = {
};
/**
- * snd_pcm_suspend
+ * snd_pcm_suspend - trigger SUSPEND to all linked streams
* @substream: the PCM substream
*
- * Trigger SUSPEND to all linked streams.
* After this call, all streams are changed to SUSPENDED state.
*/
int snd_pcm_suspend(struct snd_pcm_substream *substream)
@@ -1088,10 +1083,9 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
EXPORT_SYMBOL(snd_pcm_suspend);
/**
- * snd_pcm_suspend_all
+ * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
* @pcm: the PCM instance
*
- * Trigger SUSPEND to all substreams in the given pcm.
* After this call, all streams are changed to SUSPENDED state.
*/
int snd_pcm_suspend_all(struct snd_pcm *pcm)
@@ -1313,11 +1307,9 @@ static struct action_ops snd_pcm_action_prepare = {
};
/**
- * snd_pcm_prepare
+ * snd_pcm_prepare - prepare the PCM substream to be triggerable
* @substream: the PCM substream instance
* @file: file to refer f_flags
- *
- * Prepare the PCM substream to be triggerable.
*/
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
struct file *file)
diff --git a/sound/core/sound.c b/sound/core/sound.c
index c0685e2f0af..44a69bb8d4f 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -274,9 +274,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
return minor;
}
snd_minors[minor] = preg;
- preg->dev = device_create_drvdata(sound_class, device,
- MKDEV(major, minor),
- private_data, "%s", name);
+ preg->dev = device_create(sound_class, device, MKDEV(major, minor),
+ private_data, "%s", name);
if (IS_ERR(preg->dev)) {
snd_minors[minor] = NULL;
mutex_unlock(&sound_mutex);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index e5e749f3e0e..73be7e14a60 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -51,7 +51,7 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
if (err < 0)
return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
- if (err) < 0)
+ if (err < 0)
return err;
return 0;
}
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 83e90057270..c13a178383b 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -87,8 +87,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
- struct video_device *dev = video_devdata(file);
- struct snd_tea575x *tea = video_get_drvdata(dev);
+ struct snd_tea575x *tea = video_drvdata(file);
void __user *arg = (void __user *)data;
switch(cmd) {
@@ -175,6 +174,21 @@ static void snd_tea575x_release(struct video_device *vfd)
{
}
+static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file)
+{
+ struct snd_tea575x *tea = video_drvdata(file);
+
+ return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0;
+}
+
+static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file)
+{
+ struct snd_tea575x *tea = video_drvdata(file);
+
+ clear_bit(0, &tea->in_use);
+ return 0;
+}
+
/*
* initialize all the tea575x chips
*/
@@ -193,9 +207,10 @@ void snd_tea575x_init(struct snd_tea575x *tea)
tea->vd.release = snd_tea575x_release;
video_set_drvdata(&tea->vd, tea);
tea->vd.fops = &tea->fops;
+ tea->in_use = 0;
tea->fops.owner = tea->card->module;
- tea->fops.open = video_exclusive_open;
- tea->fops.release = video_exclusive_release;
+ tea->fops.open = snd_tea575x_exclusive_open;
+ tea->fops.release = snd_tea575x_exclusive_release;
tea->fops.ioctl = snd_tea575x_ioctl;
if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) {
snd_printk(KERN_ERR "unable to register tea575x tuner\n");
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index b63839e8f9b..456a1b4d783 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -30,7 +30,7 @@
**************************************************************************
*
* History
- * May 02, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 02, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
* Removed non existant WM9700
* Added support for WM9705, WM9708, WM9709, WM9710, WM9711
* WM9712 and WM9717
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index b493660deb3..e5d42399491 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -26,7 +26,7 @@
#include <asm/cpu/dac.h>
#include <asm/cpu/timer.h>
#include <asm/machvec.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
#include <asm/hd64461.h>
#define MODNAME "sh_dac_audio"
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 7d89c081a08..61aaedae6b7 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -560,19 +560,18 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
- device_create_drvdata(sound_class, NULL,
- MKDEV(SOUND_MAJOR, dev_list[i].minor),
- NULL, "%s", dev_list[i].name);
+ device_create(sound_class, NULL,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
+ "%s", dev_list[i].name);
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
- device_create_drvdata(sound_class, NULL,
- MKDEV(SOUND_MAJOR,
- dev_list[i].minor + (j*0x10)),
- NULL,
- "%s%d", dev_list[i].name, j);
+ device_create(sound_class, NULL,
+ MKDEV(SOUND_MAJOR,
+ dev_list[i].minor + (j*0x10)),
+ NULL, "%s%d", dev_list[i].name, j);
}
if (sound_nblocks >= 1024)
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 6ce3cbe98a6..6e831aff1bd 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -476,7 +476,7 @@ static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
}
/*
- * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
* removed broken wolfson00 patch.
* added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
*/
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index a7d89662acf..88fbf285d2b 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -759,7 +759,6 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
SPCS_GENERATIONSTATUS | 0x00001200 |
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
- }
#endif
return 0;
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 1a65775d28e..2eed2c8b98d 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -116,6 +116,7 @@ static int nvhdmi_build_pcms(struct hda_codec *codec)
codec->pcm_info = info;
info->name = "NVIDIA HDMI";
+ info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback;
return 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0b6e682c46d..e72707cb60a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -822,6 +822,27 @@ static void alc_sku_automute(struct hda_codec *codec)
spec->jack_present ? 0 : PIN_OUT);
}
+static void alc_mic_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int present;
+ unsigned int mic_nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
+ unsigned int fmic_nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
+ unsigned int mix_nid = spec->capsrc_nids[0];
+ unsigned int capsrc_idx_mic, capsrc_idx_fmic;
+
+ capsrc_idx_mic = mic_nid - 0x18;
+ capsrc_idx_fmic = fmic_nid - 0x18;
+ present = snd_hda_codec_read(codec, mic_nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (capsrc_idx_mic << 8) | (present ? 0 : 0x80));
+ snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (capsrc_idx_fmic << 8) | (present ? 0x80 : 0));
+ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
/* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
{
@@ -829,10 +850,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
res >>= 28;
else
res >>= 26;
- if (res != ALC880_HP_EVENT)
- return;
+ if (res == ALC880_HP_EVENT)
+ alc_sku_automute(codec);
+
+ if (res == ALC880_MIC_EVENT)
+ alc_mic_automute(codec);
+}
+static void alc_inithook(struct hda_codec *codec)
+{
alc_sku_automute(codec);
+ alc_mic_automute(codec);
}
/* additional initialization for ALC888 variants */
@@ -1018,10 +1046,17 @@ do_sku:
else
return;
}
+ if (spec->autocfg.hp_pins[0])
+ snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | ALC880_HP_EVENT);
- snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC880_HP_EVENT);
+ if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
+ spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
+ snd_hda_codec_write(codec,
+ spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | ALC880_MIC_EVENT);
spec->unsol_event = alc_sku_unsol_event;
}
@@ -3808,7 +3843,7 @@ static void alc880_auto_init(struct hda_codec *codec)
alc880_auto_init_extra_out(codec);
alc880_auto_init_analog_input(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
/*
@@ -5219,7 +5254,7 @@ static void alc260_auto_init(struct hda_codec *codec)
alc260_auto_init_multi_out(codec);
alc260_auto_init_analog_input(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -6629,7 +6664,7 @@ static void alc882_auto_init(struct hda_codec *codec)
alc882_auto_init_analog_input(codec);
alc882_auto_init_input_src(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
@@ -8306,8 +8341,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1043, 0x8317, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
@@ -8758,7 +8793,7 @@ static void alc883_auto_init(struct hda_codec *codec)
alc883_auto_init_analog_input(codec);
alc883_auto_init_input_src(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
static int patch_alc883(struct hda_codec *codec)
@@ -8802,8 +8837,13 @@ static int patch_alc883(struct hda_codec *codec)
switch (codec->vendor_id) {
case 0x10ec0888:
- spec->stream_name_analog = "ALC888 Analog";
- spec->stream_name_digital = "ALC888 Digital";
+ if (codec->revision_id == 0x100101) {
+ spec->stream_name_analog = "ALC1200 Analog";
+ spec->stream_name_digital = "ALC1200 Digital";
+ } else {
+ spec->stream_name_analog = "ALC888 Analog";
+ spec->stream_name_digital = "ALC888 Digital";
+ }
break;
case 0x10ec0889:
spec->stream_name_analog = "ALC889 Analog";
@@ -10285,7 +10325,7 @@ static void alc262_auto_init(struct hda_codec *codec)
alc262_auto_init_analog_input(codec);
alc262_auto_init_input_src(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
/*
@@ -10343,7 +10383,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
ALC262_TOSHIBA_RX1),
- SND_PCI_QUIRK(0x1179, 0x0268, "Toshiba S06", ALC262_TOSHIBA_S06),
+ SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
@@ -11417,7 +11457,7 @@ static void alc268_auto_init(struct hda_codec *codec)
alc268_auto_init_mono_speaker_out(codec);
alc268_auto_init_analog_input(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
/*
@@ -12200,7 +12240,7 @@ static void alc269_auto_init(struct hda_codec *codec)
alc269_auto_init_hp_out(codec);
alc269_auto_init_analog_input(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
/*
@@ -13281,7 +13321,7 @@ static void alc861_auto_init(struct hda_codec *codec)
alc861_auto_init_hp_out(codec);
alc861_auto_init_analog_input(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -14393,7 +14433,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
alc861vd_auto_init_analog_input(codec);
alc861vd_auto_init_input_src(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
static int patch_alc861vd(struct hda_codec *codec)
@@ -15667,7 +15707,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
- SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
+ SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
@@ -15680,6 +15720,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
@@ -16223,7 +16264,7 @@ static void alc662_auto_init(struct hda_codec *codec)
alc662_auto_init_analog_input(codec);
alc662_auto_init_input_src(codec);
if (spec->unsol_event)
- alc_sku_automute(codec);
+ alc_inithook(codec);
}
static int patch_alc662(struct hda_codec *codec)
@@ -16268,6 +16309,9 @@ static int patch_alc662(struct hda_codec *codec)
if (codec->vendor_id == 0x10ec0663) {
spec->stream_name_analog = "ALC663 Analog";
spec->stream_name_digital = "ALC663 Digital";
+ } else if (codec->vendor_id == 0x10ec0272) {
+ spec->stream_name_analog = "ALC272 Analog";
+ spec->stream_name_digital = "ALC272 Digital";
} else {
spec->stream_name_analog = "ALC662 Analog";
spec->stream_name_digital = "ALC662 Digital";
@@ -16305,6 +16349,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
{ .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
{ .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
+ { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -16323,7 +16368,10 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
.patch = patch_alc882 }, /* should be patch_alc883() in future */
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
+ { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
+ { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
+ .patch = patch_alc883 },
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c461baa83c2..a2ac7205d45 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -322,8 +322,8 @@ static hda_nid_t stac92hd71bxx_mux_nids[2] = {
0x1a, 0x1b
};
-static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
- 0x1c,
+static hda_nid_t stac92hd71bxx_dmux_nids[2] = {
+ 0x1c, 0x1d,
};
static hda_nid_t stac92hd71bxx_smux_nids[2] = {
@@ -861,20 +861,18 @@ static struct hda_verb stac92hd71bxx_core_init[] = {
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
/* connect headphone jack to dac1 */
{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
/* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
};
-#define HD_DISABLE_PORTF 3
+#define HD_DISABLE_PORTF 2
static struct hda_verb stac92hd71bxx_analog_core_init[] = {
/* start of config #1 */
/* connect port 0f to audio mixer */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
/* unmute right and left channels for node 0x0f */
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* start of config #2 */
@@ -883,10 +881,6 @@ static struct hda_verb stac92hd71bxx_analog_core_init[] = {
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
/* connect headphone jack to dac1 */
{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* connect port 0d to audio mixer */
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2},
- /* unmute dac0 input in audio mixer */
- { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
/* unmute right and left channels for nodes 0x0a, 0xd */
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -1107,6 +1101,7 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
STAC_INPUT_SOURCE(2),
+ STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
@@ -1119,8 +1114,17 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
*/
- HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT),
+
+ HDA_CODEC_MUTE("Import1 Mux Capture Switch", 0x17, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Import1 Mux Capture Volume", 0x17, 0x1, HDA_INPUT),
+
+ HDA_CODEC_MUTE("DAC0 Capture Switch", 0x17, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x17, 0x3, HDA_INPUT),
+
+ HDA_CODEC_MUTE("DAC1 Capture Switch", 0x17, 0x4, HDA_INPUT),
+ HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x17, 0x4, HDA_INPUT),
{ } /* end */
};
@@ -1649,7 +1653,7 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
static unsigned int ref92hd71bxx_pin_configs[11] = {
0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
- 0x0181302e, 0x01114010, 0x01019020, 0x90a000f0,
+ 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0,
0x90a000f0, 0x01452050, 0x01452050,
};
@@ -2812,7 +2816,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- hda_nid_t nid;
+ hda_nid_t nid = 0;
int i, err;
struct sigmatel_spec *spec = codec->spec;
@@ -3000,7 +3004,7 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
/* labels for amp mux outputs */
static const char *stac92xx_amp_labels[3] = {
- "Front Microphone", "Microphone", "Line In"
+ "Front Microphone", "Microphone", "Line In",
};
/* create amp out controls mux on capable codecs */
@@ -4327,6 +4331,16 @@ static struct hda_codec_ops stac92hd71bxx_patch_ops = {
#endif
};
+static struct hda_input_mux stac92hd71bxx_dmux = {
+ .num_items = 4,
+ .items = {
+ { "Analog Inputs", 0x00 },
+ { "Mixer", 0x01 },
+ { "Digital Mic 1", 0x02 },
+ { "Digital Mic 2", 0x03 },
+ }
+};
+
static int patch_stac92hd71bxx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
@@ -4341,6 +4355,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
spec->pin_nids = stac92hd71bxx_pin_nids;
+ memcpy(&spec->private_dimux, &stac92hd71bxx_dmux,
+ sizeof(stac92hd71bxx_dmux));
spec->board_config = snd_hda_check_board_config(codec,
STAC_92HD71BXX_MODELS,
stac92hd71bxx_models,
@@ -4392,6 +4408,7 @@ again:
/* no output amps */
spec->num_pwrs = 0;
spec->mixer = stac92hd71bxx_analog_mixer;
+ spec->dinput_mux = &spec->private_dimux;
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
@@ -4409,12 +4426,13 @@ again:
spec->num_pwrs = 0;
/* fallthru */
default:
+ spec->dinput_mux = &spec->private_dimux;
spec->mixer = stac92hd71bxx_analog_mixer;
spec->init = stac92hd71bxx_analog_core_init;
codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
}
- spec->aloopback_mask = 0x20;
+ spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
if (spec->board_config > STAC_92HD71BXX_REF) {
@@ -4456,6 +4474,10 @@ again:
spec->multiout.num_dacs = 1;
spec->multiout.hp_nid = 0x11;
spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
+ if (spec->dinput_mux)
+ spec->private_dimux.num_items +=
+ spec->num_dmics -
+ (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1);
err = stac92xx_parse_auto_config(codec, 0x21, 0x23);
if (!err) {
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index 20d0e328288..8f9e3859c37 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -666,6 +666,7 @@ static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM;
card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+ memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8);
ret = snd_ps3_change_avsetting(card);
@@ -685,6 +686,7 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
{
struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
struct snd_ps3_avsetting_info avs;
+ int ret;
avs = card->avs;
@@ -729,19 +731,92 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
return 1;
}
- if ((card->avs.avs_audio_width != avs.avs_audio_width) ||
- (card->avs.avs_audio_rate != avs.avs_audio_rate)) {
- card->avs = avs;
- snd_ps3_change_avsetting(card);
+ memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8);
+ if (memcmp(&card->avs, &avs, sizeof(avs))) {
pr_debug("%s: after freq=%d width=%d\n", __func__,
card->avs.avs_audio_rate, card->avs.avs_audio_width);
- return 0;
+ card->avs = avs;
+ snd_ps3_change_avsetting(card);
+ ret = 0;
} else
+ ret = 1;
+
+ /* check CS non-audio bit and mute accordingly */
+ if (avs.avs_cs_info[0] & 0x02)
+ ps3av_audio_mute_analog(1); /* mute if non-audio */
+ else
+ ps3av_audio_mute_analog(0);
+
+ return ret;
+}
+
+/*
+ * SPDIF status bits controls
+ */
+static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
+/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */
+static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ memset(ucontrol->value.iec958.status, 0xff, 8);
+ return 0;
+}
+
+static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8);
+ return 0;
+}
+
+static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) {
+ memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8);
return 1;
+ }
+ return 0;
}
+static struct snd_kcontrol_new spdif_ctls[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .info = snd_ps3_spdif_mask_info,
+ .get = snd_ps3_spdif_cmask_get,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+ .info = snd_ps3_spdif_mask_info,
+ .get = snd_ps3_spdif_pmask_get,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = snd_ps3_spdif_mask_info,
+ .get = snd_ps3_spdif_default_get,
+ .put = snd_ps3_spdif_default_put,
+ },
+};
static int snd_ps3_map_mmio(void)
@@ -842,7 +917,7 @@ static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
{
- int ret;
+ int i, ret;
u64 lpar_addr, lpar_size;
BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
@@ -903,6 +978,15 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
strcpy(the_card.card->driver, "PS3");
strcpy(the_card.card->shortname, "PS3");
strcpy(the_card.card->longname, "PS3 sound");
+
+ /* create control elements */
+ for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) {
+ ret = snd_ctl_add(the_card.card,
+ snd_ctl_new1(&spdif_ctls[i], &the_card));
+ if (ret < 0)
+ goto clean_card;
+ }
+
/* create PCM devices instance */
/* NOTE:this driver works assuming pcm:substream = 1:1 */
ret = snd_pcm_new(the_card.card,
diff --git a/sound/ppc/snd_ps3.h b/sound/ppc/snd_ps3.h
index 4b7e6fbbe50..326fb29e82d 100644
--- a/sound/ppc/snd_ps3.h
+++ b/sound/ppc/snd_ps3.h
@@ -51,6 +51,7 @@ struct snd_ps3_avsetting_info {
uint32_t avs_audio_width;
uint32_t avs_audio_format; /* fixed */
uint32_t avs_audio_source; /* fixed */
+ unsigned char avs_cs_info[8];
};
/*
* PS3 audio 'card' instance
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c
index 98a2d5826a8..b1966e4dfcd 100644
--- a/sound/soc/at32/playpaq_wm8510.c
+++ b/sound/soc/at32/playpaq_wm8510.c
@@ -304,7 +304,7 @@ static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
-static const char *intercon[][3] = {
+static const struct snd_soc_dapm_route intercon[] = {
/* speaker connected to SPKOUT */
{"Ext Spk", NULL, "SPKOUTP"},
{"Ext Spk", NULL, "SPKOUTN"},
@@ -312,9 +312,6 @@ static const char *intercon[][3] = {
{"Mic Bias", NULL, "Int Mic"},
{"MICN", NULL, "Mic Bias"},
{"MICP", NULL, "Mic Bias"},
-
- /* Terminator */
- {NULL, NULL, NULL},
};
@@ -334,11 +331,8 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
/*
* Setup audio path interconnects
*/
- for (i = 0; intercon[i][0] != NULL; i++) {
- snd_soc_dapm_connect_input(codec,
- intercon[i][0],
- intercon[i][1], intercon[i][2]);
- }
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
/* always connected pins */
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
index 905186502e0..85a883299c2 100644
--- a/sound/soc/at91/Kconfig
+++ b/sound/soc/at91/Kconfig
@@ -8,20 +8,3 @@ config SND_AT91_SOC
config SND_AT91_SOC_SSC
tristate
-
-config SND_AT91_SOC_ETI_B1_WM8731
- tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
- depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
- select SND_AT91_SOC_SSC
- select SND_SOC_WM8731
- help
- Say Y if you want to add support for SoC audio on WM8731-based
- Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
-
-config SND_AT91_SOC_ETI_SLAVE
- bool "Run codec in slave Mode on Endrelia boards"
- depends on SND_AT91_SOC_ETI_B1_WM8731
- default n
- help
- Say Y if you want to run with the AT91 SSC generating the BCLK
- and LRC signals on Endrelia boards.
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
index f23da17cc32..b817f11df28 100644
--- a/sound/soc/at91/Makefile
+++ b/sound/soc/at91/Makefile
@@ -4,8 +4,3 @@ snd-soc-at91-ssc-objs := at91-ssc.o
obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
-
-# AT91 Machine Support
-snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
-
-obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
index a5b1a79ebff..1b61cc46126 100644
--- a/sound/soc/at91/at91-ssc.c
+++ b/sound/soc/at91/at91-ssc.c
@@ -5,7 +5,7 @@
* Endrelia Technologies Inc.
*
* Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644
index 684781e4088..00000000000
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 29, 2006
- *
- * Based on corgi.c by:
- *
- * Copyright 2005 Wolfson Microelectronics PLC.
- * Copyright 2005 Openedhand Ltd.
- *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- * Richard Purdie <richard@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-
-#include "../codecs/wm8731.h"
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x)
-#else
-#define DBG(x...)
-#endif
-
-static struct clk *pck1_clk;
-static struct clk *pllb_clk;
-
-
-static int eti_b1_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* cpu clock is the AT91 master clock sent to the SSC */
- ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
- 60000000, SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- /* codec system clock is supplied by PCK1, set to 12MHz */
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
- 12000000, SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- /* Start PCK1 clock. */
- clk_enable(pck1_clk);
- DBG("pck1 started\n");
-
- return 0;
-}
-
-static void eti_b1_shutdown(struct snd_pcm_substream *substream)
-{
- /* Stop PCK1 clock. */
- clk_disable(pck1_clk);
- DBG("pck1 stopped\n");
-}
-
-static int eti_b1_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
- unsigned int rate;
- int cmr_div, period;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /*
- * The SSC clock dividers depend on the sample rate. The CMR.DIV
- * field divides the system master clock MCK to drive the SSC TK
- * signal which provides the codec BCLK. The TCMR.PERIOD and
- * RCMR.PERIOD fields further divide the BCLK signal to drive
- * the SSC TF and RF signals which provide the codec DACLRC and
- * ADCLRC clocks.
- *
- * The dividers were determined through trial and error, where a
- * CMR.DIV value is chosen such that the resulting BCLK value is
- * divisible, or almost divisible, by (2 * sample rate), and then
- * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
- */
- rate = params_rate(params);
-
- switch (rate) {
- case 8000:
- cmr_div = 25; /* BCLK = 60MHz/(2*25) = 1.2MHz */
- period = 74; /* LRC = BCLK/(2*(74+1)) = 8000Hz */
- break;
- case 32000:
- cmr_div = 7; /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
- period = 66; /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
- break;
- case 48000:
- cmr_div = 13; /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
- period = 23; /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
- break;
- default:
- printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
- return -EINVAL;
- }
-
- /* set the MCK divider for BCLK */
- ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
- if (ret < 0)
- return ret;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* set the BCLK divider for DACLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- AT91SSC_TCMR_PERIOD, period);
- } else {
- /* set the BCLK divider for ADCLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- AT91SSC_RCMR_PERIOD, period);
- }
- if (ret < 0)
- return ret;
-
-#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
- /*
- * Codec in Master Mode.
- */
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
-#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-
- return 0;
-}
-
-static struct snd_soc_ops eti_b1_ops = {
- .startup = eti_b1_startup,
- .hw_params = eti_b1_hw_params,
- .shutdown = eti_b1_shutdown,
-};
-
-
-static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-
- /* speaker connected to LHPOUT */
- {"Ext Spk", NULL, "LHPOUT"},
-
- /* mic is connected to Mic Jack, with WM8731 Mic Bias */
- {"MICIN", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Int Mic"},
-};
-
-/*
- * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
- */
-static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
-{
- DBG("eti_b1_wm8731_init() called\n");
-
- /* Add specific widgets */
- snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
- ARRAY_SIZE(eti_b1_dapm_widgets));
-
- /* Set up specific audio path interconnects */
- snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
-
- /* not connected */
- snd_soc_dapm_disable_pin(codec, "RLINEIN");
- snd_soc_dapm_disable_pin(codec, "LLINEIN");
-
- /* always connected */
- snd_soc_dapm_enable_pin(codec, "Int Mic");
- snd_soc_dapm_enable_pin(codec, "Ext Spk");
-
- snd_soc_dapm_sync(codec);
-
- return 0;
-}
-
-static struct snd_soc_dai_link eti_b1_dai = {
- .name = "WM8731",
- .stream_name = "WM8731 PCM",
- .cpu_dai = &at91_ssc_dai[1],
- .codec_dai = &wm8731_dai,
- .init = eti_b1_wm8731_init,
- .ops = &eti_b1_ops,
-};
-
-static struct snd_soc_machine snd_soc_machine_eti_b1 = {
- .name = "ETI_B1_WM8731",
- .dai_link = &eti_b1_dai,
- .num_links = 1,
-};
-
-static struct wm8731_setup_data eti_b1_wm8731_setup = {
- .i2c_bus = 0,
- .i2c_address = 0x1a,
-};
-
-static struct snd_soc_device eti_b1_snd_devdata = {
- .machine = &snd_soc_machine_eti_b1,
- .platform = &at91_soc_platform,
- .codec_dev = &soc_codec_dev_wm8731,
- .codec_data = &eti_b1_wm8731_setup,
-};
-
-static struct platform_device *eti_b1_snd_device;
-
-static int __init eti_b1_init(void)
-{
- int ret;
- struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
- if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
- DBG("SSC1 memory region is busy\n");
- return -EBUSY;
- }
-
- ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
- if (!ssc->base) {
- DBG("SSC1 memory ioremap failed\n");
- ret = -ENOMEM;
- goto fail_release_mem;
- }
-
- ssc->pid = AT91RM9200_ID_SSC1;
-
- eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
- if (!eti_b1_snd_device) {
- DBG("platform device allocation failed\n");
- ret = -ENOMEM;
- goto fail_io_unmap;
- }
-
- platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
- eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
-
- ret = platform_device_add(eti_b1_snd_device);
- if (ret) {
- DBG("platform device add failed\n");
- platform_device_put(eti_b1_snd_device);
- goto fail_io_unmap;
- }
-
- at91_set_A_periph(AT91_PIN_PB6, 0); /* TF1 */
- at91_set_A_periph(AT91_PIN_PB7, 0); /* TK1 */
- at91_set_A_periph(AT91_PIN_PB8, 0); /* TD1 */
- at91_set_A_periph(AT91_PIN_PB9, 0); /* RD1 */
-/* at91_set_A_periph(AT91_PIN_PB10, 0);*/ /* RK1 */
- at91_set_A_periph(AT91_PIN_PB11, 0); /* RF1 */
-
- /*
- * Set PCK1 parent to PLLB and its rate to 12 Mhz.
- */
- pllb_clk = clk_get(NULL, "pllb");
- pck1_clk = clk_get(NULL, "pck1");
-
- clk_set_parent(pck1_clk, pllb_clk);
- clk_set_rate(pck1_clk, 12000000);
-
- DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
-
- /* assign the GPIO pin to PCK1 */
- at91_set_B_periph(AT91_PIN_PA24, 0);
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
- printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
-#else
- printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
-#endif
- return ret;
-
-fail_io_unmap:
- iounmap(ssc->base);
-fail_release_mem:
- release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
- return ret;
-}
-
-static void __exit eti_b1_exit(void)
-{
- struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
- clk_put(pck1_clk);
- clk_put(pllb_clk);
-
- platform_device_unregister(eti_b1_snd_device);
-
- iounmap(ssc->base);
- release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-}
-
-module_init(eti_b1_init);
-module_exit(eti_b1_exit);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index f98331d099e..dc006206f62 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -17,6 +17,22 @@ config SND_BF5XX_SOC_SSM2602
help
Say Y if you want to add support for SoC audio on BF527-EZKIT.
+config SND_BF5XX_SOC_AD73311
+ tristate "SoC AD73311 Audio support for Blackfin"
+ depends on SND_BF5XX_I2S
+ select SND_BF5XX_SOC_I2S
+ select SND_SOC_AD73311
+ help
+ Say Y if you want to add support for AD73311 codec on Blackfin.
+
+config SND_BFIN_AD73311_SE
+ int "PF pin for AD73311L Chip Select"
+ depends on SND_BF5XX_SOC_AD73311
+ default 4
+ help
+ Enter the GPIO used to control AD73311's SE pin. Acceptable
+ values are 0 to 7
+
config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip"
depends on BLACKFIN && SND_SOC
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 9ea8bd9e0ba..97bb37a6359 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
# Blackfin Machine Support
snd-ad1980-objs := bf5xx-ad1980.o
snd-ssm2602-objs := bf5xx-ssm2602.o
-
+snd-ad73311-objs := bf5xx-ad73311.o
obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
+obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 51f4907c483..25e50d2ea1e 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
sport->tx_pos += runtime->period_size;
if (sport->tx_pos >= runtime->buffer_size)
sport->tx_pos %= runtime->buffer_size;
+ sport->tx_delay_pos = sport->tx_pos;
} else {
bf5xx_ac97_to_pcm(
(struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
@@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
struct snd_pcm_substream *pcm = data;
#if defined(CONFIG_SND_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = pcm->runtime;
+ struct sport_device *sport = runtime->private_data;
bf5xx_mmap_copy(pcm, runtime->period_size);
+ if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (sport->once == 0) {
+ snd_pcm_period_elapsed(pcm);
+ bf5xx_mmap_copy(pcm, runtime->period_size);
+ sport->once = 1;
+ }
+ }
#endif
snd_pcm_period_elapsed(pcm);
}
@@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ memset(runtime->dma_area, 0, runtime->buffer_size);
snd_pcm_lib_free_pages(substream);
return 0;
}
@@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
* SPORT working in TMD mode(include AC97).
*/
#if defined(CONFIG_SND_MMAP_SUPPORT)
- size_t size = bf5xx_pcm_hardware.buffer_bytes_max
- * sizeof(struct ac97_frame) / 4;
- /*clean up intermediate buffer*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- memset(sport->tx_dma_buf, 0, size);
sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
runtime->period_size * sizeof(struct ac97_frame));
} else {
- memset(sport->rx_dma_buf, 0, size);
sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
runtime->period_size * sizeof(struct ac97_frame));
@@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
pr_debug("%s enter\n", __func__);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ bf5xx_mmap_copy(substream, runtime->period_size);
+ snd_pcm_period_elapsed(substream);
+ sport->tx_delay_pos = 0;
sport_tx_start(sport);
+ }
else
sport_rx_start(sport);
break;
@@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
#if defined(CONFIG_SND_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- curr = sport->tx_pos;
+ curr = sport->tx_delay_pos;
else
curr = sport->rx_pos;
#else
@@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
+static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct sport_device *sport = runtime->private_data;
+
+ pr_debug("%s enter\n", __func__);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ sport->once = 0;
+ memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+ } else
+ memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+
+ return 0;
+}
+
#ifdef CONFIG_SND_MMAP_SUPPORT
static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
@@ -272,6 +299,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
.open = bf5xx_pcm_open,
+ .close = bf5xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = bf5xx_pcm_hw_params,
.hw_free = bf5xx_pcm_hw_free,
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index c782e311fd5..5e5aafb6485 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -129,7 +129,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
struct ac97_frame *nextwrite;
sport_incfrag(sport, &nextfrag, 1);
- sport_incfrag(sport, &nextfrag, 1);
nextwrite = (struct ac97_frame *)(sport->tx_buf + \
nextfrag * sport->tx_fragsize);
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644
index 00000000000..622c9b90953
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -0,0 +1,240 @@
+/*
+ * File: sound/soc/blackfin/bf5xx-ad73311.c
+ * Author: Cliff Cai <Cliff.Cai@analog.com>
+ *
+ * Created: Thur Sep 25 2008
+ * Description: Board driver for ad73311 sound chip
+ *
+ * Modified:
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include "../codecs/ad73311.h"
+#include "bf5xx-sport.h"
+#include "bf5xx-i2s-pcm.h"
+#include "bf5xx-i2s.h"
+
+#if CONFIG_SND_BF5XX_SPORT_NUM == 0
+#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
+#define bfin_read_SPORT_TCR1 bfin_read_SPORT0_TCR1
+#define bfin_write_SPORT_TCR2 bfin_write_SPORT0_TCR2
+#define bfin_write_SPORT_TX16 bfin_write_SPORT0_TX16
+#define bfin_read_SPORT_STAT bfin_read_SPORT0_STAT
+#else
+#define bfin_write_SPORT_TCR1 bfin_write_SPORT1_TCR1
+#define bfin_read_SPORT_TCR1 bfin_read_SPORT1_TCR1
+#define bfin_write_SPORT_TCR2 bfin_write_SPORT1_TCR2
+#define bfin_write_SPORT_TX16 bfin_write_SPORT1_TX16
+#define bfin_read_SPORT_STAT bfin_read_SPORT1_STAT
+#endif
+
+#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
+
+static struct snd_soc_machine bf5xx_ad73311;
+
+static int snd_ad73311_startup(void)
+{
+ pr_debug("%s enter\n", __func__);
+
+ /* Pull up SE pin on AD73311L */
+ gpio_set_value(GPIO_SE, 1);
+ return 0;
+}
+
+static int snd_ad73311_configure(void)
+{
+ unsigned short ctrl_regs[6];
+ unsigned short status = 0;
+ int count = 0;
+
+ /* DMCLK = MCLK = 16.384 MHz
+ * SCLK = DMCLK/8 = 2.048 MHz
+ * Sample Rate = DMCLK/2048 = 8 KHz
+ */
+ ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
+ REGB_SCDIV(0) | REGB_DIRATE(0);
+ ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
+ REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
+ ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
+ REGD_IGS(2);
+ ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
+ ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
+ ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
+
+ local_irq_disable();
+ snd_ad73311_startup();
+ udelay(1);
+
+ bfin_write_SPORT_TCR1(TFSR);
+ bfin_write_SPORT_TCR2(0xF);
+ SSYNC();
+
+ /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
+ * FIFO before enable SPORT to transfer the data
+ */
+ for (count = 0; count < 6; count++)
+ bfin_write_SPORT_TX16(ctrl_regs[count]);
+ SSYNC();
+ bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
+ SSYNC();
+
+ /* When TUVF is set, the data is already send out */
+ while (!(status & TUVF) && count++ < 10000) {
+ udelay(1);
+ status = bfin_read_SPORT_STAT();
+ SSYNC();
+ }
+ bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
+ SSYNC();
+ local_irq_enable();
+
+ if (count == 10000) {
+ printk(KERN_ERR "ad73311: failed to configure codec\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int bf5xx_probe(struct platform_device *pdev)
+{
+ int err;
+ if (gpio_request(GPIO_SE, "AD73311_SE")) {
+ printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
+ return -EBUSY;
+ }
+
+ gpio_direction_output(GPIO_SE, 0);
+
+ err = snd_ad73311_configure();
+ if (err < 0)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ pr_debug("%s enter\n", __func__);
+ cpu_dai->private_data = sport_handle;
+ return 0;
+}
+
+static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret = 0;
+
+ pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
+ params_format(params));
+
+ /* set cpu DAI configuration */
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+static struct snd_soc_ops bf5xx_ad73311_ops = {
+ .startup = bf5xx_ad73311_startup,
+ .hw_params = bf5xx_ad73311_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_ad73311_dai = {
+ .name = "ad73311",
+ .stream_name = "AD73311",
+ .cpu_dai = &bf5xx_i2s_dai,
+ .codec_dai = &ad73311_dai,
+ .ops = &bf5xx_ad73311_ops,
+};
+
+static struct snd_soc_machine bf5xx_ad73311 = {
+ .name = "bf5xx_ad73311",
+ .probe = bf5xx_probe,
+ .dai_link = &bf5xx_ad73311_dai,
+ .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
+ .machine = &bf5xx_ad73311,
+ .platform = &bf5xx_i2s_soc_platform,
+ .codec_dev = &soc_codec_dev_ad73311,
+};
+
+static struct platform_device *bf52x_ad73311_snd_device;
+
+static int __init bf5xx_ad73311_init(void)
+{
+ int ret;
+
+ pr_debug("%s enter\n", __func__);
+ bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!bf52x_ad73311_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
+ bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
+ ret = platform_device_add(bf52x_ad73311_snd_device);
+
+ if (ret)
+ platform_device_put(bf52x_ad73311_snd_device);
+
+ return ret;
+}
+
+static void __exit bf5xx_ad73311_exit(void)
+{
+ pr_debug("%s enter\n", __func__);
+ platform_device_unregister(bf52x_ad73311_snd_device);
+}
+
+module_init(bf5xx_ad73311_init);
+module_exit(bf5xx_ad73311_exit);
+
+/* Module information */
+MODULE_AUTHOR("Cliff Cai");
+MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 43a4092eeb8..827587f0818 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -70,6 +70,13 @@ static struct sport_param sport_params[2] = {
}
};
+static u16 sport_req[][7] = {
+ { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
+ { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
+};
+
static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
@@ -78,6 +85,14 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
/* interface format:support I2S,slave mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
+ bf5xx_i2s.tcr1 |= TFSR | TCKFE;
+ bf5xx_i2s.rcr1 |= RFSR | RCKFE;
+ bf5xx_i2s.tcr2 |= TSFSE;
+ bf5xx_i2s.rcr2 |= RSFSE;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ bf5xx_i2s.tcr1 |= TFSR;
+ bf5xx_i2s.rcr1 |= RFSR;
break;
case SND_SOC_DAIFMT_LEFT_J:
ret = -EINVAL;
@@ -127,14 +142,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
bf5xx_i2s.tcr2 |= 15;
bf5xx_i2s.rcr2 |= 15;
+ sport_handle->wdsize = 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
bf5xx_i2s.tcr2 |= 23;
bf5xx_i2s.rcr2 |= 23;
+ sport_handle->wdsize = 3;
break;
case SNDRV_PCM_FORMAT_S32_LE:
bf5xx_i2s.tcr2 |= 31;
bf5xx_i2s.rcr2 |= 31;
+ sport_handle->wdsize = 4;
break;
}
@@ -145,17 +163,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
* need to configure both of them at the time when the first
* stream is opened.
*
- * CPU DAI format:I2S, slave mode.
+ * CPU DAI:slave mode.
*/
- ret = sport_config_rx(sport_handle, RFSR | RCKFE,
- RSFSE|bf5xx_i2s.rcr2, 0, 0);
+ ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
+ bf5xx_i2s.rcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
}
- ret = sport_config_tx(sport_handle, TFSR | TCKFE,
- TSFSE|bf5xx_i2s.tcr2, 0, 0);
+ ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
+ bf5xx_i2s.tcr2, 0, 0);
if (ret) {
pr_err("SPORT is busy!\n");
return -EBUSY;
@@ -174,13 +192,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
static int bf5xx_i2s_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- u16 sport_req[][7] = {
- { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
- P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
- { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
- P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
- };
-
pr_debug("%s enter\n", __func__);
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
pr_err("Requesting Peripherals failed\n");
@@ -198,6 +209,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
return 0;
}
+static void bf5xx_i2s_remove(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ pr_debug("%s enter\n", __func__);
+ peripheral_free_list(&sport_req[sport_num][0]);
+}
+
#ifdef CONFIG_PM
static int bf5xx_i2s_suspend(struct platform_device *dev,
struct snd_soc_dai *dai)
@@ -263,15 +281,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
.id = 0,
.type = SND_SOC_DAI_I2S,
.probe = bf5xx_i2s_probe,
+ .remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend,
.resume = bf5xx_i2s_resume,
.playback = {
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = BF5XX_I2S_RATES,
.formats = BF5XX_I2S_FORMATS,},
.capture = {
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = BF5XX_I2S_RATES,
.formats = BF5XX_I2S_FORMATS,},
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 4c163454bbf..fcadcc081f7 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -123,6 +123,8 @@ struct sport_device {
int rx_pos;
unsigned int tx_buffer_size;
unsigned int rx_buffer_size;
+ int tx_delay_pos;
+ int once;
#endif
void *private_data;
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e0b9869df0f..38a0e3b620a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -3,9 +3,11 @@ config SND_SOC_ALL_CODECS
depends on I2C
select SPI
select SPI_MASTER
+ select SND_SOC_AD73311
select SND_SOC_AK4535
select SND_SOC_CS4270
select SND_SOC_SSM2602
+ select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC26
select SND_SOC_TLV320AIC3X
select SND_SOC_UDA1380
@@ -34,6 +36,9 @@ config SND_SOC_AC97_CODEC
config SND_SOC_AD1980
tristate
+config SND_SOC_AD73311
+ tristate
+
config SND_SOC_AK4535
tristate
@@ -58,9 +63,13 @@ config SND_SOC_CS4270_VD33_ERRATA
config SND_SOC_SSM2602
tristate
+config SND_SOC_TLV320AIC23
+ tristate
+ depends on I2C
+
config SND_SOC_TLV320AIC26
- tristate "TI TLV320AIC26 Codec support"
- depends on SND_SOC && SPI
+ tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
+ depends on SPI
config SND_SOC_TLV320AIC3X
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f977978a340..90f0a585fc7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,8 +1,10 @@
snd-soc-ac97-objs := ac97.o
snd-soc-ad1980-objs := ad1980.o
+snd-soc-ad73311-objs := ad73311.o
snd-soc-ak4535-objs := ak4535.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-ssm2602-objs := ssm2602.o
+snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-uda1380-objs := uda1380.o
@@ -20,9 +22,11 @@ snd-soc-wm9713-objs := wm9713.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
+obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 61fd96ca7bc..bd1ebdc6c86 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -2,8 +2,7 @@
* ac97.c -- ALSA Soc AC97 codec support
*
* Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 4e09c1f2c06..1397b8e06c0 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <sound/core.h>
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
new file mode 100644
index 00000000000..37af8607b00
--- /dev/null
+++ b/sound/soc/codecs/ad73311.c
@@ -0,0 +1,107 @@
+/*
+ * ad73311.c -- ALSA Soc AD73311 codec support
+ *
+ * Copyright: Analog Device Inc.
+ * Author: Cliff Cai <cliff.cai@analog.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Revision history
+ * 25th Sep 2008 Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "ad73311.h"
+
+struct snd_soc_dai ad73311_dai = {
+ .name = "AD73311",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+};
+EXPORT_SYMBOL_GPL(ad73311_dai);
+
+static int ad73311_soc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+ mutex_init(&codec->mutex);
+ codec->name = "AD73311";
+ codec->owner = THIS_MODULE;
+ codec->dai = &ad73311_dai;
+ codec->num_dai = 1;
+ socdev->codec = codec;
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "ad73311: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ ret = snd_soc_register_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "ad73311: failed to register card\n");
+ goto register_err;
+ }
+
+ return ret;
+
+register_err:
+ snd_soc_free_pcms(socdev);
+pcm_err:
+ kfree(socdev->codec);
+ socdev->codec = NULL;
+ return ret;
+}
+
+static int ad73311_soc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ if (codec == NULL)
+ return 0;
+ snd_soc_free_pcms(socdev);
+ kfree(codec);
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ad73311 = {
+ .probe = ad73311_soc_probe,
+ .remove = ad73311_soc_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
+
+MODULE_DESCRIPTION("ASoC ad73311 driver");
+MODULE_AUTHOR("Cliff Cai ");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
new file mode 100644
index 00000000000..507ce0c30ed
--- /dev/null
+++ b/sound/soc/codecs/ad73311.h
@@ -0,0 +1,90 @@
+/*
+ * File: sound/soc/codec/ad73311.h
+ * Based on:
+ * Author: Cliff Cai <cliff.cai@analog.com>
+ *
+ * Created: Thur Sep 25, 2008
+ * Description: definitions for AD73311 registers
+ *
+ *
+ * Modified:
+ * Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AD73311_H__
+#define __AD73311_H__
+
+#define AD_CONTROL 0x8000
+#define AD_DATA 0x0000
+#define AD_READ 0x4000
+#define AD_WRITE 0x0000
+
+/* Control register A */
+#define CTRL_REG_A (0 << 8)
+
+#define REGA_MODE_PRO 0x00
+#define REGA_MODE_DATA 0x01
+#define REGA_MODE_MIXED 0x03
+#define REGA_DLB 0x04
+#define REGA_SLB 0x08
+#define REGA_DEVC(x) ((x & 0x7) << 4)
+#define REGA_RESET 0x80
+
+/* Control register B */
+#define CTRL_REG_B (1 << 8)
+
+#define REGB_DIRATE(x) (x & 0x3)
+#define REGB_SCDIV(x) ((x & 0x3) << 2)
+#define REGB_MCDIV(x) ((x & 0x7) << 4)
+#define REGB_CEE (1 << 7)
+
+/* Control register C */
+#define CTRL_REG_C (2 << 8)
+
+#define REGC_PUDEV (1 << 0)
+#define REGC_PUADC (1 << 3)
+#define REGC_PUDAC (1 << 4)
+#define REGC_PUREF (1 << 5)
+#define REGC_REFUSE (1 << 6)
+
+/* Control register D */
+#define CTRL_REG_D (3 << 8)
+
+#define REGD_IGS(x) (x & 0x7)
+#define REGD_RMOD (1 << 3)
+#define REGD_OGS(x) ((x & 0x7) << 4)
+#define REGD_MUTE (x << 7)
+
+/* Control register E */
+#define CTRL_REG_E (4 << 8)
+
+#define REGE_DA(x) (x & 0x1f)
+#define REGE_IBYP (1 << 5)
+
+/* Control register F */
+#define CTRL_REG_F (5 << 8)
+
+#define REGF_SEEN (1 << 5)
+#define REGF_INV (1 << 6)
+#define REGF_ALB (1 << 7)
+
+extern struct snd_soc_dai ad73311_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ad73311;
+#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 088cf992772..2a89b5888e1 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -28,7 +28,6 @@
#include "ak4535.h"
-#define AUDIO_NAME "ak4535"
#define AK4535_VERSION "0.3"
struct snd_soc_codec_device soc_codec_dev_ak4535;
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 940ce1c3522..44ef0dacd56 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -42,7 +42,6 @@
#include "ssm2602.h"
-#define AUDIO_NAME "ssm2602"
#define SSM2602_VERSION "0.1"
struct snd_soc_codec_device soc_codec_dev_ssm2602;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
new file mode 100644
index 00000000000..44308dac9e1
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -0,0 +1,714 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * 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.
+ *
+ * Notes:
+ * The AIC23 is a driver for a low power stereo audio
+ * codec tlv320aic23
+ *
+ * The machine layer should disable unsupported inputs/outputs by
+ * snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+
+#include "tlv320aic23.h"
+
+#define AIC23_VERSION "0.1"
+
+struct tlv320aic23_srate_reg_info {
+ u32 sample_rate;
+ u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
+ u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
+/*
+ * AIC23 register cache
+ */
+static const u16 tlv320aic23_reg[] = {
+ 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
+ 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
+ 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
+};
+
+/*
+ * read tlv320aic23 register cache
+ */
+static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
+ *codec, unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+ return -1;
+ return cache[reg];
+}
+
+/*
+ * write tlv320aic23 register cache
+ */
+static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, u16 value)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * write to the tlv320aic23 register space
+ */
+static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+
+ u8 data[2];
+
+ /* TLV320AIC23 has 7 bit address and 9 bits of data
+ * so we need to switch one data bit into reg and rest
+ * of data into val
+ */
+
+ if ((reg < 0 || reg > 9) && (reg != 15)) {
+ printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg);
+ return -1;
+ }
+
+ data[0] = (reg << 1) | (value >> 8 & 0x01);
+ data[1] = value & 0xff;
+
+ tlv320aic23_write_reg_cache(codec, reg, value);
+
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+
+ printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
+ value, reg);
+
+ return -EIO;
+}
+
+static const char *rec_src_text[] = { "Line", "Mic" };
+static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+
+static const struct soc_enum rec_src_enum =
+ SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+
+static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
+SOC_DAPM_ENUM("Input Select", rec_src_enum);
+
+static const struct soc_enum tlv320aic23_rec_src =
+ SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+static const struct soc_enum tlv320aic23_deemph =
+ SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
+
+static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
+static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
+
+static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 val, reg;
+
+ val = (ucontrol->value.integer.value[0] & 0x07);
+
+ /* linear conversion to userspace
+ * 000 = -6db
+ * 001 = -9db
+ * 010 = -12db
+ * 011 = -18db (Min)
+ * 100 = 0db (Max)
+ */
+ val = (val >= 4) ? 4 : (3 - val);
+
+ reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
+ tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+
+ return 0;
+}
+
+static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 val;
+
+ val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+ val = val >> 6;
+ val = (val >= 4) ? 4 : (3 - val);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+
+}
+
+#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
+ .put = snd_soc_tlv320aic23_put_volsw, \
+ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
+ TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
+ SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
+ SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
+ TLV320AIC23_RINVOL, 7, 1, 0),
+ SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
+ TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
+ SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
+ SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
+ SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
+ 6, 4, 0, sidetone_vol_tlv),
+ SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
+};
+
+/* add non dapm controls */
+static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
+{
+
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&tlv320aic23_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+
+}
+
+/* PGA Mixer controls for Line and Mic switch */
+static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
+ SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
+ SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
+ SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
+ SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
+ &tlv320aic23_rec_src_mux_controls),
+ SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
+ &tlv320aic23_output_mixer_controls[0],
+ ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
+ SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
+
+ SND_SOC_DAPM_OUTPUT("LHPOUT"),
+ SND_SOC_DAPM_OUTPUT("RHPOUT"),
+ SND_SOC_DAPM_OUTPUT("LOUT"),
+ SND_SOC_DAPM_OUTPUT("ROUT"),
+
+ SND_SOC_DAPM_INPUT("LLINEIN"),
+ SND_SOC_DAPM_INPUT("RLINEIN"),
+
+ SND_SOC_DAPM_INPUT("MICIN"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ /* Output Mixer */
+ {"Output Mixer", "Line Bypass Switch", "Line Input"},
+ {"Output Mixer", "Playback Switch", "DAC"},
+ {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
+
+ /* Outputs */
+ {"RHPOUT", NULL, "Output Mixer"},
+ {"LHPOUT", NULL, "Output Mixer"},
+ {"LOUT", NULL, "Output Mixer"},
+ {"ROUT", NULL, "Output Mixer"},
+
+ /* Inputs */
+ {"Line Input", "NULL", "LLINEIN"},
+ {"Line Input", "NULL", "RLINEIN"},
+
+ {"Mic Input", "NULL", "MICIN"},
+
+ /* input mux */
+ {"Capture Source", "Line", "Line Input"},
+ {"Capture Source", "Mic", "Mic Input"},
+ {"ADC", NULL, "Capture Source"},
+
+};
+
+/* tlv320aic23 related */
+static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
+ {4000, 0x06, 1}, /* 4000 */
+ {8000, 0x06, 0}, /* 8000 */
+ {16000, 0x0C, 1}, /* 16000 */
+ {22050, 0x11, 1}, /* 22050 */
+ {24000, 0x00, 1}, /* 24000 */
+ {32000, 0x0C, 0}, /* 32000 */
+ {44100, 0x11, 0}, /* 44100 */
+ {48000, 0x00, 0}, /* 48000 */
+ {88200, 0x1F, 0}, /* 88200 */
+ {96000, 0x0E, 0}, /* 96000 */
+};
+
+static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+ ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+ /* set up audio path interconnects */
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ u16 iface_reg, data;
+ u8 count = 0;
+
+ iface_reg =
+ tlv320aic23_read_reg_cache(codec,
+ TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
+ /* Search for the right sample rate */
+ /* Verify what happens if the rate is not supported
+ * now it goes to 96Khz */
+ while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
+ (count < ARRAY_SIZE(srate_reg_info))) {
+ count++;
+ }
+
+ data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
+ (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
+ TLV320AIC23_USB_CLK_ON;
+
+ tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface_reg |= (0x01 << 2);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface_reg |= (0x02 << 2);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ iface_reg |= (0x03 << 2);
+ break;
+ }
+ tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+ return 0;
+}
+
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+
+ /* set active */
+ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+
+ return 0;
+}
+
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+
+ /* deactivate */
+ if (!codec->active) {
+ udelay(50);
+ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+ }
+}
+
+static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 reg;
+
+ reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+ if (mute)
+ reg |= TLV320AIC23_DACM_MUTE;
+
+ else
+ reg &= ~TLV320AIC23_DACM_MUTE;
+
+ tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+
+ return 0;
+}
+
+static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface_reg;
+
+ iface_reg =
+ tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface_reg |= TLV320AIC23_MS_MASTER;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface_reg |= TLV320AIC23_FOR_I2S;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface_reg |= TLV320AIC23_FOR_DSP;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface_reg |= TLV320AIC23_FOR_LJUST;
+ break;
+ default:
+ return -EINVAL;
+
+ }
+
+ tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+ return 0;
+}
+
+static int tlv320aic23_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;
+
+ switch (freq) {
+ case 12000000:
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ /* vref/mid, osc on, dac unmute */
+ tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* everything off except vref/vmid, */
+ tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040);
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* everything off, dac mute, inactive */
+ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+ tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+#define AIC23_RATES SNDRV_PCM_RATE_8000_96000
+#define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai tlv320aic23_dai = {
+ .name = "tlv320aic23",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = AIC23_RATES,
+ .formats = AIC23_FORMATS,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = AIC23_RATES,
+ .formats = AIC23_FORMATS,},
+ .ops = {
+ .prepare = tlv320aic23_pcm_prepare,
+ .hw_params = tlv320aic23_hw_params,
+ .shutdown = tlv320aic23_shutdown,
+ },
+ .dai_ops = {
+ .digital_mute = tlv320aic23_mute,
+ .set_fmt = tlv320aic23_set_dai_fmt,
+ .set_sysclk = tlv320aic23_set_dai_sysclk,
+ }
+};
+EXPORT_SYMBOL_GPL(tlv320aic23_dai);
+
+static int tlv320aic23_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int tlv320aic23_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+ int i;
+ u16 reg;
+
+ /* Sync reg_cache with the hardware */
+ for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) {
+ u16 val = tlv320aic23_read_reg_cache(codec, reg);
+ tlv320aic23_write(codec, reg, val);
+ }
+
+ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
+
+ return 0;
+}
+
+/*
+ * initialise the AIC23 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int tlv320aic23_init(struct snd_soc_device *socdev)
+{
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret = 0;
+ u16 reg;
+
+ codec->name = "tlv320aic23";
+ codec->owner = THIS_MODULE;
+ codec->read = tlv320aic23_read_reg_cache;
+ codec->write = tlv320aic23_write;
+ codec->set_bias_level = tlv320aic23_set_bias_level;
+ codec->dai = &tlv320aic23_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
+ codec->reg_cache =
+ kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* Reset codec */
+ tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ /* power on device */
+ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+
+ /* Unmute input */
+ reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
+ tlv320aic23_write(codec, TLV320AIC23_LINVOL,
+ (reg & (~TLV320AIC23_LIM_MUTED)) |
+ (TLV320AIC23_LRS_ENABLED));
+
+ reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
+ tlv320aic23_write(codec, TLV320AIC23_RINVOL,
+ (reg & (~TLV320AIC23_LIM_MUTED)) |
+ TLV320AIC23_LRS_ENABLED);
+
+ reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
+ tlv320aic23_write(codec, TLV320AIC23_ANLG,
+ (reg) & (~TLV320AIC23_BYPASS_ON) &
+ (~TLV320AIC23_MICM_MUTED));
+
+ /* Default output volume */
+ tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
+ TLV320AIC23_DEFAULT_OUT_VOL &
+ TLV320AIC23_OUT_VOL_MASK);
+ tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
+ TLV320AIC23_DEFAULT_OUT_VOL &
+ TLV320AIC23_OUT_VOL_MASK);
+
+ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+
+ tlv320aic23_add_controls(codec);
+ tlv320aic23_add_widgets(codec);
+ ret = snd_soc_register_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "tlv320aic23: failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+ return ret;
+}
+static struct snd_soc_device *tlv320aic23_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+/*
+ * If the i2c layer weren't so broken, we could pass this kind of data
+ * around
+ */
+static int tlv320aic23_codec_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ struct snd_soc_device *socdev = tlv320aic23_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EINVAL;
+
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ ret = tlv320aic23_init(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
+ goto err;
+ }
+ return ret;
+
+err:
+ kfree(codec);
+ kfree(i2c);
+ return ret;
+}
+static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
+{
+ put_device(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id tlv320aic23_id[] = {
+ {"tlv320aic23", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
+
+static struct i2c_driver tlv320aic23_i2c_driver = {
+ .driver = {
+ .name = "tlv320aic23",
+ },
+ .probe = tlv320aic23_codec_probe,
+ .remove = __exit_p(tlv320aic23_i2c_remove),
+ .id_table = tlv320aic23_id,
+};
+
+#endif
+
+static int tlv320aic23_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
+
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+
+ socdev->codec = codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ tlv320aic23_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ codec->hw_write = (hw_write_t) i2c_master_send;
+ codec->hw_read = NULL;
+ ret = i2c_add_driver(&tlv320aic23_i2c_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add i2c driver");
+#endif
+ return ret;
+}
+
+static int tlv320aic23_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ if (codec->control_data)
+ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&tlv320aic23_i2c_driver);
+#endif
+ kfree(codec->reg_cache);
+ kfree(codec);
+
+ return 0;
+}
+struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
+ .probe = tlv320aic23_probe,
+ .remove = tlv320aic23_remove,
+ .suspend = tlv320aic23_suspend,
+ .resume = tlv320aic23_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
new file mode 100644
index 00000000000..79d1faf8e57
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -0,0 +1,122 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd
+ *
+ * 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 _TLV320AIC23_H
+#define _TLV320AIC23_H
+
+/* Codec TLV320AIC23 */
+#define TLV320AIC23_LINVOL 0x00
+#define TLV320AIC23_RINVOL 0x01
+#define TLV320AIC23_LCHNVOL 0x02
+#define TLV320AIC23_RCHNVOL 0x03
+#define TLV320AIC23_ANLG 0x04
+#define TLV320AIC23_DIGT 0x05
+#define TLV320AIC23_PWR 0x06
+#define TLV320AIC23_DIGT_FMT 0x07
+#define TLV320AIC23_SRATE 0x08
+#define TLV320AIC23_ACTIVE 0x09
+#define TLV320AIC23_RESET 0x0F
+
+/* Left (right) line input volume control register */
+#define TLV320AIC23_LRS_ENABLED 0x0100
+#define TLV320AIC23_LIM_MUTED 0x0080
+#define TLV320AIC23_LIV_DEFAULT 0x0017
+#define TLV320AIC23_LIV_MAX 0x001f
+#define TLV320AIC23_LIV_MIN 0x0000
+
+/* Left (right) channel headphone volume control register */
+#define TLV320AIC23_LZC_ON 0x0080
+#define TLV320AIC23_LHV_DEFAULT 0x0079
+#define TLV320AIC23_LHV_MAX 0x007f
+#define TLV320AIC23_LHV_MIN 0x0000
+
+/* Analog audio path control register */
+#define TLV320AIC23_STA_REG(x) ((x)<<6)
+#define TLV320AIC23_STE_ENABLED 0x0020
+#define TLV320AIC23_DAC_SELECTED 0x0010
+#define TLV320AIC23_BYPASS_ON 0x0008
+#define TLV320AIC23_INSEL_MIC 0x0004
+#define TLV320AIC23_MICM_MUTED 0x0002
+#define TLV320AIC23_MICB_20DB 0x0001
+
+/* Digital audio path control register */
+#define TLV320AIC23_DACM_MUTE 0x0008
+#define TLV320AIC23_DEEMP_32K 0x0002
+#define TLV320AIC23_DEEMP_44K 0x0004
+#define TLV320AIC23_DEEMP_48K 0x0006
+#define TLV320AIC23_ADCHP_ON 0x0001
+
+/* Power control down register */
+#define TLV320AIC23_DEVICE_PWR_OFF 0x0080
+#define TLV320AIC23_CLK_OFF 0x0040
+#define TLV320AIC23_OSC_OFF 0x0020
+#define TLV320AIC23_OUT_OFF 0x0010
+#define TLV320AIC23_DAC_OFF 0x0008
+#define TLV320AIC23_ADC_OFF 0x0004
+#define TLV320AIC23_MIC_OFF 0x0002
+#define TLV320AIC23_LINE_OFF 0x0001
+
+/* Digital audio interface register */
+#define TLV320AIC23_MS_MASTER 0x0040
+#define TLV320AIC23_LRSWAP_ON 0x0020
+#define TLV320AIC23_LRP_ON 0x0010
+#define TLV320AIC23_IWL_16 0x0000
+#define TLV320AIC23_IWL_20 0x0004
+#define TLV320AIC23_IWL_24 0x0008
+#define TLV320AIC23_IWL_32 0x000C
+#define TLV320AIC23_FOR_I2S 0x0002
+#define TLV320AIC23_FOR_DSP 0x0003
+#define TLV320AIC23_FOR_LJUST 0x0001
+
+/* Sample rate control register */
+#define TLV320AIC23_CLKOUT_HALF 0x0080
+#define TLV320AIC23_CLKIN_HALF 0x0040
+#define TLV320AIC23_BOSR_384fs 0x0002 /* BOSR_272fs in USB mode */
+#define TLV320AIC23_USB_CLK_ON 0x0001
+#define TLV320AIC23_SR_MASK 0xf
+#define TLV320AIC23_CLKOUT_SHIFT 7
+#define TLV320AIC23_CLKIN_SHIFT 6
+#define TLV320AIC23_SR_SHIFT 2
+#define TLV320AIC23_BOSR_SHIFT 1
+
+/* Digital interface register */
+#define TLV320AIC23_ACT_ON 0x0001
+
+/*
+ * AUDIO related MACROS
+ */
+
+#define TLV320AIC23_DEFAULT_OUT_VOL 0x70
+#define TLV320AIC23_DEFAULT_IN_VOLUME 0x10
+
+#define TLV320AIC23_OUT_VOL_MIN TLV320AIC23_LHV_MIN
+#define TLV320AIC23_OUT_VOL_MAX TLV320AIC23_LHV_MAX
+#define TLV320AIC23_OUT_VO_RANGE (TLV320AIC23_OUT_VOL_MAX - \
+ TLV320AIC23_OUT_VOL_MIN)
+#define TLV320AIC23_OUT_VOL_MASK TLV320AIC23_OUT_VOL_MAX
+
+#define TLV320AIC23_IN_VOL_MIN TLV320AIC23_LIV_MIN
+#define TLV320AIC23_IN_VOL_MAX TLV320AIC23_LIV_MAX
+#define TLV320AIC23_IN_VOL_RANGE (TLV320AIC23_IN_VOL_MAX - \
+ TLV320AIC23_IN_VOL_MIN)
+#define TLV320AIC23_IN_VOL_MASK TLV320AIC23_IN_VOL_MAX
+
+#define TLV320AIC23_SIDETONE_MASK 0x1c0
+#define TLV320AIC23_SIDETONE_0 0x100
+#define TLV320AIC23_SIDETONE_6 0x000
+#define TLV320AIC23_SIDETONE_9 0x040
+#define TLV320AIC23_SIDETONE_12 0x080
+#define TLV320AIC23_SIDETONE_18 0x0c0
+
+extern struct snd_soc_dai tlv320aic23_dai;
+extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
+
+#endif /* _TLV320AIC23_H */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 566a427c928..05336ed7e49 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -48,7 +48,6 @@
#include "tlv320aic3x.h"
-#define AUDIO_NAME "aic3x"
#define AIC3X_VERSION "0.2"
/* codec private data */
@@ -991,7 +990,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
struct snd_soc_dai aic3x_dai = {
- .name = "aic3x",
+ .name = "tlv320aic3x",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -1055,7 +1054,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
struct aic3x_setup_data *setup = socdev->codec_data;
int reg, ret = 0;
- codec->name = "aic3x";
+ codec->name = "tlv320aic3x";
codec->owner = THIS_MODULE;
codec->read = aic3x_read_reg_cache;
codec->write = aic3x_write;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index d206d7f892b..a69ee72a7af 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -36,7 +36,6 @@
#include "uda1380.h"
#define UDA1380_VERSION "0.6"
-#define AUDIO_NAME "uda1380"
/*
* uda1380 register cache
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 9a37c8d95ed..d8ca2da8d63 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -3,7 +3,7 @@
*
* Copyright 2006 Wolfson Microelectronics PLC.
*
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* 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
@@ -18,6 +18,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -27,7 +28,6 @@
#include "wm8510.h"
-#define AUDIO_NAME "wm8510"
#define WM8510_VERSION "0.6"
struct snd_soc_codec_device soc_codec_dev_wm8510;
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
0x0001,
};
+#define WM8510_POWER1_BIASEN 0x08
+#define WM8510_POWER1_BUFIOEN 0x10
+
/*
* read wm8510 register cache
*/
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
-SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0,
- &wm8510_micpga_controls[0],
- ARRAY_SIZE(wm8510_micpga_controls)),
+SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
+ &wm8510_micpga_controls[0],
+ ARRAY_SIZE(wm8510_micpga_controls)),
SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
&wm8510_boost_controls[0],
ARRAY_SIZE(wm8510_boost_controls)),
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
static int wm8510_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
switch (level) {
case SND_SOC_BIAS_ON:
- wm8510_write(codec, WM8510_POWER1, 0x1ff);
- wm8510_write(codec, WM8510_POWER2, 0x1ff);
- wm8510_write(codec, WM8510_POWER3, 0x1ff);
- break;
case SND_SOC_BIAS_PREPARE:
+ power1 |= 0x1; /* VMID 50k */
+ wm8510_write(codec, WM8510_POWER1, power1);
+ break;
+
case SND_SOC_BIAS_STANDBY:
+ power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
+
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Initial cap charge at VMID 5k */
+ wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
+ mdelay(100);
+ }
+
+ power1 |= 0x2; /* VMID 500k */
+ wm8510_write(codec, WM8510_POWER1, power1);
break;
+
case SND_SOC_BIAS_OFF:
- /* everything off, dac mute, inactive */
- wm8510_write(codec, WM8510_POWER1, 0x0);
- wm8510_write(codec, WM8510_POWER2, 0x0);
- wm8510_write(codec, WM8510_POWER3, 0x0);
+ wm8510_write(codec, WM8510_POWER1, 0);
+ wm8510_write(codec, WM8510_POWER2, 0);
+ wm8510_write(codec, WM8510_POWER3, 0);
break;
}
+
codec->bias_level = level;
return 0;
}
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
}
/* power on device */
+ codec->bias_level = SND_SOC_BIAS_OFF;
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8510_add_controls(codec);
wm8510_add_widgets(codec);
@@ -747,6 +763,62 @@ err_driver:
}
#endif
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8510_spi_probe(struct spi_device *spi)
+{
+ struct snd_soc_device *socdev = wm8510_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ codec->control_data = spi;
+
+ ret = wm8510_init(socdev);
+ if (ret < 0)
+ dev_err(&spi->dev, "failed to initialise WM8510\n");
+
+ return ret;
+}
+
+static int __devexit wm8510_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver wm8510_spi_driver = {
+ .driver = {
+ .name = "wm8510",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8510_spi_probe,
+ .remove = __devexit_p(wm8510_spi_remove),
+};
+
+static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+ u8 msg[2];
+
+ if (len <= 0)
+ return 0;
+
+ msg[0] = data[0];
+ msg[1] = data[1];
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = &msg[0];
+ t.len = len;
+
+ spi_message_add_tail(&t, &m);
+ spi_sync(spi, &m);
+
+ return len;
+}
+#endif /* CONFIG_SPI_MASTER */
+
static int wm8510_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -772,8 +844,14 @@ static int wm8510_probe(struct platform_device *pdev)
codec->hw_write = (hw_write_t)i2c_master_send;
ret = wm8510_add_i2c_device(pdev, setup);
}
-#else
- /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ if (setup->spi) {
+ codec->hw_write = (hw_write_t)wm8510_spi_write;
+ ret = spi_register_driver(&wm8510_spi_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add spi driver");
+ }
#endif
if (ret != 0)
@@ -796,6 +874,9 @@ static int wm8510_remove(struct platform_device *pdev)
i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8510_i2c_driver);
#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8510_spi_driver);
+#endif
kfree(codec);
return 0;
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
index c5368396045..bdefcf5c69f 100644
--- a/sound/soc/codecs/wm8510.h
+++ b/sound/soc/codecs/wm8510.h
@@ -94,6 +94,7 @@
#define WM8510_MCLKDIV_12 (7 << 5)
struct wm8510_setup_data {
+ int spi;
int i2c_bus;
unsigned short i2c_address;
};
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index df1ffbe305b..627ebfb4209 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -18,7 +18,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -36,7 +35,6 @@
#include "wm8580.h"
-#define AUDIO_NAME "wm8580"
#define WM8580_VERSION "0.1"
struct pll_state {
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7b64d9a7ff7..7f8a7e36b33 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -29,7 +29,6 @@
#include "wm8731.h"
-#define AUDIO_NAME "wm8731"
#define WM8731_VERSION "0.13"
struct snd_soc_codec_device soc_codec_dev_wm8731;
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 4892e398a59..9b7296ee5b0 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -29,7 +29,6 @@
#include "wm8750.h"
-#define AUDIO_NAME "WM8750"
#define WM8750_VERSION "0.12"
/* codec private data */
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 8c4df44f334..d426eaa2218 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -2,8 +2,7 @@
* wm8753.c -- WM8753 ALSA Soc Audio driver
*
* Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -40,6 +39,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -51,7 +51,6 @@
#include "wm8753.h"
-#define AUDIO_NAME "wm8753"
#define WM8753_VERSION "0.16"
static int caps_charge = 2000;
@@ -1719,6 +1718,63 @@ err_driver:
}
#endif
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
+{
+ struct snd_soc_device *socdev = wm8753_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ codec->control_data = spi;
+
+ ret = wm8753_init(socdev);
+ if (ret < 0)
+ dev_err(&spi->dev, "failed to initialise WM8753\n");
+
+ return ret;
+}
+
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver wm8753_spi_driver = {
+ .driver = {
+ .name = "wm8753",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8753_spi_probe,
+ .remove = __devexit_p(wm8753_spi_remove),
+};
+
+static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+ u8 msg[2];
+
+ if (len <= 0)
+ return 0;
+
+ msg[0] = data[0];
+ msg[1] = data[1];
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = &msg[0];
+ t.len = len;
+
+ spi_message_add_tail(&t, &m);
+ spi_sync(spi, &m);
+
+ return len;
+}
+#endif
+
+
static int wm8753_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1753,8 +1809,14 @@ static int wm8753_probe(struct platform_device *pdev)
codec->hw_write = (hw_write_t)i2c_master_send;
ret = wm8753_add_i2c_device(pdev, setup);
}
-#else
- /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ if (setup->spi) {
+ codec->hw_write = (hw_write_t)wm8753_spi_write;
+ ret = spi_register_driver(&wm8753_spi_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add spi driver");
+ }
#endif
if (ret != 0) {
@@ -1798,6 +1860,9 @@ static int wm8753_remove(struct platform_device *pdev)
i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8753_i2c_driver);
#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8753_spi_driver);
+#endif
kfree(codec->private_data);
kfree(codec);
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 7defde069f1..f55704ce931 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -2,8 +2,7 @@
* wm8753.h -- audio driver for WM8753
*
* Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -79,6 +78,7 @@
#define WM8753_ADCTL2 0x3f
struct wm8753_setup_data {
+ int spi;
int i2c_bus;
unsigned short i2c_address;
};
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 0b8c6d38b48..3b326c9b558 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -18,7 +18,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index a3f54ec4226..ce40d787760 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -653,14 +653,14 @@ static const struct snd_kcontrol_new wm8903_snd_controls[] = {
/* Input PGAs - No TLV since the scale depends on PGA mode */
SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0,
- 7, 1, 0),
+ 7, 1, 1),
SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0,
0, 31, 0),
SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1,
6, 1, 0),
SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0,
- 7, 1, 0),
+ 7, 1, 1),
SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0,
0, 31, 0),
SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1,
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 974a4cd0f3f..f41a578ddd4 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -29,7 +29,6 @@
#include "wm8971.h"
-#define AUDIO_NAME "wm8971"
#define WM8971_VERSION "0.9"
#define WM8971_REG_COUNT 43
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 63410d7b5ef..572d22b0880 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -30,7 +30,6 @@
#include "wm8990.h"
-#define AUDIO_NAME "wm8990"
#define WM8990_VERSION "0.2"
/* codec private data */
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 2f1c91b1d55..ffb471e420e 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -2,8 +2,7 @@
* wm9712.c -- ALSA Soc WM9712 codec support
*
* Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 441d0580db1..aba402b3c99 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -2,8 +2,7 @@
* wm9713.c -- ALSA Soc WM9713 codec support
*
* Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index aea27e70043..8b7766b998d 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -13,3 +13,11 @@ config SND_OMAP_SOC_N810
select SND_SOC_TLV320AIC3X
help
Say Y if you want to add support for SoC audio on Nokia N810.
+
+config SND_OMAP_SOC_OSK5912
+ tristate "SoC Audio support for omap osk5912"
+ depends on SND_OMAP_SOC && MACH_OMAP_OSK
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TLV320AIC23
+ help
+ Say Y if you want to add support for SoC audio on osk5912.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index d8d8d58075e..e09d1f297f6 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
+snd-soc-osk5912-objs := osk5912.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index d166b6b2a60..fae3ad36e0b 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -247,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
int i, err;
/* Not connected */
- snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
- snd_soc_dapm_disable_pin(codec, "HPLCOM");
- snd_soc_dapm_disable_pin(codec, "HPRCOM");
+ snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
+ snd_soc_dapm_nc_pin(codec, "HPLCOM");
+ snd_soc_dapm_nc_pin(codec, "HPRCOM");
/* Add N810 specific controls */
for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 35310e16d7f..853b33ae343 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -43,6 +43,7 @@
struct omap_mcbsp_data {
unsigned int bus_id;
struct omap_mcbsp_reg_cfg regs;
+ unsigned int fmt;
/*
* Flags indicating is the bus already activated and configured by
* another substream
@@ -59,12 +60,7 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
* Stream DMA parameters. DMA request line and port address are set runtime
* since they are different between OMAP1 and later OMAPs
*/
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = {
-{
- { .name = "I2S PCM Stereo out", },
- { .name = "I2S PCM Stereo in", },
-},
-};
+static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
static const int omap1_dma_reqs[][2] = {
@@ -84,11 +80,22 @@ static const unsigned long omap1_mcbsp_port[][2] = {
static const int omap1_dma_reqs[][2] = {};
static const unsigned long omap1_mcbsp_port[][2] = {};
#endif
-#if defined(CONFIG_ARCH_OMAP2420)
-static const int omap2420_dma_reqs[][2] = {
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+static const int omap24xx_dma_reqs[][2] = {
{ OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
{ OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+ { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
+ { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
+ { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
+#endif
};
+#else
+static const int omap24xx_dma_reqs[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
static const unsigned long omap2420_mcbsp_port[][2] = {
{ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
@@ -96,10 +103,43 @@ static const unsigned long omap2420_mcbsp_port[][2] = {
OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
};
#else
-static const int omap2420_dma_reqs[][2] = {};
static const unsigned long omap2420_mcbsp_port[][2] = {};
#endif
+#if defined(CONFIG_ARCH_OMAP2430)
+static const unsigned long omap2430_mcbsp_port[][2] = {
+ { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap2430_mcbsp_port[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP34XX)
+static const unsigned long omap34xx_mcbsp_port[][2] = {
+ { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap34xx_mcbsp_port[][2] = {};
+#endif
+
static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -161,20 +201,26 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
+ int wlen;
unsigned long port;
if (cpu_class_is_omap1()) {
dma = omap1_dma_reqs[bus_id][substream->stream];
port = omap1_mcbsp_port[bus_id][substream->stream];
} else if (cpu_is_omap2420()) {
- dma = omap2420_dma_reqs[bus_id][substream->stream];
+ dma = omap24xx_dma_reqs[bus_id][substream->stream];
port = omap2420_mcbsp_port[bus_id][substream->stream];
+ } else if (cpu_is_omap2430()) {
+ dma = omap24xx_dma_reqs[bus_id][substream->stream];
+ port = omap2430_mcbsp_port[bus_id][substream->stream];
+ } else if (cpu_is_omap343x()) {
+ dma = omap24xx_dma_reqs[bus_id][substream->stream];
+ port = omap34xx_mcbsp_port[bus_id][substream->stream];
} else {
- /*
- * TODO: Add support for 2430 and 3430
- */
return -ENODEV;
}
+ omap_mcbsp_dai_dma_params[id][substream->stream].name =
+ substream->stream ? "Audio Capture" : "Audio Playback";
omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
@@ -200,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
/* Set word lengths */
+ wlen = 16;
regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16);
regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16);
regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
- /* Set FS period and length in terms of bit clock periods */
- regs->srgr2 |= FPER(16 * 2 - 1);
- regs->srgr1 |= FWID(16 - 1);
break;
default:
/* Unsupported PCM format */
return -EINVAL;
}
+ /* Set FS period and length in terms of bit clock periods */
+ switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ regs->srgr2 |= FPER(wlen * 2 - 1);
+ regs->srgr1 |= FWID(wlen - 1);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ regs->srgr2 |= FPER(wlen * 2 - 1);
+ regs->srgr1 |= FWID(0);
+ break;
+ }
+
omap_mcbsp_config(bus_id, &mcbsp_data->regs);
mcbsp_data->configured = 1;
@@ -228,10 +284,12 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
{
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ unsigned int temp_fmt = fmt;
if (mcbsp_data->configured)
return 0;
+ mcbsp_data->fmt = fmt;
memset(regs, 0, sizeof(*regs));
/* Generic McBSP register settings */
regs->spcr2 |= XINTM(3) | FREE;
@@ -245,6 +303,13 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
regs->rcr2 |= RDATDLY(1);
regs->xcr2 |= XDATDLY(1);
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ /* 0-bit data delay */
+ regs->rcr2 |= RDATDLY(0);
+ regs->xcr2 |= XDATDLY(0);
+ /* Invert bit clock and FS polarity configuration for DSP_A */
+ temp_fmt ^= SND_SOC_DAIFMT_IB_IF;
+ break;
default:
/* Unsupported data format */
return -EINVAL;
@@ -267,7 +332,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
}
/* Set bit clock (CLKX/CLKR) and FS polarities */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
/*
* Normal BCLK + FS.
@@ -310,7 +375,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
int clk_id)
{
int sel_bit;
- u16 reg;
+ u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
if (cpu_class_is_omap1()) {
/* OMAP1's can use only external source clock */
@@ -320,6 +385,12 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
return 0;
}
+ if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
+ return -EINVAL;
+
+ if (cpu_is_omap343x())
+ reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
+
switch (mcbsp_data->bus_id) {
case 0:
reg = OMAP2_CONTROL_DEVCONF0;
@@ -329,20 +400,26 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
reg = OMAP2_CONTROL_DEVCONF0;
sel_bit = 6;
break;
- /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */
+ case 2:
+ reg = reg_devconf1;
+ sel_bit = 0;
+ break;
+ case 3:
+ reg = reg_devconf1;
+ sel_bit = 2;
+ break;
+ case 4:
+ reg = reg_devconf1;
+ sel_bit = 4;
+ break;
default:
return -EINVAL;
}
- if (cpu_class_is_omap2()) {
- if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) {
- omap_ctrl_writel(omap_ctrl_readl(reg) &
- ~(1 << sel_bit), reg);
- } else {
- omap_ctrl_writel(omap_ctrl_readl(reg) |
- (1 << sel_bit), reg);
- }
- }
+ if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
+ omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
+ else
+ omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
return 0;
}
@@ -376,37 +453,49 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
return err;
}
-struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = {
-{
- .name = "omap-mcbsp-dai",
- .id = 0,
- .type = SND_SOC_DAI_I2S,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = OMAP_MCBSP_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = OMAP_MCBSP_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = {
- .startup = omap_mcbsp_dai_startup,
- .shutdown = omap_mcbsp_dai_shutdown,
- .trigger = omap_mcbsp_dai_trigger,
- .hw_params = omap_mcbsp_dai_hw_params,
- },
- .dai_ops = {
- .set_fmt = omap_mcbsp_dai_set_dai_fmt,
- .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
- .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
- },
- .private_data = &mcbsp_data[0].bus_id,
-},
+#define OMAP_MCBSP_DAI_BUILDER(link_id) \
+{ \
+ .name = "omap-mcbsp-dai-(link_id)", \
+ .id = (link_id), \
+ .type = SND_SOC_DAI_I2S, \
+ .playback = { \
+ .channels_min = 2, \
+ .channels_max = 2, \
+ .rates = OMAP_MCBSP_RATES, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, \
+ }, \
+ .capture = { \
+ .channels_min = 2, \
+ .channels_max = 2, \
+ .rates = OMAP_MCBSP_RATES, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE, \
+ }, \
+ .ops = { \
+ .startup = omap_mcbsp_dai_startup, \
+ .shutdown = omap_mcbsp_dai_shutdown, \
+ .trigger = omap_mcbsp_dai_trigger, \
+ .hw_params = omap_mcbsp_dai_hw_params, \
+ }, \
+ .dai_ops = { \
+ .set_fmt = omap_mcbsp_dai_set_dai_fmt, \
+ .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
+ .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
+ }, \
+ .private_data = &mcbsp_data[(link_id)].bus_id, \
+}
+
+struct snd_soc_dai omap_mcbsp_dai[] = {
+ OMAP_MCBSP_DAI_BUILDER(0),
+ OMAP_MCBSP_DAI_BUILDER(1),
+#if NUM_LINKS >= 3
+ OMAP_MCBSP_DAI_BUILDER(2),
+#endif
+#if NUM_LINKS == 5
+ OMAP_MCBSP_DAI_BUILDER(3),
+ OMAP_MCBSP_DAI_BUILDER(4),
+#endif
};
+
EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index ed8afb55067..df7ad13ba73 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -38,11 +38,17 @@ enum omap_mcbsp_div {
OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */
};
-/*
- * REVISIT: Preparation for the ASoC v2. Let the number of available links to
- * be same than number of McBSP ports found in OMAP(s) we are compiling for.
- */
-#define NUM_LINKS 1
+#if defined(CONFIG_ARCH_OMAP2420)
+#define NUM_LINKS 2
+#endif
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+#undef NUM_LINKS
+#define NUM_LINKS 3
+#endif
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#undef NUM_LINKS
+#define NUM_LINKS 5
+#endif
extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 690bfeaec4a..e9084fdd208 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
prtd->dma_data = dma_data;
err = omap_request_dma(dma_data->dma_req, dma_data->name,
omap_pcm_dma_irq, substream, &prtd->dma_ch);
- if (!cpu_is_omap1510()) {
+ if (!err & !cpu_is_omap1510()) {
/*
* Link channel with itself so DMA doesn't need any
* reprogramming while looping the buffer
@@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC;
dma_params.src_start = runtime->dma_addr;
dma_params.dst_start = dma_data->port_addr;
+ dma_params.dst_port = OMAP_DMA_PORT_MPUI;
} else {
dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
dma_params.src_start = dma_data->port_addr;
dma_params.dst_start = runtime->dma_addr;
+ dma_params.src_port = OMAP_DMA_PORT_MPUI;
}
/*
* Set DMA transfer frame size equal to ALSA period size and frame
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
new file mode 100644
index 00000000000..0fe73379689
--- /dev/null
+++ b/sound/soc/omap/osk5912.c
@@ -0,0 +1,232 @@
+/*
+ * osk5912.c -- SoC audio for OSK 5912
+ *
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * Contact: Arun KS <arunks@mistralsolutions.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/tlv320aic23.h"
+
+#define CODEC_CLOCK 12000000
+
+static struct clk *tlv320aic23_mclk;
+
+static int osk_startup(struct snd_pcm_substream *substream)
+{
+ return clk_enable(tlv320aic23_mclk);
+}
+
+static void osk_shutdown(struct snd_pcm_substream *substream)
+{
+ clk_disable(tlv320aic23_mclk);
+}
+
+static int osk_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int err;
+
+ /* Set codec DAI configuration */
+ err = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (err < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return err;
+ }
+
+ /* Set cpu DAI configuration */
+ err = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (err < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return err;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ err =
+ snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
+
+ if (err < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return err;
+ }
+
+ return err;
+}
+
+static struct snd_soc_ops osk_ops = {
+ .startup = osk_startup,
+ .hw_params = osk_hw_params,
+ .shutdown = osk_shutdown,
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Headphone Jack", NULL, "LHPOUT"},
+ {"Headphone Jack", NULL, "RHPOUT"},
+
+ {"LLINEIN", NULL, "Line In"},
+ {"RLINEIN", NULL, "Line In"},
+
+ {"MICIN", NULL, "Mic Jack"},
+};
+
+static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
+{
+
+ /* Add osk5912 specific widgets */
+ snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+ ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+ /* Set up osk5912 specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+ snd_soc_dapm_enable_pin(codec, "Line In");
+ snd_soc_dapm_enable_pin(codec, "Mic Jack");
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link osk_dai = {
+ .name = "TLV320AIC23",
+ .stream_name = "AIC23",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &tlv320aic23_dai,
+ .init = osk_tlv320aic23_init,
+ .ops = &osk_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_osk = {
+ .name = "OSK5912",
+ .dai_link = &osk_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device osk_snd_devdata = {
+ .machine = &snd_soc_machine_osk,
+ .platform = &omap_soc_platform,
+ .codec_dev = &soc_codec_dev_tlv320aic23,
+};
+
+static struct platform_device *osk_snd_device;
+
+static int __init osk_soc_init(void)
+{
+ int err;
+ u32 curRate;
+ struct device *dev;
+
+ if (!(machine_is_omap_osk()))
+ return -ENODEV;
+
+ osk_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!osk_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
+ osk_snd_devdata.dev = &osk_snd_device->dev;
+ *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */
+ err = platform_device_add(osk_snd_device);
+ if (err)
+ goto err1;
+
+ dev = &osk_snd_device->dev;
+
+ tlv320aic23_mclk = clk_get(dev, "mclk");
+ if (IS_ERR(tlv320aic23_mclk)) {
+ printk(KERN_ERR "Could not get mclk clock\n");
+ return -ENODEV;
+ }
+
+ if (clk_get_usecount(tlv320aic23_mclk) > 0) {
+ /* MCLK is already in use */
+ printk(KERN_WARNING
+ "MCLK in use at %d Hz. We change it to %d Hz\n",
+ (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
+ }
+
+ /*
+ * Configure 12 MHz output on MCLK.
+ */
+ curRate = (uint) clk_get_rate(tlv320aic23_mclk);
+ if (curRate != CODEC_CLOCK) {
+ if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
+ printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
+ err = -ECANCELED;
+ goto err1;
+ }
+ }
+
+ printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
+ (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
+ clk_get_usecount(tlv320aic23_mclk));
+
+ return 0;
+err1:
+ clk_put(tlv320aic23_mclk);
+ platform_device_del(osk_snd_device);
+ platform_device_put(osk_snd_device);
+
+ return err;
+
+}
+
+static void __exit osk_soc_exit(void)
+{
+ platform_device_unregister(osk_snd_device);
+}
+
+module_init(osk_soc_init);
+module_exit(osk_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC OSK 5912");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1a8373de7f3..2718eaf7895 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -4,7 +4,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Richard Purdie <richard@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -281,8 +281,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
{
int i, err;
- snd_soc_dapm_disable_pin(codec, "LLINEIN");
- snd_soc_dapm_disable_pin(codec, "RLINEIN");
+ snd_soc_dapm_nc_pin(codec, "LLINEIN");
+ snd_soc_dapm_nc_pin(codec, "RLINEIN");
/* Add corgi specific controls */
for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index d9c3f7b28be..e6ff6929ab4 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -9,7 +9,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Richard Purdie <richard@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index f84f7d8db09..4d9930c5278 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -4,7 +4,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Richard Purdie <richard@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
{
int i, err;
- snd_soc_dapm_disable_pin(codec, "LLINEIN");
- snd_soc_dapm_disable_pin(codec, "RLINEIN");
+ snd_soc_dapm_nc_pin(codec, "LLINEIN");
+ snd_soc_dapm_nc_pin(codec, "RLINEIN");
snd_soc_dapm_enable_pin(codec, "MICIN");
/* Add poodle specific controls */
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 2fb58298513..e758034db5c 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -3,7 +3,7 @@
*
* Copyright 2005 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * lrg@slimlogic.co.uk
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -405,6 +405,6 @@ module_init(pxa2xx_i2s_init);
module_exit(pxa2xx_i2s_exit);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 9a70b00fc30..d307b6757e9 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -4,7 +4,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Richard Purdie <richard@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -281,13 +281,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
int i, err;
/* NC codec pins */
- snd_soc_dapm_disable_pin(codec, "RINPUT1");
- snd_soc_dapm_disable_pin(codec, "LINPUT2");
- snd_soc_dapm_disable_pin(codec, "RINPUT2");
- snd_soc_dapm_disable_pin(codec, "LINPUT3");
- snd_soc_dapm_disable_pin(codec, "RINPUT3");
- snd_soc_dapm_disable_pin(codec, "OUT3");
- snd_soc_dapm_disable_pin(codec, "MONO1");
+ snd_soc_dapm_nc_pin(codec, "RINPUT1");
+ snd_soc_dapm_nc_pin(codec, "LINPUT2");
+ snd_soc_dapm_nc_pin(codec, "RINPUT2");
+ snd_soc_dapm_nc_pin(codec, "LINPUT3");
+ snd_soc_dapm_nc_pin(codec, "RINPUT3");
+ snd_soc_dapm_nc_pin(codec, "OUT3");
+ snd_soc_dapm_nc_pin(codec, "MONO1");
/* Add spitz specific controls */
for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 2baaa750f12..afefe41b8c4 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -4,7 +4,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Richard Purdie <richard@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
{
int i, err;
- snd_soc_dapm_disable_pin(codec, "OUT3");
- snd_soc_dapm_disable_pin(codec, "MONOOUT");
+ snd_soc_dapm_nc_pin(codec, "OUT3");
+ snd_soc_dapm_nc_pin(codec, "MONOOUT");
/* add tosa specific controls */
for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 73a50e93a9a..87ddfefcc2f 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -511,21 +511,20 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
DBG("Entered %s\n", __func__);
/* set up NC codec pins */
- snd_soc_dapm_disable_pin(codec, "LOUT2");
- snd_soc_dapm_disable_pin(codec, "ROUT2");
- snd_soc_dapm_disable_pin(codec, "OUT3");
- snd_soc_dapm_disable_pin(codec, "OUT4");
- snd_soc_dapm_disable_pin(codec, "LINE1");
- snd_soc_dapm_disable_pin(codec, "LINE2");
-
-
- /* set endpoints to default mode */
- set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+ snd_soc_dapm_nc_pin(codec, "LOUT2");
+ snd_soc_dapm_nc_pin(codec, "ROUT2");
+ snd_soc_dapm_nc_pin(codec, "OUT3");
+ snd_soc_dapm_nc_pin(codec, "OUT4");
+ snd_soc_dapm_nc_pin(codec, "LINE1");
+ snd_soc_dapm_nc_pin(codec, "LINE2");
/* Add neo1973 specific widgets */
snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
ARRAY_SIZE(wm8753_dapm_widgets));
+ /* set endpoints to default mode */
+ set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+
/* add neo1973 specific controls */
for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
err = snd_ctl_add(codec->card,
@@ -603,6 +602,8 @@ static int lm4857_i2c_probe(struct i2c_client *client,
{
DBG("Entered %s\n", __func__);
+ i2c = client;
+
lm4857_write_regs();
return 0;
}
@@ -611,6 +612,8 @@ static int lm4857_i2c_remove(struct i2c_client *client)
{
DBG("Entered %s\n", __func__);
+ i2c = NULL;
+
return 0;
}
@@ -650,7 +653,7 @@ static void lm4857_shutdown(struct i2c_client *dev)
}
static const struct i2c_device_id lm4857_i2c_id[] = {
- { "neo1973_lm4857", 0 }
+ { "neo1973_lm4857", 0 },
{ }
};
@@ -668,48 +671,6 @@ static struct i2c_driver lm4857_i2c_driver = {
};
static struct platform_device *neo1973_snd_device;
-static struct i2c_client *lm4857_client;
-
-static int __init neo1973_add_lm4857_device(struct platform_device *pdev,
- int i2c_bus,
- unsigned short i2c_address)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&lm4857_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add lm4857 driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = i2c_address;
- strlcpy(info.type, "neo1973_lm4857", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n", i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add lm4857 device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- lm4857_client = client;
- return 0;
-
-err_driver:
- i2c_del_driver(&lm4857_i2c_driver);
- return -ENODEV;
-}
static int __init neo1973_init(void)
{
@@ -736,8 +697,8 @@ static int __init neo1973_init(void)
return ret;
}
- ret = neo1973_add_lm4857_device(neo1973_snd_device,
- neo1973_wm8753_setup, 0x7C);
+ ret = i2c_add_driver(&lm4857_i2c_driver);
+
if (ret != 0)
platform_device_unregister(neo1973_snd_device);
@@ -748,7 +709,6 @@ static void __exit neo1973_exit(void)
{
DBG("Entered %s\n", __func__);
- i2c_unregister_device(lm4857_client);
i2c_del_driver(&lm4857_i2c_driver);
platform_device_unregister(neo1973_snd_device);
}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ad381138fc2..462e635dfc7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4,8 +4,7 @@
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* with code, comments and ideas from :-
* Richard Purdie <richard@openedhand.com>
*
@@ -1886,7 +1885,7 @@ module_init(snd_soc_init);
module_exit(snd_soc_exit);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
MODULE_DESCRIPTION("ALSA SoC Core");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:soc-audio");
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 9ca9c08610f..7351db9606e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2,8 +2,7 @@
* soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
*
* Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -832,7 +831,7 @@ int snd_soc_dapm_sys_add(struct device *dev)
return ret;
asoc_debugfs = debugfs_create_dir("asoc", NULL);
- if (!IS_ERR(asoc_debugfs))
+ if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
&pop_time);
else
@@ -1484,6 +1483,26 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
/**
+ * snd_soc_dapm_nc_pin - permanently disable pin.
+ * @codec: SoC codec
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets. At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
+{
+ return snd_soc_dapm_set_pin(codec, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
+
+/**
* snd_soc_dapm_get_pin_status - get audio pin status
* @codec: audio codec
* @pin: audio signal pin endpoint (or start point)
@@ -1521,6 +1540,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
MODULE_LICENSE("GPL");
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 4ae07e236b3..faef87a9bc3 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -220,9 +220,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
- device_create_drvdata(sound_class, dev,
- MKDEV(SOUND_MAJOR, s->unit_minor),
- NULL, s->name+6);
+ device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
+ NULL, s->name+6);
return r;
fail:
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index b441fe2cd19..c2515b680f9 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -118,12 +118,11 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
void *vaddr;
struct us122l *us122l = area->vm_private_data;
struct usb_stream *s;
- int vm_f = VM_FAULT_SIGBUS;
mutex_lock(&us122l->mutex);
s = us122l->sk.s;
if (!s)
- goto out;
+ goto unlock;
offset = vmf->pgoff << PAGE_SHIFT;
if (offset < PAGE_ALIGN(s->read_size))
@@ -131,7 +130,7 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
else {
offset -= PAGE_ALIGN(s->read_size);
if (offset >= PAGE_ALIGN(s->write_size))
- goto out;
+ goto unlock;
vaddr = us122l->sk.write_page + offset;
}
@@ -141,9 +140,11 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
mutex_unlock(&us122l->mutex);
vmf->page = page;
- vm_f = 0;
-out:
- return vm_f;
+
+ return 0;
+unlock:
+ mutex_unlock(&us122l->mutex);
+ return VM_FAULT_SIGBUS;
}
static void usb_stream_hwdep_vm_close(struct vm_area_struct *area)