[alsa-devel] [PATCH 5/5] asihpi: add hwdep (experimental)

Eliot Blennerhassett linux at audioscience.com
Thu Mar 6 02:51:18 CET 2008


Add hpi ioctl via hwdep (experimental, disabled by default).
Adjust sampleclock control to use new hpi apis. 

Signed-off-by: Eliot Blennerhassett <linux at audioscience.com
---
diff -r 6def4892d3f5 pci/Kconfig
--- a/pci/Kconfig	Mon Mar 03 11:05:48 2008 +0100
+++ b/pci/Kconfig	Sat Feb 23 20:24:59 2008 +1300
@@ -17,6 +17,7 @@ config SND_ASIHPI
 	depends on SND && X86
 	select FW_LOADER
 	select SND_PCM
+	select SND_HWDEP
 	help
 	  Say 'Y' or 'M' to include support for AudioScience ASIxxxx soundcards.
 
diff -r 6def4892d3f5 pci/asihpi/asihpi.c
--- a/pci/asihpi/asihpi.c	Mon Mar 03 11:05:48 2008 +0100
+++ b/pci/asihpi/asihpi.c	Wed Mar 05 21:59:31 2008 +1300
@@ -23,6 +23,9 @@
  */
 /* >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
@@ -66,19 +69,28 @@
 #include <sound/info.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/hwdep.h>
 
 #include "hpi.h"
 
 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;
-
-module_param_array(index, int, NULL, 0444);
+static int enable_hpi_hwdep;
+
+module_param_array(index, int, NULL, S_IRUGO);
 MODULE_PARM_DESC(index, "ALSA Index value for AudioScience soundcard.");
-module_param_array(id, charp, NULL, 0444);
+
+module_param_array(id, charp, NULL, S_IRUGO);
 MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");
-module_param_array(enable, bool, NULL, 0444);
+
+module_param_array(enable, bool, NULL, S_IRUGO);
 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);
@@ -114,6 +126,7 @@ struct clk_source {
 
 struct clk_cache {
 	int count;
+	int has_local;
 	struct clk_source s[MAX_CLOCKSOURCES];
 };
 
@@ -1602,7 +1615,6 @@ static int __devinit snd_asihpi_aesebu_t
 	snd_control->info = snd_asihpi_aesebu_format_info;
 	snd_control->get = snd_asihpi_aesebu_tx_format_get;
 	snd_control->put = snd_asihpi_aesebu_tx_format_put;
-	snd_control->index = asihpi_control->wDstNodeIndex + ixb;
 
 	asihpi_ctl_name(snd_control, asihpi_control, "Format");
 
@@ -1909,9 +1921,9 @@ static int log2lin[] = {
 	  6790940,
 	  2147484, /* -60dB */
 	   679094,
-	   214748,
+	   214748, /* -80 */
 	    67909,
-	    21475,
+	    21475, /* -100 */
 	     6791,
 	     2147,
 	      679,
@@ -2153,8 +2165,9 @@ static void __devinit snd_asihpi_cmode_n
  ------------------------------------------------------------*/
 
 static char *sampleclock_sources[MAX_CLOCKSOURCES] =
