[alsa-devel] [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range.

linux at audioscience.com linux at audioscience.com
Thu Jun 5 06:06:55 CEST 2008


From: Eliot Blennerhassett <linux at audioscience.com>


Signed-off-by: Eliot Blennerhassett <eblennerhassett at audioscience.com>

diff --git a/pci/asihpi/asihpi.c b/pci/asihpi/asihpi.c
index 538c771..3ffc47b 100644
--- a/pci/asihpi/asihpi.c
+++ b/pci/asihpi/asihpi.c
@@ -24,9 +24,6 @@
 /* >0: print Hw params, timer vars. >1: print stream write/copy sizes  */
 #define REALLY_VERBOSE_LOGGING 0
 
-/* Experimental HPI hwdep interface */
-#define EXPERIMENTAL_HWDEP 0
-
 #if REALLY_VERBOSE_LOGGING
 #define VPRINTK1 printk
 #else
@@ -50,7 +47,14 @@
 #define ASI_STYLE_NAMES 1
 #endif
 
+#ifndef KERNEL_ALSA_BUILD
+/* building in ALSA source tree */
 #include "adriver.h"
+#else
+/* building in kernel tree */
+#include <sound/driver.h>
+#endif
+
 #include <linux/pci.h>
 #include <linux/version.h>
 #include <linux/init.h>
@@ -68,11 +72,16 @@
 #include <sound/hwdep.h>
 
 #include "hpi.h"
+#include "hpioctl.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("AudioScience Inc. <support at audioscience.com>");
+MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-static int enable_hpi_hwdep;
+static int enable_hpi_hwdep = 1;
 
 module_param_array(index, int, NULL, S_IRUGO);
 MODULE_PARM_DESC(index, "ALSA Index value for AudioScience soundcard.");
@@ -85,15 +94,18 @@ MODULE_PARM_DESC(enable, "ALSA Enable AudioScience soundcard.");
 
 module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(enable_hpi_hwdep,
-		"ALSA Enable HPI hwdep for AudioScience soundcard "
-		"(experimental)");
-
-/* used by hpimod.c, stop sparse from complaining */
-int snd_asihpi_bind(struct hpi_adapter *hpi_card);
-void snd_asihpi_unbind(struct hpi_adapter *hpi_card);
+		"ALSA Enable HPI hwdep for AudioScience soundcard ");
 
-/* index base 0 or 1 for control names or indices */
-static const int ixb;
+/* identify driver */
+#ifdef KERNEL_ALSA_BUILD
+static char * build_info = "Built using headers from kernel source";
+module_param(build_info, charp, S_IRUGO);
+MODULE_PARM_DESC(build_info, "Built using headers from kernel source");
+#else
+static char * build_info = "Built within ALSA source";
+module_param(build_info, charp, S_IRUGO);
+MODULE_PARM_DESC(build_info, "Built within ALSA source");
+#endif
 
 /* set to 1 to dump every control from adapter to log */
 static const int mixer_dump;
@@ -142,6 +154,7 @@ struct snd_card_asihpi {
 
 	int support_mmap;
 	int support_grouping;
+	int support_mrx;
 };
 
 /* Per stream data */
@@ -352,6 +365,89 @@ static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsaFormat,
 	return -EINVAL;
 }
 
