Commit 2807314d467e7dd929c42050031aabbd28e78f0b
Committed by
Jaroslav Kysela
1 parent
ef5fa1a49f
Exists in
master
and in
4 other branches
[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>
Showing 8 changed files with 192 additions and 5 deletions Side-by-side Diff
include/sound/asound.h
... | ... | @@ -92,6 +92,7 @@ |
92 | 92 | SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ |
93 | 93 | SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ |
94 | 94 | SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ |
95 | + SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ | |
95 | 96 | |
96 | 97 | /* Don't forget to change the following: */ |
97 | 98 | SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC |
include/sound/hda_hwdep.h
1 | +/* | |
2 | + * HWDEP Interface for HD-audio codec | |
3 | + * | |
4 | + * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de> | |
5 | + * | |
6 | + * This driver is free software; you can redistribute it and/or modify | |
7 | + * it under the terms of the GNU General Public License as published by | |
8 | + * the Free Software Foundation; either version 2 of the License, or | |
9 | + * (at your option) any later version. | |
10 | + * | |
11 | + * This driver is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + * | |
16 | + * You should have received a copy of the GNU General Public License | |
17 | + * along with this program; if not, write to the Free Software | |
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | + */ | |
20 | + | |
21 | +#ifndef __SOUND_HDA_HWDEP_H | |
22 | +#define __SOUND_HDA_HWDEP_H | |
23 | + | |
24 | +#define HDA_HWDEP_VERSION ((1 << 16) | (0 << 8) | (0 << 0)) /* 1.0.0 */ | |
25 | + | |
26 | +/* verb */ | |
27 | +#define HDA_REG_NID_SHIFT 24 | |
28 | +#define HDA_REG_VERB_SHIFT 8 | |
29 | +#define HDA_REG_VAL_SHIFT 0 | |
30 | +#define HDA_VERB(nid,verb,param) ((nid)<<24 | (verb)<<8 | (param)) | |
31 | + | |
32 | +struct hda_verb_ioctl { | |
33 | + u32 verb; /* HDA_VERB() */ | |
34 | + u32 res; /* response */ | |
35 | +}; | |
36 | + | |
37 | +/* | |
38 | + * ioctls | |
39 | + */ | |
40 | +#define HDA_IOCTL_PVERSION _IOR('H', 0x10, int) | |
41 | +#define HDA_IOCTL_VERB_WRITE _IOWR('H', 0x11, struct hda_verb_ioctl) | |
42 | +#define HDA_IOCTL_GET_WCAP _IOWR('H', 0x12, struct hda_verb_ioctl) | |
43 | + | |
44 | +#endif |
sound/pci/Kconfig
... | ... | @@ -500,6 +500,15 @@ |
500 | 500 | To compile this driver as a module, choose M here: the module |
501 | 501 | will be called snd-hda-intel. |
502 | 502 | |
503 | +config SND_HDA_HWDEP | |
504 | + bool "Build hwdep interface for HD-audio driver" | |
505 | + depends on SND_HDA_INTEL | |
506 | + select SND_HWDEP | |
507 | + help | |
508 | + Say Y here to build a hwdep interface for HD-audio driver. | |
509 | + This interface can be used for out-of-bound communication | |
510 | + with codesc for debugging purposes. | |
511 | + | |
503 | 512 | config SND_HDSP |
504 | 513 | tristate "RME Hammerfall DSP Audio" |
505 | 514 | depends on SND |
sound/pci/hda/Makefile
1 | -snd-hda-intel-objs := hda_intel.o | |
1 | +snd-hda-intel-y := hda_intel.o | |
2 | 2 | # since snd-hda-intel is the only driver using hda-codec, |
3 | 3 | # merge it into a single module although it was originally |
4 | 4 | # designed to be individual modules |
5 | -snd-hda-intel-objs += hda_codec.o \ | |
5 | +snd-hda-intel-y += hda_codec.o \ | |
6 | 6 | hda_generic.o \ |
7 | 7 | patch_realtek.o \ |
8 | 8 | patch_cmedia.o \ |
... | ... | @@ -12,9 +12,8 @@ |
12 | 12 | patch_atihdmi.o \ |
13 | 13 | patch_conexant.o \ |
14 | 14 | patch_via.o |
15 | -ifdef CONFIG_PROC_FS | |
16 | -snd-hda-intel-objs += hda_proc.o | |
17 | -endif | |
15 | +snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o | |
16 | +snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | |
18 | 17 | |
19 | 18 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o |
sound/pci/hda/hda_codec.c
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | #include <sound/tlv.h> |
32 | 32 | #include <sound/initval.h> |
33 | 33 | #include "hda_local.h" |
34 | +#include <sound/hda_hwdep.h> | |
34 | 35 | |
35 | 36 | |
36 | 37 | /* |
... | ... | @@ -594,6 +595,9 @@ |
594 | 595 | init_unsol_queue(bus); |
595 | 596 | |
596 | 597 | snd_hda_codec_proc_new(codec); |
598 | +#ifdef CONFIG_SND_HDA_HWDEP | |
599 | + snd_hda_create_hwdep(codec); | |
600 | +#endif | |
597 | 601 | |
598 | 602 | sprintf(component, "HDA:%08x", codec->vendor_id); |
599 | 603 | snd_component_add(codec->bus->card, component); |
sound/pci/hda/hda_codec.h
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <sound/info.h> |
25 | 25 | #include <sound/control.h> |
26 | 26 | #include <sound/pcm.h> |
27 | +#include <sound/hwdep.h> | |
27 | 28 | |
28 | 29 | /* |
29 | 30 | * nodes |
... | ... | @@ -566,6 +567,8 @@ |
566 | 567 | unsigned int spdif_status; /* IEC958 status bits */ |
567 | 568 | unsigned short spdif_ctls; /* SPDIF control bits */ |
568 | 569 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
570 | + | |
571 | + struct snd_hwdep *hwdep; /* assigned hwdep device */ | |
569 | 572 | }; |
570 | 573 | |
571 | 574 | /* direction */ |
sound/pci/hda/hda_hwdep.c
1 | +/* | |
2 | + * HWDEP Interface for HD-audio codec | |
3 | + * | |
4 | + * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de> | |
5 | + * | |
6 | + * This driver is free software; you can redistribute it and/or modify | |
7 | + * it under the terms of the GNU General Public License as published by | |
8 | + * the Free Software Foundation; either version 2 of the License, or | |
9 | + * (at your option) any later version. | |
10 | + * | |
11 | + * This driver is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + * | |
16 | + * You should have received a copy of the GNU General Public License | |
17 | + * along with this program; if not, write to the Free Software | |
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | + */ | |
20 | + | |
21 | +#include <sound/driver.h> | |
22 | +#include <linux/init.h> | |
23 | +#include <linux/slab.h> | |
24 | +#include <linux/pci.h> | |
25 | +#include <linux/compat.h> | |
26 | +#include <linux/mutex.h> | |
27 | +#include <sound/core.h> | |
28 | +#include "hda_codec.h" | |
29 | +#include "hda_local.h" | |
30 | +#include <sound/hda_hwdep.h> | |
31 | + | |
32 | +/* | |
33 | + * write/read an out-of-bound verb | |
34 | + */ | |
35 | +static int verb_write_ioctl(struct hda_codec *codec, | |
36 | + struct hda_verb_ioctl __user *arg) | |
37 | +{ | |
38 | + u32 verb, res; | |
39 | + | |
40 | + if (get_user(verb, &arg->verb)) | |
41 | + return -EFAULT; | |
42 | + res = snd_hda_codec_read(codec, verb >> 24, 0, | |
43 | + (verb >> 8) & 0xffff, verb & 0xff); | |
44 | + if (put_user(res, &arg->res)) | |
45 | + return -EFAULT; | |
46 | + return 0; | |
47 | +} | |
48 | + | |
49 | +static int get_wcap_ioctl(struct hda_codec *codec, | |
50 | + struct hda_verb_ioctl __user *arg) | |
51 | +{ | |
52 | + u32 verb, res; | |
53 | + | |
54 | + if (get_user(verb, &arg->verb)) | |
55 | + return -EFAULT; | |
56 | + res = get_wcaps(codec, verb >> 24); | |
57 | + if (put_user(res, &arg->res)) | |
58 | + return -EFAULT; | |
59 | + return 0; | |
60 | +} | |
61 | + | |
62 | + | |
63 | +/* | |
64 | + */ | |
65 | +static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | |
66 | + unsigned int cmd, unsigned long arg) | |
67 | +{ | |
68 | + struct hda_codec *codec = hw->private_data; | |
69 | + void __user *argp = (void __user *)arg; | |
70 | + | |
71 | + switch (cmd) { | |
72 | + case HDA_IOCTL_PVERSION: | |
73 | + return put_user(HDA_HWDEP_VERSION, (int __user *)argp); | |
74 | + case HDA_IOCTL_VERB_WRITE: | |
75 | + return verb_write_ioctl(codec, argp); | |
76 | + case HDA_IOCTL_GET_WCAP: | |
77 | + return get_wcap_ioctl(codec, argp); | |
78 | + } | |
79 | + return -ENOIOCTLCMD; | |
80 | +} | |
81 | + | |
82 | +#ifdef CONFIG_COMPAT | |
83 | +static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file, | |
84 | + unsigned int cmd, unsigned long arg) | |
85 | +{ | |
86 | + return hda_hwdep_ioctl(hw, file, cmd, compat_ptr(arg)); | |
87 | +} | |
88 | +#endif | |
89 | + | |
90 | +static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |
91 | +{ | |
92 | +#ifndef CONFIG_SND_DEBUG_DETECT | |
93 | + if (!capable(CAP_SYS_RAWIO)) | |
94 | + return -EACCES; | |
95 | +#endif | |
96 | + return 0; | |
97 | +} | |
98 | + | |
99 | +int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |
100 | +{ | |
101 | + char hwname[16]; | |
102 | + struct snd_hwdep *hwdep; | |
103 | + int err; | |
104 | + | |
105 | + sprintf(hwname, "HDA Codec %d", codec->addr); | |
106 | + err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep); | |
107 | + if (err < 0) | |
108 | + return err; | |
109 | + codec->hwdep = hwdep; | |
110 | + sprintf(hwdep->name, "HDA Codec %d", codec->addr); | |
111 | + hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | |
112 | + hwdep->private_data = codec; | |
113 | + hwdep->exclusive = 1; | |
114 | + | |
115 | + hwdep->ops.open = hda_hwdep_open; | |
116 | + hwdep->ops.ioctl = hda_hwdep_ioctl; | |
117 | +#ifdef CONFIG_COMPAT | |
118 | + hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | |
119 | +#endif | |
120 | + | |
121 | + return 0; | |
122 | +} |
sound/pci/hda/hda_local.h