-    { "N/A", "Adapter", "AES/EBU Sync", "Word External", "Word Header",
-	  "SMPTE", "AES/EBU In1", "Auto", "Cobranet",
+    { "N/A", "Local PLL", "AES/EBU Sync", "Word External", "Word Header",
+	  "SMPTE", "AES/EBU In1", "Auto", "Network", "Invalid",
+	  "Prev Module",
 	  "AES/EBU In2", "AES/EBU In3", "AES/EBU In4", "AES/EBU In5",
 	  "AES/EBU In6", "AES/EBU In7", "AES/EBU In8"};
 
@@ -2239,7 +2252,9 @@ static void __devinit snd_asihpi_clksrc_
 	snd_control->info = snd_asihpi_clksrc_info;
 	snd_control->get = snd_asihpi_clksrc_get;
 	snd_control->put = snd_asihpi_clksrc_put;
-	asihpi_ctl_name(snd_control, asihpi_control, "ClockSource");
+	asihpi_ctl_name(snd_control, asihpi_control, "Source");
+
+	clkcache->has_local = 0;
 
 	for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) {
 		if  (HPI_ControlQuery(phSubSys, hSC,
@@ -2250,6 +2265,8 @@ static void __devinit snd_asihpi_clksrc_
 		clkcache->s[i].name = sampleclock_sources[wSource];
 		if (wSource == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
 			hasAesIn = 1;
+		if (wSource == HPI_SAMPLECLOCK_SOURCE_LOCAL)
+			clkcache->has_local = 1;
 	}
 	if (hasAesIn)
 		/* already will have picked up index 0 above */
@@ -2271,7 +2288,7 @@ static void __devinit snd_asihpi_clksrc_
 /*------------------------------------------------------------
    Clkrate controls
  ------------------------------------------------------------*/
-static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol,
+static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -2283,18 +2300,18 @@ static int snd_asihpi_clkrate_info(struc
 	return 0;
 }
 
-static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
+static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
 	u32 hControl = kcontrol->private_value;
 	u32 dwRate;
 
-	HPI_SampleClock_GetSampleRate(phSubSys, hControl, &dwRate);
+	HPI_SampleClock_GetLocalRate(phSubSys, hControl, &dwRate);
 	ucontrol->value.integer.value[0] = dwRate;
 	return 0;
 }
 
-static int snd_asihpi_clkrate_put(struct snd_kcontrol *kcontrol,
+static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
 	int change;
@@ -2304,21 +2321,55 @@ static int snd_asihpi_clkrate_put(struct
 	   asihpi->mixer_clkrate[addr][1] != right;
 	 */
 	change = 1;
-	HPI_SampleClock_SetSampleRate(phSubSys, hControl,
+	HPI_SampleClock_SetLocalRate(phSubSys, hControl,
 				      ucontrol->value.integer.value[0]);
 	return change;
 }
 
+static void __devinit snd_asihpi_clklocal_new(
+					struct hpi_control *asihpi_control,
+					struct snd_kcontrol_new *snd_control)
+{
+	snd_control->info = snd_asihpi_clklocal_info;
+	snd_control->get = snd_asihpi_clklocal_get;
+	snd_control->put = snd_asihpi_clklocal_put;
+
+	asihpi_ctl_name(snd_control, asihpi_control, "LocalRate");
+}
+
+static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 8000;
+	uinfo->value.integer.max = 192000;
+	uinfo->value.integer.step = 100;
+
+	return 0;
+}
+
+static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	u32 hControl = kcontrol->private_value;
+	u32 dwRate;
+
+	HPI_SampleClock_GetSampleRate(phSubSys, hControl, &dwRate);
+	ucontrol->value.integer.value[0] = dwRate;
+	return 0;
+}
+
 static void __devinit snd_asihpi_clkrate_new(struct hpi_control 
*asihpi_control,
 					  struct snd_kcontrol_new *snd_control)
 {
 	snd_control->info = snd_asihpi_clkrate_info;
 	snd_control->get = snd_asihpi_clkrate_get;
-	snd_control->put = snd_asihpi_clkrate_put;
+	snd_control->access =
+	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
 
 	asihpi_ctl_name(snd_control, asihpi_control, "Rate");
 }
-
 /*------------------------------------------------------------
    Mixer
  ------------------------------------------------------------*/
@@ -2404,6 +2455,14 @@ static int __devinit snd_card_asihpi_mix
 				return err;
 			snd_asihpi_clkrate_new(&asihpi_control,
 					       &snd_control);
+			err = snd_ctl_add(card,
+					snd_ctl_new1(&snd_control, asihpi));
+			if (err < 0)
+				return err;
+			if (asihpi->cc.has_local)
+				snd_asihpi_clklocal_new(&asihpi_control,
+					       &snd_control);
+
 			break;
 		case HPI_CONTROL_CONNECTION:	/* ignore these */
 			continue;
@@ -2510,6 +2569,55 @@ static void __devinit snd_asihpi_proc_in
 }
 
 /*------------------------------------------------------------
+   HWDEP
+ ------------------------------------------------------------*/
+
+static int snd_asihpi_hpi_open(struct snd_hwdep * hw, struct file *file)
+{
+	return 0;
+}
+
+static int snd_asihpi_hpi_release(struct snd_hwdep * hw, struct file *file)
+{
+	return 0;
+}
+
+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);
+}
+
+
+/* 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)
+{
+	struct snd_hwdep *hw;
+	int err;
+
+	if (rhwdep)
+		*rhwdep = NULL;
+	err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);
+	if (err < 0)
+		return err;
+	strcpy(hw->name, "asihpi (HPI)");
+	hw->iface = SNDRV_HWDEP_IFACE_LAST;
+	hw->ops.open = snd_asihpi_hpi_open;
+	hw->ops.ioctl = snd_asihpi_hpi_ioctl;
+	hw->ops.release = snd_asihpi_hpi_release;
+	hw->private_data = asihpi;
+	if (rhwdep)
+		*rhwdep = hw;
+	return 0;
+}
+
+/*------------------------------------------------------------
    CARD
  ------------------------------------------------------------*/
 int __devinit snd_asihpi_bind(struct hpi_adapter *hpi_card)
