asihpi driver, adds tuner controls
PATCH 1/1 asihpi driver, adds tuner controls
Hello everybody,
the following patch adds tuner ( gain, freq, band ) as alsa mixer controls for asihpi based cards.
--
Delio Brignoli
[email protected]
PS
it's the first time I'm submitting a patch to alsa, I couldn't find any etiquette information on the website about how to submit patches ( maybe I haven't looked hard enough ) :-P
pci/asihpi.c +318 -5
@@ -74,6 +74,12 @@#define TIMER_JIFFIES 15 +static int _ret_err; +#define RETURN_IF_NEG (X ) if ( ( _ret_err = X ) < 0 ) {\ + if (mixer_dump) snd_printk(KERN_INFO "Error, returning %d in %s at line %d\n", _ret_err, __FILE__, __LINE__);\ + return _ret_err;\ + } + typedef struct snd_card_asihpi { snd_card_t *card; spinlock_t mixer_lock;
@@ -784,10 +790,21 @@HW16 wSrcNodeIndex;HW16 wDstNodeType;HW16 wDstNodeIndex; +HW16 wBand; } hpi_control_t;#define TEXT (a) a +#define ASIHPI_TUNER_BAND_STRINGS \ +{ \ + TEXT("invalid"), \ + TEXT("AM"), \ + TEXT("FM (mono)"), \ + TEXT("TV"), \ + TEXT("FM (stereo)"), \ + TEXT("AUX") \ +} +#ifdef ASI_STYLE_NAMES #define ASIHPI_SOURCENODE_STRINGS \ { \
@@ -845,17 +862,41 @@#endif #define NUM_DESTNODE_STRINGS 7 -#if ( (NUM_SOURCENODE_STRINGS < (HPI_SOURCENODE_LAST_INDEX -HPI_SOURCENODE_BASE +1 )) || -(NUM_DESTNODE_STRINGS < (HPI_DESTNODE_LAST_INDEX -HPI_DESTNODE_BASE +1 ))) +#if ( (NUM_SOURCENODE_STRINGS < (HPI_SOURCENODE_LAST_INDEX -HPI_SOURCENODE_BASE +1 )) || (NUM_DESTNODE_STRINGS < (HPI_DESTNODE_LAST_INDEX -HPI_DESTNODE_BASE +1 )))#error "Fewer node strings than #defines - new HPI?"#endif -#if ( (NUM_SOURCENODE_STRINGS > (HPI_SOURCENODE_LAST_INDEX -HPI_SOURCENODE_BASE +1 )) || -(NUM_DESTNODE_STRINGS < (HPI_DESTNODE_LAST_INDEX -HPI_DESTNODE_BASE +1 ))) +#if ( (NUM_SOURCENODE_STRINGS > (HPI_SOURCENODE_LAST_INDEX -HPI_SOURCENODE_BASE +1 )) || (NUM_DESTNODE_STRINGS < (HPI_DESTNODE_LAST_INDEX -HPI_DESTNODE_BASE +1 )))#warning "More Node strings than HPI defines - old HPI?"#endif static char *asihpi_src_names[] =ASIHPI_SOURCENODE_STRINGS ;static char *asihpi_dst_names[] =ASIHPI_DESTNODE_STRINGS ; +static char *asihpi_tuner_band_names[] =ASIHPI_TUNER_BAND_STRINGS ; + +inline int ctl_add (snd_card_t * card,snd_kcontrol_new_t * ctl,snd_card_asihpi_t * asihpi ) { +int err; + +if ((err =snd_ctl_add (card,snd_ctl_new1 (ctl, asihpi))) <0 ) { +return err; + }else if (mixer_dump) +snd_printk (KERN_INFO "Added %s(%d)\n" , ctl->name, ctl->index); + +return 0 ; +} + +void asihpi_ctl_name_prefix (snd_kcontrol_new_t * snd_control,hpi_control_t * asihpi_control) { + +if (asihpi_control->wDstNodeType) +sprintf (snd_control->name,"%s %s%d" , + asihpi_src_names[asihpi_control->wSrcNodeType], + asihpi_dst_names[asihpi_control->wDstNodeType], + asihpi_control->wDstNodeIndex +1 ); +else { +strcpy (snd_control->name, + asihpi_src_names[asihpi_control->wSrcNodeType]); + } + +}/*------------------------------------------------------------ Volume controls
@@ -1030,6 +1071,274 @@ }/*------------------------------------------------------------ +Tuner controls +------------------------------------------------------------*/ + +/* Gain */ + +static int snd_asihpi_tuner_gain_info (snd_kcontrol_t * kcontrol, +snd_ctl_elem_info_t * uinfo) +{ +HPI_HCONTROL hControl = kcontrol->private_value; +HW16 err; +short idx; +HW32 gainRange[3 ]; + +for (idx =0 ; idx <3 ; idx++) { + err =HPI_ControlQuery ( phSubSys, hControl,HPI_TUNER_GAIN , idx,0 , &gainRange[idx] ); +if (err !=0 )return err; + } + + uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER ; + uinfo->count =1 ; + uinfo->value.integer.min = ( (int )gainRange[0 ] ) / HPI_UNITS_PER_dB; + uinfo->value.integer.max = ( (int )gainRange[1 ] ) / HPI_UNITS_PER_dB; + uinfo->value.integer.step = ( (int ) gainRange[2 ] ) / HPI_UNITS_PER_dB; +return 0 ; +} + +static int snd_asihpi_tuner_gain_get (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +/* +snd_card_asihpi_t *asihpi = snd_kcontrol_chip(kcontrol); +unsigned long flags; +*/ +HPI_HCONTROL hControl = kcontrol->private_value; +short gain; + +HPI_Tuner_GetGain (phSubSys, hControl, &gain); + ucontrol->value.integer.value[0 ] = gain / HPI_UNITS_PER_dB; + +return 0 ; +} + +static int snd_asihpi_tuner_gain_put (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +/* +snd_card_asihpi_t *asihpi = snd_kcontrol_chip(kcontrol); +unsigned long flags; +*/ +HPI_HCONTROL hControl = kcontrol->private_value; +short gain; + + gain = (ucontrol->value.integer.value[0 ]) * HPI_UNITS_PER_dB; +HPI_Tuner_SetGain (phSubSys, hControl, gain); + +return 1 ; +} + +/* Band */ + +static int asihpi_tuner_band_query (snd_kcontrol_t * kcontrol,HW32 * bandList,HW32 len ) { +HPI_HCONTROL hControl = kcontrol->private_value; +HW16 err; +HW32 idx; + +for (idx=0 ; idx < len; idx++) { + err =HPI_ControlQuery ( phSubSys, hControl ,HPI_TUNER_BAND , idx,0 , &bandList[idx]); +if (err !=0 )break ; + } + +return idx; +} + +static int snd_asihpi_tuner_band_info (snd_kcontrol_t * kcontrol, +snd_ctl_elem_info_t * uinfo) +{ +HW32 tunerBands[HPI_TUNER_BAND_LAST ]; +HW32 numBands =0 ; + + numBands =asihpi_tuner_band_query ( kcontrol, tunerBands,HPI_TUNER_BAND_LAST ); + + uinfo->type =SNDRV_CTL_ELEM_TYPE_ENUMERATED ; + uinfo->count =1 ; + uinfo->value.enumerated.items = numBands; + +if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items -1 ; + +strcpy ( uinfo->value.enumerated.name, + asihpi_tuner_band_names[tunerBands[uinfo->value.enumerated.item]]); + +return 0 ; +} + +static int snd_asihpi_tuner_band_get (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +HPI_HCONTROL hControl = kcontrol->private_value; +/* +snd_card_asihpi_t *asihpi = snd_kcontrol_chip(kcontrol); +unsigned long flags; +*/ +HW16 band, idx; +HW32 tunerBands[HPI_TUNER_BAND_LAST ]; +HW32 numBands =0 ; + + numBands =asihpi_tuner_band_query ( kcontrol, tunerBands,HPI_TUNER_BAND_LAST ); + +HPI_Tuner_GetBand (phSubSys, hControl, &band); + + ucontrol->value.enumerated.item[0 ] =-1 ; +for (idx =0 ; idx <HPI_TUNER_BAND_LAST ; idx++) +if ( tunerBands[ idx ] == band ) { + ucontrol->value.enumerated.item[0 ] = idx; +break ; + } + + RETURN_IF_NEG(ucontrol->value.enumerated.item[0]) + +return 0 ; +} + +static int snd_asihpi_tuner_band_put (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +/* +snd_card_asihpi_t *asihpi = snd_kcontrol_chip(kcontrol); +unsigned long flags; +*/ +HPI_HCONTROL hControl = kcontrol->private_value; +HW16 band; +HW32 tunerBands[HPI_TUNER_BAND_LAST ]; +HW32 numBands =0 ; + + numBands =asihpi_tuner_band_query ( kcontrol, tunerBands,HPI_TUNER_BAND_LAST ); + + band = tunerBands[ucontrol->value.enumerated.item[0 ]]; +HPI_Tuner_SetBand (phSubSys, hControl, band); + +return 1 ; +} + +/* Freq */ + +static int snd_asihpi_tuner_freq_info (snd_kcontrol_t * kcontrol, +snd_ctl_elem_info_t * uinfo) +{ +HPI_HCONTROL hControl = kcontrol->private_value; +HW16 err; +HW32 tunerBands[HPI_TUNER_BAND_LAST ]; +HW32 numBands =0 , band_iter, idx; +HW32 freqRange[3 ], tempFreqRange[3 ]; + + numBands =asihpi_tuner_band_query ( kcontrol, tunerBands,HPI_TUNER_BAND_LAST ); + + freqRange[0 ] =INT_MAX ; + freqRange[1 ] =0 ; + freqRange[2 ] =INT_MAX ; + +for ( band_iter =0 ; band_iter < numBands; band_iter++ ) { +for (idx =0 ; idx <3 ; idx++) { + err =HPI_ControlQuery ( phSubSys, hControl,HPI_TUNER_FREQ , idx, tunerBands[band_iter], &tempFreqRange[idx] ); +if (err !=0 )return err; + } + +/* skip band with bogus stepping */ +if ( tempFreqRange[2 ] <=0 ) +continue ; + +if ( tempFreqRange[0 ] < freqRange[0 ] ) + freqRange[0 ] = tempFreqRange[0 ]; +if ( tempFreqRange[1 ] > freqRange[1 ] ) + freqRange[1 ] = tempFreqRange[1 ]; +if ( tempFreqRange[2 ] < freqRange[2 ] ) + freqRange[2 ] = tempFreqRange[2 ]; + } + + uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER ; + uinfo->count =1 ; + uinfo->value.integer.min = ( (int )freqRange[0 ] ); + uinfo->value.integer.max = ( (int )freqRange[1 ] ); + uinfo->value.integer.step = ( (int )freqRange[2 ] ); +return 0 ; +} + +static int snd_asihpi_tuner_freq_get (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +snd_card_asihpi_t *asihpi =snd_kcontrol_chip (kcontrol); +unsigned long flags; +HPI_HCONTROL hControl = kcontrol->private_value; +HW32 freq; + +spin_lock_irqsave (&asihpi->mixer_lock, flags); +HPI_Tuner_GetFrequency (phSubSys, hControl, &freq); + ucontrol->value.integer.value[0 ] = freq; +spin_unlock_irqrestore (&asihpi->mixer_lock, flags); + +return 0 ; +} + +static int snd_asihpi_tuner_freq_put (snd_kcontrol_t * kcontrol, +snd_ctl_elem_value_t * ucontrol) +{ +snd_card_asihpi_t *asihpi =snd_kcontrol_chip (kcontrol); +unsigned long flags; +HPI_HCONTROL hControl = kcontrol->private_value; +HW32 freq; + + freq = ucontrol->value.integer.value[0 ]; +spin_lock_irqsave (&asihpi->mixer_lock, flags); +HPI_Tuner_SetFrequency (phSubSys, hControl, freq); +spin_unlock_irqrestore (&asihpi->mixer_lock, flags); + +return 1 ; +} + +/* Tuner control group initializer */ + +static int __init snd_asihpi_tuner_new (snd_card_asihpi_t * asihpi,hpi_control_t * asihpi_control, +snd_kcontrol_new_t * snd_control) +{ + +snd_card_t *card = asihpi->card; + +/* Gain ctl */ + + snd_control->info = snd_asihpi_tuner_gain_info; + snd_control->get = snd_asihpi_tuner_gain_get; + snd_control->put = snd_asihpi_tuner_gain_put; + snd_control->index = asihpi_control->wSrcNodeIndex +1 ; + +asihpi_ctl_name_prefix ( snd_control, asihpi_control ); +strcat (snd_control->name," Gain" ); + +RETURN_IF_NEG ( ctl_add(card ,snd_control ,asihpi ) ) + +/* Band ctl */ + + snd_control->info = snd_asihpi_tuner_band_info; + snd_control->get = snd_asihpi_tuner_band_get; + snd_control->put = snd_asihpi_tuner_band_put; + snd_control->index = asihpi_control->wSrcNodeIndex +1 ; + +asihpi_ctl_name_prefix ( snd_control, asihpi_control ); +strcat (snd_control->name," Band" ); + +RETURN_IF_NEG ( ctl_add(card ,snd_control ,asihpi ) ) + +/* Freq ctl */ + + snd_control->info = snd_asihpi_tuner_freq_info; + snd_control->get = snd_asihpi_tuner_freq_get; + snd_control->put = snd_asihpi_tuner_freq_put; + snd_control->index = asihpi_control->wSrcNodeIndex +1 ; + +asihpi_ctl_name_prefix ( snd_control, asihpi_control ); +strcat (snd_control->name," Freq" ); + +RETURN_IF_NEG ( ctl_add(card ,snd_control ,asihpi ) ) + +/* Level meter */ + + return 0; +} + + +/*------------------------------------------------------------ Meter controls ------------------------------------------------------------*/ static int snd_asihpi_meter_info(snd_kcontrol_t * kcontrol,
@@ -1437,6 +1746,7 @@/*------------------------------------------------------------ Mixer ------------------------------------------------------------*/ +static int __init snd_card_asihpi_new_mixer (snd_card_asihpi_t * asihpi) {snd_card_t *card = asihpi->card;
@@ -1525,10 +1835,13 @@break ;case HPI_CONTROL_CONNECTION :// ignore these continue ; +case HPI_CONTROL_TUNER : +RETURN_IF_NEG (snd_asihpi_tuner_new (asihpi, &asihpi_control, + &snd_control) ); +continue ;case HPI_CONTROL_MUTE :case HPI_CONTROL_AESEBU_TRANSMITTER :case HPI_CONTROL_AESEBU_RECEIVER : -case HPI_CONTROL_TUNER :case HPI_CONTROL_ONOFFSWITCH :case HPI_CONTROL_VOX :case HPI_CONTROL_BITSTREAM :
At Mon, 18 Jul 2005 22:48:13 -0700,
Quoted 5 lines · Delio Brignoli
Hello everybody,
the following patch adds tuner ( gain, freq, band ) as alsa mixer controls for asihpi based cards.
RETURN_IF_NEG() is a bit ugly. In your code, it's not clear whether this is for a debug purpose or for checking a critical error.
If it's just a check, you can use snd_assert(). Otherwise, a plain if() would be easier to read.
Could you rewrite that stuff?
Quoted 4 lines
PS
it's the first time I'm submitting a patch to alsa, I couldn't find any etiquette information on the website about how to submit patches ( maybe I haven't looked hard enough ) :-P
Your patch is OK. We prefer a unified diff as you already did.
Thanks,
Takashi
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies from IBM. Find simple to follow Roadmaps, straightforward articles, informative Webcasts and more! Get everything you need to get up to speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click