Index: btsco.c =================================================================== RCS file: /cvsroot/bluetooth-alsa/btsco/kernel/btsco.c,v retrieving revision 1.6 diff -c -r1.6 btsco.c *** btsco.c 19 Mar 2005 14:28:59 -0000 1.6 --- btsco.c 23 Aug 2005 15:01:19 -0000 *************** *** 21,26 **** --- 21,46 ---- * */ + + /* note: defining these two independently is not tested, + * thus not recommended + */ + + /* enable dynamic compression */ + #define DYNAMIC_COMPRESSION + /* enable automatic endianness fixup */ + #define AUTO_FIXUP_ENDIANNESS + + + #ifdef DYNAMIC_COMPRESSION + /* Autoadjust mic at most this often in 1/8000s */ + #define GRABSAMPLES 400 + /* Maximum push for the mike 16= 1:1 - default 20:1 = 320 */ + #define COMPRESSION_MAX_16 320 + /* Minimum push for the mike 1= 1:16 */ + #define COMPRESSION_MIN_16 1 + #endif + #define chip_t snd_card_bt_sco_t #include *************** *** 93,100 **** snd_card_t *card; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST + 1]; ! snd_kcontrol_t *mixer_controls[MIXER_ADDR_LAST + 2]; /* also loopback */ volatile int loopback; atomic_t playback_count, capture_count; volatile int count_changed; spinlock_t count_changed_lock; --- 113,127 ---- snd_card_t *card; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST + 1]; ! #ifdef DYNAMIC_COMPRESSION ! snd_kcontrol_t *mixer_controls[MIXER_ADDR_LAST + 2 + 1]; /* also loopback and agc */ ! #else ! snd_kcontrol_t *mixer_controls[MIXER_ADDR_LAST + 2 ]; /* also loopback */ ! #endif volatile int loopback; + #ifdef DYNAMIC_COMPRESSION + volatile int agc; + #endif atomic_t playback_count, capture_count; volatile int count_changed; spinlock_t count_changed_lock; *************** *** 569,574 **** --- 596,632 ---- return changed; } + #ifdef DYNAMIC_COMPRESSION + static int snd_bt_sco_agc_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) + { + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + ucontrol->value.integer.value[0] = bt_sco->agc; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return 0; + } + + static int snd_bt_sco_agc_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) + { + snd_card_bt_sco_t *bt_sco = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int changed; + int agc; + + agc = !!ucontrol->value.integer.value[0]; + + spin_lock_irqsave(&bt_sco->mixer_lock, flags); + changed = bt_sco->agc != agc; + bt_sco->agc = agc; + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags); + return changed; + } + #endif + #define BT_SCO_CONTROLS (sizeof(snd_bt_sco_controls)/sizeof(snd_kcontrol_new_t)) static snd_kcontrol_new_t snd_bt_sco_controls[] = { *************** *** 581,586 **** --- 639,654 ---- .get = snd_bt_sco_loopback_get, .put = snd_bt_sco_loopback_put, } + #ifdef DYNAMIC_COMPRESSION + , + {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "AGC Switch", + .index = 0, + .info = snd_bt_sco_boolean_info, + .get = snd_bt_sco_agc_get, + .put = snd_bt_sco_agc_put, + } + #endif }; int __init snd_card_bt_sco_new_mixer(snd_card_bt_sco_t * bt_sco) *************** *** 790,795 **** --- 858,874 ---- struct msghdr msg; struct iovec iov; sigset_t unblocked; + #if defined(DYNAMIC_COMPRESSION) || defined(AUTO_FIXUP_ENDIANNESS) + int i; + #endif + #ifdef DYNAMIC_COMPRESSION + static int factor=16; + static int maxvalsmoothed=0; + static int maxvalgrablen=GRABSAMPLES; /* adjust volume at most 4 times/second */ + #endif + #ifdef AUTO_FIXUP_ENDIANNESS + static int swap=0; + #endif lock_kernel(); *************** *** 839,844 **** --- 918,1000 ---- len = sock_recvmsg(sock, &msg, BUF_SIZE, 0); if (len > 0) { + #if defined (AUTO_FIXUP_ENDIANNESS) || defined (DYNAMIC_COMPRESSION) + int lostatcnt; + lostatcnt=0; + + if (len&1) dprintk("odd len %d\n",len); + for(i=0;i0x7fff) { + k=0x7fff; + if (bt_sco->agc&&factor>COMPRESSION_MIN_16) factor--; + } else if (k<-0x8000) { + k=0x8000; + if (bt_sco->agc&&factor>COMPRESSION_MIN_16) factor--; + } + #else + k=j; + #endif + buf[i+1]=(k>>8)&0xff; + buf[i ]=k&0xff; + #ifdef DYNAMIC_COMPRESSION + /* find the highest absolute value in a + * GRABSAMPLES long interval. + */ + if (k<0) k=-j; + if (k>maxvalsmoothed) maxvalsmoothed=k; + /* if the interval is over, recalculate + * the compression factor. Move it slowly. + */ + if (maxvalgrablen--<=0) { + maxvalgrablen=GRABSAMPLES; + /* If the noise goes up over 1000, we stop + * pushing the software gain + */ + if (maxvalsmoothed<1000&&factoragc) factor=16; + maxvalsmoothed=0; + } + #endif + } + #ifdef AUTO_FIXUP_ENDIANNESS + if (lostatcnt==len/2&&len>32&&maxvalgrablen>GRABSAMPLES-len) { + dprintk("SWAP problem detected! Fixing.\n"); + swap=!swap; + } + #endif + #endif /* any of them */ down(&bt_sco->capture_sem); if (bt_sco->capture) { snd_card_bt_sco_pcm_receive