@@ -2602,10 +2710,13 @@ int __devinit snd_asihpi_bind(struct hpi
 				  HPI_CONTROL_SAMPLECLOCK, &hControl);
 
 	if (!err)
-		err = HPI_SampleClock_SetSampleRate(phSubSys,
+		err = HPI_SampleClock_SetLocalRate(phSubSys,
 				hControl, adapter_fs);
 
 	snd_asihpi_proc_init(asihpi);
+
+	if (enable_hpi_hwdep)
+		snd_asihpi_hpi_new(asihpi, 0, NULL);
 
 	if (asihpi->support_mmap)
 		strcpy(card->driver, "ASIHPI-MMAP");
diff -r 6def4892d3f5 pci/asihpi/hpimod.c
--- a/pci/asihpi/hpimod.c	Mon Mar 03 11:05:48 2008 +0100
+++ b/pci/asihpi/hpimod.c	Wed Mar 05 21:59:31 2008 +1300
@@ -24,14 +24,10 @@ Linux HPI driver module
 #include "hpi.h"
 #include "hpidebug.h"
 #include "hpimsgx.h"
+
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 #include <linux/stringify.h>
 
@@ -167,13 +163,13 @@ static int hpi_release(
 }
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11)
-static long hpi_ioctl(
+long asihpi_hpi_ioctl(
 	struct file *file,
 	unsigned int cmd,
 	unsigned long arg
 )
 #else
-static int hpi_ioctl(
+static int asihpi_hpi_ioctl(
 	struct inode *inode,
 	struct file *file,
 	unsigned int cmd,
@@ -225,8 +221,18 @@ static int hpi_ioctl(
 
 		/* -1=no data 0=read from user mem, 1=write to user mem */
 		int wrflag = -1;
-		int nAdapter = hm.wAdapterIndex;
+		u32 nAdapter = hm.wAdapterIndex;
 		switch (hm.wFunction) {
+		case HPI_SUBSYS_CREATE_ADAPTER:
+		case HPI_SUBSYS_DELETE_ADAPTER:
+			/* Application must not use these functions! */
+			hr.wSize = sizeof(struct hpi_response_header);
+			hr.wError = HPI_ERROR_INVALID_OPERATION;
+			hr.wFunction = hm.wFunction;
+			uncopied_bytes = copy_to_user(phr, &hr, hr.wSize);
+			if (uncopied_bytes)
+				return -EFAULT;
+			return 0;
 		case HPI_OSTREAM_WRITE:
 		case HPI_ISTREAM_READ:
 			/* Yes, sparse, this is correct. */
@@ -252,60 +258,49 @@ static int hpi_ioctl(
 			break;
 		}
 
-		if ((nAdapter >= HPI_MAX_ADAPTERS || nAdapter < 0) &&
-			(hm.wObject != HPI_OBJ_SUBSYSTEM))
-			hr.wError = HPI_ERROR_INVALID_OBJ_INDEX;
-		else {
-			if (mutex_lock_interruptible(&adapters[nAdapter].
-					mutex))
-				return -EINTR;
-
-			if (wrflag == 0) {
-				if (size > bufsize) {
-					mutex_unlock(&adapters[nAdapter].
-						mutex);
-					HPI_DEBUG_LOG(ERROR,
-						"Requested transfer of %d "
-						"bytes, max buffer size "
-						"is %d bytes.\n", size,
-						bufsize);
-					return -EINVAL;
-				}
-
-				uncopied_bytes =
-					copy_from_user(pa->pBuffer, ptr,
-					size);
-				if (uncopied_bytes)
-					HPI_DEBUG_LOG(WARNING,
-						"Missed %d of %d "
-						"bytes from user\n",
-						uncopied_bytes, size);
+		if (mutex_lock_interruptible(&adapters[nAdapter].mutex))
+			return -EINTR;
+
+		if (wrflag == 0) {
+			if (size > bufsize) {
+				mutex_unlock(&adapters[nAdapter].mutex);
+				HPI_DEBUG_LOG(ERROR,
+					"Requested transfer of %d "
+					"bytes, max buffer size "
+					"is %d bytes.\n", size, bufsize);
+				return -EINVAL;
 			}
 
-			HPI_MessageF(&hm, &hr, file);
-
-			if (wrflag == 1) {
-				if (size > bufsize) {
-					mutex_unlock(&adapters[nAdapter].
-						mutex);
-					HPI_DEBUG_LOG(ERROR,
-						"Requested transfer of %d "
-						"bytes, max buffer size is "
-						"%d bytes.\n", size, bufsize);
-					return -EINVAL;
-				}
-
-				uncopied_bytes =
-					copy_to_user(ptr, pa->pBuffer, size);
-				if (uncopied_bytes)
-					HPI_DEBUG_LOG(WARNING,
-						"Missed %d of %d "
-						"bytes to user\n",
-						uncopied_bytes, size);
+			uncopied_bytes =
+				copy_from_user(pa->pBuffer, ptr, size);
+			if (uncopied_bytes)
+				HPI_DEBUG_LOG(WARNING,
+					"Missed %d of %d "
+					"bytes from user\n",
+					uncopied_bytes, size);
+		}
+
+		HPI_MessageF(&hm, &hr, file);
+
+		if (wrflag == 1) {
+			if (size > bufsize) {
+				mutex_unlock(&adapters[nAdapter].mutex);
+				HPI_DEBUG_LOG(ERROR,
+					"Requested transfer of %d "
+					"bytes, max buffer size is "
+					"%d bytes.\n", size, bufsize);
+				return -EINVAL;
 			}
 
-			mutex_unlock(&adapters[nAdapter].mutex);
+			uncopied_bytes = copy_to_user(ptr, pa->pBuffer, size);
+			if (uncopied_bytes)
+				HPI_DEBUG_LOG(WARNING,
+					"Missed %d of %d "
+					"bytes to user\n",
+					uncopied_bytes, size);
 		}
+
+		mutex_unlock(&adapters[nAdapter].mutex);
 	}
 
 	/* on return response size must be set */
@@ -322,9 +317,9 @@ static struct file_operations hpi_fops =
 static struct file_operations hpi_fops = {
 	.owner = THIS_MODULE,
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11)
-	.unlocked_ioctl = hpi_ioctl,
+	.unlocked_ioctl = asihpi_hpi_ioctl,
 #else
-	.ioctl = hpi_ioctl,
+	.ioctl = asihpi_hpi_ioctl,
 #endif
 	.open = hpi_open,
 	.release = hpi_release
@@ -399,6 +394,9 @@ static int __devinit adapter_probe(
 
 	/* call CreateAdapterObject on the relevant hpi module */
 	HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
+	if (hr.wError)
+		goto err;
+
 	adapter.pBuffer = vmalloc(bufsize);
 	if (adapter.pBuffer == NULL) {
 		HPI_DEBUG_LOG(ERROR,
@@ -407,39 +405,37 @@ static int __devinit adapter_probe(
 		goto err;
 	}
 
-	if (hr.wError == 0) {
-		adapter.index = hr.u.s.wAdapterIndex;
-		adapter.type = hr.u.s.awAdapterList[adapter.index];
+	adapter.index = hr.u.s.wAdapterIndex;
+	adapter.type = hr.u.s.awAdapterList[adapter.index];
+	hm.wAdapterIndex = adapter.index;
+
+	err = HPI_AdapterOpen(NULL, adapter.index);
+	if (err)
+		goto err;
+
+	adapter.snd_card_asihpi = NULL;
+	/* WARNING can't init sem in 'adapter'
+	 * and then copy it to adapters[] ?!?!
+	 */
+	adapters[hr.u.s.wAdapterIndex] = adapter;
+	mutex_init(&adapters[adapter.index].mutex);
+#ifdef ALSA_BUILD
+	if (snd_asihpi_bind(&adapters[adapter.index])) {
+		HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM,
+			HPI_SUBSYS_DELETE_ADAPTER);
 		hm.wAdapterIndex = adapter.index;
-
-		err = HPI_AdapterOpen(NULL, adapter.index);
-		if (err)
-			goto err;
-
-		adapter.snd_card_asihpi = NULL;
-		/* WARNING can't init sem in 'adapter'
-		 * and then copy it to adapters[] ?!?!
-		 */
-		adapters[hr.u.s.wAdapterIndex] = adapter;
-		mutex_init(&adapters[adapter.index].mutex);
-#ifdef ALSA_BUILD
-		if (snd_asihpi_bind(&adapters[adapter.index])) {
-			HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM,
-				HPI_SUBSYS_DELETE_ADAPTER);
-			hm.wAdapterIndex = adapter.index;
-			HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
-			goto err;
-		}
-#endif
-
-		pci_set_drvdata(pci_dev, &adapters[adapter.index]);
-		adapter_count++;
-
-		printk(KERN_INFO
-			"Probe found adapter ASI%04X HPI index #%d.\n",
-			adapter.type, adapter.index);
-		return 0;
-	}
+		HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
+		goto err;
+	}
+#endif
+
+	pci_set_drvdata(pci_dev, &adapters[adapter.index]);
+	adapter_count++;
+
+	printk(KERN_INFO
+		"Probe found adapter ASI%04X HPI index #%d.\n",
+		adapter.type, adapter.index);
+	return 0;
 
 err:
 	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {


More information about the Alsa-devel mailing list