* [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature @ 2010-02-17 14:45 Ilkka Koskinen 2010-02-17 14:45 ` [PATCHv2 1/2] " Ilkka Koskinen 2010-02-18 13:06 ` [PATCHv2 0/2] " Jarkko Nikula 0 siblings, 2 replies; 12+ messages in thread From: Ilkka Koskinen @ 2010-02-17 14:45 UTC (permalink / raw) To: alsa-devel, linux-omap, peter.ujfalusi, jhnikula, broonie, tony Cc: eduardo.valentin, ext-eero.nurkkala The first patch implements McBSP sidetone feature on OMAP3 while the second one provides ALSA interface for using it. The patch set is based on the patch Eduardo Valentin sent to alsa-devel mailing list in October 2009. Channel gain control and enabling the sidetone have been moved to ALSA interface as suggested in comments. Since previous review round, I have corrected both the pointed issues in ASoC patch. In addition, I rebased this patch on top of Janusz Krzysztofik's McBSP register cache patches in linux-omap-2.6.git Eero Nurkkala (1): McBSP: OMAP3: Add sidetone feature Ilkka Koskinen (1): ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone arch/arm/mach-omap2/mcbsp.c | 2 + arch/arm/plat-omap/include/plat/mcbsp.h | 63 +++++ arch/arm/plat-omap/mcbsp.c | 394 ++++++++++++++++++++++++++++++- sound/soc/omap/omap-mcbsp.c | 176 ++++++++++++++ sound/soc/omap/omap-mcbsp.h | 2 + 5 files changed, 636 insertions(+), 1 deletions(-) ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-17 14:45 [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature Ilkka Koskinen @ 2010-02-17 14:45 ` Ilkka Koskinen 2010-02-17 14:46 ` [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone Ilkka Koskinen 2010-02-18 0:25 ` [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature Tony Lindgren 2010-02-18 13:06 ` [PATCHv2 0/2] " Jarkko Nikula 1 sibling, 2 replies; 12+ messages in thread From: Ilkka Koskinen @ 2010-02-17 14:45 UTC (permalink / raw) To: alsa-devel, linux-omap, peter.ujfalusi, jhnikula, broonie, tony Cc: eduardo.valentin, ext-eero.nurkkala From: Eero Nurkkala <ext-eero.nurkkala@nokia.com> Add sidetone feature to McBSP instances 2 and 3 on OMAP3 based devices. Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> --- arch/arm/mach-omap2/mcbsp.c | 2 + arch/arm/plat-omap/include/plat/mcbsp.h | 63 +++++ arch/arm/plat-omap/mcbsp.c | 396 ++++++++++++++++++++++++++++++- 3 files changed, 460 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index d601f94..be8fce3 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -136,6 +136,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, @@ -145,6 +146,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/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 4df957b..5db1653 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/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 @@ -146,6 +149,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) @@ -264,6 +276,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 @@ -374,10 +404,25 @@ struct omap_mcbsp_platform_data { u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; #ifdef CONFIG_ARCH_OMAP3 + /* Sidetone block for McBSP 2 and 3 */ + unsigned long phys_base_st; u16 buffer_size; #endif }; +#define OMAP_MCBSP_ST_CHANNEL_0 (1 << 0) +#define OMAP_MCBSP_ST_CHANNEL_1 (1 << 1) + +struct omap_mcbsp_st_data { + void __iomem *io_base_st; + bool running; + bool enabled; + 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; @@ -410,6 +455,7 @@ struct omap_mcbsp { struct clk *iclk; struct clk *fclk; #ifdef CONFIG_ARCH_OMAP3 + struct omap_mcbsp_st_data *st_data; int dma_op_mode; u16 max_tx_thres; u16 max_rx_thres; @@ -459,4 +505,21 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf); int omap_mcbsp_pollwrite(unsigned int id, u16 buf); int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type); +#ifdef CONFIG_ARCH_OMAP3 +/* Sidetone specific API */ +int omap_st_set_chgain(unsigned int id, s16 ch0gain, s16 ch1gain, int channels); +int omap_st_get_chgain(unsigned int id, s16 *ch0gain, s16 *ch1gain); +int omap_st_enable(unsigned int id); +int omap_st_disable(unsigned int id); +int omap_st_is_enabled(unsigned int id); +#else +static inline int omap_st_set_chgain(unsigned int id, s16 ch0gain, + s16 ch1gain, int channels) { return 0; } +static inline int omap_st_get_chgain(unsigned int id, s16 *ch0gain, + s16 *ch1gain) { return 0; } +static inline int omap_st_enable(unsigned int id) { return 0; } +static inline int omap_st_disable(unsigned int id) { return 0; } +static inline int omap_st_is_enabled(unsigned int id) { return 0; } +#endif + #endif diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 473be3d..921a5c1 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -27,6 +27,8 @@ #include <plat/dma.h> #include <plat/mcbsp.h> +#include "../mach-omap2/cm-regbits-34xx.h" + struct omap_mcbsp **mcbsp_ptr; int omap_mcbsp_count, omap_mcbsp_cache_size; @@ -58,6 +60,18 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) } } +#ifdef CONFIG_ARCH_OMAP3 +void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) +{ + __raw_writel(val, mcbsp->st_data->io_base_st + reg); +} + +int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) +{ + return __raw_readl(mcbsp->st_data->io_base_st + reg); +} +#endif + #define MCBSP_READ(mcbsp, reg) \ omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) #define MCBSP_WRITE(mcbsp, reg, val) \ @@ -68,6 +82,11 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; +#define MCBSP_ST_READ(mcbsp, reg) \ + omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) +#define MCBSP_ST_WRITE(mcbsp, reg, val) \ + omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) + static void omap_mcbsp_dump_reg(u8 id) { struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); @@ -211,6 +230,251 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) EXPORT_SYMBOL(omap_mcbsp_config); #ifdef CONFIG_ARCH_OMAP3 +static void omap_st_on(struct omap_mcbsp *mcbsp) +{ + unsigned int w; + + /* + * 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 &= ~(1 << (mcbsp->id - 2)); + cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); + + /* Enable McBSP Sidetone */ + w = MCBSP_READ(mcbsp, SSELCR); + MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); + + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); + + /* Enable Sidetone from Sidetone Core */ + w = MCBSP_ST_READ(mcbsp, SSELCR); + MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN); +} + +static void omap_st_off(struct omap_mcbsp *mcbsp) +{ + unsigned int w; + + w = MCBSP_ST_READ(mcbsp, SSELCR); + MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); + + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE); + + w = MCBSP_READ(mcbsp, SSELCR); + MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); + + w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); + w |= 1 << (mcbsp->id - 2); + cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); +} + +static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) +{ + u16 val, i; + + val = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, val & ~(ST_AUTOIDLE)); + + val = MCBSP_ST_READ(mcbsp, SSELCR); + + if (val & ST_COEFFWREN) + MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); + + MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN); + + for (i = 0; i < 128; i++) + MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]); + + i = 0; + + val = MCBSP_ST_READ(mcbsp, SSELCR); + while (!(val & ST_COEFFWRDONE) && (++i < 1000)) + val = MCBSP_ST_READ(mcbsp, SSELCR); + + MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); + + if (i == 1000) + dev_err(mcbsp->dev, "McBSP FIR load error!\n"); +} + +static void omap_st_chgain(struct omap_mcbsp *mcbsp) +{ + u16 w; + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); + + w = MCBSP_ST_READ(mcbsp, SSELCR); + + MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \ + ST_CH1GAIN(st_data->ch1gain)); +} + +int omap_st_set_chgain(unsigned int id, s16 ch0gain, s16 ch1gain, + int channels) +{ + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + + if (!st_data) + return -ENOENT; + + spin_lock_irq(&mcbsp->lock); + if (channels & OMAP_MCBSP_ST_CHANNEL_0) + st_data->ch0gain = ch0gain; + + if (channels & OMAP_MCBSP_ST_CHANNEL_1) + st_data->ch1gain = ch1gain; + + if (st_data->enabled) + omap_st_chgain(mcbsp); + spin_unlock_irq(&mcbsp->lock); + + return 0; +} +EXPORT_SYMBOL(omap_st_set_chgain); + +int omap_st_get_chgain(unsigned int id, s16 *ch0gain, s16 *ch1gain) +{ + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + + if (!st_data) + return -ENOENT; + + spin_lock_irq(&mcbsp->lock); + *ch0gain = st_data->ch0gain; + *ch1gain = st_data->ch1gain; + spin_unlock_irq(&mcbsp->lock); + + return 0; +} +EXPORT_SYMBOL(omap_st_get_chgain); + +static int omap_st_start(struct omap_mcbsp *mcbsp) +{ + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + + if (st_data && st_data->enabled && !st_data->running) { + omap_st_fir_write(mcbsp, st_data->taps); + omap_st_chgain(mcbsp); + + if (!mcbsp->free) { + omap_st_on(mcbsp); + st_data->running = 1; + } + } + + return 0; +} + +int omap_st_enable(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + + if (!st_data) + return -ENODEV; + + spin_lock_irq(&mcbsp->lock); + st_data->enabled = 1; + omap_st_start(mcbsp); + spin_unlock_irq(&mcbsp->lock); + + return 0; +} +EXPORT_SYMBOL(omap_st_enable); + +static int omap_st_stop(struct omap_mcbsp *mcbsp) +{ + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + + if (st_data && st_data->running) { + if (!mcbsp->free) { + omap_st_off(mcbsp); + st_data->running = 0; + } + } + + return 0; +} + +int omap_st_disable(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + int ret = 0; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + + if (!st_data) + return -ENODEV; + + spin_lock_irq(&mcbsp->lock); + omap_st_stop(mcbsp); + st_data->enabled = 0; + spin_unlock_irq(&mcbsp->lock); + + return ret; +} +EXPORT_SYMBOL(omap_st_disable); + +int omap_st_is_enabled(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + + if (!st_data) + return -ENODEV; + + + return st_data->enabled; +} +EXPORT_SYMBOL(omap_st_is_enabled); + /* * omap_mcbsp_set_tx_threshold configures how to deal * with transmit threshold. the threshold value and handler can be @@ -363,6 +627,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 /* @@ -546,6 +812,9 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) } mcbsp = id_to_mcbsp_ptr(id); + if (cpu_is_omap34xx()) + omap_st_start(mcbsp); + mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7; mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7; @@ -637,6 +906,9 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) w = MCBSP_READ_CACHE(mcbsp, SPCR2); MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); } + + if (cpu_is_omap34xx()) + omap_st_stop(mcbsp); } EXPORT_SYMBOL(omap_mcbsp_stop); @@ -1212,6 +1484,64 @@ unlock: static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_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 const struct attribute *additional_attrs[] = { &dev_attr_max_tx_thres.attr, &dev_attr_max_rx_thres.attr, @@ -1233,6 +1563,60 @@ 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_taps.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; @@ -1246,6 +1630,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; @@ -1254,8 +1644,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.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone 2010-02-17 14:45 ` [PATCHv2 1/2] " Ilkka Koskinen @ 2010-02-17 14:46 ` Ilkka Koskinen 2010-02-18 8:14 ` Peter Ujfalusi 2010-02-18 0:25 ` [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature Tony Lindgren 1 sibling, 1 reply; 12+ messages in thread From: Ilkka Koskinen @ 2010-02-17 14:46 UTC (permalink / raw) To: alsa-devel, linux-omap, peter.ujfalusi, jhnikula, broonie, tony Cc: eduardo.valentin, ext-eero.nurkkala Add ASoC interface for OMAP McBSP2 and McBSP3 sidetones. Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> --- sound/soc/omap/omap-mcbsp.c | 176 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/omap/omap-mcbsp.h | 2 + 2 files changed, 178 insertions(+), 0 deletions(-) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index c0039b3..9078cf2 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -39,6 +39,14 @@ #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) +#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \ + xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = omap_mcbsp_st_info_volsw, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = (unsigned long) &(struct soc_mixer_control) \ + {.min = xmin, .max = xmax} } + struct omap_mcbsp_data { unsigned int bus_id; struct omap_mcbsp_reg_cfg regs; @@ -637,6 +645,174 @@ struct snd_soc_dai omap_mcbsp_dai[] = { EXPORT_SYMBOL_GPL(omap_mcbsp_dai); +int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; + int min = mc->min; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = min; + uinfo->value.integer.max = max; + return 0; +} + +static int omap_mcbsp_set_st_channel_vol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + int id, int channel) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; + int min = mc->min; + int val = ucontrol->value.integer.value[0]; + + if (val < min || val > max) + return -EINVAL; + + return omap_st_set_chgain((id)-1, val, 0, channel); +} + +static int omap_mcbsp_get_st_channel_vol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + int id, int channel) +{ + s16 ch0gain, ch1gain; + + if (omap_st_get_chgain((id)-1, &ch0gain, &ch1gain)) + return -EAGAIN; + + if (channel == OMAP_MCBSP_ST_CHANNEL_0) + ucontrol->value.integer.value[0] = ch0gain; + else if (channel == OMAP_MCBSP_ST_CHANNEL_1) + ucontrol->value.integer.value[0] = ch1gain; + + return 0; +} + +#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ +static int \ +omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ + struct snd_ctl_elem_value *uc) \ +{ \ + return omap_mcbsp_set_st_channel_vol(kc, uc, id, \ + OMAP_MCBSP_ST_CHANNEL_##channel); \ +} + +#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ +static int \ +omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ + struct snd_ctl_elem_value *uc) \ +{ \ + return omap_mcbsp_get_st_channel_vol(kc, uc, id, \ + OMAP_MCBSP_ST_CHANNEL_##channel); \ +} + +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) + +static int omap_mcbsp2_st_set_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 value = ucontrol->value.integer.value[0]; + + if (value == omap_st_is_enabled(1)) + return 0; + + if (value) + omap_st_enable(1); + else + omap_st_disable(1); + + return 1; +} + +static int omap_mcbsp2_st_get_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = omap_st_is_enabled(1); + return 0; +} + +static int omap_mcbsp3_st_set_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u8 value = ucontrol->value.integer.value[0]; + + if (value == omap_st_is_enabled(2)) + return 0; + + if (value) + omap_st_enable(2); + else + omap_st_disable(2); + + return 1; +} + +static int omap_mcbsp3_st_get_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + ucontrol->value.integer.value[0] = omap_st_is_enabled(2); + return 0; +} + +static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { + SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 0, 0, 1, 0, + omap_mcbsp2_st_get_mode, omap_mcbsp2_st_set_mode), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", + -32768, 32767, + omap_mcbsp2_get_st_ch0_volume, + omap_mcbsp2_set_st_ch0_volume), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", + -32768, 32767, + omap_mcbsp2_get_st_ch1_volume, + omap_mcbsp2_set_st_ch1_volume), +}; + +static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { + SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 0, 0, 1, 0, + omap_mcbsp3_st_get_mode, omap_mcbsp3_st_set_mode), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", + -32768, 32767, + omap_mcbsp3_get_st_ch0_volume, + omap_mcbsp3_set_st_ch0_volume), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", + -32768, 32767, + omap_mcbsp3_get_st_ch1_volume, + omap_mcbsp3_set_st_ch1_volume), +}; + +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) +{ + if (!cpu_is_omap34xx()) + return -ENODEV; + + switch (mcbsp_id) { + case 2: /* McBSP 2 */ + return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, + ARRAY_SIZE(omap_mcbsp2_st_controls)); + case 3: /* McBSP 3 */ + return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, + ARRAY_SIZE(omap_mcbsp3_st_controls)); + default: + break; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); + static int __init snd_omap_mcbsp_init(void) { return snd_soc_register_dais(omap_mcbsp_dai, diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 1968d03..6c363e5 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -57,4 +57,6 @@ enum omap_mcbsp_div { extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); + #endif -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone 2010-02-17 14:46 ` [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone Ilkka Koskinen @ 2010-02-18 8:14 ` Peter Ujfalusi 2010-02-18 8:49 ` ilkka.koskinen 0 siblings, 1 reply; 12+ messages in thread From: Peter Ujfalusi @ 2010-02-18 8:14 UTC (permalink / raw) To: Koskinen Ilkka (Nokia-D/Tampere) Cc: alsa-devel, tony, broonie, Valentin Eduardo (Nokia-D/Helsinki), Nurkkala Eero.An (EXT-Offcode/Oulu), linux-omap Hello, Looks good, but I have one comment, you can consider if you like it... ... > +static int omap_mcbsp2_st_set_mode(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + u8 value = ucontrol->value.integer.value[0]; > + > + if (value == omap_st_is_enabled(1)) > + return 0; > + > + if (value) > + omap_st_enable(1); > + else > + omap_st_disable(1); > + > + return 1; > +} > + > +static int omap_mcbsp2_st_get_mode(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + ucontrol->value.integer.value[0] = omap_st_is_enabled(1); > + return 0; > +} > + > +static int omap_mcbsp3_st_set_mode(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + u8 value = ucontrol->value.integer.value[0]; > + > + if (value == omap_st_is_enabled(2)) > + return 0; > + > + if (value) > + omap_st_enable(2); > + else > + omap_st_disable(2); > + > + return 1; > +} > + > +static int omap_mcbsp3_st_get_mode(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + > + ucontrol->value.integer.value[0] = omap_st_is_enabled(2); > + return 0; > +} Instead of having these two set of function, I would have only one: static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; u8 value = ucontrol->value.integer.value[0]; if (value == omap_st_is_enabled(mc->reg)) return 0; if (value) omap_st_enable(mc->reg); else omap_st_disable(mc->reg); return 1; } static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); return 0; } Than > +static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { > + SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 0, 0, 1, 0, > + omap_mcbsp2_st_get_mode, omap_mcbsp2_st_set_mode), SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), > + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", > + -32768, 32767, > + omap_mcbsp2_get_st_ch0_volume, > + omap_mcbsp2_set_st_ch0_volume), > + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", > + -32768, 32767, > + omap_mcbsp2_get_st_ch1_volume, > + omap_mcbsp2_set_st_ch1_volume), > +}; > + > +static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { > + SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 0, 0, 1, 0, > + omap_mcbsp3_st_get_mode, omap_mcbsp3_st_set_mode), SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), > + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", > + -32768, 32767, > + omap_mcbsp3_get_st_ch0_volume, > + omap_mcbsp3_set_st_ch0_volume), > + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", > + -32768, 32767, > + omap_mcbsp3_get_st_ch1_volume, > + omap_mcbsp3_set_st_ch1_volume), > +}; > + > +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) > +{ > + if (!cpu_is_omap34xx()) > + return -ENODEV; > + > + switch (mcbsp_id) { > + case 2: /* McBSP 2 */ > + return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, > + ARRAY_SIZE(omap_mcbsp2_st_controls)); > + case 3: /* McBSP 3 */ > + return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, > + ARRAY_SIZE(omap_mcbsp3_st_controls)); > + default: > + break; > + } > + > + return -EINVAL; > +} > +EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); > + > static int __init snd_omap_mcbsp_init(void) > { > return snd_soc_register_dais(omap_mcbsp_dai, > diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h > index 1968d03..6c363e5 100644 > --- a/sound/soc/omap/omap-mcbsp.h > +++ b/sound/soc/omap/omap-mcbsp.h > @@ -57,4 +57,6 @@ enum omap_mcbsp_div { > > extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; > > +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); > + > #endif -- Péter ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone 2010-02-18 8:14 ` Peter Ujfalusi @ 2010-02-18 8:49 ` ilkka.koskinen 0 siblings, 0 replies; 12+ messages in thread From: ilkka.koskinen @ 2010-02-18 8:49 UTC (permalink / raw) To: peter.ujfalusi Cc: alsa-devel, tony, broonie, eduardo.valentin, ext-Eero.Nurkkala, linux-omap >From: Ujfalusi Peter (Nokia-D/Tampere) >Sent: 18 February, 2010 10:15 > >Hello, > >Looks good, but I have one comment, you can consider if you like it... > >... > >> +static int omap_mcbsp2_st_set_mode(struct snd_kcontrol *kcontrol, >> + struct snd_ctl_elem_value *ucontrol) >> +{ >> + u8 value = ucontrol->value.integer.value[0]; >> + >> + if (value == omap_st_is_enabled(1)) >> + return 0; >> + >> + if (value) >> + omap_st_enable(1); >> + else >> + omap_st_disable(1); >> + >> + return 1; >> +} >> + >> +static int omap_mcbsp2_st_get_mode(struct snd_kcontrol *kcontrol, >> + struct snd_ctl_elem_value *ucontrol) >> +{ >> + ucontrol->value.integer.value[0] = omap_st_is_enabled(1); >> + return 0; >> +} >> + >> +static int omap_mcbsp3_st_set_mode(struct snd_kcontrol *kcontrol, >> + struct snd_ctl_elem_value *ucontrol) >> +{ >> + u8 value = ucontrol->value.integer.value[0]; >> + >> + if (value == omap_st_is_enabled(2)) >> + return 0; >> + >> + if (value) >> + omap_st_enable(2); >> + else >> + omap_st_disable(2); >> + >> + return 1; >> +} >> + >> +static int omap_mcbsp3_st_get_mode(struct snd_kcontrol *kcontrol, >> + struct snd_ctl_elem_value *ucontrol) >> +{ >> + >> + ucontrol->value.integer.value[0] = omap_st_is_enabled(2); >> + return 0; >> +} > >Instead of having these two set of function, I would have only one: > >static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, > struct >snd_ctl_elem_value *ucontrol) >{ > struct soc_mixer_control *mc = > (struct soc_mixer_control >*)kcontrol->private_value; > u8 value = ucontrol->value.integer.value[0]; > > if (value == omap_st_is_enabled(mc->reg)) > return 0; > > if (value) > omap_st_enable(mc->reg); > else > omap_st_disable(mc->reg); > > return 1; >} > >static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, > struct >snd_ctl_elem_value *ucontrol) >{ > struct soc_mixer_control *mc = > (struct soc_mixer_control >*)kcontrol->private_value; > > ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); > > return 0; >} > >Than Makes sense - I'll change it. Cheers, Ilkka >> +static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { >> + SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 0, 0, 1, 0, >> + omap_mcbsp2_st_get_mode, >omap_mcbsp2_st_set_mode), > > SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, > omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), > >> + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel >0 Volume", >> + -32768, 32767, >> + omap_mcbsp2_get_st_ch0_volume, >> + omap_mcbsp2_set_st_ch0_volume), >> + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel >1 Volume", >> + -32768, 32767, >> + omap_mcbsp2_get_st_ch1_volume, >> + omap_mcbsp2_set_st_ch1_volume), >> +}; >> + >> +static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { >> + SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 0, 0, 1, 0, >> + omap_mcbsp3_st_get_mode, >omap_mcbsp3_st_set_mode), > > SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, > omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), > >> + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel >0 Volume", >> + -32768, 32767, >> + omap_mcbsp3_get_st_ch0_volume, >> + omap_mcbsp3_set_st_ch0_volume), >> + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel >1 Volume", >> + -32768, 32767, >> + omap_mcbsp3_get_st_ch1_volume, >> + omap_mcbsp3_set_st_ch1_volume), >> +}; >> + >> +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, >int mcbsp_id) >> +{ >> + if (!cpu_is_omap34xx()) >> + return -ENODEV; >> + >> + switch (mcbsp_id) { >> + case 2: /* McBSP 2 */ >> + return snd_soc_add_controls(codec, >omap_mcbsp2_st_controls, >> + >ARRAY_SIZE(omap_mcbsp2_st_controls)); >> + case 3: /* McBSP 3 */ >> + return snd_soc_add_controls(codec, >omap_mcbsp3_st_controls, >> + >ARRAY_SIZE(omap_mcbsp3_st_controls)); >> + default: >> + break; >> + } >> + >> + return -EINVAL; >> +} >> +EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); >> + >> static int __init snd_omap_mcbsp_init(void) >> { >> return snd_soc_register_dais(omap_mcbsp_dai, >> diff --git a/sound/soc/omap/omap-mcbsp.h >b/sound/soc/omap/omap-mcbsp.h >> index 1968d03..6c363e5 100644 >> --- a/sound/soc/omap/omap-mcbsp.h >> +++ b/sound/soc/omap/omap-mcbsp.h >> @@ -57,4 +57,6 @@ enum omap_mcbsp_div { >> >> extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; >> >> +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, >int mcbsp_id); >> + >> #endif > >-- >Péter > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-17 14:45 ` [PATCHv2 1/2] " Ilkka Koskinen 2010-02-17 14:46 ` [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone Ilkka Koskinen @ 2010-02-18 0:25 ` Tony Lindgren 2010-02-18 10:58 ` Ilkka Koskinen 1 sibling, 1 reply; 12+ messages in thread From: Tony Lindgren @ 2010-02-18 0:25 UTC (permalink / raw) To: Ilkka Koskinen Cc: alsa-devel, peter.ujfalusi, broonie, eduardo.valentin, ext-eero.nurkkala, linux-omap * Ilkka Koskinen <ilkka.koskinen@nokia.com> [100217 06:41]: > From: Eero Nurkkala <ext-eero.nurkkala@nokia.com> > > Add sidetone feature to McBSP instances 2 and 3 on OMAP3 based devices. > > Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> This one looks good to me and can be merged via Alsa list along with the other patch. Acked-by: Tony Lindgren <tony@atomide.com> > --- > arch/arm/mach-omap2/mcbsp.c | 2 + > arch/arm/plat-omap/include/plat/mcbsp.h | 63 +++++ > arch/arm/plat-omap/mcbsp.c | 396 ++++++++++++++++++++++++++++++- > 3 files changed, 460 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c > index d601f94..be8fce3 100644 > --- a/arch/arm/mach-omap2/mcbsp.c > +++ b/arch/arm/mach-omap2/mcbsp.c > @@ -136,6 +136,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, > @@ -145,6 +146,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/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h > index 4df957b..5db1653 100644 > --- a/arch/arm/plat-omap/include/plat/mcbsp.h > +++ b/arch/arm/plat-omap/include/plat/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 > @@ -146,6 +149,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) > @@ -264,6 +276,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 > @@ -374,10 +404,25 @@ struct omap_mcbsp_platform_data { > u16 rx_irq, tx_irq; > struct omap_mcbsp_ops *ops; > #ifdef CONFIG_ARCH_OMAP3 > + /* Sidetone block for McBSP 2 and 3 */ > + unsigned long phys_base_st; > u16 buffer_size; > #endif > }; > > +#define OMAP_MCBSP_ST_CHANNEL_0 (1 << 0) > +#define OMAP_MCBSP_ST_CHANNEL_1 (1 << 1) > + > +struct omap_mcbsp_st_data { > + void __iomem *io_base_st; > + bool running; > + bool enabled; > + 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; > @@ -410,6 +455,7 @@ struct omap_mcbsp { > struct clk *iclk; > struct clk *fclk; > #ifdef CONFIG_ARCH_OMAP3 > + struct omap_mcbsp_st_data *st_data; > int dma_op_mode; > u16 max_tx_thres; > u16 max_rx_thres; > @@ -459,4 +505,21 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf); > int omap_mcbsp_pollwrite(unsigned int id, u16 buf); > int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type); > > +#ifdef CONFIG_ARCH_OMAP3 > +/* Sidetone specific API */ > +int omap_st_set_chgain(unsigned int id, s16 ch0gain, s16 ch1gain, int channels); > +int omap_st_get_chgain(unsigned int id, s16 *ch0gain, s16 *ch1gain); > +int omap_st_enable(unsigned int id); > +int omap_st_disable(unsigned int id); > +int omap_st_is_enabled(unsigned int id); > +#else > +static inline int omap_st_set_chgain(unsigned int id, s16 ch0gain, > + s16 ch1gain, int channels) { return 0; } > +static inline int omap_st_get_chgain(unsigned int id, s16 *ch0gain, > + s16 *ch1gain) { return 0; } > +static inline int omap_st_enable(unsigned int id) { return 0; } > +static inline int omap_st_disable(unsigned int id) { return 0; } > +static inline int omap_st_is_enabled(unsigned int id) { return 0; } > +#endif > + > #endif > diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c > index 473be3d..921a5c1 100644 > --- a/arch/arm/plat-omap/mcbsp.c > +++ b/arch/arm/plat-omap/mcbsp.c > @@ -27,6 +27,8 @@ > #include <plat/dma.h> > #include <plat/mcbsp.h> > > +#include "../mach-omap2/cm-regbits-34xx.h" > + > struct omap_mcbsp **mcbsp_ptr; > int omap_mcbsp_count, omap_mcbsp_cache_size; > > @@ -58,6 +60,18 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) > } > } > > +#ifdef CONFIG_ARCH_OMAP3 > +void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) > +{ > + __raw_writel(val, mcbsp->st_data->io_base_st + reg); > +} > + > +int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) > +{ > + return __raw_readl(mcbsp->st_data->io_base_st + reg); > +} > +#endif > + > #define MCBSP_READ(mcbsp, reg) \ > omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) > #define MCBSP_WRITE(mcbsp, reg, val) \ > @@ -68,6 +82,11 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) > #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) > #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; > > +#define MCBSP_ST_READ(mcbsp, reg) \ > + omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) > +#define MCBSP_ST_WRITE(mcbsp, reg, val) \ > + omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) > + > static void omap_mcbsp_dump_reg(u8 id) > { > struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); > @@ -211,6 +230,251 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) > EXPORT_SYMBOL(omap_mcbsp_config); > > #ifdef CONFIG_ARCH_OMAP3 > +static void omap_st_on(struct omap_mcbsp *mcbsp) > +{ > + unsigned int w; > + > + /* > + * 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 &= ~(1 << (mcbsp->id - 2)); > + cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); > + > + /* Enable McBSP Sidetone */ > + w = MCBSP_READ(mcbsp, SSELCR); > + MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); > + > + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); > + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); > + > + /* Enable Sidetone from Sidetone Core */ > + w = MCBSP_ST_READ(mcbsp, SSELCR); > + MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN); > +} > + > +static void omap_st_off(struct omap_mcbsp *mcbsp) > +{ > + unsigned int w; > + > + w = MCBSP_ST_READ(mcbsp, SSELCR); > + MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); > + > + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); > + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE); > + > + w = MCBSP_READ(mcbsp, SSELCR); > + MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); > + > + w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); > + w |= 1 << (mcbsp->id - 2); > + cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); > +} > + > +static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) > +{ > + u16 val, i; > + > + val = MCBSP_ST_READ(mcbsp, SYSCONFIG); > + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, val & ~(ST_AUTOIDLE)); > + > + val = MCBSP_ST_READ(mcbsp, SSELCR); > + > + if (val & ST_COEFFWREN) > + MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); > + > + MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN); > + > + for (i = 0; i < 128; i++) > + MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]); > + > + i = 0; > + > + val = MCBSP_ST_READ(mcbsp, SSELCR); > + while (!(val & ST_COEFFWRDONE) && (++i < 1000)) > + val = MCBSP_ST_READ(mcbsp, SSELCR); > + > + MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); > + > + if (i == 1000) > + dev_err(mcbsp->dev, "McBSP FIR load error!\n"); > +} > + > +static void omap_st_chgain(struct omap_mcbsp *mcbsp) > +{ > + u16 w; > + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; > + > + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); > + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); > + > + w = MCBSP_ST_READ(mcbsp, SSELCR); > + > + MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \ > + ST_CH1GAIN(st_data->ch1gain)); > +} > + > +int omap_st_set_chgain(unsigned int id, s16 ch0gain, s16 ch1gain, > + int channels) > +{ > + struct omap_mcbsp *mcbsp; > + struct omap_mcbsp_st_data *st_data; > + > + if (!omap_mcbsp_check_valid_id(id)) { > + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); > + return -ENODEV; > + } > + > + mcbsp = id_to_mcbsp_ptr(id); > + st_data = mcbsp->st_data; > + > + if (!st_data) > + return -ENOENT; > + > + spin_lock_irq(&mcbsp->lock); > + if (channels & OMAP_MCBSP_ST_CHANNEL_0) > + st_data->ch0gain = ch0gain; > + > + if (channels & OMAP_MCBSP_ST_CHANNEL_1) > + st_data->ch1gain = ch1gain; > + > + if (st_data->enabled) > + omap_st_chgain(mcbsp); > + spin_unlock_irq(&mcbsp->lock); > + > + return 0; > +} > +EXPORT_SYMBOL(omap_st_set_chgain); > + > +int omap_st_get_chgain(unsigned int id, s16 *ch0gain, s16 *ch1gain) > +{ > + struct omap_mcbsp *mcbsp; > + struct omap_mcbsp_st_data *st_data; > + > + if (!omap_mcbsp_check_valid_id(id)) { > + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); > + return -ENODEV; > + } > + > + mcbsp = id_to_mcbsp_ptr(id); > + st_data = mcbsp->st_data; > + > + if (!st_data) > + return -ENOENT; > + > + spin_lock_irq(&mcbsp->lock); > + *ch0gain = st_data->ch0gain; > + *ch1gain = st_data->ch1gain; > + spin_unlock_irq(&mcbsp->lock); > + > + return 0; > +} > +EXPORT_SYMBOL(omap_st_get_chgain); > + > +static int omap_st_start(struct omap_mcbsp *mcbsp) > +{ > + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; > + > + if (st_data && st_data->enabled && !st_data->running) { > + omap_st_fir_write(mcbsp, st_data->taps); > + omap_st_chgain(mcbsp); > + > + if (!mcbsp->free) { > + omap_st_on(mcbsp); > + st_data->running = 1; > + } > + } > + > + return 0; > +} > + > +int omap_st_enable(unsigned int id) > +{ > + struct omap_mcbsp *mcbsp; > + struct omap_mcbsp_st_data *st_data; > + > + if (!omap_mcbsp_check_valid_id(id)) { > + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); > + return -ENODEV; > + } > + > + mcbsp = id_to_mcbsp_ptr(id); > + st_data = mcbsp->st_data; > + > + if (!st_data) > + return -ENODEV; > + > + spin_lock_irq(&mcbsp->lock); > + st_data->enabled = 1; > + omap_st_start(mcbsp); > + spin_unlock_irq(&mcbsp->lock); > + > + return 0; > +} > +EXPORT_SYMBOL(omap_st_enable); > + > +static int omap_st_stop(struct omap_mcbsp *mcbsp) > +{ > + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; > + > + if (st_data && st_data->running) { > + if (!mcbsp->free) { > + omap_st_off(mcbsp); > + st_data->running = 0; > + } > + } > + > + return 0; > +} > + > +int omap_st_disable(unsigned int id) > +{ > + struct omap_mcbsp *mcbsp; > + struct omap_mcbsp_st_data *st_data; > + int ret = 0; > + > + if (!omap_mcbsp_check_valid_id(id)) { > + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); > + return -ENODEV; > + } > + > + mcbsp = id_to_mcbsp_ptr(id); > + st_data = mcbsp->st_data; > + > + if (!st_data) > + return -ENODEV; > + > + spin_lock_irq(&mcbsp->lock); > + omap_st_stop(mcbsp); > + st_data->enabled = 0; > + spin_unlock_irq(&mcbsp->lock); > + > + return ret; > +} > +EXPORT_SYMBOL(omap_st_disable); > + > +int omap_st_is_enabled(unsigned int id) > +{ > + struct omap_mcbsp *mcbsp; > + struct omap_mcbsp_st_data *st_data; > + > + if (!omap_mcbsp_check_valid_id(id)) { > + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); > + return -ENODEV; > + } > + > + mcbsp = id_to_mcbsp_ptr(id); > + st_data = mcbsp->st_data; > + > + if (!st_data) > + return -ENODEV; > + > + > + return st_data->enabled; > +} > +EXPORT_SYMBOL(omap_st_is_enabled); > + > /* > * omap_mcbsp_set_tx_threshold configures how to deal > * with transmit threshold. the threshold value and handler can be > @@ -363,6 +627,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 > > /* > @@ -546,6 +812,9 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) > } > mcbsp = id_to_mcbsp_ptr(id); > > + if (cpu_is_omap34xx()) > + omap_st_start(mcbsp); > + > mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7; > mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7; > > @@ -637,6 +906,9 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) > w = MCBSP_READ_CACHE(mcbsp, SPCR2); > MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); > } > + > + if (cpu_is_omap34xx()) > + omap_st_stop(mcbsp); > } > EXPORT_SYMBOL(omap_mcbsp_stop); > > @@ -1212,6 +1484,64 @@ unlock: > > static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_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 const struct attribute *additional_attrs[] = { > &dev_attr_max_tx_thres.attr, > &dev_attr_max_rx_thres.attr, > @@ -1233,6 +1563,60 @@ 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_taps.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; > @@ -1246,6 +1630,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; > @@ -1254,8 +1644,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.0.4 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-18 0:25 ` [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature Tony Lindgren @ 2010-02-18 10:58 ` Ilkka Koskinen 2010-02-18 11:01 ` Mark Brown 2010-02-18 17:14 ` Tony Lindgren 0 siblings, 2 replies; 12+ messages in thread From: Ilkka Koskinen @ 2010-02-18 10:58 UTC (permalink / raw) To: ext Tony Lindgren Cc: Koskinen Ilkka (Nokia-D/Tampere), alsa-devel, linux-omap, Ujfalusi Peter (Nokia-D/Tampere), jhnikula, broonie, Valentin Eduardo (Nokia-D/Helsinki), Nurkkala Eero.An (EXT-Offcode/Oulu) Hi, On Thu, 18 Feb 2010, ext Tony Lindgren wrote: > * Ilkka Koskinen <ilkka.koskinen@nokia.com> [100217 06:41]: >> From: Eero Nurkkala <ext-eero.nurkkala@nokia.com> >> >> Add sidetone feature to McBSP instances 2 and 3 on OMAP3 based devices. >> >> Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> > > This one looks good to me and can be merged via Alsa list along with > the other patch. > > Acked-by: Tony Lindgren <tony@atomide.com> Is that easiest way to do that? I mean, I'm afraid that the ALSA tree doesn't have Janusz Krzysztofik's McBSP register cache patches nor does it have your "omap3: Replace ARCH_OMAP34XX with ARCH_OMAP3" patch either. Anyway, I'll send the updated patches still today. Cheers, Ilkka ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-18 10:58 ` Ilkka Koskinen @ 2010-02-18 11:01 ` Mark Brown 2010-02-18 17:16 ` Tony Lindgren 2010-02-18 17:14 ` Tony Lindgren 1 sibling, 1 reply; 12+ messages in thread From: Mark Brown @ 2010-02-18 11:01 UTC (permalink / raw) To: Ilkka Koskinen Cc: alsa-devel, linux-omap, ext Tony Lindgren, Valentin Eduardo (Nokia-D/Helsinki), Ujfalusi Peter (Nokia-D/Tampere), Nurkkala Eero.An (EXT-Offcode/Oulu), Koskinen Ilkka (Nokia-D/Tampere) On Thu, Feb 18, 2010 at 12:58:55PM +0200, Ilkka Koskinen wrote: > Is that easiest way to do that? I mean, I'm afraid that the ALSA > tree doesn't have Janusz Krzysztofik's McBSP register cache patches > nor does it have your "omap3: Replace ARCH_OMAP34XX with ARCH_OMAP3" > patch either. > Anyway, I'll send the updated patches still today. Given that the merge window is likely to open within a week it might be simplest to just wait until that's sorted through, or if the patches will both apply in the OMAP tree and merge cleanly with ASoC then I'd be happy with pushing them that way (I'd expect, I'd need to review the second one). ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-18 11:01 ` Mark Brown @ 2010-02-18 17:16 ` Tony Lindgren 0 siblings, 0 replies; 12+ messages in thread From: Tony Lindgren @ 2010-02-18 17:16 UTC (permalink / raw) To: Mark Brown Cc: Ilkka Koskinen, Koskinen Ilkka (Nokia-D/Tampere), alsa-devel, linux-omap, Ujfalusi Peter (Nokia-D/Tampere), jhnikula, Valentin Eduardo (Nokia-D/Helsinki), Nurkkala Eero.An (EXT-Offcode/Oulu) * Mark Brown <broonie@opensource.wolfsonmicro.com> [100218 02:58]: > On Thu, Feb 18, 2010 at 12:58:55PM +0200, Ilkka Koskinen wrote: > > > Is that easiest way to do that? I mean, I'm afraid that the ALSA > > tree doesn't have Janusz Krzysztofik's McBSP register cache patches > > nor does it have your "omap3: Replace ARCH_OMAP34XX with ARCH_OMAP3" > > patch either. > > > Anyway, I'll send the updated patches still today. > > Given that the merge window is likely to open within a week it might be > simplest to just wait until that's sorted through, or if the patches > will both apply in the OMAP tree and merge cleanly with ASoC then I'd be > happy with pushing them that way (I'd expect, I'd need to review the > second one). Yeah I can add them once they're OK from ASoC point of view. Or we can wait and you can merge them later. Either way works just fine for me. Regards, Tony ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature 2010-02-18 10:58 ` Ilkka Koskinen 2010-02-18 11:01 ` Mark Brown @ 2010-02-18 17:14 ` Tony Lindgren 1 sibling, 0 replies; 12+ messages in thread From: Tony Lindgren @ 2010-02-18 17:14 UTC (permalink / raw) To: Ilkka Koskinen Cc: alsa-devel, linux-omap, Valentin Eduardo (Nokia-D/Helsinki), broonie, Ujfalusi Peter (Nokia-D/Tampere), Nurkkala Eero.An (EXT-Offcode/Oulu), Koskinen Ilkka (Nokia-D/Tampere) * Ilkka Koskinen <ikoskine@nokia.com> [100218 02:54]: > > Hi, > > On Thu, 18 Feb 2010, ext Tony Lindgren wrote: > >* Ilkka Koskinen <ilkka.koskinen@nokia.com> [100217 06:41]: > >>From: Eero Nurkkala <ext-eero.nurkkala@nokia.com> > >> > >>Add sidetone feature to McBSP instances 2 and 3 on OMAP3 based devices. > >> > >>Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> > > > >This one looks good to me and can be merged via Alsa list along with > >the other patch. > > > >Acked-by: Tony Lindgren <tony@atomide.com> > > Is that easiest way to do that? I mean, I'm afraid that the ALSA > tree doesn't have Janusz Krzysztofik's McBSP register cache patches > nor does it have your "omap3: Replace ARCH_OMAP34XX with ARCH_OMAP3" > patch either. > > Anyway, I'll send the updated patches still today. OH, that's right, I totally forgot about that. Sounds like I should add them both to omap for-next once everybody is happy. Regards, Tony ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature 2010-02-17 14:45 [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature Ilkka Koskinen 2010-02-17 14:45 ` [PATCHv2 1/2] " Ilkka Koskinen @ 2010-02-18 13:06 ` Jarkko Nikula 2010-02-18 14:04 ` Peter Ujfalusi 1 sibling, 1 reply; 12+ messages in thread From: Jarkko Nikula @ 2010-02-18 13:06 UTC (permalink / raw) To: Ilkka Koskinen Cc: alsa-devel, linux-omap, peter.ujfalusi, broonie, tony, eduardo.valentin, ext-eero.nurkkala On Wed, 17 Feb 2010 16:45:58 +0200 Ilkka Koskinen <ilkka.koskinen@nokia.com> wrote: > The first patch implements McBSP sidetone feature on OMAP3 while the second one > provides ALSA interface for using it. > Do I have something wrong since I cannot adjust the controls? Both "McBSP2 Sidetone Channel [0|1]" show 50%. I used line wrapped diff below. -- Jarkko diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c index d88ad5c..ac4f287 100644 --- a/sound/soc/omap/omap3beagle.c +++ b/sound/soc/omap/omap3beagle.c @@ -84,6 +84,11 @@ static int omap3beagle_hw_params(struct snd_pcm_substream *substream, return 0; } +static int omap3beagle_init(struct snd_soc_codec *codec) +{ + return omap_mcbsp_st_add_controls(codec, 2); +} + static struct snd_soc_ops omap3beagle_ops = { .hw_params = omap3beagle_hw_params, }; @@ -95,6 +100,7 @@ static struct snd_soc_dai_link omap3beagle_dai = { .cpu_dai = &omap_mcbsp_dai[0], .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], .ops = &omap3beagle_ops, + .init = omap3beagle_init, }; /* Audio machine driver */ ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature 2010-02-18 13:06 ` [PATCHv2 0/2] " Jarkko Nikula @ 2010-02-18 14:04 ` Peter Ujfalusi 0 siblings, 0 replies; 12+ messages in thread From: Peter Ujfalusi @ 2010-02-18 14:04 UTC (permalink / raw) To: ext Jarkko Nikula Cc: alsa-devel, linux-omap, tony, broonie, Valentin Eduardo (Nokia-D/Helsinki), Nurkkala Eero.An (EXT-Offcode/Oulu), Koskinen Ilkka (Nokia-D/Tampere) On Thursday 18 February 2010 15:06:21 ext Jarkko Nikula wrote: > On Wed, 17 Feb 2010 16:45:58 +0200 > > Ilkka Koskinen <ilkka.koskinen@nokia.com> wrote: > > The first patch implements McBSP sidetone feature on OMAP3 while the > > second one provides ALSA interface for using it. > > Do I have something wrong since I cannot adjust the controls? Both > "McBSP2 Sidetone Channel [0|1]" show 50%. Hmmm, at least there is no way to set the ch1 gain... I'll comment in the patch. > > I used line wrapped diff below. -- Péter ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-02-18 17:15 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-02-17 14:45 [PATCHv2 0/2] McBSP: OMAP3: Add sidetone feature Ilkka Koskinen 2010-02-17 14:45 ` [PATCHv2 1/2] " Ilkka Koskinen 2010-02-17 14:46 ` [PATCHv2 2/2] ASoC: OMAP-McBSP: ASoC interface for McBSP sidetone Ilkka Koskinen 2010-02-18 8:14 ` Peter Ujfalusi 2010-02-18 8:49 ` ilkka.koskinen 2010-02-18 0:25 ` [PATCHv2 1/2] McBSP: OMAP3: Add sidetone feature Tony Lindgren 2010-02-18 10:58 ` Ilkka Koskinen 2010-02-18 11:01 ` Mark Brown 2010-02-18 17:16 ` Tony Lindgren 2010-02-18 17:14 ` Tony Lindgren 2010-02-18 13:06 ` [PATCHv2 0/2] " Jarkko Nikula 2010-02-18 14:04 ` Peter Ujfalusi
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.