diff options
-rw-r--r-- | include/sound/tlv320dac33-plat.h | 2 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 125 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 137 |
4 files changed, 158 insertions, 108 deletions
diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h index 3f428d53195b..6c6649656798 100644 --- a/include/sound/tlv320dac33-plat.h +++ b/include/sound/tlv320dac33-plat.h | |||
@@ -15,6 +15,8 @@ | |||
15 | 15 | ||
16 | struct tlv320dac33_platform_data { | 16 | struct tlv320dac33_platform_data { |
17 | int power_gpio; | 17 | int power_gpio; |
18 | int mode1_latency; /* latency caused by the i2c writes in us */ | ||
19 | int auto_fifo_config; /* FIFO config based on the period size */ | ||
18 | int keep_bclk; /* Keep the BCLK running in FIFO modes */ | 20 | int keep_bclk; /* Keep the BCLK running in FIFO modes */ |
19 | u8 burst_bclkdiv; | 21 | u8 burst_bclkdiv; |
20 | }; | 22 | }; |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 2fa946ce23a2..8651b01ed223 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -49,8 +49,6 @@ | |||
49 | 49 | ||
50 | #define NSAMPLE_MAX 5700 | 50 | #define NSAMPLE_MAX 5700 |
51 | 51 | ||
52 | #define LATENCY_TIME_MS 20 | ||
53 | |||
54 | #define MODE7_LTHR 10 | 52 | #define MODE7_LTHR 10 |
55 | #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) | 53 | #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) |
56 | 54 | ||
@@ -62,6 +60,9 @@ | |||
62 | #define US_TO_SAMPLES(rate, us) \ | 60 | #define US_TO_SAMPLES(rate, us) \ |
63 | (rate / (1000000 / us)) | 61 | (rate / (1000000 / us)) |
64 | 62 | ||
63 | #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ | ||
64 | ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) | ||
65 | |||
65 | static void dac33_calculate_times(struct snd_pcm_substream *substream); | 66 | static void dac33_calculate_times(struct snd_pcm_substream *substream); |
66 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); | 67 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); |
67 | 68 | ||
@@ -107,6 +108,10 @@ struct tlv320dac33_priv { | |||
107 | * this */ | 108 | * this */ |
108 | enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ | 109 | enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ |
109 | unsigned int nsample; /* burst read amount from host */ | 110 | unsigned int nsample; /* burst read amount from host */ |
111 | int mode1_latency; /* latency caused by the i2c writes in | ||
112 | * us */ | ||
113 | int auto_fifo_config; /* Configure the FIFO based on the | ||
114 | * period size */ | ||
110 | u8 burst_bclkdiv; /* BCLK divider value in burst mode */ | 115 | u8 burst_bclkdiv; /* BCLK divider value in burst mode */ |
111 | unsigned int burst_rate; /* Interface speed in Burst modes */ | 116 | unsigned int burst_rate; /* Interface speed in Burst modes */ |
112 | 117 | ||
@@ -538,13 +543,16 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = { | |||
538 | DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), | 543 | DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), |
539 | }; | 544 | }; |
540 | 545 | ||
541 | static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { | 546 | static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { |
547 | SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, | ||
548 | dac33_get_fifo_mode, dac33_set_fifo_mode), | ||
549 | }; | ||
550 | |||
551 | static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = { | ||
542 | SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, | 552 | SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, |
543 | dac33_get_nsample, dac33_set_nsample), | 553 | dac33_get_nsample, dac33_set_nsample), |
544 | SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, | 554 | SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, |
545 | dac33_get_uthr, dac33_set_uthr), | 555 | dac33_get_uthr, dac33_set_uthr), |
546 | SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, | ||
547 | dac33_get_fifo_mode, dac33_set_fifo_mode), | ||
548 | }; | 556 | }; |
549 | 557 | ||
550 | /* Analog bypass */ | 558 | /* Analog bypass */ |
@@ -649,7 +657,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | |||
649 | switch (dac33->fifo_mode) { | 657 | switch (dac33->fifo_mode) { |
650 | case DAC33_FIFO_MODE1: | 658 | case DAC33_FIFO_MODE1: |
651 | dac33_write16(codec, DAC33_NSAMPLE_MSB, | 659 | dac33_write16(codec, DAC33_NSAMPLE_MSB, |
652 | DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); | 660 | DAC33_THRREG(dac33->nsample)); |
653 | 661 | ||
654 | /* Take the timestamps */ | 662 | /* Take the timestamps */ |
655 | spin_lock_irq(&dac33->lock); | 663 | spin_lock_irq(&dac33->lock); |
@@ -798,6 +806,10 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, | |||
798 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 806 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
799 | 807 | ||
800 | dac33->substream = NULL; | 808 | dac33->substream = NULL; |
809 | |||
810 | /* Reset the nSample restrictions */ | ||
811 | dac33->nsample_min = 0; | ||
812 | dac33->nsample_max = NSAMPLE_MAX; | ||
801 | } | 813 | } |
802 | 814 | ||
803 | static int dac33_hw_params(struct snd_pcm_substream *substream, | 815 | static int dac33_hw_params(struct snd_pcm_substream *substream, |
@@ -1040,54 +1052,68 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) | |||
1040 | struct snd_soc_device *socdev = rtd->socdev; | 1052 | struct snd_soc_device *socdev = rtd->socdev; |
1041 | struct snd_soc_codec *codec = socdev->card->codec; | 1053 | struct snd_soc_codec *codec = socdev->card->codec; |
1042 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1054 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1055 | unsigned int period_size = substream->runtime->period_size; | ||
1056 | unsigned int rate = substream->runtime->rate; | ||
1043 | unsigned int nsample_limit; | 1057 | unsigned int nsample_limit; |
1044 | 1058 | ||
1045 | /* In bypass mode we don't need to calculate */ | 1059 | /* In bypass mode we don't need to calculate */ |
1046 | if (!dac33->fifo_mode) | 1060 | if (!dac33->fifo_mode) |
1047 | return; | 1061 | return; |
1048 | 1062 | ||
1049 | /* Number of samples (16bit, stereo) in one period */ | ||
1050 | dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4; | ||
1051 | |||
1052 | /* Number of samples (16bit, stereo) in ALSA buffer */ | ||
1053 | dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4; | ||
1054 | /* Subtract one period from the total */ | ||
1055 | dac33->nsample_max -= dac33->nsample_min; | ||
1056 | |||
1057 | /* Number of samples for LATENCY_TIME_MS / 2 */ | ||
1058 | dac33->alarm_threshold = substream->runtime->rate / | ||
1059 | (1000 / (LATENCY_TIME_MS / 2)); | ||
1060 | |||
1061 | /* Find and fix up the lowest nsmaple limit */ | ||
1062 | nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS); | ||
1063 | |||
1064 | if (dac33->nsample_min < nsample_limit) | ||
1065 | dac33->nsample_min = nsample_limit; | ||
1066 | |||
1067 | if (dac33->nsample < dac33->nsample_min) | ||
1068 | dac33->nsample = dac33->nsample_min; | ||
1069 | |||
1070 | /* | ||
1071 | * Find and fix up the highest nsmaple limit | ||
1072 | * In order to not overflow the DAC33 buffer substract the | ||
1073 | * alarm_threshold value from the size of the DAC33 buffer | ||
1074 | */ | ||
1075 | nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; | ||
1076 | |||
1077 | if (dac33->nsample_max > nsample_limit) | ||
1078 | dac33->nsample_max = nsample_limit; | ||
1079 | |||
1080 | if (dac33->nsample > dac33->nsample_max) | ||
1081 | dac33->nsample = dac33->nsample_max; | ||
1082 | |||
1083 | switch (dac33->fifo_mode) { | 1063 | switch (dac33->fifo_mode) { |
1084 | case DAC33_FIFO_MODE1: | 1064 | case DAC33_FIFO_MODE1: |
1065 | /* Number of samples under i2c latency */ | ||
1066 | dac33->alarm_threshold = US_TO_SAMPLES(rate, | ||
1067 | dac33->mode1_latency); | ||
1068 | if (dac33->auto_fifo_config) { | ||
1069 | if (period_size <= dac33->alarm_threshold) | ||
1070 | /* | ||
1071 | * Configure nSamaple to number of periods, | ||
1072 | * which covers the latency requironment. | ||
1073 | */ | ||
1074 | dac33->nsample = period_size * | ||
1075 | ((dac33->alarm_threshold / period_size) + | ||
1076 | (dac33->alarm_threshold % period_size ? | ||
1077 | 1 : 0)); | ||
1078 | else | ||
1079 | dac33->nsample = period_size; | ||
1080 | } else { | ||
1081 | /* nSample time shall not be shorter than i2c latency */ | ||
1082 | dac33->nsample_min = dac33->alarm_threshold; | ||
1083 | /* | ||
1084 | * nSample should not be bigger than alsa buffer minus | ||
1085 | * size of one period to avoid overruns | ||
1086 | */ | ||
1087 | dac33->nsample_max = substream->runtime->buffer_size - | ||
1088 | period_size; | ||
1089 | nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - | ||
1090 | dac33->alarm_threshold; | ||
1091 | if (dac33->nsample_max > nsample_limit) | ||
1092 | dac33->nsample_max = nsample_limit; | ||
1093 | |||
1094 | /* Correct the nSample if it is outside of the ranges */ | ||
1095 | if (dac33->nsample < dac33->nsample_min) | ||
1096 | dac33->nsample = dac33->nsample_min; | ||
1097 | if (dac33->nsample > dac33->nsample_max) | ||
1098 | dac33->nsample = dac33->nsample_max; | ||
1099 | } | ||
1100 | |||
1085 | dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, | 1101 | dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, |
1086 | dac33->nsample); | 1102 | dac33->nsample); |
1087 | dac33->t_stamp1 = 0; | 1103 | dac33->t_stamp1 = 0; |
1088 | dac33->t_stamp2 = 0; | 1104 | dac33->t_stamp2 = 0; |
1089 | break; | 1105 | break; |
1090 | case DAC33_FIFO_MODE7: | 1106 | case DAC33_FIFO_MODE7: |
1107 | if (dac33->auto_fifo_config) { | ||
1108 | dac33->uthr = UTHR_FROM_PERIOD_SIZE( | ||
1109 | period_size, | ||
1110 | rate, | ||
1111 | dac33->burst_rate) + 9; | ||
1112 | if (dac33->uthr > MODE7_UTHR) | ||
1113 | dac33->uthr = MODE7_UTHR; | ||
1114 | if (dac33->uthr < (MODE7_LTHR + 10)) | ||
1115 | dac33->uthr = (MODE7_LTHR + 10); | ||
1116 | } | ||
1091 | dac33->mode7_us_to_lthr = | 1117 | dac33->mode7_us_to_lthr = |
1092 | SAMPLES_TO_US(substream->runtime->rate, | 1118 | SAMPLES_TO_US(substream->runtime->rate, |
1093 | dac33->uthr - MODE7_LTHR + 1); | 1119 | dac33->uthr - MODE7_LTHR + 1); |
@@ -1385,10 +1411,15 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1385 | 1411 | ||
1386 | snd_soc_add_controls(codec, dac33_snd_controls, | 1412 | snd_soc_add_controls(codec, dac33_snd_controls, |
1387 | ARRAY_SIZE(dac33_snd_controls)); | 1413 | ARRAY_SIZE(dac33_snd_controls)); |
1388 | /* Only add the nSample controls, if we have valid IRQ number */ | 1414 | /* Only add the FIFO controls, if we have valid IRQ number */ |
1389 | if (dac33->irq >= 0) | 1415 | if (dac33->irq >= 0) { |
1390 | snd_soc_add_controls(codec, dac33_nsample_snd_controls, | 1416 | snd_soc_add_controls(codec, dac33_mode_snd_controls, |
1391 | ARRAY_SIZE(dac33_nsample_snd_controls)); | 1417 | ARRAY_SIZE(dac33_mode_snd_controls)); |
1418 | /* FIFO usage controls only, if autoio config is not selected */ | ||
1419 | if (!dac33->auto_fifo_config) | ||
1420 | snd_soc_add_controls(codec, dac33_fifo_snd_controls, | ||
1421 | ARRAY_SIZE(dac33_fifo_snd_controls)); | ||
1422 | } | ||
1392 | 1423 | ||
1393 | dac33_add_widgets(codec); | 1424 | dac33_add_widgets(codec); |
1394 | 1425 | ||
@@ -1519,6 +1550,10 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1519 | /* Pre calculate the burst rate */ | 1550 | /* Pre calculate the burst rate */ |
1520 | dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; | 1551 | dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; |
1521 | dac33->keep_bclk = pdata->keep_bclk; | 1552 | dac33->keep_bclk = pdata->keep_bclk; |
1553 | dac33->auto_fifo_config = pdata->auto_fifo_config; | ||
1554 | dac33->mode1_latency = pdata->mode1_latency; | ||
1555 | if (!dac33->mode1_latency) | ||
1556 | dac33->mode1_latency = 10000; /* 10ms */ | ||
1522 | dac33->irq = client->irq; | 1557 | dac33->irq = client->irq; |
1523 | dac33->nsample = NSAMPLE_MAX; | 1558 | dac33->nsample = NSAMPLE_MAX; |
1524 | dac33->nsample_max = NSAMPLE_MAX; | 1559 | dac33->nsample_max = NSAMPLE_MAX; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index bd557c2bcb8c..d401c597d38f 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -1432,11 +1432,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1432 | TX2 Left/Right: either analog Left/Right or Digimic1 */ | 1432 | TX2 Left/Right: either analog Left/Right or Digimic1 */ |
1433 | SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0, | 1433 | SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0, |
1434 | &twl4030_dapm_micpathtx1_control, micpath_event, | 1434 | &twl4030_dapm_micpathtx1_control, micpath_event, |
1435 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| | ||
1436 | SND_SOC_DAPM_POST_REG), | 1435 | SND_SOC_DAPM_POST_REG), |
1437 | SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0, | 1436 | SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0, |
1438 | &twl4030_dapm_micpathtx2_control, micpath_event, | 1437 | &twl4030_dapm_micpathtx2_control, micpath_event, |
1439 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| | ||
1440 | SND_SOC_DAPM_POST_REG), | 1438 | SND_SOC_DAPM_POST_REG), |
1441 | 1439 | ||
1442 | /* Analog input mixers for the capture amplifiers */ | 1440 | /* Analog input mixers for the capture amplifiers */ |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index aebd3af2ab79..86f213905e2c 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -155,13 +155,23 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | |||
155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
156 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 156 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
157 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 157 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
158 | struct omap_pcm_dma_data *dma_data; | ||
158 | int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); | 159 | int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); |
159 | int words; | 160 | int words; |
160 | 161 | ||
162 | dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | ||
163 | |||
161 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ | 164 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ |
162 | if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) | 165 | if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) |
163 | /* The FIFO size depends on the McBSP word configuration */ | 166 | /* |
164 | words = snd_pcm_lib_period_bytes(substream) / | 167 | * Configure McBSP threshold based on either: |
168 | * packet_size, when the sDMA is in packet mode, or | ||
169 | * based on the period size. | ||
170 | */ | ||
171 | if (dma_data->packet_size) | ||
172 | words = dma_data->packet_size; | ||
173 | else | ||
174 | words = snd_pcm_lib_period_bytes(substream) / | ||
165 | (mcbsp_data->wlen / 8); | 175 | (mcbsp_data->wlen / 8); |
166 | else | 176 | else |
167 | words = 1; | 177 | words = 1; |
@@ -192,31 +202,6 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, | |||
192 | return snd_interval_refine(buffer_size, &frames); | 202 | return snd_interval_refine(buffer_size, &frames); |
193 | } | 203 | } |
194 | 204 | ||
195 | static int omap_mcbsp_hwrule_max_periodsize(struct snd_pcm_hw_params *params, | ||
196 | struct snd_pcm_hw_rule *rule) | ||
197 | { | ||
198 | struct snd_interval *period_size = hw_param_interval(params, | ||
199 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | ||
200 | struct snd_interval *channels = hw_param_interval(params, | ||
201 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
202 | struct snd_pcm_substream *substream = rule->private; | ||
203 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
204 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
205 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
206 | struct snd_interval frames; | ||
207 | int size; | ||
208 | |||
209 | snd_interval_any(&frames); | ||
210 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
211 | size = omap_mcbsp_get_max_tx_threshold(mcbsp_data->bus_id); | ||
212 | else | ||
213 | size = omap_mcbsp_get_max_rx_threshold(mcbsp_data->bus_id); | ||
214 | |||
215 | frames.max = size / channels->min; | ||
216 | frames.integer = 1; | ||
217 | return snd_interval_refine(period_size, &frames); | ||
218 | } | ||
219 | |||
220 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | 205 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, |
221 | struct snd_soc_dai *dai) | 206 | struct snd_soc_dai *dai) |
222 | { | 207 | { |
@@ -245,10 +230,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
245 | * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) | 230 | * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) |
246 | */ | 231 | */ |
247 | if (cpu_is_omap343x()) { | 232 | if (cpu_is_omap343x()) { |
248 | int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); | ||
249 | |||
250 | /* | 233 | /* |
251 | * The first rule is for the buffer size, we should not allow | 234 | * Rule for the buffer size. We should not allow |
252 | * smaller buffer than the FIFO size to avoid underruns | 235 | * smaller buffer than the FIFO size to avoid underruns |
253 | */ | 236 | */ |
254 | snd_pcm_hw_rule_add(substream->runtime, 0, | 237 | snd_pcm_hw_rule_add(substream->runtime, 0, |
@@ -257,17 +240,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
257 | mcbsp_data, | 240 | mcbsp_data, |
258 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); | 241 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); |
259 | 242 | ||
260 | /* | 243 | /* Make sure, that the period size is always even */ |
261 | * In case of threshold mode, the rule will ensure, that the | 244 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
262 | * period size is not bigger than the maximum allowed threshold | 245 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); |
263 | * value. | ||
264 | */ | ||
265 | if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) | ||
266 | snd_pcm_hw_rule_add(substream->runtime, 0, | ||
267 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
268 | omap_mcbsp_hwrule_max_periodsize, | ||
269 | substream, | ||
270 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); | ||
271 | } | 246 | } |
272 | 247 | ||
273 | return err; | 248 | return err; |
@@ -348,11 +323,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
348 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 323 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
349 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 324 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
350 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 325 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
351 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; | 326 | struct omap_pcm_dma_data *dma_data; |
327 | int dma, bus_id = mcbsp_data->bus_id; | ||
352 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; | 328 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; |
329 | int pkt_size = 0; | ||
353 | unsigned long port; | 330 | unsigned long port; |
354 | unsigned int format, div, framesize, master; | 331 | unsigned int format, div, framesize, master; |
355 | 332 | ||
333 | dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; | ||
356 | if (cpu_class_is_omap1()) { | 334 | if (cpu_class_is_omap1()) { |
357 | dma = omap1_dma_reqs[bus_id][substream->stream]; | 335 | dma = omap1_dma_reqs[bus_id][substream->stream]; |
358 | port = omap1_mcbsp_port[bus_id][substream->stream]; | 336 | port = omap1_mcbsp_port[bus_id][substream->stream]; |
@@ -365,35 +343,74 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
365 | } else if (cpu_is_omap343x()) { | 343 | } else if (cpu_is_omap343x()) { |
366 | dma = omap24xx_dma_reqs[bus_id][substream->stream]; | 344 | dma = omap24xx_dma_reqs[bus_id][substream->stream]; |
367 | port = omap34xx_mcbsp_port[bus_id][substream->stream]; | 345 | port = omap34xx_mcbsp_port[bus_id][substream->stream]; |
368 | omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = | ||
369 | omap_mcbsp_set_threshold; | ||
370 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ | ||
371 | if (omap_mcbsp_get_dma_op_mode(bus_id) == | ||
372 | MCBSP_DMA_MODE_THRESHOLD) | ||
373 | sync_mode = OMAP_DMA_SYNC_FRAME; | ||
374 | } else { | 346 | } else { |
375 | return -ENODEV; | 347 | return -ENODEV; |
376 | } | 348 | } |
377 | omap_mcbsp_dai_dma_params[id][substream->stream].name = | ||
378 | substream->stream ? "Audio Capture" : "Audio Playback"; | ||
379 | omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; | ||
380 | omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; | ||
381 | omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; | ||
382 | switch (params_format(params)) { | 349 | switch (params_format(params)) { |
383 | case SNDRV_PCM_FORMAT_S16_LE: | 350 | case SNDRV_PCM_FORMAT_S16_LE: |
384 | omap_mcbsp_dai_dma_params[id][substream->stream].data_type = | 351 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; |
385 | OMAP_DMA_DATA_TYPE_S16; | 352 | wlen = 16; |
386 | break; | 353 | break; |
387 | case SNDRV_PCM_FORMAT_S32_LE: | 354 | case SNDRV_PCM_FORMAT_S32_LE: |
388 | omap_mcbsp_dai_dma_params[id][substream->stream].data_type = | 355 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; |
389 | OMAP_DMA_DATA_TYPE_S32; | 356 | wlen = 32; |
390 | break; | 357 | break; |
391 | default: | 358 | default: |
392 | return -EINVAL; | 359 | return -EINVAL; |
393 | } | 360 | } |
361 | if (cpu_is_omap343x()) { | ||
362 | dma_data->set_threshold = omap_mcbsp_set_threshold; | ||
363 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ | ||
364 | if (omap_mcbsp_get_dma_op_mode(bus_id) == | ||
365 | MCBSP_DMA_MODE_THRESHOLD) { | ||
366 | int period_words, max_thrsh; | ||
367 | |||
368 | period_words = params_period_bytes(params) / (wlen / 8); | ||
369 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
370 | max_thrsh = omap_mcbsp_get_max_tx_threshold( | ||
371 | mcbsp_data->bus_id); | ||
372 | else | ||
373 | max_thrsh = omap_mcbsp_get_max_rx_threshold( | ||
374 | mcbsp_data->bus_id); | ||
375 | /* | ||
376 | * If the period contains less or equal number of words, | ||
377 | * we are using the original threshold mode setup: | ||
378 | * McBSP threshold = sDMA frame size = period_size | ||
379 | * Otherwise we switch to sDMA packet mode: | ||
380 | * McBSP threshold = sDMA packet size | ||
381 | * sDMA frame size = period size | ||
382 | */ | ||
383 | if (period_words > max_thrsh) { | ||
384 | int divider = 0; | ||
385 | |||
386 | /* | ||
387 | * Look for the biggest threshold value, which | ||
388 | * divides the period size evenly. | ||
389 | */ | ||
390 | divider = period_words / max_thrsh; | ||
391 | if (period_words % max_thrsh) | ||
392 | divider++; | ||
393 | while (period_words % divider && | ||
394 | divider < period_words) | ||
395 | divider++; | ||
396 | if (divider == period_words) | ||
397 | return -EINVAL; | ||
398 | |||
399 | pkt_size = period_words / divider; | ||
400 | sync_mode = OMAP_DMA_SYNC_PACKET; | ||
401 | } else { | ||
402 | sync_mode = OMAP_DMA_SYNC_FRAME; | ||
403 | } | ||
404 | } | ||
405 | } | ||
406 | |||
407 | dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; | ||
408 | dma_data->dma_req = dma; | ||
409 | dma_data->port_addr = port; | ||
410 | dma_data->sync_mode = sync_mode; | ||
411 | dma_data->packet_size = pkt_size; | ||
394 | 412 | ||
395 | snd_soc_dai_set_dma_data(cpu_dai, substream, | 413 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); |
396 | &omap_mcbsp_dai_dma_params[id][substream->stream]); | ||
397 | 414 | ||
398 | if (mcbsp_data->configured) { | 415 | if (mcbsp_data->configured) { |
399 | /* McBSP already configured by another stream */ | 416 | /* McBSP already configured by another stream */ |
@@ -419,7 +436,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
419 | switch (params_format(params)) { | 436 | switch (params_format(params)) { |
420 | case SNDRV_PCM_FORMAT_S16_LE: | 437 | case SNDRV_PCM_FORMAT_S16_LE: |
421 | /* Set word lengths */ | 438 | /* Set word lengths */ |
422 | wlen = 16; | ||
423 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); | 439 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); |
424 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); | 440 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); |
425 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); | 441 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); |
@@ -427,7 +443,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
427 | break; | 443 | break; |
428 | case SNDRV_PCM_FORMAT_S32_LE: | 444 | case SNDRV_PCM_FORMAT_S32_LE: |
429 | /* Set word lengths */ | 445 | /* Set word lengths */ |
430 | wlen = 32; | ||
431 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); | 446 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); |
432 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); | 447 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); |
433 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); | 448 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); |