1eb7b3a05STakashi Sakamoto /* 2eb7b3a05STakashi Sakamoto * bebob_stream.c - a part of driver for BeBoB based devices 3eb7b3a05STakashi Sakamoto * 4eb7b3a05STakashi Sakamoto * Copyright (c) 2013-2014 Takashi Sakamoto 5eb7b3a05STakashi Sakamoto * 6eb7b3a05STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 7eb7b3a05STakashi Sakamoto */ 8eb7b3a05STakashi Sakamoto 9eb7b3a05STakashi Sakamoto #include "./bebob.h" 10eb7b3a05STakashi Sakamoto 119a73195eSTakashi Sakamoto #define CALLBACK_TIMEOUT 2000 12b6bc8123STakashi Sakamoto #define FW_ISO_RESOURCE_DELAY 1000 13eb7b3a05STakashi Sakamoto 14eb7b3a05STakashi Sakamoto /* 15eb7b3a05STakashi Sakamoto * NOTE; 16eb7b3a05STakashi Sakamoto * For BeBoB streams, Both of input and output CMP connection are important. 17eb7b3a05STakashi Sakamoto * 18eb7b3a05STakashi Sakamoto * For most devices, each CMP connection starts to transmit/receive a 19eb7b3a05STakashi Sakamoto * corresponding stream. But for a few devices, both of CMP connection needs 20eb7b3a05STakashi Sakamoto * to start transmitting stream. An example is 'M-Audio Firewire 410'. 21eb7b3a05STakashi Sakamoto */ 22eb7b3a05STakashi Sakamoto 23eb7b3a05STakashi Sakamoto /* 128 is an arbitrary length but it seems to be enough */ 24eb7b3a05STakashi Sakamoto #define FORMAT_MAXIMUM_LENGTH 128 25eb7b3a05STakashi Sakamoto 26eb7b3a05STakashi Sakamoto const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES] = { 27eb7b3a05STakashi Sakamoto [0] = 32000, 28eb7b3a05STakashi Sakamoto [1] = 44100, 29eb7b3a05STakashi Sakamoto [2] = 48000, 30eb7b3a05STakashi Sakamoto [3] = 88200, 31eb7b3a05STakashi Sakamoto [4] = 96000, 32eb7b3a05STakashi Sakamoto [5] = 176400, 33eb7b3a05STakashi Sakamoto [6] = 192000, 34eb7b3a05STakashi Sakamoto }; 35eb7b3a05STakashi Sakamoto 36eb7b3a05STakashi Sakamoto /* 37eb7b3a05STakashi Sakamoto * See: Table 51: Extended Stream Format Info ‘Sampling Frequency’ 38eb7b3a05STakashi Sakamoto * in Additional AVC commands (Nov 2003, BridgeCo) 39eb7b3a05STakashi Sakamoto */ 40eb7b3a05STakashi Sakamoto static const unsigned int bridgeco_freq_table[] = { 41eb7b3a05STakashi Sakamoto [0] = 0x02, 42eb7b3a05STakashi Sakamoto [1] = 0x03, 43eb7b3a05STakashi Sakamoto [2] = 0x04, 44eb7b3a05STakashi Sakamoto [3] = 0x0a, 45eb7b3a05STakashi Sakamoto [4] = 0x05, 46eb7b3a05STakashi Sakamoto [5] = 0x06, 47eb7b3a05STakashi Sakamoto [6] = 0x07, 48eb7b3a05STakashi Sakamoto }; 49eb7b3a05STakashi Sakamoto 5007905298SLucas Tanure static int 5107905298SLucas Tanure get_formation_index(unsigned int rate, unsigned int *index) 52eb7b3a05STakashi Sakamoto { 53eb7b3a05STakashi Sakamoto unsigned int i; 54eb7b3a05STakashi Sakamoto 55eb7b3a05STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) { 5607905298SLucas Tanure if (snd_bebob_rate_table[i] == rate) { 5707905298SLucas Tanure *index = i; 5807905298SLucas Tanure return 0; 5907905298SLucas Tanure } 60eb7b3a05STakashi Sakamoto } 61eb7b3a05STakashi Sakamoto return -EINVAL; 62eb7b3a05STakashi Sakamoto } 63eb7b3a05STakashi Sakamoto 64eb7b3a05STakashi Sakamoto int 65eb7b3a05STakashi Sakamoto snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *curr_rate) 66eb7b3a05STakashi Sakamoto { 67eb7b3a05STakashi Sakamoto unsigned int tx_rate, rx_rate, trials; 68eb7b3a05STakashi Sakamoto int err; 69eb7b3a05STakashi Sakamoto 70eb7b3a05STakashi Sakamoto trials = 0; 71eb7b3a05STakashi Sakamoto do { 72eb7b3a05STakashi Sakamoto err = avc_general_get_sig_fmt(bebob->unit, &tx_rate, 73eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_OUT, 0); 74eb7b3a05STakashi Sakamoto } while (err == -EAGAIN && ++trials < 3); 75eb7b3a05STakashi Sakamoto if (err < 0) 76eb7b3a05STakashi Sakamoto goto end; 77eb7b3a05STakashi Sakamoto 78eb7b3a05STakashi Sakamoto trials = 0; 79eb7b3a05STakashi Sakamoto do { 80eb7b3a05STakashi Sakamoto err = avc_general_get_sig_fmt(bebob->unit, &rx_rate, 81eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 82eb7b3a05STakashi Sakamoto } while (err == -EAGAIN && ++trials < 3); 83eb7b3a05STakashi Sakamoto if (err < 0) 84eb7b3a05STakashi Sakamoto goto end; 85eb7b3a05STakashi Sakamoto 86eb7b3a05STakashi Sakamoto *curr_rate = rx_rate; 87eb7b3a05STakashi Sakamoto if (rx_rate == tx_rate) 88eb7b3a05STakashi Sakamoto goto end; 89eb7b3a05STakashi Sakamoto 90eb7b3a05STakashi Sakamoto /* synchronize receive stream rate to transmit stream rate */ 91eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rx_rate, 92eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 93eb7b3a05STakashi Sakamoto end: 94eb7b3a05STakashi Sakamoto return err; 95eb7b3a05STakashi Sakamoto } 96eb7b3a05STakashi Sakamoto 97eb7b3a05STakashi Sakamoto int 98eb7b3a05STakashi Sakamoto snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate) 99eb7b3a05STakashi Sakamoto { 100eb7b3a05STakashi Sakamoto int err; 101eb7b3a05STakashi Sakamoto 102eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rate, 103eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_OUT, 0); 104eb7b3a05STakashi Sakamoto if (err < 0) 105eb7b3a05STakashi Sakamoto goto end; 106eb7b3a05STakashi Sakamoto 107eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rate, 108eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 109eb7b3a05STakashi Sakamoto if (err < 0) 110eb7b3a05STakashi Sakamoto goto end; 111eb7b3a05STakashi Sakamoto 112eb7b3a05STakashi Sakamoto /* 113eb7b3a05STakashi Sakamoto * Some devices need a bit time for transition. 114eb7b3a05STakashi Sakamoto * 300msec is got by some experiments. 115eb7b3a05STakashi Sakamoto */ 116eb7b3a05STakashi Sakamoto msleep(300); 117eb7b3a05STakashi Sakamoto end: 118eb7b3a05STakashi Sakamoto return err; 119eb7b3a05STakashi Sakamoto } 120eb7b3a05STakashi Sakamoto 1213e254b16STakashi Sakamoto int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, 1223e254b16STakashi Sakamoto enum snd_bebob_clock_type *src) 123eb7b3a05STakashi Sakamoto { 1246b9866c8SJulia Lawall const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; 125eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; 1261fc9522aSTakashi Sakamoto unsigned int id; 1275a668812STakashi Sakamoto enum avc_bridgeco_plug_type type; 128eb7b3a05STakashi Sakamoto int err = 0; 129eb7b3a05STakashi Sakamoto 1301fc9522aSTakashi Sakamoto /* 1.The device has its own operation to switch source of clock */ 1311fc9522aSTakashi Sakamoto if (clk_spec) { 1321fc9522aSTakashi Sakamoto err = clk_spec->get(bebob, &id); 133d1d0b6b6SChristian Vogel if (err < 0) { 1341fc9522aSTakashi Sakamoto dev_err(&bebob->unit->device, 1351fc9522aSTakashi Sakamoto "fail to get clock source: %d\n", err); 136d1d0b6b6SChristian Vogel goto end; 137d1d0b6b6SChristian Vogel } 138d1d0b6b6SChristian Vogel 139d1d0b6b6SChristian Vogel if (id >= clk_spec->num) { 140d1d0b6b6SChristian Vogel dev_err(&bebob->unit->device, 141d1d0b6b6SChristian Vogel "clock source %d out of range 0..%d\n", 142d1d0b6b6SChristian Vogel id, clk_spec->num - 1); 143d1d0b6b6SChristian Vogel err = -EIO; 144d1d0b6b6SChristian Vogel goto end; 145d1d0b6b6SChristian Vogel } 146d1d0b6b6SChristian Vogel 1473e254b16STakashi Sakamoto *src = clk_spec->types[id]; 1481fc9522aSTakashi Sakamoto goto end; 1491fc9522aSTakashi Sakamoto } 1501fc9522aSTakashi Sakamoto 151eb7b3a05STakashi Sakamoto /* 1521fc9522aSTakashi Sakamoto * 2.The device don't support to switch source of clock then assumed 153eb7b3a05STakashi Sakamoto * to use internal clock always 154eb7b3a05STakashi Sakamoto */ 155eb7b3a05STakashi Sakamoto if (bebob->sync_input_plug < 0) { 1563e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 157eb7b3a05STakashi Sakamoto goto end; 158eb7b3a05STakashi Sakamoto } 159eb7b3a05STakashi Sakamoto 160eb7b3a05STakashi Sakamoto /* 1611fc9522aSTakashi Sakamoto * 3.The device supports to switch source of clock by an usual way. 162eb7b3a05STakashi Sakamoto * Let's check input for 'Music Sub Unit Sync Input' plug. 163eb7b3a05STakashi Sakamoto */ 164eb7b3a05STakashi Sakamoto avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 165eb7b3a05STakashi Sakamoto bebob->sync_input_plug); 166eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_input(bebob->unit, addr, input); 167eb7b3a05STakashi Sakamoto if (err < 0) { 168eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 169eb7b3a05STakashi Sakamoto "fail to get an input for MSU in plug %d: %d\n", 170eb7b3a05STakashi Sakamoto bebob->sync_input_plug, err); 171eb7b3a05STakashi Sakamoto goto end; 172eb7b3a05STakashi Sakamoto } 173eb7b3a05STakashi Sakamoto 174eb7b3a05STakashi Sakamoto /* 175eb7b3a05STakashi Sakamoto * If there are no input plugs, all of fields are 0xff. 176eb7b3a05STakashi Sakamoto * Here check the first field. This field is used for direction. 177eb7b3a05STakashi Sakamoto */ 178eb7b3a05STakashi Sakamoto if (input[0] == 0xff) { 1793e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 180eb7b3a05STakashi Sakamoto goto end; 181eb7b3a05STakashi Sakamoto } 182eb7b3a05STakashi Sakamoto 1835a668812STakashi Sakamoto /* The source from any output plugs is for one purpose only. */ 1845a668812STakashi Sakamoto if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) { 185eb7b3a05STakashi Sakamoto /* 1865a668812STakashi Sakamoto * In BeBoB architecture, the source from music subunit may 1875a668812STakashi Sakamoto * bypass from oPCR[0]. This means that this source gives 1885a668812STakashi Sakamoto * synchronization to IEEE 1394 cycle start packet. 189eb7b3a05STakashi Sakamoto */ 1905a668812STakashi Sakamoto if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && 1915a668812STakashi Sakamoto input[2] == 0x0c) { 1923e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 1935a668812STakashi Sakamoto goto end; 1945a668812STakashi Sakamoto } 1955a668812STakashi Sakamoto /* The source from any input units is for several purposes. */ 1965a668812STakashi Sakamoto } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) { 1975a668812STakashi Sakamoto if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) { 1985a668812STakashi Sakamoto if (input[3] == 0x00) { 1995a668812STakashi Sakamoto /* 2005a668812STakashi Sakamoto * This source comes from iPCR[0]. This means 2015a668812STakashi Sakamoto * that presentation timestamp calculated by 2025a668812STakashi Sakamoto * SYT series of the received packets. In 2035a668812STakashi Sakamoto * short, this driver is the master of 2045a668812STakashi Sakamoto * synchronization. 2055a668812STakashi Sakamoto */ 2063e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_SYT; 2075a668812STakashi Sakamoto goto end; 2085a668812STakashi Sakamoto } else { 2095a668812STakashi Sakamoto /* 2105a668812STakashi Sakamoto * This source comes from iPCR[1-29]. This 2115a668812STakashi Sakamoto * means that the synchronization stream is not 2125a668812STakashi Sakamoto * the Audio/MIDI compound stream. 2135a668812STakashi Sakamoto */ 2143e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2155a668812STakashi Sakamoto goto end; 2165a668812STakashi Sakamoto } 2175a668812STakashi Sakamoto } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { 2185a668812STakashi Sakamoto /* Check type of this plug. */ 2195a668812STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, 2205a668812STakashi Sakamoto AVC_BRIDGECO_PLUG_DIR_IN, 2215a668812STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, 2225a668812STakashi Sakamoto input[3]); 2235a668812STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, 2245a668812STakashi Sakamoto &type); 2255a668812STakashi Sakamoto if (err < 0) 2265a668812STakashi Sakamoto goto end; 2275a668812STakashi Sakamoto 2285a668812STakashi Sakamoto if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) { 2295a668812STakashi Sakamoto /* 2305a668812STakashi Sakamoto * SPDIF/ADAT or sometimes (not always) word 2315a668812STakashi Sakamoto * clock. 2325a668812STakashi Sakamoto */ 2333e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2345a668812STakashi Sakamoto goto end; 2355a668812STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { 2365a668812STakashi Sakamoto /* Often word clock. */ 2373e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2385a668812STakashi Sakamoto goto end; 2395a668812STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { 2405a668812STakashi Sakamoto /* 2415a668812STakashi Sakamoto * Not standard. 2425a668812STakashi Sakamoto * Mostly, additional internal clock. 2435a668812STakashi Sakamoto */ 2443e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 2455a668812STakashi Sakamoto goto end; 2465a668812STakashi Sakamoto } 2475a668812STakashi Sakamoto } 2485a668812STakashi Sakamoto } 2495a668812STakashi Sakamoto 2505a668812STakashi Sakamoto /* Not supported. */ 2515a668812STakashi Sakamoto err = -EIO; 252eb7b3a05STakashi Sakamoto end: 253eb7b3a05STakashi Sakamoto return err; 254eb7b3a05STakashi Sakamoto } 255eb7b3a05STakashi Sakamoto 256eb7b3a05STakashi Sakamoto static unsigned int 257eb7b3a05STakashi Sakamoto map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) 258eb7b3a05STakashi Sakamoto { 259eb7b3a05STakashi Sakamoto unsigned int sec, sections, ch, channels; 260eb7b3a05STakashi Sakamoto unsigned int pcm, midi, location; 261eb7b3a05STakashi Sakamoto unsigned int stm_pos, sec_loc, pos; 262eb7b3a05STakashi Sakamoto u8 *buf, addr[AVC_BRIDGECO_ADDR_BYTES], type; 263eb7b3a05STakashi Sakamoto enum avc_bridgeco_plug_dir dir; 264eb7b3a05STakashi Sakamoto int err; 265eb7b3a05STakashi Sakamoto 266eb7b3a05STakashi Sakamoto /* 267eb7b3a05STakashi Sakamoto * The length of return value of this command cannot be expected. Here 268eb7b3a05STakashi Sakamoto * use the maximum length of FCP. 269eb7b3a05STakashi Sakamoto */ 270eb7b3a05STakashi Sakamoto buf = kzalloc(256, GFP_KERNEL); 271eb7b3a05STakashi Sakamoto if (buf == NULL) 272eb7b3a05STakashi Sakamoto return -ENOMEM; 273eb7b3a05STakashi Sakamoto 274eb7b3a05STakashi Sakamoto if (s == &bebob->tx_stream) 275eb7b3a05STakashi Sakamoto dir = AVC_BRIDGECO_PLUG_DIR_OUT; 276eb7b3a05STakashi Sakamoto else 277eb7b3a05STakashi Sakamoto dir = AVC_BRIDGECO_PLUG_DIR_IN; 278eb7b3a05STakashi Sakamoto 279eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 280eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_ch_pos(bebob->unit, addr, buf, 256); 281eb7b3a05STakashi Sakamoto if (err < 0) { 282eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 283eb7b3a05STakashi Sakamoto "fail to get channel position for isoc %s plug 0: %d\n", 284eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : "out", 285eb7b3a05STakashi Sakamoto err); 286eb7b3a05STakashi Sakamoto goto end; 287eb7b3a05STakashi Sakamoto } 288eb7b3a05STakashi Sakamoto pos = 0; 289eb7b3a05STakashi Sakamoto 290eb7b3a05STakashi Sakamoto /* positions in I/O buffer */ 291eb7b3a05STakashi Sakamoto pcm = 0; 292eb7b3a05STakashi Sakamoto midi = 0; 293eb7b3a05STakashi Sakamoto 294eb7b3a05STakashi Sakamoto /* the number of sections in AMDTP packet */ 295eb7b3a05STakashi Sakamoto sections = buf[pos++]; 296eb7b3a05STakashi Sakamoto 297eb7b3a05STakashi Sakamoto for (sec = 0; sec < sections; sec++) { 298eb7b3a05STakashi Sakamoto /* type of this section */ 299eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, 300eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 301eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_section_type(bebob->unit, addr, 302eb7b3a05STakashi Sakamoto sec, &type); 303eb7b3a05STakashi Sakamoto if (err < 0) { 304eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 305eb7b3a05STakashi Sakamoto "fail to get section type for isoc %s plug 0: %d\n", 306eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : 307eb7b3a05STakashi Sakamoto "out", 308eb7b3a05STakashi Sakamoto err); 309eb7b3a05STakashi Sakamoto goto end; 310eb7b3a05STakashi Sakamoto } 311eb7b3a05STakashi Sakamoto /* NoType */ 312eb7b3a05STakashi Sakamoto if (type == 0xff) { 313eb7b3a05STakashi Sakamoto err = -ENOSYS; 314eb7b3a05STakashi Sakamoto goto end; 315eb7b3a05STakashi Sakamoto } 316eb7b3a05STakashi Sakamoto 317eb7b3a05STakashi Sakamoto /* the number of channels in this section */ 318eb7b3a05STakashi Sakamoto channels = buf[pos++]; 319eb7b3a05STakashi Sakamoto 320eb7b3a05STakashi Sakamoto for (ch = 0; ch < channels; ch++) { 321eb7b3a05STakashi Sakamoto /* position of this channel in AMDTP packet */ 322eb7b3a05STakashi Sakamoto stm_pos = buf[pos++] - 1; 323eb7b3a05STakashi Sakamoto /* location of this channel in this section */ 324eb7b3a05STakashi Sakamoto sec_loc = buf[pos++] - 1; 325eb7b3a05STakashi Sakamoto 3269076c22dSTakashi Sakamoto /* 3279076c22dSTakashi Sakamoto * Basically the number of location is within the 3289076c22dSTakashi Sakamoto * number of channels in this section. But some models 3299076c22dSTakashi Sakamoto * of M-Audio don't follow this. Its location for MIDI 3309076c22dSTakashi Sakamoto * is the position of MIDI channels in AMDTP packet. 3319076c22dSTakashi Sakamoto */ 3329076c22dSTakashi Sakamoto if (sec_loc >= channels) 3339076c22dSTakashi Sakamoto sec_loc = ch; 3349076c22dSTakashi Sakamoto 335eb7b3a05STakashi Sakamoto switch (type) { 336eb7b3a05STakashi Sakamoto /* for MIDI conformant data channel */ 337eb7b3a05STakashi Sakamoto case 0x0a: 338eb7b3a05STakashi Sakamoto /* AMDTP_MAX_CHANNELS_FOR_MIDI is 1. */ 339eb7b3a05STakashi Sakamoto if ((midi > 0) && (stm_pos != midi)) { 340eb7b3a05STakashi Sakamoto err = -ENOSYS; 341eb7b3a05STakashi Sakamoto goto end; 342eb7b3a05STakashi Sakamoto } 343f65be911STakashi Sakamoto amdtp_am824_set_midi_position(s, stm_pos); 344eb7b3a05STakashi Sakamoto midi = stm_pos; 345eb7b3a05STakashi Sakamoto break; 346eb7b3a05STakashi Sakamoto /* for PCM data channel */ 347eb7b3a05STakashi Sakamoto case 0x01: /* Headphone */ 348eb7b3a05STakashi Sakamoto case 0x02: /* Microphone */ 349eb7b3a05STakashi Sakamoto case 0x03: /* Line */ 350eb7b3a05STakashi Sakamoto case 0x04: /* SPDIF */ 351eb7b3a05STakashi Sakamoto case 0x05: /* ADAT */ 352eb7b3a05STakashi Sakamoto case 0x06: /* TDIF */ 353eb7b3a05STakashi Sakamoto case 0x07: /* MADI */ 354eb7b3a05STakashi Sakamoto /* for undefined/changeable signal */ 355eb7b3a05STakashi Sakamoto case 0x08: /* Analog */ 356eb7b3a05STakashi Sakamoto case 0x09: /* Digital */ 357eb7b3a05STakashi Sakamoto default: 358eb7b3a05STakashi Sakamoto location = pcm + sec_loc; 35949c7b3fcSTakashi Sakamoto if (location >= AM824_MAX_CHANNELS_FOR_PCM) { 360eb7b3a05STakashi Sakamoto err = -ENOSYS; 361eb7b3a05STakashi Sakamoto goto end; 362eb7b3a05STakashi Sakamoto } 363f65be911STakashi Sakamoto amdtp_am824_set_pcm_position(s, location, 364f65be911STakashi Sakamoto stm_pos); 365eb7b3a05STakashi Sakamoto break; 366eb7b3a05STakashi Sakamoto } 367eb7b3a05STakashi Sakamoto } 368eb7b3a05STakashi Sakamoto 369eb7b3a05STakashi Sakamoto if (type != 0x0a) 370eb7b3a05STakashi Sakamoto pcm += channels; 371eb7b3a05STakashi Sakamoto else 372eb7b3a05STakashi Sakamoto midi += channels; 373eb7b3a05STakashi Sakamoto } 374eb7b3a05STakashi Sakamoto end: 375eb7b3a05STakashi Sakamoto kfree(buf); 376eb7b3a05STakashi Sakamoto return err; 377eb7b3a05STakashi Sakamoto } 378eb7b3a05STakashi Sakamoto 379eb7b3a05STakashi Sakamoto static int 380eb7b3a05STakashi Sakamoto init_both_connections(struct snd_bebob *bebob) 381eb7b3a05STakashi Sakamoto { 382eb7b3a05STakashi Sakamoto int err; 383eb7b3a05STakashi Sakamoto 384eb7b3a05STakashi Sakamoto err = cmp_connection_init(&bebob->in_conn, 385eb7b3a05STakashi Sakamoto bebob->unit, CMP_INPUT, 0); 386eb7b3a05STakashi Sakamoto if (err < 0) 387eb7b3a05STakashi Sakamoto goto end; 388eb7b3a05STakashi Sakamoto 389eb7b3a05STakashi Sakamoto err = cmp_connection_init(&bebob->out_conn, 390eb7b3a05STakashi Sakamoto bebob->unit, CMP_OUTPUT, 0); 391eb7b3a05STakashi Sakamoto if (err < 0) 392eb7b3a05STakashi Sakamoto cmp_connection_destroy(&bebob->in_conn); 393eb7b3a05STakashi Sakamoto end: 394eb7b3a05STakashi Sakamoto return err; 395eb7b3a05STakashi Sakamoto } 396eb7b3a05STakashi Sakamoto 397eb7b3a05STakashi Sakamoto static int 398eb7b3a05STakashi Sakamoto check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) 399eb7b3a05STakashi Sakamoto { 400eb7b3a05STakashi Sakamoto struct cmp_connection *conn; 401eb7b3a05STakashi Sakamoto bool used; 402eb7b3a05STakashi Sakamoto int err; 403eb7b3a05STakashi Sakamoto 404eb7b3a05STakashi Sakamoto if (s == &bebob->tx_stream) 405eb7b3a05STakashi Sakamoto conn = &bebob->out_conn; 406eb7b3a05STakashi Sakamoto else 407eb7b3a05STakashi Sakamoto conn = &bebob->in_conn; 408eb7b3a05STakashi Sakamoto 409eb7b3a05STakashi Sakamoto err = cmp_connection_check_used(conn, &used); 410eb7b3a05STakashi Sakamoto if ((err >= 0) && used && !amdtp_stream_running(s)) { 411eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 412eb7b3a05STakashi Sakamoto "Connection established by others: %cPCR[%d]\n", 413eb7b3a05STakashi Sakamoto (conn->direction == CMP_OUTPUT) ? 'o' : 'i', 414eb7b3a05STakashi Sakamoto conn->pcr_index); 415eb7b3a05STakashi Sakamoto err = -EBUSY; 416eb7b3a05STakashi Sakamoto } 417eb7b3a05STakashi Sakamoto 418eb7b3a05STakashi Sakamoto return err; 419eb7b3a05STakashi Sakamoto } 420eb7b3a05STakashi Sakamoto 421eb7b3a05STakashi Sakamoto static int 422eb7b3a05STakashi Sakamoto make_both_connections(struct snd_bebob *bebob, unsigned int rate) 423eb7b3a05STakashi Sakamoto { 424b6bc8123STakashi Sakamoto int index, pcm_channels, midi_channels, err = 0; 425b6bc8123STakashi Sakamoto 426b6bc8123STakashi Sakamoto if (bebob->connected) 427b6bc8123STakashi Sakamoto goto end; 428eb7b3a05STakashi Sakamoto 429eb7b3a05STakashi Sakamoto /* confirm params for both streams */ 43007905298SLucas Tanure err = get_formation_index(rate, &index); 43107905298SLucas Tanure if (err < 0) 43207905298SLucas Tanure goto end; 433eb7b3a05STakashi Sakamoto pcm_channels = bebob->tx_stream_formations[index].pcm; 434eb7b3a05STakashi Sakamoto midi_channels = bebob->tx_stream_formations[index].midi; 43551c29fd2STakashi Sakamoto err = amdtp_am824_set_parameters(&bebob->tx_stream, rate, 43627ec83b5STakashi Sakamoto pcm_channels, midi_channels * 8, 43727ec83b5STakashi Sakamoto false); 438547e631cSTakashi Sakamoto if (err < 0) 439547e631cSTakashi Sakamoto goto end; 440547e631cSTakashi Sakamoto 441eb7b3a05STakashi Sakamoto pcm_channels = bebob->rx_stream_formations[index].pcm; 442eb7b3a05STakashi Sakamoto midi_channels = bebob->rx_stream_formations[index].midi; 44351c29fd2STakashi Sakamoto err = amdtp_am824_set_parameters(&bebob->rx_stream, rate, 44427ec83b5STakashi Sakamoto pcm_channels, midi_channels * 8, 44527ec83b5STakashi Sakamoto false); 446547e631cSTakashi Sakamoto if (err < 0) 447547e631cSTakashi Sakamoto goto end; 448eb7b3a05STakashi Sakamoto 449eb7b3a05STakashi Sakamoto /* establish connections for both streams */ 450eb7b3a05STakashi Sakamoto err = cmp_connection_establish(&bebob->out_conn, 451eb7b3a05STakashi Sakamoto amdtp_stream_get_max_payload(&bebob->tx_stream)); 452eb7b3a05STakashi Sakamoto if (err < 0) 453eb7b3a05STakashi Sakamoto goto end; 454eb7b3a05STakashi Sakamoto err = cmp_connection_establish(&bebob->in_conn, 455eb7b3a05STakashi Sakamoto amdtp_stream_get_max_payload(&bebob->rx_stream)); 456b6bc8123STakashi Sakamoto if (err < 0) { 457eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->out_conn); 458b6bc8123STakashi Sakamoto goto end; 459b6bc8123STakashi Sakamoto } 460b6bc8123STakashi Sakamoto 461b6bc8123STakashi Sakamoto bebob->connected = true; 462eb7b3a05STakashi Sakamoto end: 463eb7b3a05STakashi Sakamoto return err; 464eb7b3a05STakashi Sakamoto } 465eb7b3a05STakashi Sakamoto 466eb7b3a05STakashi Sakamoto static void 467eb7b3a05STakashi Sakamoto break_both_connections(struct snd_bebob *bebob) 468eb7b3a05STakashi Sakamoto { 469eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->in_conn); 470eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->out_conn); 471b6bc8123STakashi Sakamoto 472b6bc8123STakashi Sakamoto bebob->connected = false; 4733149ac48STakashi Sakamoto 4743149ac48STakashi Sakamoto /* These models seems to be in transition state for a longer time. */ 4753149ac48STakashi Sakamoto if (bebob->maudio_special_quirk != NULL) 4763149ac48STakashi Sakamoto msleep(200); 477eb7b3a05STakashi Sakamoto } 478eb7b3a05STakashi Sakamoto 479eb7b3a05STakashi Sakamoto static void 480eb7b3a05STakashi Sakamoto destroy_both_connections(struct snd_bebob *bebob) 481eb7b3a05STakashi Sakamoto { 482eb7b3a05STakashi Sakamoto cmp_connection_destroy(&bebob->in_conn); 483eb7b3a05STakashi Sakamoto cmp_connection_destroy(&bebob->out_conn); 484eb7b3a05STakashi Sakamoto } 485eb7b3a05STakashi Sakamoto 486eb7b3a05STakashi Sakamoto static int 487eb7b3a05STakashi Sakamoto get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) 488eb7b3a05STakashi Sakamoto { 48905773792STakashi Sakamoto enum snd_bebob_clock_type src; 49005773792STakashi Sakamoto int err; 49105773792STakashi Sakamoto 49205773792STakashi Sakamoto err = snd_bebob_stream_get_clock_src(bebob, &src); 49305773792STakashi Sakamoto if (err < 0) 49405773792STakashi Sakamoto return err; 49505773792STakashi Sakamoto 49605773792STakashi Sakamoto switch (src) { 49705773792STakashi Sakamoto case SND_BEBOB_CLOCK_TYPE_INTERNAL: 49805773792STakashi Sakamoto case SND_BEBOB_CLOCK_TYPE_EXTERNAL: 499eb7b3a05STakashi Sakamoto *sync_mode = CIP_SYNC_TO_DEVICE; 50005773792STakashi Sakamoto break; 50105773792STakashi Sakamoto default: 50205773792STakashi Sakamoto case SND_BEBOB_CLOCK_TYPE_SYT: 50305773792STakashi Sakamoto *sync_mode = 0; 50405773792STakashi Sakamoto break; 50505773792STakashi Sakamoto } 50605773792STakashi Sakamoto 507eb7b3a05STakashi Sakamoto return 0; 508eb7b3a05STakashi Sakamoto } 509eb7b3a05STakashi Sakamoto 510eb7b3a05STakashi Sakamoto static int 511eb7b3a05STakashi Sakamoto start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream, 512eb7b3a05STakashi Sakamoto unsigned int rate) 513eb7b3a05STakashi Sakamoto { 514eb7b3a05STakashi Sakamoto struct cmp_connection *conn; 515eb7b3a05STakashi Sakamoto int err = 0; 516eb7b3a05STakashi Sakamoto 517eb7b3a05STakashi Sakamoto if (stream == &bebob->rx_stream) 518eb7b3a05STakashi Sakamoto conn = &bebob->in_conn; 519eb7b3a05STakashi Sakamoto else 520eb7b3a05STakashi Sakamoto conn = &bebob->out_conn; 521eb7b3a05STakashi Sakamoto 522eb7b3a05STakashi Sakamoto /* channel mapping */ 5233149ac48STakashi Sakamoto if (bebob->maudio_special_quirk == NULL) { 524eb7b3a05STakashi Sakamoto err = map_data_channels(bebob, stream); 525eb7b3a05STakashi Sakamoto if (err < 0) 526eb7b3a05STakashi Sakamoto goto end; 5273149ac48STakashi Sakamoto } 528eb7b3a05STakashi Sakamoto 529eb7b3a05STakashi Sakamoto /* start amdtp stream */ 530eb7b3a05STakashi Sakamoto err = amdtp_stream_start(stream, 531eb7b3a05STakashi Sakamoto conn->resources.channel, 532eb7b3a05STakashi Sakamoto conn->speed); 533eb7b3a05STakashi Sakamoto end: 534eb7b3a05STakashi Sakamoto return err; 535eb7b3a05STakashi Sakamoto } 536eb7b3a05STakashi Sakamoto 537eb7b3a05STakashi Sakamoto int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) 538eb7b3a05STakashi Sakamoto { 539eb7b3a05STakashi Sakamoto int err; 540eb7b3a05STakashi Sakamoto 541eb7b3a05STakashi Sakamoto err = init_both_connections(bebob); 542eb7b3a05STakashi Sakamoto if (err < 0) 543eb7b3a05STakashi Sakamoto goto end; 544eb7b3a05STakashi Sakamoto 5455955815eSTakashi Sakamoto err = amdtp_am824_init(&bebob->tx_stream, bebob->unit, 546eb7b3a05STakashi Sakamoto AMDTP_IN_STREAM, CIP_BLOCKING); 547eb7b3a05STakashi Sakamoto if (err < 0) { 548eb7b3a05STakashi Sakamoto amdtp_stream_destroy(&bebob->tx_stream); 549eb7b3a05STakashi Sakamoto destroy_both_connections(bebob); 550eb7b3a05STakashi Sakamoto goto end; 551eb7b3a05STakashi Sakamoto } 552b6bc8123STakashi Sakamoto /* See comments in next function */ 553b6bc8123STakashi Sakamoto init_completion(&bebob->bus_reset); 554b6bc8123STakashi Sakamoto bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; 555c4d860a0STakashi Sakamoto 556c4d860a0STakashi Sakamoto /* 557c4d860a0STakashi Sakamoto * BeBoB v3 transfers packets with these qurks: 558c4d860a0STakashi Sakamoto * - In the beginning of streaming, the value of dbc is incremented 559c4d860a0STakashi Sakamoto * even if no data blocks are transferred. 560c4d860a0STakashi Sakamoto * - The value of dbc is reset suddenly. 561c4d860a0STakashi Sakamoto */ 562c4d860a0STakashi Sakamoto if (bebob->version > 2) 563c4d860a0STakashi Sakamoto bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | 564c4d860a0STakashi Sakamoto CIP_SKIP_DBC_ZERO_CHECK; 565c4d860a0STakashi Sakamoto 5669d59124cSTakashi Sakamoto /* 5679d59124cSTakashi Sakamoto * At high sampling rate, M-Audio special firmware transmits empty 5689d59124cSTakashi Sakamoto * packet with the value of dbc incremented by 8 but the others are 5699d59124cSTakashi Sakamoto * valid to IEC 61883-1. 5709d59124cSTakashi Sakamoto */ 5719d59124cSTakashi Sakamoto if (bebob->maudio_special_quirk) 5729d59124cSTakashi Sakamoto bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; 573eb7b3a05STakashi Sakamoto 5745955815eSTakashi Sakamoto err = amdtp_am824_init(&bebob->rx_stream, bebob->unit, 575eb7b3a05STakashi Sakamoto AMDTP_OUT_STREAM, CIP_BLOCKING); 576eb7b3a05STakashi Sakamoto if (err < 0) { 577eb7b3a05STakashi Sakamoto amdtp_stream_destroy(&bebob->tx_stream); 578eb7b3a05STakashi Sakamoto amdtp_stream_destroy(&bebob->rx_stream); 579eb7b3a05STakashi Sakamoto destroy_both_connections(bebob); 580eb7b3a05STakashi Sakamoto } 581eb7b3a05STakashi Sakamoto end: 582eb7b3a05STakashi Sakamoto return err; 583eb7b3a05STakashi Sakamoto } 584eb7b3a05STakashi Sakamoto 5854a286d55STakashi Sakamoto int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) 586eb7b3a05STakashi Sakamoto { 5876b9866c8SJulia Lawall const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; 588eb7b3a05STakashi Sakamoto struct amdtp_stream *master, *slave; 589eb7b3a05STakashi Sakamoto enum cip_flags sync_mode; 590eb7b3a05STakashi Sakamoto unsigned int curr_rate; 591b6bc8123STakashi Sakamoto bool updated = false; 592eb7b3a05STakashi Sakamoto int err = 0; 593eb7b3a05STakashi Sakamoto 594b6bc8123STakashi Sakamoto /* 595b6bc8123STakashi Sakamoto * Normal BeBoB firmware has a quirk at bus reset to transmits packets 596b6bc8123STakashi Sakamoto * with discontinuous value in dbc field. 597b6bc8123STakashi Sakamoto * 598b6bc8123STakashi Sakamoto * This 'struct completion' is used to call .update() at first to update 599b6bc8123STakashi Sakamoto * connections/streams. Next following codes handle streaming error. 600b6bc8123STakashi Sakamoto */ 601b6bc8123STakashi Sakamoto if (amdtp_streaming_error(&bebob->tx_stream)) { 602b6bc8123STakashi Sakamoto if (completion_done(&bebob->bus_reset)) 603b6bc8123STakashi Sakamoto reinit_completion(&bebob->bus_reset); 604b6bc8123STakashi Sakamoto 605b6bc8123STakashi Sakamoto updated = (wait_for_completion_interruptible_timeout( 606b6bc8123STakashi Sakamoto &bebob->bus_reset, 607b6bc8123STakashi Sakamoto msecs_to_jiffies(FW_ISO_RESOURCE_DELAY)) > 0); 608b6bc8123STakashi Sakamoto } 609b6bc8123STakashi Sakamoto 610eb7b3a05STakashi Sakamoto mutex_lock(&bebob->mutex); 611eb7b3a05STakashi Sakamoto 612eb7b3a05STakashi Sakamoto /* Need no substreams */ 6138d1c2694STakashi Sakamoto if (atomic_read(&bebob->substreams_counter) == 0) 614eb7b3a05STakashi Sakamoto goto end; 615eb7b3a05STakashi Sakamoto 616eb7b3a05STakashi Sakamoto err = get_sync_mode(bebob, &sync_mode); 617eb7b3a05STakashi Sakamoto if (err < 0) 618eb7b3a05STakashi Sakamoto goto end; 619eb7b3a05STakashi Sakamoto if (sync_mode == CIP_SYNC_TO_DEVICE) { 620eb7b3a05STakashi Sakamoto master = &bebob->tx_stream; 621eb7b3a05STakashi Sakamoto slave = &bebob->rx_stream; 622eb7b3a05STakashi Sakamoto } else { 623eb7b3a05STakashi Sakamoto master = &bebob->rx_stream; 624eb7b3a05STakashi Sakamoto slave = &bebob->tx_stream; 625eb7b3a05STakashi Sakamoto } 626eb7b3a05STakashi Sakamoto 627eb7b3a05STakashi Sakamoto /* 628eb7b3a05STakashi Sakamoto * Considering JACK/FFADO streaming: 629eb7b3a05STakashi Sakamoto * TODO: This can be removed hwdep functionality becomes popular. 630eb7b3a05STakashi Sakamoto */ 631eb7b3a05STakashi Sakamoto err = check_connection_used_by_others(bebob, master); 632eb7b3a05STakashi Sakamoto if (err < 0) 633eb7b3a05STakashi Sakamoto goto end; 634eb7b3a05STakashi Sakamoto 635b6bc8123STakashi Sakamoto /* 636b6bc8123STakashi Sakamoto * packet queueing error or detecting discontinuity 637b6bc8123STakashi Sakamoto * 638b6bc8123STakashi Sakamoto * At bus reset, connections should not be broken here. So streams need 639b6bc8123STakashi Sakamoto * to be re-started. This is a reason to use SKIP_INIT_DBC_CHECK flag. 640b6bc8123STakashi Sakamoto */ 641b6bc8123STakashi Sakamoto if (amdtp_streaming_error(master)) 642eb7b3a05STakashi Sakamoto amdtp_stream_stop(master); 643eb7b3a05STakashi Sakamoto if (amdtp_streaming_error(slave)) 644eb7b3a05STakashi Sakamoto amdtp_stream_stop(slave); 645b6bc8123STakashi Sakamoto if (!updated && 646b6bc8123STakashi Sakamoto !amdtp_stream_running(master) && !amdtp_stream_running(slave)) 647b6bc8123STakashi Sakamoto break_both_connections(bebob); 648eb7b3a05STakashi Sakamoto 649eb7b3a05STakashi Sakamoto /* stop streams if rate is different */ 6501fc9522aSTakashi Sakamoto err = rate_spec->get(bebob, &curr_rate); 651eb7b3a05STakashi Sakamoto if (err < 0) { 652eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 653eb7b3a05STakashi Sakamoto "fail to get sampling rate: %d\n", err); 654eb7b3a05STakashi Sakamoto goto end; 655eb7b3a05STakashi Sakamoto } 656eb7b3a05STakashi Sakamoto if (rate == 0) 657eb7b3a05STakashi Sakamoto rate = curr_rate; 658eb7b3a05STakashi Sakamoto if (rate != curr_rate) { 659eb7b3a05STakashi Sakamoto amdtp_stream_stop(master); 660eb7b3a05STakashi Sakamoto amdtp_stream_stop(slave); 661eb7b3a05STakashi Sakamoto break_both_connections(bebob); 662eb7b3a05STakashi Sakamoto } 663eb7b3a05STakashi Sakamoto 664eb7b3a05STakashi Sakamoto /* master should be always running */ 665eb7b3a05STakashi Sakamoto if (!amdtp_stream_running(master)) { 666eb7b3a05STakashi Sakamoto amdtp_stream_set_sync(sync_mode, master, slave); 667eb7b3a05STakashi Sakamoto bebob->master = master; 668eb7b3a05STakashi Sakamoto 669eb7b3a05STakashi Sakamoto /* 670eb7b3a05STakashi Sakamoto * NOTE: 671eb7b3a05STakashi Sakamoto * If establishing connections at first, Yamaha GO46 672eb7b3a05STakashi Sakamoto * (and maybe Terratec X24) don't generate sound. 6733149ac48STakashi Sakamoto * 6743149ac48STakashi Sakamoto * For firmware customized by M-Audio, refer to next NOTE. 675eb7b3a05STakashi Sakamoto */ 6763149ac48STakashi Sakamoto if (bebob->maudio_special_quirk == NULL) { 6771fc9522aSTakashi Sakamoto err = rate_spec->set(bebob, rate); 678eb7b3a05STakashi Sakamoto if (err < 0) { 679eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 680eb7b3a05STakashi Sakamoto "fail to set sampling rate: %d\n", 681eb7b3a05STakashi Sakamoto err); 682eb7b3a05STakashi Sakamoto goto end; 683eb7b3a05STakashi Sakamoto } 6843149ac48STakashi Sakamoto } 685eb7b3a05STakashi Sakamoto 686eb7b3a05STakashi Sakamoto err = make_both_connections(bebob, rate); 687eb7b3a05STakashi Sakamoto if (err < 0) 688eb7b3a05STakashi Sakamoto goto end; 689eb7b3a05STakashi Sakamoto 690eb7b3a05STakashi Sakamoto err = start_stream(bebob, master, rate); 691eb7b3a05STakashi Sakamoto if (err < 0) { 692eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 693eb7b3a05STakashi Sakamoto "fail to run AMDTP master stream:%d\n", err); 694eb7b3a05STakashi Sakamoto break_both_connections(bebob); 695eb7b3a05STakashi Sakamoto goto end; 696eb7b3a05STakashi Sakamoto } 697eb7b3a05STakashi Sakamoto 6983149ac48STakashi Sakamoto /* 6993149ac48STakashi Sakamoto * NOTE: 7003149ac48STakashi Sakamoto * The firmware customized by M-Audio uses these commands to 7013149ac48STakashi Sakamoto * start transmitting stream. This is not usual way. 7023149ac48STakashi Sakamoto */ 7033149ac48STakashi Sakamoto if (bebob->maudio_special_quirk != NULL) { 7043149ac48STakashi Sakamoto err = rate_spec->set(bebob, rate); 7053149ac48STakashi Sakamoto if (err < 0) { 7063149ac48STakashi Sakamoto dev_err(&bebob->unit->device, 7073149ac48STakashi Sakamoto "fail to ensure sampling rate: %d\n", 7083149ac48STakashi Sakamoto err); 7093149ac48STakashi Sakamoto amdtp_stream_stop(master); 7103149ac48STakashi Sakamoto break_both_connections(bebob); 7113149ac48STakashi Sakamoto goto end; 7123149ac48STakashi Sakamoto } 7133149ac48STakashi Sakamoto } 7143149ac48STakashi Sakamoto 715eb7b3a05STakashi Sakamoto /* wait first callback */ 716eb7b3a05STakashi Sakamoto if (!amdtp_stream_wait_callback(master, CALLBACK_TIMEOUT)) { 717eb7b3a05STakashi Sakamoto amdtp_stream_stop(master); 718eb7b3a05STakashi Sakamoto break_both_connections(bebob); 719eb7b3a05STakashi Sakamoto err = -ETIMEDOUT; 720eb7b3a05STakashi Sakamoto goto end; 721eb7b3a05STakashi Sakamoto } 722eb7b3a05STakashi Sakamoto } 723eb7b3a05STakashi Sakamoto 724eb7b3a05STakashi Sakamoto /* start slave if needed */ 7258d1c2694STakashi Sakamoto if (!amdtp_stream_running(slave)) { 726eb7b3a05STakashi Sakamoto err = start_stream(bebob, slave, rate); 727eb7b3a05STakashi Sakamoto if (err < 0) { 728eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 729eb7b3a05STakashi Sakamoto "fail to run AMDTP slave stream:%d\n", err); 730eb7b3a05STakashi Sakamoto amdtp_stream_stop(master); 731eb7b3a05STakashi Sakamoto break_both_connections(bebob); 732eb7b3a05STakashi Sakamoto goto end; 733eb7b3a05STakashi Sakamoto } 734eb7b3a05STakashi Sakamoto 735eb7b3a05STakashi Sakamoto /* wait first callback */ 736eb7b3a05STakashi Sakamoto if (!amdtp_stream_wait_callback(slave, CALLBACK_TIMEOUT)) { 737eb7b3a05STakashi Sakamoto amdtp_stream_stop(slave); 738eb7b3a05STakashi Sakamoto amdtp_stream_stop(master); 739eb7b3a05STakashi Sakamoto break_both_connections(bebob); 740eb7b3a05STakashi Sakamoto err = -ETIMEDOUT; 741eb7b3a05STakashi Sakamoto } 742eb7b3a05STakashi Sakamoto } 743eb7b3a05STakashi Sakamoto end: 744eb7b3a05STakashi Sakamoto mutex_unlock(&bebob->mutex); 745eb7b3a05STakashi Sakamoto return err; 746eb7b3a05STakashi Sakamoto } 747eb7b3a05STakashi Sakamoto 748eb7b3a05STakashi Sakamoto void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) 749eb7b3a05STakashi Sakamoto { 750eb7b3a05STakashi Sakamoto struct amdtp_stream *master, *slave; 751eb7b3a05STakashi Sakamoto 752eb7b3a05STakashi Sakamoto if (bebob->master == &bebob->rx_stream) { 753eb7b3a05STakashi Sakamoto slave = &bebob->tx_stream; 754eb7b3a05STakashi Sakamoto master = &bebob->rx_stream; 755eb7b3a05STakashi Sakamoto } else { 756eb7b3a05STakashi Sakamoto slave = &bebob->rx_stream; 757eb7b3a05STakashi Sakamoto master = &bebob->tx_stream; 758eb7b3a05STakashi Sakamoto } 759eb7b3a05STakashi Sakamoto 760c6e5e741STakashi Sakamoto mutex_lock(&bebob->mutex); 761c6e5e741STakashi Sakamoto 7628d1c2694STakashi Sakamoto if (atomic_read(&bebob->substreams_counter) == 0) { 7638d1c2694STakashi Sakamoto amdtp_stream_pcm_abort(master); 7648d1c2694STakashi Sakamoto amdtp_stream_stop(master); 7658d1c2694STakashi Sakamoto 766eb7b3a05STakashi Sakamoto amdtp_stream_pcm_abort(slave); 767eb7b3a05STakashi Sakamoto amdtp_stream_stop(slave); 768eb7b3a05STakashi Sakamoto 769eb7b3a05STakashi Sakamoto break_both_connections(bebob); 770eb7b3a05STakashi Sakamoto } 771eb7b3a05STakashi Sakamoto 772eb7b3a05STakashi Sakamoto mutex_unlock(&bebob->mutex); 773eb7b3a05STakashi Sakamoto } 774eb7b3a05STakashi Sakamoto 775eb7b3a05STakashi Sakamoto void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) 776eb7b3a05STakashi Sakamoto { 777eb7b3a05STakashi Sakamoto /* vs. XRUN recovery due to discontinuity at bus reset */ 778eb7b3a05STakashi Sakamoto mutex_lock(&bebob->mutex); 779eb7b3a05STakashi Sakamoto 780eb7b3a05STakashi Sakamoto if ((cmp_connection_update(&bebob->in_conn) < 0) || 781eb7b3a05STakashi Sakamoto (cmp_connection_update(&bebob->out_conn) < 0)) { 782eb7b3a05STakashi Sakamoto amdtp_stream_pcm_abort(&bebob->rx_stream); 783eb7b3a05STakashi Sakamoto amdtp_stream_pcm_abort(&bebob->tx_stream); 784eb7b3a05STakashi Sakamoto amdtp_stream_stop(&bebob->rx_stream); 785eb7b3a05STakashi Sakamoto amdtp_stream_stop(&bebob->tx_stream); 786eb7b3a05STakashi Sakamoto break_both_connections(bebob); 787eb7b3a05STakashi Sakamoto } else { 788eb7b3a05STakashi Sakamoto amdtp_stream_update(&bebob->rx_stream); 789eb7b3a05STakashi Sakamoto amdtp_stream_update(&bebob->tx_stream); 790eb7b3a05STakashi Sakamoto } 791eb7b3a05STakashi Sakamoto 792b6bc8123STakashi Sakamoto /* wake up stream_start_duplex() */ 793b6bc8123STakashi Sakamoto if (!completion_done(&bebob->bus_reset)) 794b6bc8123STakashi Sakamoto complete_all(&bebob->bus_reset); 795b6bc8123STakashi Sakamoto 796eb7b3a05STakashi Sakamoto mutex_unlock(&bebob->mutex); 797eb7b3a05STakashi Sakamoto } 798eb7b3a05STakashi Sakamoto 799d23c2cc4STakashi Sakamoto /* 800d23c2cc4STakashi Sakamoto * This function should be called before starting streams or after stopping 801d23c2cc4STakashi Sakamoto * streams. 802d23c2cc4STakashi Sakamoto */ 803eb7b3a05STakashi Sakamoto void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) 804eb7b3a05STakashi Sakamoto { 805eb7b3a05STakashi Sakamoto amdtp_stream_destroy(&bebob->rx_stream); 806eb7b3a05STakashi Sakamoto amdtp_stream_destroy(&bebob->tx_stream); 807eb7b3a05STakashi Sakamoto 808eb7b3a05STakashi Sakamoto destroy_both_connections(bebob); 809eb7b3a05STakashi Sakamoto } 810eb7b3a05STakashi Sakamoto 811eb7b3a05STakashi Sakamoto /* 812eb7b3a05STakashi Sakamoto * See: Table 50: Extended Stream Format Info Format Hierarchy Level 2’ 813eb7b3a05STakashi Sakamoto * in Additional AVC commands (Nov 2003, BridgeCo) 814eb7b3a05STakashi Sakamoto * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005 815eb7b3a05STakashi Sakamoto */ 816eb7b3a05STakashi Sakamoto static int 817eb7b3a05STakashi Sakamoto parse_stream_formation(u8 *buf, unsigned int len, 818eb7b3a05STakashi Sakamoto struct snd_bebob_stream_formation *formation) 819eb7b3a05STakashi Sakamoto { 820eb7b3a05STakashi Sakamoto unsigned int i, e, channels, format; 821eb7b3a05STakashi Sakamoto 822eb7b3a05STakashi Sakamoto /* 823eb7b3a05STakashi Sakamoto * this module can support a hierarchy combination that: 824eb7b3a05STakashi Sakamoto * Root: Audio and Music (0x90) 825eb7b3a05STakashi Sakamoto * Level 1: AM824 Compound (0x40) 826eb7b3a05STakashi Sakamoto */ 827eb7b3a05STakashi Sakamoto if ((buf[0] != 0x90) || (buf[1] != 0x40)) 828eb7b3a05STakashi Sakamoto return -ENOSYS; 829eb7b3a05STakashi Sakamoto 830eb7b3a05STakashi Sakamoto /* check sampling rate */ 831eb7b3a05STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(bridgeco_freq_table); i++) { 832eb7b3a05STakashi Sakamoto if (buf[2] == bridgeco_freq_table[i]) 833eb7b3a05STakashi Sakamoto break; 834eb7b3a05STakashi Sakamoto } 83533a5f989SDan Carpenter if (i == ARRAY_SIZE(bridgeco_freq_table)) 836eb7b3a05STakashi Sakamoto return -ENOSYS; 837eb7b3a05STakashi Sakamoto 838eb7b3a05STakashi Sakamoto /* Avoid double count by different entries for the same rate. */ 839eb7b3a05STakashi Sakamoto memset(&formation[i], 0, sizeof(struct snd_bebob_stream_formation)); 840eb7b3a05STakashi Sakamoto 841eb7b3a05STakashi Sakamoto for (e = 0; e < buf[4]; e++) { 842eb7b3a05STakashi Sakamoto channels = buf[5 + e * 2]; 843eb7b3a05STakashi Sakamoto format = buf[6 + e * 2]; 844eb7b3a05STakashi Sakamoto 845eb7b3a05STakashi Sakamoto switch (format) { 84651fa31d4STakashi Sakamoto /* IEC 60958 Conformant, currently handled as MBLA */ 847eb7b3a05STakashi Sakamoto case 0x00: 848eb7b3a05STakashi Sakamoto /* Multi bit linear audio */ 849eb7b3a05STakashi Sakamoto case 0x06: /* Raw */ 850eb7b3a05STakashi Sakamoto formation[i].pcm += channels; 851eb7b3a05STakashi Sakamoto break; 852eb7b3a05STakashi Sakamoto /* MIDI Conformant */ 853eb7b3a05STakashi Sakamoto case 0x0d: 854eb7b3a05STakashi Sakamoto formation[i].midi += channels; 855eb7b3a05STakashi Sakamoto break; 856eb7b3a05STakashi Sakamoto /* IEC 61937-3 to 7 */ 857eb7b3a05STakashi Sakamoto case 0x01: 858eb7b3a05STakashi Sakamoto case 0x02: 859eb7b3a05STakashi Sakamoto case 0x03: 860eb7b3a05STakashi Sakamoto case 0x04: 861eb7b3a05STakashi Sakamoto case 0x05: 862eb7b3a05STakashi Sakamoto /* Multi bit linear audio */ 863eb7b3a05STakashi Sakamoto case 0x07: /* DVD-Audio */ 864eb7b3a05STakashi Sakamoto case 0x0c: /* High Precision */ 865eb7b3a05STakashi Sakamoto /* One Bit Audio */ 866eb7b3a05STakashi Sakamoto case 0x08: /* (Plain) Raw */ 867eb7b3a05STakashi Sakamoto case 0x09: /* (Plain) SACD */ 868eb7b3a05STakashi Sakamoto case 0x0a: /* (Encoded) Raw */ 869eb7b3a05STakashi Sakamoto case 0x0b: /* (Encoded) SACD */ 870eb7b3a05STakashi Sakamoto /* Synchronization Stream (Stereo Raw audio) */ 871eb7b3a05STakashi Sakamoto case 0x40: 872eb7b3a05STakashi Sakamoto /* Don't care */ 873eb7b3a05STakashi Sakamoto case 0xff: 874eb7b3a05STakashi Sakamoto default: 875eb7b3a05STakashi Sakamoto return -ENOSYS; /* not supported */ 876eb7b3a05STakashi Sakamoto } 877eb7b3a05STakashi Sakamoto } 878eb7b3a05STakashi Sakamoto 87949c7b3fcSTakashi Sakamoto if (formation[i].pcm > AM824_MAX_CHANNELS_FOR_PCM || 88049c7b3fcSTakashi Sakamoto formation[i].midi > AM824_MAX_CHANNELS_FOR_MIDI) 881eb7b3a05STakashi Sakamoto return -ENOSYS; 882eb7b3a05STakashi Sakamoto 883eb7b3a05STakashi Sakamoto return 0; 884eb7b3a05STakashi Sakamoto } 885eb7b3a05STakashi Sakamoto 886eb7b3a05STakashi Sakamoto static int 887eb7b3a05STakashi Sakamoto fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir, 888eb7b3a05STakashi Sakamoto unsigned short pid) 889eb7b3a05STakashi Sakamoto { 890eb7b3a05STakashi Sakamoto u8 *buf; 891eb7b3a05STakashi Sakamoto struct snd_bebob_stream_formation *formations; 892eb7b3a05STakashi Sakamoto unsigned int len, eid; 893eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES]; 894eb7b3a05STakashi Sakamoto int err; 895eb7b3a05STakashi Sakamoto 896eb7b3a05STakashi Sakamoto buf = kmalloc(FORMAT_MAXIMUM_LENGTH, GFP_KERNEL); 897eb7b3a05STakashi Sakamoto if (buf == NULL) 898eb7b3a05STakashi Sakamoto return -ENOMEM; 899eb7b3a05STakashi Sakamoto 900eb7b3a05STakashi Sakamoto if (dir == AVC_BRIDGECO_PLUG_DIR_IN) 901eb7b3a05STakashi Sakamoto formations = bebob->rx_stream_formations; 902eb7b3a05STakashi Sakamoto else 903eb7b3a05STakashi Sakamoto formations = bebob->tx_stream_formations; 904eb7b3a05STakashi Sakamoto 905eb7b3a05STakashi Sakamoto for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; eid++) { 906eb7b3a05STakashi Sakamoto len = FORMAT_MAXIMUM_LENGTH; 907eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, 908eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, pid); 909eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf, 910eb7b3a05STakashi Sakamoto &len, eid); 911eb7b3a05STakashi Sakamoto /* No entries remained. */ 912eb7b3a05STakashi Sakamoto if (err == -EINVAL && eid > 0) { 913eb7b3a05STakashi Sakamoto err = 0; 914eb7b3a05STakashi Sakamoto break; 915eb7b3a05STakashi Sakamoto } else if (err < 0) { 916eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 917eb7b3a05STakashi Sakamoto "fail to get stream format %d for isoc %s plug %d:%d\n", 918eb7b3a05STakashi Sakamoto eid, 919eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : 920eb7b3a05STakashi Sakamoto "out", 921eb7b3a05STakashi Sakamoto pid, err); 922eb7b3a05STakashi Sakamoto break; 923eb7b3a05STakashi Sakamoto } 924eb7b3a05STakashi Sakamoto 925eb7b3a05STakashi Sakamoto err = parse_stream_formation(buf, len, formations); 926eb7b3a05STakashi Sakamoto if (err < 0) 927eb7b3a05STakashi Sakamoto break; 928eb7b3a05STakashi Sakamoto } 929eb7b3a05STakashi Sakamoto 930eb7b3a05STakashi Sakamoto kfree(buf); 931eb7b3a05STakashi Sakamoto return err; 932eb7b3a05STakashi Sakamoto } 933eb7b3a05STakashi Sakamoto 934eb7b3a05STakashi Sakamoto static int 935eb7b3a05STakashi Sakamoto seek_msu_sync_input_plug(struct snd_bebob *bebob) 936eb7b3a05STakashi Sakamoto { 937eb7b3a05STakashi Sakamoto u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; 938a6b598bfSTakashi Sakamoto unsigned int i; 939a6b598bfSTakashi Sakamoto enum avc_bridgeco_plug_type type; 940eb7b3a05STakashi Sakamoto int err; 941eb7b3a05STakashi Sakamoto 942eb7b3a05STakashi Sakamoto /* Get the number of Music Sub Unit for both direction. */ 943eb7b3a05STakashi Sakamoto err = avc_general_get_plug_info(bebob->unit, 0x0c, 0x00, 0x00, plugs); 944eb7b3a05STakashi Sakamoto if (err < 0) { 945eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 946eb7b3a05STakashi Sakamoto "fail to get info for MSU in/out plugs: %d\n", 947eb7b3a05STakashi Sakamoto err); 948eb7b3a05STakashi Sakamoto goto end; 949eb7b3a05STakashi Sakamoto } 950eb7b3a05STakashi Sakamoto 951eb7b3a05STakashi Sakamoto /* seek destination plugs for 'MSU sync input' */ 952eb7b3a05STakashi Sakamoto bebob->sync_input_plug = -1; 953eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[0]; i++) { 954eb7b3a05STakashi Sakamoto avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, i); 955eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 956eb7b3a05STakashi Sakamoto if (err < 0) { 957eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 958eb7b3a05STakashi Sakamoto "fail to get type for MSU in plug %d: %d\n", 959eb7b3a05STakashi Sakamoto i, err); 960eb7b3a05STakashi Sakamoto goto end; 961eb7b3a05STakashi Sakamoto } 962eb7b3a05STakashi Sakamoto 963eb7b3a05STakashi Sakamoto if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { 964eb7b3a05STakashi Sakamoto bebob->sync_input_plug = i; 965eb7b3a05STakashi Sakamoto break; 966eb7b3a05STakashi Sakamoto } 967eb7b3a05STakashi Sakamoto } 968eb7b3a05STakashi Sakamoto end: 969eb7b3a05STakashi Sakamoto return err; 970eb7b3a05STakashi Sakamoto } 971eb7b3a05STakashi Sakamoto 972eb7b3a05STakashi Sakamoto int snd_bebob_stream_discover(struct snd_bebob *bebob) 973eb7b3a05STakashi Sakamoto { 9746b9866c8SJulia Lawall const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; 975eb7b3a05STakashi Sakamoto u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; 976eb7b3a05STakashi Sakamoto enum avc_bridgeco_plug_type type; 977eb7b3a05STakashi Sakamoto unsigned int i; 978eb7b3a05STakashi Sakamoto int err; 979eb7b3a05STakashi Sakamoto 980eb7b3a05STakashi Sakamoto /* the number of plugs for isoc in/out, ext in/out */ 981eb7b3a05STakashi Sakamoto err = avc_general_get_plug_info(bebob->unit, 0x1f, 0x07, 0x00, plugs); 982eb7b3a05STakashi Sakamoto if (err < 0) { 983eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 984eb7b3a05STakashi Sakamoto "fail to get info for isoc/external in/out plugs: %d\n", 985eb7b3a05STakashi Sakamoto err); 986eb7b3a05STakashi Sakamoto goto end; 987eb7b3a05STakashi Sakamoto } 988eb7b3a05STakashi Sakamoto 989eb7b3a05STakashi Sakamoto /* 990eb7b3a05STakashi Sakamoto * This module supports at least one isoc input plug and one isoc 991eb7b3a05STakashi Sakamoto * output plug. 992eb7b3a05STakashi Sakamoto */ 993eb7b3a05STakashi Sakamoto if ((plugs[0] == 0) || (plugs[1] == 0)) { 994eb7b3a05STakashi Sakamoto err = -ENOSYS; 995eb7b3a05STakashi Sakamoto goto end; 996eb7b3a05STakashi Sakamoto } 997eb7b3a05STakashi Sakamoto 998eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 999eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 1000eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 1001eb7b3a05STakashi Sakamoto if (err < 0) { 1002eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 1003eb7b3a05STakashi Sakamoto "fail to get type for isoc in plug 0: %d\n", err); 1004eb7b3a05STakashi Sakamoto goto end; 1005eb7b3a05STakashi Sakamoto } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { 1006eb7b3a05STakashi Sakamoto err = -ENOSYS; 1007eb7b3a05STakashi Sakamoto goto end; 1008eb7b3a05STakashi Sakamoto } 1009eb7b3a05STakashi Sakamoto err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_IN, 0); 1010eb7b3a05STakashi Sakamoto if (err < 0) 1011eb7b3a05STakashi Sakamoto goto end; 1012eb7b3a05STakashi Sakamoto 1013eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, 1014eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 1015eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 1016eb7b3a05STakashi Sakamoto if (err < 0) { 1017eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 1018eb7b3a05STakashi Sakamoto "fail to get type for isoc out plug 0: %d\n", err); 1019eb7b3a05STakashi Sakamoto goto end; 1020eb7b3a05STakashi Sakamoto } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { 1021eb7b3a05STakashi Sakamoto err = -ENOSYS; 1022eb7b3a05STakashi Sakamoto goto end; 1023eb7b3a05STakashi Sakamoto } 1024eb7b3a05STakashi Sakamoto err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_OUT, 0); 1025eb7b3a05STakashi Sakamoto if (err < 0) 1026eb7b3a05STakashi Sakamoto goto end; 1027eb7b3a05STakashi Sakamoto 1028eb7b3a05STakashi Sakamoto /* count external input plugs for MIDI */ 1029eb7b3a05STakashi Sakamoto bebob->midi_input_ports = 0; 1030eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[2]; i++) { 1031eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 1032eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, i); 1033eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 1034eb7b3a05STakashi Sakamoto if (err < 0) { 1035eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 1036eb7b3a05STakashi Sakamoto "fail to get type for external in plug %d: %d\n", 1037eb7b3a05STakashi Sakamoto i, err); 1038eb7b3a05STakashi Sakamoto goto end; 1039eb7b3a05STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { 1040eb7b3a05STakashi Sakamoto bebob->midi_input_ports++; 1041eb7b3a05STakashi Sakamoto } 1042eb7b3a05STakashi Sakamoto } 1043eb7b3a05STakashi Sakamoto 1044eb7b3a05STakashi Sakamoto /* count external output plugs for MIDI */ 1045eb7b3a05STakashi Sakamoto bebob->midi_output_ports = 0; 1046eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[3]; i++) { 1047eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, 1048eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, i); 1049eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 1050eb7b3a05STakashi Sakamoto if (err < 0) { 1051eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 1052eb7b3a05STakashi Sakamoto "fail to get type for external out plug %d: %d\n", 1053eb7b3a05STakashi Sakamoto i, err); 1054eb7b3a05STakashi Sakamoto goto end; 1055eb7b3a05STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { 1056eb7b3a05STakashi Sakamoto bebob->midi_output_ports++; 1057eb7b3a05STakashi Sakamoto } 1058eb7b3a05STakashi Sakamoto } 1059eb7b3a05STakashi Sakamoto 1060eb7b3a05STakashi Sakamoto /* for check source of clock later */ 10611fc9522aSTakashi Sakamoto if (!clk_spec) 1062eb7b3a05STakashi Sakamoto err = seek_msu_sync_input_plug(bebob); 1063eb7b3a05STakashi Sakamoto end: 1064eb7b3a05STakashi Sakamoto return err; 1065eb7b3a05STakashi Sakamoto } 1066618eabeaSTakashi Sakamoto 1067618eabeaSTakashi Sakamoto void snd_bebob_stream_lock_changed(struct snd_bebob *bebob) 1068618eabeaSTakashi Sakamoto { 1069618eabeaSTakashi Sakamoto bebob->dev_lock_changed = true; 1070618eabeaSTakashi Sakamoto wake_up(&bebob->hwdep_wait); 1071618eabeaSTakashi Sakamoto } 1072618eabeaSTakashi Sakamoto 1073618eabeaSTakashi Sakamoto int snd_bebob_stream_lock_try(struct snd_bebob *bebob) 1074618eabeaSTakashi Sakamoto { 1075618eabeaSTakashi Sakamoto int err; 1076618eabeaSTakashi Sakamoto 1077618eabeaSTakashi Sakamoto spin_lock_irq(&bebob->lock); 1078618eabeaSTakashi Sakamoto 1079618eabeaSTakashi Sakamoto /* user land lock this */ 1080618eabeaSTakashi Sakamoto if (bebob->dev_lock_count < 0) { 1081618eabeaSTakashi Sakamoto err = -EBUSY; 1082618eabeaSTakashi Sakamoto goto end; 1083618eabeaSTakashi Sakamoto } 1084618eabeaSTakashi Sakamoto 1085618eabeaSTakashi Sakamoto /* this is the first time */ 1086618eabeaSTakashi Sakamoto if (bebob->dev_lock_count++ == 0) 1087618eabeaSTakashi Sakamoto snd_bebob_stream_lock_changed(bebob); 1088618eabeaSTakashi Sakamoto err = 0; 1089618eabeaSTakashi Sakamoto end: 1090618eabeaSTakashi Sakamoto spin_unlock_irq(&bebob->lock); 1091618eabeaSTakashi Sakamoto return err; 1092618eabeaSTakashi Sakamoto } 1093618eabeaSTakashi Sakamoto 1094618eabeaSTakashi Sakamoto void snd_bebob_stream_lock_release(struct snd_bebob *bebob) 1095618eabeaSTakashi Sakamoto { 1096618eabeaSTakashi Sakamoto spin_lock_irq(&bebob->lock); 1097618eabeaSTakashi Sakamoto 1098618eabeaSTakashi Sakamoto if (WARN_ON(bebob->dev_lock_count <= 0)) 1099618eabeaSTakashi Sakamoto goto end; 1100618eabeaSTakashi Sakamoto if (--bebob->dev_lock_count == 0) 1101618eabeaSTakashi Sakamoto snd_bebob_stream_lock_changed(bebob); 1102618eabeaSTakashi Sakamoto end: 1103618eabeaSTakashi Sakamoto spin_unlock_irq(&bebob->lock); 1104618eabeaSTakashi Sakamoto } 1105