* [PATCH 0/8] RX-51 audio drivers
@ 2009-10-08 11:58 Eduardo Valentin
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
` (7 more replies)
0 siblings, 8 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
Hello everyone,
Here is a patch series with most of audio support for RX51.
Basically it includes asoc machine driver for rx51, tpa6130a2 amplifier
driver (asoc version), board file configuration and setup and the
sidetone feature of mcbsp.
On top of that, there are few patches to use regulator framework
to control vmmc2.
This series is based on linux-omap. So basically after applying it,
you can boot the device and have sound support.
Even though this patches were tested using linux-omap, the series
is applicable on top of sound-2.6 tree as well.
Please review. And as usual, comments are welcome.
BR,
---
Eduardo Valentin
Eduardo Valentin (6):
ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
OMAP: RX51: Add audio board file
board-rx51-peripherals: split vaux3 and vmmc2 supplies
RX-51: Audio: Add usage of regulator framework to control VMMC2
ASoC: tlv320aic3x: add initial usage of regulator framework to
control avdd_dac
ASoC: tpa6130a2: Control vdd using regulator framework
Eero Nurkkala (1):
McBSP: OMAP3: Add Sidetone feature
Peter Ujfalusi (1):
ASoC: TPA6130A2 amplifier driver
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-rx51-audio.c | 132 +++++
arch/arm/mach-omap2/board-rx51-peripherals.c | 22 +-
arch/arm/mach-omap2/mcbsp.c | 2 +
arch/arm/plat-omap/include/mach/mcbsp.h | 43 ++
arch/arm/plat-omap/mcbsp.c | 379 ++++++++++++-
include/sound/tpa6130a2-plat.h | 30 +
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/tlv320aic3x.c | 26 +
sound/soc/codecs/tpa6130a2.c | 396 +++++++++++++
sound/soc/codecs/tpa6130a2.h | 62 ++
sound/soc/omap/Kconfig | 10 +
sound/soc/omap/Makefile | 2 +
sound/soc/omap/aic34b_dummy.c | 271 +++++++++
sound/soc/omap/aic34b_dummy.h | 32 +
sound/soc/omap/rx51.c | 793 ++++++++++++++++++++++++++
sound/soc/omap/rx51.h | 29 +
18 files changed, 2225 insertions(+), 11 deletions(-)
create mode 100644 arch/arm/mach-omap2/board-rx51-audio.c
create mode 100644 include/sound/tpa6130a2-plat.h
create mode 100644 sound/soc/codecs/tpa6130a2.c
create mode 100644 sound/soc/codecs/tpa6130a2.h
create mode 100644 sound/soc/omap/aic34b_dummy.c
create mode 100644 sound/soc/omap/aic34b_dummy.h
create mode 100644 sound/soc/omap/rx51.c
create mode 100644 sound/soc/omap/rx51.h
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 12:30 ` Eero Nurkkala
2009-10-08 12:52 ` Mark Brown
2009-10-08 11:58 ` [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver Eduardo Valentin
` (6 subsequent siblings)
7 siblings, 2 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Driver for Texas Instruments TPA6130A2 headphone stereo
amplifier.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
include/sound/tpa6130a2-plat.h | 30 +++
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/tpa6130a2.c | 380 ++++++++++++++++++++++++++++++++++++++++
sound/soc/codecs/tpa6130a2.h | 62 +++++++
5 files changed, 478 insertions(+), 0 deletions(-)
create mode 100644 include/sound/tpa6130a2-plat.h
create mode 100644 sound/soc/codecs/tpa6130a2.c
create mode 100644 sound/soc/codecs/tpa6130a2.h
diff --git a/include/sound/tpa6130a2-plat.h b/include/sound/tpa6130a2-plat.h
new file mode 100644
index 0000000..d315728
--- /dev/null
+++ b/include/sound/tpa6130a2-plat.h
@@ -0,0 +1,30 @@
+/*
+ * TPA6130A2 driver platform header
+ *
+ * Copyright (C) Nokia Corporation
+ *
+ * Written by Peter Ujfalusi <peter.ujfalusi@nokia.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
+ */
+
+#ifndef TPA6130A2_PLAT_H
+#define TPA6130A2_PLAT_H
+
+struct tpa6130a2_platform_data {
+ int (*set_power)(int state);
+};
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0edca93..2437fd3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -28,6 +28,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TLV320AIC23 if I2C
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC3X if I2C
+ select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TWL4030 if TWL4030_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
@@ -220,3 +221,6 @@ config SND_SOC_WM9713
# Amp
config SND_SOC_MAX9877
tristate
+
+config SND_SOC_TPA6130A2
+ tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fb4af28..498c024 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -47,6 +47,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
# Amp
snd-soc-max9877-objs := max9877.o
+snd-soc-tpa6130a2-objs := tpa6130a2.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
@@ -97,3 +98,4 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
+obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
new file mode 100644
index 0000000..d246aad
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -0,0 +1,380 @@
+/*
+ * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
+ *
+ * Copyright (C) Nokia Corporation
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@nokia.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/module.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/sysfs.h>
+#include <sound/tpa6130a2-plat.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "tpa6130a2.h"
+
+struct i2c_client *tpa6130a2_client;
+
+/* This struct is used to save the context */
+struct tpa6130a2_data {
+ /* mutex protect access to tpa6130a2_data structure */
+ struct mutex mutex;
+ unsigned char regs[TPA6130A2_CACHEREGNUM];
+ unsigned char power_state;
+ int (*set_power)(int state);
+};
+
+static int tpa6130a2_i2c_read(int reg)
+{
+ struct tpa6130a2_data *data;
+ int val;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ /* If powered off, return the cached value */
+ if (data->power_state) {
+ val = i2c_smbus_read_byte_data(tpa6130a2_client, reg);
+ if (val < 0)
+ dev_err(&tpa6130a2_client->dev, "Read failed\n");
+ else
+ data->regs[reg] = val;
+ } else {
+ val = data->regs[reg];
+ }
+
+ return val;
+}
+
+static int tpa6130a2_i2c_write(int reg, u8 value)
+{
+ struct tpa6130a2_data *data;
+ int val = 0;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ if (data->power_state) {
+ val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
+ if (val < 0)
+ dev_err(&tpa6130a2_client->dev, "Write failed\n");
+ }
+
+ /* Either powered on or off, we save the context */
+ data->regs[reg] = value;
+
+ return val;
+}
+
+static u8 tpa6130a2_read(int reg)
+{
+ struct tpa6130a2_data *data;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ return data->regs[reg];
+}
+
+static void tpa6130a2_initialize(void)
+{
+ struct tpa6130a2_data *data;
+ int i;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ for (i = 1; i < TPA6130A2_REG_VERSION; i++)
+ tpa6130a2_i2c_write(i, data->regs[i]);
+}
+
+void tpa6130a2_power(int power)
+{
+ struct tpa6130a2_data *data;
+ u8 val;
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ mutex_lock(&data->mutex);
+ if (power) {
+ /* Power on */
+ if (data->set_power) {
+ data->set_power(1);
+ data->power_state = 1;
+ tpa6130a2_initialize();
+ }
+ /* Clear SWS */
+ val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
+ val &= ~TPA6130A2_SWS;
+ tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
+ } else {
+ /* set SWS */
+ val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
+ val |= TPA6130A2_SWS;
+ tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
+ /* Power off */
+ if (data->set_power) {
+ data->set_power(0);
+ data->power_state = 0;
+ }
+ }
+ mutex_unlock(&data->mutex);
+}
+
+static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int mask = mc->max;
+ unsigned int invert = mc->invert;
+ struct tpa6130a2_data *data;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ mutex_lock(&data->mutex);
+
+ ucontrol->value.integer.value[0] =
+ (tpa6130a2_read(reg) >> shift) & mask;
+
+ if (invert)
+ ucontrol->value.integer.value[0] =
+ mask - ucontrol->value.integer.value[0];
+
+ mutex_unlock(&data->mutex);
+ return 0;
+}
+
+static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int mask = mc->max;
+ unsigned int invert = mc->invert;
+ unsigned int val = (ucontrol->value.integer.value[0] & mask);
+ unsigned int val_reg;
+ struct tpa6130a2_data *data;
+
+ BUG_ON(tpa6130a2_client == NULL);
+
+ data = i2c_get_clientdata(tpa6130a2_client);
+
+ if (invert)
+ val = mask - val;
+
+ mutex_lock(&data->mutex);
+
+ val_reg = tpa6130a2_read(reg);
+ if (((val_reg >> shift) & mask) == val) {
+ mutex_unlock(&data->mutex);
+ return 0;
+ }
+
+ val_reg &= ~(mask << shift);
+ val_reg |= val << shift;
+ tpa6130a2_i2c_write(reg, val_reg);
+
+ mutex_unlock(&data->mutex);
+
+ return 1;
+}
+
+/*
+ * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
+ * down in gain. Justify scale so that it is quite correct from -20 dB and
+ * up. This setting shows -30 dB at minimum, -12.95 dB at 49 % (actual
+ * is -10.3 dB) and 4.65 dB at maximum (actual is 4 dB).
+ */
+static const unsigned int tpa6130_tlv[] = {
+ TLV_DB_RANGE_HEAD(10),
+ 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
+ 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
+ 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
+ 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
+ 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
+ 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
+ 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
+ 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0),
+};
+
+static const struct snd_kcontrol_new tpa6130a2_controls[] = {
+ SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
+ TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
+ tpa6130a2_get_reg, tpa6130a2_set_reg,
+ tpa6130_tlv),
+};
+
+static int tpa6130a2_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ tpa6130a2_power(1);
+ else
+ tpa6130a2_power(0);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
+ /* Outputs */
+ SND_SOC_DAPM_HP("TPA6130A2 Headphone", tpa6130a2_hp_event),
+};
+
+int tpa6130a2_add_controls(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
+ ARRAY_SIZE(tpa6130a2_dapm_widgets));
+
+ return snd_soc_add_controls(codec, tpa6130a2_controls,
+ ARRAY_SIZE(tpa6130a2_controls));
+
+}
+EXPORT_SYMBOL(tpa6130a2_add_controls);
+
+static int tpa6130a2_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err;
+ struct device *dev;
+ struct tpa6130a2_data *data;
+ struct tpa6130a2_platform_data *pdata;
+
+ dev = &client->dev;
+
+ tpa6130a2_client = client;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ i2c_set_clientdata(tpa6130a2_client, data);
+
+ if (client->dev.platform_data == NULL) {
+ dev_err(dev, "Platform data not set\n");
+ dump_stack();
+ err = -ENODEV;
+ goto fail2;
+ }
+
+ pdata = (struct tpa6130a2_platform_data *)client->dev.platform_data;
+ /* Set default register values */
+ data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
+ TPA6130A2_HP_EN_R |
+ TPA6130A2_HP_EN_L;
+ data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_VOLUME(20);
+
+ mutex_init(&data->mutex);
+
+ data->set_power = pdata->set_power;
+ if (!pdata->set_power) {
+ data->power_state = 1;
+ tpa6130a2_initialize();
+ }
+ tpa6130a2_power(1);
+
+ /* Read version */
+ err = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
+ TPA6130A2_VERSION_MASK;
+ if ((err != 1) && (err != 2)) {
+ dev_err(dev, "Unexpected headphone amplifier chip version "
+ "of 0x%02x, was expecting 0x01 or 0x02\n", err);
+ err = -ENODEV;
+
+ goto fail3;
+ }
+
+ dev_info(dev, "Version %d detected\n", err);
+
+ /* Disable the chip */
+ tpa6130a2_power(0);
+
+ return 0;
+fail3:
+ tpa6130a2_power(0);
+fail2:
+ kfree(data);
+ i2c_set_clientdata(tpa6130a2_client, NULL);
+fail1:
+ tpa6130a2_client = 0;
+
+ return err;
+}
+
+static int tpa6130a2_remove(struct i2c_client *client)
+{
+ struct tpa6130a2_data *data = i2c_get_clientdata(client);
+
+ tpa6130a2_power(0);
+ kfree(data);
+ tpa6130a2_client = 0;
+
+ return 0;
+}
+
+static const struct i2c_device_id tpa6130a2_id[] = {
+ { "tpa6130a2", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
+
+static struct i2c_driver tpa6130a2_i2c_driver = {
+ .driver = {
+ .name = "tpa6130a2",
+ .owner = THIS_MODULE,
+ },
+ .probe = tpa6130a2_probe,
+ .remove = __devexit_p(tpa6130a2_remove),
+ .id_table = tpa6130a2_id,
+};
+
+static int __init tpa6130a2_init(void)
+{
+ return i2c_add_driver(&tpa6130a2_i2c_driver);
+}
+
+static void __exit tpa6130a2_exit(void)
+{
+ i2c_del_driver(&tpa6130a2_i2c_driver);
+}
+
+MODULE_AUTHOR("Peter Ujfalusi");
+MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
+MODULE_LICENSE("GPL");
+
+module_init(tpa6130a2_init);
+module_exit(tpa6130a2_exit);
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h
new file mode 100644
index 0000000..6a794f1
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.h
@@ -0,0 +1,62 @@
+/*
+ * ALSA SoC TPA6130A2 amplifier driver
+ *
+ * Copyright (C) Nokia Corporation
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@nokia.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
+ *
+ */
+
+#ifndef __TPA6130A2_H__
+#define __TPA6130A2_H__
+
+/* Register addresses */
+#define TPA6130A2_REG_CONTROL 0x01
+#define TPA6130A2_REG_VOL_MUTE 0x02
+#define TPA6130A2_REG_OUT_IMPEDANCE 0x03
+#define TPA6130A2_REG_VERSION 0x04
+
+#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1)
+
+/* Register bits */
+/* TPA6130A2_REG_CONTROL (0x01) */
+#define TPA6130A2_SWS (0x01 << 0)
+#define TPA6130A2_TERMAL (0x01 << 1)
+#define TPA6130A2_MODE(x) (x << 4)
+#define TPA6130A2_MODE_STEREO (0x00)
+#define TPA6130A2_MODE_DUAL_MONO (0x01)
+#define TPA6130A2_MODE_BRIDGE (0x02)
+#define TPA6130A2_MODE_MASK (0x03)
+#define TPA6130A2_HP_EN_R (0x01 << 6)
+#define TPA6130A2_HP_EN_L (0x01 << 7)
+
+/* TPA6130A2_REG_VOL_MUTE (0x02) */
+#define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0)
+#define TPA6130A2_MUTE_R (0x01 << 6)
+#define TPA6130A2_MUTE_L (0x01 << 7)
+
+/* TPA6130A2_REG_OUT_IMPEDANCE (0x03) */
+#define TPA6130A2_HIZ_R (0x01 << 0)
+#define TPA6130A2_HIZ_L (0x01 << 1)
+
+/* TPA6130A2_REG_VERSION (0x04) */
+#define TPA6130A2_VERSION_MASK (0x0f)
+
+extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
+extern void tpa6130a2_power(int power);
+
+#endif /* __TPA6130A2_H__ */
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 12:31 ` Eero Nurkkala
2009-10-08 13:11 ` Mark Brown
2009-10-08 11:58 ` [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature Eduardo Valentin
` (5 subsequent siblings)
7 siblings, 2 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
Introduce RX-51 Machine driver for ASoC and AIC34b_dummy (block B) i2c driver.
Also move the request_gpio of speaker_enabled
from board-rx51-peripherals.c to this machine driver.
These drivers were originally written by Jarkko Nikula.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 -
sound/soc/omap/Kconfig | 10 +
sound/soc/omap/Makefile | 2 +
sound/soc/omap/aic34b_dummy.c | 271 +++++++++
sound/soc/omap/aic34b_dummy.h | 32 +
sound/soc/omap/rx51.c | 793 ++++++++++++++++++++++++++
sound/soc/omap/rx51.h | 29 +
7 files changed, 1137 insertions(+), 2 deletions(-)
create mode 100644 sound/soc/omap/aic34b_dummy.c
create mode 100644 sound/soc/omap/aic34b_dummy.h
create mode 100644 sound/soc/omap/rx51.c
create mode 100644 sound/soc/omap/rx51.h
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index c1af532..b227475 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -262,8 +262,6 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
/* FIXME this gpio setup is just a placeholder for now */
gpio_request(gpio + 6, "backlight_pwm");
gpio_direction_output(gpio + 6, 0);
- gpio_request(gpio + 7, "speaker_en");
- gpio_direction_output(gpio + 7, 1);
/* set up MMC adapters, linking their regulators to them */
twl4030_mmc_init(mmc);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 2dee983..bdcd4be 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -15,6 +15,16 @@ config SND_OMAP_SOC_N810
help
Say Y if you want to add support for SoC audio on Nokia N810.
+config SND_OMAP_SOC_RX51
+ tristate "SoC Audio support for Nokia RX51"
+ depends on SND_OMAP_SOC && MACH_NOKIA_RX51
+ select OMAP_MCBSP
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TLV320AIC3X
+ select SND_SOC_TPA6130A2
+ help
+ Say Y if you want to add support for SoC audio on Nokia RX51.
+
config SND_OMAP_SOC_AMS_DELTA
tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
depends on SND_OMAP_SOC && MACH_AMS_DELTA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 02d6947..7dec270 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -16,8 +16,10 @@ snd-soc-sdp3430-objs := sdp3430.o
snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
snd-soc-zoom2-objs := zoom2.o
+snd-soc-rx51-objs := rx51.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o aic34b_dummy.o
obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
diff --git a/sound/soc/omap/aic34b_dummy.c b/sound/soc/omap/aic34b_dummy.c
new file mode 100644
index 0000000..17c4d9c
--- /dev/null
+++ b/sound/soc/omap/aic34b_dummy.c
@@ -0,0 +1,271 @@
+/*
+ * aic34b_dummy.c -- Dummy driver for AIC34 block B parts used in Nokia RX51
+ *
+ * Purpose for this driver is to cover few audio connections on Nokia RX51 HW
+ * which are connected into block B of TLV320AIC34 dual codec.
+ *
+ * Copyright (C) 2008 - 2009 Nokia Corporation
+ *
+ * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ * Eduardo Valentin <eduardo.valentin@nokia.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
+ *
+ * TODO:
+ * - Get rid of this driver, at least when ASoC v2 is merged and when
+ * we can support multiple codec instances in tlv320aic3x.c driver.
+ * This driver is hacked only for Nokia RX51 HW.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/soc.h>
+
+#include "../codecs/tlv320aic3x.h"
+
+struct i2c_client *aic34b_client;
+static DEFINE_MUTEX(aic34b_mutex);
+static DEFINE_MUTEX(button_press_mutex);
+static ktime_t button_press_denial_start;
+static int aic34b_volume;
+static int button_press_denied;
+static int aic34b_bias;
+
+
+static int aic34b_read(struct i2c_client *client, unsigned int reg,
+ u8 *value)
+{
+ int err;
+
+ err = i2c_smbus_read_byte_data(client, reg);
+ *value = err;
+ return (err >= 0) ? 0 : err;
+}
+
+static int aic34b_write(struct i2c_client *client, unsigned int reg,
+ u8 value)
+{
+ u8 data[2];
+
+ data[0] = reg & 0xff;
+ data[1] = value & 0xff;
+
+ return (i2c_master_send(client, data, 2) == 2) ? 0 : -EIO;
+}
+
+/*
+ * Introduce a derivative FIR filter to detect unnecessary button
+ * presses caused by a change in the MICBIAS. The filter returns
+ * TRUE in the event there has not been a change in MICBIAS within
+ * the time window (500ms). If the rate of change within the window
+ * is >= 1, all button presses are denied. In addition, if bias is
+ * zero, then all button presses are also denied explicitly.
+ */
+int allow_button_press(void)
+{
+ /* If bias is not on, no chance for button presses */
+ if (!aic34b_bias)
+ return 0;
+
+ /* If explicitly granted a button press */
+ if (!button_press_denied) {
+ return 1;
+ } else {
+ int64_t delta;
+ /* This is the FIR portion with specified time window */
+ mutex_lock(&button_press_mutex);
+ delta = ktime_to_ns(ktime_sub(ktime_get(),
+ button_press_denial_start));
+
+ if (delta < 0) {
+ button_press_denied = 0;
+ /* If the clock ever wraps */
+ button_press_denial_start.tv.sec = 0;
+ button_press_denial_start.tv.nsec = 0;
+ mutex_unlock(&button_press_mutex);
+ return 1;
+ }
+ do_div(delta, 1000000);
+ /* Time window is 500ms */
+ if (delta >= 500) {
+ button_press_denied = 0;
+ mutex_unlock(&button_press_mutex);
+ return 1;
+ }
+ mutex_unlock(&button_press_mutex);
+ }
+
+ /* There was a change in MICBIAS within time window */
+ return 0;
+}
+EXPORT_SYMBOL(allow_button_press);
+
+static void deny_button_press(void)
+{
+ mutex_lock(&button_press_mutex);
+ button_press_denied = 1;
+ button_press_denial_start = ktime_get();
+ mutex_unlock(&button_press_mutex);
+}
+
+void aic34b_set_mic_bias(int bias)
+{
+ if (aic34b_client == NULL)
+ return;
+
+ mutex_lock(&aic34b_mutex);
+ aic34b_write(aic34b_client, MICBIAS_CTRL, (bias & 0x3) << 6);
+ aic34b_bias = bias;
+ deny_button_press();
+ mutex_unlock(&aic34b_mutex);
+}
+EXPORT_SYMBOL(aic34b_set_mic_bias);
+
+int aic34b_set_volume(u8 volume)
+{
+ u8 val;
+
+ if (aic34b_client == NULL)
+ return 0;
+
+ mutex_lock(&aic34b_mutex);
+
+ /* Volume control for Right PGA to HPLOUT */
+ aic34b_read(aic34b_client, 49, &val);
+ val &= ~0x7f;
+ aic34b_write(aic34b_client, 49, val | (~volume & 0x7f));
+
+ /* Volume control for Right PGA to HPLCOM */
+ aic34b_read(aic34b_client, 56, &val);
+ val &= ~0x7f;
+ aic34b_write(aic34b_client, 56, val | (~volume & 0x7f));
+
+ aic34b_volume = volume;
+ mutex_unlock(&aic34b_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(aic34b_set_volume);
+
+void aic34b_ear_enable(int enable)
+{
+ u8 val;
+
+ if (aic34b_client == NULL)
+ return;
+
+ mutex_lock(&aic34b_mutex);
+ if (enable) {
+ /* Connect LINE2R to RADC */
+ aic34b_write(aic34b_client, LINE2R_2_RADC_CTRL, 0x80);
+ /* Unmute Right ADC-PGA */
+ aic34b_write(aic34b_client, RADC_VOL, 0x00);
+ /* Right PGA -> HPLOUT */
+ aic34b_read(aic34b_client, 49, &val);
+ aic34b_write(aic34b_client, 49, val | 0x80);
+ /* Unmute HPLOUT with 1 dB gain */
+ aic34b_write(aic34b_client, HPLOUT_CTRL, 0x19);
+ /* Right PGA -> HPLCOM */
+ aic34b_read(aic34b_client, 56, &val);
+ aic34b_write(aic34b_client, 56, val | 0x80);
+ /* Unmute HPLCOM with 1 dB gain */
+ aic34b_write(aic34b_client, HPLCOM_CTRL, 0x19);
+ } else {
+ /* Disconnect LINE2R from RADC */
+ aic34b_write(aic34b_client, LINE2R_2_RADC_CTRL, 0xF8);
+ /* Mute Right ADC-PGA */
+ aic34b_write(aic34b_client, RADC_VOL, 0x80);
+ /* Detach Right PGA from HPLOUT */
+ aic34b_write(aic34b_client, 49, (~aic34b_volume & 0x7f));
+ /* Power down HPLOUT */
+ aic34b_write(aic34b_client, HPLOUT_CTRL, 0x06);
+ /* Detach Right PGA from HPLCOM */
+ aic34b_write(aic34b_client, 56, (~aic34b_volume & 0x7f));
+ /* Power down HPLCOM */
+ aic34b_write(aic34b_client, HPLCOM_CTRL, 0x06);
+ /* Deny any possible keypresses for a second */
+ deny_button_press();
+ /* To regain low power consumption, reset is needed */
+ aic34b_write(aic34b_client, AIC3X_RESET, SOFT_RESET);
+ /* And need to restore volume level */
+ aic34b_write(aic34b_client, 49, (~aic34b_volume & 0x7f));
+ aic34b_write(aic34b_client, 56, (~aic34b_volume & 0x7f));
+ /* Need to restore MICBIAS if set */
+ if (aic34b_bias)
+ aic34b_write(aic34b_client, MICBIAS_CTRL,
+ (aic34b_bias & 0x3) << 6);
+ }
+ mutex_unlock(&aic34b_mutex);
+}
+EXPORT_SYMBOL(aic34b_ear_enable);
+
+static int aic34b_dummy_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ u8 val;
+
+ if (aic34b_read(client, AIC3X_PLL_PROGA_REG, &val) || val != 0x10) {
+ /* Chip not present */
+ return -ENODEV;
+ }
+ aic34b_client = client;
+
+ /* Configure LINE2R for differential mode */
+ aic34b_read(client, LINE2R_2_RADC_CTRL, &val);
+ aic34b_write(client, LINE2R_2_RADC_CTRL, val | 0x80);
+
+ return 0;
+}
+
+static int aic34b_dummy_remove(struct i2c_client *client)
+{
+ aic34b_client = NULL;
+
+ return 0;
+}
+
+static const struct i2c_device_id aic34b_dummy_id[] = {
+ { "aic34b_dummy", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aic34b_dummy_id);
+
+static struct i2c_driver aic34b_dummy_driver = {
+ .driver = {
+ .name = "aic34b_dummy"
+ },
+ .probe = aic34b_dummy_probe,
+ .remove = aic34b_dummy_remove,
+ .id_table = aic34b_dummy_id,
+};
+
+static int __init aic34b_dummy_init(void)
+{
+ return i2c_add_driver(&aic34b_dummy_driver);
+}
+
+static void __exit aic34b_dummy_exit(void)
+{
+ i2c_del_driver(&aic34b_dummy_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("Dummy driver for AIC34 block B parts used on Nokia RX51");
+MODULE_LICENSE("GPL");
+
+module_init(aic34b_dummy_init);
+module_exit(aic34b_dummy_exit);
diff --git a/sound/soc/omap/aic34b_dummy.h b/sound/soc/omap/aic34b_dummy.h
new file mode 100644
index 0000000..2d386bf
--- /dev/null
+++ b/sound/soc/omap/aic34b_dummy.h
@@ -0,0 +1,32 @@
+/*
+ * aic34b_dummy.h
+ *
+ * Copyright (C) 2008 - 2009 Nokia Corporation
+ *
+ * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ * Eduardo Valentin <eduardo.valentin@nokia.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
+ *
+ */
+
+#ifndef __AIC34B_DUMMY__
+#define __AIC34B_DUMMY__
+
+extern void aic34b_ear_enable(int enable);
+void aic34b_set_mic_bias(int bias);
+int aic34b_set_volume(u8 volume);
+
+#endif
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
new file mode 100644
index 0000000..74bafb2
--- /dev/null
+++ b/sound/soc/omap/rx51.c
@@ -0,0 +1,793 @@
+/*
+ * rx51.c -- SoC audio for Nokia RX51
+ *
+ * Copyright (C) 2008 - 2009 Nokia Corporation
+ *
+ * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ * Eduardo Valentin <eduardo.valentin@nokia.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/delay.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <sound/tlv.h>
+
+#include <linux/i2c/twl4030.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/tlv320aic3x.h"
+#include "../codecs/tpa6130a2.h"
+#include "aic34b_dummy.h"
+
+#define RX51_CODEC_RESET_GPIO 60
+#define RX51_TVOUT_SEL_GPIO 40
+#define RX51_ECI_SWITCH_1_GPIO 178
+#define RX51_ECI_SWITCH_2_GPIO 182
+/* REVISIT: TWL4030 GPIO base in RX51. Now statically defined to 192 */
+#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7)
+
+enum {
+ RX51_JACK_DISABLED,
+ RX51_JACK_HP, /* headphone: stereo output, no mic */
+ RX51_JACK_HS, /* headset: stereo output with mic */
+ RX51_JACK_MIC, /* mic input only */
+ RX51_JACK_ECI, /* ECI headset */
+ RX51_JACK_TVOUT, /* stereo output with tv-out */
+};
+
+static int rx51_spk_func;
+static int rx51_jack_func;
+static int rx51_fmtx_func;
+static int rx51_dmic_func;
+static int rx51_ear_func;
+static struct snd_jack *rx51_jack;
+
+static DEFINE_MUTEX(eci_mutex);
+static int rx51_eci_mode = 1;
+static int rx51_dapm_jack_bias;
+static int tpa6130_enable;
+static int aic34b_volume;
+
+static void rx51_set_eci_switches(int mode)
+{
+ switch (mode) {
+ case 0: /* Bias off */
+ case 1: /* Bias according to rx51_dapm_jack_bias */
+ case 4: /* Bias on */
+ /* Codec connected to mic/bias line */
+ gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
+ gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 1);
+ break;
+ case 2:
+ /* ECI INT#2 detect connected to mic/bias line */
+ gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
+ gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
+ break;
+ case 3:
+ /* ECI RX/TX connected to mic/bias line */
+ gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 1);
+ gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
+ break;
+ }
+}
+
+static void rx51_set_jack_bias(void)
+{
+ int enable_bias = 0;
+
+ mutex_lock(&eci_mutex);
+ if ((rx51_eci_mode == 1 && rx51_dapm_jack_bias) || rx51_eci_mode == 4)
+ enable_bias = 1;
+ else if (rx51_eci_mode == 1 && rx51_jack_func == RX51_JACK_ECI)
+ enable_bias = 1;
+ mutex_unlock(&eci_mutex);
+ if (enable_bias)
+ aic34b_set_mic_bias(2); /* 2.5 V */
+ else
+ aic34b_set_mic_bias(0);
+}
+
+static void rx51_set_jack_bias_handler(struct work_struct *unused)
+{
+ rx51_set_jack_bias();
+}
+DECLARE_WORK(rx51_jack_bias_work, rx51_set_jack_bias_handler);
+
+static void rx51_ext_control(struct snd_soc_codec *codec)
+{
+ int hp = 0, mic = 0, tvout = 0;
+
+ switch (rx51_jack_func) {
+ case RX51_JACK_ECI:
+ case RX51_JACK_HS:
+ mic = 1;
+ case RX51_JACK_HP:
+ hp = 1;
+ break;
+ case RX51_JACK_MIC:
+ mic = 1;
+ break;
+ case RX51_JACK_TVOUT:
+ hp = 1;
+ tvout = 1;
+ break;
+ }
+
+ gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
+
+ if (rx51_spk_func)
+ snd_soc_dapm_enable_pin(codec, "Ext Spk");
+ else
+ snd_soc_dapm_disable_pin(codec, "Ext Spk");
+ if (hp)
+ snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+ else
+ snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+ if (mic)
+ snd_soc_dapm_enable_pin(codec, "Mic Jack");
+ else
+ snd_soc_dapm_disable_pin(codec, "Mic Jack");
+ if (rx51_fmtx_func)
+ snd_soc_dapm_enable_pin(codec, "FM Transmitter");
+ else
+ snd_soc_dapm_disable_pin(codec, "FM Transmitter");
+ if (rx51_dmic_func)
+ snd_soc_dapm_enable_pin(codec, "DMic");
+ else
+ snd_soc_dapm_disable_pin(codec, "DMic");
+ if (rx51_ear_func)
+ snd_soc_dapm_enable_pin(codec, "Earphone");
+ else
+ snd_soc_dapm_disable_pin(codec, "Earphone");
+
+ snd_soc_dapm_sync(codec);
+}
+
+int rx51_set_eci_mode(int mode)
+{
+ if (mode < 0 || mode > 4)
+ return -EINVAL;
+
+ mutex_lock(&eci_mutex);
+ if (rx51_eci_mode == mode) {
+ mutex_unlock(&eci_mutex);
+ return 0;
+ }
+
+ rx51_eci_mode = mode;
+ rx51_set_eci_switches(rx51_eci_mode);
+ mutex_unlock(&eci_mutex);
+
+ rx51_set_jack_bias();
+
+ return 0;
+}
+EXPORT_SYMBOL(rx51_set_eci_mode);
+
+static ssize_t eci_mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", rx51_eci_mode);
+}
+
+static ssize_t eci_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int mode, retval;
+ if (sscanf(buf, "%d", &mode) != 1)
+ return -EINVAL;
+ retval = rx51_set_eci_mode(mode);
+
+ return (retval < 0) ? retval : count;
+}
+
+static DEVICE_ATTR(eci_mode, S_IRUGO | S_IWUSR,
+ eci_mode_show, eci_mode_store);
+
+void rx51_jack_report(int status)
+{
+ snd_jack_report(rx51_jack, status);
+}
+EXPORT_SYMBOL(rx51_jack_report);
+
+static int rx51_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->socdev->card->codec;
+
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
+
+ rx51_ext_control(codec);
+
+ return 0;
+}
+
+static int rx51_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_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (err < 0)
+ return err;
+
+ /* Set cpu DAI configuration */
+ err = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (err < 0)
+ return err;
+
+ /* Set the codec system clock for DAC and ADC */
+ return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
+ SND_SOC_CLOCK_IN);
+}
+
+static int rx51_bt_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;
+
+ /* Set cpu DAI configuration */
+ return cpu_dai->ops->set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+}
+
+static struct snd_soc_ops rx51_bt_ops = {
+ .hw_params = rx51_bt_hw_params,
+};
+
+static struct snd_soc_ops rx51_ops = {
+ .startup = rx51_startup,
+ .hw_params = rx51_hw_params,
+};
+
+static int rx51_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rx51_spk_func;
+
+ return 0;
+}
+
+static int rx51_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (rx51_spk_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ rx51_spk_func = ucontrol->value.integer.value[0];
+ rx51_ext_control(codec);
+
+ return 1;
+}
+
+static int rx51_spk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1);
+ else
+ gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0);
+
+ return 0;
+}
+
+static int rx51_get_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rx51_jack_func;
+
+ return 0;
+}
+
+static int rx51_set_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (rx51_jack_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ rx51_jack_func = ucontrol->value.integer.value[0];
+
+ mutex_lock(&eci_mutex);
+ if (rx51_jack_func == RX51_JACK_ECI) {
+ /* Set ECI switches according to ECI mode */
+ rx51_set_eci_switches(rx51_eci_mode);
+ schedule_work(&rx51_jack_bias_work);
+ } else {
+ /*
+ * Let the codec always be connected to mic/bias line when
+ * jack is in non-ECI function
+ */
+ rx51_set_eci_switches(1);
+ schedule_work(&rx51_jack_bias_work);
+ }
+ mutex_unlock(&eci_mutex);
+
+ rx51_ext_control(codec);
+
+ return 1;
+}
+
+static int rx51_jack_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(k);
+ /*
+ * Note: HP amp and fmtx must not be enabled at the same
+ * time. We keep a shadow copy of the desired tpa_enable value but
+ * keep the hpamp really disabled whenever fmtx is enabled. If
+ * hpamp is requested on but fmtx is enabled, hpamp is kept
+ * disabled and enabled later from rx51_set_fmtx function when
+ * user disables fmtx.
+ */
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ if (!rx51_fmtx_func)
+ snd_soc_dapm_enable_pin(codec, "TPA6130A2 Headphone");
+ tpa6130_enable = 1;
+ } else {
+ tpa6130_enable = 1;
+ snd_soc_dapm_disable_pin(codec, "TPA6130A2 Headphone");
+ tpa6130_enable = 0;
+ }
+
+ return 0;
+}
+
+static int rx51_jack_mic_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ rx51_dapm_jack_bias = 1;
+ else
+ rx51_dapm_jack_bias = 0;
+ schedule_work(&rx51_jack_bias_work);
+
+ return 0;
+}
+
+static int rx51_get_fmtx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rx51_fmtx_func;
+
+ return 0;
+}
+
+static int rx51_set_fmtx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (rx51_fmtx_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ rx51_fmtx_func = ucontrol->value.integer.value[0];
+ rx51_ext_control(codec);
+
+ /* fmtx and tpa must not be enabled at the same time */
+ if (rx51_fmtx_func && tpa6130_enable)
+ snd_soc_dapm_disable_pin(codec, "TPA6130A2 Headphone");
+ if (!rx51_fmtx_func && tpa6130_enable)
+ snd_soc_dapm_enable_pin(codec, "TPA6130A2 Headphone");
+
+ return 1;
+}
+
+static int rx51_get_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rx51_dmic_func;
+
+ return 0;
+}
+
+static int rx51_set_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (rx51_dmic_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ rx51_dmic_func = ucontrol->value.integer.value[0];
+ rx51_ext_control(codec);
+
+ return 1;
+}
+
+static int rx51_get_ear(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rx51_ear_func;
+
+ return 0;
+}
+
+static int rx51_set_ear(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (rx51_ear_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ rx51_ear_func = ucontrol->value.integer.value[0];
+ rx51_ext_control(codec);
+
+ return 1;
+}
+
+static int rx51_ear_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ aic34b_ear_enable(1);
+ else
+ aic34b_ear_enable(0);
+
+ return 0;
+}
+
+enum {
+ RX51_EXT_API_AIC34B,
+};
+#define SOC_RX51_EXT_SINGLE_TLV(xname, ext_api, max, 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 = rx51_ext_info_volsw, \
+ .get = rx51_ext_get_volsw, \
+ .put = rx51_ext_put_volsw, \
+ .private_value = (ext_api) << 26 | (max) << 16, \
+}
+
+static int rx51_ext_info_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int max = (kcontrol->private_value >> 16) & 0xff;
+
+ if (max == 1)
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ else
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = max;
+
+ return 0;
+}
+
+static int rx51_ext_get_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ext_api = (kcontrol->private_value >> 26) & 0x0f;
+
+ switch (ext_api) {
+ case RX51_EXT_API_AIC34B:
+ ucontrol->value.integer.value[0] = aic34b_volume;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rx51_ext_put_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ext_api = (kcontrol->private_value >> 26) & 0x0f;
+ int change = 0;
+
+ switch (ext_api) {
+ case RX51_EXT_API_AIC34B:
+ change = (aic34b_volume != ucontrol->value.integer.value[0]);
+ aic34b_volume = ucontrol->value.integer.value[0];
+ aic34b_set_volume(aic34b_volume);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return change;
+}
+
+static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
+ SND_SOC_DAPM_SPK("Headphone Jack", rx51_jack_hp_event),
+ SND_SOC_DAPM_MIC("Mic Jack", rx51_jack_mic_event),
+ SND_SOC_DAPM_OUTPUT("FM Transmitter"),
+ SND_SOC_DAPM_MIC("DMic", NULL),
+ SND_SOC_DAPM_SPK("Earphone", rx51_ear_event),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"Ext Spk", NULL, "HPLOUT"},
+ {"Ext Spk", NULL, "HPROUT"},
+
+ {"TPA6130A2 Headphone", NULL, "LLOUT"},
+ {"TPA6130A2 Headphone", NULL, "RLOUT"},
+ {"LINE1L", NULL, "Mic Jack"},
+
+ {"FM Transmitter", NULL, "LLOUT"},
+ {"FM Transmitter", NULL, "RLOUT"},
+
+ {"Earphone", NULL, "MONO_LOUT"},
+
+ {"DMic Rate 64", NULL, "Mic Bias 2V"},
+ {"Mic Bias 2V", NULL, "DMic"},
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *jack_function[] = {"Off", "Headphone", "Headset",
+ "Mic", "ECI Headset", "TV-OUT"};
+static const char *fmtx_function[] = {"Off", "On"};
+static const char *input_function[] = {"ADC", "Digital Mic"};
+static const char *ear_function[] = {"Off", "On"};
+
+static const struct soc_enum rx51_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fmtx_function), fmtx_function),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ear_function), ear_function),
+};
+
+/*
+ * TLV320AIC3x output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB.
+ * Step size is approximately 0.5 dB over most of the scale but increasing
+ * near the very low levels.
+ * Define dB scale so that it is mostly correct for range about -55 to 0 dB
+ * but having increasing dB difference below that (and where it doesn't count
+ * so much). This setting shows -50 dB (actual is -50.3 dB) for register
+ * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117.
+ */
+static DECLARE_TLV_DB_SCALE(aic3x_output_stage_tlv, -5900, 50, 1);
+
+static const struct snd_kcontrol_new aic34_rx51_controls[] = {
+ SOC_ENUM_EXT("Speaker Function", rx51_enum[0],
+ rx51_get_spk, rx51_set_spk),
+ SOC_ENUM_EXT("Jack Function", rx51_enum[1],
+ rx51_get_jack, rx51_set_jack),
+ SOC_ENUM_EXT("FMTX Function", rx51_enum[2],
+ rx51_get_fmtx, rx51_set_fmtx),
+ SOC_ENUM_EXT("Input Select", rx51_enum[3],
+ rx51_get_input, rx51_set_input),
+ SOC_ENUM_EXT("Earphone Function", rx51_enum[4],
+ rx51_get_ear, rx51_set_ear),
+ SOC_RX51_EXT_SINGLE_TLV("Earphone Playback Volume",
+ RX51_EXT_API_AIC34B, 118,
+ aic3x_output_stage_tlv),
+};
+
+static int rx51_aic34_init(struct snd_soc_codec *codec)
+{
+ int i, err;
+
+ /* Add TPA6130A2 controls */
+ tpa6130a2_add_controls(codec);
+
+ /* set up NC codec pins */
+ snd_soc_dapm_nc_pin(codec, "MIC3L");
+ snd_soc_dapm_nc_pin(codec, "MIC3R");
+ snd_soc_dapm_nc_pin(codec, "LINE1R");
+
+ /* Create jack for accessory reporting */
+ err = snd_jack_new(codec->card, "Jack", SND_JACK_MECHANICAL |
+ SND_JACK_HEADSET | SND_JACK_AVOUT, &rx51_jack);
+ if (err < 0)
+ return err;
+
+ /* Add RX51 specific controls */
+ for (i = 0; i < ARRAY_SIZE(aic34_rx51_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&aic34_rx51_controls[i], codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* Add RX51 specific widgets */
+ snd_soc_dapm_new_controls(codec, aic34_dapm_widgets,
+ ARRAY_SIZE(aic34_dapm_widgets));
+
+ /* Set up RX51 specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_enable_pin(codec, "Earphone");
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+/* Since all codec control is done by Bluetooth hardware
+ only some constrains need to be set for it */
+struct snd_soc_dai btcodec_dai = {
+ .name = "Bluetooth codec",
+ .playback = {
+ .stream_name = "BT Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .capture = {
+ .stream_name = "BT Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link rx51_dai[] = {
+ {
+ .name = "TLV320AIC34",
+ .stream_name = "AIC34",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &aic3x_dai,
+ .init = rx51_aic34_init,
+ .ops = &rx51_ops,
+ }, {
+ .name = "Bluetooth PCM",
+ .stream_name = "Bluetooth",
+ .cpu_dai = &omap_mcbsp_dai[1],
+ .codec_dai = &btcodec_dai,
+ .ops = &rx51_bt_ops,
+ }
+};
+
+/* Audio private data */
+static struct aic3x_setup_data rx51_aic34_setup = {
+ .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
+ .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
+};
+
+/* Audio card */
+static struct snd_soc_card rx51_sound_card = {
+ .name = "RX51",
+ .dai_link = rx51_dai,
+ .num_links = ARRAY_SIZE(rx51_dai),
+ .platform = &omap_soc_platform,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device rx51_snd_devdata = {
+ .card = &rx51_sound_card,
+ .codec_dev = &soc_codec_dev_aic3x,
+ .codec_data = &rx51_aic34_setup,
+};
+
+static struct platform_device *rx51_snd_device;
+
+#define REMAP_OFFSET 2
+#define DEDICATED_OFFSET 3
+#define VMMC2_DEV_GRP 0x2B
+#define VMMC2_285V 0x0a
+
+static int __init rx51_soc_init(void)
+{
+ int err;
+ struct device *dev;
+
+ if (!machine_is_nokia_rx51())
+ return -ENODEV;
+
+ if (gpio_request(RX51_CODEC_RESET_GPIO, NULL) < 0)
+ BUG();
+ if (gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel") < 0)
+ BUG();
+ if (gpio_request(RX51_ECI_SWITCH_1_GPIO, "ECI switch 1") < 0)
+ BUG();
+ if (gpio_request(RX51_ECI_SWITCH_2_GPIO, "ECI switch 2") < 0)
+ BUG();
+ gpio_direction_output(RX51_CODEC_RESET_GPIO, 0);
+ gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
+ gpio_direction_output(RX51_ECI_SWITCH_1_GPIO, 0);
+ gpio_direction_output(RX51_ECI_SWITCH_2_GPIO, 1);
+
+ gpio_set_value(RX51_CODEC_RESET_GPIO, 0);
+ udelay(1);
+ gpio_set_value(RX51_CODEC_RESET_GPIO, 1);
+ msleep(1);
+
+ if (gpio_request(RX51_SPEAKER_AMP_TWL_GPIO, NULL) < 0)
+ BUG();
+ gpio_direction_output(RX51_SPEAKER_AMP_TWL_GPIO, 0);
+
+ err = snd_soc_register_dai(&btcodec_dai);
+ if (err)
+ return err;
+
+ rx51_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!rx51_snd_device) {
+ err = -ENOMEM;
+ goto err0;
+ }
+
+ platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata);
+ rx51_snd_devdata.dev = &rx51_snd_device->dev;
+ err = platform_device_add(rx51_snd_device);
+ if (err)
+ goto err1;
+
+ dev = &rx51_snd_device->dev;
+
+ *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1;
+ *(unsigned int *)rx51_dai[1].cpu_dai->private_data = 2;
+
+ err = device_create_file(dev, &dev_attr_eci_mode);
+ if (err)
+ goto err2;
+
+ return err;
+err2:
+ platform_device_del(rx51_snd_device);
+err1:
+ platform_device_put(rx51_snd_device);
+err0:
+ snd_soc_unregister_dai(&btcodec_dai);
+
+ return err;
+
+}
+
+static void __exit rx51_soc_exit(void)
+{
+ platform_device_unregister(rx51_snd_device);
+ snd_soc_unregister_dai(&btcodec_dai);
+}
+
+module_init(rx51_soc_init);
+module_exit(rx51_soc_exit);
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("ALSA SoC Nokia RX51");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/rx51.h b/sound/soc/omap/rx51.h
new file mode 100644
index 0000000..ee55260
--- /dev/null
+++ b/sound/soc/omap/rx51.h
@@ -0,0 +1,29 @@
+#ifndef _RX51_H_
+#define _RX51_H_
+
+/*
+ * rx51.h - SoC audio for Nokia RX51
+ *
+ * Copyright (C) 2008 - 2009 Nokia Corporation
+ *
+ * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ * Eduardo Valentin <eduardo.valentin@nokia.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; version 2 of the License.
+ *
+ * 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
+ */
+
+int rx51_set_eci_mode(int mode);
+void rx51_jack_report(int status);
+
+#endif /* _RX51_H_ */
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
2009-10-08 11:58 ` [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 13:17 ` Mark Brown
2009-10-08 11:58 ` [PATCH 4/8] OMAP: RX51: Add audio board file Eduardo Valentin
` (4 subsequent siblings)
7 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eero Nurkkala, Eduardo Valentin
From: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
Add Sidetone feature to mcbsp instances 2 and 3 on OMAP3 based devices.
Signed-off-by: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
arch/arm/mach-omap2/mcbsp.c | 2 +
arch/arm/plat-omap/include/mach/mcbsp.h | 43 ++++
arch/arm/plat-omap/mcbsp.c | 379 ++++++++++++++++++++++++++++++-
3 files changed, 423 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index a846aa1..c5b4d33 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -132,6 +132,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
},
{
.phys_base = OMAP34XX_MCBSP2_BASE,
+ .phys_base_st = OMAP34XX_MCBSP2_ST_BASE,
.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
@@ -141,6 +142,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
},
{
.phys_base = OMAP34XX_MCBSP3_BASE,
+ .phys_base_st = OMAP34XX_MCBSP3_ST_BASE,
.dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX,
.dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX,
.rx_irq = INT_24XX_MCBSP3_IRQ_RX,
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h
index 7e9cae3..8ecc09d 100644
--- a/arch/arm/plat-omap/include/mach/mcbsp.h
+++ b/arch/arm/plat-omap/include/mach/mcbsp.h
@@ -49,6 +49,9 @@
#define OMAP34XX_MCBSP1_BASE 0x48074000
#define OMAP34XX_MCBSP2_BASE 0x49022000
+#define OMAP34XX_MCBSP2_ST_BASE 0x49028000
+#define OMAP34XX_MCBSP3_BASE 0x49024000
+#define OMAP34XX_MCBSP3_ST_BASE 0x4902A000
#define OMAP34XX_MCBSP3_BASE 0x49024000
#define OMAP34XX_MCBSP4_BASE 0x49026000
#define OMAP34XX_MCBSP5_BASE 0x48096000
@@ -147,6 +150,15 @@
#define OMAP_MCBSP_REG_WAKEUPEN 0xA8
#define OMAP_MCBSP_REG_XCCR 0xAC
#define OMAP_MCBSP_REG_RCCR 0xB0
+#define OMAP_MCBSP_REG_SSELCR 0xBC
+
+#define OMAP_ST_REG_REV 0x00
+#define OMAP_ST_REG_SYSCONFIG 0x10
+#define OMAP_ST_REG_IRQSTATUS 0x18
+#define OMAP_ST_REG_IRQENABLE 0x1C
+#define OMAP_ST_REG_SGAINCR 0x24
+#define OMAP_ST_REG_SFIRCR 0x28
+#define OMAP_ST_REG_SSELCR 0x2C
#define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
#define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
@@ -265,6 +277,24 @@
#define ENAWAKEUP 0x0004
#define SOFTRST 0x0002
+/********************** McBSP SSELCR bit definitions ***********************/
+#define SIDETONEEN 0x0400
+
+/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
+#define ST_AUTOIDLE 0x0001
+
+/********************** McBSP Sidetone SGAINCR bit definitions *************/
+#define ST_CH1GAIN(value) ((value<<16)) /* Bits 16:31 */
+#define ST_CH0GAIN(value) (value) /* Bits 0:15 */
+
+/********************** McBSP Sidetone SFIRCR bit definitions **************/
+#define ST_FIRCOEFF(value) (value) /* Bits 0:15 */
+
+/********************** McBSP Sidetone SSELCR bit definitions **************/
+#define ST_COEFFWRDONE 0x0004
+#define ST_COEFFWREN 0x0002
+#define ST_SIDETONEEN 0x0001
+
/********************** McBSP DMA operating modes **************************/
#define MCBSP_DMA_MODE_ELEMENT 0
#define MCBSP_DMA_MODE_THRESHOLD 1
@@ -375,10 +405,22 @@ struct omap_mcbsp_platform_data {
u16 rx_irq, tx_irq;
struct omap_mcbsp_ops *ops;
#ifdef CONFIG_ARCH_OMAP34XX
+ /* Sidetone block for McBSP 2 and 3 */
+ unsigned long phys_base_st;
u16 buffer_size;
#endif
};
+struct omap_mcbsp_st_data {
+ void __iomem *io_base_st;
+ int enabled;
+ int running;
+ s16 taps[128]; /* Sidetone filter coefficients */
+ int nr_taps; /* Number of filter coefficients in use */
+ s16 ch0gain;
+ s16 ch1gain;
+};
+
struct omap_mcbsp {
struct device *dev;
unsigned long phys_base;
@@ -411,6 +453,7 @@ struct omap_mcbsp {
struct clk *iclk;
struct clk *fclk;
#ifdef CONFIG_ARCH_OMAP34XX
+ struct omap_mcbsp_st_data *st_data;
int dma_op_mode;
u16 max_tx_thres;
u16 max_rx_thres;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 88ac976..9baa4b4 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -26,6 +26,9 @@
#include <mach/dma.h>
#include <mach/mcbsp.h>
+#ifdef CONFIG_ARCH_OMAP34XX
+#include "../mach-omap2/cm-regbits-34xx.h"
+#endif
struct omap_mcbsp **mcbsp_ptr;
int omap_mcbsp_count;
@@ -54,6 +57,11 @@ int omap_mcbsp_read(void __iomem *io_base, u16 reg)
#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
+#define OMAP_ST_READ(base, reg) \
+ omap_mcbsp_read(base, OMAP_ST_REG_##reg)
+#define OMAP_ST_WRITE(base, reg, val) \
+ omap_mcbsp_write(base, OMAP_ST_REG_##reg, val)
+
static void omap_mcbsp_dump_reg(u8 id)
{
struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
@@ -199,6 +207,160 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
EXPORT_SYMBOL(omap_mcbsp_config);
#ifdef CONFIG_ARCH_OMAP34XX
+static void omap_st_enable(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data;
+ void __iomem *io_base_mcbsp;
+ void __iomem *io_base_st;
+ unsigned int w;
+
+ io_base_mcbsp = mcbsp->io_base;
+ st_data = mcbsp->st_data;
+ io_base_st = st_data->io_base_st;
+
+ /*
+ * Sidetone uses McBSP ICLK - which must not idle when sidetones
+ * are enabled or sidetones start sounding ugly.
+ */
+ w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+ w &= ~(mcbsp->id - 1);
+ cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+
+ /* Enable McBSP Sidetone */
+ w = OMAP_MCBSP_READ(io_base_mcbsp, SSELCR);
+ OMAP_MCBSP_WRITE(io_base_mcbsp, SSELCR, w | SIDETONEEN);
+
+ w = OMAP_ST_READ(io_base_st, SYSCONFIG);
+ OMAP_ST_WRITE(io_base_st, SYSCONFIG, w & ~(ST_AUTOIDLE));
+
+ /* Enable Sidetone from Sidetone Core */
+ w = OMAP_ST_READ(io_base_st, SSELCR);
+ OMAP_ST_WRITE(io_base_st, SSELCR, w | ST_SIDETONEEN);
+}
+
+static void omap_st_disable(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data;
+ void __iomem *io_base_mcbsp;
+ void __iomem *io_base_st;
+ unsigned int w;
+
+ io_base_mcbsp = mcbsp->io_base;
+ st_data = mcbsp->st_data;
+ io_base_st = st_data->io_base_st;
+
+ w = OMAP_ST_READ(io_base_st, SSELCR);
+ OMAP_ST_WRITE(io_base_st, SSELCR, w & ~(ST_SIDETONEEN));
+
+ w = OMAP_ST_READ(io_base_st, SYSCONFIG);
+ OMAP_ST_WRITE(io_base_st, SYSCONFIG, w | ST_AUTOIDLE);
+
+ w = OMAP_MCBSP_READ(io_base_mcbsp, SSELCR);
+ OMAP_MCBSP_WRITE(io_base_mcbsp, SSELCR, w & ~(SIDETONEEN));
+
+ w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+ w |= (mcbsp->id - 1);
+ cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+}
+
+static void omap_st_enable_autoidle(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data;
+ void __iomem *io_base_st;
+ unsigned int w;
+
+ st_data = mcbsp->st_data;
+ io_base_st = st_data->io_base_st;
+
+ w = OMAP_ST_READ(io_base_st, SYSCONFIG);
+ OMAP_ST_WRITE(io_base_st, SYSCONFIG, w | ST_AUTOIDLE);
+}
+
+static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
+{
+ struct omap_mcbsp_st_data *st_data;
+ void __iomem *io_base;
+ u16 w, i;
+
+ st_data = mcbsp->st_data;
+ io_base = st_data->io_base_st;
+
+ w = OMAP_ST_READ(io_base, SYSCONFIG);
+ OMAP_ST_WRITE(io_base, SYSCONFIG, w & ~(ST_AUTOIDLE));
+
+ w = OMAP_ST_READ(io_base, SSELCR);
+
+ if (w & ST_COEFFWREN)
+ OMAP_ST_WRITE(io_base, SSELCR, w & ~(ST_COEFFWREN));
+
+ OMAP_ST_WRITE(io_base, SSELCR, w | ST_COEFFWREN);
+
+ for (i = 0; i < 128; i++)
+ OMAP_ST_WRITE(io_base, SFIRCR, fir[i]);
+
+ i = 0;
+
+ w = OMAP_ST_READ(io_base, SSELCR);
+ while (!(w & ST_COEFFWRDONE) && (++i < 1000))
+ w = OMAP_ST_READ(io_base, SSELCR);
+
+ OMAP_ST_WRITE(io_base, SSELCR, w & ~(ST_COEFFWREN));
+
+ if (i == 1000)
+ dev_err(mcbsp->dev, "McBSP FIR load error!\n");
+}
+
+static void omap_st_chgain(struct omap_mcbsp *mcbsp, s16 ch0gain, s16 ch1gain)
+{
+ struct omap_mcbsp_st_data *st_data;
+ void __iomem *io_base;
+ u16 w;
+
+ st_data = mcbsp->st_data;
+ io_base = st_data->io_base_st;
+
+ w = OMAP_ST_READ(io_base, SYSCONFIG);
+ OMAP_ST_WRITE(io_base, SYSCONFIG, w & ~(ST_AUTOIDLE));
+
+ w = OMAP_ST_READ(io_base, SSELCR);
+
+ OMAP_ST_WRITE(io_base, SGAINCR, ST_CH0GAIN(ch0gain) | \
+ ST_CH1GAIN(ch1gain));
+}
+
+static void omap_st_start(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcbsp->lock, flags);
+ if (st_data) {
+ omap_st_fir_write(mcbsp, mcbsp->st_data->taps);
+ omap_st_chgain(mcbsp,
+ mcbsp->st_data->ch0gain,
+ mcbsp->st_data->ch1gain);
+ if (st_data->enabled)
+ omap_st_enable(mcbsp);
+ else
+ omap_st_enable_autoidle(mcbsp);
+ st_data->running = 1;
+ }
+ spin_unlock_irqrestore(&mcbsp->lock, flags);
+}
+
+static void omap_st_stop(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcbsp->lock, flags);
+ if (st_data && st_data->running) {
+ omap_st_disable(mcbsp);
+ st_data->running = 0;
+ }
+ spin_unlock_irqrestore(&mcbsp->lock, flags);
+}
+
/*
* omap_mcbsp_set_tx_threshold configures how to deal
* with transmit threshold. the threshold value and handler can be
@@ -360,6 +522,8 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
#else
static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
+static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
+static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
#endif
/*
@@ -516,6 +680,9 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
mcbsp = id_to_mcbsp_ptr(id);
io_base = mcbsp->io_base;
+ if (cpu_is_omap34xx())
+ omap_st_start(mcbsp);
+
mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7;
mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7;
@@ -609,6 +776,9 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
w = OMAP_MCBSP_READ(io_base, SPCR2);
OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
}
+
+ if (cpu_is_omap34xx())
+ omap_st_stop(mcbsp);
}
EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -1190,6 +1360,147 @@ unlock:
static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
+static ssize_t st_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ return sprintf(buf, "%d\n", st_data->enabled);
+}
+
+static ssize_t st_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ unsigned long val;
+ int status;
+
+ status = strict_strtoul(buf, 0, &val);
+ if (status)
+ return status;
+
+ spin_lock_irq(&mcbsp->lock);
+ st_data->enabled = !!val;
+
+ if (st_data->running) {
+ if (st_data->enabled)
+ omap_st_enable(mcbsp);
+ else
+ omap_st_disable(mcbsp);
+ }
+ spin_unlock_irq(&mcbsp->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(st_enable, 0644, st_enable_show, st_enable_store);
+
+static ssize_t st_taps_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ ssize_t status = 0;
+ int i;
+
+ spin_lock_irq(&mcbsp->lock);
+ for (i = 0; i < st_data->nr_taps; i++)
+ status += sprintf(&buf[status], (i ? ", %d" : "%d"),
+ st_data->taps[i]);
+ if (i)
+ status += sprintf(&buf[status], "\n");
+ spin_unlock_irq(&mcbsp->lock);
+
+ return status;
+}
+
+static ssize_t st_taps_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ int val, tmp, status, i = 0;
+
+ spin_lock_irq(&mcbsp->lock);
+ memset(st_data->taps, 0, sizeof(st_data->taps));
+ st_data->nr_taps = 0;
+
+ do {
+ status = sscanf(buf, "%d%n", &val, &tmp);
+ if (status < 0 || status == 0) {
+ size = -EINVAL;
+ goto out;
+ }
+ if (val < -32768 || val > 32767) {
+ size = -EINVAL;
+ goto out;
+ }
+ st_data->taps[i++] = val;
+ buf += tmp;
+ if (*buf != ',')
+ break;
+ buf++;
+ } while (1);
+
+ st_data->nr_taps = i;
+
+out:
+ spin_unlock_irq(&mcbsp->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
+
+static ssize_t st_chgain_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (strcmp("st_ch0gain", attr->attr.name) == 0)
+ return sprintf(buf, "%d\n", st_data->ch0gain);
+ else
+ return sprintf(buf, "%d\n", st_data->ch1gain);
+}
+
+static ssize_t st_chgain_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ long val;
+ int status;
+
+ status = strict_strtol(buf, 0, &val);
+ if (status)
+ return status;
+ if (val < -32768 || val > 32767)
+ return -EINVAL;
+
+ spin_lock_irq(&mcbsp->lock);
+ if (strcmp("st_ch0gain", attr->attr.name) == 0)
+ st_data->ch0gain = val;
+ else
+ st_data->ch1gain = val;
+
+ if (st_data->running)
+ omap_st_chgain(mcbsp,
+ mcbsp->st_data->ch0gain,
+ mcbsp->st_data->ch1gain);
+ spin_unlock_irq(&mcbsp->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(st_ch0gain, 0644, st_chgain_show, st_chgain_store);
+static DEVICE_ATTR(st_ch1gain, 0644, st_chgain_show, st_chgain_store);
+
static const struct attribute *additional_attrs[] = {
&dev_attr_max_tx_thres.attr,
&dev_attr_max_rx_thres.attr,
@@ -1211,6 +1522,62 @@ static inline void __devexit omap_additional_remove(struct device *dev)
sysfs_remove_group(&dev->kobj, &additional_attr_group);
}
+static const struct attribute *sidetone_attrs[] = {
+ &dev_attr_st_enable.attr,
+ &dev_attr_st_taps.attr,
+ &dev_attr_st_ch0gain.attr,
+ &dev_attr_st_ch1gain.attr,
+ NULL,
+};
+
+static const struct attribute_group sidetone_attr_group = {
+ .attrs = (struct attribute **)sidetone_attrs,
+};
+
+int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
+ struct omap_mcbsp_st_data *st_data;
+ int err;
+
+ st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL);
+ if (!st_data) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ st_data->io_base_st = ioremap(pdata->phys_base_st, SZ_4K);
+ if (!st_data->io_base_st) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+ if (err)
+ goto err3;
+
+ mcbsp->st_data = st_data;
+ return 0;
+
+err3:
+ iounmap(st_data->io_base_st);
+err2:
+ kfree(st_data);
+err1:
+ return err;
+
+}
+
+static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (st_data) {
+ sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+ iounmap(st_data->io_base_st);
+ kfree(st_data);
+ }
+}
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
{
mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
@@ -1224,6 +1591,12 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
if (omap_additional_add(mcbsp->dev))
dev_warn(mcbsp->dev,
"Unable to create additional controls\n");
+
+ if (mcbsp->id == 2 || mcbsp->id == 3)
+ if (omap_st_add(mcbsp))
+ dev_warn(mcbsp->dev,
+ "Unable to create sidetone controls\n");
+
} else {
mcbsp->max_tx_thres = -EINVAL;
mcbsp->max_rx_thres = -EINVAL;
@@ -1232,8 +1605,12 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
{
- if (cpu_is_omap34xx())
+ if (cpu_is_omap34xx()) {
omap_additional_remove(mcbsp->dev);
+
+ if (mcbsp->id == 2 || mcbsp->id == 3)
+ omap_st_remove(mcbsp);
+ }
}
#else
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 4/8] OMAP: RX51: Add audio board file
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
` (2 preceding siblings ...)
2009-10-08 11:58 ` [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 11:58 ` [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies Eduardo Valentin
` (3 subsequent siblings)
7 siblings, 0 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
Add board-rx51-audio.c with audio support for rx51 boards.
Platform data included for the following drivers:
si4713, aic34b_dummy and tpa6130a2.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-rx51-audio.c | 132 ++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-omap2/board-rx51-audio.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 6b7702f..50f2fbe 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o
obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
board-rx51-peripherals.o \
+ board-rx51-audio.o \
mmc-twl4030.o
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
mmc-twl4030.o \
diff --git a/arch/arm/mach-omap2/board-rx51-audio.c b/arch/arm/mach-omap2/board-rx51-audio.c
new file mode 100644
index 0000000..cba42b5
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rx51-audio.c
@@ -0,0 +1,132 @@
+/*
+ * linux/arch/arm/mach-omap2/board-rx51-audio.c
+ *
+ * Copyright (C) 2008 Nokia
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/i2c/twl4030.h>
+#include <sound/tpa6130a2-plat.h>
+#include <media/si4713.h>
+#include <media/radio-si4713.h>
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+
+#define RX51_FMTX_RESET_GPIO 163
+#define RX51_FMTX_IRQ 53
+#define RX51_FMRX_IRQ 43
+#define RX51_HEADPHN_EN_GPIO 98
+
+static int si4713_set_power(int power)
+{
+ if (!power)
+ udelay(1);
+ gpio_set_value(RX51_FMTX_RESET_GPIO, power);
+ udelay(50);
+
+ return 0;
+}
+
+static struct si4713_platform_data rx51_si4713_platform_data = {
+ .set_power = si4713_set_power,
+};
+
+static void __init rx51_init_si4713(void)
+{
+ int r;
+
+ r = gpio_request(RX51_FMTX_RESET_GPIO, "si4713");
+ if (r < 0) {
+ printk(KERN_ERR "Failed to request gpio for FMTx rst\n");
+ return;
+ }
+
+ gpio_direction_output(RX51_FMTX_RESET_GPIO, 0);
+}
+
+static int tpa6130a2_set_power(int state)
+{
+ gpio_set_value(RX51_HEADPHN_EN_GPIO, !!state);
+ return 0;
+}
+
+static struct tpa6130a2_platform_data rx51_tpa6130a2_platform_data = {
+ .set_power = tpa6130a2_set_power,
+};
+
+static void __init rx51_init_tpa6130a2(void)
+{
+ int r;
+
+ r = gpio_request(RX51_HEADPHN_EN_GPIO, "tpa6130a2");
+ if (r < 0) {
+ printk(KERN_ERR "Failed to request shutdown gpio "
+ "for TPA6130a2 chip\n");
+ }
+
+ gpio_direction_output(RX51_HEADPHN_EN_GPIO, 0);
+
+ return;
+}
+
+struct i2c_board_info si4713_board_info = {
+ I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH),
+ .irq = OMAP_GPIO_IRQ(RX51_FMTX_IRQ),
+ .platform_data = &rx51_si4713_platform_data,
+};
+
+static struct radio_si4713_platform_data rx51_radio_si4713_platform_data = {
+ .i2c_bus = 2,
+ .subdev_board_info = &si4713_board_info,
+};
+
+static struct platform_device radio_fmtx = {
+ .name = "radio-si4713",
+ .id = -1,
+ .dev = {
+ .platform_data = &rx51_radio_si4713_platform_data,
+ },
+};
+
+static struct platform_device *rx51_audio_devices[] = {
+ &radio_fmtx,
+};
+
+static struct i2c_board_info __initdata rx51_audio_i2c_board_info_2[] = {
+ {
+ I2C_BOARD_INFO("aic34b_dummy", 0x19),
+ },
+ {
+ I2C_BOARD_INFO("tlv320aic3x", 0x18),
+ },
+ {
+ I2C_BOARD_INFO("tpa6130a2", 0x60),
+ .platform_data = &rx51_tpa6130a2_platform_data,
+ },
+};
+
+static int __init rx51_audio_init(void)
+{
+ if (!machine_is_nokia_rx51())
+ return 0;
+
+ platform_add_devices(rx51_audio_devices,
+ ARRAY_SIZE(rx51_audio_devices));
+
+ rx51_init_tpa6130a2();
+ rx51_init_si4713();
+ i2c_register_board_info(2, rx51_audio_i2c_board_info_2,
+ ARRAY_SIZE(rx51_audio_i2c_board_info_2));
+
+ return 0;
+}
+
+subsys_initcall(rx51_audio_init);
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
` (3 preceding siblings ...)
2009-10-08 11:58 ` [PATCH 4/8] OMAP: RX51: Add audio board file Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 13:21 ` Mark Brown
2009-10-08 11:58 ` [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2 Eduardo Valentin
` (2 subsequent siblings)
7 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
Use separated supplies for vaux3 and vmmc2.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
arch/arm/mach-omap2/board-rx51-peripherals.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index b227475..92f7dfa 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -125,6 +125,10 @@ static struct regulator_consumer_supply rx51_vmmc1_supply = {
.supply = "vmmc",
};
+static struct regulator_consumer_supply rx51_vaux3_supply = {
+ .supply = "vmmc",
+};
+
static struct regulator_consumer_supply rx51_vmmc2_supply = {
.supply = "vmmc",
};
@@ -184,7 +188,7 @@ static struct regulator_init_data rx51_vaux3_mmc = {
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
- .consumer_supplies = &rx51_vmmc2_supply,
+ .consumer_supplies = &rx51_vaux3_supply,
};
static struct regulator_init_data rx51_vaux4 = {
@@ -266,7 +270,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
/* set up MMC adapters, linking their regulators to them */
twl4030_mmc_init(mmc);
rx51_vmmc1_supply.dev = mmc[0].dev;
- rx51_vmmc2_supply.dev = mmc[1].dev;
+ rx51_vaux3_supply.dev = mmc[1].dev;
rx51_vsim_supply.dev = mmc[1].dev;
return 0;
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
` (4 preceding siblings ...)
2009-10-08 11:58 ` [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 13:26 ` Mark Brown
2009-10-08 11:58 ` [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac Eduardo Valentin
2009-10-08 11:58 ` [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework Eduardo Valentin
7 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
This patch adds two supplies for VMMC2 on rx51 boards.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
arch/arm/mach-omap2/board-rx51-peripherals.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 92f7dfa..9177b1c 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -129,8 +129,9 @@ static struct regulator_consumer_supply rx51_vaux3_supply = {
.supply = "vmmc",
};
-static struct regulator_consumer_supply rx51_vmmc2_supply = {
- .supply = "vmmc",
+static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
+ REGULATOR_SUPPLY("avdd_dac", "2-0018"), /* tlv320aic3x */
+ REGULATOR_SUPPLY("vdd", "2-0060"), /* tpa6130a2*/
};
static struct regulator_consumer_supply rx51_vsim_supply = {
@@ -230,8 +231,8 @@ static struct regulator_init_data rx51_vmmc2 = {
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
- .num_consumer_supplies = 1,
- .consumer_supplies = &rx51_vmmc2_supply,
+ .num_consumer_supplies = ARRAY_SIZE(rx51_vmmc2_supplies),
+ .consumer_supplies = rx51_vmmc2_supplies,
};
static struct regulator_init_data rx51_vsim = {
@@ -442,10 +443,9 @@ static int __init rx51_i2c_init(void)
if ((system_rev >= SYSTEM_REV_S_USES_VAUX3 && system_rev < 0x100) ||
system_rev >= SYSTEM_REV_B_USES_VAUX3)
rx51_twldata.vaux3 = &rx51_vaux3_mmc;
- else {
+ else
rx51_twldata.vaux3 = &rx51_vaux3_cam;
- rx51_twldata.vmmc2 = &rx51_vmmc2;
- }
+ rx51_twldata.vmmc2 = &rx51_vmmc2;
omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1,
ARRAY_SIZE(rx51_peripherals_i2c_board_info_1));
omap_register_i2c_bus(2, 100, NULL, 0);
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
` (5 preceding siblings ...)
2009-10-08 11:58 ` [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2 Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 12:17 ` Eero Nurkkala
2009-10-08 13:38 ` Mark Brown
2009-10-08 11:58 ` [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework Eduardo Valentin
7 siblings, 2 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
This patch adds initial usage of regulator framework to control avdd_dac
inside tlv320aic3x ASoC codec driver.
The refcount to avdd_dac is increased / decreased
only during probe and remove. Here it is still needed to implement
proper enable/disable regulator depending on chip usage. Now if driver
can get regulator for avdd_dac, then it will just let it on on probe
and then leave it off on remove.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
sound/soc/codecs/tlv320aic3x.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 3395cf9..82e0a64 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -38,6 +38,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -56,6 +57,7 @@ struct aic3x_priv {
struct snd_soc_codec codec;
unsigned int sysclk;
int master;
+ struct regulator *regulator;
};
/*
@@ -1286,6 +1288,11 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
snd_soc_unregister_dai(&aic3x_dai);
snd_soc_unregister_codec(&aic3x->codec);
+ if (aic3x->regulator) {
+ regulator_disable(aic3x->regulator);
+ regulator_put(aic3x->regulator);
+ }
+
kfree(aic3x);
aic3x_codec = NULL;
@@ -1320,6 +1327,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
codec->control_data = i2c;
codec->hw_write = (hw_write_t) i2c_master_send;
+ aic3x->regulator = regulator_get(&i2c->dev, "avdd_dac");
+ if (IS_ERR(aic3x->regulator)) {
+ dev_warn(&i2c->dev, "No regulator to supply avdd_dac."
+ " Assuming always on.\n");
+ aic3x->regulator = NULL;
+ }
+
+ /*
+ * REVISIT: Need to add proper code to put into sleep mode
+ * avdd_dac regulator. For now, just leave it on.
+ */
+ if (aic3x->regulator) {
+ int err;
+
+ err = regulator_enable(aic3x->regulator);
+ if (err < 0)
+ return err;
+ }
+
i2c_set_clientdata(i2c, aic3x);
return aic3x_register(codec);
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
` (6 preceding siblings ...)
2009-10-08 11:58 ` [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac Eduardo Valentin
@ 2009-10-08 11:58 ` Eduardo Valentin
2009-10-08 13:43 ` Mark Brown
7 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 11:58 UTC (permalink / raw)
To: Mark Brown, ext Tony Lindgren
Cc: Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel, Eduardo Valentin
From: Eduardo Valentin <eduardo.valentin@nokia.com>
This patch adds regulator framework control over vdd for tpa6130a2 driver.
Vdd refcount is increased every time the device
is power on and decreased when device is power off. If driver
fails to get regulator for "vdd" supply, then it will assume
its regulator is always on.
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
---
sound/soc/codecs/tpa6130a2.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index d246aad..35720ce 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -26,6 +26,7 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
#include <sound/tpa6130a2-plat.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
@@ -42,6 +43,7 @@ struct tpa6130a2_data {
unsigned char regs[TPA6130A2_CACHEREGNUM];
unsigned char power_state;
int (*set_power)(int state);
+ struct regulator *regulator;
};
static int tpa6130a2_i2c_read(int reg)
@@ -121,6 +123,8 @@ void tpa6130a2_power(int power)
mutex_lock(&data->mutex);
if (power) {
+ if (data->regulator)
+ regulator_enable(data->regulator);
/* Power on */
if (data->set_power) {
data->set_power(1);
@@ -141,6 +145,8 @@ void tpa6130a2_power(int power)
data->set_power(0);
data->power_state = 0;
}
+ if (data->regulator)
+ regulator_disable(data->regulator);
}
mutex_unlock(&data->mutex);
}
@@ -292,6 +298,12 @@ static int tpa6130a2_probe(struct i2c_client *client,
}
pdata = (struct tpa6130a2_platform_data *)client->dev.platform_data;
+ data->regulator = regulator_get(dev, "vdd");
+ if (IS_ERR(data->regulator)) {
+ dev_info(dev, "Could not get regulator for vdd. "
+ "Executing without regulator.\n");
+ data->regulator = NULL;
+ }
/* Set default register values */
data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
TPA6130A2_HP_EN_R |
@@ -326,6 +338,8 @@ static int tpa6130a2_probe(struct i2c_client *client,
return 0;
fail3:
tpa6130a2_power(0);
+ if (data->regulator)
+ regulator_put(data->regulator);
fail2:
kfree(data);
i2c_set_clientdata(tpa6130a2_client, NULL);
@@ -340,6 +354,8 @@ static int tpa6130a2_remove(struct i2c_client *client)
struct tpa6130a2_data *data = i2c_get_clientdata(client);
tpa6130a2_power(0);
+ if (data->regulator)
+ regulator_put(data->regulator);
kfree(data);
tpa6130a2_client = 0;
--
1.6.4.183.g04423
^ permalink raw reply related [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 11:58 ` [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac Eduardo Valentin
@ 2009-10-08 12:17 ` Eero Nurkkala
2009-10-08 13:17 ` Eduardo Valentin
2009-10-08 13:40 ` Mark Brown
2009-10-08 13:38 ` Mark Brown
1 sibling, 2 replies; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-08 12:17 UTC (permalink / raw)
To: Valentin Eduardo (Nokia-D/Helsinki)
Cc: Mark Brown, ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Jarkko Nikula, Linux-OMAP, ALSA-Devel
On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
wrote:
> From: Eduardo Valentin <eduardo.valentin@nokia.com>
>
> This patch adds initial usage of regulator framework to control avdd_dac
> inside tlv320aic3x ASoC codec driver.
>
> The refcount to avdd_dac is increased / decreased
> only during probe and remove. Here it is still needed to implement
> proper enable/disable regulator depending on chip usage. Now if driver
> can get regulator for avdd_dac, then it will just let it on on probe
> and then leave it off on remove.
>
> Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
> ---
> sound/soc/codecs/tlv320aic3x.c | 26 ++++++++++++++++++++++++++
> 1 files changed, 26 insertions(+), 0 deletions(-)
>
> diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
> index 3395cf9..82e0a64 100644
> --- a/sound/soc/codecs/tlv320aic3x.c
> +++ b/sound/soc/codecs/tlv320aic3x.c
> @@ -38,6 +38,7 @@
> #include <linux/delay.h>
> #include <linux/pm.h>
> #include <linux/i2c.h>
> +#include <linux/regulator/consumer.h>
> #include <linux/platform_device.h>
> #include <sound/core.h>
> #include <sound/pcm.h>
> @@ -56,6 +57,7 @@ struct aic3x_priv {
> struct snd_soc_codec codec;
> unsigned int sysclk;
> int master;
> + struct regulator *regulator;
> };
>
> /*
> @@ -1286,6 +1288,11 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
> snd_soc_unregister_dai(&aic3x_dai);
> snd_soc_unregister_codec(&aic3x->codec);
>
> + if (aic3x->regulator) {
> + regulator_disable(aic3x->regulator);
> + regulator_put(aic3x->regulator);
> + }
> +
> kfree(aic3x);
> aic3x_codec = NULL;
>
> @@ -1320,6 +1327,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
> codec->control_data = i2c;
> codec->hw_write = (hw_write_t) i2c_master_send;
>
> + aic3x->regulator = regulator_get(&i2c->dev, "avdd_dac");
> + if (IS_ERR(aic3x->regulator)) {
> + dev_warn(&i2c->dev, "No regulator to supply avdd_dac."
> + " Assuming always on.\n");
> + aic3x->regulator = NULL;
> + }
> +
> + /*
> + * REVISIT: Need to add proper code to put into sleep mode
> + * avdd_dac regulator. For now, just leave it on.
> + */
Will this ever be revisited =) ? If so, I think there's going to be a
jungle in finding the right spots - you need to remember the bypass
paths also (bias is not on necessarily). Also, this is regulator thing
is highly platform dependent, not aic3x related really at all, so is
this the correct place... Just a thought, dont take it too seriously ;)
> + if (aic3x->regulator) {
> + int err;
> +
> + err = regulator_enable(aic3x->regulator);
> + if (err < 0)
> + return err;
> + }
> +
> i2c_set_clientdata(i2c, aic3x);
>
> return aic3x_register(codec);
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
@ 2009-10-08 12:30 ` Eero Nurkkala
2009-10-08 13:07 ` Peter Ujfalusi
2009-10-08 12:52 ` Mark Brown
1 sibling, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-08 12:30 UTC (permalink / raw)
To: Valentin Eduardo (Nokia-D/Helsinki)
Cc: Mark Brown, ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Jarkko Nikula, Linux-OMAP, ALSA-Devel
On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
wrote:
> +/*
> + * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
> + * down in gain. Justify scale so that it is quite correct from -20 dB and
> + * up. This setting shows -30 dB at minimum, -12.95 dB at 49 % (actual
> + * is -10.3 dB) and 4.65 dB at maximum (actual is 4 dB).
> + */
The comment is misleading from all it says. For me it seems that the
scale is quite correct from -59.5 to 4 dB or so. Also the minimum is
-59.5 dB, not -30.
> +static const unsigned int tpa6130_tlv[] = {
> + TLV_DB_RANGE_HEAD(10),
> + 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
> + 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
> + 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
> + 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
> + 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
> + 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
> + 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
> + 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
> + 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
> + 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0),
> +};
> +
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-08 11:58 ` [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver Eduardo Valentin
@ 2009-10-08 12:31 ` Eero Nurkkala
2009-10-08 13:18 ` Eduardo Valentin
2009-10-08 13:11 ` Mark Brown
1 sibling, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-08 12:31 UTC (permalink / raw)
To: Valentin Eduardo (Nokia-D/Helsinki)
Cc: Mark Brown, ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Jarkko Nikula, Linux-OMAP, ALSA-Devel
On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
wrote:
> From: Eduardo Valentin <eduardo.valentin@nokia.com>
>
> Introduce RX-51 Machine driver for ASoC and AIC34b_dummy (block B) i2c driver.
>
> Also move the request_gpio of speaker_enabled
> from board-rx51-peripherals.c to this machine driver.
>
> These drivers were originally written by Jarkko Nikula.
>
> Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
> ---
> arch/arm/mach-omap2/board-rx51-peripherals.c | 2 -
> sound/soc/omap/Kconfig | 10 +
> sound/soc/omap/Makefile | 2 +
> sound/soc/omap/aic34b_dummy.c | 271 +++++++++
> sound/soc/omap/aic34b_dummy.h | 32 +
> sound/soc/omap/rx51.c | 793 ++++++++++++++++++++++++++
> sound/soc/omap/rx51.h | 29 +
> 7 files changed, 1137 insertions(+), 2 deletions(-)
> create mode 100644 sound/soc/omap/aic34b_dummy.c
> create mode 100644 sound/soc/omap/aic34b_dummy.h
> create mode 100644 sound/soc/omap/rx51.c
> create mode 100644 sound/soc/omap/rx51.h
>
> diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
> index c1af532..b227475 100644
> --- a/arch/arm/mach-omap2/board-rx51-peripherals.c
> +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
> @@ -262,8 +262,6 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
> /* FIXME this gpio setup is just a placeholder for now */
> gpio_request(gpio + 6, "backlight_pwm");
> gpio_direction_output(gpio + 6, 0);
> - gpio_request(gpio + 7, "speaker_en");
> - gpio_direction_output(gpio + 7, 1);
>
> /* set up MMC adapters, linking their regulators to them */
> twl4030_mmc_init(mmc);
> diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
> index 2dee983..bdcd4be 100644
> --- a/sound/soc/omap/Kconfig
> +++ b/sound/soc/omap/Kconfig
> @@ -15,6 +15,16 @@ config SND_OMAP_SOC_N810
> help
> Say Y if you want to add support for SoC audio on Nokia N810.
>
> +config SND_OMAP_SOC_RX51
> + tristate "SoC Audio support for Nokia RX51"
> + depends on SND_OMAP_SOC && MACH_NOKIA_RX51
> + select OMAP_MCBSP
> + select SND_OMAP_SOC_MCBSP
> + select SND_SOC_TLV320AIC3X
> + select SND_SOC_TPA6130A2
> + help
> + Say Y if you want to add support for SoC audio on Nokia RX51.
> +
> config SND_OMAP_SOC_AMS_DELTA
> tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
> depends on SND_OMAP_SOC && MACH_AMS_DELTA
> diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
> index 02d6947..7dec270 100644
> --- a/sound/soc/omap/Makefile
> +++ b/sound/soc/omap/Makefile
> @@ -16,8 +16,10 @@ snd-soc-sdp3430-objs := sdp3430.o
> snd-soc-omap3pandora-objs := omap3pandora.o
> snd-soc-omap3beagle-objs := omap3beagle.o
> snd-soc-zoom2-objs := zoom2.o
> +snd-soc-rx51-objs := rx51.o
>
> obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
> +obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o aic34b_dummy.o
> obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
> obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
> obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
> diff --git a/sound/soc/omap/aic34b_dummy.c b/sound/soc/omap/aic34b_dummy.c
> new file mode 100644
> index 0000000..17c4d9c
> --- /dev/null
> +++ b/sound/soc/omap/aic34b_dummy.c
> @@ -0,0 +1,271 @@
> +/*
> + * aic34b_dummy.c -- Dummy driver for AIC34 block B parts used in Nokia RX51
> + *
> + * Purpose for this driver is to cover few audio connections on Nokia RX51 HW
> + * which are connected into block B of TLV320AIC34 dual codec.
> + *
> + * Copyright (C) 2008 - 2009 Nokia Corporation
> + *
> + * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
> + * Eduardo Valentin <eduardo.valentin@nokia.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
> + *
> + * TODO:
> + * - Get rid of this driver, at least when ASoC v2 is merged and when
> + * we can support multiple codec instances in tlv320aic3x.c driver.
> + * This driver is hacked only for Nokia RX51 HW.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <sound/soc.h>
> +
> +#include "../codecs/tlv320aic3x.h"
> +
> +struct i2c_client *aic34b_client;
> +static DEFINE_MUTEX(aic34b_mutex);
> +static DEFINE_MUTEX(button_press_mutex);
> +static ktime_t button_press_denial_start;
> +static int aic34b_volume;
> +static int button_press_denied;
> +static int aic34b_bias;
> +
> +
> +static int aic34b_read(struct i2c_client *client, unsigned int reg,
> + u8 *value)
> +{
> + int err;
> +
> + err = i2c_smbus_read_byte_data(client, reg);
> + *value = err;
> + return (err >= 0) ? 0 : err;
> +}
> +
> +static int aic34b_write(struct i2c_client *client, unsigned int reg,
> + u8 value)
> +{
> + u8 data[2];
> +
> + data[0] = reg & 0xff;
> + data[1] = value & 0xff;
> +
> + return (i2c_master_send(client, data, 2) == 2) ? 0 : -EIO;
> +}
> +
> +/*
> + * Introduce a derivative FIR filter to detect unnecessary button
> + * presses caused by a change in the MICBIAS. The filter returns
> + * TRUE in the event there has not been a change in MICBIAS within
> + * the time window (500ms). If the rate of change within the window
> + * is >= 1, all button presses are denied. In addition, if bias is
> + * zero, then all button presses are also denied explicitly.
> + */
> +int allow_button_press(void)
> +{
> + /* If bias is not on, no chance for button presses */
> + if (!aic34b_bias)
> + return 0;
> +
> + /* If explicitly granted a button press */
> + if (!button_press_denied) {
> + return 1;
> + } else {
> + int64_t delta;
> + /* This is the FIR portion with specified time window */
> + mutex_lock(&button_press_mutex);
> + delta = ktime_to_ns(ktime_sub(ktime_get(),
> + button_press_denial_start));
> +
> + if (delta < 0) {
> + button_press_denied = 0;
> + /* If the clock ever wraps */
> + button_press_denial_start.tv.sec = 0;
> + button_press_denial_start.tv.nsec = 0;
> + mutex_unlock(&button_press_mutex);
> + return 1;
> + }
> + do_div(delta, 1000000);
> + /* Time window is 500ms */
> + if (delta >= 500) {
> + button_press_denied = 0;
> + mutex_unlock(&button_press_mutex);
> + return 1;
> + }
> + mutex_unlock(&button_press_mutex);
> + }
> +
> + /* There was a change in MICBIAS within time window */
> + return 0;
> +}
> +EXPORT_SYMBOL(allow_button_press);
> +
> +static void deny_button_press(void)
> +{
> + mutex_lock(&button_press_mutex);
> + button_press_denied = 1;
> + button_press_denial_start = ktime_get();
> + mutex_unlock(&button_press_mutex);
> +}
> +
> +void aic34b_set_mic_bias(int bias)
> +{
> + if (aic34b_client == NULL)
> + return;
> +
> + mutex_lock(&aic34b_mutex);
> + aic34b_write(aic34b_client, MICBIAS_CTRL, (bias & 0x3) << 6);
> + aic34b_bias = bias;
> + deny_button_press();
> + mutex_unlock(&aic34b_mutex);
> +}
> +EXPORT_SYMBOL(aic34b_set_mic_bias);
> +
> +int aic34b_set_volume(u8 volume)
> +{
> + u8 val;
> +
> + if (aic34b_client == NULL)
> + return 0;
> +
> + mutex_lock(&aic34b_mutex);
> +
> + /* Volume control for Right PGA to HPLOUT */
> + aic34b_read(aic34b_client, 49, &val);
> + val &= ~0x7f;
> + aic34b_write(aic34b_client, 49, val | (~volume & 0x7f));
> +
> + /* Volume control for Right PGA to HPLCOM */
> + aic34b_read(aic34b_client, 56, &val);
> + val &= ~0x7f;
> + aic34b_write(aic34b_client, 56, val | (~volume & 0x7f));
> +
> + aic34b_volume = volume;
> + mutex_unlock(&aic34b_mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(aic34b_set_volume);
> +
> +void aic34b_ear_enable(int enable)
> +{
> + u8 val;
> +
> + if (aic34b_client == NULL)
> + return;
> +
> + mutex_lock(&aic34b_mutex);
> + if (enable) {
> + /* Connect LINE2R to RADC */
> + aic34b_write(aic34b_client, LINE2R_2_RADC_CTRL, 0x80);
> + /* Unmute Right ADC-PGA */
> + aic34b_write(aic34b_client, RADC_VOL, 0x00);
> + /* Right PGA -> HPLOUT */
> + aic34b_read(aic34b_client, 49, &val);
> + aic34b_write(aic34b_client, 49, val | 0x80);
> + /* Unmute HPLOUT with 1 dB gain */
> + aic34b_write(aic34b_client, HPLOUT_CTRL, 0x19);
> + /* Right PGA -> HPLCOM */
> + aic34b_read(aic34b_client, 56, &val);
> + aic34b_write(aic34b_client, 56, val | 0x80);
> + /* Unmute HPLCOM with 1 dB gain */
> + aic34b_write(aic34b_client, HPLCOM_CTRL, 0x19);
> + } else {
> + /* Disconnect LINE2R from RADC */
> + aic34b_write(aic34b_client, LINE2R_2_RADC_CTRL, 0xF8);
> + /* Mute Right ADC-PGA */
> + aic34b_write(aic34b_client, RADC_VOL, 0x80);
> + /* Detach Right PGA from HPLOUT */
> + aic34b_write(aic34b_client, 49, (~aic34b_volume & 0x7f));
> + /* Power down HPLOUT */
> + aic34b_write(aic34b_client, HPLOUT_CTRL, 0x06);
> + /* Detach Right PGA from HPLCOM */
> + aic34b_write(aic34b_client, 56, (~aic34b_volume & 0x7f));
> + /* Power down HPLCOM */
> + aic34b_write(aic34b_client, HPLCOM_CTRL, 0x06);
> + /* Deny any possible keypresses for a second */
> + deny_button_press();
> + /* To regain low power consumption, reset is needed */
> + aic34b_write(aic34b_client, AIC3X_RESET, SOFT_RESET);
> + /* And need to restore volume level */
> + aic34b_write(aic34b_client, 49, (~aic34b_volume & 0x7f));
> + aic34b_write(aic34b_client, 56, (~aic34b_volume & 0x7f));
> + /* Need to restore MICBIAS if set */
> + if (aic34b_bias)
> + aic34b_write(aic34b_client, MICBIAS_CTRL,
> + (aic34b_bias & 0x3) << 6);
> + }
> + mutex_unlock(&aic34b_mutex);
> +}
> +EXPORT_SYMBOL(aic34b_ear_enable);
> +
> +static int aic34b_dummy_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + u8 val;
> +
> + if (aic34b_read(client, AIC3X_PLL_PROGA_REG, &val) || val != 0x10) {
> + /* Chip not present */
> + return -ENODEV;
> + }
> + aic34b_client = client;
> +
> + /* Configure LINE2R for differential mode */
> + aic34b_read(client, LINE2R_2_RADC_CTRL, &val);
> + aic34b_write(client, LINE2R_2_RADC_CTRL, val | 0x80);
> +
> + return 0;
> +}
> +
> +static int aic34b_dummy_remove(struct i2c_client *client)
> +{
> + aic34b_client = NULL;
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id aic34b_dummy_id[] = {
> + { "aic34b_dummy", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, aic34b_dummy_id);
> +
> +static struct i2c_driver aic34b_dummy_driver = {
> + .driver = {
> + .name = "aic34b_dummy"
> + },
> + .probe = aic34b_dummy_probe,
> + .remove = aic34b_dummy_remove,
> + .id_table = aic34b_dummy_id,
> +};
> +
> +static int __init aic34b_dummy_init(void)
> +{
> + return i2c_add_driver(&aic34b_dummy_driver);
> +}
> +
> +static void __exit aic34b_dummy_exit(void)
> +{
> + i2c_del_driver(&aic34b_dummy_driver);
> +}
> +
> +MODULE_AUTHOR("Nokia Corporation");
> +MODULE_DESCRIPTION("Dummy driver for AIC34 block B parts used on Nokia RX51");
> +MODULE_LICENSE("GPL");
> +
> +module_init(aic34b_dummy_init);
> +module_exit(aic34b_dummy_exit);
> diff --git a/sound/soc/omap/aic34b_dummy.h b/sound/soc/omap/aic34b_dummy.h
> new file mode 100644
> index 0000000..2d386bf
> --- /dev/null
> +++ b/sound/soc/omap/aic34b_dummy.h
> @@ -0,0 +1,32 @@
> +/*
> + * aic34b_dummy.h
> + *
> + * Copyright (C) 2008 - 2009 Nokia Corporation
> + *
> + * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
> + * Eduardo Valentin <eduardo.valentin@nokia.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
> + *
> + */
> +
> +#ifndef __AIC34B_DUMMY__
> +#define __AIC34B_DUMMY__
> +
> +extern void aic34b_ear_enable(int enable);
> +void aic34b_set_mic_bias(int bias);
> +int aic34b_set_volume(u8 volume);
> +
> +#endif
> diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
> new file mode 100644
> index 0000000..74bafb2
> --- /dev/null
> +++ b/sound/soc/omap/rx51.c
> @@ -0,0 +1,793 @@
> +/*
> + * rx51.c -- SoC audio for Nokia RX51
> + *
> + * Copyright (C) 2008 - 2009 Nokia Corporation
> + *
> + * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
> + * Eduardo Valentin <eduardo.valentin@nokia.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/delay.h>
> +#include <linux/platform_device.h>
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/jack.h>
> +#include <sound/tlv.h>
> +
> +#include <linux/i2c/twl4030.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/tlv320aic3x.h"
> +#include "../codecs/tpa6130a2.h"
> +#include "aic34b_dummy.h"
> +
> +#define RX51_CODEC_RESET_GPIO 60
> +#define RX51_TVOUT_SEL_GPIO 40
> +#define RX51_ECI_SWITCH_1_GPIO 178
> +#define RX51_ECI_SWITCH_2_GPIO 182
> +/* REVISIT: TWL4030 GPIO base in RX51. Now statically defined to 192 */
> +#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7)
> +
> +enum {
> + RX51_JACK_DISABLED,
> + RX51_JACK_HP, /* headphone: stereo output, no mic */
> + RX51_JACK_HS, /* headset: stereo output with mic */
> + RX51_JACK_MIC, /* mic input only */
> + RX51_JACK_ECI, /* ECI headset */
> + RX51_JACK_TVOUT, /* stereo output with tv-out */
> +};
> +
> +static int rx51_spk_func;
> +static int rx51_jack_func;
> +static int rx51_fmtx_func;
> +static int rx51_dmic_func;
> +static int rx51_ear_func;
> +static struct snd_jack *rx51_jack;
> +
> +static DEFINE_MUTEX(eci_mutex);
> +static int rx51_eci_mode = 1;
> +static int rx51_dapm_jack_bias;
> +static int tpa6130_enable;
> +static int aic34b_volume;
> +
> +static void rx51_set_eci_switches(int mode)
> +{
> + switch (mode) {
> + case 0: /* Bias off */
> + case 1: /* Bias according to rx51_dapm_jack_bias */
> + case 4: /* Bias on */
> + /* Codec connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 1);
> + break;
> + case 2:
> + /* ECI INT#2 detect connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
> + break;
> + case 3:
> + /* ECI RX/TX connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 1);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
> + break;
> + }
> +}
> +
> +static void rx51_set_jack_bias(void)
> +{
> + int enable_bias = 0;
> +
> + mutex_lock(&eci_mutex);
> + if ((rx51_eci_mode == 1 && rx51_dapm_jack_bias) || rx51_eci_mode == 4)
> + enable_bias = 1;
> + else if (rx51_eci_mode == 1 && rx51_jack_func == RX51_JACK_ECI)
> + enable_bias = 1;
> + mutex_unlock(&eci_mutex);
> + if (enable_bias)
> + aic34b_set_mic_bias(2); /* 2.5 V */
> + else
> + aic34b_set_mic_bias(0);
> +}
> +
> +static void rx51_set_jack_bias_handler(struct work_struct *unused)
> +{
> + rx51_set_jack_bias();
> +}
> +DECLARE_WORK(rx51_jack_bias_work, rx51_set_jack_bias_handler);
> +
> +static void rx51_ext_control(struct snd_soc_codec *codec)
> +{
> + int hp = 0, mic = 0, tvout = 0;
> +
> + switch (rx51_jack_func) {
> + case RX51_JACK_ECI:
> + case RX51_JACK_HS:
> + mic = 1;
> + case RX51_JACK_HP:
> + hp = 1;
> + break;
> + case RX51_JACK_MIC:
> + mic = 1;
> + break;
> + case RX51_JACK_TVOUT:
> + hp = 1;
> + tvout = 1;
> + break;
> + }
> +
> + gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
> +
> + if (rx51_spk_func)
> + snd_soc_dapm_enable_pin(codec, "Ext Spk");
> + else
> + snd_soc_dapm_disable_pin(codec, "Ext Spk");
> + if (hp)
> + snd_soc_dapm_enable_pin(codec, "Headphone Jack");
> + else
> + snd_soc_dapm_disable_pin(codec, "Headphone Jack");
> + if (mic)
> + snd_soc_dapm_enable_pin(codec, "Mic Jack");
> + else
> + snd_soc_dapm_disable_pin(codec, "Mic Jack");
> + if (rx51_fmtx_func)
> + snd_soc_dapm_enable_pin(codec, "FM Transmitter");
> + else
> + snd_soc_dapm_disable_pin(codec, "FM Transmitter");
> + if (rx51_dmic_func)
> + snd_soc_dapm_enable_pin(codec, "DMic");
> + else
> + snd_soc_dapm_disable_pin(codec, "DMic");
> + if (rx51_ear_func)
> + snd_soc_dapm_enable_pin(codec, "Earphone");
> + else
> + snd_soc_dapm_disable_pin(codec, "Earphone");
> +
> + snd_soc_dapm_sync(codec);
> +}
> +
> +int rx51_set_eci_mode(int mode)
> +{
> + if (mode < 0 || mode > 4)
> + return -EINVAL;
> +
> + mutex_lock(&eci_mutex);
> + if (rx51_eci_mode == mode) {
> + mutex_unlock(&eci_mutex);
> + return 0;
> + }
> +
> + rx51_eci_mode = mode;
> + rx51_set_eci_switches(rx51_eci_mode);
> + mutex_unlock(&eci_mutex);
> +
> + rx51_set_jack_bias();
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(rx51_set_eci_mode);
> +
> +static ssize_t eci_mode_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + return sprintf(buf, "%d\n", rx51_eci_mode);
> +}
> +
> +static ssize_t eci_mode_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + int mode, retval;
> + if (sscanf(buf, "%d", &mode) != 1)
> + return -EINVAL;
> + retval = rx51_set_eci_mode(mode);
> +
> + return (retval < 0) ? retval : count;
> +}
> +
> +static DEVICE_ATTR(eci_mode, S_IRUGO | S_IWUSR,
> + eci_mode_show, eci_mode_store);
> +
> +void rx51_jack_report(int status)
> +{
> + snd_jack_report(rx51_jack, status);
> +}
> +EXPORT_SYMBOL(rx51_jack_report);
> +
> +static int rx51_startup(struct snd_pcm_substream *substream)
> +{
> + struct snd_pcm_runtime *runtime = substream->runtime;
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct snd_soc_codec *codec = rtd->socdev->card->codec;
> +
> + snd_pcm_hw_constraint_minmax(runtime,
> + SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
> +
> + rx51_ext_control(codec);
> +
> + return 0;
> +}
> +
> +static int rx51_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_IB_NF |
> + SND_SOC_DAIFMT_CBM_CFM);
> + if (err < 0)
> + return err;
> +
> + /* Set cpu DAI configuration */
> + err = snd_soc_dai_set_fmt(cpu_dai,
> + SND_SOC_DAIFMT_DSP_A |
> + SND_SOC_DAIFMT_IB_NF |
> + SND_SOC_DAIFMT_CBM_CFM);
> + if (err < 0)
> + return err;
> +
> + /* Set the codec system clock for DAC and ADC */
> + return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
> + SND_SOC_CLOCK_IN);
> +}
> +
> +static int rx51_bt_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;
> +
> + /* Set cpu DAI configuration */
> + return cpu_dai->ops->set_fmt(cpu_dai,
> + SND_SOC_DAIFMT_DSP_A |
> + SND_SOC_DAIFMT_IB_NF |
> + SND_SOC_DAIFMT_CBM_CFM);
> +}
> +
> +static struct snd_soc_ops rx51_bt_ops = {
> + .hw_params = rx51_bt_hw_params,
> +};
> +
> +static struct snd_soc_ops rx51_ops = {
> + .startup = rx51_startup,
> + .hw_params = rx51_hw_params,
> +};
> +
> +static int rx51_get_spk(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + ucontrol->value.integer.value[0] = rx51_spk_func;
> +
> + return 0;
> +}
> +
> +static int rx51_set_spk(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> + if (rx51_spk_func == ucontrol->value.integer.value[0])
> + return 0;
> +
> + rx51_spk_func = ucontrol->value.integer.value[0];
> + rx51_ext_control(codec);
> +
> + return 1;
> +}
> +
> +static int rx51_spk_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
> + if (SND_SOC_DAPM_EVENT_ON(event))
> + gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1);
> + else
> + gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0);
> +
> + return 0;
> +}
> +
> +static int rx51_get_jack(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + ucontrol->value.integer.value[0] = rx51_jack_func;
> +
> + return 0;
> +}
> +
> +static int rx51_set_jack(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> + if (rx51_jack_func == ucontrol->value.integer.value[0])
> + return 0;
> +
> + rx51_jack_func = ucontrol->value.integer.value[0];
> +
> + mutex_lock(&eci_mutex);
> + if (rx51_jack_func == RX51_JACK_ECI) {
> + /* Set ECI switches according to ECI mode */
> + rx51_set_eci_switches(rx51_eci_mode);
> + schedule_work(&rx51_jack_bias_work);
> + } else {
> + /*
> + * Let the codec always be connected to mic/bias line when
> + * jack is in non-ECI function
> + */
> + rx51_set_eci_switches(1);
> + schedule_work(&rx51_jack_bias_work);
> + }
> + mutex_unlock(&eci_mutex);
> +
> + rx51_ext_control(codec);
> +
> + return 1;
> +}
> +
> +static int rx51_jack_hp_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(k);
> + /*
> + * Note: HP amp and fmtx must not be enabled at the same
> + * time. We keep a shadow copy of the desired tpa_enable value but
> + * keep the hpamp really disabled whenever fmtx is enabled. If
> + * hpamp is requested on but fmtx is enabled, hpamp is kept
> + * disabled and enabled later from rx51_set_fmtx function when
> + * user disables fmtx.
> + */
> + if (SND_SOC_DAPM_EVENT_ON(event)) {
> + if (!rx51_fmtx_func)
> + snd_soc_dapm_enable_pin(codec, "TPA6130A2 Headphone");
> + tpa6130_enable = 1;
> + } else {
> + tpa6130_enable = 1;
> + snd_soc_dapm_disable_pin(codec, "TPA6130A2 Headphone");
> + tpa6130_enable = 0;
> + }
> +
> + return 0;
> +}
> +
> +static int rx51_jack_mic_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
> + if (SND_SOC_DAPM_EVENT_ON(event))
> + rx51_dapm_jack_bias = 1;
> + else
> + rx51_dapm_jack_bias = 0;
> + schedule_work(&rx51_jack_bias_work);
> +
> + return 0;
> +}
> +
> +static int rx51_get_fmtx(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + ucontrol->value.integer.value[0] = rx51_fmtx_func;
> +
> + return 0;
> +}
> +
> +static int rx51_set_fmtx(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> + if (rx51_fmtx_func == ucontrol->value.integer.value[0])
> + return 0;
> +
> + rx51_fmtx_func = ucontrol->value.integer.value[0];
> + rx51_ext_control(codec);
> +
> + /* fmtx and tpa must not be enabled at the same time */
> + if (rx51_fmtx_func && tpa6130_enable)
> + snd_soc_dapm_disable_pin(codec, "TPA6130A2 Headphone");
> + if (!rx51_fmtx_func && tpa6130_enable)
> + snd_soc_dapm_enable_pin(codec, "TPA6130A2 Headphone");
> +
> + return 1;
> +}
> +
> +static int rx51_get_input(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + ucontrol->value.integer.value[0] = rx51_dmic_func;
> +
> + return 0;
> +}
> +
> +static int rx51_set_input(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> + if (rx51_dmic_func == ucontrol->value.integer.value[0])
> + return 0;
> +
> + rx51_dmic_func = ucontrol->value.integer.value[0];
> + rx51_ext_control(codec);
> +
> + return 1;
> +}
> +
> +static int rx51_get_ear(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + ucontrol->value.integer.value[0] = rx51_ear_func;
> +
> + return 0;
> +}
> +
> +static int rx51_set_ear(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +
> + if (rx51_ear_func == ucontrol->value.integer.value[0])
> + return 0;
> +
> + rx51_ear_func = ucontrol->value.integer.value[0];
> + rx51_ext_control(codec);
> +
> + return 1;
> +}
> +
> +static int rx51_ear_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
> + if (SND_SOC_DAPM_EVENT_ON(event))
> + aic34b_ear_enable(1);
> + else
> + aic34b_ear_enable(0);
> +
> + return 0;
> +}
> +
> +enum {
> + RX51_EXT_API_AIC34B,
> +};
> +#define SOC_RX51_EXT_SINGLE_TLV(xname, ext_api, max, 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 = rx51_ext_info_volsw, \
> + .get = rx51_ext_get_volsw, \
> + .put = rx51_ext_put_volsw, \
> + .private_value = (ext_api) << 26 | (max) << 16, \
> +}
> +
> +static int rx51_ext_info_volsw(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_info *uinfo)
> +{
> + int max = (kcontrol->private_value >> 16) & 0xff;
> +
> + if (max == 1)
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
> + else
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> +
> + uinfo->count = 1;
> + uinfo->value.integer.min = 0;
> + uinfo->value.integer.max = max;
> +
> + return 0;
> +}
> +
> +static int rx51_ext_get_volsw(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + int ext_api = (kcontrol->private_value >> 26) & 0x0f;
> +
> + switch (ext_api) {
> + case RX51_EXT_API_AIC34B:
> + ucontrol->value.integer.value[0] = aic34b_volume;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int rx51_ext_put_volsw(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + int ext_api = (kcontrol->private_value >> 26) & 0x0f;
> + int change = 0;
> +
> + switch (ext_api) {
> + case RX51_EXT_API_AIC34B:
> + change = (aic34b_volume != ucontrol->value.integer.value[0]);
> + aic34b_volume = ucontrol->value.integer.value[0];
> + aic34b_set_volume(aic34b_volume);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return change;
> +}
> +
> +static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
> + SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
> + SND_SOC_DAPM_SPK("Headphone Jack", rx51_jack_hp_event),
> + SND_SOC_DAPM_MIC("Mic Jack", rx51_jack_mic_event),
> + SND_SOC_DAPM_OUTPUT("FM Transmitter"),
> + SND_SOC_DAPM_MIC("DMic", NULL),
> + SND_SOC_DAPM_SPK("Earphone", rx51_ear_event),
> +};
> +
> +static const struct snd_soc_dapm_route audio_map[] = {
> + {"Ext Spk", NULL, "HPLOUT"},
> + {"Ext Spk", NULL, "HPROUT"},
> +
> + {"TPA6130A2 Headphone", NULL, "LLOUT"},
> + {"TPA6130A2 Headphone", NULL, "RLOUT"},
> + {"LINE1L", NULL, "Mic Jack"},
> +
> + {"FM Transmitter", NULL, "LLOUT"},
> + {"FM Transmitter", NULL, "RLOUT"},
> +
> + {"Earphone", NULL, "MONO_LOUT"},
> +
> + {"DMic Rate 64", NULL, "Mic Bias 2V"},
> + {"Mic Bias 2V", NULL, "DMic"},
> +};
> +
> +static const char *spk_function[] = {"Off", "On"};
> +static const char *jack_function[] = {"Off", "Headphone", "Headset",
> + "Mic", "ECI Headset", "TV-OUT"};
> +static const char *fmtx_function[] = {"Off", "On"};
> +static const char *input_function[] = {"ADC", "Digital Mic"};
> +static const char *ear_function[] = {"Off", "On"};
> +
> +static const struct soc_enum rx51_enum[] = {
> + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
> + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
> + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fmtx_function), fmtx_function),
> + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
> + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ear_function), ear_function),
> +};
> +
> +/*
> + * TLV320AIC3x output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB.
> + * Step size is approximately 0.5 dB over most of the scale but increasing
> + * near the very low levels.
> + * Define dB scale so that it is mostly correct for range about -55 to 0 dB
> + * but having increasing dB difference below that (and where it doesn't count
> + * so much). This setting shows -50 dB (actual is -50.3 dB) for register
> + * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117.
> + */
> +static DECLARE_TLV_DB_SCALE(aic3x_output_stage_tlv, -5900, 50, 1);
> +
> +static const struct snd_kcontrol_new aic34_rx51_controls[] = {
> + SOC_ENUM_EXT("Speaker Function", rx51_enum[0],
> + rx51_get_spk, rx51_set_spk),
> + SOC_ENUM_EXT("Jack Function", rx51_enum[1],
> + rx51_get_jack, rx51_set_jack),
> + SOC_ENUM_EXT("FMTX Function", rx51_enum[2],
> + rx51_get_fmtx, rx51_set_fmtx),
> + SOC_ENUM_EXT("Input Select", rx51_enum[3],
> + rx51_get_input, rx51_set_input),
> + SOC_ENUM_EXT("Earphone Function", rx51_enum[4],
> + rx51_get_ear, rx51_set_ear),
> + SOC_RX51_EXT_SINGLE_TLV("Earphone Playback Volume",
> + RX51_EXT_API_AIC34B, 118,
> + aic3x_output_stage_tlv),
> +};
> +
> +static int rx51_aic34_init(struct snd_soc_codec *codec)
> +{
> + int i, err;
> +
> + /* Add TPA6130A2 controls */
> + tpa6130a2_add_controls(codec);
> +
> + /* set up NC codec pins */
> + snd_soc_dapm_nc_pin(codec, "MIC3L");
> + snd_soc_dapm_nc_pin(codec, "MIC3R");
> + snd_soc_dapm_nc_pin(codec, "LINE1R");
> +
> + /* Create jack for accessory reporting */
> + err = snd_jack_new(codec->card, "Jack", SND_JACK_MECHANICAL |
> + SND_JACK_HEADSET | SND_JACK_AVOUT, &rx51_jack);
> + if (err < 0)
> + return err;
> +
> + /* Add RX51 specific controls */
> + for (i = 0; i < ARRAY_SIZE(aic34_rx51_controls); i++) {
> + err = snd_ctl_add(codec->card,
> + snd_soc_cnew(&aic34_rx51_controls[i], codec, NULL));
> + if (err < 0)
> + return err;
> + }
> +
> + /* Add RX51 specific widgets */
> + snd_soc_dapm_new_controls(codec, aic34_dapm_widgets,
> + ARRAY_SIZE(aic34_dapm_widgets));
> +
> + /* Set up RX51 specific audio path audio_map */
> + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
> +
> + snd_soc_dapm_enable_pin(codec, "Earphone");
> +
> + snd_soc_dapm_sync(codec);
> +
> + return 0;
> +}
> +
> +/* Since all codec control is done by Bluetooth hardware
> + only some constrains need to be set for it */
> +struct snd_soc_dai btcodec_dai = {
> + .name = "Bluetooth codec",
> + .playback = {
> + .stream_name = "BT Playback",
> + .channels_min = 1,
> + .channels_max = 1,
> + .rates = SNDRV_PCM_RATE_8000,
> + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
> + .capture = {
> + .stream_name = "BT Capture",
> + .channels_min = 1,
> + .channels_max = 1,
> + .rates = SNDRV_PCM_RATE_8000,
> + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
> +};
> +
> +/* Digital audio interface glue - connects codec <--> CPU */
> +static struct snd_soc_dai_link rx51_dai[] = {
> + {
> + .name = "TLV320AIC34",
> + .stream_name = "AIC34",
> + .cpu_dai = &omap_mcbsp_dai[0],
> + .codec_dai = &aic3x_dai,
> + .init = rx51_aic34_init,
> + .ops = &rx51_ops,
> + }, {
> + .name = "Bluetooth PCM",
> + .stream_name = "Bluetooth",
> + .cpu_dai = &omap_mcbsp_dai[1],
> + .codec_dai = &btcodec_dai,
> + .ops = &rx51_bt_ops,
> + }
> +};
> +
> +/* Audio private data */
> +static struct aic3x_setup_data rx51_aic34_setup = {
> + .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
> + .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
> +};
> +
> +/* Audio card */
> +static struct snd_soc_card rx51_sound_card = {
> + .name = "RX51",
> + .dai_link = rx51_dai,
> + .num_links = ARRAY_SIZE(rx51_dai),
> + .platform = &omap_soc_platform,
> +};
> +
> +/* Audio subsystem */
> +static struct snd_soc_device rx51_snd_devdata = {
> + .card = &rx51_sound_card,
> + .codec_dev = &soc_codec_dev_aic3x,
> + .codec_data = &rx51_aic34_setup,
> +};
> +
> +static struct platform_device *rx51_snd_device;
> +
> +#define REMAP_OFFSET 2
> +#define DEDICATED_OFFSET 3
> +#define VMMC2_DEV_GRP 0x2B
> +#define VMMC2_285V 0x0a
> +
These defines appear unused?
> +static int __init rx51_soc_init(void)
> +{
> + int err;
> + struct device *dev;
> +
> + if (!machine_is_nokia_rx51())
> + return -ENODEV;
> +
> + if (gpio_request(RX51_CODEC_RESET_GPIO, NULL) < 0)
> + BUG();
> + if (gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel") < 0)
> + BUG();
> + if (gpio_request(RX51_ECI_SWITCH_1_GPIO, "ECI switch 1") < 0)
> + BUG();
> + if (gpio_request(RX51_ECI_SWITCH_2_GPIO, "ECI switch 2") < 0)
> + BUG();
> + gpio_direction_output(RX51_CODEC_RESET_GPIO, 0);
> + gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
> + gpio_direction_output(RX51_ECI_SWITCH_1_GPIO, 0);
> + gpio_direction_output(RX51_ECI_SWITCH_2_GPIO, 1);
> +
> + gpio_set_value(RX51_CODEC_RESET_GPIO, 0);
> + udelay(1);
> + gpio_set_value(RX51_CODEC_RESET_GPIO, 1);
> + msleep(1);
> +
> + if (gpio_request(RX51_SPEAKER_AMP_TWL_GPIO, NULL) < 0)
> + BUG();
> + gpio_direction_output(RX51_SPEAKER_AMP_TWL_GPIO, 0);
> +
> + err = snd_soc_register_dai(&btcodec_dai);
> + if (err)
> + return err;
> +
> + rx51_snd_device = platform_device_alloc("soc-audio", -1);
> + if (!rx51_snd_device) {
> + err = -ENOMEM;
> + goto err0;
> + }
> +
> + platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata);
> + rx51_snd_devdata.dev = &rx51_snd_device->dev;
> + err = platform_device_add(rx51_snd_device);
> + if (err)
> + goto err1;
> +
> + dev = &rx51_snd_device->dev;
> +
> + *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1;
> + *(unsigned int *)rx51_dai[1].cpu_dai->private_data = 2;
> +
> + err = device_create_file(dev, &dev_attr_eci_mode);
> + if (err)
> + goto err2;
> +
> + return err;
> +err2:
> + platform_device_del(rx51_snd_device);
> +err1:
> + platform_device_put(rx51_snd_device);
> +err0:
> + snd_soc_unregister_dai(&btcodec_dai);
> +
> + return err;
> +
> +}
> +
> +static void __exit rx51_soc_exit(void)
> +{
> + platform_device_unregister(rx51_snd_device);
> + snd_soc_unregister_dai(&btcodec_dai);
> +}
> +
> +module_init(rx51_soc_init);
> +module_exit(rx51_soc_exit);
> +
> +MODULE_AUTHOR("Nokia Corporation");
> +MODULE_DESCRIPTION("ALSA SoC Nokia RX51");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/omap/rx51.h b/sound/soc/omap/rx51.h
> new file mode 100644
> index 0000000..ee55260
> --- /dev/null
> +++ b/sound/soc/omap/rx51.h
> @@ -0,0 +1,29 @@
> +#ifndef _RX51_H_
> +#define _RX51_H_
> +
> +/*
> + * rx51.h - SoC audio for Nokia RX51
> + *
> + * Copyright (C) 2008 - 2009 Nokia Corporation
> + *
> + * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
> + * Eduardo Valentin <eduardo.valentin@nokia.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; version 2 of the License.
> + *
> + * 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
> + */
> +
> +int rx51_set_eci_mode(int mode);
> +void rx51_jack_report(int status);
> +
> +#endif /* _RX51_H_ */
> --
> 1.6.4.183.g04423
>
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
2009-10-08 12:30 ` Eero Nurkkala
@ 2009-10-08 12:52 ` Mark Brown
2009-10-08 13:38 ` Peter Ujfalusi
1 sibling, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 12:52 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:50PM +0300, Eduardo Valentin wrote:
> +struct tpa6130a2_platform_data {
> + int (*set_power)(int state);
> +};
Why is this a callback and not just a GPIO number? That'd seem simpler
for users.
> +int tpa6130a2_add_controls(struct snd_soc_codec *codec)
> +{
> + snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
> + ARRAY_SIZE(tpa6130a2_dapm_widgets));
> +
> + return snd_soc_add_controls(codec, tpa6130a2_controls,
> + ARRAY_SIZE(tpa6130a2_controls));
> +
> +}
> +EXPORT_SYMBOL(tpa6130a2_add_controls);
All the ASoC APIs are EXPORT_SYMBOL_GPL().
> + pdata = (struct tpa6130a2_platform_data *)client->dev.platform_data;
> + /* Set default register values */
> + data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
> + TPA6130A2_HP_EN_R |
> + TPA6130A2_HP_EN_L;
This looks like you could implement stereo paths with individual power
control?
> + data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_VOLUME(20);
The standard thing is to use hardware defaults and leave decisions like
this up to user space.
> + data->set_power = pdata->set_power;
> + if (!pdata->set_power) {
> + data->power_state = 1;
> + tpa6130a2_initialize();
> + }
> + tpa6130a2_power(1);
> +
> + /* Read version */
> + err = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
> + TPA6130A2_VERSION_MASK;
> + if ((err != 1) && (err != 2)) {
> + dev_err(dev, "Unexpected headphone amplifier chip version "
> + "of 0x%02x, was expecting 0x01 or 0x02\n", err);
> + err = -ENODEV;
This seems a bit excessive - is it really likely that the register map
would be changed incompatibly in a future version?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 12:30 ` Eero Nurkkala
@ 2009-10-08 13:07 ` Peter Ujfalusi
0 siblings, 0 replies; 58+ messages in thread
From: Peter Ujfalusi @ 2009-10-08 13:07 UTC (permalink / raw)
To: Nurkkala Eero.An (EXT-Offcode/Oulu)
Cc: Valentin Eduardo (Nokia-D/Helsinki), Mark Brown,
ext Tony Lindgren, Jarkko Nikula, Linux-OMAP, ALSA-Devel
On Thursday 08 October 2009 15:30:29 Nurkkala Eero.An (EXT-Offcode/Oulu) wrote:
> On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
>
> wrote:
> > +/*
> > + * TPA6130 volume. From -59.5 to 4 dB with increasing step size when
> > going + * down in gain. Justify scale so that it is quite correct from
> > -20 dB and + * up. This setting shows -30 dB at minimum, -12.95 dB at 49
> > % (actual + * is -10.3 dB) and 4.65 dB at maximum (actual is 4 dB).
> > + */
>
> The comment is misleading from all it says. For me it seems that the
> scale is quite correct from -59.5 to 4 dB or so. Also the minimum is
> -59.5 dB, not -30.
Yes, the scale is really close to the reality, the comment need to be fixed.
--
Péter
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-08 11:58 ` [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver Eduardo Valentin
2009-10-08 12:31 ` Eero Nurkkala
@ 2009-10-08 13:11 ` Mark Brown
2009-10-09 5:44 ` Jarkko Nikula
1 sibling, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:11 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:51PM +0300, Eduardo Valentin wrote:
> From: Eduardo Valentin <eduardo.valentin@nokia.com>
> Introduce RX-51 Machine driver for ASoC and AIC34b_dummy (block B) i2c driver.
What is an "AIC34b_dummy (block B)"? You probably want to split it out
into a separate patch.
> + * TODO:
> + * - Get rid of this driver, at least when ASoC v2 is merged and when
> + * we can support multiple codec instances in tlv320aic3x.c driver.
> + * This driver is hacked only for Nokia RX51 HW.
Could you please explain what the issue here is? A description of the
hardware would go a long way here.
> +EXPORT_SYMBOL(aic34b_set_mic_bias);
EXPORT_SYMBOL_GPL().
> +static void rx51_set_eci_switches(int mode)
> +{
> + switch (mode) {
> + case 0: /* Bias off */
> + case 1: /* Bias according to rx51_dapm_jack_bias */
> + case 4: /* Bias on */
> + /* Codec connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 1);
> + break;
> + case 2:
> + /* ECI INT#2 detect connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 0);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
> + break;
> + case 3:
> + /* ECI RX/TX connected to mic/bias line */
> + gpio_set_value(RX51_ECI_SWITCH_1_GPIO, 1);
> + gpio_set_value(RX51_ECI_SWITCH_2_GPIO, 0);
> + break;
> + }
Some defines for the mode (instead of magic numbers) would be nice).
> +void rx51_jack_report(int status)
> +{
> + snd_jack_report(rx51_jack, status);
> +}
> +EXPORT_SYMBOL(rx51_jack_report);
Why is this being exported?
> +enum {
> + RX51_EXT_API_AIC34B,
> +};
> +#define SOC_RX51_EXT_SINGLE_TLV(xname, ext_api, max, 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 = rx51_ext_info_volsw, \
> + .get = rx51_ext_get_volsw, \
> + .put = rx51_ext_put_volsw, \
> + .private_value = (ext_api) << 26 | (max) << 16, \
> +}
This looks like it ought to be pushed down into some other driver?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-08 11:58 ` [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature Eduardo Valentin
@ 2009-10-08 13:17 ` Mark Brown
2009-10-08 13:23 ` Eduardo Valentin
2009-10-09 5:09 ` Eero Nurkkala
0 siblings, 2 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:17 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:52PM +0300, Eduardo Valentin wrote:
> +static const struct attribute *sidetone_attrs[] = {
> + &dev_attr_st_enable.attr,
> + &dev_attr_st_taps.attr,
> + &dev_attr_st_ch0gain.attr,
> + &dev_attr_st_ch1gain.attr,
> + NULL,
> +};
This stuff, particularly the enable, probably wants to be pushed out via
an ALSA API rather than via random sysfs stuff. It'd be better to
publish a control API here and then use that from within ALSA.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 12:17 ` Eero Nurkkala
@ 2009-10-08 13:17 ` Eduardo Valentin
2009-10-08 13:40 ` Mark Brown
1 sibling, 0 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 13:17 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Valentin Eduardo (Nokia-D/Helsinki),
Mark Brown, Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:17:07PM +0200, Nurkkala Eero.An (EXT-Offcode/Oulu) wrote:
> On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
> wrote:
> > From: Eduardo Valentin <eduardo.valentin@nokia.com>
> >
> > This patch adds initial usage of regulator framework to control avdd_dac
> > inside tlv320aic3x ASoC codec driver.
> >
> > The refcount to avdd_dac is increased / decreased
> > only during probe and remove. Here it is still needed to implement
> > proper enable/disable regulator depending on chip usage. Now if driver
> > can get regulator for avdd_dac, then it will just let it on on probe
> > and then leave it off on remove.
> >
> > Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
> > ---
> > sound/soc/codecs/tlv320aic3x.c | 26 ++++++++++++++++++++++++++
> > 1 files changed, 26 insertions(+), 0 deletions(-)
> >
> > diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
> > index 3395cf9..82e0a64 100644
> > --- a/sound/soc/codecs/tlv320aic3x.c
> > +++ b/sound/soc/codecs/tlv320aic3x.c
> > @@ -38,6 +38,7 @@
> > #include <linux/delay.h>
> > #include <linux/pm.h>
> > #include <linux/i2c.h>
> > +#include <linux/regulator/consumer.h>
> > #include <linux/platform_device.h>
> > #include <sound/core.h>
> > #include <sound/pcm.h>
> > @@ -56,6 +57,7 @@ struct aic3x_priv {
> > struct snd_soc_codec codec;
> > unsigned int sysclk;
> > int master;
> > + struct regulator *regulator;
> > };
> >
> > /*
> > @@ -1286,6 +1288,11 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
> > snd_soc_unregister_dai(&aic3x_dai);
> > snd_soc_unregister_codec(&aic3x->codec);
> >
> > + if (aic3x->regulator) {
> > + regulator_disable(aic3x->regulator);
> > + regulator_put(aic3x->regulator);
> > + }
> > +
> > kfree(aic3x);
> > aic3x_codec = NULL;
> >
> > @@ -1320,6 +1327,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
> > codec->control_data = i2c;
> > codec->hw_write = (hw_write_t) i2c_master_send;
> >
> > + aic3x->regulator = regulator_get(&i2c->dev, "avdd_dac");
> > + if (IS_ERR(aic3x->regulator)) {
> > + dev_warn(&i2c->dev, "No regulator to supply avdd_dac."
> > + " Assuming always on.\n");
> > + aic3x->regulator = NULL;
> > + }
> > +
> > + /*
> > + * REVISIT: Need to add proper code to put into sleep mode
> > + * avdd_dac regulator. For now, just leave it on.
> > + */
>
> Will this ever be revisited =) ? If so, I think there's going to be a
> jungle in finding the right spots - you need to remember the bypass
> paths also (bias is not on necessarily). Also, this is regulator thing
> is highly platform dependent, not aic3x related really at all, so is
> this the correct place... Just a thought, dont take it too seriously ;)
Heheh.. no I don't take it too seriously, don't worry :-)
Actually I've discussed about it with Peter. Initially I wrote it
inside rx51 machine driver. But then, we agreed it is actually a
thing which must be controlled by the driver. The same way it is done
for TPA for instance.
Of course, the presence of that regulator must not be a blocker for
the driver. As you can see, if the regulator can not be queried, the driver
will assume that it is always on.
I must agree with you, but would rephrase as: the presence of this regulator
is board specific, but controlling when it must be enabled/disabled is a role
for the driver, in this case, tlv320aic3x.
What do you think ?
>
> > + if (aic3x->regulator) {
> > + int err;
> > +
> > + err = regulator_enable(aic3x->regulator);
> > + if (err < 0)
> > + return err;
> > + }
> > +
> > i2c_set_clientdata(i2c, aic3x);
> >
> > return aic3x_register(codec);
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-08 12:31 ` Eero Nurkkala
@ 2009-10-08 13:18 ` Eduardo Valentin
0 siblings, 0 replies; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 13:18 UTC (permalink / raw)
To: Nurkkala Eero.An (EXT-Offcode/Oulu)
Cc: Valentin Eduardo (Nokia-D/Helsinki), Mark Brown,
ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Jarkko Nikula, Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 02:31:26PM +0200, Nurkkala Eero.An (EXT-Offcode/Oulu) wrote:
> On Thu, 2009-10-08 at 13:58 +0200, Valentin Eduardo (Nokia-D/Helsinki)
> wrote:
> > From: Eduardo Valentin <eduardo.valentin@nokia.com>
> >
> > Introduce RX-51 Machine driver for ASoC and AIC34b_dummy (block B) i2c driver.
> >
> > Also move the request_gpio of speaker_enabled
> > from board-rx51-peripherals.c to this machine driver.
> >
> > These drivers were originally written by Jarkko Nikula.
> >
> > Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
> > ---
> > arch/arm/mach-omap2/board-rx51-peripherals.c | 2 -
> > sound/soc/omap/Kconfig | 10 +
> > sound/soc/omap/Makefile | 2 +
> > sound/soc/omap/aic34b_dummy.c | 271 +++++++++
> > sound/soc/omap/aic34b_dummy.h | 32 +
> > sound/soc/omap/rx51.c | 793 ++++++++++++++++++++++++++
> > sound/soc/omap/rx51.h | 29 +
> > 7 files changed, 1137 insertions(+), 2 deletions(-)
> > create mode 100644 sound/soc/omap/aic34b_dummy.c
> > create mode 100644 sound/soc/omap/aic34b_dummy.h
> > create mode 100644 sound/soc/omap/rx51.c
> > create mode 100644 sound/soc/omap/rx51.h
> >
<snip>
> > +static struct platform_device *rx51_snd_device;
> > +
> > +#define REMAP_OFFSET 2
> > +#define DEDICATED_OFFSET 3
> > +#define VMMC2_DEV_GRP 0x2B
> > +#define VMMC2_285V 0x0a
> > +
>
> These defines appear unused?
yeah, will rip then off.
>
> > +static int __init rx51_soc_init(void)
> > +{
> > + int err;
> > + struct device *dev;
> > +
> > + if (!machine_is_nokia_rx51())
> > + return -ENODEV;
> > +
> > + if (gpio_request(RX51_CODEC_RESET_GPIO, NULL) < 0)
> > + BUG();
> > + if (gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel") < 0)
> > + BUG();
> > + if (gpio_request(RX51_ECI_SWITCH_1_GPIO, "ECI switch 1") < 0)
> > + BUG();
> > + if (gpio_request(RX51_ECI_SWITCH_2_GPIO, "ECI switch 2") < 0)
> > + BUG();
> > + gpio_direction_output(RX51_CODEC_RESET_GPIO, 0);
> > + gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
> > + gpio_direction_output(RX51_ECI_SWITCH_1_GPIO, 0);
> > + gpio_direction_output(RX51_ECI_SWITCH_2_GPIO, 1);
> > +
> > + gpio_set_value(RX51_CODEC_RESET_GPIO, 0);
> > + udelay(1);
> > + gpio_set_value(RX51_CODEC_RESET_GPIO, 1);
> > + msleep(1);
> > +
> > + if (gpio_request(RX51_SPEAKER_AMP_TWL_GPIO, NULL) < 0)
> > + BUG();
> > + gpio_direction_output(RX51_SPEAKER_AMP_TWL_GPIO, 0);
> > +
> > + err = snd_soc_register_dai(&btcodec_dai);
> > + if (err)
> > + return err;
> > +
> > + rx51_snd_device = platform_device_alloc("soc-audio", -1);
> > + if (!rx51_snd_device) {
> > + err = -ENOMEM;
> > + goto err0;
> > + }
> > +
> > + platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata);
> > + rx51_snd_devdata.dev = &rx51_snd_device->dev;
> > + err = platform_device_add(rx51_snd_device);
> > + if (err)
> > + goto err1;
> > +
> > + dev = &rx51_snd_device->dev;
> > +
> > + *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1;
> > + *(unsigned int *)rx51_dai[1].cpu_dai->private_data = 2;
> > +
> > + err = device_create_file(dev, &dev_attr_eci_mode);
> > + if (err)
> > + goto err2;
> > +
> > + return err;
> > +err2:
> > + platform_device_del(rx51_snd_device);
> > +err1:
> > + platform_device_put(rx51_snd_device);
> > +err0:
> > + snd_soc_unregister_dai(&btcodec_dai);
> > +
> > + return err;
> > +
> > +}
> > +
> > +static void __exit rx51_soc_exit(void)
> > +{
> > + platform_device_unregister(rx51_snd_device);
> > + snd_soc_unregister_dai(&btcodec_dai);
> > +}
> > +
> > +module_init(rx51_soc_init);
> > +module_exit(rx51_soc_exit);
> > +
> > +MODULE_AUTHOR("Nokia Corporation");
> > +MODULE_DESCRIPTION("ALSA SoC Nokia RX51");
> > +MODULE_LICENSE("GPL");
> > diff --git a/sound/soc/omap/rx51.h b/sound/soc/omap/rx51.h
> > new file mode 100644
> > index 0000000..ee55260
> > --- /dev/null
> > +++ b/sound/soc/omap/rx51.h
> > @@ -0,0 +1,29 @@
> > +#ifndef _RX51_H_
> > +#define _RX51_H_
> > +
> > +/*
> > + * rx51.h - SoC audio for Nokia RX51
> > + *
> > + * Copyright (C) 2008 - 2009 Nokia Corporation
> > + *
> > + * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com>
> > + * Eduardo Valentin <eduardo.valentin@nokia.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; version 2 of the License.
> > + *
> > + * 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
> > + */
> > +
> > +int rx51_set_eci_mode(int mode);
> > +void rx51_jack_report(int status);
> > +
> > +#endif /* _RX51_H_ */
> > --
> > 1.6.4.183.g04423
> >
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-08 11:58 ` [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies Eduardo Valentin
@ 2009-10-08 13:21 ` Mark Brown
2009-10-09 6:45 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:21 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:54PM +0300, Eduardo Valentin wrote:
> From: Eduardo Valentin <eduardo.valentin@nokia.com>
> Use separated supplies for vaux3 and vmmc2.
> Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
> +static struct regulator_consumer_supply rx51_vaux3_supply = {
> + .supply = "vmmc",
> +};
> +
I'd expect all these supplies to have devices associated with them (see
below)...
> static struct regulator_consumer_supply rx51_vmmc2_supply = {
> .supply = "vmmc",
> };
> @@ -184,7 +188,7 @@ static struct regulator_init_data rx51_vaux3_mmc = {
> | REGULATOR_CHANGE_STATUS,
> },
> .num_consumer_supplies = 1,
> - .consumer_supplies = &rx51_vmmc2_supply,
> + .consumer_supplies = &rx51_vaux3_supply,
> };
I may have missed it but I don't see rx51_vmmc2_supply added back
anywhere in the patch?
> static struct regulator_init_data rx51_vaux4 = {
> @@ -266,7 +270,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
> /* set up MMC adapters, linking their regulators to them */
> twl4030_mmc_init(mmc);
> rx51_vmmc1_supply.dev = mmc[0].dev;
> - rx51_vmmc2_supply.dev = mmc[1].dev;
> + rx51_vaux3_supply.dev = mmc[1].dev;
...using dev_name rather than dev should avoid the need to do this at
runtime.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-08 13:17 ` Mark Brown
@ 2009-10-08 13:23 ` Eduardo Valentin
2009-10-08 13:27 ` Mark Brown
2009-10-09 5:09 ` Eero Nurkkala
1 sibling, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 13:23 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 03:17:02PM +0200, Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:52PM +0300, Eduardo Valentin wrote:
>
> > +static const struct attribute *sidetone_attrs[] = {
> > + &dev_attr_st_enable.attr,
> > + &dev_attr_st_taps.attr,
> > + &dev_attr_st_ch0gain.attr,
> > + &dev_attr_st_ch1gain.attr,
> > + NULL,
> > +};
>
> This stuff, particularly the enable, probably wants to be pushed out via
> an ALSA API rather than via random sysfs stuff. It'd be better to
> publish a control API here and then use that from within ALSA.
I see. The thing is this mcbsp driver is kinda of odd driver.
It is currently a platform driver. And it is supposed to be not
restricted to audio things (even though it is currently used only
by audio). It does not export any alsa interface currently.
So, maybe we should rip off this sysfs things, export
symbols inside kernel and then export to user land somewhere else
from alsa code?
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-08 11:58 ` [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2 Eduardo Valentin
@ 2009-10-08 13:26 ` Mark Brown
2009-10-12 9:04 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:26 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:55PM +0300, Eduardo Valentin wrote:
> +static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
> + REGULATOR_SUPPLY("avdd_dac", "2-0018"), /* tlv320aic3x */
> + REGULATOR_SUPPLY("vdd", "2-0060"), /* tpa6130a2*/
> };
avdd_dac is the only supply added for the tlv320aic3x but, for example,
the tlv320aic34 has something like 8 supplies from a quick scan of the
datasheet. It'd be better to set up all of the supplies, even if only
with a fixed voltage regulator supplying them, since when regulator
support is added to the CODEC driver it should be requesting all the
supplies it needs and therefore fail to instatiate if some are missing.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-08 13:23 ` Eduardo Valentin
@ 2009-10-08 13:27 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:27 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 04:23:33PM +0300, Eduardo Valentin wrote:
> So, maybe we should rip off this sysfs things, export
> symbols inside kernel and then export to user land somewhere else
> from alsa code?
Yes, that's what I'm suggesting. Provide an API to ALSA and then let
ALSA worry about the control stuff.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 12:52 ` Mark Brown
@ 2009-10-08 13:38 ` Peter Ujfalusi
2009-10-08 13:53 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Peter Ujfalusi @ 2009-10-08 13:38 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thursday 08 October 2009 15:52:13 ext Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:50PM +0300, Eduardo Valentin wrote:
> > +struct tpa6130a2_platform_data {
> > + int (*set_power)(int state);
> > +};
>
> Why is this a callback and not just a GPIO number? That'd seem simpler
> for users.
Well, same amount of code, but in different place if the power is enabled
through a GPIO. But if the power is controlled via different means (nothing
comes to mind, but there are exotic systems out there), in this way it is simple
to handle
>
> > +int tpa6130a2_add_controls(struct snd_soc_codec *codec)
> > +{
> > + snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
> > + ARRAY_SIZE(tpa6130a2_dapm_widgets));
> > +
> > + return snd_soc_add_controls(codec, tpa6130a2_controls,
> > + ARRAY_SIZE(tpa6130a2_controls));
> > +
> > +}
> > +EXPORT_SYMBOL(tpa6130a2_add_controls);
>
> All the ASoC APIs are EXPORT_SYMBOL_GPL().
Right.
>
> > + pdata = (struct tpa6130a2_platform_data *)client->dev.platform_data;
> > + /* Set default register values */
> > + data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
> > + TPA6130A2_HP_EN_R |
> > + TPA6130A2_HP_EN_L;
>
> This looks like you could implement stereo paths with individual power
> control?
Can we put something in between DAPM_OUTPUT and DAPM_HP to handle the stereo
path correctly?
We could have two paths from codec to the "TPA6130A2 Headphone", which is needed
to actually control the power of the amplifier.
At the end we are not really gaining much, but one more level of switch on the
path.
We could have simple mute alsa controls in tpa6130a2_controls for the amplifier
itself...
>
> > + data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_VOLUME(20);
>
> The standard thing is to use hardware defaults and leave decisions like
> this up to user space.
OK, The reset value is 0 (-59.5 dB)
>
> > + data->set_power = pdata->set_power;
> > + if (!pdata->set_power) {
> > + data->power_state = 1;
> > + tpa6130a2_initialize();
> > + }
> > + tpa6130a2_power(1);
> > +
> > + /* Read version */
> > + err = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
> > + TPA6130A2_VERSION_MASK;
> > + if ((err != 1) && (err != 2)) {
> > + dev_err(dev, "Unexpected headphone amplifier chip version "
> > + "of 0x%02x, was expecting 0x01 or 0x02\n", err);
> > + err = -ENODEV;
>
> This seems a bit excessive - is it really likely that the register map
> would be changed incompatibly in a future version?
Hmm, we have only seen these versions of the chip, and we know that the driver
works with these. Also we don't have any information on different versions, but
I would think that the register map is not changing (the reset values for some
registers are different)
--
Péter
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 11:58 ` [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac Eduardo Valentin
2009-10-08 12:17 ` Eero Nurkkala
@ 2009-10-08 13:38 ` Mark Brown
1 sibling, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:38 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:56PM +0300, Eduardo Valentin wrote:
> This patch adds initial usage of regulator framework to control avdd_dac
> inside tlv320aic3x ASoC codec driver.
If you're going to do this you should add support for all the supplies
of the device, not just one of them. The extra effort required is low
and it avoids compatibility problems when someone wants to set up other
supplies, causing existing boards to need to specify them.
> + aic3x->regulator = regulator_get(&i2c->dev, "avdd_dac");
> + if (IS_ERR(aic3x->regulator)) {
> + dev_warn(&i2c->dev, "No regulator to supply avdd_dac."
> + " Assuming always on.\n");
You shouldn't split error messages over multiple lines like this, it
breaks grepping to try to find where the message came from.
I'd also rather see failure to get the regulator treated as a hard
error. When the regulator API compiled out it is stubbed so that for
simple get/enable/disable/put usage it will return success but do
nothing. If the regulator API is compiled in and we're not able to
acquire regulators there's a good chance that things will break (eg, due
to supplies being turned off because they appear to be unused) so
flagging the error immediately is less likely to result in runtime
fragility.
> + /*
> + * REVISIT: Need to add proper code to put into sleep mode
> + * avdd_dac regulator. For now, just leave it on.
> + */
> + if (aic3x->regulator) {
> + int err;
> +
> + err = regulator_enable(aic3x->regulator);
> + if (err < 0)
> + return err;
> + }
The best way to handle this is to push the enable/disable into the bias
level configuration so that the regulators are enabled when the chip
goes off->standby and disabled during standby->off. This will have the
same effect for the moment but will mean that we'll be able to add core
support for fully powering down the audio subsystem at runtime in the
future.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 12:17 ` Eero Nurkkala
2009-10-08 13:17 ` Eduardo Valentin
@ 2009-10-08 13:40 ` Mark Brown
2009-10-08 15:44 ` ext-Eero.Nurkkala
1 sibling, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:40 UTC (permalink / raw)
To: Eero Nurkkala
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 03:17:07PM +0300, Eero Nurkkala wrote:
> Will this ever be revisited =) ? If so, I think there's going to be a
> jungle in finding the right spots - you need to remember the bypass
> paths also (bias is not on necessarily).
The bias is always on when any path through the chip is on, this was
fixed in either .31 or .30.
> Also, this is regulator thing
> is highly platform dependent, not aic3x related really at all, so is
> this the correct place... Just a thought, dont take it too seriously ;)
I'm not sure what you mean by this?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework
2009-10-08 11:58 ` [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework Eduardo Valentin
@ 2009-10-08 13:43 ` Mark Brown
2009-10-08 13:56 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:43 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 02:58:57PM +0300, Eduardo Valentin wrote:
> + data->regulator = regulator_get(dev, "vdd");
> + if (IS_ERR(data->regulator)) {
> + dev_info(dev, "Could not get regulator for vdd. "
> + "Executing without regulator.\n");
> + data->regulator = NULL;
> + }
Similar comments to the previous patch apply to this driver - regulator
usage should be unconditional, error messages should not be split over
multiple lines and you should represent all the supplies separately (it
looks like there's both VDD and CPVSS required here, for example) to
avoid future surprises.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 13:38 ` Peter Ujfalusi
@ 2009-10-08 13:53 ` Mark Brown
2009-10-09 6:53 ` Peter Ujfalusi
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 13:53 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 04:38:24PM +0300, Peter Ujfalusi wrote:
> On Thursday 08 October 2009 15:52:13 ext Mark Brown wrote:
> > On Thu, Oct 08, 2009 at 02:58:50PM +0300, Eduardo Valentin wrote:
> > > +struct tpa6130a2_platform_data {
> > > + int (*set_power)(int state);
> > > +};
> > Why is this a callback and not just a GPIO number? That'd seem simpler
> > for users.
> Well, same amount of code, but in different place if the power is enabled
Until someone adds a second board, at which point they need to copy the
code to acquire and release the GPIO.
> through a GPIO. But if the power is controlled via different means (nothing
> comes to mind, but there are exotic systems out there), in this way it is simple
> to handle
I suspect we can deal with that adequately when it crops up, for example
by having the driver set up a default callback function if a GPIO is
specified instead of a callback.
> > > + pdata = (struct tpa6130a2_platform_data *)client->dev.platform_data;
> > > + /* Set default register values */
> > > + data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
> > > + TPA6130A2_HP_EN_R |
> > > + TPA6130A2_HP_EN_L;
> > This looks like you could implement stereo paths with individual power
> > control?
> Can we put something in between DAPM_OUTPUT and DAPM_HP to handle the stereo
> path correctly?
Yes.
> We could have two paths from codec to the "TPA6130A2 Headphone", which is needed
> to actually control the power of the amplifier.
Or make "TPA6130A2 Headphone" be a SND_SOC_DAPM_SUPPLY() connected to
the individual channels for the headphone outputs, which should do the
right thing.
> At the end we are not really gaining much, but one more level of switch on the
> path.
> We could have simple mute alsa controls in tpa6130a2_controls for the amplifier
> itself...
It'd mean that mono outputs would only need to enable one of the
channels. Depending on the hardware feeding the amp this may behave
better - there may be some noise or leakage on the idle channel which
it'd be better to avoid amplifying - and it should certainly use a
little less power.
> > > + err = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
> > > + TPA6130A2_VERSION_MASK;
> > > + if ((err != 1) && (err != 2)) {
> > > + dev_err(dev, "Unexpected headphone amplifier chip version "
> > > + "of 0x%02x, was expecting 0x01 or 0x02\n", err);
> > > + err = -ENODEV;
> > This seems a bit excessive - is it really likely that the register map
> > would be changed incompatibly in a future version?
> Hmm, we have only seen these versions of the chip, and we know that the driver
> works with these. Also we don't have any information on different versions, but
> I would think that the register map is not changing (the reset values for some
> registers are different)
It's fairly common to see some incompatible changes in early silicon
revisions but once things get properly launched it's fairly unusual.
I'd be more inclined to print a warning here rather than fail - chances
are that the driver will work fine with any new revisions that are
produced.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework
2009-10-08 13:43 ` Mark Brown
@ 2009-10-08 13:56 ` Eduardo Valentin
2009-10-08 14:41 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-08 13:56 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, Oct 08, 2009 at 03:43:33PM +0200, Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:57PM +0300, Eduardo Valentin wrote:
>
> > + data->regulator = regulator_get(dev, "vdd");
> > + if (IS_ERR(data->regulator)) {
> > + dev_info(dev, "Could not get regulator for vdd. "
> > + "Executing without regulator.\n");
> > + data->regulator = NULL;
> > + }
>
> Similar comments to the previous patch apply to this driver - regulator
> usage should be unconditional, error messages should not be split over
> multiple lines and you should represent all the supplies separately (it
> looks like there's both VDD and CPVSS required here, for example) to
> avoid future surprises.
Yeah. The idea here was to keep driver running even if regulators
are not properly set in board files. Maybe those in which the regulator
is always on. That's why I wrote it with "nicely" message.
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework
2009-10-08 13:56 ` Eduardo Valentin
@ 2009-10-08 14:41 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-08 14:41 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 04:56:28PM +0300, Eduardo Valentin wrote:
> On Thu, Oct 08, 2009 at 03:43:33PM +0200, Mark Brown wrote:
> > Similar comments to the previous patch apply to this driver - regulator
> > usage should be unconditional, error messages should not be split over
> > multiple lines and you should represent all the supplies separately (it
> > looks like there's both VDD and CPVSS required here, for example) to
> > avoid future surprises.
> Yeah. The idea here was to keep driver running even if regulators
> are not properly set in board files. Maybe those in which the regulator
> is always on. That's why I wrote it with "nicely" message.
The issue is that this doesn't actually end up increasing the system
robustness since in some systems the regulator control will be required
and the failures can be non-obvious, such as having a shared regulator
powered off at run time due to other system activity. A misconfigured
regulator supply that stops probe is relatively easy to diagnose and fix
compared to potential silent interactions with other subsystems.
It's simple enough to set up a fixed voltage regulator in the board for
any supplies that don't have soft regulators.
^ permalink raw reply [flat|nested] 58+ messages in thread
* RE: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 13:40 ` Mark Brown
@ 2009-10-08 15:44 ` ext-Eero.Nurkkala
2009-10-08 16:01 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: ext-Eero.Nurkkala @ 2009-10-08 15:44 UTC (permalink / raw)
To: broonie
Cc: eduardo.valentin, tony, peter.ujfalusi, jhnikula, linux-omap,
alsa-devel
Mark Brown wrote:
>> Will this ever be revisited =) ? If so, I think there's going to be a
>> jungle in finding the right spots - you need to remember the bypass
>> paths also (bias is not on necessarily).
>
> The bias is always on when any path through the chip is on, this was
> fixed in either .31 or .30.
Good! Thanks for the update.
>> Also, this is regulator thing
>> is highly platform dependent, not aic3x related really at all, so is
>> this the correct place... Just a thought, dont take it too seriously ;)
>
> I'm not sure what you mean by this?
You may power the aic3x from a fixed source, or from multiple sources, with
and without any regulator in between. It's up to the HW and HW design.
Moreover, you don't _power off_ (turn the regulator off) the analog voltages
of aic3x; things won't work. So it's not like a switch everybody may use. Or
nothing prevent you from experiencing that...
- EEro
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 15:44 ` ext-Eero.Nurkkala
@ 2009-10-08 16:01 ` Mark Brown
2009-10-09 4:28 ` Eero Nurkkala
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-08 16:01 UTC (permalink / raw)
To: <ext-Eero.Nurkkala@nokia.com>
Cc: <eduardo.valentin@nokia.com>, <tony@atomide.com>,
<peter.ujfalusi@nokia.com>, <jhnikula@gmail.com>,
<linux-omap@vger.kernel.org>,
<alsa-devel@vger.kernel.org>
On 8 Oct 2009, at 16:44, <ext-Eero.Nurkkala@nokia.com> wrote:
> Mark Brown wrote:
>>
>>> Also, this is regulator
>>> thing
>>> is highly platform dependent, not aic3x related really at all, so is
>>> this the correct place... Just a thought, dont take it too
>>> seriously ;)
>>
>> I'm not sure what you mean by this?
>
> You may power the aic3x from a fixed source, or from multiple
> sources, with
> and without any regulator in between. It's up to the HW and HW design.
The regulator API can cope with all this pretty transparently - if
multiple supplies come from the same regulator the API will hide that
from the consumer. There is a fixed voltage regulator driver which can
be used to represent supplies with no soft control.
> Moreover, you don't _power off_ (turn the regulator off) the analog
> voltages
> of aic3x; things won't work. So it's not like a switch everybody may
> use. Or
> nothing prevent you from experiencing that...
I'd expect the usage would be that after the audio subsystem has been
idle for some configurable period of time the core would bring the
audio subsystem down to bias off, at which point supplies could also
be switched off.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-08 16:01 ` Mark Brown
@ 2009-10-09 4:28 ` Eero Nurkkala
2009-10-09 10:19 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-09 4:28 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), <tony@atomide.com>,
Ujfalusi Peter (Nokia-D/Tampere), <jhnikula@gmail.com>,
<linux-omap@vger.kernel.org>,
<alsa-devel@vger.kernel.org>
On Thu, 2009-10-08 at 18:01 +0200, ext Mark Brown wrote:
> On 8 Oct 2009, at 16:44, <ext-Eero.Nurkkala@nokia.com> wrote:
>
> > Mark Brown wrote:
> >>
> >>> Also, this is regulator
> >>> thing
> >>> is highly platform dependent, not aic3x related really at all, so is
> >>> this the correct place... Just a thought, dont take it too
> >>> seriously ;)
> >>
> >> I'm not sure what you mean by this?
> >
> > You may power the aic3x from a fixed source, or from multiple
> > sources, with
> > and without any regulator in between. It's up to the HW and HW design.
>
> The regulator API can cope with all this pretty transparently - if
> multiple supplies come from the same regulator the API will hide that
> from the consumer. There is a fixed voltage regulator driver which can
> be used to represent supplies with no soft control.
>
> > Moreover, you don't _power off_ (turn the regulator off) the analog
> > voltages
> > of aic3x; things won't work. So it's not like a switch everybody may
> > use. Or
> > nothing prevent you from experiencing that...
>
> I'd expect the usage would be that after the audio subsystem has been
> idle for some configurable period of time the core would bring the
> audio subsystem down to bias off, at which point supplies could also
> be switched off.
Right. That would also sound like the RST line also needs also be
asserted, and then rewriting all register contents upon wakeup? And also
redirecting all i2c traffic to the cache instead of any real i2c writes
(meanwhile the device is shut down)? Like in tpa6130?
- Eero
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-08 13:17 ` Mark Brown
2009-10-08 13:23 ` Eduardo Valentin
@ 2009-10-09 5:09 ` Eero Nurkkala
2009-10-09 10:44 ` [alsa-devel] " Mark Brown
1 sibling, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-09 5:09 UTC (permalink / raw)
To: alsa-devel
Cc: ext Tony Lindgren, Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Thu, 2009-10-08 at 15:17 +0200, ext Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:52PM +0300, Eduardo Valentin wrote:
>
> > +static const struct attribute *sidetone_attrs[] = {
> > + &dev_attr_st_enable.attr,
> > + &dev_attr_st_taps.attr,
> > + &dev_attr_st_ch0gain.attr,
> > + &dev_attr_st_ch1gain.attr,
> > + NULL,
> > +};
>
> This stuff, particularly the enable, probably wants to be pushed out via
> an ALSA API rather than via random sysfs stuff. It'd be better to
> publish a control API here and then use that from within ALSA.
Hmm. What would be the way to transfer 128 x s16 words; is there an ALSA
control for something like that already ? IIRC correctly, the max
bytesize per control is (or used to be) something like 256 bytes or so.
So that gets right at it. (that's the sidetone 128 tap FIR in question)
- Eero
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-08 13:11 ` Mark Brown
@ 2009-10-09 5:44 ` Jarkko Nikula
2009-10-09 6:37 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Jarkko Nikula @ 2009-10-09 5:44 UTC (permalink / raw)
To: Mark Brown
Cc: Eduardo Valentin, ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Thu, 8 Oct 2009 14:11:16 +0100
Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:
> What is an "AIC34b_dummy (block B)"? You probably want to split it out
> into a separate patch.
>
I think this is the reason why Eduardo mentioned my name in the commit
log :-)
Yep, dummy driver is for block B of AIC34 which is basically dual AIC33
in a same package.
> > + * TODO:
> > + * - Get rid of this driver, at least when ASoC v2 is merged and when
> > + * we can support multiple codec instances in tlv320aic3x.c driver.
> > + * This driver is hacked only for Nokia RX51 HW.
>
> Could you please explain what the issue here is? A description of the
> hardware would go a long way here.
>
Eduardo, please correct me if I remember wrong but block B of AIC34 is
not used as an codec as such but more like an amplifier and analogic
mixer with digital parts unused. So with this dummy driver the HW
features were easier to support than to develop multiple intance
support for codec drivers.
--
Jarkko
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-09 5:44 ` Jarkko Nikula
@ 2009-10-09 6:37 ` Eduardo Valentin
2009-10-09 12:19 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-09 6:37 UTC (permalink / raw)
To: ext Jarkko Nikula
Cc: Mark Brown, Valentin Eduardo (Nokia-D/Helsinki),
ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Fri, Oct 09, 2009 at 07:44:00AM +0200, Jarkko Nikula wrote:
> On Thu, 8 Oct 2009 14:11:16 +0100
> Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:
>
> > What is an "AIC34b_dummy (block B)"? You probably want to split it out
> > into a separate patch.
> >
> I think this is the reason why Eduardo mentioned my name in the commit
> log :-)
Yeah, I mentioned Jarkko because he was the person who initially wrote those drivers :-).
But I can split then if you prefer. No problem.
>
> Yep, dummy driver is for block B of AIC34 which is basically dual AIC33
> in a same package.
Yes. This is correct.
>
> > > + * TODO:
> > > + * - Get rid of this driver, at least when ASoC v2 is merged and when
> > > + * we can support multiple codec instances in tlv320aic3x.c driver.
> > > + * This driver is hacked only for Nokia RX51 HW.
> >
> > Could you please explain what the issue here is? A description of the
> > hardware would go a long way here.
> >
> Eduardo, please correct me if I remember wrong but block B of AIC34 is
> not used as an codec as such but more like an amplifier and analogic
> mixer with digital parts unused. So with this dummy driver the HW
> features were easier to support than to develop multiple intance
> support for codec drivers.
Yes. This is also correct. It is more like an amplifier / mixer.
I think that's why you named it dummy :-).
But I think I should add this info as a comment inside the code.
>
>
> --
> Jarkko
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-08 13:21 ` Mark Brown
@ 2009-10-09 6:45 ` Eduardo Valentin
2009-10-09 11:03 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-09 6:45 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 03:21:10PM +0200, Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:54PM +0300, Eduardo Valentin wrote:
> > From: Eduardo Valentin <eduardo.valentin@nokia.com>
>
> > Use separated supplies for vaux3 and vmmc2.
>
> > Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
>
> > +static struct regulator_consumer_supply rx51_vaux3_supply = {
> > + .supply = "vmmc",
> > +};
> > +
>
> I'd expect all these supplies to have devices associated with them (see
> below)...
>
> > static struct regulator_consumer_supply rx51_vmmc2_supply = {
> > .supply = "vmmc",
> > };
> > @@ -184,7 +188,7 @@ static struct regulator_init_data rx51_vaux3_mmc = {
> > | REGULATOR_CHANGE_STATUS,
> > },
> > .num_consumer_supplies = 1,
> > - .consumer_supplies = &rx51_vmmc2_supply,
> > + .consumer_supplies = &rx51_vaux3_supply,
> > };
>
> I may have missed it but I don't see rx51_vmmc2_supply added back
> anywhere in the patch?
yes. That's because this patch is just to split then. As you can see
in current code, this structure, rx51_vmmc2_supply, is actually used
by rx51_vaux3_mmc and rx51_vmmc2. So the idea is to have separated
supplies for each one. This patch just splits then. Patch 0006 of this
series adds usage of rx51_vmmc2_supply.
>
> > static struct regulator_init_data rx51_vaux4 = {
> > @@ -266,7 +270,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
> > /* set up MMC adapters, linking their regulators to them */
> > twl4030_mmc_init(mmc);
> > rx51_vmmc1_supply.dev = mmc[0].dev;
> > - rx51_vmmc2_supply.dev = mmc[1].dev;
> > + rx51_vaux3_supply.dev = mmc[1].dev;
>
> ...using dev_name rather than dev should avoid the need to do this at
> runtime.
I see your point. As mentioned above, this patch is just a split.
I just added rx51_vaux3_supply to be owned by rx51_vaux3_mmc. And
let the code behavior as it was before.
Maybe your proposal must be sent into a separated patch/patch series (?).
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-08 13:53 ` Mark Brown
@ 2009-10-09 6:53 ` Peter Ujfalusi
2009-10-09 10:36 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Peter Ujfalusi @ 2009-10-09 6:53 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thursday 08 October 2009 16:53:42 ext Mark Brown wrote:
> On Thu, Oct 08, 2009 at 04:38:24PM +0300, Peter Ujfalusi wrote:
> > On Thursday 08 October 2009 15:52:13 ext Mark Brown wrote:
> > > On Thu, Oct 08, 2009 at 02:58:50PM +0300, Eduardo Valentin wrote:
> > > > +struct tpa6130a2_platform_data {
> > > > + int (*set_power)(int state);
> > > > +};
> > >
> > > Why is this a callback and not just a GPIO number? That'd seem simpler
> > > for users.
> >
> > Well, same amount of code, but in different place if the power is enabled
>
> Until someone adds a second board, at which point they need to copy the
> code to acquire and release the GPIO.
>
> > through a GPIO. But if the power is controlled via different means
> > (nothing comes to mind, but there are exotic systems out there), in this
> > way it is simple to handle
>
> I suspect we can deal with that adequately when it crops up, for example
> by having the driver set up a default callback function if a GPIO is
> specified instead of a callback.
Good point.
I'll replace the .set_power with power_gpio.
>
> > > > + pdata = (struct tpa6130a2_platform_data
> > > > *)client->dev.platform_data; + /* Set default register values */
> > > > + data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS |
> > > > + TPA6130A2_HP_EN_R |
> > > > + TPA6130A2_HP_EN_L;
> > >
> > > This looks like you could implement stereo paths with individual power
> > > control?
> >
> > Can we put something in between DAPM_OUTPUT and DAPM_HP to handle the
> > stereo path correctly?
>
> Yes.
Great. I can add one SND_SOC_DAPM_PGA_E per channel, which enables/disables the
channel.
Adding a widget with actual alsa control seams to be problematic, since those
are working with the codec's registers, so adding such a widget would require to
implement a new set of .info .get and .set functions for the TPA alone.
>
> > We could have two paths from codec to the "TPA6130A2 Headphone", which is
> > needed to actually control the power of the amplifier.
>
> Or make "TPA6130A2 Headphone" be a SND_SOC_DAPM_SUPPLY() connected to
> the individual channels for the headphone outputs, which should do the
> right thing.
I see, using the event/event_flags with the DAPM_SUPPLY should do it.
So is it OK if I modify the tpa6130a2 DAPM path to be like this:
PGA_E("TPA6130A2 Left") -> SUPPLY("TPA6130A2 power") -> HP("TPA6130A2
Headphone")
PGA_E("TPA6130A2 Right") -> SUPPLY("TPA6130A2 power") -> HP("TPA6130A2
Headphone")
Or should I add individual HP for the two channels:
HP("TPA6130A2 Headphone Left")
HP("TPA6130A2 Headphone Right")
Than in machine driver just connect (for example rx51):
{"TPA6130A2 Left", NULL, "LLOUT"},
{"TPA6130A2 Right", NULL, "RLOUT"},
>
> > At the end we are not really gaining much, but one more level of switch
> > on the path.
> > We could have simple mute alsa controls in tpa6130a2_controls for the
> > amplifier itself...
>
> It'd mean that mono outputs would only need to enable one of the
> channels. Depending on the hardware feeding the amp this may behave
> better - there may be some noise or leakage on the idle channel which
> it'd be better to avoid amplifying - and it should certainly use a
> little less power.
OK, Does my proposal above feasible?
>
> > > > + err = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
> > > > + TPA6130A2_VERSION_MASK;
> > > > + if ((err != 1) && (err != 2)) {
> > > > + dev_err(dev, "Unexpected headphone amplifier chip version "
> > > > + "of 0x%02x, was expecting 0x01 or 0x02\n", err);
> > > > + err = -ENODEV;
> > >
> > > This seems a bit excessive - is it really likely that the register map
> > > would be changed incompatibly in a future version?
> >
> > Hmm, we have only seen these versions of the chip, and we know that the
> > driver works with these. Also we don't have any information on different
> > versions, but I would think that the register map is not changing (the
> > reset values for some registers are different)
>
> It's fairly common to see some incompatible changes in early silicon
> revisions but once things get properly launched it's fairly unusual.
> I'd be more inclined to print a warning here rather than fail - chances
> are that the driver will work fine with any new revisions that are
> produced.
Right, going to be warning (with text change).
>
Thanks,
Péter
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac
2009-10-09 4:28 ` Eero Nurkkala
@ 2009-10-09 10:19 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-09 10:19 UTC (permalink / raw)
To: Eero Nurkkala
Cc: Valentin Eduardo (Nokia-D/Helsinki), <tony@atomide.com>,
Ujfalusi Peter (Nokia-D/Tampere), <jhnikula@gmail.com>,
<linux-omap@vger.kernel.org>,
<alsa-devel@vger.kernel.org>
On Fri, Oct 09, 2009 at 07:28:03AM +0300, Eero Nurkkala wrote:
> On Thu, 2009-10-08 at 18:01 +0200, ext Mark Brown wrote:
> > I'd expect the usage would be that after the audio subsystem has been
> > idle for some configurable period of time the core would bring the
> > audio subsystem down to bias off, at which point supplies could also
> > be switched off.
> Right. That would also sound like the RST line also needs also be
> asserted, and then rewriting all register contents upon wakeup? And also
> redirecting all i2c traffic to the cache instead of any real i2c writes
> (meanwhile the device is shut down)? Like in tpa6130?
Yes. I'd expect that if this is being implemented there'll be some
degree of assistance from the core for some of this.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/8] ASoC: TPA6130A2 amplifier driver
2009-10-09 6:53 ` Peter Ujfalusi
@ 2009-10-09 10:36 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-09 10:36 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: alsa-devel, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Fri, Oct 09, 2009 at 09:53:21AM +0300, Peter Ujfalusi wrote:
> On Thursday 08 October 2009 16:53:42 ext Mark Brown wrote:
> Adding a widget with actual alsa control seams to be problematic, since those
> are working with the codec's registers, so adding such a widget would require to
> implement a new set of .info .get and .set functions for the TPA alone.
Yes, chips like this are the major reason for needing to support having
more than one CODEC device in the core.
> Or should I add individual HP for the two channels:
> HP("TPA6130A2 Headphone Left")
> HP("TPA6130A2 Headphone Right")
> Than in machine driver just connect (for example rx51):
> {"TPA6130A2 Left", NULL, "LLOUT"},
> {"TPA6130A2 Right", NULL, "RLOUT"},
That's what I was thinking of, yes.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [alsa-devel] [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-09 5:09 ` Eero Nurkkala
@ 2009-10-09 10:44 ` Mark Brown
2009-10-12 6:17 ` Eero Nurkkala
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-09 10:44 UTC (permalink / raw)
To: Eero Nurkkala
Cc: alsa-devel, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Fri, Oct 09, 2009 at 08:09:27AM +0300, Eero Nurkkala wrote:
> On Thu, 2009-10-08 at 15:17 +0200, ext Mark Brown wrote:
> > This stuff, particularly the enable, probably wants to be pushed out via
> > an ALSA API rather than via random sysfs stuff. It'd be better to
> > publish a control API here and then use that from within ALSA.
> Hmm. What would be the way to transfer 128 x s16 words; is there an ALSA
> control for something like that already ? IIRC correctly, the max
> bytesize per control is (or used to be) something like 256 bytes or so.
> So that gets right at it. (that's the sidetone 128 tap FIR in question)
For things like the FIR you probably don't want to expose the entire
table directly to user space. Depending on the typical usage it may be
that platform data is the appropriate mechanism, with some simpler thing
presented to applications allowing switching between a limited set of
settings. sysfs may end up being the best option for the FIR setup.
My main concern here is that the control goes into the ALSA domain so
that the audio drivers know what's going on with these sidetone paths,
particular in terms of the routing.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-09 6:45 ` Eduardo Valentin
@ 2009-10-09 11:03 ` Mark Brown
2009-10-12 8:08 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-09 11:03 UTC (permalink / raw)
To: Eduardo Valentin
Cc: alsa-devel, ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Fri, Oct 09, 2009 at 09:45:29AM +0300, Eduardo Valentin wrote:
> On Thu, Oct 08, 2009 at 03:21:10PM +0200, Mark Brown wrote:
> > On Thu, Oct 08, 2009 at 02:58:54PM +0300, Eduardo Valentin wrote:
> > I may have missed it but I don't see rx51_vmmc2_supply added back
> > anywhere in the patch?
> yes. That's because this patch is just to split then. As you can see
> in current code, this structure, rx51_vmmc2_supply, is actually used
> by rx51_vaux3_mmc and rx51_vmmc2. So the idea is to have separated
> supplies for each one. This patch just splits then. Patch 0006 of this
> series adds usage of rx51_vmmc2_supply.
Might be an idea to change the description to something like "add a
separate structure for...", it wasn't 100% clear what was going on
(probably because the diff doesn't include sufficient context to make it
clear).
> > ...using dev_name rather than dev should avoid the need to do this at
> > runtime.
> I see your point. As mentioned above, this patch is just a split.
> I just added rx51_vaux3_supply to be owned by rx51_vaux3_mmc. And
> let the code behavior as it was before.
> Maybe your proposal must be sent into a separated patch/patch series (?).
Yes, it's definately a separate patch - might be good to put it into the
series before this one.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver
2009-10-09 6:37 ` Eduardo Valentin
@ 2009-10-09 12:19 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-09 12:19 UTC (permalink / raw)
To: Eduardo Valentin
Cc: alsa-devel, ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Fri, Oct 09, 2009 at 09:37:20AM +0300, Eduardo Valentin wrote:
> On Fri, Oct 09, 2009 at 07:44:00AM +0200, Jarkko Nikula wrote:
> > Yep, dummy driver is for block B of AIC34 which is basically dual AIC33
> > in a same package.
> Yes. This is correct.
So to software it just looks like two devices at separate I2C addresses
so once multi CODEC support is present there will be no need to have
specific support for it at all?
> > Eduardo, please correct me if I remember wrong but block B of AIC34 is
> > not used as an codec as such but more like an amplifier and analogic
> > mixer with digital parts unused. So with this dummy driver the HW
> > features were easier to support than to develop multiple intance
> > support for codec drivers.
> Yes. This is also correct. It is more like an amplifier / mixer.
> I think that's why you named it dummy :-).
> But I think I should add this info as a comment inside the code.
Some words or ASCII art in the machine driver would help a lot, I think.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-09 10:44 ` [alsa-devel] " Mark Brown
@ 2009-10-12 6:17 ` Eero Nurkkala
2009-10-12 9:12 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-12 6:17 UTC (permalink / raw)
To: ext Mark Brown
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Fri, 2009-10-09 at 12:44 +0200, ext Mark Brown wrote:
> On Fri, Oct 09, 2009 at 08:09:27AM +0300, Eero Nurkkala wrote:
> > On Thu, 2009-10-08 at 15:17 +0200, ext Mark Brown wrote:
>
> > > This stuff, particularly the enable, probably wants to be pushed out via
> > > an ALSA API rather than via random sysfs stuff. It'd be better to
> > > publish a control API here and then use that from within ALSA.
>
> > Hmm. What would be the way to transfer 128 x s16 words; is there an ALSA
> > control for something like that already ? IIRC correctly, the max
> > bytesize per control is (or used to be) something like 256 bytes or so.
> > So that gets right at it. (that's the sidetone 128 tap FIR in question)
>
> For things like the FIR you probably don't want to expose the entire
> table directly to user space. Depending on the typical usage it may be
> that platform data is the appropriate mechanism, with some simpler thing
> presented to applications allowing switching between a limited set of
> settings. sysfs may end up being the best option for the FIR setup.
>
> My main concern here is that the control goes into the ALSA domain so
> that the audio drivers know what's going on with these sidetone paths,
> particular in terms of the routing.
Indeed. If I'm not totally wrong, the sidetone engineering is such,
that the sinetones should be of constant volume (this may depend on
the usecase). So, let's say we have the TPA6130 codec's volume used
along with a sidetone:
1. A change in TPA6130 volume should lead to a change in
the sidetone's gain (if it's enabled). The change of gain
is directly related to the change in the TPA's volume.
That said, if the sidetone's gain is of the domain [-2,2], how
could it translate into the TPA's nonlinear dB domain?. If
that may be resolved somehow feasibly, this sounds like a very
useful relation? Ideas?
This is all assumed that the FIR itself doesn't cause any gains
to the signal level at the desired frequency domain(s).
- Eero
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-09 11:03 ` Mark Brown
@ 2009-10-12 8:08 ` Eduardo Valentin
2009-10-12 9:18 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-12 8:08 UTC (permalink / raw)
To: ext Mark Brown
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
Hello,
On Fri, Oct 09, 2009 at 01:03:47PM +0200, Mark Brown wrote:
> On Fri, Oct 09, 2009 at 09:45:29AM +0300, Eduardo Valentin wrote:
> > On Thu, Oct 08, 2009 at 03:21:10PM +0200, Mark Brown wrote:
> > > On Thu, Oct 08, 2009 at 02:58:54PM +0300, Eduardo Valentin wrote:
>
> > > I may have missed it but I don't see rx51_vmmc2_supply added back
> > > anywhere in the patch?
>
> > yes. That's because this patch is just to split then. As you can see
> > in current code, this structure, rx51_vmmc2_supply, is actually used
> > by rx51_vaux3_mmc and rx51_vmmc2. So the idea is to have separated
> > supplies for each one. This patch just splits then. Patch 0006 of this
> > series adds usage of rx51_vmmc2_supply.
>
> Might be an idea to change the description to something like "add a
> separate structure for...", it wasn't 100% clear what was going on
> (probably because the diff doesn't include sufficient context to make it
> clear).
>
> > > ...using dev_name rather than dev should avoid the need to do this at
> > > runtime.
I'm afraid using dev_name is not that easy. The mmc driver generates device
name at runtime. That's why this board file setups .dev at runtime as well.
rx51_twlgpio_setup -> twl4030_mmc_init -> omap2_init_mmc
So, changing this supply to something static using .dev_name it is not
possible with current code. That would need refactoring the whole mmc and
hsmmc setup. And the device naming procedure is dependent on cpu as well.
Check arch/arm/mach-omap2/device.c:omap2_init_mmc.
>
> > I see your point. As mentioned above, this patch is just a split.
> > I just added rx51_vaux3_supply to be owned by rx51_vaux3_mmc. And
> > let the code behavior as it was before.
>
> > Maybe your proposal must be sent into a separated patch/patch series (?).
>
> Yes, it's definately a separate patch - might be good to put it into the
> series before this one.
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-08 13:26 ` Mark Brown
@ 2009-10-12 9:04 ` Eduardo Valentin
2009-10-12 9:21 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-12 9:04 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Thu, Oct 08, 2009 at 03:26:19PM +0200, Mark Brown wrote:
> On Thu, Oct 08, 2009 at 02:58:55PM +0300, Eduardo Valentin wrote:
>
> > +static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
> > + REGULATOR_SUPPLY("avdd_dac", "2-0018"), /* tlv320aic3x */
> > + REGULATOR_SUPPLY("vdd", "2-0060"), /* tpa6130a2*/
> > };
>
> avdd_dac is the only supply added for the tlv320aic3x but, for example,
> the tlv320aic34 has something like 8 supplies from a quick scan of the
> datasheet. It'd be better to set up all of the supplies, even if only
> with a fixed voltage regulator supplying them, since when regulator
> support is added to the CODEC driver it should be requesting all the
> supplies it needs and therefore fail to instatiate if some are missing.
Right. Should we add 4 instances of drvdd and 2 of iovdd? So, naming those would be like:
REGULATOR_SUPPLY("drvdd0", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd1", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd2", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd3", "2-0018"), /* tlv320aic3x */
or even better:
REGULATOR_SUPPLY("drvdd_b4", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd_a4", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd_b9", "2-0018"), /* tlv320aic3x */
REGULATOR_SUPPLY("drvdd_a9", "2-0018"), /* tlv320aic3x */
what do you think?
BR
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-12 6:17 ` Eero Nurkkala
@ 2009-10-12 9:12 ` Mark Brown
2009-10-12 9:28 ` Eero Nurkkala
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-12 9:12 UTC (permalink / raw)
To: Eero Nurkkala
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Mon, Oct 12, 2009 at 09:17:41AM +0300, Eero Nurkkala wrote:
> Indeed. If I'm not totally wrong, the sidetone engineering is such,
> that the sinetones should be of constant volume (this may depend on
> the usecase). So, let's say we have the TPA6130 codec's volume used
> along with a sidetone:
> 1. A change in TPA6130 volume should lead to a change in
> the sidetone's gain (if it's enabled). The change of gain
> is directly related to the change in the TPA's volume.
Could you go into more detail about why there should be a relationship
between the two gains?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-12 8:08 ` Eduardo Valentin
@ 2009-10-12 9:18 ` Mark Brown
2009-10-14 17:15 ` Tony Lindgren
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-12 9:18 UTC (permalink / raw)
To: Eduardo Valentin
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Mon, Oct 12, 2009 at 11:08:58AM +0300, Eduardo Valentin wrote:
> I'm afraid using dev_name is not that easy. The mmc driver generates device
> name at runtime. That's why this board file setups .dev at runtime as well.
> rx51_twlgpio_setup -> twl4030_mmc_init -> omap2_init_mmc
> So, changing this supply to something static using .dev_name it is not
> possible with current code. That would need refactoring the whole mmc and
> hsmmc setup. And the device naming procedure is dependent on cpu as well.
> Check arch/arm/mach-omap2/device.c:omap2_init_mmc.
Oh, dear - that sounds broken for hardware that's fixed on the board.
That said, the code there looks like it's supposed to come out with the
same answer each time it's run? How does this work with the clock API?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-12 9:04 ` Eduardo Valentin
@ 2009-10-12 9:21 ` Mark Brown
2009-10-19 9:13 ` Eduardo Valentin
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-12 9:21 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Mon, Oct 12, 2009 at 12:04:55PM +0300, Eduardo Valentin wrote:
> Right. Should we add 4 instances of drvdd and 2 of iovdd? So, naming those would be like:
No, if there's multiple pins for the supply then there's no need to
represent those individually - they're required to be wired together in
hardware.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-12 9:12 ` Mark Brown
@ 2009-10-12 9:28 ` Eero Nurkkala
2009-10-12 9:32 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-12 9:28 UTC (permalink / raw)
To: ext Mark Brown
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Mon, 2009-10-12 at 11:12 +0200, ext Mark Brown wrote:
> On Mon, Oct 12, 2009 at 09:17:41AM +0300, Eero Nurkkala wrote:
>
> > Indeed. If I'm not totally wrong, the sidetone engineering is such,
> > that the sinetones should be of constant volume (this may depend on
> > the usecase). So, let's say we have the TPA6130 codec's volume used
> > along with a sidetone:
>
> > 1. A change in TPA6130 volume should lead to a change in
> > the sidetone's gain (if it's enabled). The change of gain
> > is directly related to the change in the TPA's volume.
>
> Could you go into more detail about why there should be a relationship
> between the two gains?
As mentioned, in some (or most) cases the absolute sinetone level (dB)
is expected constant. Even a volume change should not effect the
sidetone level. Thus, if there's a change in volume, the sidetone gains
should be readjusted. If that can happen automatically, that would
be just nice =)
I don't know whether there "should" be a relationship, but if there was,
that'd be very useful. But it gets complicated as there may be
several volume controls in the path. Anyway, that was just an idea that
may just as well be ignored.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-12 9:28 ` Eero Nurkkala
@ 2009-10-12 9:32 ` Mark Brown
2009-10-12 10:28 ` Eero Nurkkala
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-12 9:32 UTC (permalink / raw)
To: Eero Nurkkala
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Mon, Oct 12, 2009 at 12:28:25PM +0300, Eero Nurkkala wrote:
> As mentioned, in some (or most) cases the absolute sinetone level (dB)
> is expected constant. Even a volume change should not effect the
> sidetone level. Thus, if there's a change in volume, the sidetone gains
> should be readjusted. If that can happen automatically, that would
> be just nice =)
That's what you said, but could you please go into a bit more detail
about why you beleive that this should be the case? Is there some
hardware limitation here?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-12 9:32 ` Mark Brown
@ 2009-10-12 10:28 ` Eero Nurkkala
2009-10-12 10:33 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eero Nurkkala @ 2009-10-12 10:28 UTC (permalink / raw)
To: ext Mark Brown
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Mon, 2009-10-12 at 11:32 +0200, ext Mark Brown wrote:
> On Mon, Oct 12, 2009 at 12:28:25PM +0300, Eero Nurkkala wrote:
>
> > As mentioned, in some (or most) cases the absolute sinetone level (dB)
> > is expected constant. Even a volume change should not effect the
> > sidetone level. Thus, if there's a change in volume, the sidetone gains
> > should be readjusted. If that can happen automatically, that would
> > be just nice =)
>
> That's what you said, but could you please go into a bit more detail
> about why you beleive that this should be the case? Is there some
> hardware limitation here?
No HW limits here... it's all about the hmm, "friendliness" of
sidetones.
"The more intense the side-tone, the less intensely the speaker talks."
(June 12, 1948) [REF]
So changing the headset volume should not make the speaker talk
more/less intensely? Of course it all depends... this is just one
aspect to this.
[REF]
LOUDNESS OF SPEAKING: THE EFFECT OF THE INTENSITY
OF SIDE-TONE UPON THE INTENSITY OF THE SPEAKER
Kenyon College
Acoustic Laboratory
Gambier, Ohio
School of Aviation Medicine and Research
N.A.S., Pensacola, Florida
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature
2009-10-12 10:28 ` Eero Nurkkala
@ 2009-10-12 10:33 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-12 10:33 UTC (permalink / raw)
To: Eero Nurkkala
Cc: alsa-devel@alsa-project.org, ext Tony Lindgren,
Valentin Eduardo (Nokia-D/Helsinki),
Ujfalusi Peter (Nokia-D/Tampere), Linux-OMAP, ALSA-Devel
On Mon, Oct 12, 2009 at 01:28:48PM +0300, Eero Nurkkala wrote:
> No HW limits here... it's all about the hmm, "friendliness" of
> sidetones.
This is an application level issue. We've no way of determining within
the drivers if a given path is actually being used as a real sidetone or
if it is being used for some other purpose. As far as the drivers are
concerned these are unrelated controls.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-12 9:18 ` Mark Brown
@ 2009-10-14 17:15 ` Tony Lindgren
2009-10-15 9:01 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Tony Lindgren @ 2009-10-14 17:15 UTC (permalink / raw)
To: Mark Brown
Cc: alsa-devel@alsa-project.org, Eduardo Valentin,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
* Mark Brown <broonie@opensource.wolfsonmicro.com> [091012 02:18]:
> On Mon, Oct 12, 2009 at 11:08:58AM +0300, Eduardo Valentin wrote:
>
> > I'm afraid using dev_name is not that easy. The mmc driver generates device
> > name at runtime. That's why this board file setups .dev at runtime as well.
>
> > rx51_twlgpio_setup -> twl4030_mmc_init -> omap2_init_mmc
>
> > So, changing this supply to something static using .dev_name it is not
> > possible with current code. That would need refactoring the whole mmc and
> > hsmmc setup. And the device naming procedure is dependent on cpu as well.
> > Check arch/arm/mach-omap2/device.c:omap2_init_mmc.
>
> Oh, dear - that sounds broken for hardware that's fixed on the board.
> That said, the code there looks like it's supposed to come out with the
> same answer each time it's run? How does this work with the clock API?
The clocks are matched using clkdev. Basically the driver just requests
functional clock (fck) and interface clock (ick):
$ grep mmci arch/arm/*omap*/clock*.c
arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310),
arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
arch/arm/mach-omap1/clock.c: CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX),
arch/arm/mach-omap1/clock.c: CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_243X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_243X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_243X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_243X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
arch/arm/mach-omap2/clock24xx.c: CLK("mmci-omap-hs.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_343X),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_343X),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_343X),
arch/arm/mach-omap2/clock34xx.c: CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_343X),
Regards,
Tony
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-14 17:15 ` Tony Lindgren
@ 2009-10-15 9:01 ` Mark Brown
2009-10-16 16:14 ` Tony Lindgren
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-15 9:01 UTC (permalink / raw)
To: Tony Lindgren
Cc: alsa-devel@alsa-project.org, Eduardo Valentin,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
On Wed, Oct 14, 2009 at 10:15:48AM -0700, Tony Lindgren wrote:
> * Mark Brown <broonie@opensource.wolfsonmicro.com> [091012 02:18]:
> > On Mon, Oct 12, 2009 at 11:08:58AM +0300, Eduardo Valentin wrote:
> > > I'm afraid using dev_name is not that easy. The mmc driver generates device
> > > name at runtime. That's why this board file setups .dev at runtime as well.
...
> > > So, changing this supply to something static using .dev_name it is not
> > > possible with current code. That would need refactoring the whole mmc and
> > > hsmmc setup. And the device naming procedure is dependent on cpu as well.
> > > Check arch/arm/mach-omap2/device.c:omap2_init_mmc.
> > same answer each time it's run? How does this work with the clock API?
> The clocks are matched using clkdev. Basically the driver just requests
> functional clock (fck) and interface clock (ick):
> $ grep mmci arch/arm/*omap*/clock*.c
> arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310),
> arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
So this is using the standard dev_name based clkdev matching which
Eduardo said was impossible for the regulators. Is it just that this
will actually work fine for the regulators or is there some other magic
in the OMAP code that joins things up?
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies
2009-10-15 9:01 ` Mark Brown
@ 2009-10-16 16:14 ` Tony Lindgren
0 siblings, 0 replies; 58+ messages in thread
From: Tony Lindgren @ 2009-10-16 16:14 UTC (permalink / raw)
To: Mark Brown
Cc: alsa-devel@alsa-project.org, Eduardo Valentin,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Linux-OMAP, ALSA-Devel
* Mark Brown <broonie@opensource.wolfsonmicro.com> [091015 02:01]:
> On Wed, Oct 14, 2009 at 10:15:48AM -0700, Tony Lindgren wrote:
> > * Mark Brown <broonie@opensource.wolfsonmicro.com> [091012 02:18]:
> > > On Mon, Oct 12, 2009 at 11:08:58AM +0300, Eduardo Valentin wrote:
>
> > > > I'm afraid using dev_name is not that easy. The mmc driver generates device
> > > > name at runtime. That's why this board file setups .dev at runtime as well.
>
> ...
>
> > > > So, changing this supply to something static using .dev_name it is not
> > > > possible with current code. That would need refactoring the whole mmc and
> > > > hsmmc setup. And the device naming procedure is dependent on cpu as well.
> > > > Check arch/arm/mach-omap2/device.c:omap2_init_mmc.
>
> > > same answer each time it's run? How does this work with the clock API?
>
> > The clocks are matched using clkdev. Basically the driver just requests
> > functional clock (fck) and interface clock (ick):
>
> > $ grep mmci arch/arm/*omap*/clock*.c
> > arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310),
> > arch/arm/mach-omap1/clock.c: CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
>
> So this is using the standard dev_name based clkdev matching which
> Eduardo said was impossible for the regulators. Is it just that this
> will actually work fine for the regulators or is there some other magic
> in the OMAP code that joins things up?
Well the mmc regulators are just passed from board-*.c files to
mmc-twl4030.c which does all the low-level init needed. No other
special magic going on.
Eduardro, care to check the dev_name issue one more time?
Regards,
Tony
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-12 9:21 ` Mark Brown
@ 2009-10-19 9:13 ` Eduardo Valentin
2009-10-19 9:23 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Eduardo Valentin @ 2009-10-19 9:13 UTC (permalink / raw)
To: ext Mark Brown
Cc: Valentin Eduardo (Nokia-D/Helsinki), ext Tony Lindgren,
Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
Hi,
On Mon, Oct 12, 2009 at 11:21:04AM +0200, Mark Brown wrote:
> On Mon, Oct 12, 2009 at 12:04:55PM +0300, Eduardo Valentin wrote:
>
> > Right. Should we add 4 instances of drvdd and 2 of iovdd? So, naming those would be like:
>
> No, if there's multiple pins for the supply then there's no need to
> represent those individually - they're required to be wired together in
> hardware.
Might be a stupid question probably because of my lack of knowledge of regulator framework,
but if the driver code must be written in such a way that it requires all regulators
for its supplies, then what happens with those which are grounded? How do you provide the
regulator_init_data in this case (where the supply is actually grounded) ?
BR,
--
Eduardo Valentin
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-19 9:13 ` Eduardo Valentin
@ 2009-10-19 9:23 ` Mark Brown
2009-10-19 9:24 ` Mark Brown
0 siblings, 1 reply; 58+ messages in thread
From: Mark Brown @ 2009-10-19 9:23 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Mon, Oct 19, 2009 at 12:13:00PM +0300, Eduardo Valentin wrote:
[Please fix your MUA to wrap before 80 columns.]
> Might be a stupid question probably because of my lack of knowledge of
> regulator framework, but if the driver code must be written in such a
> way that it requires all regulators for its supplies, then what
> happens with those which are grounded? How do you provide the
> regulator_init_data in this case (where the supply is actually grounded) ?
That sounds like a fixed voltage regulator. Though for a device where
some of the supplies are optional if the driver needs to know about it
it may make more sense to have the driver know about that and only
request supplies which it will use.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2
2009-10-19 9:23 ` Mark Brown
@ 2009-10-19 9:24 ` Mark Brown
0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2009-10-19 9:24 UTC (permalink / raw)
To: Eduardo Valentin
Cc: ext Tony Lindgren, Ujfalusi Peter (Nokia-D/Tampere),
Nurkkala Eero.An (EXT-Offcode/Oulu), Jarkko Nikula, Linux-OMAP,
ALSA-Devel
On Mon, Oct 19, 2009 at 10:23:32AM +0100, Mark Brown wrote:
> On Mon, Oct 19, 2009 at 12:13:00PM +0300, Eduardo Valentin wrote:
> > Might be a stupid question probably because of my lack of knowledge of
> > regulator framework, but if the driver code must be written in such a
> > way that it requires all regulators for its supplies, then what
> > happens with those which are grounded? How do you provide the
> > regulator_init_data in this case (where the supply is actually grounded) ?
> That sounds like a fixed voltage regulator. Though for a device where
> some of the supplies are optional if the driver needs to know about it
> it may make more sense to have the driver know about that and only
> request supplies which it will use.
...or possibly just handle the error when it fails to obtain them.
^ permalink raw reply [flat|nested] 58+ messages in thread
end of thread, other threads:[~2009-10-19 9:24 UTC | newest]
Thread overview: 58+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-08 11:58 [PATCH 0/8] RX-51 audio drivers Eduardo Valentin
2009-10-08 11:58 ` [PATCH 1/8] ASoC: TPA6130A2 amplifier driver Eduardo Valentin
2009-10-08 12:30 ` Eero Nurkkala
2009-10-08 13:07 ` Peter Ujfalusi
2009-10-08 12:52 ` Mark Brown
2009-10-08 13:38 ` Peter Ujfalusi
2009-10-08 13:53 ` Mark Brown
2009-10-09 6:53 ` Peter Ujfalusi
2009-10-09 10:36 ` Mark Brown
2009-10-08 11:58 ` [PATCH 2/8] ASoC: OMAP: RX-51 Machine driver and AIC34b_dummy driver Eduardo Valentin
2009-10-08 12:31 ` Eero Nurkkala
2009-10-08 13:18 ` Eduardo Valentin
2009-10-08 13:11 ` Mark Brown
2009-10-09 5:44 ` Jarkko Nikula
2009-10-09 6:37 ` Eduardo Valentin
2009-10-09 12:19 ` Mark Brown
2009-10-08 11:58 ` [PATCH 3/8] McBSP: OMAP3: Add Sidetone feature Eduardo Valentin
2009-10-08 13:17 ` Mark Brown
2009-10-08 13:23 ` Eduardo Valentin
2009-10-08 13:27 ` Mark Brown
2009-10-09 5:09 ` Eero Nurkkala
2009-10-09 10:44 ` [alsa-devel] " Mark Brown
2009-10-12 6:17 ` Eero Nurkkala
2009-10-12 9:12 ` Mark Brown
2009-10-12 9:28 ` Eero Nurkkala
2009-10-12 9:32 ` Mark Brown
2009-10-12 10:28 ` Eero Nurkkala
2009-10-12 10:33 ` Mark Brown
2009-10-08 11:58 ` [PATCH 4/8] OMAP: RX51: Add audio board file Eduardo Valentin
2009-10-08 11:58 ` [PATCH 5/8] board-rx51-peripherals: split vaux3 and vmmc2 supplies Eduardo Valentin
2009-10-08 13:21 ` Mark Brown
2009-10-09 6:45 ` Eduardo Valentin
2009-10-09 11:03 ` Mark Brown
2009-10-12 8:08 ` Eduardo Valentin
2009-10-12 9:18 ` Mark Brown
2009-10-14 17:15 ` Tony Lindgren
2009-10-15 9:01 ` Mark Brown
2009-10-16 16:14 ` Tony Lindgren
2009-10-08 11:58 ` [PATCH 6/8] RX-51: Audio: Add usage of regulator framework to control VMMC2 Eduardo Valentin
2009-10-08 13:26 ` Mark Brown
2009-10-12 9:04 ` Eduardo Valentin
2009-10-12 9:21 ` Mark Brown
2009-10-19 9:13 ` Eduardo Valentin
2009-10-19 9:23 ` Mark Brown
2009-10-19 9:24 ` Mark Brown
2009-10-08 11:58 ` [PATCH 7/8] ASoC: tlv320aic3x: add initial usage of regulator framework to control avdd_dac Eduardo Valentin
2009-10-08 12:17 ` Eero Nurkkala
2009-10-08 13:17 ` Eduardo Valentin
2009-10-08 13:40 ` Mark Brown
2009-10-08 15:44 ` ext-Eero.Nurkkala
2009-10-08 16:01 ` Mark Brown
2009-10-09 4:28 ` Eero Nurkkala
2009-10-09 10:19 ` Mark Brown
2009-10-08 13:38 ` Mark Brown
2009-10-08 11:58 ` [PATCH 8/8] ASoC: tpa6130a2: Control vdd using regulator framework Eduardo Valentin
2009-10-08 13:43 ` Mark Brown
2009-10-08 13:56 ` Eduardo Valentin
2009-10-08 14:41 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).