Skip to contentSkip to conversation

asihpi driver, adds tuner controls

PATCH In review Delio Brignoli 2 participants 2 messages Jul 19, 2005 – Jul 27, 2005

lore
Share & tools
lore
#0 lore raw

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:
#1 lore raw

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