[alsa-devel] [PATCH 1/4] ASoC: TLV320AIC23B Support more sample rates

Takashi Iwai tiwai at suse.de
Wed Nov 5 21:35:01 CET 2008


At Wed,  5 Nov 2008 18:53:28 +0000,
Mark Brown wrote:
> 
> From: Troy Kisky <troy.kisky at boundarydevices.com>
> 
> Add support for more sample rates, different crystals
> and split playback/capture rates.
> 
> Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
> Acked-by: Arun KS <arunks at mistralsolutions.com>
> Signed-off-by: Mark Brown <broonie at opensource.wolfsonmicro.com>
> ---
>  sound/soc/codecs/tlv320aic23.c |  227 ++++++++++++++++++++++++++++++++--------
>  1 files changed, 182 insertions(+), 45 deletions(-)
> 
> diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
> index 44308da..c1b2060 100644
> --- a/sound/soc/codecs/tlv320aic23.c
> +++ b/sound/soc/codecs/tlv320aic23.c
> +unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
> +		int dac, int dac_l, int dac_h, int need_dac)

Should be static.

> +{
> +	if ((adc >= adc_l) && (adc <= adc_h) &&
> +			(dac >= dac_l) && (dac <= dac_h)) {
> +		unsigned diff_adc = need_adc - adc;
> +		unsigned diff_dac = need_dac - dac;
> +		unsigned score;
> +		if (((int)diff_adc) < 0)
> +			diff_adc = -diff_adc;
> +		if (((int)diff_dac) < 0)
> +			diff_dac = -diff_dac;
> +		score = diff_adc + diff_dac;
> +		return score;
> +	}
> +	return 0xffffffff;

-1 would be simpler and safer (for possible missing f's).

> +}
> +int find_rate(int mclk, u32 need_adc, u32 need_dac)

Use static.

> +{
> +	int i, j;
> +	int best_i = -1;
> +	int best_j = -1;
> +	int best_div = 0;
> +	unsigned best_score = 0xffffffff;

-1 would be safer.

> +	int adc_l, adc_h, dac_l, dac_h;
> +
> +	need_adc *= SR_MULT;
> +	need_dac *= SR_MULT;
> +	/*
> +	 * rates given are +/- 1/32
> +	 */
> +	adc_l = need_adc - (need_adc >> 5);
> +	adc_h = need_adc + (need_adc >> 5);
> +	dac_l = need_dac - (need_dac >> 5);
> +	dac_h = need_dac + (need_dac >> 5);
> +	for (i = 0; i < 4; i++) {
> +		int base = mclk / bosr_usb_divisor_table[i];
> +		int mask = sr_valid_mask[i];
> +		for (j = 0; j < 16; j++, mask >>= 1) {
> +			int adc;
> +			int dac;
> +			int score;
> +			if ((mask & 1) == 0)
> +				continue;
> +			adc = base * sr_adc_mult_table[j];
> +			dac = base * sr_dac_mult_table[j];
> +			score = get_score(adc, adc_l, adc_h, need_adc,
> +					dac, dac_l, dac_h, need_dac);
> +			if (best_score > score) {
> +				best_score = score;
> +				best_i = i;
> +				best_j = j;
> +				best_div = 0;
> +			}
> +			score = get_score((adc >> 1), adc_l, adc_h, need_adc,
> +					(dac >> 1), dac_l, dac_h, need_dac);
> +			/* prefer to have a /2 */
> +			if ((score != 0xffffffff) && (best_score >= score)) {
> +				best_score = score;
> +				best_i = i;
> +				best_j = j;
> +				best_div = 1;
> +			}
> +		}
> +	}
> +	return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
> +}
> +
> +static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
> +		u32 *sample_rate_adc, u32 *sample_rate_dac)
> +{
> +	int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
> +	int sr = (src >> 2) & 0x0f;
> +	int val = (mclk / bosr_usb_divisor_table[src & 3]);
> +	int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
> +	int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
> +	if (src & TLV320AIC23_CLKIN_HALF) {
> +		adc >>= 1;
> +		dac >>= 1;
> +	}
> +	*sample_rate_adc = adc;
> +	*sample_rate_dac = dac;
> +}
> +
> +static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
> +		u32 sample_rate_adc, u32 sample_rate_dac)
> +{
> +	/* Search for the right sample rate */
> +	int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
> +	if (data < 0) {
> +		printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
> +				__func__, sample_rate_adc, sample_rate_dac);
> +		return -EINVAL;
> +	}
> +	tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
> +	if (1) {

For what?


Takashi


More information about the Alsa-devel mailing list