[alsa-devel] [PATCH - ASIHPI 1/8] Common init files for HPI
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) + + /*********************************************************** +*/
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) +
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
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;
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);
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,
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 +);
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",
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
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
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...
participants (3)
-
Eliot Blennerhassett
-
linux@audioscience.com
-
Takashi Iwai