+static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
+					 struct snd_pcm_hardware *pcmhw)
+{
+	u16 err;
+	u32 hControl;
+	u32 sampleRate;
+	int idx;
+	unsigned int rate_min = 200000;
+	unsigned int rate_max = 0;
+	unsigned int rates = 0;
+
+	if (asihpi->support_mrx) {
+		rates |= SNDRV_PCM_RATE_CONTINUOUS;
+		rates |= SNDRV_PCM_RATE_8000_96000;
+		rate_min = 8000;
+		rate_max = 100000;
+	} else {
+		/* on cards without SRC, valid rates are determined by sampleclock */
+		err = HPI_MixerGetControl(phSubSys, asihpi->hMixer,
+					  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
+					  HPI_CONTROL_SAMPLECLOCK, &hControl);
+
+		for (idx=0; idx<100; idx++) {
+			if (HPI_ControlQuery(phSubSys, hControl, HPI_SAMPLECLOCK_SAMPLERATE,
+					idx, 0, &sampleRate))
+				break;
+
+			rate_min = min(rate_min, sampleRate);
+			rate_max = max(rate_max, sampleRate);
+
+			switch (sampleRate) {
+			case 5512:
+				rates |= SNDRV_PCM_RATE_5512;
+				break;
+			case 8000:
+				rates |= SNDRV_PCM_RATE_8000;
+				break;
+			case 11025:
+				rates |= SNDRV_PCM_RATE_11025;
+				break;
+			case 16000:
+				rates |= SNDRV_PCM_RATE_16000;
+				break;
+			case 22050:
+				rates |= SNDRV_PCM_RATE_22050;
+				break;
+			case 32000:
+				rates |= SNDRV_PCM_RATE_32000;
+				break;
+			case 44100:
+				rates |= SNDRV_PCM_RATE_44100;
+				break;
+			case 48000:
+				rates |= SNDRV_PCM_RATE_48000;
+				break;
+			case 64000:
+				rates |= SNDRV_PCM_RATE_64000;
+				break;
+			case 88200:
+				rates |= SNDRV_PCM_RATE_88200;
+				break;
+			case 96000:
+				rates |= SNDRV_PCM_RATE_96000;
+				break;
+			case 176400:
+				rates |= SNDRV_PCM_RATE_176400;
+				break;
+			case 192000:
+				rates |= SNDRV_PCM_RATE_192000;
+				break;
+			default: /* some other rate */
+				rates |= SNDRV_PCM_RATE_KNOT;
+			}
+		}
+	}
+
+	/*printk(KERN_INFO "Supported rates %X %d %d\n", rates, rate_min, rate_max); */
+	pcmhw->rates = rates;
+	pcmhw->rate_min = rate_min;
+	pcmhw->rate_max = rate_max;
+
+}
+
 static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 					 struct snd_pcm_hw_params *params)
 {
@@ -784,7 +880,7 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
 
 static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
 						u32 hStream,
-						u64 *formats)
+						struct snd_pcm_hardware * pcmhw)
 {
   struct hpi_format hpi_format;
 	u16 wFormat;
@@ -810,7 +906,7 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
 		err = HPI_OutStreamQueryFormat(phSubSys, hStream,
 					     &hpi_format);
 		if (!err && (hpi_to_alsa_formats[wFormat] != -1))
-			*formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
+			pcmhw->formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
 	}
 }
 
@@ -860,11 +956,10 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
 	runtime->private_free = snd_card_asihpi_runtime_free;
 
 	snd_card_asihpi_playback_format(card, dpcm->hStream,
-					&snd_card_asihpi_playback.formats);
-	snd_card_asihpi_playback.rates = SNDRV_PCM_RATE_CONTINUOUS |
-					SNDRV_PCM_RATE_8000_192000;
-	snd_card_asihpi_playback.rate_min = 5500;
-	snd_card_asihpi_playback.rate_max = 192000;
+					&snd_card_asihpi_playback);
+
+	snd_card_asihpi_pcm_samplerates(card,  &snd_card_asihpi_playback);
+
 	snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED |
 					SNDRV_PCM_INFO_PAUSE;
 
@@ -1006,12 +1101,13 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
 
 static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
 					u32 hStream,
-					u64 *formats)
+					 struct snd_pcm_hardware *pcmhw)
 {
   struct hpi_format hpi_format;
 	u16 wFormat;
 	u16 err;
 	u32 hControl;
+	u32 dwSampleRate = 48000;
 
 	/* on cards without SRC, must query at valid rate,
 		maybe set by external sync */
@@ -1021,20 +1117,21 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
 
 	if (!err)
 		err = HPI_SampleClock_GetSampleRate(phSubSys, hControl,
-			&hpi_format.dwSampleRate);
+			&dwSampleRate);
 
 	for (wFormat = HPI_FORMAT_PCM8_UNSIGNED;
 		wFormat <= HPI_FORMAT_PCM24_SIGNED; wFormat++) {
 
-		HPI_FormatCreate(&hpi_format, 2, wFormat, 48000, 128000, 0);
+		HPI_FormatCreate(&hpi_format, 2, wFormat, dwSampleRate, 128000, 0);
 		err =
 		    HPI_InStreamQueryFormat(phSubSys, hStream,
 					    &hpi_format);
 		if (!err)
-			*formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
+			pcmhw->formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
 	}
 }
 
