All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH - ASIHPI 1/8] Common init files for HPI
@ 2008-06-05  4:06 linux
  2008-06-05  4:06 ` [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range linux
  2008-06-05  4:34 ` [PATCH - ASIHPI 1/8] Common init files for HPI Eliot Blennerhassett
  0 siblings, 2 replies; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/hpioctl.c b/pci/asihpi/hpioctl.c
new file mode 100644
index 0000000..5192db3
--- /dev/null
+++ b/pci/asihpi/hpioctl.c
@@ -0,0 +1,440 @@
+/*******************************************************************************
+
+    AudioScience HPI driver
+    Copyright (C) 1997-2003  AudioScience Inc. <support@audioscience.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of version 2 of the GNU General Public License as
+    published by the Free Software Foundation;
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Common Linux HPI ioctl and module probe/remove functions
+*******************************************************************************/
+#define SOURCEFILE_NAME "hpioctl.c"
+
+#include "hpi.h"
+#include "hpidebug.h"
+#include "hpimsgx.h"
+#include "hpioctl.h"
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <asm/uaccess.h>
+#include <linux/stringify.h>
+
+#ifndef HPIMOD_DEFAULT_BUF_SIZE
+#   define HPIMOD_DEFAULT_BUF_SIZE 192000
+#endif
+
+#ifdef MODULE_FIRMWARE
+MODULE_FIRMWARE("asihpi/dsp5000.bin");
+MODULE_FIRMWARE("asihpi/dsp6200.bin");
+MODULE_FIRMWARE("asihpi/dsp6205.bin");
+MODULE_FIRMWARE("asihpi/dsp6400.bin");
+MODULE_FIRMWARE("asihpi/dsp6600.bin");
+MODULE_FIRMWARE("asihpi/dsp8700.bin");
+MODULE_FIRMWARE("asihpi/dsp8900.bin");
+#endif
+
+static int bufsize = HPIMOD_DEFAULT_BUF_SIZE;
+module_param(bufsize, int,
+	S_IRUGO
+);
+/* Allow the debug level to be changed after module load.
+ E.g.   echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
+*/
+module_param(hpiDebugLevel, int,
+	S_IRUGO | S_IWUSR
+);
+
+/* List of adapters found */
+static struct hpi_adapter adapters[HPI_MAX_ADAPTERS];
+
+/* Wrapper function to HPI_Message to enable dumping of the
+   message and response types.
+*/
+static void HPI_MessageF(
+	struct hpi_message *phm,
+	struct hpi_response *phr,
+	struct file *file
+)
+{
+	int nAdapter = phm->wAdapterIndex;
+
+	if ((nAdapter >= HPI_MAX_ADAPTERS || nAdapter < 0) &&
+		(phm->wObject != HPI_OBJ_SUBSYSTEM))
+		phr->wError = HPI_ERROR_INVALID_OBJ_INDEX;
+	else
+		HPI_MessageEx(phm, phr, file);
+}
+
+/* This is called from hpifunc.c functions, called by ALSA
+ * (or other kernel process) In this case there is no file descriptor
+ * available for the message cache code
+ */
+void HPI_Message(
+	struct hpi_message *phm,
+	struct hpi_response *phr
+)
+{
+	HPI_MessageF(phm, phr, HOWNER_KERNEL);
+}
+
+EXPORT_SYMBOL(HPI_Message);
+/* export HPI_Message for radio-asihpi */
+
+int asihpi_hpi_release(
+	struct file *file
+)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+
+/* HPI_DEBUG_LOG(INFO,"hpi_release file %p, pid %d\n", file, current->pid); */
+	/* close the subsystem just in case the application forgot to. */
+	HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE);
+	HPI_MessageEx(&hm, &hr, file);
+	return 0;
+}
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11)
+long asihpi_hpi_ioctl(
+	struct file *file,
+	unsigned int cmd,
+	unsigned long arg
+)
+#else
+int asihpi_hpi_ioctl(
+	struct inode *inode,
+	struct file *file,
+	unsigned int cmd,
+	unsigned long arg
+)
+#endif
+{
+	struct hpi_ioctl_linux __user *phpi_ioctl_data;
+	void __user *phm;
+	void __user *phr;
+	struct hpi_message hm;
+	struct hpi_response hr;
+	u32 uncopied_bytes;
+	struct hpi_adapter *pa;
+
+	if (cmd != HPI_IOCTL_LINUX)
+		return -EINVAL;
+
+	phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
+
+	/* Read the message and response pointers from user space.  */
+	get_user(phm, &phpi_ioctl_data->phm);
+	get_user(phr, &phpi_ioctl_data->phr);
+
+	/* Now read the message size and data from user space.  */
+	/* get_user(hm.wSize, (u16 __user *)phm); */
+	uncopied_bytes = copy_from_user(&hm, phm, sizeof(hm));
+	if (uncopied_bytes)
+		return -EFAULT;
+
+	pa = &adapters[hm.wAdapterIndex];
+
+	if ((hm.wAdapterIndex > HPI_MAX_ADAPTERS) || (!pa->type)) {
+		HPI_InitResponse(&hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_OPEN,
+			HPI_ERROR_BAD_ADAPTER_NUMBER);
+
+		uncopied_bytes = copy_to_user(phr, &hr, sizeof(hr));
+		if (uncopied_bytes)
+			return -EFAULT;
+		return 0;
+	}
+
+	hr.wSize = 0;
+	/* Response filled either copy from cache, or by HPI_Message() */
+	{
+		/* Dig out any pointers embedded in the message.  */
+		u16 __user *ptr = NULL;
+		u32 size = 0;
+
+		/* -1=no data 0=read from user mem, 1=write to user mem */
+		int wrflag = -1;
+		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. */
+			ptr = (u16 __user *)hm.u.d.u.Data.pbData;
+			size = hm.u.d.u.Data.dwDataSize;
+
+			hm.u.d.u.Data.pbData = pa->pBuffer;
+			/*
+			   if (size > bufsize) {
+			   size = bufsize;
+			   hm.u.d.u.Data.dwDataSize = size;
+			   }
+			 */
+
+			if (hm.wFunction == HPI_ISTREAM_READ)
+				/* from card, WRITE to user mem */
+				wrflag = 1;
+			else
+				wrflag = 0;
+			break;
+
+		default:
+			break;
+		}
+
+		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);
+		}
+
+		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);
+		}
+
+		mutex_unlock(&adapters[nAdapter].mutex);
+	}
+
+	/* on return response size must be set */
+	if (!hr.wSize)
+		return -EFAULT;
+
+	/* Copy the response back to user space.  */
+	uncopied_bytes = copy_to_user(phr, &hr, sizeof(hr));
+	if (uncopied_bytes)
+		return -EFAULT;
+	return 0;
+}
+
+int __devinit asihpi_adapter_probe(
+	struct pci_dev *pci_dev,
+	const struct pci_device_id *pci_id
+)
+{
+	int err, idx;
+	unsigned int memlen;
+	struct hpi_message hm;
+	struct hpi_response hr;
+	struct hpi_adapter adapter;
+	struct hpi_pci Pci;
+
+	memset(&adapter, 0, sizeof(adapter));
+
+	printk(KERN_DEBUG "Probe PCI device (%04x:%04x,%04x:%04x,%04x)\n",
+		pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor,
+		pci_dev->subsystem_device, pci_dev->devfn);
+
+	HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER);
+	HPI_InitResponse(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
+		HPI_ERROR_PROCESSING_MESSAGE);
+
+	hm.wAdapterIndex = -1;	/* an invalid index */
+
+	/* fill in HPI_PCI information from kernel provided information */
+	adapter.pci = pci_dev;
+
+	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
+		HPI_DEBUG_LOG(DEBUG, "Resource %d %s %llx-%llx\n",
+			idx, pci_dev->resource[idx].name,
+			(unsigned long long)pci_resource_start(pci_dev, idx),
+			(unsigned long long)pci_resource_end(pci_dev, idx));
+
+		memlen = pci_resource_len(pci_dev, idx);
+		if (memlen) {
+			adapter.apRemappedMemBase[idx] =
+				ioremap(pci_resource_start(pci_dev, idx),
+				memlen);
+			if (!adapter.apRemappedMemBase[idx]) {
+				HPI_DEBUG_LOG(ERROR,
+					"ioremap failed, aborting\n");
+				/* unmap previously mapped pci mem space */
+				goto err;
+			}
+		} else
+			adapter.apRemappedMemBase[idx] = NULL;
+
+		Pci.apMemBase[idx] = adapter.apRemappedMemBase[idx];
+	}
+
+	Pci.wBusNumber = pci_dev->bus->number;
+	Pci.wVendorId = (u16)pci_dev->vendor;
+	Pci.wDeviceId = (u16)pci_dev->device;
+	Pci.wSubSysVendorId = (u16)(pci_dev->subsystem_vendor & 0xffff);
+	Pci.wSubSysDeviceId = (u16)(pci_dev->subsystem_device & 0xffff);
+	Pci.wDeviceNumber = pci_dev->devfn;
+	Pci.wInterrupt = pci_dev->irq;
+	Pci.pOsData = pci_dev;
+
+	hm.u.s.Resource.wBusType = HPI_BUS_PCI;
+	hm.u.s.Resource.r.Pci = &Pci;
+
+	/* 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,
+			"HPI could not allocate kernel buffer size %d\n",
+			bufsize);
+		goto err;
+	}
+
+	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 mutex in 'adapter'
+	 * and then copy it to adapters[] ?!?!
+	 */
+	adapters[hr.u.s.wAdapterIndex] = adapter;
+	mutex_init(&adapters[adapter.index].mutex);
+	pci_set_drvdata(pci_dev, &adapters[adapter.index]);
+
+	/* 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++) {
+		if (adapter.apRemappedMemBase[idx]) {
+			iounmap(adapter.apRemappedMemBase[idx]);
+			adapter.apRemappedMemBase[idx] = NULL;
+		}
+	}
+
+	if (adapter.pBuffer)
+		vfree(adapter.pBuffer);
+
+	HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
+	return -ENODEV;
+}
+
+void __devexit asihpi_adapter_remove(
+	struct pci_dev *pci_dev
+)
+{
+	int idx;
+	struct hpi_message hm;
+	struct hpi_response hr;
+	struct hpi_adapter *pa;
+	pa = (struct hpi_adapter *)pci_get_drvdata(pci_dev);
+
+	HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_DELETE_ADAPTER);
+	hm.wAdapterIndex = pa->index;
+	HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
+
+	/* unmap PCI memory space, mapped during device init. */
+	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
+		if (pa->apRemappedMemBase[idx]) {
+			iounmap(pa->apRemappedMemBase[idx]);
+			pa->apRemappedMemBase[idx] = NULL;
+		}
+	}
+
+	if (pa->pBuffer)
+		vfree(pa->pBuffer);
+
+	pci_set_drvdata(pci_dev, NULL);
+	/*
+	   printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x),"
+	   " HPI index # %d, removed.\n",
+	   pci_dev->vendor, pci_dev->device,
+	   pci_dev->subsystem_vendor,
+	   pci_dev->subsystem_device, pci_dev->devfn,
+	   pa->index);
+	 */
+}
+
+void __init asihpi_init(
+	void
+)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+
+	memset(adapters, 0, sizeof(adapters));
+
+	/* HPI_DebugLevelSet(debug); now set directly as module param */
+	printk(KERN_INFO "ASIHPI driver %d.%02d.%02d\n",
+		HPI_VER_MAJOR(HPI_VER),
+		HPI_VER_MINOR(HPI_VER), HPI_VER_RELEASE(HPI_VER));
+
+	HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_DRIVER_LOAD);
+	HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
+}
+
+void asihpi_exit(
+	void
+)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+
+	HPI_InitMessage(&hm, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_DRIVER_UNLOAD);
+	HPI_MessageEx(&hm, &hr, HOWNER_KERNEL);
+}
+
+/***********************************************************
+*/
diff --git a/pci/asihpi/hpioctl.h b/pci/asihpi/hpioctl.h
new file mode 100644
index 0000000..5363472
--- /dev/null
+++ b/pci/asihpi/hpioctl.h
@@ -0,0 +1,58 @@
+/*******************************************************************************
+
+    AudioScience HPI driver
+    Copyright (C) 1997-2003  AudioScience Inc. <support@audioscience.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of version 2 of the GNU General Public License as
+    published by the Free Software Foundation;
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Linux HPI ioctl, and shared module init functions
+*******************************************************************************/
+
+int __devinit asihpi_adapter_probe(
+	struct pci_dev *pci_dev,
+	const struct pci_device_id *pci_id
+);
+void __devexit asihpi_adapter_remove(
+	struct pci_dev *pci_dev
+);
+void __init asihpi_init(
+	void
+);
+void __exit asihpi_exit(
+	void
+);
+
+int asihpi_hpi_release(
+	struct file *file
+);
+
+long asihpi_hpi_ioctl(
+	struct file *file,
+	unsigned int cmd,
+	unsigned long arg
+);
+
+/* This is called from hpifunc.c functions, called by ALSA
+ * (or other kernel process) In this case there is no file descriptor
+ * available for the message cache code
+ */
+void HPI_Message(
+	struct hpi_message *phm,
+	struct hpi_response *phr
+);
+
+#define HOWNER_KERNEL ((void *)-1)
+
+	/***********************************************************
+*/
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range.
  2008-06-05  4:06 [PATCH - ASIHPI 1/8] Common init files for HPI linux
