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
a540e133
Commit
a540e133
authored
Feb 12, 2010
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote branch 'alsa/devel' into topic/misc
parents
cebe41d4
c3a3e040
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
273 additions
and
165 deletions
+273
-165
sound/drivers/dummy.c
sound/drivers/dummy.c
+180
-110
sound/usb/usbmixer.c
sound/usb/usbmixer.c
+76
-49
sound/usb/usbmixer_maps.c
sound/usb/usbmixer_maps.c
+17
-6
No files found.
sound/drivers/dummy.c
View file @
a540e133
...
...
@@ -45,109 +45,23 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
#define MAX_PCM_SUBSTREAMS 128
#define MAX_MIDI_DEVICES 2
#if 0 /* emu10k1 emulation */
#define MAX_BUFFER_SIZE (128 * 1024)
static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
{
int err;
err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
if (err < 0)
return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
if (err < 0)
return err;
return 0;
}
#define add_playback_constraints emu10k1_playback_constraints
#endif
#if 0 /* RME9652 emulation */
#define MAX_BUFFER_SIZE (26 * 64 * 1024)
#define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
#define USE_CHANNELS_MIN 26
#define USE_CHANNELS_MAX 26
#define USE_PERIODS_MIN 2
#define USE_PERIODS_MAX 2
#endif
#if 0 /* ICE1712 emulation */
#define MAX_BUFFER_SIZE (256 * 1024)
#define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
#define USE_CHANNELS_MIN 10
#define USE_CHANNELS_MAX 10
#define USE_PERIODS_MIN 1
#define USE_PERIODS_MAX 1024
#endif
#if 0 /* UDA1341 emulation */
#define MAX_BUFFER_SIZE (16380)
#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
#define USE_CHANNELS_MIN 2
#define USE_CHANNELS_MAX 2
#define USE_PERIODS_MIN 2
#define USE_PERIODS_MAX 255
#endif
#if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
#define USE_CHANNELS_MIN 2
#define USE_CHANNELS_MAX 2
#define USE_RATE SNDRV_PCM_RATE_48000
#define USE_RATE_MIN 48000
#define USE_RATE_MAX 48000
#endif
#if 0 /* CA0106 */
#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
#define USE_CHANNELS_MIN 2
#define USE_CHANNELS_MAX 2
#define USE_RATE (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000)
#define USE_RATE_MIN 48000
#define USE_RATE_MAX 192000
#define MAX_BUFFER_SIZE ((65536-64)*8)
#define MAX_PERIOD_SIZE (65536-64)
#define USE_PERIODS_MIN 2
#define USE_PERIODS_MAX 8
#endif
/* defaults */
#ifndef MAX_BUFFER_SIZE
#define MAX_BUFFER_SIZE (64*1024)
#endif
#ifndef MAX_PERIOD_SIZE
#define MIN_PERIOD_SIZE 64
#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE
#endif
#ifndef USE_FORMATS
#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
#endif
#ifndef USE_RATE
#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
#define USE_RATE_MIN 5500
#define USE_RATE_MAX 48000
#endif
#ifndef USE_CHANNELS_MIN
#define USE_CHANNELS_MIN 1
#endif
#ifndef USE_CHANNELS_MAX
#define USE_CHANNELS_MAX 2
#endif
#ifndef USE_PERIODS_MIN
#define USE_PERIODS_MIN 1
#endif
#ifndef USE_PERIODS_MAX
#define USE_PERIODS_MAX 1024
#endif
#ifndef add_playback_constraints
#define add_playback_constraints(x) 0
#endif
#ifndef add_capture_constraints
#define add_capture_constraints(x) 0
#endif
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
]
=
{
1
,
[
1
...
(
SNDRV_CARDS
-
1
)]
=
0
};
static
char
*
model
[
SNDRV_CARDS
]
=
{[
0
...
(
SNDRV_CARDS
-
1
)]
=
NULL
};
static
int
pcm_devs
[
SNDRV_CARDS
]
=
{[
0
...
(
SNDRV_CARDS
-
1
)]
=
1
};
static
int
pcm_substreams
[
SNDRV_CARDS
]
=
{[
0
...
(
SNDRV_CARDS
-
1
)]
=
8
};
//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
...
...
@@ -162,6 +76,8 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC
(
id
,
"ID string for dummy soundcard."
);
module_param_array
(
enable
,
bool
,
NULL
,
0444
);
MODULE_PARM_DESC
(
enable
,
"Enable this dummy soundcard."
);
module_param_array
(
model
,
charp
,
NULL
,
0444
);
MODULE_PARM_DESC
(
model
,
"Soundcard model."
);
module_param_array
(
pcm_devs
,
int
,
NULL
,
0444
);
MODULE_PARM_DESC
(
pcm_devs
,
"PCM devices # (0-4) for dummy driver."
);
module_param_array
(
pcm_substreams
,
int
,
NULL
,
0444
);
...
...
@@ -193,15 +109,120 @@ struct dummy_timer_ops {
snd_pcm_uframes_t
(
*
pointer
)(
struct
snd_pcm_substream
*
);
};
struct
dummy_model
{
const
char
*
name
;
int
(
*
playback_constraints
)(
struct
snd_pcm_runtime
*
runtime
);
int
(
*
capture_constraints
)(
struct
snd_pcm_runtime
*
runtime
);
u64
formats
;
size_t
buffer_bytes_max
;
size_t
period_bytes_min
;
size_t
period_bytes_max
;
unsigned
int
periods_min
;
unsigned
int
periods_max
;
unsigned
int
rates
;
unsigned
int
rate_min
;
unsigned
int
rate_max
;
unsigned
int
channels_min
;
unsigned
int
channels_max
;
};
struct
snd_dummy
{
struct
snd_card
*
card
;
struct
dummy_model
*
model
;
struct
snd_pcm
*
pcm
;
struct
snd_pcm_hardware
pcm_hw
;
spinlock_t
mixer_lock
;
int
mixer_volume
[
MIXER_ADDR_LAST
+
1
][
2
];
int
capture_source
[
MIXER_ADDR_LAST
+
1
][
2
];
const
struct
dummy_timer_ops
*
timer_ops
;
};
/*
* card models
*/
static
int
emu10k1_playback_constraints
(
struct
snd_pcm_runtime
*
runtime
)
{
int
err
;
err
=
snd_pcm_hw_constraint_integer
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
);
if
(
err
<
0
)
return
err
;
err
=
snd_pcm_hw_constraint_minmax
(
runtime
,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
256
,
UINT_MAX
);
if
(
err
<
0
)
return
err
;
return
0
;
}
struct
dummy_model
model_emu10k1
=
{
.
name
=
"emu10k1"
,
.
playback_constraints
=
emu10k1_playback_constraints
,
.
buffer_bytes_max
=
128
*
1024
,
};
struct
dummy_model
model_rme9652
=
{
.
name
=
"rme9652"
,
.
buffer_bytes_max
=
26
*
64
*
1024
,
.
formats
=
SNDRV_PCM_FMTBIT_S32_LE
,
.
channels_min
=
26
,
.
channels_max
=
26
,
.
periods_min
=
2
,
.
periods_max
=
2
,
};
struct
dummy_model
model_ice1712
=
{
.
name
=
"ice1712"
,
.
buffer_bytes_max
=
256
*
1024
,
.
formats
=
SNDRV_PCM_FMTBIT_S32_LE
,
.
channels_min
=
10
,
.
channels_max
=
10
,
.
periods_min
=
1
,
.
periods_max
=
1024
,
};
struct
dummy_model
model_uda1341
=
{
.
name
=
"uda1341"
,
.
buffer_bytes_max
=
16380
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
periods_min
=
2
,
.
periods_max
=
255
,
};
struct
dummy_model
model_ac97
=
{
.
name
=
"ac97"
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_48000
,
.
rate_min
=
48000
,
.
rate_max
=
48000
,
};
struct
dummy_model
model_ca0106
=
{
.
name
=
"ca0106"
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
buffer_bytes_max
=
((
65536
-
64
)
*
8
),
.
period_bytes_max
=
(
65536
-
64
),
.
periods_min
=
2
,
.
periods_max
=
8
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_48000
|
SNDRV_PCM_RATE_96000
|
SNDRV_PCM_RATE_192000
,
.
rate_min
=
48000
,
.
rate_max
=
192000
,
};
struct
dummy_model
*
dummy_models
[]
=
{
&
model_emu10k1
,
&
model_rme9652
,
&
model_ice1712
,
&
model_uda1341
,
&
model_ac97
,
&
model_ca0106
,
NULL
};
/*
* system timer interface
*/
...
...
@@ -509,7 +530,7 @@ static struct snd_pcm_hardware dummy_pcm_hardware = {
.
channels_min
=
USE_CHANNELS_MIN
,
.
channels_max
=
USE_CHANNELS_MAX
,
.
buffer_bytes_max
=
MAX_BUFFER_SIZE
,
.
period_bytes_min
=
64
,
.
period_bytes_min
=
MIN_PERIOD_SIZE
,
.
period_bytes_max
=
MAX_PERIOD_SIZE
,
.
periods_min
=
USE_PERIODS_MIN
,
.
periods_max
=
USE_PERIODS_MAX
,
...
...
@@ -538,6 +559,7 @@ static int dummy_pcm_hw_free(struct snd_pcm_substream *substream)
static
int
dummy_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_dummy
*
dummy
=
snd_pcm_substream_chip
(
substream
);
struct
dummy_model
*
model
=
dummy
->
model
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
int
err
;
...
...
@@ -551,7 +573,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
if
(
err
<
0
)
return
err
;
runtime
->
hw
=
dummy
_pcm_hardware
;
runtime
->
hw
=
dummy
->
pcm_hw
;
if
(
substream
->
pcm
->
device
&
1
)
{
runtime
->
hw
.
info
&=
~
SNDRV_PCM_INFO_INTERLEAVED
;
runtime
->
hw
.
info
|=
SNDRV_PCM_INFO_NONINTERLEAVED
;
...
...
@@ -560,10 +582,16 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
runtime
->
hw
.
info
&=
~
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
err
=
add_playback_constraints
(
substream
->
runtime
);
else
err
=
add_capture_constraints
(
substream
->
runtime
);
if
(
model
==
NULL
)
return
0
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
if
(
model
->
playback_constraints
)
err
=
model
->
playback_constraints
(
substream
->
runtime
);
}
else
{
if
(
model
->
capture_constraints
)
err
=
model
->
capture_constraints
(
substream
->
runtime
);
}
if
(
err
<
0
)
{
dummy
->
timer_ops
->
free
(
substream
);
return
err
;
...
...
@@ -823,17 +851,19 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
/*
* proc interface
*/
static
void
print_formats
(
struct
snd_info_buffer
*
buffer
)
static
void
print_formats
(
struct
snd_dummy
*
dummy
,
struct
snd_info_buffer
*
buffer
)
{
int
i
;
for
(
i
=
0
;
i
<
SNDRV_PCM_FORMAT_LAST
;
i
++
)
{
if
(
dummy
_pcm_hardware
.
formats
&
(
1ULL
<<
i
))
if
(
dummy
->
pcm_hw
.
formats
&
(
1ULL
<<
i
))
snd_iprintf
(
buffer
,
" %s"
,
snd_pcm_format_name
(
i
));
}
}
static
void
print_rates
(
struct
snd_info_buffer
*
buffer
)
static
void
print_rates
(
struct
snd_dummy
*
dummy
,
struct
snd_info_buffer
*
buffer
)
{
static
int
rates
[]
=
{
5512
,
8000
,
11025
,
16000
,
22050
,
32000
,
44100
,
48000
,
...
...
@@ -841,19 +871,19 @@ static void print_rates(struct snd_info_buffer *buffer)
};
int
i
;
if
(
dummy
_pcm_hardware
.
rates
&
SNDRV_PCM_RATE_CONTINUOUS
)
if
(
dummy
->
pcm_hw
.
rates
&
SNDRV_PCM_RATE_CONTINUOUS
)
snd_iprintf
(
buffer
,
" continuous"
);
if
(
dummy
_pcm_hardware
.
rates
&
SNDRV_PCM_RATE_KNOT
)
if
(
dummy
->
pcm_hw
.
rates
&
SNDRV_PCM_RATE_KNOT
)
snd_iprintf
(
buffer
,
" knot"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
rates
);
i
++
)
if
(
dummy
_pcm_hardware
.
rates
&
(
1
<<
i
))
if
(
dummy
->
pcm_hw
.
rates
&
(
1
<<
i
))
snd_iprintf
(
buffer
,
" %d"
,
rates
[
i
]);
}
#define get_dummy_int_ptr(ofs) \
(unsigned int *)((char *)&
dummy_pcm_hardware
+ (ofs))
#define get_dummy_ll_ptr(ofs) \
(unsigned long long *)((char *)&
dummy_pcm_hardware
+ (ofs))
#define get_dummy_int_ptr(
dummy,
ofs) \
(unsigned int *)((char *)&
((dummy)->pcm_hw)
+ (ofs))
#define get_dummy_ll_ptr(
dummy,
ofs) \
(unsigned long long *)((char *)&
((dummy)->pcm_hw)
+ (ofs))
struct
dummy_hw_field
{
const
char
*
name
;
...
...
@@ -884,20 +914,21 @@ static struct dummy_hw_field fields[] = {
static
void
dummy_proc_read
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
struct
snd_dummy
*
dummy
=
entry
->
private_data
;
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
fields
);
i
++
)
{
snd_iprintf
(
buffer
,
"%s "
,
fields
[
i
].
name
);
if
(
fields
[
i
].
size
==
sizeof
(
int
))
snd_iprintf
(
buffer
,
fields
[
i
].
format
,
*
get_dummy_int_ptr
(
fields
[
i
].
offset
));
*
get_dummy_int_ptr
(
dummy
,
fields
[
i
].
offset
));
else
snd_iprintf
(
buffer
,
fields
[
i
].
format
,
*
get_dummy_ll_ptr
(
fields
[
i
].
offset
));
*
get_dummy_ll_ptr
(
dummy
,
fields
[
i
].
offset
));
if
(
!
strcmp
(
fields
[
i
].
name
,
"formats"
))
print_formats
(
buffer
);
print_formats
(
dummy
,
buffer
);
else
if
(
!
strcmp
(
fields
[
i
].
name
,
"rates"
))
print_rates
(
buffer
);
print_rates
(
dummy
,
buffer
);
snd_iprintf
(
buffer
,
"
\n
"
);
}
}
...
...
@@ -905,6 +936,7 @@ static void dummy_proc_read(struct snd_info_entry *entry,
static
void
dummy_proc_write
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
struct
snd_dummy
*
dummy
=
entry
->
private_data
;
char
line
[
64
];
while
(
!
snd_info_get_line
(
buffer
,
line
,
sizeof
(
line
)))
{
...
...
@@ -924,9 +956,9 @@ static void dummy_proc_write(struct snd_info_entry *entry,
if
(
strict_strtoull
(
item
,
0
,
&
val
))
continue
;
if
(
fields
[
i
].
size
==
sizeof
(
int
))
*
get_dummy_int_ptr
(
fields
[
i
].
offset
)
=
val
;
*
get_dummy_int_ptr
(
dummy
,
fields
[
i
].
offset
)
=
val
;
else
*
get_dummy_ll_ptr
(
fields
[
i
].
offset
)
=
val
;
*
get_dummy_ll_ptr
(
dummy
,
fields
[
i
].
offset
)
=
val
;
}
}
...
...
@@ -938,6 +970,7 @@ static void __devinit dummy_proc_init(struct snd_dummy *chip)
snd_info_set_text_ops
(
entry
,
chip
,
dummy_proc_read
);
entry
->
c
.
text
.
write
=
dummy_proc_write
;
entry
->
mode
|=
S_IWUSR
;
entry
->
private_data
=
chip
;
}
}
#else
...
...
@@ -948,6 +981,7 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
{
struct
snd_card
*
card
;
struct
snd_dummy
*
dummy
;
struct
dummy_model
*
m
=
NULL
,
**
mdl
;
int
idx
,
err
;
int
dev
=
devptr
->
id
;
...
...
@@ -957,6 +991,15 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
return
err
;
dummy
=
card
->
private_data
;
dummy
->
card
=
card
;
for
(
mdl
=
dummy_models
;
*
mdl
&&
model
[
dev
];
mdl
++
)
{
if
(
strcmp
(
model
[
dev
],
(
*
mdl
)
->
name
)
==
0
)
{
printk
(
KERN_INFO
"snd-dummy: Using model '%s' for card %i
\n
"
,
(
*
mdl
)
->
name
,
card
->
number
);
m
=
dummy
->
model
=
*
mdl
;
break
;
}
}
for
(
idx
=
0
;
idx
<
MAX_PCM_DEVICES
&&
idx
<
pcm_devs
[
dev
];
idx
++
)
{
if
(
pcm_substreams
[
dev
]
<
1
)
pcm_substreams
[
dev
]
=
1
;
...
...
@@ -966,6 +1009,33 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
if
(
err
<
0
)
goto
__nodev
;
}
dummy
->
pcm_hw
=
dummy_pcm_hardware
;
if
(
m
)
{
if
(
m
->
formats
)
dummy
->
pcm_hw
.
formats
=
m
->
formats
;
if
(
m
->
buffer_bytes_max
)
dummy
->
pcm_hw
.
buffer_bytes_max
=
m
->
buffer_bytes_max
;
if
(
m
->
period_bytes_min
)
dummy
->
pcm_hw
.
period_bytes_min
=
m
->
period_bytes_min
;
if
(
m
->
period_bytes_max
)
dummy
->
pcm_hw
.
period_bytes_max
=
m
->
period_bytes_max
;
if
(
m
->
periods_min
)
dummy
->
pcm_hw
.
periods_min
=
m
->
periods_min
;
if
(
m
->
periods_max
)
dummy
->
pcm_hw
.
periods_max
=
m
->
periods_max
;
if
(
m
->
rates
)
dummy
->
pcm_hw
.
rates
=
m
->
rates
;
if
(
m
->
rate_min
)
dummy
->
pcm_hw
.
rate_min
=
m
->
rate_min
;
if
(
m
->
rate_max
)
dummy
->
pcm_hw
.
rate_max
=
m
->
rate_max
;
if
(
m
->
channels_min
)
dummy
->
pcm_hw
.
channels_min
=
m
->
channels_min
;
if
(
m
->
channels_max
)
dummy
->
pcm_hw
.
channels_max
=
m
->
channels_max
;
}
err
=
snd_card_dummy_new_mixer
(
dummy
);
if
(
err
<
0
)
goto
__nodev
;
...
...
sound/usb/usbmixer.c
View file @
a540e133
...
...
@@ -123,6 +123,7 @@ struct usb_mixer_elem_info {
int
channels
;
int
val_type
;
int
min
,
max
,
res
;
int
dBmin
,
dBmax
;
int
cached
;
int
cache_val
[
MAX_CHANNELS
];
u8
initialized
;
...
...
@@ -209,42 +210,50 @@ enum {
*/
#include "usbmixer_maps.c"
/* get the mapped name if the unit matches */
static
int
check_mapped_name
(
struct
mixer_build
*
state
,
int
unitid
,
int
control
,
char
*
buf
,
int
buflen
)
static
const
struct
usbmix_name_map
*
find_map
(
struct
mixer_build
*
state
,
int
unitid
,
int
control
)
{
const
struct
usbmix_name_map
*
p
;
const
struct
usbmix_name_map
*
p
=
state
->
map
;
if
(
!
state
->
ma
p
)
return
0
;
if
(
!
p
)
return
NULL
;
for
(
p
=
state
->
map
;
p
->
id
;
p
++
)
{
if
(
p
->
id
==
unitid
&&
p
->
name
&&
(
!
control
||
!
p
->
control
||
control
==
p
->
control
))
{
buflen
--
;
return
strlcpy
(
buf
,
p
->
name
,
buflen
);
}
if
(
p
->
id
==
unitid
&&
(
!
control
||
!
p
->
control
||
control
==
p
->
control
))
return
p
;
}
return
NULL
;
}
/* get the mapped name if the unit matches */
static
int
check_mapped_name
(
const
struct
usbmix_name_map
*
p
,
char
*
buf
,
int
buflen
)
{
if
(
!
p
||
!
p
->
name
)
return
0
;
buflen
--
;
return
strlcpy
(
buf
,
p
->
name
,
buflen
);
}
/* check whether the control should be ignored */
static
int
check_ignored_ctl
(
struct
mixer_build
*
state
,
int
unitid
,
int
control
)
static
inline
int
check_ignored_ctl
(
const
struct
usbmix_name_map
*
p
)
{
const
struct
usbmix_name_map
*
p
;
if
(
!
state
->
map
)
if
(
!
p
||
p
->
name
||
p
->
dB
)
return
0
;
for
(
p
=
state
->
map
;
p
->
id
;
p
++
)
{
if
(
p
->
id
==
unitid
&&
!
p
->
name
&&
(
!
control
||
!
p
->
control
||
control
==
p
->
control
))
{
/*
printk(KERN_DEBUG "ignored control %d:%d\n",
unitid, control);
*/
return
1
;
}
/* dB mapping */
static
inline
void
check_mapped_dB
(
const
struct
usbmix_name_map
*
p
,
struct
usb_mixer_elem_info
*
cval
)
{
if
(
p
&&
p
->
dB
)
{
cval
->
dBmin
=
p
->
dB
->
min
;
cval
->
dBmax
=
p
->
dB
->
max
;
}
}
return
0
;
}
/* get the mapped selector source name */
...
...
@@ -481,20 +490,8 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
if
(
size
<
sizeof
(
scale
))
return
-
ENOMEM
;
/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
scale
[
2
]
=
(
convert_signed_value
(
cval
,
cval
->
min
)
*
100
)
/
256
;
scale
[
3
]
=
(
convert_signed_value
(
cval
,
cval
->
max
)
*
100
)
/
256
;
if
(
scale
[
3
]
<=
scale
[
2
])
{
/* something is wrong; assume it's either from/to 0dB */
if
(
scale
[
2
]
<
0
)
scale
[
3
]
=
0
;
else
if
(
scale
[
2
]
>
0
)
scale
[
2
]
=
0
;
else
/* totally crap, return an error */
return
-
EINVAL
;
}
scale
[
2
]
=
cval
->
dBmin
;
scale
[
3
]
=
cval
->
dBmax
;
if
(
copy_to_user
(
_tlv
,
scale
,
sizeof
(
scale
)))
return
-
EFAULT
;
return
0
;
...
...
@@ -735,6 +732,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval
->
min
=
default_min
;
cval
->
max
=
cval
->
min
+
1
;
cval
->
res
=
1
;
cval
->
dBmin
=
cval
->
dBmax
=
0
;
if
(
cval
->
val_type
==
USB_MIXER_BOOLEAN
||
cval
->
val_type
==
USB_MIXER_INV_BOOLEAN
)
{
...
...
@@ -802,6 +800,24 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval
->
initialized
=
1
;
}
/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
cval
->
dBmin
=
(
convert_signed_value
(
cval
,
cval
->
min
)
*
100
)
/
256
;
cval
->
dBmax
=
(
convert_signed_value
(
cval
,
cval
->
max
)
*
100
)
/
256
;
if
(
cval
->
dBmin
>
cval
->
dBmax
)
{
/* something is wrong; assume it's either from/to 0dB */
if
(
cval
->
dBmin
<
0
)
cval
->
dBmax
=
0
;
else
if
(
cval
->
dBmin
>
0
)
cval
->
dBmin
=
0
;
if
(
cval
->
dBmin
>
cval
->
dBmax
)
{
/* totally crap, return an error */
return
-
EINVAL
;
}
}
return
0
;
}
...
...
@@ -927,6 +943,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
int
nameid
=
desc
[
desc
[
0
]
-
1
];
struct
snd_kcontrol
*
kctl
;
struct
usb_mixer_elem_info
*
cval
;
const
struct
usbmix_name_map
*
map
;
control
++
;
/* change from zero-based to 1-based value */
...
...
@@ -935,7 +952,8 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
return
;
}
if
(
check_ignored_ctl
(
state
,
unitid
,
control
))
map
=
find_map
(
state
,
unitid
,
control
);
if
(
check_ignored_ctl
(
map
))
return
;
cval
=
kzalloc
(
sizeof
(
*
cval
),
GFP_KERNEL
);
...
...
@@ -969,10 +987,11 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
}
kctl
->
private_free
=
usb_mixer_elem_free
;
len
=
check_mapped_name
(
state
,
unitid
,
control
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
len
=
check_mapped_name
(
map
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
mapped_name
=
len
!=
0
;
if
(
!
len
&&
nameid
)
len
=
snd_usb_copy_string_desc
(
state
,
nameid
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
len
=
snd_usb_copy_string_desc
(
state
,
nameid
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
switch
(
control
)
{
case
USB_FEATURE_MUTE
:
...
...
@@ -1010,6 +1029,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
kctl
->
vd
[
0
].
access
|=
SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
;
check_mapped_dB
(
map
,
cval
);
}
break
;
...
...
@@ -1137,8 +1157,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
unsigned
int
num_outs
=
desc
[
5
+
input_pins
];
unsigned
int
i
,
len
;
struct
snd_kcontrol
*
kctl
;
const
struct
usbmix_name_map
*
map
;
if
(
check_ignored_ctl
(
state
,
unitid
,
0
))
map
=
find_map
(
state
,
unitid
,
0
);
if
(
check_ignored_ctl
(
map
))
return
;
cval
=
kzalloc
(
sizeof
(
*
cval
),
GFP_KERNEL
);
...
...
@@ -1167,7 +1189,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
}
kctl
->
private_free
=
usb_mixer_elem_free
;
len
=
check_mapped_name
(
state
,
unitid
,
0
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
len
=
check_mapped_name
(
map
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
if
(
!
len
)
len
=
get_term_name
(
state
,
iterm
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
),
0
);
if
(
!
len
)
...
...
@@ -1382,6 +1404,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
int
i
,
err
,
nameid
,
type
,
len
;
struct
procunit_info
*
info
;
struct
procunit_value_info
*
valinfo
;
const
struct
usbmix_name_map
*
map
;
static
struct
procunit_value_info
default_value_info
[]
=
{
{
0x01
,
"Switch"
,
USB_MIXER_BOOLEAN
},
{
0
}
...
...
@@ -1411,7 +1434,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
/* FIXME: bitmap might be longer than 8bit */
if
(
!
(
dsc
[
12
+
num_ins
]
&
(
1
<<
(
valinfo
->
control
-
1
))))
continue
;
if
(
check_ignored_ctl
(
state
,
unitid
,
valinfo
->
control
))
map
=
find_map
(
state
,
unitid
,
valinfo
->
control
);
if
(
check_ignored_ctl
(
map
))
continue
;
cval
=
kzalloc
(
sizeof
(
*
cval
),
GFP_KERNEL
);
if
(
!
cval
)
{
...
...
@@ -1452,8 +1476,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
}
kctl
->
private_free
=
usb_mixer_elem_free
;
if
(
check_mapped_name
(
state
,
unitid
,
cval
->
control
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
)))
;
if
(
check_mapped_name
(
map
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
)))
/* nothing */
;
else
if
(
info
->
name
)
strlcpy
(
kctl
->
id
.
name
,
info
->
name
,
sizeof
(
kctl
->
id
.
name
));
else
{
...
...
@@ -1592,6 +1617,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
int
err
;
struct
usb_mixer_elem_info
*
cval
;
struct
snd_kcontrol
*
kctl
;
const
struct
usbmix_name_map
*
map
;
char
**
namelist
;
if
(
!
num_ins
||
desc
[
0
]
<
5
+
num_ins
)
{
...
...
@@ -1607,7 +1633,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
if
(
num_ins
==
1
)
/* only one ? nonsense! */
return
0
;
if
(
check_ignored_ctl
(
state
,
unitid
,
0
))
map
=
find_map
(
state
,
unitid
,
0
);
if
(
check_ignored_ctl
(
map
))
return
0
;
cval
=
kzalloc
(
sizeof
(
*
cval
),
GFP_KERNEL
);
...
...
@@ -1662,7 +1689,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
kctl
->
private_free
=
usb_mixer_selector_elem_free
;
nameid
=
desc
[
desc
[
0
]
-
1
];
len
=
check_mapped_name
(
state
,
unitid
,
0
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
len
=
check_mapped_name
(
map
,
kctl
->
id
.
name
,
sizeof
(
kctl
->
id
.
name
));
if
(
len
)
;
else
if
(
nameid
)
...
...
sound/usb/usbmixer_maps.c
View file @
a540e133
...
...
@@ -19,11 +19,16 @@
*
*/
struct
usbmix_dB_map
{
u32
min
;
u32
max
;
};
struct
usbmix_name_map
{
int
id
;
const
char
*
name
;
int
control
;
struct
usbmix_dB_map
*
dB
;
};
struct
usbmix_selector_map
{
...
...
@@ -72,7 +77,7 @@ static struct usbmix_name_map extigy_map[] = {
{
8
,
"Line Playback"
},
/* FU */
/* 9: IT mic */
{
10
,
"Mic Playback"
},
/* FU */
{
11
,
"Capture
Input
Source"
},
/* SU */
{
11
,
"Capture Source"
},
/* SU */
{
12
,
"Capture"
},
/* FU */
/* 13: OT pcm capture */
/* 14: MU (w/o controls) */
...
...
@@ -102,6 +107,9 @@ static struct usbmix_name_map extigy_map[] = {
* e.g. no Master and fake PCM volume
* Pavel Mihaylov <bin@bash.info>
*/
static
struct
usbmix_dB_map
mp3plus_dB_1
=
{
-
4781
,
0
};
/* just guess */
static
struct
usbmix_dB_map
mp3plus_dB_2
=
{
-
1781
,
618
};
/* just guess */
static
struct
usbmix_name_map
mp3plus_map
[]
=
{
/* 1: IT pcm */
/* 2: IT mic */
...
...
@@ -110,16 +118,19 @@ static struct usbmix_name_map mp3plus_map[] = {
/* 5: OT digital out */
/* 6: OT speaker */
/* 7: OT pcm capture */
{
8
,
"Capture
Input
Source"
},
/* FU, default PCM Capture Source */
{
8
,
"Capture Source"
},
/* FU, default PCM Capture Source */
/* (Mic, Input 1 = Line input, Input 2 = Optical input) */
{
9
,
"Master Playback"
},
/* FU, default Speaker 1 */
/* { 10, "Mic Capture", 1 }, */
/* FU, Mic Capture */
/* { 10, "Mic Capture", 2 }, */
/* FU, Mic Capture */
{
10
,
/* "Mic Capture", */
NULL
,
2
,
.
dB
=
&
mp3plus_dB_2
},
/* FU, Mic Capture */
{
10
,
"Mic Boost"
,
7
},
/* FU, default Auto Gain Input */
{
11
,
"Line Capture"
},
/* FU, default PCM Capture */
{
11
,
"Line Capture"
,
.
dB
=
&
mp3plus_dB_2
},
/* FU, default PCM Capture */
{
12
,
"Digital In Playback"
},
/* FU, default PCM 1 */
/* { 13, "Mic Playback" }, */
/* FU, default Mic Playback */
{
14
,
"Line Playback"
},
/* FU, default Speaker */
{
13
,
/* "Mic Playback", */
.
dB
=
&
mp3plus_dB_1
},
/* FU, default Mic Playback */
{
14
,
"Line Playback"
,
.
dB
=
&
mp3plus_dB_1
},
/* FU, default Speaker */
/* 15: MU */
{
0
}
/* terminator */
};
...
...
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