Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Peter Ujfalusi and committed by
Liam Girdwood
a577b318 f430a27f

+65 -26
+1
include/sound/tlv320dac33-plat.h
··· 16 16 struct tlv320dac33_platform_data { 17 17 int power_gpio; 18 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 20 int keep_bclk; /* Keep the BCLK running in FIFO modes */ 20 21 u8 burst_bclkdiv; 21 22 };
+64 -26
sound/soc/codecs/tlv320dac33.c
··· 60 60 #define US_TO_SAMPLES(rate, us) \ 61 61 (rate / (1000000 / us)) 62 62 63 + #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ 64 + ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) 65 + 63 66 static void dac33_calculate_times(struct snd_pcm_substream *substream); 64 67 static int dac33_prepare_chip(struct snd_pcm_substream *substream); 65 68 ··· 110 107 unsigned int nsample; /* burst read amount from host */ 111 108 int mode1_latency; /* latency caused by the i2c writes in 112 109 * us */ 110 + int auto_fifo_config; /* Configure the FIFO based on the 111 + * period size */ 113 112 u8 burst_bclkdiv; /* BCLK divider value in burst mode */ 114 113 unsigned int burst_rate; /* Interface speed in Burst modes */ 115 114 ··· 543 538 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), 544 539 }; 545 540 546 - static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { 547 - SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, 548 - dac33_get_nsample, dac33_set_nsample), 549 - SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, 550 - dac33_get_uthr, dac33_set_uthr), 541 + static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { 551 542 SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, 552 543 dac33_get_fifo_mode, dac33_set_fifo_mode), 544 + }; 545 + 546 + static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = { 547 + SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, 548 + dac33_get_nsample, dac33_set_nsample), 549 + SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, 550 + dac33_get_uthr, dac33_set_uthr), 553 551 }; 554 552 555 553 /* Analog bypass */ ··· 1065 1057 /* Number of samples under i2c latency */ 1066 1058 dac33->alarm_threshold = US_TO_SAMPLES(rate, 1067 1059 dac33->mode1_latency); 1068 - /* nSample time shall not be shorter than i2c latency */ 1069 - dac33->nsample_min = dac33->alarm_threshold; 1070 - /* 1071 - * nSample should not be bigger than alsa buffer minus 1072 - * size of one period to avoid overruns 1073 - */ 1074 - dac33->nsample_max = substream->runtime->buffer_size - 1075 - period_size; 1076 - nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - 1077 - dac33->alarm_threshold; 1078 - if (dac33->nsample_max > nsample_limit) 1079 - dac33->nsample_max = nsample_limit; 1060 + if (dac33->auto_fifo_config) { 1061 + if (period_size <= dac33->alarm_threshold) 1062 + /* 1063 + * Configure nSamaple to number of periods, 1064 + * which covers the latency requironment. 1065 + */ 1066 + dac33->nsample = period_size * 1067 + ((dac33->alarm_threshold / period_size) + 1068 + (dac33->alarm_threshold % period_size ? 1069 + 1 : 0)); 1070 + else 1071 + dac33->nsample = period_size; 1072 + } else { 1073 + /* nSample time shall not be shorter than i2c latency */ 1074 + dac33->nsample_min = dac33->alarm_threshold; 1075 + /* 1076 + * nSample should not be bigger than alsa buffer minus 1077 + * size of one period to avoid overruns 1078 + */ 1079 + dac33->nsample_max = substream->runtime->buffer_size - 1080 + period_size; 1081 + nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - 1082 + dac33->alarm_threshold; 1083 + if (dac33->nsample_max > nsample_limit) 1084 + dac33->nsample_max = nsample_limit; 1080 1085 1081 - /* Correct the nSample if it is outside of the ranges */ 1082 - if (dac33->nsample < dac33->nsample_min) 1083 - dac33->nsample = dac33->nsample_min; 1084 - if (dac33->nsample > dac33->nsample_max) 1085 - dac33->nsample = dac33->nsample_max; 1086 + /* Correct the nSample if it is outside of the ranges */ 1087 + if (dac33->nsample < dac33->nsample_min) 1088 + dac33->nsample = dac33->nsample_min; 1089 + if (dac33->nsample > dac33->nsample_max) 1090 + dac33->nsample = dac33->nsample_max; 1091 + } 1086 1092 1087 1093 dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, 1088 1094 dac33->nsample); ··· 1104 1082 dac33->t_stamp2 = 0; 1105 1083 break; 1106 1084 case DAC33_FIFO_MODE7: 1085 + if (dac33->auto_fifo_config) { 1086 + dac33->uthr = UTHR_FROM_PERIOD_SIZE( 1087 + period_size, 1088 + rate, 1089 + dac33->burst_rate) + 9; 1090 + if (dac33->uthr > MODE7_UTHR) 1091 + dac33->uthr = MODE7_UTHR; 1092 + if (dac33->uthr < (MODE7_LTHR + 10)) 1093 + dac33->uthr = (MODE7_LTHR + 10); 1094 + } 1107 1095 dac33->mode7_us_to_lthr = 1108 1096 SAMPLES_TO_US(substream->runtime->rate, 1109 1097 dac33->uthr - MODE7_LTHR + 1); ··· 1411 1379 1412 1380 snd_soc_add_controls(codec, dac33_snd_controls, 1413 1381 ARRAY_SIZE(dac33_snd_controls)); 1414 - /* Only add the nSample controls, if we have valid IRQ number */ 1415 - if (dac33->irq >= 0) 1416 - snd_soc_add_controls(codec, dac33_nsample_snd_controls, 1417 - ARRAY_SIZE(dac33_nsample_snd_controls)); 1382 + /* Only add the FIFO controls, if we have valid IRQ number */ 1383 + if (dac33->irq >= 0) { 1384 + snd_soc_add_controls(codec, dac33_mode_snd_controls, 1385 + ARRAY_SIZE(dac33_mode_snd_controls)); 1386 + /* FIFO usage controls only, if autoio config is not selected */ 1387 + if (!dac33->auto_fifo_config) 1388 + snd_soc_add_controls(codec, dac33_fifo_snd_controls, 1389 + ARRAY_SIZE(dac33_fifo_snd_controls)); 1390 + } 1418 1391 1419 1392 dac33_add_widgets(codec); 1420 1393 ··· 1550 1513 /* Pre calculate the burst rate */ 1551 1514 dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; 1552 1515 dac33->keep_bclk = pdata->keep_bclk; 1516 + dac33->auto_fifo_config = pdata->auto_fifo_config; 1553 1517 dac33->mode1_latency = pdata->mode1_latency; 1554 1518 if (!dac33->mode1_latency) 1555 1519 dac33->mode1_latency = 10000; /* 10ms */