+
 static struct snd_pcm_hardware snd_card_asihpi_capture = {
 	.channels_min = 1,
 	.channels_max = 2,
@@ -1079,12 +1176,11 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
 	runtime->private_free = snd_card_asihpi_runtime_free;
 
 	snd_card_asihpi_capture_format(card, dpcm->hStream,
-				       &snd_card_asihpi_capture.formats);
-	snd_card_asihpi_capture.rates = SNDRV_PCM_RATE_CONTINUOUS |
-					SNDRV_PCM_RATE_8000_192000;
-	snd_card_asihpi_capture.rate_min = 5500;
-	snd_card_asihpi_capture.rate_max = 192000;
+				       &snd_card_asihpi_capture);
+
+	snd_card_asihpi_pcm_samplerates(card,  &snd_card_asihpi_capture);
 	snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED;
+
 	if (card->support_mmap)
 		snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP |
 						SNDRV_PCM_INFO_MMAP_VALID;
@@ -1300,50 +1396,29 @@ static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
 	return 0;
 }
 
+/* Convert HPI control name and location into ALSA control name */
 static void asihpi_ctl_name(struct snd_kcontrol_new *snd_control,
 				struct hpi_control *asihpi_control,
 				char *name)
 {
-#if 1
-/* entire control ID is a string */
 	if (asihpi_control->wSrcNodeType && asihpi_control->wDstNodeType)
 		sprintf(snd_control->name, "%s%d to %s%d %s",
 			asihpi_src_names[asihpi_control->wSrcNodeType],
-			asihpi_control->wSrcNodeIndex + ixb,
+			asihpi_control->wSrcNodeIndex,
 			asihpi_dst_names[asihpi_control->wDstNodeType],
-			asihpi_control->wDstNodeIndex + ixb,
+			asihpi_control->wDstNodeIndex,
 			name);
 	else if (asihpi_control->wDstNodeType) {
 		sprintf(snd_control->name, "%s%d %s",
 		asihpi_dst_names[asihpi_control->wDstNodeType],
-		asihpi_control->wDstNodeIndex + ixb,
+		asihpi_control->wDstNodeIndex,
 		name);
 	} else {
 		sprintf(snd_control->name, "%s%d %s",
 		asihpi_src_names[asihpi_control->wSrcNodeType],
-		asihpi_control->wSrcNodeIndex + ixb,
+		asihpi_control->wSrcNodeIndex,
 		name);
 	}
-#else
-/* use string plus index of destination or only node */
-	snd_control->index = asihpi_control->wDstNodeIndex + ixb;
-	if (asihpi_control->wSrcNodeType && asihpi_control->wDstNodeType)
-		sprintf(snd_control->name, "%s%d to %s %s",
-			asihpi_src_names[asihpi_control->wSrcNodeType],
-			asihpi_control->wSrcNodeIndex + ixb,
-			asihpi_dst_names[asihpi_control->wDstNodeType],
-			name);
-	else if (asihpi_control->wDstNodeType)
-		sprintf(snd_control->name, "%s %s",
-		asihpi_dst_names[asihpi_control->wDstNodeType],
-		name);
-	else {
-		sprintf(snd_control->name, "%s %s",
-		asihpi_src_names[asihpi_control->wSrcNodeType],
-		name);
-		snd_control->index = asihpi_control->wSrcNodeIndex + ixb;
-	}
-#endif
 }
 
 /*------------------------------------------------------------
@@ -2041,7 +2116,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
 
 	sprintf(uinfo->value.enumerated.name, "%s %d",
 		asihpi_src_names[wSrcNodeType - HPI_SOURCENODE_BASE],
-		wSrcNodeIndex + ixb);
+		wSrcNodeIndex);
 	return 0;
 }
 
@@ -2201,15 +2276,16 @@ static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
 			(struct snd_card_asihpi *)(kcontrol->private_data);
 	struct clk_cache *clkcache = &asihpi->cc;
 	u32 hControl = kcontrol->private_value;
-	u16 wSource, wIndex;
+	u16 wSource, wIndex = 0;
 	int i;
 
 	ucontrol->value.enumerated.item[0] = 0;
-	/*Get current clock source, return "N/A" if an error occurs*/
 	if (HPI_SampleClock_GetSource(phSubSys, hControl, &wSource))
 		wSource = 0;
