[ALSA] hda-intel - Add hwdep interface

Added a hwdep interface for each codec (enabled per kconfig).
This interface can be used for reading/writing HD-audio verbs
and other purposes as future extensions.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
Takashi Iwai 2007-07-27 18:58:06 +02:00 committed by Jaroslav Kysela
parent ef5fa1a49f
commit 2807314d46
8 changed files with 192 additions and 5 deletions

View File

@ -92,6 +92,7 @@ enum {
SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC

44
include/sound/hda_hwdep.h Normal file
View File

@ -0,0 +1,44 @@
/*
* HWDEP Interface for HD-audio codec
*
* Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This driver 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
*/
#ifndef __SOUND_HDA_HWDEP_H
#define __SOUND_HDA_HWDEP_H
#define HDA_HWDEP_VERSION ((1 << 16) | (0 << 8) | (0 << 0)) /* 1.0.0 */
/* verb */
#define HDA_REG_NID_SHIFT 24
#define HDA_REG_VERB_SHIFT 8
#define HDA_REG_VAL_SHIFT 0
#define HDA_VERB(nid,verb,param) ((nid)<<24 | (verb)<<8 | (param))
struct hda_verb_ioctl {
u32 verb; /* HDA_VERB() */
u32 res; /* response */
};
/*
* ioctls
*/
#define HDA_IOCTL_PVERSION _IOR('H', 0x10, int)
#define HDA_IOCTL_VERB_WRITE _IOWR('H', 0x11, struct hda_verb_ioctl)
#define HDA_IOCTL_GET_WCAP _IOWR('H', 0x12, struct hda_verb_ioctl)
#endif

View File

@ -500,6 +500,15 @@ config SND_HDA_INTEL
To compile this driver as a module, choose M here: the module
will be called snd-hda-intel.
config SND_HDA_HWDEP
bool "Build hwdep interface for HD-audio driver"
depends on SND_HDA_INTEL
select SND_HWDEP
help
Say Y here to build a hwdep interface for HD-audio driver.
This interface can be used for out-of-bound communication
with codesc for debugging purposes.
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
depends on SND

View File

@ -1,8 +1,8 @@
snd-hda-intel-objs := hda_intel.o
snd-hda-intel-y := hda_intel.o
# since snd-hda-intel is the only driver using hda-codec,
# merge it into a single module although it was originally
# designed to be individual modules
snd-hda-intel-objs += hda_codec.o \
snd-hda-intel-y += hda_codec.o \
hda_generic.o \
patch_realtek.o \
patch_cmedia.o \
@ -12,8 +12,7 @@ snd-hda-intel-objs += hda_codec.o \
patch_atihdmi.o \
patch_conexant.o \
patch_via.o
ifdef CONFIG_PROC_FS
snd-hda-intel-objs += hda_proc.o
endif
snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o

View File

@ -31,6 +31,7 @@
#include <sound/tlv.h>
#include <sound/initval.h>
#include "hda_local.h"
#include <sound/hda_hwdep.h>
/*
@ -594,6 +595,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
init_unsol_queue(bus);
snd_hda_codec_proc_new(codec);
#ifdef CONFIG_SND_HDA_HWDEP
snd_hda_create_hwdep(codec);
#endif
sprintf(component, "HDA:%08x", codec->vendor_id);
snd_component_add(codec->bus->card, component);

View File

@ -24,6 +24,7 @@
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/hwdep.h>
/*
* nodes
@ -566,6 +567,8 @@ struct hda_codec {
unsigned int spdif_status; /* IEC958 status bits */
unsigned short spdif_ctls; /* SPDIF control bits */
unsigned int spdif_in_enable; /* SPDIF input enable? */
struct snd_hwdep *hwdep; /* assigned hwdep device */
};
/* direction */

122
sound/pci/hda/hda_hwdep.c Normal file
View File

@ -0,0 +1,122 @@
/*
* HWDEP Interface for HD-audio codec
*
* Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This driver 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
*/
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/compat.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include <sound/hda_hwdep.h>
/*
* write/read an out-of-bound verb
*/
static int verb_write_ioctl(struct hda_codec *codec,
struct hda_verb_ioctl __user *arg)
{
u32 verb, res;
if (get_user(verb, &arg->verb))
return -EFAULT;
res = snd_hda_codec_read(codec, verb >> 24, 0,
(verb >> 8) & 0xffff, verb & 0xff);
if (put_user(res, &arg->res))
return -EFAULT;
return 0;
}
static int get_wcap_ioctl(struct hda_codec *codec,
struct hda_verb_ioctl __user *arg)
{
u32 verb, res;
if (get_user(verb, &arg->verb))
return -EFAULT;
res = get_wcaps(codec, verb >> 24);
if (put_user(res, &arg->res))
return -EFAULT;
return 0;
}
/*
*/
static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hda_codec *codec = hw->private_data;
void __user *argp = (void __user *)arg;
switch (cmd) {
case HDA_IOCTL_PVERSION:
return put_user(HDA_HWDEP_VERSION, (int __user *)argp);
case HDA_IOCTL_VERB_WRITE:
return verb_write_ioctl(codec, argp);
case HDA_IOCTL_GET_WCAP:
return get_wcap_ioctl(codec, argp);
}
return -ENOIOCTLCMD;
}
#ifdef CONFIG_COMPAT
static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
return hda_hwdep_ioctl(hw, file, cmd, compat_ptr(arg));
}
#endif
static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
#ifndef CONFIG_SND_DEBUG_DETECT
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
#endif
return 0;
}
int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
{
char hwname[16];
struct snd_hwdep *hwdep;
int err;
sprintf(hwname, "HDA Codec %d", codec->addr);
err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep);
if (err < 0)
return err;
codec->hwdep = hwdep;
sprintf(hwdep->name, "HDA Codec %d", codec->addr);
hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
hwdep->private_data = codec;
hwdep->exclusive = 1;
hwdep->ops.open = hda_hwdep_open;
hwdep->ops.ioctl = hda_hwdep_ioctl;
#ifdef CONFIG_COMPAT
hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
#endif
return 0;
}

View File

@ -313,4 +313,9 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
/*
* hwdep interface
*/
int snd_hda_create_hwdep(struct hda_codec *codec);
#endif /* __SOUND_HDA_LOCAL_H */