* [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.