@ 2008-06-05  4:06 ` linux
  2008-06-05  4:06   ` [PATCH - ASIHPI 3/8] Replace hpimod.c with hpioctl.c linux
  2008-06-05  4:34 ` [PATCH - ASIHPI 1/8] Common init files for HPI Eliot Blennerhassett
  1 sibling, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


Signed-off-by: Eliot Blennerhassett <eblennerhassett@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@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

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 3/8] Replace hpimod.c with hpioctl.c
  2008-06-05  4:06 ` [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range linux
@ 2008-06-05  4:06   ` linux
  2008-06-05  4:06     ` [PATCH - ASIHPI 4/8] Include pci table again, avoiding warning about extern linux
  0 siblings, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/Makefile b/pci/asihpi/Makefile
index 6d81cab..942dd84 100644
--- a/pci/asihpi/Makefile
+++ b/pci/asihpi/Makefile
@@ -5,7 +5,7 @@ endif
 include $(SND_TOPDIR)/toplevel.config
 include $(SND_TOPDIR)/Makefile.conf
 
-snd-asihpi-objs := asihpi.o hpimod.o hpimsginit.o\
+snd-asihpi-objs := asihpi.o hpioctl.o hpimsginit.o\
 	hpicmn.o hpifunc.o hpidebug.o hpidspcd.o\
 	hpios_linux_kernel.o hpi6000.o hpi6205.o hpimsgx.o
 
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 4/8] Include pci table again, avoiding warning about extern.
  2008-06-05  4:06   ` [PATCH - ASIHPI 3/8] Replace hpimod.c with hpioctl.c linux
@ 2008-06-05  4:06     ` linux
  2008-06-05  4:06       ` [PATCH - ASIHPI 5/8] Log warning if DSP code version doesn't match driver linux
  0 siblings, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/hpimsgx.c b/pci/asihpi/hpimsgx.c
index ac56a24..b843e9f 100644
--- a/pci/asihpi/hpimsgx.c
+++ b/pci/asihpi/hpimsgx.c
@@ -25,7 +25,9 @@ Extended Message Function With Response Cacheing
 #include "hpimsgx.h"
 #include "hpidebug.h"
 
-extern struct pci_device_id asihpi_pci_tbl[];	/* hpimod.c mod device tbl */
+static struct pci_device_id asihpi_pci_tbl[] = {
+#include "hpipcida.h"
+};
 
 static struct hpios_spinlock msgxLock;
 
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 5/8] Log warning if DSP code version doesn't match driver.
  2008-06-05  4:06     ` [PATCH - ASIHPI 4/8] Include pci table again, avoiding warning about extern linux
@ 2008-06-05  4:06       ` linux
  2008-06-05  4:06         ` [PATCH - ASIHPI 6/8] Version 3.10.00. Add new functions for HD radio tuner, and for firmware debug linux
  0 siblings, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/hpidspcd.c b/pci/asihpi/hpidspcd.c
