-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcontrol.c
117 lines (96 loc) · 3.03 KB
/
control.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
* Behringer BCD2000 driver
*
* Copyright (C) 2014 Mario Kicherer ([email protected])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include "bcd2000.h"
#include "control.h"
#include "midi.h"
static const char * const phono_mic_sw_texts[2] = { "Phono A", "Mic" };
/*
* switch between Phono A and Mic input using a MIDI program change command
*
* The manual specifies "c0 [00|01]" but the windows driver sends
* "09 01 [00|01]", we follow the manual here.
*/
static void bcd2000_control_phono_mic_sw_update(struct bcd2000_control *ctrl)
{
int actual_length, ret;
char buffer[MIDI_URB_BUFSIZE] = MIDI_CMD_PREFIX_INIT;
buffer[2] = 2;
buffer[3] = 0xC0;
buffer[4] = ctrl->phono_mic_switch;
ret = usb_interrupt_msg(ctrl->bcd2k->dev, usb_sndintpipe(ctrl->bcd2k->dev, 0x1),
buffer, MIDI_URB_BUFSIZE, &actual_length, 100);
if (ret)
dev_err(&ctrl->bcd2k->dev->dev, PREFIX "usb_interrupt_msg failed\n");
}
static int bcd2000_control_phono_mic_sw_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
return snd_ctl_enum_info(uinfo, 1, 2, phono_mic_sw_texts);
}
static int bcd2000_control_phono_mic_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct bcd2000_control *ctrl = snd_kcontrol_chip(kcontrol);
int changed = 0;
if (ctrl->phono_mic_switch != ucontrol->value.enumerated.item[0]) {
ctrl->phono_mic_switch = ucontrol->value.enumerated.item[0];
bcd2000_control_phono_mic_sw_update(ctrl);
changed = 1;
}
return changed;
}
static int bcd2000_control_phono_mic_sw_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct bcd2000_control *ctrl = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = ctrl->phono_mic_switch;
return 0;
}
static struct snd_kcontrol_new elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Phono A / Mic Capture Switch",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = bcd2000_control_phono_mic_sw_info,
.get = bcd2000_control_phono_mic_sw_get,
.put = bcd2000_control_phono_mic_sw_put
},
{}
};
int bcd2000_init_control(struct bcd2000 *bcd2k)
{
int i, ret;
bcd2k->control.bcd2k = bcd2k;
i = 0;
while (elements[i].name) {
ret = snd_ctl_add(bcd2k->card, snd_ctl_new1(&elements[i],
&bcd2k->control));
if (ret < 0) {
dev_err(&bcd2k->dev->dev, "cannot add control\n");
return ret;
}
i++;
}
return 0;
}
void bcd2000_free_control(struct bcd2000 *bcd2k)
{
}