Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: usb-audio: Add support for Presonus Studio 1810c

This patch adds support for Presonus Studio 1810c, a usb interface
that's UAC2 compliant with a few quirks and a few extra hw-specific
controls. I've tested all 3 altsettings and the added switch
controls and they work as expected.

More infos on the card:
https://www.presonus.com/products/Studio-1810c

Note that this work is based on packet inspection with
usbmon. I just wanted to get this card to work for using
it on our open-source radio station:
https://github.com/UoC-Radio

v2 address issues reported by Takashi:
* Properly get/set enum type controls
* Prevent race condition on switch_get/set
* Various control naming changes
* Various coding style fixes

v3 improve readability of sample rate filtering
and some other minor changes.

Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Link: https://lore.kernel.org/r/5e47481a.1c69fb81.befb3.8dac@mx.google.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Nick Kossifidis and committed by
Takashi Iwai
8dc5efe3 146f6697

+681
+1
sound/usb/Makefile
··· 13 13 mixer_scarlett.o \ 14 14 mixer_scarlett_gen2.o \ 15 15 mixer_us16x08.o \ 16 + mixer_s1810c.o \ 16 17 pcm.o \ 17 18 power.o \ 18 19 proc.o \
+37
sound/usb/format.c
··· 226 226 return 0; 227 227 } 228 228 229 + 230 + /* 231 + * Presonus Studio 1810c supports a limited set of sampling 232 + * rates per altsetting but reports the full set each time. 233 + * If we don't filter out the unsupported rates and attempt 234 + * to configure the card, it will hang refusing to do any 235 + * further audio I/O until a hard reset is performed. 236 + * 237 + * The list of supported rates per altsetting (set of available 238 + * I/O channels) is described in the owner's manual, section 2.2. 239 + */ 240 + static bool s1810c_valid_sample_rate(struct audioformat *fp, 241 + unsigned int rate) 242 + { 243 + switch (fp->altsetting) { 244 + case 1: 245 + /* All ADAT ports available */ 246 + return rate <= 48000; 247 + case 2: 248 + /* Half of ADAT ports available */ 249 + return (rate == 88200 || rate == 96000); 250 + case 3: 251 + /* Analog I/O only (no S/PDIF nor ADAT) */ 252 + return rate >= 176400; 253 + default: 254 + return false; 255 + } 256 + return false; 257 + } 258 + 229 259 /* 230 260 * Helper function to walk the array of sample rate triplets reported by 231 261 * the device. The problem is that we need to parse whole array first to ··· 292 262 } 293 263 294 264 for (rate = min; rate <= max; rate += res) { 265 + 266 + /* Filter out invalid rates on Presonus Studio 1810c */ 267 + if (chip->usb_id == USB_ID(0x0194f, 0x010c) && 268 + !s1810c_valid_sample_rate(fp, rate)) 269 + goto skip_rate; 270 + 295 271 if (fp->rate_table) 296 272 fp->rate_table[nr_rates] = rate; 297 273 if (!fp->rate_min || rate < fp->rate_min) ··· 312 276 break; 313 277 } 314 278 279 + skip_rate: 315 280 /* avoid endless loop */ 316 281 if (res == 0) 317 282 break;
+5
sound/usb/mixer_quirks.c
··· 34 34 #include "mixer_scarlett.h" 35 35 #include "mixer_scarlett_gen2.h" 36 36 #include "mixer_us16x08.h" 37 + #include "mixer_s1810c.h" 37 38 #include "helper.h" 38 39 39 40 struct std_mono_table { ··· 2277 2276 case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */ 2278 2277 case USB_ID(0x2a39, 0x3fd4): /* RME */ 2279 2278 err = snd_rme_controls_create(mixer); 2279 + break; 2280 + 2281 + case USB_ID(0x0194f, 0x010c): /* Presonus Studio 1810c */ 2282 + err = snd_sc1810_init_mixer(mixer); 2280 2283 break; 2281 2284 } 2282 2285
+595
sound/usb/mixer_s1810c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Presonus Studio 1810c driver for ALSA 4 + * Copyright (C) 2019 Nick Kossifidis <mickflemm@gmail.com> 5 + * 6 + * Based on reverse engineering of the communication protocol 7 + * between the windows driver / Univeral Control (UC) program 8 + * and the device, through usbmon. 9 + * 10 + * For now this bypasses the mixer, with all channels split, 11 + * so that the software can mix with greater flexibility. 12 + * It also adds controls for the 4 buttons on the front of 13 + * the device. 14 + */ 15 + 16 + #include <linux/usb.h> 17 + #include <linux/usb/audio-v2.h> 18 + #include <linux/slab.h> 19 + #include <sound/core.h> 20 + #include <sound/control.h> 21 + 22 + #include "usbaudio.h" 23 + #include "mixer.h" 24 + #include "mixer_quirks.h" 25 + #include "helper.h" 26 + #include "mixer_s1810c.h" 27 + 28 + #define SC1810C_CMD_REQ 160 29 + #define SC1810C_CMD_REQTYPE \ 30 + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT) 31 + #define SC1810C_CMD_F1 0x50617269 32 + #define SC1810C_CMD_F2 0x14 33 + 34 + /* 35 + * DISCLAIMER: These are just guesses based on the 36 + * dumps I got. 37 + * 38 + * It seems like a selects between 39 + * device (0), mixer (0x64) and output (0x65) 40 + * 41 + * For mixer (0x64): 42 + * * b selects an input channel (see below). 43 + * * c selects an output channel pair (see below). 44 + * * d selects left (0) or right (1) of that pair. 45 + * * e 0-> disconnect, 0x01000000-> connect, 46 + * 0x0109-> used for stereo-linking channels, 47 + * e is also used for setting volume levels 48 + * in which case b is also set so I guess 49 + * this way it is possible to set the volume 50 + * level from the specified input to the 51 + * specified output. 52 + * 53 + * IN Channels: 54 + * 0 - 7 Mic/Inst/Line (Analog inputs) 55 + * 8 - 9 S/PDIF 56 + * 10 - 17 ADAT 57 + * 18 - 35 DAW (Inputs from the host) 58 + * 59 + * OUT Channels (pairs): 60 + * 0 -> Main out 61 + * 1 -> Line1/2 62 + * 2 -> Line3/4 63 + * 3 -> S/PDIF 64 + * 4 -> ADAT? 65 + * 66 + * For device (0): 67 + * * b and c are not used, at least not on the 68 + * dumps I got. 69 + * * d sets the control id to be modified 70 + * (see below). 71 + * * e sets the setting for that control. 72 + * (so for the switches I was interested 73 + * in it's 0/1) 74 + * 75 + * For output (0x65): 76 + * * b is the output channel (see above). 77 + * * c is zero. 78 + * * e I guess the same as with mixer except 0x0109 79 + * which I didn't see in my dumps. 80 + * 81 + * The two fixed fields have the same values for 82 + * mixer and output but a different set for device. 83 + */ 84 + struct s1810c_ctl_packet { 85 + u32 a; 86 + u32 b; 87 + u32 fixed1; 88 + u32 fixed2; 89 + u32 c; 90 + u32 d; 91 + u32 e; 92 + }; 93 + 94 + #define SC1810C_CTL_LINE_SW 0 95 + #define SC1810C_CTL_MUTE_SW 1 96 + #define SC1810C_CTL_AB_SW 3 97 + #define SC1810C_CTL_48V_SW 4 98 + 99 + #define SC1810C_SET_STATE_REQ 161 100 + #define SC1810C_SET_STATE_REQTYPE SC1810C_CMD_REQTYPE 101 + #define SC1810C_SET_STATE_F1 0x64656D73 102 + #define SC1810C_SET_STATE_F2 0xF4 103 + 104 + #define SC1810C_GET_STATE_REQ 162 105 + #define SC1810C_GET_STATE_REQTYPE \ 106 + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN) 107 + #define SC1810C_GET_STATE_F1 SC1810C_SET_STATE_F1 108 + #define SC1810C_GET_STATE_F2 SC1810C_SET_STATE_F2 109 + 110 + #define SC1810C_STATE_F1_IDX 2 111 + #define SC1810C_STATE_F2_IDX 3 112 + 113 + /* 114 + * This packet includes mixer volumes and 115 + * various other fields, it's an extended 116 + * version of ctl_packet, with a and b 117 + * being zero and different f1/f2. 118 + */ 119 + struct s1810c_state_packet { 120 + u32 fields[63]; 121 + }; 122 + 123 + #define SC1810C_STATE_48V_SW 58 124 + #define SC1810C_STATE_LINE_SW 59 125 + #define SC1810C_STATE_MUTE_SW 60 126 + #define SC1810C_STATE_AB_SW 62 127 + 128 + struct s1810_mixer_state { 129 + uint16_t seqnum; 130 + struct mutex usb_mutex; 131 + struct mutex data_mutex; 132 + }; 133 + 134 + static int 135 + snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a, 136 + u32 b, u32 c, u32 d, u32 e) 137 + { 138 + struct s1810c_ctl_packet pkt = { 0 }; 139 + int ret = 0; 140 + 141 + pkt.fixed1 = SC1810C_CMD_F1; 142 + pkt.fixed2 = SC1810C_CMD_F2; 143 + 144 + pkt.a = a; 145 + pkt.b = b; 146 + pkt.c = c; 147 + pkt.d = d; 148 + /* 149 + * Value for settings 0/1 for this 150 + * output channel is always 0 (probably because 151 + * there is no ADAT output on 1810c) 152 + */ 153 + pkt.e = (c == 4) ? 0 : e; 154 + 155 + ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 156 + SC1810C_CMD_REQ, 157 + SC1810C_CMD_REQTYPE, 0, 0, &pkt, sizeof(pkt)); 158 + if (ret < 0) { 159 + dev_warn(&dev->dev, "could not send ctl packet\n"); 160 + return ret; 161 + } 162 + return 0; 163 + } 164 + 165 + /* 166 + * When opening Universal Control the program periodicaly 167 + * sends and receives state packets for syncinc state between 168 + * the device and the host. 169 + * 170 + * Note that if we send only the request to get data back we'll 171 + * get an error, we need to first send an empty state packet and 172 + * then ask to receive a filled. Their seqnumbers must also match. 173 + */ 174 + static int 175 + snd_sc1810c_get_status_field(struct usb_device *dev, 176 + u32 *field, int field_idx, uint16_t *seqnum) 177 + { 178 + struct s1810c_state_packet pkt_out = { 0 }; 179 + struct s1810c_state_packet pkt_in = { 0 }; 180 + int ret = 0; 181 + 182 + pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1; 183 + pkt_out.fields[SC1810C_STATE_F2_IDX] = SC1810C_SET_STATE_F2; 184 + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 185 + SC1810C_SET_STATE_REQ, 186 + SC1810C_SET_STATE_REQTYPE, 187 + (*seqnum), 0, &pkt_out, sizeof(pkt_out)); 188 + if (ret < 0) { 189 + dev_warn(&dev->dev, "could not send state packet (%d)\n", ret); 190 + return ret; 191 + } 192 + 193 + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 194 + SC1810C_GET_STATE_REQ, 195 + SC1810C_GET_STATE_REQTYPE, 196 + (*seqnum), 0, &pkt_in, sizeof(pkt_in)); 197 + if (ret < 0) { 198 + dev_warn(&dev->dev, "could not get state field %u (%d)\n", 199 + field_idx, ret); 200 + return ret; 201 + } 202 + 203 + (*field) = pkt_in.fields[field_idx]; 204 + (*seqnum)++; 205 + return 0; 206 + } 207 + 208 + /* 209 + * This is what I got when bypassing the mixer with 210 + * all channels split. I'm not 100% sure of what's going 211 + * on, I could probably clean this up based on my observations 212 + * but I prefer to keep the same behavior as the windows driver. 213 + */ 214 + static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip) 215 + { 216 + u32 a, b, c, e, n, off; 217 + struct usb_device *dev = chip->dev; 218 + 219 + /* Set initial volume levels ? */ 220 + a = 0x64; 221 + e = 0xbc; 222 + for (n = 0; n < 2; n++) { 223 + off = n * 18; 224 + for (b = off, c = 0; b < 18 + off; b++) { 225 + /* This channel to all outputs ? */ 226 + for (c = 0; c <= 8; c++) { 227 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); 228 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); 229 + } 230 + /* This channel to main output (again) */ 231 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); 232 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); 233 + } 234 + /* 235 + * I noticed on UC that DAW channels have different 236 + * initial volumes, so this makes sense. 237 + */ 238 + e = 0xb53bf0; 239 + } 240 + 241 + /* Connect analog outputs ? */ 242 + a = 0x65; 243 + e = 0x01000000; 244 + for (b = 1; b < 3; b++) { 245 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); 246 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); 247 + } 248 + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e); 249 + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e); 250 + 251 + /* Set initial volume levels for S/PDIF mappings ? */ 252 + a = 0x64; 253 + e = 0xbc; 254 + c = 3; 255 + for (n = 0; n < 2; n++) { 256 + off = n * 18; 257 + for (b = off; b < 18 + off; b++) { 258 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); 259 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); 260 + } 261 + e = 0xb53bf0; 262 + } 263 + 264 + /* Connect S/PDIF output ? */ 265 + a = 0x65; 266 + e = 0x01000000; 267 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); 268 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); 269 + 270 + /* Connect all outputs (again) ? */ 271 + a = 0x65; 272 + e = 0x01000000; 273 + for (b = 0; b < 4; b++) { 274 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); 275 + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); 276 + } 277 + 278 + /* Basic routing to get sound out of the device */ 279 + a = 0x64; 280 + e = 0x01000000; 281 + for (c = 0; c < 4; c++) { 282 + for (b = 0; b < 36; b++) { 283 + if ((c == 0 && b == 18) || /* DAW1/2 -> Main */ 284 + (c == 1 && b == 20) || /* DAW3/4 -> Line3/4 */ 285 + (c == 2 && b == 22) || /* DAW4/5 -> Line5/6 */ 286 + (c == 3 && b == 24)) { /* DAW5/6 -> S/PDIF */ 287 + /* Left */ 288 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); 289 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); 290 + b++; 291 + /* Right */ 292 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); 293 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); 294 + } else { 295 + /* Leave the rest disconnected */ 296 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); 297 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); 298 + } 299 + } 300 + } 301 + 302 + /* Set initial volume levels for S/PDIF (again) ? */ 303 + a = 0x64; 304 + e = 0xbc; 305 + c = 3; 306 + for (n = 0; n < 2; n++) { 307 + off = n * 18; 308 + for (b = off; b < 18 + off; b++) { 309 + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); 310 + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); 311 + } 312 + e = 0xb53bf0; 313 + } 314 + 315 + /* Connect S/PDIF outputs (again) ? */ 316 + a = 0x65; 317 + e = 0x01000000; 318 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); 319 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); 320 + 321 + /* Again ? */ 322 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); 323 + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); 324 + 325 + return 0; 326 + } 327 + 328 + /* 329 + * Sync state with the device and retrieve the requested field, 330 + * whose index is specified in (kctl->private_value & 0xFF), 331 + * from the received fields array. 332 + */ 333 + static int 334 + snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer, 335 + struct snd_kcontrol *kctl, u32 *state) 336 + { 337 + struct snd_usb_audio *chip = mixer->chip; 338 + struct s1810_mixer_state *private = mixer->private_data; 339 + u32 field = 0; 340 + u32 ctl_idx = (u32) (kctl->private_value & 0xFF); 341 + int ret = 0; 342 + 343 + mutex_lock(&private->usb_mutex); 344 + ret = snd_sc1810c_get_status_field(chip->dev, &field, 345 + ctl_idx, &private->seqnum); 346 + if (ret < 0) 347 + goto unlock; 348 + 349 + *state = field; 350 + unlock: 351 + mutex_unlock(&private->usb_mutex); 352 + return ret ? ret : 0; 353 + } 354 + 355 + /* 356 + * Send a control packet to the device for the control id 357 + * specified in (kctl->private_value >> 8) with value 358 + * specified in (kctl->private_value >> 16). 359 + */ 360 + static int 361 + snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer, 362 + struct snd_kcontrol *kctl) 363 + { 364 + struct snd_usb_audio *chip = mixer->chip; 365 + struct s1810_mixer_state *private = mixer->private_data; 366 + u32 pval = (u32) kctl->private_value; 367 + u32 ctl_id = (pval >> 8) & 0xFF; 368 + u32 ctl_val = (pval >> 16) & 0x1; 369 + int ret = 0; 370 + 371 + mutex_lock(&private->usb_mutex); 372 + ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val); 373 + mutex_unlock(&private->usb_mutex); 374 + return ret; 375 + } 376 + 377 + /* Generic get/set/init functions for switch controls */ 378 + 379 + static int 380 + snd_s1810c_switch_get(struct snd_kcontrol *kctl, 381 + struct snd_ctl_elem_value *ctl_elem) 382 + { 383 + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); 384 + struct usb_mixer_interface *mixer = list->mixer; 385 + struct s1810_mixer_state *private = mixer->private_data; 386 + u32 pval = (u32) kctl->private_value; 387 + u32 ctl_idx = pval & 0xFF; 388 + u32 state = 0; 389 + int ret = 0; 390 + 391 + mutex_lock(&private->data_mutex); 392 + ret = snd_s1810c_get_switch_state(mixer, kctl, &state); 393 + if (ret < 0) 394 + goto unlock; 395 + 396 + switch (ctl_idx) { 397 + case SC1810C_STATE_LINE_SW: 398 + case SC1810C_STATE_AB_SW: 399 + ctl_elem->value.enumerated.item[0] = (int)state; 400 + break; 401 + default: 402 + ctl_elem->value.integer.value[0] = (long)state; 403 + } 404 + 405 + unlock: 406 + mutex_unlock(&private->data_mutex); 407 + return (ret < 0) ? ret : 0; 408 + } 409 + 410 + static int 411 + snd_s1810c_switch_set(struct snd_kcontrol *kctl, 412 + struct snd_ctl_elem_value *ctl_elem) 413 + { 414 + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); 415 + struct usb_mixer_interface *mixer = list->mixer; 416 + struct s1810_mixer_state *private = mixer->private_data; 417 + u32 pval = (u32) kctl->private_value; 418 + u32 ctl_idx = pval & 0xFF; 419 + u32 curval = 0; 420 + u32 newval = 0; 421 + int ret = 0; 422 + 423 + mutex_lock(&private->data_mutex); 424 + ret = snd_s1810c_get_switch_state(mixer, kctl, &curval); 425 + if (ret < 0) 426 + goto unlock; 427 + 428 + switch (ctl_idx) { 429 + case SC1810C_STATE_LINE_SW: 430 + case SC1810C_STATE_AB_SW: 431 + newval = (u32) ctl_elem->value.enumerated.item[0]; 432 + break; 433 + default: 434 + newval = (u32) ctl_elem->value.integer.value[0]; 435 + } 436 + 437 + if (curval == newval) 438 + goto unlock; 439 + 440 + kctl->private_value &= ~(0x1 << 16); 441 + kctl->private_value |= (unsigned int)(newval & 0x1) << 16; 442 + ret = snd_s1810c_set_switch_state(mixer, kctl); 443 + 444 + unlock: 445 + mutex_unlock(&private->data_mutex); 446 + return (ret < 0) ? 0 : 1; 447 + } 448 + 449 + static int 450 + snd_s1810c_switch_init(struct usb_mixer_interface *mixer, 451 + const struct snd_kcontrol_new *new_kctl) 452 + { 453 + struct snd_kcontrol *kctl; 454 + struct usb_mixer_elem_info *elem; 455 + 456 + elem = kzalloc(sizeof(struct usb_mixer_elem_info), GFP_KERNEL); 457 + if (!elem) 458 + return -ENOMEM; 459 + 460 + elem->head.mixer = mixer; 461 + elem->control = 0; 462 + elem->head.id = 0; 463 + elem->channels = 1; 464 + 465 + kctl = snd_ctl_new1(new_kctl, elem); 466 + if (!kctl) { 467 + kfree(elem); 468 + return -ENOMEM; 469 + } 470 + kctl->private_free = snd_usb_mixer_elem_free; 471 + 472 + return snd_usb_mixer_add_control(&elem->head, kctl); 473 + } 474 + 475 + static int 476 + snd_s1810c_line_sw_info(struct snd_kcontrol *kctl, 477 + struct snd_ctl_elem_info *uinfo) 478 + { 479 + static const char *const texts[2] = { 480 + "Preamp On (Mic/Inst)", 481 + "Preamp Off (Line in)" 482 + }; 483 + 484 + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); 485 + } 486 + 487 + static const struct snd_kcontrol_new snd_s1810c_line_sw = { 488 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 489 + .name = "Line 1/2 Source Type", 490 + .info = snd_s1810c_line_sw_info, 491 + .get = snd_s1810c_switch_get, 492 + .put = snd_s1810c_switch_set, 493 + .private_value = (SC1810C_STATE_LINE_SW | SC1810C_CTL_LINE_SW << 8) 494 + }; 495 + 496 + static const struct snd_kcontrol_new snd_s1810c_mute_sw = { 497 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 498 + .name = "Mute Main Out Switch", 499 + .info = snd_ctl_boolean_mono_info, 500 + .get = snd_s1810c_switch_get, 501 + .put = snd_s1810c_switch_set, 502 + .private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8) 503 + }; 504 + 505 + static const struct snd_kcontrol_new snd_s1810c_48v_sw = { 506 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 507 + .name = "48V Phantom Power On Mic Inputs Switch", 508 + .info = snd_ctl_boolean_mono_info, 509 + .get = snd_s1810c_switch_get, 510 + .put = snd_s1810c_switch_set, 511 + .private_value = (SC1810C_STATE_48V_SW | SC1810C_CTL_48V_SW << 8) 512 + }; 513 + 514 + static int 515 + snd_s1810c_ab_sw_info(struct snd_kcontrol *kctl, 516 + struct snd_ctl_elem_info *uinfo) 517 + { 518 + static const char *const texts[2] = { 519 + "1/2", 520 + "3/4" 521 + }; 522 + 523 + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); 524 + } 525 + 526 + static const struct snd_kcontrol_new snd_s1810c_ab_sw = { 527 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 528 + .name = "Headphone 1 Source Route", 529 + .info = snd_s1810c_ab_sw_info, 530 + .get = snd_s1810c_switch_get, 531 + .put = snd_s1810c_switch_set, 532 + .private_value = (SC1810C_STATE_AB_SW | SC1810C_CTL_AB_SW << 8) 533 + }; 534 + 535 + static void snd_sc1810_mixer_state_free(struct usb_mixer_interface *mixer) 536 + { 537 + struct s1810_mixer_state *private = mixer->private_data; 538 + kfree(private); 539 + mixer->private_data = NULL; 540 + } 541 + 542 + /* Entry point, called from mixer_quirks.c */ 543 + int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer) 544 + { 545 + struct s1810_mixer_state *private = NULL; 546 + struct snd_usb_audio *chip = mixer->chip; 547 + struct usb_device *dev = chip->dev; 548 + int ret = 0; 549 + 550 + /* Run this only once */ 551 + if (!list_empty(&chip->mixer_list)) 552 + return 0; 553 + 554 + dev_info(&dev->dev, 555 + "Presonus Studio 1810c, device_setup: %u\n", chip->setup); 556 + if (chip->setup == 1) 557 + dev_info(&dev->dev, "(8out/18in @ 48KHz)\n"); 558 + else if (chip->setup == 2) 559 + dev_info(&dev->dev, "(6out/8in @ 192KHz)\n"); 560 + else 561 + dev_info(&dev->dev, "(8out/14in @ 96KHz)\n"); 562 + 563 + ret = snd_s1810c_init_mixer_maps(chip); 564 + if (ret < 0) 565 + return ret; 566 + 567 + private = kzalloc(sizeof(struct s1810_mixer_state), GFP_KERNEL); 568 + if (!private) 569 + return -ENOMEM; 570 + 571 + mutex_init(&private->usb_mutex); 572 + mutex_init(&private->data_mutex); 573 + 574 + mixer->private_data = private; 575 + mixer->private_free = snd_sc1810_mixer_state_free; 576 + 577 + private->seqnum = 1; 578 + 579 + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_line_sw); 580 + if (ret < 0) 581 + return ret; 582 + 583 + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_mute_sw); 584 + if (ret < 0) 585 + return ret; 586 + 587 + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_48v_sw); 588 + if (ret < 0) 589 + return ret; 590 + 591 + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw); 592 + if (ret < 0) 593 + return ret; 594 + return ret; 595 + }
+7
sound/usb/mixer_s1810c.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Presonus Studio 1810c driver for ALSA 4 + * Copyright (C) 2019 Nick Kossifidis <mickflemm@gmail.com> 5 + */ 6 + 7 + int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer);
+36
sound/usb/quirks.c
··· 1252 1252 return 0; /* keep this altsetting */ 1253 1253 } 1254 1254 1255 + static int s1810c_skip_setting_quirk(struct snd_usb_audio *chip, 1256 + int iface, int altno) 1257 + { 1258 + /* 1259 + * Altno settings: 1260 + * 1261 + * Playback (Interface 1): 1262 + * 1: 6 Analog + 2 S/PDIF 1263 + * 2: 6 Analog + 2 S/PDIF 1264 + * 3: 6 Analog 1265 + * 1266 + * Capture (Interface 2): 1267 + * 1: 8 Analog + 2 S/PDIF + 8 ADAT 1268 + * 2: 8 Analog + 2 S/PDIF + 4 ADAT 1269 + * 3: 8 Analog 1270 + */ 1271 + 1272 + /* 1273 + * I'll leave 2 as the default one and 1274 + * use device_setup to switch to the 1275 + * other two. 1276 + */ 1277 + if ((chip->setup == 0 || chip->setup > 2) && altno != 2) 1278 + return 1; 1279 + else if (chip->setup == 1 && altno != 1) 1280 + return 1; 1281 + else if (chip->setup == 2 && altno != 3) 1282 + return 1; 1283 + 1284 + return 0; 1285 + } 1286 + 1255 1287 int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, 1256 1288 int iface, 1257 1289 int altno) ··· 1297 1265 /* fasttrackpro usb: skip altsets incompatible with device_setup */ 1298 1266 if (chip->usb_id == USB_ID(0x0763, 0x2012)) 1299 1267 return fasttrackpro_skip_setting_quirk(chip, iface, altno); 1268 + /* presonus studio 1810c: skip altsets incompatible with device_setup */ 1269 + if (chip->usb_id == USB_ID(0x0194f, 0x010c)) 1270 + return s1810c_skip_setting_quirk(chip, iface, altno); 1271 + 1300 1272 1301 1273 return 0; 1302 1274 }