[ALSA] pcm: add snd_pcm_rate_to_rate_bit() helper

Add a snd_pcm_rate_to_rate_bit() function to factor out common code used
by several drivers.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 2d5dee2..27f8ef4 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -925,6 +925,7 @@
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
 
 int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
 
 static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
 					      struct snd_dma_buffer *bufp)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index afd1e49..e5f25ae 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -450,3 +450,21 @@
 }
 
 EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
+
+/**
+ * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
+ * @rate: the sample rate to convert
+ *
+ * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
+ * SNDRV_PCM_RATE_KNOT for an unknown rate.
+ */
+unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
+{
+	unsigned int i;
+
+	for (i = 0; i < snd_pcm_known_rates.count; i++)
+		if (snd_pcm_known_rates.list[i] == rate)
+			return 1u << i;
+	return SNDRV_PCM_RATE_KNOT;
+}
+EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index f0e1298..85d50b6 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -340,28 +340,9 @@
 
 static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime)
 {
-	static struct {
-		int rate;
-		unsigned int bit;
-	} ratebits[] = {
-		{8000, SNDRV_PCM_RATE_8000},
-		{11025, SNDRV_PCM_RATE_11025},
-		{16000, SNDRV_PCM_RATE_16000},
-		{22050, SNDRV_PCM_RATE_22050},
-		{32000, SNDRV_PCM_RATE_32000},
-		{44100, SNDRV_PCM_RATE_44100},
-		{48000, SNDRV_PCM_RATE_48000}
-	};
-	int i;
-
 	chip->reg_control |= CTL_DA_IOM_DA;
 	runtime->hw = snd_bt87x_digital_hw;
-	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-	for (i = 0; i < ARRAY_SIZE(ratebits); ++i)
-		if (chip->dig_rate == ratebits[i].rate) {
-			runtime->hw.rates = ratebits[i].bit;
-			break;
-		}
+	runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->dig_rate);
 	runtime->hw.rate_min = chip->dig_rate;
 	runtime->hw.rate_max = chip->dig_rate;
 	return 0;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index ee0189b..1475912 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -258,19 +258,6 @@
 		& RME32_RCR_AUDIO_ADDR_MASK);
 }
 
-static int snd_rme32_ratecode(int rate)
-{
-	switch (rate) {
-	case 32000: return SNDRV_PCM_RATE_32000;
-	case 44100: return SNDRV_PCM_RATE_44100;
-	case 48000: return SNDRV_PCM_RATE_48000;
-	case 64000: return SNDRV_PCM_RATE_64000;
-	case 88200: return SNDRV_PCM_RATE_88200;
-	case 96000: return SNDRV_PCM_RATE_96000;
-	}
-	return 0;
-}
-
 /* silence callback for halfduplex mode */
 static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel,	/* not used (interleaved data) */
 				      snd_pcm_uframes_t pos,
@@ -887,7 +874,7 @@
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
 		/* AutoSync */
-		runtime->hw.rates = snd_rme32_ratecode(rate);
+		runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
 		runtime->hw.rate_min = rate;
 		runtime->hw.rate_max = rate;
 	}       
@@ -929,7 +916,7 @@
 		if (isadat) {
 			return -EIO;
 		}
-		runtime->hw.rates = snd_rme32_ratecode(rate);
+		runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
 		runtime->hw.rate_min = rate;
 		runtime->hw.rate_max = rate;
 	}
@@ -965,7 +952,7 @@
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
                 /* AutoSync */
-                runtime->hw.rates = snd_rme32_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
@@ -989,7 +976,7 @@
 		if (!isadat) {
 			return -EIO;
 		}
-                runtime->hw.rates = snd_rme32_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
         }
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index ba4a34b..0b3c532 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -301,20 +301,6 @@
 }
 
 static int
