aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/davinci/davinci-mcasp.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index da38efba721..ef30dbdd7ae 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -25,6 +25,7 @@
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_platform.h> 26#include <linux/of_platform.h>
27#include <linux/of_device.h> 27#include <linux/of_device.h>
28#include <linux/lcm.h>
28 29
29#include <sound/core.h> 30#include <sound/core.h>
30#include <sound/pcm.h> 31#include <sound/pcm.h>
@@ -1042,14 +1043,92 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
1042 return ret; 1043 return ret;
1043} 1044}
1044 1045
1046static int davinci_mcasp_hwrule_buffersize(struct snd_pcm_hw_params *params,
1047 struct snd_pcm_hw_rule *rule,
1048 int stream)
1049{
1050 struct snd_interval *buffer_size = hw_param_interval(params,
1051 SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
1052 int channels = params_channels(params);
1053 int periods = params_periods(params);
1054 struct davinci_audio_dev *dev = rule->private;
1055 int i;
1056 u8 slots = dev->tdm_slots;
1057 u8 max_active_serializers = (channels + slots - 1) / slots;
1058 u8 num_ser = 0;
1059 u8 num_evt = 0;
1060 unsigned long step = 1;
1061
1062 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1063 for (i = 0; i < dev->num_serializer; i++) {
1064 if (dev->serial_dir[i] == TX_MODE &&
1065 num_ser < max_active_serializers)
1066 num_ser++;
1067 }
1068 num_evt = dev->txnumevt * num_ser;
1069 } else {
1070 for (i = 0; i < dev->num_serializer; i++) {
1071 if (dev->serial_dir[i] == RX_MODE &&
1072 num_ser < max_active_serializers)
1073 num_ser++;
1074 }
1075 num_evt = dev->rxnumevt * num_ser;
1076 }
1077
1078 /*
1079 * The buffersize (in samples), must be a multiple of num_evt. The
1080 * buffersize (in frames) is the product of the period_size and the
1081 * number of periods. Therefore, the buffersize should be a multiple
1082 * of the number of periods. The below finds the least common
1083 * multiple of num_evt and channels (since the number of samples
1084 * per frame is equal to the number of channels). It also makes sure
1085 * that the resulting step value (LCM / channels) is a multiple of the
1086 * number of periods.
1087 */
1088 step = lcm((lcm(num_evt, channels) / channels), periods);
1089
1090 return snd_interval_step(buffer_size, 0, step);
1091}
1092
1093static int davinci_mcasp_hwrule_txbuffersize(struct snd_pcm_hw_params *params,
1094 struct snd_pcm_hw_rule *rule)
1095{
1096 return davinci_mcasp_hwrule_buffersize(params, rule,
1097 SNDRV_PCM_STREAM_PLAYBACK);
1098}
1099
1100static int davinci_mcasp_hwrule_rxbuffersize(struct snd_pcm_hw_params *params,
1101 struct snd_pcm_hw_rule *rule)
1102{
1103 return davinci_mcasp_hwrule_buffersize(params, rule,
1104 SNDRV_PCM_STREAM_CAPTURE);
1105}
1106
1045static int davinci_mcasp_startup(struct snd_pcm_substream *substream, 1107static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
1046 struct snd_soc_dai *dai) 1108 struct snd_soc_dai *dai)
1047{ 1109{
1048 struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); 1110 struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
1049 1111
1050 if (dev->version == MCASP_VERSION_4) 1112
1113 if (dev->version == MCASP_VERSION_4) {
1051 snd_soc_dai_set_dma_data(dai, substream, 1114 snd_soc_dai_set_dma_data(dai, substream,
1052 dev->dma_params[substream->stream]); 1115 dev->dma_params[substream->stream]);
1116 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1117 if (dev->txnumevt)
1118 snd_pcm_hw_rule_add(substream->runtime, 0,
1119 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
1120 davinci_mcasp_hwrule_txbuffersize,
1121 dev,
1122 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
1123 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1124 if (dev->rxnumevt)
1125 snd_pcm_hw_rule_add(substream->runtime, 0,
1126 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
1127 davinci_mcasp_hwrule_rxbuffersize,
1128 dev,
1129 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
1130 }
1131 }
1053 else 1132 else
1054 snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); 1133 snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
1055 1134