forked from Minki/linux
719f82d398
Added the support of AudioScience ASI boards. The driver has been tested for years on alsa-driver external tree, now finally got merged to the kernel. Signed-off-by: Eliot Blennerhassett <eblennerhassett@audioscience.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
226 lines
5.8 KiB
C
226 lines
5.8 KiB
C
/************************************************************************
|
|
|
|
AudioScience HPI driver
|
|
Copyright (C) 1997-2010 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
|
|
|
|
Debug macro translation.
|
|
|
|
************************************************************************/
|
|
|
|
#include "hpi_internal.h"
|
|
#include "hpidebug.h"
|
|
|
|
/* Debug level; 0 quiet; 1 informative, 2 debug, 3 verbose debug. */
|
|
int hpi_debug_level = HPI_DEBUG_LEVEL_DEFAULT;
|
|
|
|
void hpi_debug_init(void)
|
|
{
|
|
printk(KERN_INFO "debug start\n");
|
|
}
|
|
|
|
int hpi_debug_level_set(int level)
|
|
{
|
|
int old_level;
|
|
|
|
old_level = hpi_debug_level;
|
|
hpi_debug_level = level;
|
|
return old_level;
|
|
}
|
|
|
|
int hpi_debug_level_get(void)
|
|
{
|
|
return hpi_debug_level;
|
|
}
|
|
|
|
#ifdef HPIOS_DEBUG_PRINT
|
|
/* implies OS has no printf-like function */
|
|
#include <stdarg.h>
|
|
|
|
void hpi_debug_printf(char *fmt, ...)
|
|
{
|
|
va_list arglist;
|
|
char buffer[128];
|
|
|
|
va_start(arglist, fmt);
|
|
|
|
if (buffer[0])
|
|
HPIOS_DEBUG_PRINT(buffer);
|
|
va_end(arglist);
|
|
}
|
|
#endif
|
|
|
|
struct treenode {
|
|
void *array;
|
|
unsigned int num_elements;
|
|
};
|
|
|
|
#define make_treenode_from_array(nodename, array) \
|
|
static void *tmp_strarray_##nodename[] = array; \
|
|
static struct treenode nodename = { \
|
|
&tmp_strarray_##nodename, \
|
|
ARRAY_SIZE(tmp_strarray_##nodename) \
|
|
};
|
|
|
|
#define get_treenode_elem(node_ptr, idx, type) \
|
|
(&(*((type *)(node_ptr)->array)[idx]))
|
|
|
|
make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
|
|
|
|
make_treenode_from_array(hpi_subsys_strings, HPI_SUBSYS_STRINGS)
|
|
make_treenode_from_array(hpi_adapter_strings, HPI_ADAPTER_STRINGS)
|
|
make_treenode_from_array(hpi_istream_strings, HPI_ISTREAM_STRINGS)
|
|
make_treenode_from_array(hpi_ostream_strings, HPI_OSTREAM_STRINGS)
|
|
make_treenode_from_array(hpi_mixer_strings, HPI_MIXER_STRINGS)
|
|
make_treenode_from_array(hpi_node_strings,
|
|
{
|
|
"NODE is invalid object"})
|
|
|
|
make_treenode_from_array(hpi_control_strings, HPI_CONTROL_STRINGS)
|
|
make_treenode_from_array(hpi_nvmemory_strings, HPI_OBJ_STRINGS)
|
|
make_treenode_from_array(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS)
|
|
make_treenode_from_array(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS)
|
|
make_treenode_from_array(hpi_clock_strings, HPI_CLOCK_STRINGS)
|
|
make_treenode_from_array(hpi_profile_strings, HPI_PROFILE_STRINGS)
|
|
make_treenode_from_array(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS)
|
|
#define HPI_FUNCTION_STRINGS \
|
|
{ \
|
|
&hpi_subsys_strings,\
|
|
&hpi_adapter_strings,\
|
|
&hpi_ostream_strings,\
|
|
&hpi_istream_strings,\
|
|
&hpi_mixer_strings,\
|
|
&hpi_node_strings,\
|
|
&hpi_control_strings,\
|
|
&hpi_nvmemory_strings,\
|
|
&hpi_digitalio_strings,\
|
|
&hpi_watchdog_strings,\
|
|
&hpi_clock_strings,\
|
|
&hpi_profile_strings,\
|
|
&hpi_control_strings, \
|
|
&hpi_asyncevent_strings \
|
|
};
|
|
make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
|
|
|
|
compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
|
|
|
|
static char *hpi_function_string(unsigned int function)
|
|
{
|
|
unsigned int object;
|
|
struct treenode *tmp;
|
|
|
|
object = function / HPI_OBJ_FUNCTION_SPACING;
|
|
function = function - object * HPI_OBJ_FUNCTION_SPACING;
|
|
|
|
if (object == 0 || object == HPI_OBJ_NODE
|
|
|| object > hpi_function_strings.num_elements)
|
|
return "invalid object";
|
|
|
|
tmp = get_treenode_elem(&hpi_function_strings, object - 1,
|
|
struct treenode *);
|
|
|
|
if (function == 0 || function > tmp->num_elements)
|
|
return "invalid function";
|
|
|
|
return get_treenode_elem(tmp, function - 1, char *);
|
|
}
|
|
|
|
void hpi_debug_message(struct hpi_message *phm, char *sz_fileline)
|
|
{
|
|
if (phm) {
|
|
if ((phm->object <= HPI_OBJ_MAXINDEX) && phm->object) {
|
|
u16 index = 0;
|
|
u16 attrib = 0;
|
|
int is_control = 0;
|
|
|
|
index = phm->obj_index;
|
|
switch (phm->object) {
|
|
case HPI_OBJ_ADAPTER:
|
|
case HPI_OBJ_PROFILE:
|
|
break;
|
|
case HPI_OBJ_MIXER:
|
|
if (phm->function ==
|
|
HPI_MIXER_GET_CONTROL_BY_INDEX)
|
|
index = phm->u.m.control_index;
|
|
break;
|
|
case HPI_OBJ_OSTREAM:
|
|
case HPI_OBJ_ISTREAM:
|
|
break;
|
|
|
|
case HPI_OBJ_CONTROLEX:
|
|
case HPI_OBJ_CONTROL:
|
|
if (phm->version == 1)
|
|
attrib = HPI_CTL_ATTR(UNIVERSAL, 1);
|
|
else
|
|
attrib = phm->u.c.attribute;
|
|
is_control = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (is_control && (attrib & 0xFF00)) {
|
|
int control_type = (attrib & 0xFF00) >> 8;
|
|
int attr_index = HPI_CTL_ATTR_INDEX(attrib);
|
|
/* note the KERN facility level
|
|
is in szFileline already */
|
|
printk("%s adapter %d %s "
|
|
"ctrl_index x%04x %s %d\n",
|
|
sz_fileline, phm->adapter_index,
|
|
hpi_function_string(phm->function),
|
|
index,
|
|
get_treenode_elem
|
|
(&hpi_control_type_strings,
|
|
control_type, char *),
|
|
attr_index);
|
|
|
|
} else
|
|
printk("%s adapter %d %s "
|
|
"idx x%04x attr x%04x \n",
|
|
sz_fileline, phm->adapter_index,
|
|
hpi_function_string(phm->function),
|
|
index, attrib);
|
|
} else {
|
|
printk("adap=%d, invalid obj=%d, func=0x%x\n",
|
|
phm->adapter_index, phm->object,
|
|
phm->function);
|
|
}
|
|
} else
|
|
printk(KERN_ERR
|
|
"NULL message pointer to hpi_debug_message!\n");
|
|
}
|
|
|
|
void hpi_debug_data(u16 *pdata, u32 len)
|
|
{
|
|
u32 i;
|
|
int j;
|
|
int k;
|
|
int lines;
|
|
int cols = 8;
|
|
|
|
lines = (len + cols - 1) / cols;
|
|
if (lines > 8)
|
|
lines = 8;
|
|
|
|
for (i = 0, j = 0; j < lines; j++) {
|
|
printk(KERN_DEBUG "%p:", (pdata + i));
|
|
|
|
for (k = 0; k < cols && i < len; i++, k++)
|
|
printk("%s%04x", k == 0 ? "" : " ", pdata[i]);
|
|
|
|
printk("\n");
|
|
}
|
|
}
|