-	if (HPI_SampleClock_GetSourceIndex(phSubSys, hControl, &wIndex))
-		wIndex = 0;
+
+	if (wSource == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
+		if (HPI_SampleClock_GetSourceIndex(phSubSys, hControl, &wIndex))
+			wIndex = 0;
 
 	for (i = 0; i < clkcache->count; i++)
 		if ((clkcache->s[i].source == wSource) &&
@@ -2290,6 +2366,7 @@ static void __devinit snd_asihpi_clksrc_new(struct snd_card_asihpi *asihpi,
 /*------------------------------------------------------------
    Clkrate controls
  ------------------------------------------------------------*/
+/* Need to change this to enumerated control with list of rates */
 static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_info *uinfo)
 {
@@ -2335,6 +2412,8 @@ static void __devinit snd_asihpi_clklocal_new(
 	snd_control->info = snd_asihpi_clklocal_info;
 	snd_control->get = snd_asihpi_clklocal_get;
 	snd_control->put = snd_asihpi_clklocal_put;
+	snd_control->access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
+
 
 	asihpi_ctl_name(snd_control, asihpi_control, "LocalRate");
 }
@@ -2425,9 +2504,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 		asihpi_control.wDstNodeType -= HPI_DESTNODE_BASE;
 		snd_control.index = 0;
 		snd_control.private_value = hControl;
-		snd_control.access =
-		    SNDRV_CTL_ELEM_ACCESS_WRITE |
-		    SNDRV_CTL_ELEM_ACCESS_READ;
+		snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
 		switch (asihpi_control.wControlType) {
 		case HPI_CONTROL_VOLUME:
 			snd_asihpi_volume_new(&asihpi_control,
@@ -2576,29 +2653,36 @@ static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
 
 static int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file)
 {
-	return 0;
+	if (enable_hpi_hwdep)
+		return 0;
+	else
+		return -ENODEV;
+
 }
 
 static int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file)
 {
-	return 0;
+	if (enable_hpi_hwdep)
+		return asihpi_hpi_release(file);
+	else
+		return -ENODEV;
 }
 
-long asihpi_hpi_ioctl(struct file *file,
-	  unsigned int cmd, unsigned long arg);
-
 static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
 				unsigned int cmd, unsigned long arg)
 {
-	return asihpi_hpi_ioctl(file, cmd, arg);
+	if (enable_hpi_hwdep)
+		return asihpi_hpi_ioctl(file, cmd, arg);
+	else
+		return -ENODEV;
 }
 
 
 /* results in /dev/snd/hwC#D0 file for each card with index #
    also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
 */
-int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device,
-				struct snd_hwdep **rhwdep)
+static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
+	int device, struct snd_hwdep **rhwdep)
 {
 	struct snd_hwdep *hw;
 	int err;
@@ -2622,13 +2706,15 @@ int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device,
 /*------------------------------------------------------------
    CARD
  ------------------------------------------------------------*/
-int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
+int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
+				       const struct pci_device_id *pci_id)
 {
 	int err;
 
 	u16 wVersion;
 	int pcm_substreams;
 
+	struct hpi_adapter *hpi_card;
 	struct snd_card *card;
 	struct snd_card_asihpi *asihpi;
 
@@ -2645,6 +2731,12 @@ int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
 		return -ENOENT;
 	}
 
