Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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
Hide 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
0
;
return
NULL
;
}
/* check whether the control should be ignored */
static
int
check_ignored_ctl
(
struct
mixer_build
*
state
,
int
unitid
,
int
control
)
/* get the mapped name if the unit matches */
static
int
check_mapped_name
(
const
struct
usbmix_name_map
*
p
,
char
*
buf
,
int
buflen
)
{
const
struct
usbmix_name_map
*
p
;
if
(
!
p
||
!
p
->
name
)
return
0
;
if
(
!
state
->
map
)
buflen
--
;
return
strlcpy
(
buf
,
p
->
name
,
buflen
);
}
/* check whether the control should be ignored */
static
inline
int
check_ignored_ctl
(
const
struct
usbmix_name_map
*
p
)
{
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
;
}
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