mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 08:09:56 +00:00
[ALSA] add support for SB Live! 24-Bit External remote control
This patch rewrites the remote control code to use a table for the peculiarities of the various SB models, and adds support for a third model. Signed-off-by: Raimonds Cicans <ray@vardes.lv> Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
parent
cab5c4c97a
commit
4d1a70dad0
@ -46,6 +46,27 @@
|
|||||||
/* ignore error from controls - for debugging */
|
/* ignore error from controls - for debugging */
|
||||||
/* #define IGNORE_CTL_ERROR */
|
/* #define IGNORE_CTL_ERROR */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sound Blaster remote control configuration
|
||||||
|
*
|
||||||
|
* format of remote control data:
|
||||||
|
* Extigy: xx 00
|
||||||
|
* Audigy 2 NX: 06 80 xx 00 00 00
|
||||||
|
* Live! 24-bit: 06 80 xx yy 22 83
|
||||||
|
*/
|
||||||
|
static const struct rc_config {
|
||||||
|
u32 usb_id;
|
||||||
|
u8 offset;
|
||||||
|
u8 length;
|
||||||
|
u8 packet_length;
|
||||||
|
u8 mute_mixer_id;
|
||||||
|
u32 mute_code;
|
||||||
|
} rc_configs[] = {
|
||||||
|
{ USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */
|
||||||
|
{ USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */
|
||||||
|
{ USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */
|
||||||
|
};
|
||||||
|
|
||||||
struct usb_mixer_interface {
|
struct usb_mixer_interface {
|
||||||
struct snd_usb_audio *chip;
|
struct snd_usb_audio *chip;
|
||||||
unsigned int ctrlif;
|
unsigned int ctrlif;
|
||||||
@ -55,11 +76,7 @@ struct usb_mixer_interface {
|
|||||||
struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
|
struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
|
||||||
|
|
||||||
/* Sound Blaster remote control stuff */
|
/* Sound Blaster remote control stuff */
|
||||||
enum {
|
const struct rc_config *rc_cfg;
|
||||||
RC_NONE,
|
|
||||||
RC_EXTIGY,
|
|
||||||
RC_AUDIGY2NX,
|
|
||||||
} rc_type;
|
|
||||||
unsigned long rc_hwdep_open;
|
unsigned long rc_hwdep_open;
|
||||||
u32 rc_code;
|
u32 rc_code;
|
||||||
wait_queue_head_t rc_waitq;
|
wait_queue_head_t rc_waitq;
|
||||||
@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
|
|||||||
static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
|
static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
|
||||||
int unitid)
|
int unitid)
|
||||||
{
|
{
|
||||||
if (mixer->rc_type == RC_NONE)
|
if (!mixer->rc_cfg)
|
||||||
return;
|
return;
|
||||||
/* unit ids specific to Extigy/Audigy 2 NX: */
|
/* unit ids specific to Extigy/Audigy 2 NX: */
|
||||||
switch (unitid) {
|
switch (unitid) {
|
||||||
@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct usb_mixer_interface *mixer = urb->context;
|
struct usb_mixer_interface *mixer = urb->context;
|
||||||
/*
|
const struct rc_config *rc = mixer->rc_cfg;
|
||||||
* format of remote control data:
|
|
||||||
* Extigy: xx 00
|
|
||||||
* Audigy 2 NX: 06 80 xx 00 00 00
|
|
||||||
*/
|
|
||||||
int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
|
|
||||||
u32 code;
|
u32 code;
|
||||||
|
|
||||||
if (urb->status < 0 || urb->actual_length <= offset)
|
if (urb->status < 0 || urb->actual_length < rc->packet_length)
|
||||||
return;
|
return;
|
||||||
code = mixer->rc_buffer[offset];
|
|
||||||
|
code = mixer->rc_buffer[rc->offset];
|
||||||
|
if (rc->length == 2)
|
||||||
|
code |= mixer->rc_buffer[rc->offset + 1] << 8;
|
||||||
|
|
||||||
/* the Mute button actually changes the mixer control */
|
/* the Mute button actually changes the mixer control */
|
||||||
if (code == 13)
|
if (code == rc->mute_code)
|
||||||
snd_usb_mixer_notify_id(mixer, 18);
|
snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
|
||||||
mixer->rc_code = code;
|
mixer->rc_code = code;
|
||||||
wmb();
|
wmb();
|
||||||
wake_up(&mixer->rc_waitq);
|
wake_up(&mixer->rc_waitq);
|
||||||
@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f
|
|||||||
static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
|
static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
|
||||||
{
|
{
|
||||||
struct snd_hwdep *hwdep;
|
struct snd_hwdep *hwdep;
|
||||||
int err, len;
|
int err, len, i;
|
||||||
|
|
||||||
switch (mixer->chip->usb_id) {
|
for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
|
||||||
case USB_ID(0x041e, 0x3000):
|
if (rc_configs[i].usb_id == mixer->chip->usb_id)
|
||||||
mixer->rc_type = RC_EXTIGY;
|
break;
|
||||||
len = 2;
|
if (i >= ARRAY_SIZE(rc_configs))
|
||||||
break;
|
|
||||||
case USB_ID(0x041e, 0x3020):
|
|
||||||
mixer->rc_type = RC_AUDIGY2NX;
|
|
||||||
len = 6;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
mixer->rc_cfg = &rc_configs[i];
|
||||||
|
|
||||||
|
len = mixer->rc_cfg->packet_length;
|
||||||
|
|
||||||
init_waitqueue_head(&mixer->rc_waitq);
|
init_waitqueue_head(&mixer->rc_waitq);
|
||||||
err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
|
err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user