Advertisement
Guest User

omap-mcbsp.c

a guest
Aug 6th, 2011
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 28.63 KB | None | 0 0
  1. /*
  2.  * omap-mcbsp.c  --  OMAP ALSA SoC DAI driver using McBSP port
  3.  *
  4.  * Copyright (C) 2008 Nokia Corporation
  5.  *
  6.  * Contact: Jarkko Nikula <jhnikula@gmail.com>
  7.  *          Peter Ujfalusi <peter.ujfalusi@nokia.com>
  8.  *
  9.  * This program is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License
  11.  * version 2 as published by the Free Software Foundation.
  12.  *
  13.  * This program is distributed in the hope that it will be useful, but
  14.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21.  * 02110-1301 USA
  22.  *
  23.  */
  24.  
  25. #include <linux/init.h>
  26. #include <linux/module.h>
  27. #include <linux/device.h>
  28. #include <linux/delay.h>
  29. #include <sound/core.h>
  30. #include <sound/pcm.h>
  31. #include <sound/pcm_params.h>
  32. #include <sound/initval.h>
  33. #include <sound/soc.h>
  34.  
  35. #include <plat/control.h>
  36. #include <plat/dma.h>
  37. #include <plat/mcbsp.h>
  38. #include "omap-mcbsp.h"
  39. #include "omap-pcm.h"
  40.  
  41. #define OMAP_MCBSP_RATES    (SNDRV_PCM_RATE_8000_96000)
  42.  
  43. #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
  44.     xhandler_get, xhandler_put) \
  45. {   .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
  46.     .info = omap_mcbsp_st_info_volsw, \
  47.     .get = xhandler_get, .put = xhandler_put, \
  48.     .private_value = (unsigned long) &(struct soc_mixer_control) \
  49.     {.min = xmin, .max = xmax} }
  50.  
  51. struct omap_mcbsp_data {
  52.     unsigned int            bus_id;
  53.     struct omap_mcbsp_reg_cfg   regs;
  54.     unsigned int            fmt;
  55.  
  56.     /* optional machine set_threshold() sample value */
  57.     void (*mach_set_threshold)(struct snd_pcm_substream *substream);
  58.     /*
  59.      * Flags indicating is the bus already activated and configured by
  60.      * another substream
  61.      */
  62.     int             active;
  63.     int             configured;
  64.     unsigned int            in_freq;
  65.     int             clk_div;
  66.     int             wlen;
  67. };
  68.  
  69. #define to_mcbsp(priv)  container_of((priv), struct omap_mcbsp_data, bus_id)
  70.  
  71. static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
  72.  
  73. /*
  74.  * Stream DMA parameters. DMA request line and port address are set runtime
  75.  * since they are different between OMAP1 and later OMAPs
  76.  */
  77. static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
  78.  
  79. #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
  80. static const int omap1_dma_reqs[][2] = {
  81.     { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
  82.     { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
  83.     { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
  84. };
  85. static const unsigned long omap1_mcbsp_port[][2] = {
  86.     { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
  87.       OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
  88.     { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
  89.       OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
  90.     { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
  91.       OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
  92. };
  93. #else
  94. static const int omap1_dma_reqs[][2] = {};
  95. static const unsigned long omap1_mcbsp_port[][2] = {};
  96. #endif
  97.  
  98. #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
  99. static const int omap24xx_dma_reqs[][2] = {
  100.     { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
  101.     { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
  102. #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
  103.     { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
  104.     { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
  105.     { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
  106. #endif
  107. };
  108. #else
  109. static const int omap24xx_dma_reqs[][2] = {};
  110. #endif
  111.  
  112. #if defined(CONFIG_ARCH_OMAP2420)
  113. static const unsigned long omap2420_mcbsp_port[][2] = {
  114.     { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
  115.       OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
  116.     { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
  117.       OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
  118. };
  119. #else
  120. static const unsigned long omap2420_mcbsp_port[][2] = {};
  121. #endif
  122.  
  123. #if defined(CONFIG_ARCH_OMAP2430)
  124. static const unsigned long omap2430_mcbsp_port[][2] = {
  125.     { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
  126.       OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
  127.     { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
  128.       OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
  129.     { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
  130.       OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
  131.     { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
  132.       OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
  133.     { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
  134.       OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
  135. };
  136. #else
  137. static const unsigned long omap2430_mcbsp_port[][2] = {};
  138. #endif
  139.  
  140. #if defined(CONFIG_ARCH_OMAP3)
  141. static const unsigned long omap34xx_mcbsp_port[][2] = {
  142.     { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
  143.       OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
  144.     { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
  145.       OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
  146.     { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
  147.       OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
  148.     { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
  149.       OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
  150.     { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
  151.       OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
  152. };
  153. #else
  154. static const unsigned long omap34xx_mcbsp_port[][2] = {};
  155. #endif
  156.  
  157. static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
  158. {
  159.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  160.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  161.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  162.     struct omap_pcm_dma_data *dma_data;
  163.     int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
  164.     int words;
  165.  
  166.     dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
  167.  
  168.     /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
  169.     if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
  170.         /*
  171.          * Configure McBSP threshold based on either:
  172.          * packet_size, when the sDMA is in packet mode, or
  173.          * based on the period size.
  174.          */
  175.         if (dma_data->packet_size)
  176.             words = dma_data->packet_size;
  177.         else
  178.             words = snd_pcm_lib_period_bytes(substream) /
  179.                             (mcbsp_data->wlen / 8);
  180.     else
  181.         words = 1;
  182.  
  183.     /* Configure McBSP internal buffer usage */
  184.     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  185.         omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
  186.     else
  187.         omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
  188. }
  189.  
  190. static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
  191.                     struct snd_pcm_hw_rule *rule)
  192. {
  193.     struct snd_interval *buffer_size = hw_param_interval(params,
  194.                     SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
  195.     struct snd_interval *channels = hw_param_interval(params,
  196.                     SNDRV_PCM_HW_PARAM_CHANNELS);
  197.     struct omap_mcbsp_data *mcbsp_data = rule->private;
  198.     struct snd_interval frames;
  199.     int size;
  200.  
  201.     snd_interval_any(&frames);
  202.     size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
  203.  
  204.     frames.min = size / channels->min;
  205.     frames.integer = 1;
  206.     return snd_interval_refine(buffer_size, &frames);
  207. }
  208.  
  209. static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
  210.                   struct snd_soc_dai *dai)
  211. {
  212.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  213.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  214.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  215.     int bus_id = mcbsp_data->bus_id;
  216.     int err = 0;
  217.  
  218.     if (!cpu_dai->active)
  219.         err = omap_mcbsp_request(bus_id);
  220.  
  221.     /*
  222.      * OMAP3 McBSP FIFO is word structured.
  223.      * McBSP2 has 1024 + 256 = 1280 word long buffer,
  224.      * McBSP1,3,4,5 has 128 word long buffer
  225.      * This means that the size of the FIFO depends on the sample format.
  226.      * For example on McBSP3:
  227.      * 16bit samples: size is 128 * 2 = 256 bytes
  228.      * 32bit samples: size is 128 * 4 = 512 bytes
  229.      * It is simpler to place constraint for buffer and period based on
  230.      * channels.
  231.      * McBSP3 as example again (16 or 32 bit samples):
  232.      * 1 channel (mono): size is 128 frames (128 words)
  233.      * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
  234.      * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
  235.      */
  236.     if (cpu_is_omap343x()) {
  237.         /*
  238.         * Rule for the buffer size. We should not allow
  239.         * smaller buffer than the FIFO size to avoid underruns
  240.         */
  241.         snd_pcm_hw_rule_add(substream->runtime, 0,
  242.                     SNDRV_PCM_HW_PARAM_CHANNELS,
  243.                     omap_mcbsp_hwrule_min_buffersize,
  244.                     mcbsp_data,
  245.                     SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
  246.  
  247.         /* Make sure, that the period size is always even */
  248.         snd_pcm_hw_constraint_step(substream->runtime, 0,
  249.                        SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
  250.     }
  251.  
  252.     return err;
  253. }
  254.  
  255. static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
  256.                     struct snd_soc_dai *dai)
  257. {
  258.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  259.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  260.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  261.  
  262.     if (!cpu_dai->active) {
  263.         omap_mcbsp_free(mcbsp_data->bus_id);
  264.         mcbsp_data->configured = 0;
  265.     }
  266. }
  267.  
  268. static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
  269.                   struct snd_soc_dai *dai)
  270. {
  271.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  272.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  273.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  274.     int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
  275.  
  276.     switch (cmd) {
  277.     case SNDRV_PCM_TRIGGER_START:
  278.     case SNDRV_PCM_TRIGGER_RESUME:
  279.     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  280.         mcbsp_data->active++;
  281.         omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
  282.         break;
  283.  
  284.     case SNDRV_PCM_TRIGGER_STOP:
  285.     case SNDRV_PCM_TRIGGER_SUSPEND:
  286.     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  287.         omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
  288.         mcbsp_data->active--;
  289.         break;
  290.     default:
  291.         err = -EINVAL;
  292.     }
  293.  
  294.     return err;
  295. }
  296.  
  297. static snd_pcm_sframes_t omap_mcbsp_dai_delay(
  298.             struct snd_pcm_substream *substream,
  299.             struct snd_soc_dai *dai)
  300. {
  301.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  302.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  303.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  304.     u16 fifo_use;
  305.     snd_pcm_sframes_t delay;
  306.  
  307.     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  308.         fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
  309.     else
  310.         fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
  311.  
  312.     /*
  313.      * Divide the used locations with the channel count to get the
  314.      * FIFO usage in samples (don't care about partial samples in the
  315.      * buffer).
  316.      */
  317.     delay = fifo_use / substream->runtime->channels;
  318.  
  319.     return delay;
  320. }
  321.  
  322. int omap_mcbsp_request_power_level(struct snd_pcm_substream *substream,
  323.                    enum snd_soc_power_level level)
  324. {
  325.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  326.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  327.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  328.     u16 fifo_use, prev_fifo_use = 0;
  329.     int i = 0, ret = 0;
  330.  
  331.     /* Bail out in capture case */
  332.     if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  333.         return 0;
  334.  
  335.     if (level == SND_SOC_PM_ACTIVE) {
  336.         /* Enable McBSP clock(s) */
  337.         omap_mcbsp_set_pm_state(mcbsp_data->bus_id,
  338.                     OMAP_MCBSP_PM_ACTIVE);
  339.     } else {
  340.         fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
  341.         while (fifo_use != prev_fifo_use && i < 100) {
  342.             udelay(10);
  343.             prev_fifo_use = fifo_use;
  344.             fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
  345.             i++;
  346.         }
  347.         /* Disable McBSP clock(s) */
  348.         if (i < 100)
  349.             omap_mcbsp_set_pm_state(mcbsp_data->bus_id,
  350.                         OMAP_MCBSP_PM_INACTIVE);
  351.     }
  352.     return ret;
  353. }
  354.  
  355. static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
  356.                     struct snd_pcm_hw_params *params,
  357.                     struct snd_soc_dai *dai)
  358. {
  359.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  360.     struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  361.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  362.     struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
  363.     struct omap_pcm_dma_data *dma_data;
  364.     int dma, bus_id = mcbsp_data->bus_id;
  365.     int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
  366.     int pkt_size = 0;
  367.     unsigned long port;
  368.     unsigned int format, div, framesize, master;
  369.  
  370.     dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
  371.     if (cpu_class_is_omap1()) {
  372.         dma = omap1_dma_reqs[bus_id][substream->stream];
  373.         port = omap1_mcbsp_port[bus_id][substream->stream];
  374.     } else if (cpu_is_omap2420()) {
  375.         dma = omap24xx_dma_reqs[bus_id][substream->stream];
  376.         port = omap2420_mcbsp_port[bus_id][substream->stream];
  377.     } else if (cpu_is_omap2430()) {
  378.         dma = omap24xx_dma_reqs[bus_id][substream->stream];
  379.         port = omap2430_mcbsp_port[bus_id][substream->stream];
  380.     } else if (cpu_is_omap343x()) {
  381.         dma = omap24xx_dma_reqs[bus_id][substream->stream];
  382.         port = omap34xx_mcbsp_port[bus_id][substream->stream];
  383.     } else {
  384.         return -ENODEV;
  385.     }
  386.     switch (params_format(params)) {
  387.     case SNDRV_PCM_FORMAT_S16_LE:
  388.         dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
  389.         wlen = 16;
  390.         break;
  391.     case SNDRV_PCM_FORMAT_S32_LE:
  392.         dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
  393.         wlen = 32;
  394.         break;
  395.     default:
  396.         return -EINVAL;
  397.     }
  398.     if (cpu_is_omap343x()) {
  399.         if (mcbsp_data->mach_set_threshold)
  400.             dma_data->set_threshold = mcbsp_data->mach_set_threshold;
  401.         else
  402.             dma_data->set_threshold = omap_mcbsp_set_threshold;
  403.         /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
  404.         if (omap_mcbsp_get_dma_op_mode(bus_id) ==
  405.                         MCBSP_DMA_MODE_THRESHOLD) {
  406.             int period_words, max_thrsh;
  407.  
  408.             period_words = params_period_bytes(params) / (wlen / 8);
  409.             if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  410.                 max_thrsh = omap_mcbsp_get_max_tx_threshold(
  411.                                 mcbsp_data->bus_id);
  412.             else
  413.                 max_thrsh = omap_mcbsp_get_max_rx_threshold(
  414.                                 mcbsp_data->bus_id);
  415.             /*
  416.              * If the period contains less or equal number of words,
  417.              * we are using the original threshold mode setup:
  418.              * McBSP threshold = sDMA frame size = period_size
  419.              * Otherwise we switch to sDMA packet mode:
  420.              * McBSP threshold = sDMA packet size
  421.              * sDMA frame size = period size
  422.              */
  423.             if (period_words > max_thrsh) {
  424.                 int divider = 0;
  425.  
  426.                 /*
  427.                  * Look for the biggest threshold value, which
  428.                  * divides the period size evenly.
  429.                  */
  430.                 divider = period_words / max_thrsh;
  431.                 if (period_words % max_thrsh)
  432.                     divider++;
  433.                 while (period_words % divider &&
  434.                     divider < period_words)
  435.                     divider++;
  436.                 if (divider == period_words)
  437.                     return -EINVAL;
  438.  
  439.                 pkt_size = period_words / divider;
  440.                 sync_mode = OMAP_DMA_SYNC_PACKET;
  441.             } else {
  442.                 sync_mode = OMAP_DMA_SYNC_FRAME;
  443.             }
  444.         }
  445.     }
  446.  
  447.     dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
  448.     dma_data->dma_req = dma;
  449.     dma_data->port_addr = port;
  450.     dma_data->sync_mode = sync_mode;
  451.     dma_data->packet_size = pkt_size;
  452.  
  453.     snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
  454.  
  455.     if (mcbsp_data->configured) {
  456.         /* McBSP already configured by another stream */
  457.         return 0;
  458.     }
  459.  
  460.     format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
  461.     wpf = channels = params_channels(params);
  462.     if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
  463.                   format == SND_SOC_DAIFMT_LEFT_J)) {
  464.         /* Use dual-phase frames */
  465.         regs->rcr2  |= RPHASE;
  466.         regs->xcr2  |= XPHASE;
  467.         /* Set 1 word per (McBSP) frame for phase1 and phase2 */
  468.         wpf--;
  469.         regs->rcr2  |= RFRLEN2(wpf - 1);
  470.         regs->xcr2  |= XFRLEN2(wpf - 1);
  471.     }
  472.  
  473.     regs->rcr1  |= RFRLEN1(wpf - 1);
  474.     regs->xcr1  |= XFRLEN1(wpf - 1);
  475.  
  476.     switch (params_format(params)) {
  477.     case SNDRV_PCM_FORMAT_S16_LE:
  478.         /* Set word lengths */
  479.         regs->rcr2  |= RWDLEN2(OMAP_MCBSP_WORD_16);
  480.         regs->rcr1  |= RWDLEN1(OMAP_MCBSP_WORD_16);
  481.         regs->xcr2  |= XWDLEN2(OMAP_MCBSP_WORD_16);
  482.         regs->xcr1  |= XWDLEN1(OMAP_MCBSP_WORD_16);
  483.         break;
  484.     case SNDRV_PCM_FORMAT_S32_LE:
  485.         /* Set word lengths */
  486.         regs->rcr2  |= RWDLEN2(OMAP_MCBSP_WORD_32);
  487.         regs->rcr1  |= RWDLEN1(OMAP_MCBSP_WORD_32);
  488.         regs->xcr2  |= XWDLEN2(OMAP_MCBSP_WORD_32);
  489.         regs->xcr1  |= XWDLEN1(OMAP_MCBSP_WORD_32);
  490.         break;
  491.     default:
  492.         /* Unsupported PCM format */
  493.         return -EINVAL;
  494.     }
  495.  
  496.     /* In McBSP master modes, FRAME (i.e. sample rate) is generated
  497.      * by _counting_ BCLKs. Calculate frame size in BCLKs */
  498.     master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
  499.     if (master ==   SND_SOC_DAIFMT_CBS_CFS) {
  500.         div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
  501.         framesize = (mcbsp_data->in_freq / div) / params_rate(params);
  502.  
  503.         if (framesize < wlen * channels) {
  504.             printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
  505.                     "channels\n", __func__);
  506.             return -EINVAL;
  507.         }
  508.     } else
  509.         framesize = wlen * channels;
  510.  
  511.     /* Set FS period and length in terms of bit clock periods */
  512.     switch (format) {
  513.     case SND_SOC_DAIFMT_I2S:
  514.     case SND_SOC_DAIFMT_LEFT_J:
  515.         regs->srgr2 |= FPER(framesize - 1);
  516.         regs->srgr1 |= FWID((framesize >> 1) - 1);
  517.         break;
  518.     case SND_SOC_DAIFMT_DSP_A:
  519.     case SND_SOC_DAIFMT_DSP_B:
  520.         regs->srgr2 |= FPER(framesize - 1);
  521.         regs->srgr1 |= FWID(0);
  522.         break;
  523.     }
  524.  
  525.     omap_mcbsp_config(bus_id, &mcbsp_data->regs);
  526.     mcbsp_data->wlen = wlen;
  527.     mcbsp_data->configured = 1;
  528.  
  529.     return 0;
  530. }
  531.  
  532. /*
  533.  * This must be called before _set_clkdiv and _set_sysclk since McBSP register
  534.  * cache is initialized here
  535.  */
  536. static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
  537.                       unsigned int fmt)
  538. {
  539.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  540.     struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
  541.     unsigned int temp_fmt = fmt;
  542.  
  543.     if (mcbsp_data->configured)
  544.         return 0;
  545.  
  546.     mcbsp_data->fmt = fmt;
  547.     memset(regs, 0, sizeof(*regs));
  548.     /* Generic McBSP register settings */
  549.     regs->spcr2 |= XINTM(3) | FREE;
  550.     regs->spcr1 |= RINTM(3);
  551.     /* RFIG and XFIG are not defined in 34xx */
  552.     if (!cpu_is_omap34xx()) {
  553.         regs->rcr2  |= RFIG;
  554.         regs->xcr2  |= XFIG;
  555.     }
  556.     if (cpu_is_omap2430() || cpu_is_omap34xx()) {
  557.         regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
  558.         regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
  559.     }
  560.  
  561.     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  562.     case SND_SOC_DAIFMT_I2S:
  563.         /* 1-bit data delay */
  564.         regs->rcr2  |= RDATDLY(1);
  565.         regs->xcr2  |= XDATDLY(1);
  566.         break;
  567.     case SND_SOC_DAIFMT_LEFT_J:
  568.         /* 0-bit data delay */
  569.         regs->rcr2  |= RDATDLY(0);
  570.         regs->xcr2  |= XDATDLY(0);
  571.         regs->spcr1 |= RJUST(2);
  572.         /* Invert FS polarity configuration */
  573.         temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
  574.         break;
  575.     case SND_SOC_DAIFMT_DSP_A:
  576.         /* 1-bit data delay */
  577.         regs->rcr2      |= RDATDLY(1);
  578.         regs->xcr2      |= XDATDLY(1);
  579.         /* Invert FS polarity configuration */
  580.         temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
  581.         break;
  582.     case SND_SOC_DAIFMT_DSP_B:
  583.         /* 0-bit data delay */
  584.         regs->rcr2      |= RDATDLY(0);
  585.         regs->xcr2      |= XDATDLY(0);
  586.         /* Invert FS polarity configuration */
  587.         temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
  588.         break;
  589.     default:
  590.         /* Unsupported data format */
  591.         return -EINVAL;
  592.     }
  593.  
  594.     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  595.     case SND_SOC_DAIFMT_CBS_CFS:
  596.         /* McBSP master. Set FS and bit clocks as outputs */
  597.         regs->pcr0  |= FSXM | FSRM |
  598.                    CLKXM | CLKRM;
  599.         /* Sample rate generator drives the FS */
  600.         regs->srgr2 |= FSGM;
  601.         break;
  602.     case SND_SOC_DAIFMT_CBM_CFM:
  603.         /* McBSP slave */
  604.         break;
  605.     default:
  606.         /* Unsupported master/slave configuration */
  607.         return -EINVAL;
  608.     }
  609.  
  610.     /* Set bit clock (CLKX/CLKR) and FS polarities */
  611.     switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
  612.     case SND_SOC_DAIFMT_NB_NF:
  613.         /*
  614.          * Normal BCLK + FS.
  615.          * FS active low. TX data driven on falling edge of bit clock
  616.          * and RX data sampled on rising edge of bit clock.
  617.          */
  618.         regs->pcr0  |= FSXP | FSRP |
  619.                    CLKXP | CLKRP;
  620.         break;
  621.     case SND_SOC_DAIFMT_NB_IF:
  622.         regs->pcr0  |= CLKXP | CLKRP;
  623.         break;
  624.     case SND_SOC_DAIFMT_IB_NF:
  625.         regs->pcr0  |= FSXP | FSRP;
  626.         break;
  627.     case SND_SOC_DAIFMT_IB_IF:
  628.         break;
  629.     default:
  630.         return -EINVAL;
  631.     }
  632.  
  633.     return 0;
  634. }
  635.  
  636. static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
  637.                      int div_id, int div)
  638. {
  639.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  640.     struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
  641.  
  642.     if (div_id != OMAP_MCBSP_CLKGDV)
  643.         return -ENODEV;
  644.  
  645.     mcbsp_data->clk_div = div;
  646.     regs->srgr1 |= CLKGDV(div - 1);
  647.  
  648.     return 0;
  649. }
  650.  
  651. static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
  652.                        int clk_id)
  653. {
  654.     int sel_bit;
  655.     u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
  656.  
  657.     if (cpu_class_is_omap1()) {
  658.         /* OMAP1's can use only external source clock */
  659.         if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
  660.             return -EINVAL;
  661.         else
  662.             return 0;
  663.     }
  664.  
  665.     if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
  666.         return -EINVAL;
  667.  
  668.     if (cpu_is_omap343x())
  669.         reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
  670.  
  671.     switch (mcbsp_data->bus_id) {
  672.     case 0:
  673.         reg = OMAP2_CONTROL_DEVCONF0;
  674.         sel_bit = 2;
  675.         break;
  676.     case 1:
  677.         reg = OMAP2_CONTROL_DEVCONF0;
  678.         sel_bit = 6;
  679.         break;
  680.     case 2:
  681.         reg = reg_devconf1;
  682.         sel_bit = 0;
  683.         break;
  684.     case 3:
  685.         reg = reg_devconf1;
  686.         sel_bit = 2;
  687.         break;
  688.     case 4:
  689.         reg = reg_devconf1;
  690.         sel_bit = 4;
  691.         break;
  692.     default:
  693.         return -EINVAL;
  694.     }
  695.  
  696.     if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
  697.         omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
  698.     else
  699.         omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
  700.  
  701.     return 0;
  702. }
  703.  
  704. static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
  705.                        int clk_id)
  706. {
  707.     int sel_bit, set = 0;
  708.     u16 reg = OMAP2_CONTROL_DEVCONF0;
  709.  
  710.     if (cpu_class_is_omap1())
  711.         return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
  712.     if (mcbsp_data->bus_id != 0)
  713.         return -EINVAL;
  714.  
  715.     switch (clk_id) {
  716.     case OMAP_MCBSP_CLKR_SRC_CLKX:
  717.         set = 1;
  718.     case OMAP_MCBSP_CLKR_SRC_CLKR:
  719.         sel_bit = 3;
  720.         break;
  721.     case OMAP_MCBSP_FSR_SRC_FSX:
  722.         set = 1;
  723.     case OMAP_MCBSP_FSR_SRC_FSR:
  724.         sel_bit = 4;
  725.         break;
  726.     default:
  727.         return -EINVAL;
  728.     }
  729.  
  730.     if (set)
  731.         omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
  732.     else
  733.         omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
  734.  
  735.     return 0;
  736. }
  737.  
  738. static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
  739.                      int clk_id, unsigned int freq,
  740.                      int dir)
  741. {
  742.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  743.     struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
  744.     int err = 0;
  745.  
  746.     mcbsp_data->in_freq = freq;
  747.  
  748.     switch (clk_id) {
  749.     case OMAP_MCBSP_SYSCLK_CLK:
  750.         regs->srgr2 |= CLKSM;
  751.         break;
  752.     case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
  753.     case OMAP_MCBSP_SYSCLK_CLKS_EXT:
  754.         err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
  755.         break;
  756.  
  757.     case OMAP_MCBSP_SYSCLK_CLKX_EXT:
  758.         regs->srgr2 |= CLKSM;
  759.     case OMAP_MCBSP_SYSCLK_CLKR_EXT:
  760.         regs->pcr0  |= SCLKME;
  761.         break;
  762.  
  763.     case OMAP_MCBSP_CLKR_SRC_CLKR:
  764.     case OMAP_MCBSP_CLKR_SRC_CLKX:
  765.     case OMAP_MCBSP_FSR_SRC_FSR:
  766.     case OMAP_MCBSP_FSR_SRC_FSX:
  767.         err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
  768.         break;
  769.     default:
  770.         err = -ENODEV;
  771.     }
  772.  
  773.     return err;
  774. }
  775.  
  776. static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
  777.     .startup    = omap_mcbsp_dai_startup,
  778.     .shutdown   = omap_mcbsp_dai_shutdown,
  779.     .trigger    = omap_mcbsp_dai_trigger,
  780.     .delay      = omap_mcbsp_dai_delay,
  781.     .hw_params  = omap_mcbsp_dai_hw_params,
  782.     .set_fmt    = omap_mcbsp_dai_set_dai_fmt,
  783.     .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
  784.     .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
  785.     .request_power_level = omap_mcbsp_request_power_level,
  786. };
  787.  
  788. #define OMAP_MCBSP_DAI_BUILDER(link_id)             \
  789. {                               \
  790.     .name = "omap-mcbsp-dai-"#link_id,          \
  791.     .id = (link_id),                    \
  792.     .playback = {                       \
  793.         .channels_min = 1,              \
  794.         .channels_max = 16,             \
  795.         .rates = OMAP_MCBSP_RATES,          \
  796.         .formats = SNDRV_PCM_FMTBIT_S16_LE |        \
  797.                SNDRV_PCM_FMTBIT_S32_LE,     \
  798.     },                          \
  799.     .capture = {                        \
  800.         .channels_min = 1,              \
  801.         .channels_max = 16,             \
  802.         .rates = OMAP_MCBSP_RATES,          \
  803.         .formats = SNDRV_PCM_FMTBIT_S16_LE |        \
  804.                SNDRV_PCM_FMTBIT_S32_LE,     \
  805.     },                          \
  806.     .ops = &omap_mcbsp_dai_ops,             \
  807.     .private_data = &mcbsp_data[(link_id)].bus_id,      \
  808. }
  809.  
  810. struct snd_soc_dai omap_mcbsp_dai[] = {
  811.     OMAP_MCBSP_DAI_BUILDER(0),
  812.     OMAP_MCBSP_DAI_BUILDER(1),
  813. #if NUM_LINKS >= 3
  814.     OMAP_MCBSP_DAI_BUILDER(2),
  815. #endif
  816. #if NUM_LINKS == 5
  817.     OMAP_MCBSP_DAI_BUILDER(3),
  818.     OMAP_MCBSP_DAI_BUILDER(4),
  819. #endif
  820. };
  821.  
  822. EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
  823.  
  824. int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
  825.             struct snd_ctl_elem_info *uinfo)
  826. {
  827.     struct soc_mixer_control *mc =
  828.         (struct soc_mixer_control *)kcontrol->private_value;
  829.     int max = mc->max;
  830.     int min = mc->min;
  831.  
  832.     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  833.     uinfo->count = 1;
  834.     uinfo->value.integer.min = min;
  835.     uinfo->value.integer.max = max;
  836.     return 0;
  837. }
  838.  
  839. #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)           \
  840. static int                              \
  841. omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,   \
  842.                     struct snd_ctl_elem_value *uc)  \
  843. {                                   \
  844.     struct soc_mixer_control *mc =                  \
  845.         (struct soc_mixer_control *)kc->private_value;      \
  846.     int max = mc->max;                      \
  847.     int min = mc->min;                      \
  848.     int val = uc->value.integer.value[0];               \
  849.                                     \
  850.     if (val < min || val > max)                 \
  851.         return -EINVAL;                     \
  852.                                     \
  853.     /* OMAP McBSP implementation uses index values 0..4 */      \
  854.     return omap_st_set_chgain((id)-1, channel, val);        \
  855. }
  856.  
  857. #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)           \
  858. static int                              \
  859. omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,   \
  860.                     struct snd_ctl_elem_value *uc)  \
  861. {                                   \
  862.     s16 chgain;                         \
  863.                                     \
  864.     if (omap_st_get_chgain((id)-1, channel, &chgain))       \
  865.         return -EAGAIN;                     \
  866.                                     \
  867.     uc->value.integer.value[0] = chgain;                \
  868.     return 0;                           \
  869. }
  870.  
  871. OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
  872. OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
  873. OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
  874. OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
  875. OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
  876. OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
  877. OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
  878. OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
  879.  
  880. static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
  881.                 struct snd_ctl_elem_value *ucontrol)
  882. {
  883.     struct soc_mixer_control *mc =
  884.         (struct soc_mixer_control *)kcontrol->private_value;
  885.     u8 value = ucontrol->value.integer.value[0];
  886.  
  887.     if (value == omap_st_is_enabled(mc->reg))
  888.         return 0;
  889.  
  890.     if (value)
  891.         omap_st_enable(mc->reg);
  892.     else
  893.         omap_st_disable(mc->reg);
  894.  
  895.     return 1;
  896. }
  897.  
  898. static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
  899.                 struct snd_ctl_elem_value *ucontrol)
  900. {
  901.     struct soc_mixer_control *mc =
  902.         (struct soc_mixer_control *)kcontrol->private_value;
  903.  
  904.     ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
  905.     return 0;
  906. }
  907.  
  908. static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
  909.     SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
  910.             omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
  911.     OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
  912.                       -32768, 32767,
  913.                       omap_mcbsp2_get_st_ch0_volume,
  914.                       omap_mcbsp2_set_st_ch0_volume),
  915.     OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
  916.                       -32768, 32767,
  917.                       omap_mcbsp2_get_st_ch1_volume,
  918.                       omap_mcbsp2_set_st_ch1_volume),
  919. };
  920.  
  921. static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
  922.     SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
  923.             omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
  924.     OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
  925.                       -32768, 32767,
  926.                       omap_mcbsp3_get_st_ch0_volume,
  927.                       omap_mcbsp3_set_st_ch0_volume),
  928.     OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
  929.                       -32768, 32767,
  930.                       omap_mcbsp3_get_st_ch1_volume,
  931.                       omap_mcbsp3_set_st_ch1_volume),
  932. };
  933.  
  934. int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
  935. {
  936.     if (!cpu_is_omap34xx())
  937.         return -ENODEV;
  938.  
  939.     switch (mcbsp_id) {
  940.     case 1: /* McBSP 2 */
  941.         return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
  942.                     ARRAY_SIZE(omap_mcbsp2_st_controls));
  943.     case 2: /* McBSP 3 */
  944.         return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
  945.                     ARRAY_SIZE(omap_mcbsp3_st_controls));
  946.     default:
  947.         break;
  948.     }
  949.  
  950.     return -EINVAL;
  951. }
  952. EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
  953.  
  954. int omap_mcbsp_set_threshold_func(struct snd_soc_dai *cpu_dai,
  955.         void (*mach_set_threshold)(struct snd_pcm_substream *substream))
  956. {
  957.     struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
  958.  
  959.     if (!cpu_is_omap34xx())
  960.         return -ENODEV;
  961.  
  962.     mcbsp_data->mach_set_threshold = mach_set_threshold;
  963.     return 0;
  964. }
  965. EXPORT_SYMBOL_GPL(omap_mcbsp_set_threshold_func);
  966.  
  967. static int __init snd_omap_mcbsp_init(void)
  968. {
  969.     return snd_soc_register_dais(omap_mcbsp_dai,
  970.                      ARRAY_SIZE(omap_mcbsp_dai));
  971. }
  972. module_init(snd_omap_mcbsp_init);
  973.  
  974. static void __exit snd_omap_mcbsp_exit(void)
  975. {
  976.     snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
  977. }
  978. module_exit(snd_omap_mcbsp_exit);
  979.  
  980. MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
  981. MODULE_DESCRIPTION("OMAP I2S SoC Interface");
  982. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement