26 #include <linux/module.h>
27 #include <linux/device.h>
43 #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
45 #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
46 xhandler_get, xhandler_put) \
47 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
48 .info = omap_mcbsp_st_info_volsw, \
49 .get = xhandler_get, .put = xhandler_put, \
50 .private_value = (unsigned long) &(struct soc_mixer_control) \
51 {.min = xmin, .max = xmax} }
70 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
74 dma_data = snd_soc_dai_get_dma_data(rtd->
cpu_dai, substream);
105 snd_interval_any(&frames);
106 size = mcbsp->
pdata->buffer_size;
108 frames.min = size / channels->
min;
116 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
137 if (mcbsp->
pdata->buffer_size) {
146 omap_mcbsp_hwrule_min_buffersize,
155 snd_soc_dai_set_dma_data(cpu_dai, substream,
164 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
175 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
205 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
219 delay = fifo_use / substream->
runtime->channels;
228 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
233 unsigned int format,
div, framesize, master;
235 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
248 if (mcbsp->
pdata->buffer_size) {
251 int period_words, max_thrsh;
254 period_words = params_period_bytes(params) / (wlen / 8);
266 divider = period_words / max_thrsh;
267 if (period_words % max_thrsh)
269 while (period_words % divider &&
270 divider < period_words)
272 if (divider == period_words)
275 pkt_size = period_words / divider;
276 }
else if (channels > 1) {
336 if (framesize < wlen * channels) {
338 "channels\n", __func__);
351 regs->
srgr1 |=
FWID((framesize >> 1) - 1);
371 static int omap_mcbsp_dai_set_dai_fmt(
struct snd_soc_dai *cpu_dai,
374 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
382 memset(regs, 0,
sizeof(*regs));
387 if (!mcbsp->
pdata->has_ccr) {
393 if (mcbsp->
pdata->has_ccr) {
475 static int omap_mcbsp_dai_set_clkdiv(
struct snd_soc_dai *cpu_dai,
478 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
491 static int omap_mcbsp_dai_set_dai_sysclk(
struct snd_soc_dai *cpu_dai,
492 int clk_id,
unsigned int freq,
495 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
544 .startup = omap_mcbsp_dai_startup,
545 .shutdown = omap_mcbsp_dai_shutdown,
546 .trigger = omap_mcbsp_dai_trigger,
547 .delay = omap_mcbsp_dai_delay,
548 .hw_params = omap_mcbsp_dai_hw_params,
549 .set_fmt = omap_mcbsp_dai_set_dai_fmt,
550 .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
551 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
554 static int omap_mcbsp_probe(
struct snd_soc_dai *dai)
556 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
563 static int omap_mcbsp_remove(
struct snd_soc_dai *dai)
565 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
567 pm_runtime_disable(mcbsp->
dev);
573 .probe = omap_mcbsp_probe,
574 .remove = omap_mcbsp_remove,
587 .ops = &mcbsp_dai_ops,
590 static int omap_mcbsp_st_info_volsw(
struct snd_kcontrol *kcontrol,
605 #define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \
607 omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
608 struct snd_ctl_elem_value *uc) \
610 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
611 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
612 struct soc_mixer_control *mc = \
613 (struct soc_mixer_control *)kc->private_value; \
616 int val = uc->value.integer.value[0]; \
618 if (val < min || val > max) \
622 return omap_st_set_chgain(mcbsp, channel, val); \
626 omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
627 struct snd_ctl_elem_value *uc) \
629 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
630 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
633 if (omap_st_get_chgain(mcbsp, channel, &chgain)) \
636 uc->value.integer.value[0] = chgain; \
647 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
648 u8 value = ucontrol->value.integer.value[0];
661 static int omap_mcbsp_st_get_mode(
struct snd_kcontrol *kcontrol,
665 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
671 #define OMAP_MCBSP_ST_CONTROLS(port) \
672 static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \
673 SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \
674 omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \
675 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \
677 omap_mcbsp_get_st_ch0_volume, \
678 omap_mcbsp_set_st_ch0_volume), \
679 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \
681 omap_mcbsp_get_st_ch1_volume, \
682 omap_mcbsp_set_st_ch1_volume), \
691 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
694 dev_warn(mcbsp->
dev,
"No sidetone data for port\n");
701 omap_mcbsp2_st_controls,
705 omap_mcbsp3_st_controls,
740 static const struct of_device_id omap_mcbsp_of_match[] = {
742 .compatible =
"ti,omap2420-mcbsp",
743 .data = &omap2420_pdata,
746 .compatible =
"ti,omap2430-mcbsp",
747 .data = &omap2430_pdata,
750 .compatible =
"ti,omap3-mcbsp",
751 .data = &omap3_pdata,
754 .compatible =
"ti,omap4-mcbsp",
755 .data = &omap4_pdata,
780 if (!of_property_read_u32(node,
"ti,buffer-size", &buffer_size))
783 dev_err(&pdev->
dev,
"missing platform data.\n");
790 mcbsp->
id = pdev->
id;
793 platform_set_drvdata(pdev, mcbsp);
804 struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
808 if (mcbsp->
pdata->ops && mcbsp->
pdata->ops->free)
809 mcbsp->
pdata->ops->free(mcbsp->
id);
815 platform_set_drvdata(pdev,
NULL);
822 .name =
"omap-mcbsp",
824 .of_match_table = omap_mcbsp_of_match,
827 .probe = asoc_mcbsp_probe,