[alsa-devel] [PATCHv2 00/20] OMAP ASoC changes in DMA utilization
Hello guys,
Here is version 2 of this series. There were lots of little changes and also one significant change.
Here is a changelog: - I tried to avoid additional ifdefs in mcbsp code - The WAKEUPEN_ALL macro was removed - I added a REVISIT prefix for the additional delay on mcbsp start - New added constants are now following mcbsp.h style - While reading DMA operation mode of mcbsp, now it prints also some help text to explain the meaning of each value (even though you still write numbers).
Besides, I re-wrote the code for ASoC part, now the threshold and dma op mode usage are un-glued from mcbsp code. I tried to do not leave omap-pcm.c dirty, but, there was still one needed callback for setting the mcbsp threshold, as that needs to be done before DMA is started.
In this series I've left THRESHOLD mode as default for mcbsp 2 only. But as I saw in previous comments, this is still an open issue :-)
Comments, as usual are welcome.
Eduardo Valentin (11): OMAP: McBSP: Add IRQEN, IRQSTATUS, THRESHOLD2 and THRESHOLD1 registers. OMAP: McBSP: Use appropriate value for startup delay OMAP: McBSP: Add transmit/receive threshold handler OMAP: McBSP: Create and export max_(r|t)x_thres property OMAP: McBSP: Rename thres sysfs symbols OMAP: McBSP: Change wakeup signals OMAP: McBSP: Configure NO IDLE mode for DMA mode different of threshold ASoC: OMAP: Use McBSP threshold to playback and capture ASoC: OMAP: Use DMA operating mode of McBSP ASoC: OMAP: Make DMA 64 aligned ASoC: OMAP: Enable DMA burst mode
Eero Nurkkala (7): OMAP: McBSP: Provide functions for ASoC frame syncronization OMAP: McBSP: Wakeups utilized OMAP: McBSP: Retain McBSP FCLK clockactivity OMAP: McBSP: Do not enable wakeups for no-idle mode OMAP: McBSP: Let element DMA mode hit retention also ASoC: Add runtime check for RFIG and XFIG ASoC: Always syncronize audio transfers on frames
Peter Ujfalusi (2): OMAP3: McBSP: Lower the maximum buffersize for McBSP1,3,4,5 OMAP: McBSP: Add link DMA mode selection
arch/arm/mach-omap2/mcbsp.c | 5 + arch/arm/plat-omap/include/mach/mcbsp.h | 49 ++++ arch/arm/plat-omap/mcbsp.c | 375 ++++++++++++++++++++++++++++++- sound/soc/omap/omap-mcbsp.c | 67 +++++- sound/soc/omap/omap-pcm.c | 33 +++- sound/soc/omap/omap-pcm.h | 2 + 6 files changed, 517 insertions(+), 14 deletions(-)
-- To unsubscribe from this list: send the line "unsubscribe alsa-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
ASoC has an annoying bug letting either L or R channel to be played on L channel. In other words, L and R channels can switch at random. This provides McBSP funtionality that may be used to fix this feature.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 2 + arch/arm/plat-omap/mcbsp.c | 52 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index bb154ea..77191c5 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -389,6 +389,8 @@ int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); void omap_mcbsp_start(unsigned int id); void omap_mcbsp_stop(unsigned int id); +void omap_mcbsp_xmit_enable(unsigned int id, u8 enable); +void omap_mcbsp_recv_enable(unsigned int id, u8 enable); void omap_mcbsp_xmit_word(unsigned int id, u32 word); u32 omap_mcbsp_recv_word(unsigned int id);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index efa0e01..84cc323 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -398,6 +398,58 @@ void omap_mcbsp_stop(unsigned int id) } EXPORT_SYMBOL(omap_mcbsp_stop);
+void omap_mcbsp_xmit_enable(unsigned int id, u8 enable) +{ + struct omap_mcbsp *mcbsp; + void __iomem *io_base; + u16 w; + + if (!(cpu_is_omap2430() || cpu_is_omap34xx())) + return; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + + w = OMAP_MCBSP_READ(io_base, XCCR); + + if (enable) + OMAP_MCBSP_WRITE(io_base, XCCR, w & ~(XDISABLE)); + else + OMAP_MCBSP_WRITE(io_base, XCCR, w | XDISABLE); +} +EXPORT_SYMBOL(omap_mcbsp_xmit_enable); + +void omap_mcbsp_recv_enable(unsigned int id, u8 enable) +{ + struct omap_mcbsp *mcbsp; + void __iomem *io_base; + u16 w; + + if (!(cpu_is_omap2430() || cpu_is_omap34xx())) + return; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + + w = OMAP_MCBSP_READ(io_base, RCCR); + + if (enable) + OMAP_MCBSP_WRITE(io_base, RCCR, w & ~(RDISABLE)); + else + OMAP_MCBSP_WRITE(io_base, RCCR, w | RDISABLE); +} +EXPORT_SYMBOL(omap_mcbsp_recv_enable); + /* polled mcbsp i/o operations */ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) {
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 77191c5..51908fb 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -134,6 +134,10 @@ #define OMAP_MCBSP_REG_XCERG 0x74 #define OMAP_MCBSP_REG_XCERH 0x78 #define OMAP_MCBSP_REG_SYSCON 0x8C +#define OMAP_MCBSP_REG_THRSH2 0x90 +#define OMAP_MCBSP_REG_THRSH1 0x94 +#define OMAP_MCBSP_REG_IRQST 0xA0 +#define OMAP_MCBSP_REG_IRQEN 0xA4 #define OMAP_MCBSP_REG_XCCR 0xAC #define OMAP_MCBSP_REG_RCCR 0xB0
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/mcbsp.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 84cc323..2383b08 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -359,7 +359,13 @@ void omap_mcbsp_start(unsigned int id) w = OMAP_MCBSP_READ(io_base, SPCR1); OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
- udelay(100); + /* + * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec + * REVISIT: 100us may give enough time for two CLKSRG, however + * due to some unknown PM related, clock gating etc. reason it + * is now at 500us. + */ + udelay(500);
/* Start frame sync */ w = OMAP_MCBSP_READ(io_base, SPCR2);
From: Eduardo Valentin eduardo.valentin@nokia.com
This patch adds a way to handle transmit/receive threshold. It export to mcbsp users a callback registration procedure.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 9 +++++ arch/arm/plat-omap/mcbsp.c | 50 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 51908fb..c3dac63 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -389,6 +389,15 @@ int omap_mcbsp_init(void); void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, int size); void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); +#ifdef CONFIG_ARCH_OMAP34XX +void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); +void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); +#else +static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) +{ } +static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) +{ } +#endif int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); void omap_mcbsp_start(unsigned int id); diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 2383b08..4efc6d7 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -198,6 +198,56 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) } EXPORT_SYMBOL(omap_mcbsp_config);
+#ifdef CONFIG_ARCH_OMAP34XX +/* + * omap_mcbsp_set_tx_threshold configures how to deal + * with transmit threshold. the threshold value and handler can be + * configure in here. + */ +void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) +{ + struct omap_mcbsp *mcbsp; + void __iomem *io_base; + + if (!cpu_is_omap34xx()) + return; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + + OMAP_MCBSP_WRITE(io_base, THRSH2, threshold); +} +EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); + +/* + * omap_mcbsp_set_rx_threshold configures how to deal + * with receive threshold. the threshold value and handler can be + * configure in here. + */ +void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) +{ + struct omap_mcbsp *mcbsp; + void __iomem *io_base; + + if (!cpu_is_omap34xx()) + return; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + + OMAP_MCBSP_WRITE(io_base, THRSH1, threshold); +} +EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); +#endif + /* * We can choose between IRQ based or polled IO. * This needs to be called before omap_mcbsp_request().
From: Eduardo Valentin eduardo.valentin@nokia.com
This patch export through sysfs two properties to configure maximum threshold for transmission and reception on each mcbsp instance. Also, it exports two helper functions to allow mcbsp users to read this values.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/mach-omap2/mcbsp.c | 5 + arch/arm/plat-omap/include/mach/mcbsp.h | 11 +++ arch/arm/plat-omap/mcbsp.c | 122 +++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index a5c0f04..f837114 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -129,6 +129,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, + .buffer_size = 0x7F, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -137,6 +138,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, + .buffer_size = 0x3FF, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -145,6 +147,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, + .buffer_size = 0x7F, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -153,6 +156,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, + .buffer_size = 0x7F, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -161,6 +165,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, + .buffer_size = 0x7F, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index c3dac63..51a6655 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -348,6 +348,9 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; +#ifdef CONFIG_ARCH_OMAP34XX + u16 buffer_size; +#endif };
struct omap_mcbsp { @@ -381,6 +384,10 @@ struct omap_mcbsp { struct omap_mcbsp_platform_data *pdata; struct clk *iclk; struct clk *fclk; +#ifdef CONFIG_ARCH_OMAP34XX + u16 max_tx_thres; + u16 max_rx_thres; +#endif }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; @@ -392,11 +399,15 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config #ifdef CONFIG_ARCH_OMAP34XX void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); +u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); +u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); #else static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) { } static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) { } +static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } +static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } #endif int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 4efc6d7..2c97051 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -246,6 +246,42 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) OMAP_MCBSP_WRITE(io_base, THRSH1, threshold); } EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); + +/* + * omap_mcbsp_get_max_tx_thres just return the current configured + * maximum threshold for transmission + */ +u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + + 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); + + return mcbsp->max_tx_thres; +} +EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold); + +/* + * omap_mcbsp_get_max_rx_thres just return the current configured + * maximum threshold for reception + */ +u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + + 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); + + return mcbsp->max_rx_thres; +} +EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); #endif
/* @@ -991,6 +1027,86 @@ void omap_mcbsp_set_spi_mode(unsigned int id, } EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
+#ifdef CONFIG_ARCH_OMAP34XX +#define max_thres(m) (mcbsp->pdata->buffer_size) +#define valid_threshold(m, val) ((val) <= max_thres(m)) +#define THRESHOLD_PROP_BUILDER(prop) \ +static ssize_t prop##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ + \ + return sprintf(buf, "%u\n", mcbsp->prop); \ +} \ + \ +static ssize_t prop##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t size) \ +{ \ + struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ + unsigned long val; \ + int status; \ + \ + status = strict_strtoul(buf, 0, &val); \ + if (status) \ + return status; \ + \ + if (!valid_threshold(mcbsp, val)) \ + return -EDOM; \ + \ + mcbsp->prop = val; \ + return size; \ +} \ + \ +static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); + +THRESHOLD_PROP_BUILDER(max_tx_thres); +THRESHOLD_PROP_BUILDER(max_rx_thres); + +static const struct attribute *threshold_attrs[] = { + &dev_attr_max_tx_thres.attr, + &dev_attr_max_rx_thres.attr, + NULL, +}; + +static const struct attribute_group threshold_attr_group = { + .attrs = (struct attribute **)threshold_attrs, +}; + +static inline int __devinit omap_thres_add(struct device *dev) +{ + return sysfs_create_group(&dev->kobj, &threshold_attr_group); +} + +static inline void __devexit omap_thres_remove(struct device *dev) +{ + sysfs_remove_group(&dev->kobj, &threshold_attr_group); +} + +static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) +{ + if (cpu_is_omap34xx()) { + mcbsp->max_tx_thres = max_thres(mcbsp); + mcbsp->max_rx_thres = max_thres(mcbsp); + if (omap_thres_add(mcbsp->dev)) + dev_warn(mcbsp->dev, + "Unable to create threshold controls\n"); + } else { + mcbsp->max_tx_thres = -EINVAL; + mcbsp->max_rx_thres = -EINVAL; + } +} + +static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) +{ + if (cpu_is_omap34xx()) + omap_thres_remove(mcbsp->dev); +} +#else +static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} +static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} +#endif /* CONFIG_ARCH_OMAP34XX */ + /* * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. @@ -1061,6 +1177,10 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dev = &pdev->dev; mcbsp_ptr[id] = mcbsp; platform_set_drvdata(pdev, mcbsp); + + /* Initialize mcbsp properties for OMAP34XX if needed / applicable */ + omap34xx_device_init(mcbsp); + return 0;
err_fclk: @@ -1084,6 +1204,8 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id);
+ omap34xx_device_exit(mcbsp); + clk_disable(mcbsp->fclk); clk_disable(mcbsp->iclk); clk_put(mcbsp->fclk);
From: Peter Ujfalusi peter.ujfalusi@nokia.com
Do not allow applications to use the full buffer found on McBSP1,3,4,5. Using the full buffer in threshold mode causes the McBSP buffer to run dry, which can be observed as channels are switching (in reality the channels are shifting).
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com --- arch/arm/mach-omap2/mcbsp.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index f837114..7d22caf 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -129,7 +129,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x7F, + .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -147,7 +147,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x7F, + .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -156,7 +156,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x7F, + .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -165,7 +165,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x7F, + .buffer_size = 0x6F, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
From: Eduardo Valentin eduardo.valentin@nokia.com
This patch renames the symbols that handles threshold sysfs properties. This way we can add more sysfs properties to them.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/mcbsp.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 2c97051..13e7ce3 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -1063,24 +1063,24 @@ static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); THRESHOLD_PROP_BUILDER(max_tx_thres); THRESHOLD_PROP_BUILDER(max_rx_thres);
-static const struct attribute *threshold_attrs[] = { +static const struct attribute *additional_attrs[] = { &dev_attr_max_tx_thres.attr, &dev_attr_max_rx_thres.attr, NULL, };
-static const struct attribute_group threshold_attr_group = { - .attrs = (struct attribute **)threshold_attrs, +static const struct attribute_group additional_attr_group = { + .attrs = (struct attribute **)additional_attrs, };
-static inline int __devinit omap_thres_add(struct device *dev) +static inline int __devinit omap_additional_add(struct device *dev) { - return sysfs_create_group(&dev->kobj, &threshold_attr_group); + return sysfs_create_group(&dev->kobj, &additional_attr_group); }
-static inline void __devexit omap_thres_remove(struct device *dev) +static inline void __devexit omap_additional_remove(struct device *dev) { - sysfs_remove_group(&dev->kobj, &threshold_attr_group); + sysfs_remove_group(&dev->kobj, &additional_attr_group); }
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) @@ -1088,9 +1088,9 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) if (cpu_is_omap34xx()) { mcbsp->max_tx_thres = max_thres(mcbsp); mcbsp->max_rx_thres = max_thres(mcbsp); - if (omap_thres_add(mcbsp->dev)) + if (omap_additional_add(mcbsp->dev)) dev_warn(mcbsp->dev, - "Unable to create threshold controls\n"); + "Unable to create additional controls\n"); } else { mcbsp->max_tx_thres = -EINVAL; mcbsp->max_rx_thres = -EINVAL; @@ -1100,7 +1100,7 @@ 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()) - omap_thres_remove(mcbsp->dev); + omap_additional_remove(mcbsp->dev); } #else static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
From: Peter Ujfalusi peter.ujfalusi@nokia.com
It adds a new sysfs file, where the user can configure the mcbsp mode to use. If the mcbsp channel is in use, it does not allow the change. Than in omap_pcm_open we can call the omap_mcbsp_get_opmode to get the mode, store it, than use it to implement the different modes.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 8 +++ arch/arm/plat-omap/mcbsp.c | 82 +++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 51a6655..9b2b03e 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -255,6 +255,11 @@ /********************** McBSP SYSCONFIG bit definitions ********************/ #define SOFTRST 0x0002
+/********************** McBSP DMA operating modes **************************/ +#define MCBSP_DMA_MODE_ELEMENT 0 +#define MCBSP_DMA_MODE_THRESHOLD 1 +#define MCBSP_DMA_MODE_FRAME 2 + /* we don't do multichannel for now */ struct omap_mcbsp_reg_cfg { u16 spcr2; @@ -385,6 +390,7 @@ struct omap_mcbsp { struct clk *iclk; struct clk *fclk; #ifdef CONFIG_ARCH_OMAP34XX + int dma_op_mode; u16 max_tx_thres; u16 max_rx_thres; #endif @@ -401,6 +407,7 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); +int omap_mcbsp_get_dma_op_mode(unsigned int id); #else static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) { } @@ -408,6 +415,7 @@ static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) { } static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } +static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; } #endif int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 13e7ce3..23c1b1c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -282,6 +282,29 @@ u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) return mcbsp->max_rx_thres; } EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); + +/* + * omap_mcbsp_get_dma_op_mode just return the current configured + * operating mode for the mcbsp channel + */ +int omap_mcbsp_get_dma_op_mode(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + int dma_op_mode; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + spin_lock_irq(&mcbsp->lock); + dma_op_mode = mcbsp->dma_op_mode; + spin_unlock_irq(&mcbsp->lock); + + return dma_op_mode; +} +EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); #endif
/* @@ -1063,9 +1086,65 @@ static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); THRESHOLD_PROP_BUILDER(max_tx_thres); THRESHOLD_PROP_BUILDER(max_rx_thres);
+static ssize_t dma_op_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); + int dma_op_mode; + + spin_lock_irq(&mcbsp->lock); + dma_op_mode = mcbsp->dma_op_mode; + spin_unlock_irq(&mcbsp->lock); + + return sprintf(buf, "current mode: %d\n" + "possible mode values are:\n" + "%d - %s\n" + "%d - %s\n" + "%d - %s\n", + dma_op_mode, + MCBSP_DMA_MODE_ELEMENT, "element mode", + MCBSP_DMA_MODE_THRESHOLD, "threshold mode", + MCBSP_DMA_MODE_FRAME, "frame mode"); +} + +static ssize_t dma_op_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); + unsigned long val; + int status; + + status = strict_strtoul(buf, 0, &val); + if (status) + return status; + + spin_lock_irq(&mcbsp->lock); + + if (!mcbsp->free) { + size = -EBUSY; + goto unlock; + } + + if (val > MCBSP_DMA_MODE_FRAME || val < MCBSP_DMA_MODE_ELEMENT) { + size = -EINVAL; + goto unlock; + } + + mcbsp->dma_op_mode = val; + +unlock: + spin_unlock_irq(&mcbsp->lock); + + return size; +} + +static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); + static const struct attribute *additional_attrs[] = { &dev_attr_max_tx_thres.attr, &dev_attr_max_rx_thres.attr, + &dev_attr_dma_op_mode.attr, NULL, };
@@ -1085,9 +1164,12 @@ static inline void __devexit omap_additional_remove(struct device *dev)
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) { + mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; if (cpu_is_omap34xx()) { mcbsp->max_tx_thres = max_thres(mcbsp); mcbsp->max_rx_thres = max_thres(mcbsp); + if (mcbsp->id == 2) + mcbsp->dma_op_mode = MCBSP_DMA_MODE_THRESHOLD; if (omap_additional_add(mcbsp->dev)) dev_warn(mcbsp->dev, "Unable to create additional controls\n");
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
This patch enables the smart idle mode while McBPS is being utilized. Once it's done, force idle mode is taken instead. Apart of it, it also configures what signals will wake mcbsp up.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 17 +++++++++++ arch/arm/plat-omap/mcbsp.c | 46 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 9b2b03e..2c5612a 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -138,6 +138,7 @@ #define OMAP_MCBSP_REG_THRSH1 0x94 #define OMAP_MCBSP_REG_IRQST 0xA0 #define OMAP_MCBSP_REG_IRQEN 0xA4 +#define OMAP_MCBSP_REG_WAKEUPEN 0xA8 #define OMAP_MCBSP_REG_XCCR 0xAC #define OMAP_MCBSP_REG_RCCR 0xB0
@@ -253,6 +254,8 @@ #define RDISABLE 0x0001
/********************** McBSP SYSCONFIG bit definitions ********************/ +#define SIDLEMODE(value) ((value)<<3) +#define ENAWAKEUP 0x0004 #define SOFTRST 0x0002
/********************** McBSP DMA operating modes **************************/ @@ -260,6 +263,20 @@ #define MCBSP_DMA_MODE_THRESHOLD 1 #define MCBSP_DMA_MODE_FRAME 2
+/********************** McBSP WAKEUPEN bit definitions *********************/ +#define XEMPTYEOFEN 0x4000 +#define XRDYEN 0x0400 +#define XEOFEN 0x0200 +#define XFSXEN 0x0100 +#define XSYNCERREN 0x0080 +#define RRDYEN 0x0008 +#define REOFEN 0x0004 +#define RFSREN 0x0002 +#define RSYNCERREN 0x0001 +#define WAKEUPEN_ALL (XEMPTYEOFEN | XRDYEN | XEOFEN | XFSXEN | \ + XSYNCERREN | RRDYEN | REOFEN | RFSREN | \ + RSYNCERREN) + /* we don't do multichannel for now */ struct omap_mcbsp_reg_cfg { u16 spcr2; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 23c1b1c..a8de72b 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -305,6 +305,46 @@ int omap_mcbsp_get_dma_op_mode(unsigned int id) return dma_op_mode; } EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); + +static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) +{ + /* + * Enable wakup behavior, smart idle and all wakeups + * REVISIT: some wakeups may be unnecessary + */ + if (cpu_is_omap34xx()) { + u16 syscon; + + syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); + syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03)); + syscon |= (ENAWAKEUP | SIDLEMODE(0x02)); + OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); + + OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, WAKEUPEN_ALL); + } +} + +static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) +{ + /* + * Disable wakup behavior, smart idle and all wakeups + */ + if (cpu_is_omap34xx()) { + u16 syscon; + u16 wakeupen; + + syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); + syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03)); + OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); + + wakeupen = OMAP_MCBSP_READ(mcbsp->io_base, WAKEUPEN); + wakeupen &= ~WAKEUPEN_ALL; + OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, wakeupen); + } +} +#else +static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} +static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} #endif
/* @@ -366,6 +406,9 @@ int omap_mcbsp_request(unsigned int id) clk_enable(mcbsp->iclk); clk_enable(mcbsp->fclk);
+ /* Do procedure specific to omap34xx arch, if applicable */ + omap34xx_mcbsp_request(mcbsp); + /* * Make sure that transmitter, receiver and sample-rate generator are * not running before activating IRQs. @@ -414,6 +457,9 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id);
+ /* Do procedure specific to omap34xx arch, if applicable */ + omap34xx_mcbsp_free(mcbsp); + clk_disable(mcbsp->fclk); clk_disable(mcbsp->iclk);
From: Eduardo Valentin eduardo.valentin@nokia.com
Configure only XRDYEN and RRDYEN wakeup signals in order to get better power consumption.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 3 --- arch/arm/plat-omap/mcbsp.c | 7 ++----- 2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 2c5612a..776ea4d 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -273,9 +273,6 @@ #define REOFEN 0x0004 #define RFSREN 0x0002 #define RSYNCERREN 0x0001 -#define WAKEUPEN_ALL (XEMPTYEOFEN | XRDYEN | XEOFEN | XFSXEN | \ - XSYNCERREN | RRDYEN | REOFEN | RFSREN | \ - RSYNCERREN)
/* we don't do multichannel for now */ struct omap_mcbsp_reg_cfg { diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index a8de72b..940ef03 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -320,7 +320,7 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) syscon |= (ENAWAKEUP | SIDLEMODE(0x02)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
- OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, WAKEUPEN_ALL); + OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, XRDYEN | RRDYEN); } }
@@ -331,15 +331,12 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) */ if (cpu_is_omap34xx()) { u16 syscon; - u16 wakeupen;
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
- wakeupen = OMAP_MCBSP_READ(mcbsp->io_base, WAKEUPEN); - wakeupen &= ~WAKEUPEN_ALL; - OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, wakeupen); + OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0); } } #else
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
FCLK may get autogated so that it prevents the McBSP to work properly. It is the bit 9 that must be set for maintaining the McBSP FCLK.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com Acked-by: Jarkko Nikula jarkko.nikula@nokia.com --- arch/arm/plat-omap/include/mach/mcbsp.h | 1 + arch/arm/plat-omap/mcbsp.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 776ea4d..895f001 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -254,6 +254,7 @@ #define RDISABLE 0x0001
/********************** McBSP SYSCONFIG bit definitions ********************/ +#define CLOCKACTIVITY(value) ((value)<<8) #define SIDLEMODE(value) ((value)<<3) #define ENAWAKEUP 0x0004 #define SOFTRST 0x0002 diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 940ef03..e87c887 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -316,8 +316,8 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) u16 syscon;
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); - syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03)); - syscon |= (ENAWAKEUP | SIDLEMODE(0x02)); + syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); + syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | CLOCKACTIVITY(0x02)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, XRDYEN | RRDYEN); @@ -333,7 +333,7 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) u16 syscon;
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); - syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03)); + syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0);
From: Eduardo Valentin eduardo.valentin@nokia.com
Use dma mode property to configure NO IDLE or SMART IDLE of McBSPs.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/mcbsp.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index e87c887..ff5aefb 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -317,7 +317,15 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); - syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | CLOCKACTIVITY(0x02)); + + spin_lock_irq(&mcbsp->lock); + if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) + syscon |= SIDLEMODE(0x02); + else + syscon |= SIDLEMODE(0x01); + spin_unlock_irq(&mcbsp->lock); + + syscon |= (ENAWAKEUP | CLOCKACTIVITY(0x02)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, XRDYEN | RRDYEN);
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
When no-idle mode is taken, wakeups need not to be enabled. Moreover, CLOCKACTIVITY bits are unnecessary with this mode also.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com Acked-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/mcbsp.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index ff5aefb..208f422 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -319,16 +319,17 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
spin_lock_irq(&mcbsp->lock); - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - syscon |= SIDLEMODE(0x02); - else + if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { + syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | + CLOCKACTIVITY(0x02)); + OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, + XRDYEN | RRDYEN); + } else { syscon |= SIDLEMODE(0x01); + } spin_unlock_irq(&mcbsp->lock);
- syscon |= (ENAWAKEUP | CLOCKACTIVITY(0x02)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); - - OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, XRDYEN | RRDYEN); } }
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
The device no longer hits retention if element DMA mode is taken for at least the duration of the serial console timeout. Force element DMA mode to shut down through smartidle.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com Acked-by: Eduardo Valentin eduardo.valentin@nokia.com --- arch/arm/plat-omap/mcbsp.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 208f422..50a9fea 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -343,6 +343,15 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); + /* + * HW bug workaround - If no_idle mode is taken, we need to + * go to smart_idle before going to always_idle, or the + * device will not hit retention anymore. + */ + syscon |= SIDLEMODE(0x02); + OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); + + syscon &= ~(SIDLEMODE(0x03)); OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0);
From: Eduardo Valentin eduardo.valentin@nokia.com
This patch changes the way DMA is done in omap-pcm.c in order to reduce power consumption. There is no need to have so much SW control in order to have DMA in idle state during audio streaming. Configuring McBSP threshold value and DMA to FRAME_SYNC are sufficient.
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- sound/soc/omap/omap-mcbsp.c | 43 ++++++++++++++++++++++++++++++++++++++----- sound/soc/omap/omap-pcm.c | 17 +++++++++++++++-- sound/soc/omap/omap-pcm.h | 1 + 3 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index a5d46a7..8d8500f 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { static const unsigned long omap34xx_mcbsp_port[][2] = {}; #endif
+static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream, + int thres) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + + /* Configure McBSP internal buffer usage */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, thres); + else + omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, thres); +} + static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); + int bus_id = mcbsp_data->bus_id; int err = 0;
- if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { + if (!cpu_dai->active) + err = omap_mcbsp_request(bus_id); + + if (cpu_is_omap343x()) { + int max_period; + /* * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. * Set constraint for minimum buffer size to the same than FIFO * size in order to avoid underruns in playback startup because * HW is keeping the DMA request active until FIFO is filled. */ + if (bus_id == 1) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + 4096, UINT_MAX); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + max_period = omap_mcbsp_get_max_tx_threshold(bus_id); + else + max_period = omap_mcbsp_get_max_rx_threshold(bus_id); + + max_period++; + max_period <<= 1; + snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + 32, max_period); }
- if (!cpu_dai->active) - err = omap_mcbsp_request(mcbsp_data->bus_id); - return err; }
@@ -231,6 +262,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; + omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = + omap_mcbsp_set_threshold; } else { return -ENODEV; } diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 84a1950..0c1ba0f 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -31,7 +31,7 @@ #include <mach/dma.h> #include "omap-pcm.h"
-static const struct snd_pcm_hardware omap_pcm_hardware = { +static struct snd_pcm_hardware omap_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | @@ -135,6 +135,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) struct omap_runtime_data *prtd = runtime->private_data; struct omap_pcm_dma_data *dma_data = prtd->dma_data; struct omap_dma_channel_params dma_params; + int sync_mode;
/* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -142,13 +143,19 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) return 0;
memset(&dma_params, 0, sizeof(dma_params)); + + if (cpu_is_omap34xx()) + sync_mode = OMAP_DMA_SYNC_FRAME; + else + sync_mode = OMAP_DMA_SYNC_ELEMENT; + /* * Note: Regardless of interface data formats supported by OMAP McBSP * or EAC blocks, internal representation is always fixed 16-bit/sample */ dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; + dma_params.sync_mode = sync_mode; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; @@ -183,8 +190,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; + struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0; + int samples = snd_pcm_lib_period_bytes(substream) >> 1;
spin_lock_irqsave(&prtd->lock, flags); switch (cmd) { @@ -192,6 +201,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->period_index = 0; + /* Configure McBSP internal buffer usage */ + if (dma_data->set_threshold) + dma_data->set_threshold(substream, samples - 1); + omap_start_dma(prtd->dma_ch); break;
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index 8d9d269..6fda34d 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -29,6 +29,7 @@ struct omap_pcm_dma_data { char *name; /* stream identifier */ int dma_req; /* DMA request line */ unsigned long port_addr; /* transmit/receive register */ + void (*set_threshold)(struct snd_pcm_substream *substream, int thres); };
extern struct snd_soc_platform omap_soc_platform;
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- sound/soc/omap/omap-mcbsp.c | 8 ++++++-- sound/soc/omap/omap-pcm.c | 13 +++++++++++-- sound/soc/omap/omap-pcm.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 8d8500f..42a1956 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -166,6 +166,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, err = omap_mcbsp_request(bus_id);
if (cpu_is_omap343x()) { + int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); int max_period;
/* @@ -187,7 +188,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, max_period++; max_period <<= 1;
- snd_pcm_hw_constraint_minmax(substream->runtime, + if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) + snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32, max_period); } @@ -246,7 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; - int wlen, channels, wpf; + int wlen, channels, wpf, dma_mode = MCBSP_DMA_MODE_ELEMENT; unsigned long port; unsigned int format;
@@ -262,6 +264,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; + dma_mode = omap_mcbsp_get_dma_op_mode(bus_id); omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = omap_mcbsp_set_threshold; } else { @@ -271,6 +274,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; + omap_mcbsp_dai_dma_params[id][substream->stream].dma_op_mode = dma_mode; cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
if (mcbsp_data->configured) { diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 0c1ba0f..d8f52e8 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -144,7 +144,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
memset(&dma_params, 0, sizeof(dma_params));
- if (cpu_is_omap34xx()) + /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ + if (cpu_is_omap34xx() && + (dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)) sync_mode = OMAP_DMA_SYNC_FRAME; else sync_mode = OMAP_DMA_SYNC_ELEMENT; @@ -193,9 +195,16 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0; - int samples = snd_pcm_lib_period_bytes(substream) >> 1; + int samples;
spin_lock_irqsave(&prtd->lock, flags); + + /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ + if (dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) + samples = snd_pcm_lib_period_bytes(substream) >> 1; + else + samples = 1; + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index 6fda34d..4b77487 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -29,6 +29,7 @@ struct omap_pcm_dma_data { char *name; /* stream identifier */ int dma_req; /* DMA request line */ unsigned long port_addr; /* transmit/receive register */ + int dma_op_mode; /* DMA operation mode: element, frame */ void (*set_threshold)(struct snd_pcm_substream *substream, int thres); };
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- sound/soc/omap/omap-pcm.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index d8f52e8..b41a18b 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -310,7 +310,7 @@ static struct snd_pcm_ops omap_pcm_ops = { .mmap = omap_pcm_mmap, };
-static u64 omap_pcm_dmamask = DMA_BIT_MASK(32); +static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) @@ -360,7 +360,7 @@ int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->dma_mask) card->dev->dma_mask = &omap_pcm_dmamask; if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); + card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
if (dai->playback.channels_min) { ret = omap_pcm_preallocate_dma_buffer(pcm,
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com --- sound/soc/omap/omap-pcm.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b41a18b..4506603 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -185,6 +185,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+ omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); + omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); + return 0; }
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
This is, no RFIG or XFIG (Not defined in 34xx), correct initiliazation of rccr and xccr.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com --- sound/soc/omap/omap-mcbsp.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 42a1956..2d96548 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -358,8 +358,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); - regs->rcr2 |= RFIG; - regs->xcr2 |= XFIG; + /* RFIG and XFIG are not defined in 34xx */ + if (!cpu_is_omap34xx()) { + regs->rcr2 |= RFIG; + regs->xcr2 |= XFIG; + } if (cpu_is_omap2430() || cpu_is_omap34xx()) { regs->xccr = DXENDLY(1) | XDMAEN; regs->rccr = RFULL_CYCLE | RDMAEN;
From: Eero Nurkkala ext-eero.nurkkala@nokia.com
All these steps are required for ASoC to behave correctly. rccr and xccr are format dependent, for example TDM audio has different values than I2S or DSP_A. Also the omap_mcbsp_xmit_enable and/or omap_mcbsp_recv_enable must be called right after the DMA has started. This provides no longer L and R channels switching at random.
Signed-off-by: Eero Nurkkala ext-eero.nurkkala@nokia.com --- sound/soc/omap/omap-mcbsp.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2d96548..ad40da7 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -224,6 +224,11 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (!mcbsp_data->active++) omap_mcbsp_start(mcbsp_data->bus_id); + /* Make sure data transfer is frame synchronized */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + omap_mcbsp_xmit_enable(mcbsp_data->bus_id, 1); + else + omap_mcbsp_recv_enable(mcbsp_data->bus_id, 1); break;
case SNDRV_PCM_TRIGGER_STOP: @@ -373,11 +378,15 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* 1-bit data delay */ regs->rcr2 |= RDATDLY(1); regs->xcr2 |= XDATDLY(1); + regs->rccr |= RFULL_CYCLE | RDMAEN | RDISABLE; + regs->xccr |= (DXENDLY(1) | XDMAEN | XDISABLE); break; case SND_SOC_DAIFMT_DSP_A: /* 1-bit data delay */ regs->rcr2 |= RDATDLY(1); regs->xcr2 |= XDATDLY(1); + regs->rccr |= RFULL_CYCLE | RDMAEN | RDISABLE; + regs->xccr |= (DXENDLY(1) | XDMAEN | XDISABLE); /* Invert FS polarity configuration */ temp_fmt ^= SND_SOC_DAIFMT_NB_IF; break;
On Tue, 11 Aug 2009 16:05:27 +0300 Eduardo Valentin eduardo.valentin@nokia.com wrote:
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com
sound/soc/omap/omap-mcbsp.c | 8 ++++++-- sound/soc/omap/omap-pcm.c | 13 +++++++++++-- sound/soc/omap/omap-pcm.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-)
...
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 0c1ba0f..d8f52e8 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -144,7 +144,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
memset(&dma_params, 0, sizeof(dma_params));
- if (cpu_is_omap34xx())
- /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (cpu_is_omap34xx() &&
sync_mode = OMAP_DMA_SYNC_FRAME; else sync_mode = OMAP_DMA_SYNC_ELEMENT;(dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD))
Note, you could avoid the compile error if you move this into omap-mcbsp.c and pass only sync_mode here. Probably as easy as dma_data->sync_mode since OMAP_DMA_SYNC_ELEMENT is zero.
The McBSP DAI must and can know the DMA parameters (like sync_mode) but otherwise (like MCBSP_DMA_MODE_xxx) it sounds unnecessary glue between the drivers.
@@ -193,9 +195,16 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0;
- int samples = snd_pcm_lib_period_bytes(substream) >> 1;
int samples;
spin_lock_irqsave(&prtd->lock, flags);
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
if (dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
samples = snd_pcm_lib_period_bytes(substream) >> 1;
else
samples = 1;
Can these lines in this patch and in patch 15 to be moved into omap_mcbsp_trigger? For me it looks it would simplify and remove the glue between the drivers.
On Wed, Aug 12, 2009 at 02:38:38PM +0200, Jarkko Nikula wrote:
On Tue, 11 Aug 2009 16:05:27 +0300 Eduardo Valentin eduardo.valentin@nokia.com wrote:
From: Eduardo Valentin eduardo.valentin@nokia.com
Signed-off-by: Eduardo Valentin eduardo.valentin@nokia.com
sound/soc/omap/omap-mcbsp.c | 8 ++++++-- sound/soc/omap/omap-pcm.c | 13 +++++++++++-- sound/soc/omap/omap-pcm.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-)
...
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 0c1ba0f..d8f52e8 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -144,7 +144,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
memset(&dma_params, 0, sizeof(dma_params));
- if (cpu_is_omap34xx())
- /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (cpu_is_omap34xx() &&
sync_mode = OMAP_DMA_SYNC_FRAME; else sync_mode = OMAP_DMA_SYNC_ELEMENT;(dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD))
Note, you could avoid the compile error if you move this into omap-mcbsp.c and pass only sync_mode here. Probably as easy as dma_data->sync_mode since OMAP_DMA_SYNC_ELEMENT is zero.
Yes, it is way better to use dma_data->sync_mode. Good point.
The McBSP DAI must and can know the DMA parameters (like sync_mode) but otherwise (like MCBSP_DMA_MODE_xxx) it sounds unnecessary glue between the drivers.
I think these MCBSP_DMA_MODE_xxx references can be moved to omap-mcbsp.c. Will try it and send more comments.
@@ -193,9 +195,16 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0;
- int samples = snd_pcm_lib_period_bytes(substream) >> 1;
int samples;
spin_lock_irqsave(&prtd->lock, flags);
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
if (dma_data->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
samples = snd_pcm_lib_period_bytes(substream) >> 1;
else
samples = 1;
Can these lines in this patch and in patch 15 to be moved into omap_mcbsp_trigger? For me it looks it would simplify and remove the glue between the drivers.
These sample calculation can be moved to the .set_threshold I've added. But I'm afraid we can not move this threshold thing to omap_mcbsp_dai_trigger. At that point, DMA has been started by omap_pcm_trigger, this will generate a DMA sync error at the begging of stream execution.
-- Jarkko
On Tue, 11 Aug 2009 16:05:19 +0300 Eduardo Valentin eduardo.valentin@nokia.com wrote:
From: Peter Ujfalusi peter.ujfalusi@nokia.com
It adds a new sysfs file, where the user can configure the mcbsp mode to use. If the mcbsp channel is in use, it does not allow the change. Than in omap_pcm_open we can call the omap_mcbsp_get_opmode to get the mode, store it, than use it to implement the different modes.
...
+static ssize_t dma_op_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
+{
- struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
- int dma_op_mode;
- spin_lock_irq(&mcbsp->lock);
- dma_op_mode = mcbsp->dma_op_mode;
- spin_unlock_irq(&mcbsp->lock);
- return sprintf(buf, "current mode: %d\n"
"possible mode values are:\n"
"%d - %s\n"
"%d - %s\n"
"%d - %s\n",
dma_op_mode,
MCBSP_DMA_MODE_ELEMENT, "element mode",
MCBSP_DMA_MODE_THRESHOLD, "threshold mode",
MCBSP_DMA_MODE_FRAME, "frame mode");
+}
Btw: I hacked a patch below on top of the set for setting and reading the operating mode in ascii. Freely usable, no guarantee :-)
participants (2)
-
Eduardo Valentin
-
Jarkko Nikula