At Wed, 5 Nov 2008 18:53:28 +0000, Mark Brown wrote:
From: Troy Kisky troy.kisky@boundarydevices.com
Add support for more sample rates, different crystals and split playback/capture rates.
Signed-off-by: Troy Kisky troy.kisky@boundarydevices.com Acked-by: Arun KS arunks@mistralsolutions.com Signed-off-by: Mark Brown broonie@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