Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
ec6659c3
Commit
ec6659c3
authored
Mar 24, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/vmaster-update' into for-linus
parents
c944a93d
79c7cdd5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
97 additions
and
21 deletions
+97
-21
Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+4
-0
include/sound/control.h
include/sound/control.h
+50
-2
sound/core/vmaster.c
sound/core/vmaster.c
+43
-19
No files found.
Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
View file @
ec6659c3
...
@@ -71,6 +71,10 @@
...
@@ -71,6 +71,10 @@
!Esound/pci/ac97/ac97_codec.c
!Esound/pci/ac97/ac97_codec.c
!Esound/pci/ac97/ac97_pcm.c
!Esound/pci/ac97/ac97_pcm.c
</sect1>
</sect1>
<sect1><title>
Virtual Master Control API
</title>
!Esound/core/vmaster.c
!Iinclude/sound/control.h
</sect1>
</chapter>
</chapter>
<chapter><title>
MIDI API
</title>
<chapter><title>
MIDI API
</title>
<sect1><title>
Raw MIDI API
</title>
<sect1><title>
Raw MIDI API
</title>
...
...
include/sound/control.h
View file @
ec6659c3
...
@@ -171,6 +171,54 @@ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
...
@@ -171,6 +171,54 @@ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
*/
*/
struct
snd_kcontrol
*
snd_ctl_make_virtual_master
(
char
*
name
,
struct
snd_kcontrol
*
snd_ctl_make_virtual_master
(
char
*
name
,
const
unsigned
int
*
tlv
);
const
unsigned
int
*
tlv
);
int
snd_ctl_add_slave
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
);
int
_snd_ctl_add_slave
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
,
unsigned
int
flags
);
/* optional flags for slave */
#define SND_CTL_SLAVE_NEED_UPDATE (1 << 0)
/**
* snd_ctl_add_slave - Add a virtual slave control
* @master: vmaster element
* @slave: slave element to add
*
* Add a virtual slave control to the given master element created via
* snd_ctl_create_virtual_master() beforehand.
* Returns zero if successful or a negative error code.
*
* All slaves must be the same type (returning the same information
* via info callback). The fucntion doesn't check it, so it's your
* responsibility.
*
* Also, some additional limitations:
* at most two channels,
* logarithmic volume control (dB level) thus no linear volume,
* master can only attenuate the volume without gain
*/
static
inline
int
snd_ctl_add_slave
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
)
{
return
_snd_ctl_add_slave
(
master
,
slave
,
0
);
}
/**
* snd_ctl_add_slave_uncached - Add a virtual slave control
* @master: vmaster element
* @slave: slave element to add
*
* Add a virtual slave control to the given master.
* Unlike snd_ctl_add_slave(), the element added via this function
* is supposed to have volatile values, and get callback is called
* at each time quried from the master.
*
* When the control peeks the hardware values directly and the value
* can be changed by other means than the put callback of the element,
* this function should be used to keep the value always up-to-date.
*/
static
inline
int
snd_ctl_add_slave_uncached
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
)
{
return
_snd_ctl_add_slave
(
master
,
slave
,
SND_CTL_SLAVE_NEED_UPDATE
);
}
#endif
/* __SOUND_CONTROL_H */
#endif
/* __SOUND_CONTROL_H */
sound/core/vmaster.c
View file @
ec6659c3
...
@@ -50,18 +50,38 @@ struct link_slave {
...
@@ -50,18 +50,38 @@ struct link_slave {
struct
link_master
*
master
;
struct
link_master
*
master
;
struct
link_ctl_info
info
;
struct
link_ctl_info
info
;
int
vals
[
2
];
/* current values */
int
vals
[
2
];
/* current values */
unsigned
int
flags
;
struct
snd_kcontrol
slave
;
/* the copy of original control entry */
struct
snd_kcontrol
slave
;
/* the copy of original control entry */
};
};
static
int
slave_update
(
struct
link_slave
*
slave
)
{
struct
snd_ctl_elem_value
*
uctl
;
int
err
,
ch
;
uctl
=
kmalloc
(
sizeof
(
*
uctl
),
GFP_KERNEL
);
if
(
!
uctl
)
return
-
ENOMEM
;
uctl
->
id
=
slave
->
slave
.
id
;
err
=
slave
->
slave
.
get
(
&
slave
->
slave
,
uctl
);
for
(
ch
=
0
;
ch
<
slave
->
info
.
count
;
ch
++
)
slave
->
vals
[
ch
]
=
uctl
->
value
.
integer
.
value
[
ch
];
kfree
(
uctl
);
return
0
;
}
/* get the slave ctl info and save the initial values */
/* get the slave ctl info and save the initial values */
static
int
slave_init
(
struct
link_slave
*
slave
)
static
int
slave_init
(
struct
link_slave
*
slave
)
{
{
struct
snd_ctl_elem_info
*
uinfo
;
struct
snd_ctl_elem_info
*
uinfo
;
struct
snd_ctl_elem_value
*
uctl
;
int
err
;
int
err
,
ch
;
if
(
slave
->
info
.
count
)
if
(
slave
->
info
.
count
)
{
return
0
;
/* already initialized */
/* already initialized */
if
(
slave
->
flags
&
SND_CTL_SLAVE_NEED_UPDATE
)
return
slave_update
(
slave
);
return
0
;
}
uinfo
=
kmalloc
(
sizeof
(
*
uinfo
),
GFP_KERNEL
);
uinfo
=
kmalloc
(
sizeof
(
*
uinfo
),
GFP_KERNEL
);
if
(
!
uinfo
)
if
(
!
uinfo
)
...
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave)
...
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave)
slave
->
info
.
max_val
=
uinfo
->
value
.
integer
.
max
;
slave
->
info
.
max_val
=
uinfo
->
value
.
integer
.
max
;
kfree
(
uinfo
);
kfree
(
uinfo
);
uctl
=
kmalloc
(
sizeof
(
*
uctl
),
GFP_KERNEL
);
return
slave_update
(
slave
);
if
(
!
uctl
)
return
-
ENOMEM
;
uctl
->
id
=
slave
->
slave
.
id
;
err
=
slave
->
slave
.
get
(
&
slave
->
slave
,
uctl
);
for
(
ch
=
0
;
ch
<
slave
->
info
.
count
;
ch
++
)
slave
->
vals
[
ch
]
=
uctl
->
value
.
integer
.
value
[
ch
];
kfree
(
uctl
);
return
0
;
}
}
/* initialize master volume */
/* initialize master volume */
...
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol)
...
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol)
* - logarithmic volume control (dB level), no linear volume
* - logarithmic volume control (dB level), no linear volume
* - master can only attenuate the volume, no gain
* - master can only attenuate the volume, no gain
*/
*/
int
snd_ctl_add_slave
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
)
int
_snd_ctl_add_slave
(
struct
snd_kcontrol
*
master
,
struct
snd_kcontrol
*
slave
,
unsigned
int
flags
)
{
{
struct
link_master
*
master_link
=
snd_kcontrol_chip
(
master
);
struct
link_master
*
master_link
=
snd_kcontrol_chip
(
master
);
struct
link_slave
*
srec
;
struct
link_slave
*
srec
;
...
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
...
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
srec
->
slave
=
*
slave
;
srec
->
slave
=
*
slave
;
memcpy
(
srec
->
slave
.
vd
,
slave
->
vd
,
slave
->
count
*
sizeof
(
*
slave
->
vd
));
memcpy
(
srec
->
slave
.
vd
,
slave
->
vd
,
slave
->
count
*
sizeof
(
*
slave
->
vd
));
srec
->
master
=
master_link
;
srec
->
master
=
master_link
;
srec
->
flags
=
flags
;
/* override callbacks */
/* override callbacks */
slave
->
info
=
slave_info
;
slave
->
info
=
slave_info
;
...
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
...
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
list_add_tail
(
&
srec
->
list
,
&
master_link
->
slaves
);
list_add_tail
(
&
srec
->
list
,
&
master_link
->
slaves
);
return
0
;
return
0
;
}
}
EXPORT_SYMBOL
(
_snd_ctl_add_slave
);
EXPORT_SYMBOL
(
snd_ctl_add_slave
);
/*
/*
* ctl callbacks for master controls
* ctl callbacks for master controls
...
@@ -327,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol)
...
@@ -327,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol)
}
}
/*
/**
* Create a virtual master control with the given name
* snd_ctl_make_virtual_master - Create a virtual master control
* @name: name string of the control element to create
* @tlv: optional TLV int array for dB information
*
* Creates a virtual matster control with the given name string.
* Returns the created control element, or NULL for errors (ENOMEM).
*
* After creating a vmaster element, you can add the slave controls
* via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
*
* The optional argument @tlv can be used to specify the TLV information
* for dB scale of the master control. It should be a single element
* with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
*/
*/
struct
snd_kcontrol
*
snd_ctl_make_virtual_master
(
char
*
name
,
struct
snd_kcontrol
*
snd_ctl_make_virtual_master
(
char
*
name
,
const
unsigned
int
*
tlv
)
const
unsigned
int
*
tlv
)
...
@@ -367,5 +392,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
...
@@ -367,5 +392,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
return
kctl
;
return
kctl
;
}
}
EXPORT_SYMBOL
(
snd_ctl_make_virtual_master
);
EXPORT_SYMBOL
(
snd_ctl_make_virtual_master
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment