aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@nokia.com>2010-07-28 08:26:55 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-07-29 05:21:11 -0400
commita577b318fc7cb0c46f9f0cdefb5b267490ff8ce5 (patch)
tree6e2dc8b7f900743cf5cf2b23fa89b34480cec3f8
parentf430a27f05d42d26d3e438aa262a92565170573f (diff)
ASoC: tlv320dac33: Add support for automatic FIFO configuration
Platform parameter to enable automatic FIFO configuration when the codec is in Mode1 or Mode7 FIFO mode. When this mode is selected, the controls for changing nSample (in Mode1), and UTHR (in Mode7) are not added. The driver configures the FIFO configuration based on the stream's period size in a way, that every burst will read period size of data from the host. In Mode7 we need to use a formula, which gives close enough aproximation for the burst length from the host point of view. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
-rw-r--r--include/sound/tlv320dac33-plat.h1
-rw-r--r--sound/soc/codecs/tlv320dac33.c90
2 files changed, 65 insertions, 26 deletions
diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h
index 1aa7bdbc208c..6c6649656798 100644
--- a/include/sound/tlv320dac33-plat.h
+++ b/include/sound/tlv320dac33-plat.h
@@ -16,6 +16,7 @@
16struct tlv320dac33_platform_data { 16struct tlv320dac33_platform_data {
17 int power_gpio; 17 int power_gpio;
18 int mode1_latency; /* latency caused by the i2c writes in us */ 18 int mode1_latency; /* latency caused by the i2c writes in us */
19 int auto_fifo_config; /* FIFO config based on the period size */
19 int keep_bclk; /* Keep the BCLK running in FIFO modes */ 20 int keep_bclk; /* Keep the BCLK running in FIFO modes */
20 u8 burst_bclkdiv; 21 u8 burst_bclkdiv;
21}; 22};
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index ced6fbbc9d91..8651b01ed223 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -60,6 +60,9 @@
60#define US_TO_SAMPLES(rate, us) \ 60#define US_TO_SAMPLES(rate, us) \
61 (rate / (1000000 / us)) 61 (rate / (1000000 / us))
62 62
63#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
64 ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
65
63static void dac33_calculate_times(struct snd_pcm_substream *substream); 66static void dac33_calculate_times(struct snd_pcm_substream *substream);
64static int dac33_prepare_chip(struct snd_pcm_substream *substream); 67static int dac33_prepare_chip(struct snd_pcm_substream *substream);
65 68
@@ -107,6 +110,8 @@ struct tlv320dac33_priv {
107 unsigned int nsample; /* burst read amount from host */ 110 unsigned int nsample; /* burst read amount from host */
108 int mode1_latency; /* latency caused by the i2c writes in 111 int mode1_latency; /* latency caused by the i2c writes in
109 * us */ 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
541static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { 546static 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
551static 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 */
@@ -1057,24 +1065,38 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
1057 /* Number of samples under i2c latency */ 1065 /* Number of samples under i2c latency */
1058 dac33->alarm_threshold = US_TO_SAMPLES(rate, 1066 dac33->alarm_threshold = US_TO_SAMPLES(rate,
1059 dac33->mode1_latency); 1067 dac33->mode1_latency);
1060 /* nSample time shall not be shorter than i2c latency */ 1068 if (dac33->auto_fifo_config) {
1061 dac33->nsample_min = dac33->alarm_threshold; 1069 if (period_size <= dac33->alarm_threshold)
1062 /* 1070 /*
1063 * nSample should not be bigger than alsa buffer minus 1071 * Configure nSamaple to number of periods,
1064 * size of one period to avoid overruns 1072 * which covers the latency requironment.
1065 */ 1073 */
1066 dac33->nsample_max = substream->runtime->buffer_size - 1074 dac33->nsample = period_size *
1067 period_size; 1075 ((dac33->alarm_threshold / period_size) +
1068 nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - 1076 (dac33->alarm_threshold % period_size ?
1069 dac33->alarm_threshold; 1077 1 : 0));
1070 if (dac33->nsample_max > nsample_limit) 1078 else
1071 dac33->nsample_max = nsample_limit; 1079 dac33->nsample = period_size;
1072 1080 } else {
1073 /* Correct the nSample if it is outside of the ranges */ 1081 /* nSample time shall not be shorter than i2c latency */
1074 if (dac33->nsample < dac33->nsample_min) 1082 dac33->nsample_min = dac33->alarm_threshold;
1075 dac33->nsample = dac33->nsample_min; 1083 /*
1076 if (dac33->nsample > dac33->nsample_max) 1084 * nSample should not be bigger than alsa buffer minus
1077 dac33->nsample = dac33->nsample_max; 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 }
1078 1100
1079 dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, 1101 dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate,
1080 dac33->nsample); 1102 dac33->nsample);
@@ -1082,6 +1104,16 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
1082 dac33->t_stamp2 = 0; 1104 dac33->t_stamp2 = 0;
1083 break; 1105 break;
1084 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 }
1085 dac33->mode7_us_to_lthr = 1117 dac33->mode7_us_to_lthr =
1086 SAMPLES_TO_US(substream->runtime->rate, 1118 SAMPLES_TO_US(substream->runtime->rate,
1087 dac33->uthr - MODE7_LTHR + 1); 1119 dac33->uthr - MODE7_LTHR + 1);
@@ -1379,10 +1411,15 @@ static int dac33_soc_probe(struct platform_device *pdev)
1379 1411
1380 snd_soc_add_controls(codec, dac33_snd_controls, 1412 snd_soc_add_controls(codec, dac33_snd_controls,
1381 ARRAY_SIZE(dac33_snd_controls)); 1413 ARRAY_SIZE(dac33_snd_controls));
1382 /* Only add the nSample controls, if we have valid IRQ number */ 1414 /* Only add the FIFO controls, if we have valid IRQ number */
1383 if (dac33->irq >= 0) 1415 if (dac33->irq >= 0) {
1384 snd_soc_add_controls(codec, dac33_nsample_snd_controls, 1416 snd_soc_add_controls(codec, dac33_mode_snd_controls,
1385 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 }
1386 1423
1387 dac33_add_widgets(codec); 1424 dac33_add_widgets(codec);
1388 1425
@@ -1513,6 +1550,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1513 /* Pre calculate the burst rate */ 1550 /* Pre calculate the burst rate */
1514 dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; 1551 dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32;
1515 dac33->keep_bclk = pdata->keep_bclk; 1552 dac33->keep_bclk = pdata->keep_bclk;
1553 dac33->auto_fifo_config = pdata->auto_fifo_config;
1516 dac33->mode1_latency = pdata->mode1_latency; 1554 dac33->mode1_latency = pdata->mode1_latency;
1517 if (!dac33->mode1_latency) 1555 if (!dac33->mode1_latency)
1518 dac33->mode1_latency = 10000; /* 10ms */ 1556 dac33->mode1_latency = 10000; /* 10ms */