-snd_rme96_ratecode(int rate)
-{
-    switch (rate) {
-    case 32000: return SNDRV_PCM_RATE_32000;
-    case 44100: return SNDRV_PCM_RATE_44100;
-    case 48000: return SNDRV_PCM_RATE_48000;
-    case 64000: return SNDRV_PCM_RATE_64000;
-    case 88200: return SNDRV_PCM_RATE_88200;
-    case 96000: return SNDRV_PCM_RATE_96000;
-    }
-    return 0;
-}
-
-static int
 snd_rme96_playback_silence(struct snd_pcm_substream *substream,
 			   int channel, /* not used (interleaved data) */
 			   snd_pcm_uframes_t pos,
@@ -1192,7 +1178,7 @@
 	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
 	{
                 /* slave clock */
-                runtime->hw.rates = snd_rme96_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
@@ -1219,7 +1205,7 @@
                 if (isadat) {
                         return -EIO;
                 }
-                runtime->hw.rates = snd_rme96_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
         }
@@ -1259,7 +1245,7 @@
 	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
 	{
                 /* slave clock */
-                runtime->hw.rates = snd_rme96_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
@@ -1284,7 +1270,7 @@
                 if (!isadat) {
                         return -EIO;
                 }
-                runtime->hw.rates = snd_rme96_ratecode(rate);
+                runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
         }
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 04b95ae..4f9b19c 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -490,35 +490,14 @@
 			     struct snd_pcm_substream *subs)
 {
 	struct snd_pcm_runtime *runtime = subs->runtime;
-	int i, j, fflags;
-	static int typical_freqs[] = {
-		44100,
-		22050,
-		11025,
-		0,
-	};
-	static int typical_freq_flags[] = {
-		SNDRV_PCM_RATE_44100,
-		SNDRV_PCM_RATE_22050,
-		SNDRV_PCM_RATE_11025,
-		0,
-	};
+	int i;
 
 	/* look up frequency table and fill bit mask */
 	runtime->hw.rates = 0;
-	fflags = chip->freqs_ok;
-	for (i = 0; typical_freqs[i]; i++) {
-		for (j = 0; j < chip->num_freqs; j++) {
-			if ((chip->freqs_ok & (1 << j)) &&
-			    chip->freq_table[j] == typical_freqs[i]) {
-				runtime->hw.rates |= typical_freq_flags[i];
-				fflags &= ~(1 << j);
-				break;
-			}
-		}
-	}
-	if (fflags) /* rest */
-		runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
+	for (i = 0; i < chip->num_freqs; i++)
+		if (chip->freqs_ok & (1 << i))
+			runtime->hw.rates |=
+				snd_pcm_rate_to_rate_bit(chip->freq_table[i]);
 
 	/* check for minimum and maximum rates */
 	for (i = 0; i < chip->num_freqs; i++) {
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 8beae65..43d50a4 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -56,35 +56,6 @@
 	{64, 96, 128, 192, 256, 384, 512, 768, 1024};
 
 /*
- * Sampling rate <-> bit patter mapping
- *
- * This array maps sampling rates to their SNDRV_PCM_RATE_x equivalent.
- *
- * This is really something that ALSA should provide.
- *
- * This table is used by cs4270_set_dai_sysclk() to tell ALSA which sampling
- * rates the CS4270 currently supports.
- */
-static struct {
-	unsigned int rate;
-	unsigned int bit;
-} rate_map[] = {
-	{5512, SNDRV_PCM_RATE_5512},
-	{8000, SNDRV_PCM_RATE_8000},
-	{11025, SNDRV_PCM_RATE_11025},
-	{16000, SNDRV_PCM_RATE_16000},
-	{22050, SNDRV_PCM_RATE_22050},
-	{32000, SNDRV_PCM_RATE_32000},
-	{44100, SNDRV_PCM_RATE_44100},
-	{48000, SNDRV_PCM_RATE_48000},
-	{64000, SNDRV_PCM_RATE_64000},
-	{88200, SNDRV_PCM_RATE_88200},
-	{96000, SNDRV_PCM_RATE_96000},
-	{176400, SNDRV_PCM_RATE_176400},
-	{192000, SNDRV_PCM_RATE_192000}
-};
-
-/*
  * Determine the CS4270 samples rates.
  *
  * 'freq' is the input frequency to MCLK.  The other parameters are ignored.
@@ -126,19 +97,15 @@
 	cs4270->mclk = freq;
 
 	for (i = 0; i < NUM_MCLK_RATIOS; i++) {
-		unsigned int rate;
-		unsigned int j;
-		rate = freq / mclk_ratios[i];
-		for (j = 0; j < ARRAY_SIZE(rate_map); j++) {
-			if (rate == rate_map[j].rate) {
-				rates |= rate_map[j].bit;
-				if (rate < rate_min)
-					rate_min = rate;
-				if (rate > rate_max)
-					rate_max = rate;
-			}
-		}
+		unsigned int rate = freq / mclk_ratios[i];
+		rates |= snd_pcm_rate_to_rate_bit(rate);
+		if (rate < rate_min)
+			rate_min = rate;
+		if (rate > rate_max)
+			rate_max = rate;
 	}
+	/* FIXME: soc should support a rate list */
+	rates &= ~SNDRV_PCM_RATE_KNOT;
 
 	if (!rates) {
 		printk(KERN_ERR "cs4270: could not find a valid sample rate\n");
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index ac5666f..cbe8b33 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -123,7 +123,6 @@
 	unsigned int rate_min, rate_max;	/* min/max rates */
 	unsigned int nr_rates;		/* number of rate table entries */
 	unsigned int *rate_table;	/* rate table */
-	unsigned int needs_knot;	/* any unusual rates? */
 };
 
 struct snd_usb_substream;
@@ -1761,7 +1760,7 @@
 		channels[f->format] |= (1 << f->channels);
 		rates[f->format] |= f->rates;
 		/* needs knot? */
-		if (f->needs_knot)
+		if (f->rates & SNDRV_PCM_RATE_KNOT)
 			goto __out;
 	}
 	/* check whether channels and rates match for all formats */
@@ -1817,7 +1816,7 @@
 		if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
 			return 0;
 		count += fp->nr_rates;
-		if (fp->needs_knot)
+		if (fp->rates & SNDRV_PCM_RATE_KNOT)
 			needs_knot = 1;
 	}
 	if (!needs_knot)