+	err = asihpi_adapter_probe(pci_dev, pci_id);
+	if (err < 0)
+		return err;
+
+	hpi_card = pci_get_drvdata(pci_dev);
+
 	/* first try to give the card the same index as its hardware index */
 	card = snd_card_new(hpi_card->index,
 			id[hpi_card->index], THIS_MODULE,
@@ -2672,8 +2764,9 @@ int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
 				 &asihpi->wNumInStreams,
 				 &asihpi->wVersion,
 				 &asihpi->dwSerialNumber, &asihpi->wType));
+
 	wVersion = asihpi->wVersion;
-	snd_printk(KERN_INFO "Adapter ID=%4X Index=%d NumOutStreams=%d"
+	snd_printk(KERN_INFO "Adapter ID=%4X Index=%d NumOutStreams=%d "
 			"NumInStreams=%d S/N=%d\n"
 			"Hw Version %c%d DSP code version %03d\n",
 			asihpi->wType, asihpi->wAdapterIndex,
@@ -2695,6 +2788,11 @@ int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
 
 	err = HPI_InStreamHostBufferFree(phSubSys, hStream);
 	asihpi->support_mmap = (!err);
+
+	asihpi->support_mrx = (((asihpi->wType & 0xFF00) == 0x8900) ||
+	                       ((asihpi->wType & 0xF000) == 0x6000));
+
+
 	printk(KERN_INFO "Supports mmap:%d grouping:%d\n",
 			asihpi->support_mmap, asihpi->support_grouping);
 
@@ -2717,8 +2815,9 @@ int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
 
 	snd_asihpi_proc_init(asihpi);
 
-	if (enable_hpi_hwdep)
-		snd_asihpi_hpi_new(asihpi, 0, NULL);
+	/* always create, can be enabled or disabled dynamically
+	    by enable_hwdep  module param*/
+	snd_asihpi_hpi_new(asihpi, 0, NULL);
 
 	if (asihpi->support_mmap)
 		strcpy(card->driver, "ASIHPI-MMAP");
@@ -2727,7 +2826,7 @@ int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
 
 	sprintf(card->shortname, "AudioScience ASI%4X", asihpi->wType);
 	sprintf(card->longname, "%s %i",
-			card->shortname, asihpi->wAdapterIndex + ixb);
+			card->shortname, asihpi->wAdapterIndex);
 	err = snd_card_register(card);
 	if (!err) {
 		hpi_card->snd_card_asihpi = card;
@@ -2740,8 +2839,50 @@ __nodev:
 
 }
 
-void snd_asihpi_unbind(struct hpi_adapter *hpi_card)
+static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
 {
+	struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev);
+
 	snd_card_free(hpi_card->snd_card_asihpi);
 	hpi_card->snd_card_asihpi = NULL;
+	asihpi_adapter_remove(pci_dev);
+}
+
+struct pci_device_id  asihpi_pci_tbl[] = {
+	{HPI_PCI_VENDOR_ID_TI, HPI_ADAPTER_DSP6205,
+		HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
+		(kernel_ulong_t)HPI_6205},
+	{HPI_PCI_VENDOR_ID_TI, HPI_ADAPTER_PCI2040,
+		HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
+		(kernel_ulong_t)HPI_6000},
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);
+
+static struct pci_driver driver = {
+	.name = "asihpi",
+	.id_table = asihpi_pci_tbl,
+	.probe = snd_asihpi_probe,
+	.remove = __devexit_p(snd_asihpi_remove),
+#ifdef CONFIG_PM
+/*	.suspend = snd_asihpi_suspend,
+	.resume = snd_asihpi_resume, */
+#endif
+};
+
+static int __init snd_asihpi_init(void)
+{
+	asihpi_init();
+	return pci_register_driver(&driver);
 }
+
+static void __exit snd_asihpi_exit(void)
+{
+
+	pci_unregister_driver(&driver);
+	asihpi_exit();
+}
+
+module_init(snd_asihpi_init)
+module_exit(snd_asihpi_exit)
+
-- 
1.5.4.3



More information about the Alsa-devel mailing list