#include <sound/initval.h>
#include <sound/soc.h>
-#include <plat/control.h>
#include <plat/dma.h>
#include <plat/mcbsp.h>
#include "omap-mcbsp.h"
int wlen;
};
-#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
-
static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
/*
static const int omap24xx_dma_reqs[][2] = {};
#endif
+#if defined(CONFIG_ARCH_OMAP4)
+static const int omap44xx_dma_reqs[][2] = {
+ { OMAP44XX_DMA_MCBSP1_TX, OMAP44XX_DMA_MCBSP1_RX },
+ { OMAP44XX_DMA_MCBSP2_TX, OMAP44XX_DMA_MCBSP2_RX },
+ { OMAP44XX_DMA_MCBSP3_TX, OMAP44XX_DMA_MCBSP3_RX },
+ { OMAP44XX_DMA_MCBSP4_TX, OMAP44XX_DMA_MCBSP4_RX },
+};
+#else
+static const int omap44xx_dma_reqs[][2] = {};
+#endif
+
#if defined(CONFIG_ARCH_OMAP2420)
static const unsigned long omap2420_mcbsp_port[][2] = {
{ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
static const unsigned long omap34xx_mcbsp_port[][2] = {};
#endif
+#if defined(CONFIG_ARCH_OMAP4)
+static const unsigned long omap44xx_mcbsp_port[][2] = {
+ { OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+ { OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+ OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap44xx_mcbsp_port[][2] = {};
+#endif
+
static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
{
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);
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_pcm_dma_data *dma_data;
int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
int words;
- dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
}
static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *cpu_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);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
int bus_id = mcbsp_data->bus_id;
int err = 0;
* 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
* 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
*/
- if (cpu_is_omap343x()) {
+ if (cpu_is_omap343x() || cpu_is_omap44xx()) {
/*
* Rule for the buffer size. We should not allow
* smaller buffer than the FIFO size to avoid underruns
}
static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *cpu_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);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
if (!cpu_dai->active) {
omap_mcbsp_free(mcbsp_data->bus_id);
}
static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *cpu_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);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
switch (cmd) {
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);
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
u16 fifo_use;
snd_pcm_sframes_t delay;
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *cpu_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);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
struct omap_pcm_dma_data *dma_data;
int dma, bus_id = mcbsp_data->bus_id;
} else if (cpu_is_omap343x()) {
dma = omap24xx_dma_reqs[bus_id][substream->stream];
port = omap34xx_mcbsp_port[bus_id][substream->stream];
+ } else if (cpu_is_omap44xx()) {
+ dma = omap44xx_dma_reqs[bus_id][substream->stream];
+ port = omap44xx_mcbsp_port[bus_id][substream->stream];
} else {
return -ENODEV;
}
static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
- struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
unsigned int temp_fmt = fmt;
regs->spcr2 |= XINTM(3) | FREE;
regs->spcr1 |= RINTM(3);
/* RFIG and XFIG are not defined in 34xx */
- if (!cpu_is_omap34xx()) {
+ if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) {
regs->rcr2 |= RFIG;
regs->xcr2 |= XFIG;
}
- if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
}
static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
int div_id, int div)
{
- struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
if (div_id != OMAP_MCBSP_CLKGDV)
return 0;
}
-static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
- int clk_id)
-{
- int sel_bit;
- u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
-
- if (cpu_class_is_omap1()) {
- /* OMAP1's can use only external source clock */
- if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
- return -EINVAL;
- else
- return 0;
- }
-
- if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
- return -EINVAL;
-
- if (cpu_is_omap343x())
- reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
-
- switch (mcbsp_data->bus_id) {
- case 0:
- reg = OMAP2_CONTROL_DEVCONF0;
- sel_bit = 2;
- break;
- case 1:
- reg = OMAP2_CONTROL_DEVCONF0;
- sel_bit = 6;
- break;
- case 2:
- reg = reg_devconf1;
- sel_bit = 0;
- break;
- case 3:
- reg = reg_devconf1;
- sel_bit = 2;
- break;
- case 4:
- reg = reg_devconf1;
- sel_bit = 4;
- break;
- default:
- return -EINVAL;
- }
-
- if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
- omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
- else
- omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
-
- return 0;
-}
-
-static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
- int clk_id)
-{
- int sel_bit, set = 0;
- u16 reg = OMAP2_CONTROL_DEVCONF0;
-
- if (cpu_class_is_omap1())
- return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
- if (mcbsp_data->bus_id != 0)
- return -EINVAL;
-
- switch (clk_id) {
- case OMAP_MCBSP_CLKR_SRC_CLKX:
- set = 1;
- case OMAP_MCBSP_CLKR_SRC_CLKR:
- sel_bit = 3;
- break;
- case OMAP_MCBSP_FSR_SRC_FSX:
- set = 1;
- case OMAP_MCBSP_FSR_SRC_FSR:
- sel_bit = 4;
- break;
- default:
- return -EINVAL;
- }
-
- if (set)
- omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
- else
- omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
-
- return 0;
-}
-
static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq,
int dir)
{
- struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+ struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int err = 0;
+ /* The McBSP signal muxing functions are only available on McBSP1 */
+ if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
+ clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
+ clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
+ clk_id == OMAP_MCBSP_FSR_SRC_FSX)
+ if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
+ return -EINVAL;
+
mcbsp_data->in_freq = freq;
switch (clk_id) {
regs->srgr2 |= CLKSM;
break;
case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+ if (cpu_class_is_omap1()) {
+ err = -EINVAL;
+ break;
+ }
+ err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ MCBSP_CLKS_PRCM_SRC);
+ break;
case OMAP_MCBSP_SYSCLK_CLKS_EXT:
- err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
+ if (cpu_class_is_omap1()) {
+ err = 0;
+ break;
+ }
+ err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ MCBSP_CLKS_PAD_SRC);
break;
case OMAP_MCBSP_SYSCLK_CLKX_EXT:
regs->pcr0 |= SCLKME;
break;
+
case OMAP_MCBSP_CLKR_SRC_CLKR:
+ if (cpu_class_is_omap1())
+ break;
+ omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+ break;
case OMAP_MCBSP_CLKR_SRC_CLKX:
+ if (cpu_class_is_omap1())
+ break;
+ omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+ break;
case OMAP_MCBSP_FSR_SRC_FSR:
+ if (cpu_class_is_omap1())
+ break;
+ omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+ break;
case OMAP_MCBSP_FSR_SRC_FSX:
- err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
+ if (cpu_class_is_omap1())
+ break;
+ omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
break;
default:
err = -ENODEV;
return err;
}
-static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
+static struct snd_soc_dai_ops mcbsp_dai_ops = {
.startup = omap_mcbsp_dai_startup,
.shutdown = omap_mcbsp_dai_shutdown,
.trigger = omap_mcbsp_dai_trigger,
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
};
-#define OMAP_MCBSP_DAI_BUILDER(link_id) \
-{ \
- .name = "omap-mcbsp-dai-"#link_id, \
- .id = (link_id), \
- .playback = { \
- .channels_min = 1, \
- .channels_max = 16, \
- .rates = OMAP_MCBSP_RATES, \
- .formats = SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S32_LE, \
- }, \
- .capture = { \
- .channels_min = 1, \
- .channels_max = 16, \
- .rates = OMAP_MCBSP_RATES, \
- .formats = SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S32_LE, \
- }, \
- .ops = &omap_mcbsp_dai_ops, \
- .private_data = &mcbsp_data[(link_id)].bus_id, \
+static int mcbsp_dai_probe(struct snd_soc_dai *dai)
+{
+ mcbsp_data[dai->id].bus_id = dai->id;
+ snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
+ return 0;
}
-struct snd_soc_dai omap_mcbsp_dai[] = {
- OMAP_MCBSP_DAI_BUILDER(0),
- OMAP_MCBSP_DAI_BUILDER(1),
-#if NUM_LINKS >= 3
- OMAP_MCBSP_DAI_BUILDER(2),
-#endif
-#if NUM_LINKS == 5
- OMAP_MCBSP_DAI_BUILDER(3),
- OMAP_MCBSP_DAI_BUILDER(4),
-#endif
+static struct snd_soc_dai_driver omap_mcbsp_dai =
+{
+ .probe = mcbsp_dai_probe,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = OMAP_MCBSP_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = OMAP_MCBSP_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &mcbsp_dai_ops,
};
-EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
-
-int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
+static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct soc_mixer_control *mc =
}
EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
+static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+}
+
+static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_dai(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver asoc_mcbsp_driver = {
+ .driver = {
+ .name = "omap-mcbsp-dai",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = asoc_mcbsp_probe,
+ .remove = __devexit_p(asoc_mcbsp_remove),
+};
+
static int __init snd_omap_mcbsp_init(void)
{
- return snd_soc_register_dais(omap_mcbsp_dai,
- ARRAY_SIZE(omap_mcbsp_dai));
+ return platform_driver_register(&asoc_mcbsp_driver);
}
module_init(snd_omap_mcbsp_init);
static void __exit snd_omap_mcbsp_exit(void)
{
- snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
+ platform_driver_unregister(&asoc_mcbsp_driver);
}
module_exit(snd_omap_mcbsp_exit);