@@ -2453,7 +2452,7 @@
 				    unsigned char *fmt, int offset)
 {
 	int nr_rates = fmt[offset];
-	int found;
+
 	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
 		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
 				   chip->dev->devnum, fp->iface, fp->altsetting);
@@ -2464,20 +2463,15 @@
 		/*
 		 * build the rate table and bitmap flags
 		 */
-		int r, idx, c;
+		int r, idx;
 		unsigned int nonzero_rates = 0;
-		/* this table corresponds to the SNDRV_PCM_RATE_XXX bit */
-		static unsigned int conv_rates[] = {
-			5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
-			64000, 88200, 96000, 176400, 192000
-		};
+
 		fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
 		if (fp->rate_table == NULL) {
 			snd_printk(KERN_ERR "cannot malloc\n");
 			return -1;
 		}
 
-		fp->needs_knot = 0;
 		fp->nr_rates = nr_rates;
 		fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
 		for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
@@ -2493,23 +2487,12 @@
 				fp->rate_min = rate;
 			else if (rate > fp->rate_max)
 				fp->rate_max = rate;
-			found = 0;
-			for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) {
-				if (rate == conv_rates[c]) {
-					found = 1;
-					fp->rates |= (1 << c);
-					break;
-				}
-			}
-			if (!found)
-				fp->needs_knot = 1;
+			fp->rates |= snd_pcm_rate_to_rate_bit(rate);
 		}
 		if (!nonzero_rates) {
 			hwc_debug("All rates were zero. Skipping format!\n");
 			return -1;
 		}
-		if (fp->needs_knot)
-			fp->rates |= SNDRV_PCM_RATE_KNOT;
 	} else {
 		/* continuous rates */
 		fp->rates = SNDRV_PCM_RATE_CONTINUOUS;