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