index 2665370..8c0f251 100644
--- a/pci/asihpi/hpidspcd.c
+++ b/pci/asihpi/hpidspcd.c
@@ -56,6 +56,9 @@ struct code_header {
 #pragma pack(pop)
 #endif
 
+#define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
+	    HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
+
 /***********************************************************************/
 #include "linux/pci.h"
 /*-------------------------------------------------------------------*/
@@ -100,6 +103,13 @@ short HpiDspCode_Open(
 		goto error2;
 	}
 
+	if (header.version != HPI_VER_DECIMAL) {
+		HPI_DEBUG_LOG(WARNING,
+			"Version mismatch  DSP image %d != Driver %d\n",
+			header.version, HPI_VER_DECIMAL);
+		/* goto error2;  still allow driver to load */
+	}
+
 	HPI_DEBUG_LOG(INFO, "Dsp code %s opened\n", fw_name);
 	psDspCode->psFirmware = psFirmware;
 	psDspCode->dwBlockLength = header.size / sizeof(u32);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 6/8] Version 3.10.00. Add new functions for HD radio tuner, and for firmware debug.
  2008-06-05  4:06       ` [PATCH - ASIHPI 5/8] Log warning if DSP code version doesn't match driver linux
@ 2008-06-05  4:06         ` linux
  2008-06-05  4:07           ` [PATCH - ASIHPI 7/8] Support variable size cached control information linux
  0 siblings, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:06 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/hpi.h b/pci/asihpi/hpi.h
index 1656941..a58bf71 100644
--- a/pci/asihpi/hpi.h
+++ b/pci/asihpi/hpi.h
@@ -41,12 +41,12 @@ i.e 3.05.02 is a development version
 #define HPI_VERSION_CONSTRUCTOR(maj, min, rel) \
 	((maj << 16) + (min << 8) + rel)
 
-#define HPI_VER_MAJOR(v) (v >> 16)
-#define HPI_VER_MINOR(v) ((v >> 8) & 0xFF)
-#define HPI_VER_RELEASE(v) (v & 0xFF)
+#define HPI_VER_MAJOR(v) (int)(v >> 16)
+#define HPI_VER_MINOR(v) (int)((v >> 8) & 0xFF)
+#define HPI_VER_RELEASE(v) (int)(v & 0xFF)
 
 /* Use single digits for versions less that 10 to avoid octal. */
-#define HPI_VER HPI_VERSION_CONSTRUCTOR(3L, 9, 15)
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(3L, 10, 0)
 
 #ifdef _DOX_ONLY_
 /*****************************************************************************/
@@ -191,6 +191,8 @@ extern "C" {
 #define HPI_ADAPTER_ASI1722             0x1722
 /** ASI1731 - Quad TV tuner module */
 #define HPI_ADAPTER_ASI1731             0x1731
+/** ASI1741 - Quad HDRadio "pseudo" module */
+#define HPI_ADAPTER_ASI1741             0x1741
 /*ASI2214 - USB 2.0 1xanalog in, 4 x analog out, 1 x AES in/out */
 /*#define HPI_ADAPTER_ASI2214           0x2214  */
 
@@ -408,6 +410,8 @@ OBSOLETE - OEM 4 play PCM, MPEG*/
 #define HPI_ADAPTER_ASI8801             0x8801
 
 #define HPI_ADAPTER_FAMILY_ASI8900      0x8900
+/** 4 channel AM/FM HD-Radio */
+#define HPI_ADAPTER_ASI8914             0x8914
 /** OEM FM+RDS, 2 module tuner card */
 #define HPI_ADAPTER_ASI8920             0x8920
 /** 2 module tuner card */
@@ -471,7 +475,6 @@ The following table shows what combinations of mode and bitrate are possible:
 <td><p><b>Mono<br>Stereo @ 16,<br>22.050 and<br>24kHz*</b></p>
 <td><p><b>Mono<br>Stereo @ 32,<br>44.1 and<br>48kHz</b></p>
 
-<tr><td>8<td>X<td>X<td>_
 <tr><td>16<td>X<td>X<td>_
 <tr><td>24<td>X<td>X<td>_
 <tr><td>32<td>X<td>X<td>X
@@ -622,9 +625,10 @@ Audio samples from the device are sent out on the Cobranet network.*/
 #define HPI_CONTROL_COBRANET            21	/**< Cobranet control. */
 #define HPI_CONTROL_TONEDETECTOR        22	/**< Tone detector control. */
 #define HPI_CONTROL_SILENCEDETECTOR     23	/**< Silence detector control. */
+#define HPI_CONTROL_PAD                 24	/**< Tuner PAD control. */
 
 /*! Update this if you add a new control type. , AND hpidebug.h */
-#define HPI_CONTROL_LAST_INDEX                  23
+#define HPI_CONTROL_LAST_INDEX                  24
 
 /* WARNING types 32 or greater impact bit packing in all AX4 DSP code */
 /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */
@@ -884,6 +888,9 @@ enum HPI_MIXER_STORE_COMMAND {
 /* This allows for 255 control types, 256 unique attributes each */
 #define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
 
+/* Get the sub-index of the attribute for a control type */
+#define HPI_CTL_ATTR_INDEX(i) (i&0xff)
+
 /* Original 0-based non-unique attributes, might become unique later */
 #define HPI_CTL_ATTR0(ctl, ai) (ai)
 
@@ -1009,6 +1016,42 @@ enum HPI_MIXER_STORE_COMMAND {
 #define HPI_TUNER_RDS                   HPI_CTL_ATTR0(TUNER, 9)
 /** Audio pre-emphasis. */
 #define HPI_TUNER_DEEMPHASIS            HPI_CTL_ATTR(TUNER, 10)
+/** HD-Radio tuner program control. */
+#define HPI_TUNER_PROGRAM               HPI_CTL_ATTR(TUNER, 11)
+/** HD-Radio tuner digital signal quality. */
+#define HPI_TUNER_HDRADIO_SIGNAL_QUALITY        HPI_CTL_ATTR(TUNER, 12)
+/** HD-Radio SDK firmware version. */
+#define HPI_TUNER_HDRADIO_SDK_VERSION   HPI_CTL_ATTR(TUNER, 13)
+/** HD-Radio DSP firmware version. */
+#define HPI_TUNER_HDRADIO_DSP_VERSION   HPI_CTL_ATTR(TUNER, 14)
+/** \} */
+
+/** \defgroup pads_attrs Tuner PADs control attributes
+\{
+*/
+/** The text string containing the station/channel combination. */
+#define HPI_PAD_CHANNEL_NAME            HPI_CTL_ATTR(PAD, 1)
+#define HPI_PAD_CHANNEL_NAME_LEN        16
+/** The text string containing the artist. */
+#define HPI_PAD_ARTIST                  HPI_CTL_ATTR(PAD, 2)
+#define HPI_PAD_ARTIST_LEN              64
+/** The text string containing the title. */
+#define HPI_PAD_TITLE                   HPI_CTL_ATTR(PAD, 3)
+#define HPI_PAD_TITLE_LEN               64
+/** The text string containing the comment. */
+#define HPI_PAD_COMMENT                 HPI_CTL_ATTR(PAD, 4)
+#define HPI_PAD_COMMENT_LEN             256
+/** The integer containing the PTY code. */
+#define HPI_PAD_PROGRAM_TYPE            HPI_CTL_ATTR(PAD, 5)
+/** The integer containing the program identification. */
+#define HPI_PAD_PROGRAM_ID              HPI_CTL_ATTR(PAD, 6)
+/** The integer containing whether traffic information is supported.
+Contains either 1 or 0. */
+#define HPI_PAD_TA_SUPPORT              HPI_CTL_ATTR(PAD, 7)
+/** The integer containing whether traffic announcement is in progress.
+Contains either 1 or 0. */
+#define HPI_PAD_TA_ACTIVE               HPI_CTL_ATTR(PAD, 8)
+
 /** \} */
 
 /** \defgroup tuner_bands Tuner bands
@@ -1040,13 +1083,21 @@ Used for HPI_Tuner_SetBand(),HPI_Tuner_GetBand()
 #define HPI_TUNER_LEVEL_AVERAGE         0
 #define HPI_TUNER_LEVEL_RAW             1
 
-/** Tuner video status */
+/** \defgroup tuner_status Tuner status fields
+
+These bitfield values are returned by a call to HPI_Tuner_GetStatus().
+Multiple fields are returned from a single call.
+\{
+*/
 #define HPI_TUNER_VIDEO_COLOR_PRESENT           0x0001	/**< Video color is present. */
 #define HPI_TUNER_VIDEO_IS_60HZ                 0x0020	/**< 60 Hz video detected. */
 #define HPI_TUNER_VIDEO_HORZ_SYNC_MISSING       0x0040	/**< Video HSYNC is missing. */
 #define HPI_TUNER_VIDEO_STATUS_VALID            0x0100	/**< Video status is valid. */
 #define HPI_TUNER_PLL_LOCKED                    0x1000	/**< The tuner's PLL is locked. */
 #define HPI_TUNER_FM_STEREO                     0x2000	/**< Tuner reports back FM stereo. */
+#define HPI_TUNER_DIGITAL                       0x0200	/**< Tuner reports digital programming. */
+#define HPI_TUNER_MULITPROGRAM                  0x0400	/**< Tuner reports multiple programs. */
+/** \} */
 /** \} */
 
 /* VOX control attributes */
@@ -1224,8 +1275,8 @@ enum HPI_FILTER_TYPE {
 
 #define HPI_ETHERNET_UDP_PORT (44600)	/*!< UDP messaging port */
 
-/** Base network time out is set to 2 seconds. */
-#define HPI_ETHERNET_TIMEOUT_MS      (2000)
+/** Base network time out is set to 100 milli-seconds. */
+#define HPI_ETHERNET_TIMEOUT_MS      (100)
 
 /** \defgroup tonedet_attr Tonedetector attributes
 \{
@@ -1705,6 +1756,14 @@ u16 HPI_AdapterSelfTest(
 	u16 wAdapterIndex
 );
 
+u16 HPI_AdapterDebugRead(
+	struct hpi_hsubsys *phSubSys,
+	u16 wAdapterIndex,
+	u32 dwDspAddress,
+	char *pBytes,
+	int *dwCountBytes
+);
+
 u16 HPI_AdapterSetProperty(
 	struct hpi_hsubsys *phSubSys,
 	u16 wAdapterIndex,
@@ -2363,6 +2422,87 @@ u16 HPI_Tuner_GetDeemphasis(
 	u32 hControl,
 	u32 *pdwDeemphasis
 );
+u16 HPI_Tuner_SetProgram(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 dwProgram
+);
+u16 HPI_Tuner_GetProgram(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwProgram
+);
+u16 HPI_Tuner_GetHdRadioDspVersion(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszDspVersion,
+	const u32 dwStringSize
+);
+u16 HPI_Tuner_GetHdRadioSdkVersion(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszSdkVersion,
+	const u32 dwStringSize
+);
+
+u16 HPI_Tuner_GetHdRadioSignalQuality(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwQuality
+);
+
+/****************************/
+/* PADs control             */
+/****************************/
+
+u16 HPI_PAD_GetChannelName(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszData,
+	const u32 dwDataLength
+);
+
+u16 HPI_PAD_GetArtist(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszData,
+	const u32 dwDataLength
+);
+
+u16 HPI_PAD_GetTitle(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszData,
+	const u32 dwDataLength
+);
+
+u16 HPI_PAD_GetComment(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszData,
+	const u32 dwDataLength
+);
+
+u16 HPI_PAD_GetProgramType(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwPTY
+);
+
+u16 HPI_PAD_GetRdsPI(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwPI
+);
+
+u16 HPI_PAD_GetProgramTypeString(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	const u32 dwDataType,
+	const u32 nPTY,
+	char *pszData,
+	const u32 dwDataLength
+);
 
 /****************************/
 /* AES/EBU Receiver control */
@@ -2987,7 +3127,8 @@ u16 HPI_FormatCreate(
 #define HPI_ADAPTER_GET_PROPERTY        HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 15)
 #define HPI_ADAPTER_ENUM_PROPERTY       HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 16)
 #define HPI_ADAPTER_MODULE_INFO         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 17)
-#define HPI_ADAPTER_FUNCTION_COUNT 17
+#define HPI_ADAPTER_DEBUG_READ          HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 18)
+#define HPI_ADAPTER_FUNCTION_COUNT 18
 /* OUTPUT STREAM */
 #define HPI_OSTREAM_OPEN                HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 1)
 #define HPI_OSTREAM_CLOSE               HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 2)
@@ -3135,7 +3276,7 @@ struct hpi_msg_format {
 };
 
 /**  Buffer+format structure.
-	 Must be kept 7 * 32 bits to match public struct hpi_data HPI_DATAstruct */
+	 Must be kept 7 * 32 bits to match public struct hpi_datastruct */
 struct hpi_msg_data {
 	struct hpi_msg_format Format;
 	u8 *pbData;
@@ -3145,7 +3286,7 @@ struct hpi_msg_data {
 	u32 dwDataSize;
 };
 
-/** struct hpi_data HPI_DATAstructure used up to 3.04 driver */
+/** struct hpi_datastructure used up to 3.04 driver */
 struct hpi_data_legacy32 {
 	struct hpi_format Format;
 	u32 pbData;
@@ -3153,7 +3294,7 @@ struct hpi_data_legacy32 {
 };
 
 #ifdef HPI64BIT
-/* Compatibility version of struct hpi_data HPI_DATA*/
+/* Compatibility version of struct hpi_data*/
 struct hpi_data_compat32 {
 	struct hpi_msg_format Format;
 	u32 pbData;
@@ -3218,6 +3359,10 @@ union hpi_adapterx_msg {
 	struct {
 		u16 index;
 	} module_info;
+	struct {
+		u32 dwDspAddress;
+		u32 dwCountBytes;
+	} debug_read;
 };
 
 struct hpi_adapter_res {
@@ -3334,7 +3479,7 @@ union hpi_mixerx_msg {
 
 union hpi_mixerx_res {
 	struct {
-		u32 dwBytesReturned;	/* number of items returned */
+		u32 dwBytesReturned;	/* size of items returned */
 		u32 pData;	/* pointer to data array */
 		u16 wMoreToDo;	/* indicates if there is more to do */
 	} gcabi;
@@ -3360,6 +3505,7 @@ struct hpi_control_union_msg {
 			u32 dwGain;
 			u32 dwBand;
 			u32 dwDeemphasis;
+			u32 dwProgram;
 			struct {
 				u32 dwMode;
 				u32 dwValue;
@@ -3394,6 +3540,10 @@ union hpi_control_union_res {
 			u32 dwBLER;
 		} rds;
 	} tuner;
+	struct {
+		char szData[8];
+		u32 dwRemainingChars;
+	} chars8;
 };
 
 /* HPI_CONTROLX_STRUCTURES */
@@ -3419,6 +3569,17 @@ struct hpi_controlx_msg_cobranet_bigdata {
 #endif
 };
 
+/** Used for PADS control reading of string fields.
+*/
+struct hpi_controlx_msg_pad_data {
+	u32 dwField;
+	u32 dwByteCount;
+	u8 *pbData;
+#ifndef HPI64BIT
+	u32 dwPadding;
+#endif
+};
+
 /** Used for generic data
 */
 
@@ -3432,6 +3593,7 @@ struct hpi_controlx_msg {
 		struct hpi_controlx_msg_cobranet_data cobranet_data;
 		struct hpi_controlx_msg_cobranet_bigdata cobranet_bigdata;
 		struct hpi_controlx_msg_generic generic;
+		struct hpi_controlx_msg_pad_data pad_data;
 		/* nothing extra to send for status read */
 	} u;
 	u16 wControlIndex;
@@ -3657,6 +3819,7 @@ struct hpi_response {
 		struct hpi_clock_res t;	/* dsp time */
 		struct hpi_profile_res p;
 		struct hpi_async_res as;
+		u8 bytes[52];
 	} u;
 };
 
@@ -3696,11 +3859,17 @@ struct hpi_control_defn {
 Used for efficient transfer of the control state
 between DSP and host or across a network
 */
-struct hpi_control_cache_single {
+struct hpi_control_cache_info {
 	/** one of HPI_CONTROL_* */
-	u16 ControlType;
+	u8 ControlType;
+	/** The total size of cached information in 32-bit words. */
+	u8 nSizeIn32bitWords;
 	/** The original index of the control on the DSP */
 	u16 ControlIndex;
+};
+
+struct hpi_control_cache_single {
+	struct hpi_control_cache_info i;
 	union {
 		struct {	/* volume */
 			u16 anLog[2];
@@ -3750,6 +3919,20 @@ struct hpi_control_cache_single {
 		} g;
 	} u;
 };
+
+struct hpi_control_cache_pad {
+	struct hpi_control_cache_info i;
+	u32 dwFieldValidFlags;
+	u8 cChannel[8];
+	u8 cArtist[40];
+	u8 cTitle[40];
+	u8 cComment[200];
+	u32 dwPTY;
+	u32 dwPI;
+	u32 dwTrafficSupported;
+	u32 dwTrafficAnouncement;
+};
+
 /*/////////////////////////////////////////////////////////////////////////// */
 /* declarations for 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
 struct hpi_fifo_buffer {
diff --git a/pci/asihpi/hpidebug.h b/pci/asihpi/hpidebug.h
index b8b6f61..d99a685 100644
--- a/pci/asihpi/hpidebug.h
+++ b/pci/asihpi/hpidebug.h
@@ -170,10 +170,11 @@ void hpi_debug_data(
   "HPI_ADAPTER_SET_PROPERTY",    \
   "HPI_ADAPTER_GET_PROPERTY",    \
   "HPI_ADAPTER_ENUM_PROPERTY",    \
-  "HPI_ADAPTER_MODULE_INFO"    \
+  "HPI_ADAPTER_MODULE_INFO",    \
+  "HPI_ADAPTER_DEBUG_READ"    \
 }
 
-function_count_check(HPI_ADAPTER, 17);
+function_count_check(HPI_ADAPTER, 18);
 
 #define HPI_OSTREAM_STRINGS     \
 {                               \
@@ -328,9 +329,10 @@ function_count_check(HPI_ASYNCEVENT, 6);
 	"HPI_CONTROL_COBRANET", \
 	"HPI_CONTROL_TONE_DETECT", \
 	"HPI_CONTROL_SILENCE_DETECT" \
+	"HPI_CONTROL_PAD" \
 }
 
-compile_time_assert((HPI_CONTROL_LAST_INDEX + 1) == (24),
+compile_time_assert((HPI_CONTROL_LAST_INDEX + 1) == (25),
 	controltype_strings_dont_match_defs);
 
 #define HPI_SOURCENODE_STRINGS \
diff --git a/pci/asihpi/hpifunc.c b/pci/asihpi/hpifunc.c
index ef61d18..6c33a80 100644
--- a/pci/asihpi/hpifunc.c
+++ b/pci/asihpi/hpifunc.c
@@ -606,6 +606,35 @@ u16 HPI_AdapterSelfTest(
 	return (hr.wError);
 }
 
+u16 HPI_AdapterDebugRead(
+	struct hpi_hsubsys *phSubSys,
+	u16 wAdapterIndex,
+	u32 dwDspAddress,
+	char *pBuffer,
+	int *dwCountBytes
+)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+	HPI_InitMessage(&hm, HPI_OBJ_ADAPTER, HPI_ADAPTER_DEBUG_READ);
+	hm.wAdapterIndex = wAdapterIndex;
+	hm.u.ax.debug_read.dwDspAddress = dwDspAddress;
+
+	if (*dwCountBytes > sizeof(hr.u.bytes))
+		*dwCountBytes = sizeof(hr.u.bytes);
+
+	hm.u.ax.debug_read.dwCountBytes = *dwCountBytes;
+
+	HPI_Message(&hm, &hr);
+
+	if (!hr.wError) {
+		*dwCountBytes = hr.wSize - 12;
+		memcpy(pBuffer, &hr.u.bytes, *dwCountBytes);
+	} else
+		*dwCountBytes = 0;
+	return (hr.wError);
+}
+
 u16 HPI_AdapterSetProperty(
 	struct hpi_hsubsys *phSubSys,
 	u16 wAdapterIndex,
@@ -1692,6 +1721,61 @@ u16 HPI_ControlQuery(
 	return (hr.wError);
 }
 
+static u16 HPI_Control_GetString(
+	const struct hpi_hsubsys *phSubSys,
+	const u32 hControlHandle,
+	const u16 wAttribute,
+	char *pszString,
+	const u32 wStringLength
+)
+{
+	unsigned int subStringIndex = 0, j = 0;
+	char c = 0;
+	unsigned int n = 0;
+	u16 wHE = 0;
+
+	if ((wStringLength < 1) || (wStringLength > 256))
+		return HPI_ERROR_INVALID_CONTROL_VALUE;
+	for (subStringIndex = 0; subStringIndex < wStringLength;
+		subStringIndex += 8) {
+		struct hpi_message hm;
+		struct hpi_response hr;
+
+		HPI_InitMessage(&hm, HPI_OBJ_CONTROL, HPI_CONTROL_GET_STATE);
+		u32TOINDEXES(hControlHandle, &hm.wAdapterIndex,
+			&hm.u.c.wControlIndex);
+		hm.u.c.wAttribute = wAttribute;
+		hm.u.c.dwParam1 = subStringIndex;
+		hm.u.c.dwParam2 = 0;
+		HPI_Message(&hm, &hr);
+
+		if (subStringIndex == 0
+			&& (hr.u.cu.chars8.dwRemainingChars + 8) >
+			wStringLength)
+			return HPI_ERROR_INVALID_CONTROL_VALUE;
+
+		if (hr.wError) {
+			wHE = hr.wError;
+			break;
+		}
+		for (j = 0; j < 8; j++) {
+			c = hr.u.cu.chars8.szData[j];
+			pszString[subStringIndex + j] = c;
+			n++;
+			if (n >= wStringLength) {
+				pszString[wStringLength - 1] = 0;
+				wHE = HPI_ERROR_INVALID_CONTROL_VALUE;
+				break;
+			}
+			if (c == 0)
+				break;
+		}
+		if (c == 0)
+			break;
+	}
+	return wHE;
+}
+
 #if 0
 
 u16 HPI_Tuner_QueryFrequency(
@@ -2976,6 +3060,50 @@ u16 HPI_Tuner_GetDeemphasis(
 		pdwDeemphasis);
 }
 
+u16 HPI_Tuner_SetProgram(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 dwProgram
+)
+{
+	return HPI_ControlParamSet(phSubSys, hControl, HPI_TUNER_PROGRAM,
+		dwProgram, 0);
+}
+
+u16 HPI_Tuner_GetProgram(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwProgram
+)
+{
+	return HPI_ControlParam1Get(phSubSys, hControl, HPI_TUNER_PROGRAM,
+		pdwProgram);
+}
+
+u16 HPI_Tuner_GetHdRadioDspVersion(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszDspVersion,
+	const u32 dwStringSize
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl,
+		HPI_TUNER_HDRADIO_DSP_VERSION, pszDspVersion, dwStringSize);
+}
+
+u16 HPI_Tuner_GetHdRadioSdkVersion(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszSdkVersion,
+	const u32 dwStringSize
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl,
+		HPI_TUNER_HDRADIO_SDK_VERSION, pszSdkVersion, dwStringSize);
+}
+
 u16 HPI_Tuner_GetStatus(
 	struct hpi_hsubsys *phSubSys,
 	u32 hControl,
@@ -3022,6 +3150,16 @@ u16 HPI_Tuner_GetMode(
 		nMode, 0, pnValue, NULL);
 }
 
+u16 HPI_Tuner_GetHdRadioSignalQuality(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwQuality
+)
+{
+	return HPI_ControlParamGet(phSubSys, hControl,
+		HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pdwQuality, NULL);
+}
+
 u16 HPI_Tuner_GetRDS(
 	struct hpi_hsubsys *phSubSys,
 	u32 hControl,
@@ -3042,6 +3180,82 @@ u16 HPI_Tuner_GetRDS(
 	return (hr.wError);
 }
 
+#ifdef _DOX_ONLY_
+u16 HPI_Tuner_GetHdRadioSignalQuality(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwSignalQuality
+)
+{
+	return HPI_ControlParamGet(phSubSys, hControl,
+		HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pdwSignalQuality, 0);
+}
+#endif
+
+u16 HPI_PAD_GetChannelName(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszString,
+	const u32 dwDataLength
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl, HPI_PAD_CHANNEL_NAME, pszString, dwDataLength);
+}
+
+u16 HPI_PAD_GetArtist(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszString,
+	const u32 dwDataLength
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl, HPI_PAD_ARTIST, pszString, dwDataLength);
+}
+
+u16 HPI_PAD_GetTitle(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszString,
+	const u32 dwDataLength
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl, HPI_PAD_TITLE, pszString, dwDataLength);
+}
+
+u16 HPI_PAD_GetComment(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	char *pszString,
+	const u32 dwDataLength
+)
+{
+	return HPI_Control_GetString(phSubSys,
+		hControl, HPI_PAD_COMMENT, pszString, dwDataLength);
+}
+
+u16 HPI_PAD_GetProgramType(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwPTY
+)
+{
+	return HPI_ControlParamGet(phSubSys, hControl, HPI_PAD_PROGRAM_TYPE,
+		0, 0, pdwPTY, NULL);
+}
+
+u16 HPI_PAD_GetRdsPI(
+	struct hpi_hsubsys *phSubSys,
+	u32 hControl,
+	u32 *pdwPI
+)
+{
+	return HPI_ControlParamGet(phSubSys, hControl, HPI_PAD_PROGRAM_ID,
+		0, 0, pdwPI, NULL);
+}
+
 u16 HPI_VolumeSetGain(
 	struct hpi_hsubsys *phSubSys,
 	u32 hControl,
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 7/8] Support variable size cached control information.
  2008-06-05  4:06         ` [PATCH - ASIHPI 6/8] Version 3.10.00. Add new functions for HD radio tuner, and for firmware debug linux
@ 2008-06-05  4:07           ` linux
  2008-06-05  4:07             ` [PATCH - ASIHPI 8/8] Checkpatch tweaks linux
  0 siblings, 1 reply; 11+ messages in thread
From: linux @ 2008-06-05  4:07 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <linux@audioscience.com>


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

diff --git a/pci/asihpi/hpi6000.c b/pci/asihpi/hpi6000.c
index ec2ae66..6d1834e 100644
--- a/pci/asihpi/hpi6000.c
+++ b/pci/asihpi/hpi6000.c
@@ -158,6 +158,7 @@ struct hpi_hw_obj {
 	u16 wDspCrashed;	/* when '1' DSP has crashed/died/OTL */
 
 	struct hpi_control_cache_single aControlCache[HPI_NMIXER_CONTROLS];
+	struct hpi_control_cache *pCache;
 };
 
 static u16 Hpi6000_DspBlockWrite32(
@@ -319,8 +320,7 @@ static void ControlMessage(
 			}
 
 			if (HpiCheckControlCache
-				(&((struct hpi_hw_obj *)pao->priv)->
-					aControlCache[phm->u.c.wControlIndex],
+				(((struct hpi_hw_obj *)pao->priv)->pCache,
 					phm, phr))
 				break;
 		}
@@ -331,8 +331,8 @@ static void ControlMessage(
 		break;
 	case HPI_CONTROL_SET_STATE:
 		HW_Message(pao, phm, phr);
-		HpiSyncControlCache(&((struct hpi_hw_obj *)pao->priv)->
-			aControlCache[phm->u.c.wControlIndex], phm, phr);
+		HpiSyncControlCache(
+			((struct hpi_hw_obj *)pao->priv)->pCache, phm, phr);
 		break;
 	default:
 		phr->wError = HPI_ERROR_INVALID_FUNC;
@@ -431,7 +431,7 @@ void HPI_6000(
 	/* subsytem messages get executed by every HPI. */
 	/* All other messages are ignored unless the adapter index matches */
 	/* an adapter in the HPI */
-	HPI_DEBUG_LOG(DEBUG, "O %d,F %d\n", phm->wObject, phm->wFunction);
+	HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction);
 
 	/* if Dsp has crashed then do not communicate with it any more */
 	if (phm->wObject != HPI_OBJ_SUBSYSTEM) {
@@ -573,15 +573,19 @@ static void SubSysDeleteAdapter(
 )
 {
 	struct hpi_adapter_obj *pao = NULL;
-	void *priv;
+	struct hpi_hw_obj *phw;
 
 	pao = HpiFindAdapter(phm->wAdapterIndex);
 	if (!pao)
 		return;
 
-	priv = pao->priv;
+	phw = (struct hpi_hw_obj *)pao->priv;
+
+	if (pao->wHasControlCache)
+		HpiFreeControlCache(phw->pCache);
+
 	HpiDeleteAdapter(pao);
-	kfree(priv);
+	kfree(phw);
 
 	phr->wError = 0;
 }
@@ -594,6 +598,8 @@ static short CreateAdapterObj(
 {
 	short nBootError = 0;
 	u32 dwDspIndex = 0;
+	u32 dwControlCacheSize = 0;
+	u32 dwControlCacheCount = 0;
 	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
 
 	/* init error reporting */
@@ -693,10 +699,18 @@ static short CreateAdapterObj(
 		sizeof(struct hpi_control_cache_single) *
 		HPI_NMIXER_CONTROLS);
 	/* Read the control cache length to figure out if it is turned on */
-	if (HpiReadWord
-		(&phw->ado[0], HPI_HIF_ADDR(dwControlCacheSizeInBytes)))
+	dwControlCacheSize = HpiReadWord(&phw->ado[0],
+		HPI_HIF_ADDR(dwControlCacheSizeInBytes));
+	if (dwControlCacheSize) {
+		dwControlCacheCount = HpiReadWord(&phw->ado[0],
+			HPI_HIF_ADDR(dwControlCacheCount));
 		pao->wHasControlCache = 1;
-	else
+
+		phw->pCache = HpiAllocControlCache(dwControlCacheCount,
+			dwControlCacheSize, (struct hpi_control_cache_info *)
+			&phw->aControlCache[0]
+			);
+	} else
 		pao->wHasControlCache = 0;
 
 	HPI_DEBUG_LOG(DEBUG, "Get adapter info ASI%04X index %d\n",
diff --git a/pci/asihpi/hpi6000.h b/pci/asihpi/hpi6000.h
index ba75b0b..348ad8d 100644
--- a/pci/asihpi/hpi6000.h
+++ b/pci/asihpi/hpi6000.h
@@ -45,6 +45,7 @@ struct hpi_hif_6000 {
 	u32 dwControlCacheIsDirty;
 	u32 dwControlCacheAddress;
 	u32 dwControlCacheSizeInBytes;
+	u32 dwControlCacheCount;
 };
 
 #define HPI_HIF_PACK_ADAPTER_INFO(adapter, versionMajor, versionMinor) \
diff --git a/pci/asihpi/hpi6205.c b/pci/asihpi/hpi6205.c
index b74add0..ff010a7 100644
--- a/pci/asihpi/hpi6205.c
+++ b/pci/asihpi/hpi6205.c
@@ -126,8 +126,10 @@ struct hpi_hw_obj {
 
 	struct consistent_dma_area hControlCache;
 	struct consistent_dma_area hAsyncEventBuffer;
-	struct hpi_control_cache_single *pControlCache;
+/*      struct hpi_control_cache_single *pControlCache; */
 	struct hpi_async_event *pAsyncEventBuffer;
+	struct hpi_control_cache *pCache;
+
 };
 
 /*****************************************************************************/
@@ -172,12 +174,6 @@ static void SubSysDeleteAdapter(
 	struct hpi_response *phr
 );
 
-static void AdapterGetAsserts(
-	struct hpi_adapter_obj *pao,
-	struct hpi_message *phm,
-	struct hpi_response *phr
-);
-
 static u16 CreateAdapterObj(
 	struct hpi_adapter_obj *pao,
 	u32 *pdwOsErrorCode
@@ -325,9 +321,7 @@ static void ControlMessage(
 	case HPI_CONTROL_GET_STATE:
 		if (pao->wHasControlCache) {
 			rmb();	/* make sure we see updates DMAed from DSP */
-			if (HpiCheckControlCache
-				(&pHw6205->pControlCache[phm->u.c.
-						wControlIndex], phm, phr))
+			if (HpiCheckControlCache(pHw6205->pCache, phm, phr))
 				break;
 		}
 		HW_Message(pao, phm, phr);
@@ -338,9 +332,7 @@ static void ControlMessage(
 	case HPI_CONTROL_SET_STATE:
 		HW_Message(pao, phm, phr);
 		if (pao->wHasControlCache)
-			HpiSyncControlCache(&pHw6205->
-				pControlCache[phm->u.c.
-					wControlIndex], phm, phr);
+			HpiSyncControlCache(pHw6205->pCache, phm, phr);
 		break;
 	default:
 		phr->wError = HPI_ERROR_INVALID_FUNC;
@@ -354,14 +346,7 @@ static void AdapterMessage(
 	struct hpi_response *phr
 )
 {
-
 	switch (phm->wFunction) {
-	case HPI_ADAPTER_GET_INFO:
-		HW_Message(pao, phm, phr);
-		break;
-	case HPI_ADAPTER_GET_ASSERT:
-		AdapterGetAsserts(pao, phm, phr);
-		break;
 	default:
 		HW_Message(pao, phm, phr);
 		break;
@@ -506,6 +491,7 @@ void HPI_6205(
 			AdapterMessage(pao, phm, phr);
 			break;
 
+		case HPI_OBJ_CONTROLEX:
 		case HPI_OBJ_CONTROL:
 			ControlMessage(pao, phm, phr);
 			break;
@@ -694,20 +680,25 @@ static u16 CreateAdapterObj(
 	 * Allocate bus mastering control cache buffer and tell the DSP about it
 	 */
 	if (interface->aControlCache.dwNumberOfControls) {
+		void *pControlCacheVirtual;
+
 		err = HpiOs_LockedMem_Alloc(&pHw6205->hControlCache,
-			interface->aControlCache.
-			dwNumberOfControls *
-			sizeof(struct hpi_control_cache_single),
+			interface->aControlCache.dwSizeInBytes,
 			pao->Pci.pOsData);
 		if (!err)
 			err = HpiOs_LockedMem_GetVirtAddr(&pHw6205->
-				hControlCache, (void *)
-				&pHw6205->pControlCache);
-		if (!err)
-			memset((void *)pHw6205->pControlCache, 0,
-				interface->aControlCache.
-				dwNumberOfControls *
-				sizeof(struct hpi_control_cache_single));
+				hControlCache, &pControlCacheVirtual);
+		if (!err) {
+			memset(pControlCacheVirtual, 0,
+				interface->aControlCache.dwSizeInBytes);
+
+			pHw6205->pCache =
+				HpiAllocControlCache(interface->aControlCache.
+				dwNumberOfControls,
+				interface->aControlCache.dwSizeInBytes,
+				(struct hpi_control_cache_info *)
+				pControlCacheVirtual);
+		}
 		if (!err) {
 			err = HpiOs_LockedMem_GetPhysAddr(&pHw6205->
 				hControlCache, &dwPhysAddr);
@@ -718,10 +709,8 @@ static u16 CreateAdapterObj(
 		if (!err)
 			pao->wHasControlCache = 1;
 		else {
-			if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache)) {
+			if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache))
 				HpiOs_LockedMem_Free(&pHw6205->hControlCache);
-				pHw6205->pControlCache = NULL;
-			}
 			pao->wHasControlCache = 0;
 		}
 	}
@@ -816,7 +805,7 @@ static void DeleteAdapterObj(
 
 	if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache)) {
 		HpiOs_LockedMem_Free(&pHw6205->hControlCache);
-		pHw6205->pControlCache = NULL;
+		HpiFreeControlCache(pHw6205->pCache);
 	}
 
 	if (HpiOs_LockedMem_Valid(&pHw6205->hLockedMem)) {
@@ -846,19 +835,6 @@ static void DeleteAdapterObj(
 }
 
 /*****************************************************************************/
-/* ADAPTER */
-
-static void AdapterGetAsserts(
-	struct hpi_adapter_obj *pao,
-	struct hpi_message *phm,
-	struct hpi_response *phr
-)
-{
-	HW_Message(pao, phm, phr);	/*get DSP asserts */
-	return;
-}
-
-/*****************************************************************************/
 /* OutStream Host buffer functions */
 
 /** Allocate or attach buffer for busmastering
diff --git a/pci/asihpi/hpi6205.h b/pci/asihpi/hpi6205.h
index c5309cb..2c92d59 100644
--- a/pci/asihpi/hpi6205.h
+++ b/pci/asihpi/hpi6205.h
@@ -67,7 +67,7 @@ This is used for dynamic control cache allocation
 struct controlcache_6205 {
 	u32 dwNumberOfControls;
 	u32 dwPhysicalPCI32address;
-	u32 dwSpare;
+	u32 dwSizeInBytes;
 };
 
 /*********************************************************************
diff --git a/pci/asihpi/hpicmn.c b/pci/asihpi/hpicmn.c
index 29fe40f..af83a2e 100644
--- a/pci/asihpi/hpicmn.c
+++ b/pci/asihpi/hpicmn.c
@@ -21,6 +21,7 @@
 (C) Copyright AudioScience Inc. 1998-2003
 *******************************************************************************/
 #define SOURCEFILE_NAME "hpicmn.c"
+
 #include "hpi.h"
 #include "hpidebug.h"
 #include "hpicmn.h"
@@ -106,12 +107,16 @@ struct hpi_adapter_obj *HpiFindAdapter(
 
 	pao = &adapters.adapter[wAdapterIndex];
 	if (pao->wAdapterType != 0) {
-		HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
-			wAdapterIndex);
+		/*
+		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
+		   wAdapterIndex);
+		 */
 		return (pao);
 	} else {
-		HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
-			wAdapterIndex);
+		/*
+		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
+		   wAdapterIndex);
+		 */
 		return (NULL);
 	}
 }
@@ -171,25 +176,141 @@ static void SubSysGetAdapters(
 	phr->wError = 0;	/* the function completed OK; */
 }
 
-/**
-* CheckControlCache checks if a given struct hpi_control_cache_single control
-* value is in the cache and fills the struct hpi_response accordingly.
-* It returns nonzero if a cache hit occurred, zero otherwise.
+static unsigned int ControlCacheAllocCheck(
+	struct hpi_control_cache *pC
+)
+{
+	unsigned int i;
+	int nCached = 0;
+	if (!pC)
+		return 0;
+	if ((!pC->dwInit) &&
+		(pC->pCache != NULL) &&
+		(pC->dwControlCount) && (pC->dwCacheSizeInBytes)
+		) {
+		u32 *pMasterCache;
+		pC->dwInit = 1;
+
+		pMasterCache = (u32 *)pC->pCache;
+		for (i = 0; i < pC->dwControlCount; i++) {
+			struct hpi_control_cache_info *info =
+				(struct hpi_control_cache_info *)pMasterCache;
+
+			if (info->ControlType) {
+				pC->pInfo[i] = info;
+				nCached++;
+			} else
+				pC->pInfo[i] = NULL;
+
+			if (info->nSizeIn32bitWords)
+				pMasterCache += info->nSizeIn32bitWords;
+			else
+				pMasterCache +=
+					sizeof(struct
+					hpi_control_cache_single) /
+					sizeof(u32);
+
+		}
+		/*
+		   We didn't find anything to cache, so try again later !
+		 */
+		if (!nCached)
+			pC->dwInit = 0;
+	}
+	return pC->dwInit;
+}
+
+/** Find a control.
+*/
+static short FindControl(
+	struct hpi_message *phm,
+	struct hpi_control_cache *pCache,
+	struct hpi_control_cache_info **pI,
+	u16 *pwControlIndex
+)
+{
+	if (phm->wObject == HPI_OBJ_CONTROL) {
+		*pwControlIndex = phm->u.c.wControlIndex;
+	} else {	/* controlex */
+		*pwControlIndex = phm->u.cx.wControlIndex;
+		HPI_DEBUG_LOG(VERBOSE,
+			"HpiCheckControlCache() ControlEx %d\n",
+			*pwControlIndex);
+	}
+
+	if (!ControlCacheAllocCheck(pCache)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"ControlCacheAllocCheck() failed. adap%d ci%d\n",
+			phm->wAdapterIndex, *pwControlIndex);
+		return 0;
+	}
+
+	*pI = pCache->pInfo[*pwControlIndex];
+	if (!*pI) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"Uncached Adap %d, Control %d\n",
+			phm->wAdapterIndex, *pwControlIndex);
+		return 0;
+	} else {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HpiCheckControlCache() Type %d\n",
+			(*pI)->ControlType);
+	}
+	return 1;
+}
+
+/** Used by the kernel driver to figure out if a buffer needs mapping.
+ */
+short HpiCheckBufferMapping(
+	struct hpi_control_cache *pCache,
+	struct hpi_message *phm,
+	void **p,
+	unsigned int *pN
+)
+{
+	*pN = 0;
+	*p = NULL;
+	if ((phm->wFunction == HPI_CONTROL_GET_STATE) &&
+		(phm->wObject == HPI_OBJ_CONTROLEX)
+		) {
+		u16 wControlIndex;
+		struct hpi_control_cache_info *pI;
+
+		if (!FindControl(phm, pCache, &pI, &wControlIndex))
+			return 0;
+	}
+	return 0;
+}
+
+/** CheckControlCache checks the cache and fills the struct hpi_response
+* accordingly. It returns one if a cache hit occurred, zero otherwise.
 */
 short HpiCheckControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pCache,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 )
 {
 	short found = 1;
-	/* if the control type in the cache is non-zero then */
-	/* we have cached control information to process */
+	u16 wControlIndex;
+	struct hpi_control_cache_info *pI;
+	struct hpi_control_cache_single *pC;
+
+	if (!FindControl(phm, pCache, &pI, &wControlIndex))
+		return 0;
+
 	phr->wSize =
 		sizeof(struct hpi_response_header) +
 		sizeof(struct hpi_control_res);
 	phr->wError = 0;
-	switch (pC->ControlType) {
+
+	/* pC is the default cached control strucure. May be cast to
+	   something else in the following switch statement.
+	 */
+	pC = (struct hpi_control_cache_single *)pI;
+
+	switch (pI->ControlType) {
+
 	case HPI_CONTROL_METER:
 		if (phm->u.c.wAttribute == HPI_METER_PEAK) {
 			phr->u.c.anLogValue[0] = pC->u.p.anLogPeak[0];
@@ -198,45 +319,50 @@ short HpiCheckControlCache(
 			phr->u.c.anLogValue[0] = pC->u.p.anLogRMS[0];
 			phr->u.c.anLogValue[1] = pC->u.p.anLogRMS[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.wAttribute == HPI_VOLUME_GAIN) {
 			phr->u.c.anLogValue[0] = pC->u.v.anLog[0];
 			phr->u.c.anLogValue[1] = pC->u.v.anLog[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 		if (phm->u.c.wAttribute == HPI_MULTIPLEXER_SOURCE) {
 			phr->u.c.dwParam1 = pC->u.x.wSourceNodeType;
 			phr->u.c.dwParam2 = pC->u.x.wSourceNodeIndex;
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 		if (phm->u.c.wAttribute == HPI_CHANNEL_MODE_MODE)
 			phr->u.c.dwParam1 = pC->u.m.wMode;
 		else
-			found = 0;	/* signal that message was not cached */
-
+			found = 0;
+		break;
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.wAttribute == HPI_LEVEL_GAIN) {
 			phr->u.c.anLogValue[0] = pC->u.l.anLog[0];
 			phr->u.c.anLogValue[1] = pC->u.l.anLog[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_TUNER:
-		if (phm->u.c.wAttribute == HPI_TUNER_FREQ)
-			phr->u.c.dwParam1 = pC->u.t.dwFreqInkHz;
-		else if (phm->u.c.wAttribute == HPI_TUNER_BAND)
-			phr->u.c.dwParam1 = pC->u.t.wBand;
-		else if ((phm->u.c.wAttribute == HPI_TUNER_LEVEL) &&
-			(phm->u.c.dwParam1 == HPI_TUNER_LEVEL_AVERAGE))
-			phr->u.c.dwParam1 = pC->u.t.wLevel;
-		else
-			found = 0;	/* signal that message was not cached */
+		{
+			struct hpi_control_cache_single *pCT =
+				(struct hpi_control_cache_single *)pI;
+			if (phm->u.c.wAttribute == HPI_TUNER_FREQ)
+				phr->u.c.dwParam1 = pCT->u.t.dwFreqInkHz;
+			else if (phm->u.c.wAttribute == HPI_TUNER_BAND)
+				phr->u.c.dwParam1 = pCT->u.t.wBand;
+			else if ((phm->u.c.wAttribute == HPI_TUNER_LEVEL) &&
+				(phm->u.c.dwParam1 ==
+					HPI_TUNER_LEVEL_AVERAGE))
+				phr->u.c.dwParam1 = pCT->u.t.wLevel;
+			else
+				found = 0;
+		}
 		break;
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.wAttribute == HPI_AESEBURX_ERRORSTATUS)
@@ -244,26 +370,26 @@ short HpiCheckControlCache(
 		else if (phm->u.c.wAttribute == HPI_AESEBURX_FORMAT)
 			phr->u.c.dwParam1 = pC->u.aes3rx.dwSource;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_AESEBU_TRANSMITTER:
 		if (phm->u.c.wAttribute == HPI_AESEBUTX_FORMAT)
 			phr->u.c.dwParam1 = pC->u.aes3tx.dwFormat;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_TONEDETECTOR:
 		if (phm->u.c.wAttribute == HPI_TONEDETECTOR_STATE)
 			phr->u.c.dwParam1 = pC->u.tone.wState;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_SILENCEDETECTOR:
 		if (phm->u.c.wAttribute == HPI_SILENCEDETECTOR_STATE) {
 			phr->u.c.dwParam1 = pC->u.silence.dwState;
 			phr->u.c.dwParam2 = pC->u.silence.dwCount;
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SOURCE)
@@ -278,17 +404,105 @@ short HpiCheckControlCache(
 		} else if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SAMPLERATE)
 			phr->u.c.dwParam1 = pC->u.clk.dwSampleRate;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
+		break;
+#ifndef HPI_OS_WIN16	/* SGT - below does not compile in Borland C */
+	case HPI_CONTROL_PAD:
+		{
+			struct hpi_control_cache_pad *pPad =
+				(struct hpi_control_cache_pad *)pC;
+
+			if (!(pPad->dwFieldValidFlags &
+					(1 << HPI_CTL_ATTR_INDEX(phm->u.c.
+							wAttribute)))) {
+				/* attribute not supported */
+				phr->wError =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				break;
+			}
+
+			if (phm->u.c.wAttribute == HPI_PAD_PROGRAM_ID)
+				phr->u.c.dwParam1 = pPad->dwPI;
+			else if (phm->u.c.wAttribute == HPI_PAD_PROGRAM_TYPE)
+				phr->u.c.dwParam1 = pPad->dwPTY;
+			else {
+				struct attribs {
+					u8 *pData;
+					unsigned int nSize;
+				};
+				struct attribs aDesc[] = {
+					{NULL, 0},
+					/* HPI_PAD_CHANNEL_NAME */
+					{pPad->cChannel, sizeof(pPad->
+								cChannel)}
+					,
+					/* HPI_PAD_ARTIST */
+					{pPad->cArtist, sizeof(pPad->cArtist)}
+					,
+					/* HPI_PAD_TITLE */
+					{pPad->cTitle, sizeof(pPad->cTitle)}
+					,
+					/* HPI_PAD_COMMENT */
+					{pPad->cComment, sizeof(pPad->
+								cComment)}
+					,
+				};
+
+				const u32 dwAttribute = phm->u.c.wAttribute;
+				const u32 dwIndex =
+					HPI_CTL_ATTR_INDEX(dwAttribute);
+				const u32 dwOffset = phm->u.c.dwParam1;
+				int nStringLength = 0;
+				int nRemainingChars = 0;
+
+				HPI_DEBUG_LOG(VERBOSE, "PADS control\n");
+
+				/* check the field type */
+				HPI_DEBUG_LOG(VERBOSE,
+					"PADS HPI_PADS_ %d\n", dwAttribute);
+
+				switch (dwAttribute) {
+				case HPI_PAD_CHANNEL_NAME:
+				case HPI_PAD_ARTIST:
+				case HPI_PAD_TITLE:
+				case HPI_PAD_COMMENT:
+					break;
+				default:
+					phr->wError = HPI_ERROR_INVALID_FUNC;
+				}
+				if (phr->wError)
+					break;
+
+				nStringLength = strlen(aDesc[dwIndex].pData);
+				if (dwOffset > (unsigned)nStringLength) {
+					phr->wError =
+						HPI_ERROR_INVALID_CONTROL_VALUE;
+					break;
+				}
+				HPI_DEBUG_LOG(VERBOSE,
+					"PADS memcpy (%d), offset %d \n",
+					8, dwOffset);
+				memcpy(&phr->u.cu.chars8.szData[0],
+					&aDesc[dwIndex].pData[dwOffset], 8);
+				nRemainingChars =
+					nStringLength - dwOffset - 8;
+				if (nRemainingChars < 0)
+					nRemainingChars = 0;
+				phr->u.cu.chars8.dwRemainingChars =
+					nRemainingChars;
+			}
+		}
 		break;
+#endif
 	default:
-		found = 0;	/* signal that message was not cached */
+		found = 0;
 		break;
 	}
-	if (found == 0)
-		HPI_DEBUG_LOG(VERBOSE, "Adap %d, Control %d, "
-			"Control type %d, Cached %d\n",
-			phm->wAdapterIndex, pC->ControlIndex,
-			pC->ControlType, found);
+	if (pI->ControlType && !found)
+		HPI_DEBUG_LOG(VERBOSE,
+			"Uncached Adap %d, Control %d, Control type %d\n",
+			phm->wAdapterIndex, pI->ControlIndex,
+			pI->ControlType);
 
 	return found;
 }
@@ -300,15 +514,24 @@ Volume and Level return the limited values in the response, so use these
 Multiplexer does so use sent values
 */
 void HpiSyncControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pCache,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 )
 {
-	if (phr->wError)
+	u16 wControlIndex;
+	struct hpi_control_cache_single *pC;
+	struct hpi_control_cache_info *pI;
+
+	if (!FindControl(phm, pCache, &pI, &wControlIndex))
 		return;
 
-	switch (pC->ControlType) {
+	/* pC is the default cached control strucure.
+	   May be cast to something else in the following switch statement.
+	 */
+	pC = (struct hpi_control_cache_single *)pI;
+
+	switch (pI->ControlType) {
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.wAttribute == HPI_VOLUME_GAIN) {
 			pC->u.v.anLog[0] = phr->u.c.anLogValue[0];
@@ -323,8 +546,8 @@ void HpiSyncControlCache(
 		}
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
-		/* mux does not return its setting on Set command. */
-		if (phm->u.c.wAttribute == HPI_MULTIPLEXER_SOURCE)
+		/* mode does not return its setting on Set command. */
+		if (phm->u.c.wAttribute == HPI_CHANNEL_MODE_MODE)
 			pC->u.m.wMode = (u16)phm->u.c.dwParam1;
 		break;
 	case HPI_CONTROL_LEVEL:
@@ -340,6 +563,7 @@ void HpiSyncControlCache(
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.wAttribute == HPI_AESEBURX_FORMAT)
 			pC->u.aes3rx.dwSource = phm->u.c.dwParam1;
+		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SOURCE)
 			pC->u.clk.wSource = (u16)phm->u.c.dwParam1;
@@ -358,6 +582,35 @@ void HpiSyncControlCache(
 		break;
 	}
 }
+struct hpi_control_cache *HpiAllocControlCache(
+	const u32 dwNumberOfControls,
+	const u32 dwSizeInBytes,
+	struct hpi_control_cache_info *pDSPControlBuffer
+)
+{
+	struct hpi_control_cache *pCache =
+		kmalloc(sizeof(*pCache), GFP_KERNEL);
+	pCache->dwCacheSizeInBytes = dwSizeInBytes;
+	pCache->dwControlCount = dwNumberOfControls;
+	pCache->pCache = (struct hpi_control_cache_single *)pDSPControlBuffer;
+	pCache->dwInit = 0;
+	pCache->pInfo =
+		kmalloc(sizeof(*pCache->pInfo) * pCache->dwControlCount,
+		GFP_KERNEL);
+	return pCache;
+}
+
+void HpiFreeControlCache(
+	struct hpi_control_cache *pCache
+)
+{
+	if ((pCache->dwInit) && (pCache->pInfo)) {
+		kfree(pCache->pInfo);
+		pCache->pInfo = NULL;
+		pCache->dwInit = 0;
+		kfree(pCache);
+	}
+}
 
 static void SubSysMessage(
 	struct hpi_message *phm,
diff --git a/pci/asihpi/hpicmn.h b/pci/asihpi/hpicmn.h
index 4b7692a..b0763e2 100644
--- a/pci/asihpi/hpicmn.h
+++ b/pci/asihpi/hpicmn.h
@@ -32,6 +32,18 @@ struct hpi_adapter_obj {
 	void *priv;
 };
 
+struct hpi_control_cache {
+	u32 dwInit;	       /**< indicates whether the
+				structures are initialized */
+	u32 dwControlCount;
+	u32 dwCacheSizeInBytes;
+	struct hpi_control_cache_info
+	**pInfo;		/**< pointer to allocated memory of
+				lookup pointers. */
+	struct hpi_control_cache_single
+	*pCache;		/**< pointer to DSP's control cache. */
+};
+
 struct hpi_adapter_obj *HpiFindAdapter(
 	u16 wAdapterIndex
 );
@@ -44,12 +56,22 @@ void HpiDeleteAdapter(
 );
 
 short HpiCheckControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pC,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
+struct hpi_control_cache *HpiAllocControlCache(
+	const u32 dwNumberOfControls,
+	const u32 dwSizeInBytes,
+	struct hpi_control_cache_info
+	*pDSPControlBuffer
+);
+void HpiFreeControlCache(
+	struct hpi_control_cache *pCache
+);
+
 void HpiSyncControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pC,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
@@ -57,3 +79,9 @@ u16 HpiValidateResponse(
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
+short HpiCheckBufferMapping(
+	struct hpi_control_cache *pCache,
+	struct hpi_message *phm,
+	void **p,
+	unsigned int *pN
+);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH - ASIHPI 8/8] Checkpatch tweaks
  2008-06-05  4:07           ` [PATCH - ASIHPI 7/8] Support variable size cached control information linux
@ 2008-06-05  4:07             ` linux
  0 siblings, 0 replies; 11+ messages in thread
From: linux @ 2008-06-05  4:07 UTC (permalink / raw)
  To: tiwai; +Cc: Eliot Blennerhassett, alsa-devel

From: Eliot Blennerhassett <eblennerhassett@audioscience.com>


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

diff --git a/pci/asihpi/asihpi.c b/pci/asihpi/asihpi.c
index 3ffc47b..8cbefab 100644
--- a/pci/asihpi/asihpi.c
+++ b/pci/asihpi/asihpi.c
@@ -98,11 +98,11 @@ MODULE_PARM_DESC(enable_hpi_hwdep,
 
 /* identify driver */
 #ifdef KERNEL_ALSA_BUILD
-static char * build_info = "Built using headers from kernel source";
+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";
+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
@@ -382,14 +382,16 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
 		rate_min = 8000;
 		rate_max = 100000;
 	} else {
-		/* on cards without SRC, valid rates are determined by sampleclock */
+		/* 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))
+		for (idx = 0; idx < 100; idx++) {
+			if (HPI_ControlQuery(phSubSys, hControl,
+				HPI_SAMPLECLOCK_SAMPLERATE, idx, 0,
+				&sampleRate))
 				break;
 
 			rate_min = min(rate_min, sampleRate);
@@ -441,7 +443,8 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
 		}
 	}
 
-	/*printk(KERN_INFO "Supported rates %X %d %d\n", rates, rate_min, rate_max); */
+	/*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;
@@ -880,7 +883,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,
-						struct snd_pcm_hardware * pcmhw)
+						struct snd_pcm_hardware *pcmhw)
 {
   struct hpi_format hpi_format;
 	u16 wFormat;
@@ -906,7 +909,8 @@ 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))
-			pcmhw->formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
+			pcmhw->formats |=
+				(1ULL << hpi_to_alsa_formats[wFormat]);
 	}
 }
 
@@ -1122,12 +1126,14 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
 	for (wFormat = HPI_FORMAT_PCM8_UNSIGNED;
 		wFormat <= HPI_FORMAT_PCM24_SIGNED; wFormat++) {
 
-		HPI_FormatCreate(&hpi_format, 2, wFormat, dwSampleRate, 128000, 0);
-		err =
-		    HPI_InStreamQueryFormat(phSubSys, hStream,
+		HPI_FormatCreate(
+			&hpi_format, 2, wFormat, dwSampleRate, 128000, 0);
+
+		err = HPI_InStreamQueryFormat(phSubSys, hStream,
 					    &hpi_format);
 		if (!err)
-			pcmhw->formats |= (1ULL << hpi_to_alsa_formats[wFormat]);
+			pcmhw->formats |=
+				(1ULL << hpi_to_alsa_formats[wFormat]);
 	}
 }
 
@@ -2790,7 +2796,7 @@ int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
 	asihpi->support_mmap = (!err);
 
 	asihpi->support_mrx = (((asihpi->wType & 0xFF00) == 0x8900) ||
-	                       ((asihpi->wType & 0xF000) == 0x6000));
+					((asihpi->wType & 0xF000) == 0x6000));
 
 
 	printk(KERN_INFO "Supports mmap:%d grouping:%d\n",
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH - ASIHPI 1/8] Common init files for HPI
  2008-06-05  4:06 [PATCH - ASIHPI 1/8] Common init files for HPI linux
  2008-06-05  4:06 ` [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range linux
@ 2008-06-05  4:34 ` Eliot Blennerhassett
  2008-06-06 10:34   ` Takashi Iwai
  1 sibling, 1 reply; 11+ messages in thread
From: Eliot Blennerhassett @ 2008-06-05  4:34 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel

Hi Takashi,

this patchset updates ALSA to our current 3.10.00 release.
Matching firmware is here, please use it to update alsa-firmware
http://audioscience.com/internet/download/firmware/dspbins31000.zip

One thing I haven't figured out how to get git to include a patch for deletion 
of a file? Anyway, current repo hpimod.c is replaced with hpioctl.c (you 
could consider this a rename then update)

I have restructured code a bit so that asihpi.c is the "master" module file, 
that calls utility functions in hpioctl.c for setting up HPI, and handling 
hpi ioctl via hwdep.


regards

Eliot

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH - ASIHPI 1/8] Common init files for HPI
  2008-06-05  4:34 ` [PATCH - ASIHPI 1/8] Common init files for HPI Eliot Blennerhassett
@ 2008-06-06 10:34   ` Takashi Iwai
  2008-06-11 23:22     ` Eliot Blennerhassett
  0 siblings, 1 reply; 11+ messages in thread
From: Takashi Iwai @ 2008-06-06 10:34 UTC (permalink / raw)
  To: Eliot Blennerhassett; +Cc: alsa-devel

At Thu, 05 Jun 2008 16:34:25 +1200,
Eliot Blennerhassett wrote:
> 
> Hi Takashi,
> 
> this patchset updates ALSA to our current 3.10.00 release.
> Matching firmware is here, please use it to update alsa-firmware
> http://audioscience.com/internet/download/firmware/dspbins31000.zip

Thanks, updated both alsa-driver and alsa-firmware repos.

> One thing I haven't figured out how to get git to include a patch for deletion 
> of a file? Anyway, current repo hpimod.c is replaced with hpioctl.c (you 
> could consider this a rename then update)

Just use git-mv, and git-format-patch would give you a right patch.
(And since I didn't notice this beforehand, I had to re-commit the
 tree to handle it...)

> I have restructured code a bit so that asihpi.c is the "master" module file, 
> that calls utility functions in hpioctl.c for setting up HPI, and handling 
> hpi ioctl via hwdep.

This looks good!  Let's continue to reshape a bit for merging to the
upstream.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH - ASIHPI 1/8] Common init files for HPI
  2008-06-06 10:34   ` Takashi Iwai
@ 2008-06-11 23:22     ` Eliot Blennerhassett
  0 siblings, 0 replies; 11+ messages in thread
From: Eliot Blennerhassett @ 2008-06-11 23:22 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

Takashi Iwai wrote:
> At Thu, 05 Jun 2008 16:34:25 +1200,
> Eliot Blennerhassett wrote:
>> I have restructured code a bit so that asihpi.c is the "master" module file, 
>> that calls utility functions in hpioctl.c for setting up HPI, and handling 
>> hpi ioctl via hwdep.
> 
> This looks good!  Let's continue to reshape a bit for merging to the
> upstream.

Thanks Takashi.

What sort of reshape do you have in mind?  *me* Holds breath...

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2008-06-11 23:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-05  4:06 [PATCH - ASIHPI 1/8] Common init files for HPI linux
2008-06-05  4:06 ` [PATCH - ASIHPI 2/8] Fix sampleclock source get. Fix volume control dB range linux
2008-06-05  4:06   ` [PATCH - ASIHPI 3/8] Replace hpimod.c with hpioctl.c linux
2008-06-05  4:06     ` [PATCH - ASIHPI 4/8] Include pci table again, avoiding warning about extern linux
2008-06-05  4:06       ` [PATCH - ASIHPI 5/8] Log warning if DSP code version doesn't match driver linux
2008-06-05  4:06         ` [PATCH - ASIHPI 6/8] Version 3.10.00. Add new functions for HD radio tuner, and for firmware debug linux
2008-06-05  4:07           ` [PATCH - ASIHPI 7/8] Support variable size cached control information linux
2008-06-05  4:07             ` [PATCH - ASIHPI 8/8] Checkpatch tweaks linux
2008-06-05  4:34 ` [PATCH - ASIHPI 1/8] Common init files for HPI Eliot Blennerhassett
2008-06-06 10:34   ` Takashi Iwai
2008-06-11 23:22     ` Eliot Blennerhassett

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.