1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2eb7b3a05STakashi Sakamoto /* 3eb7b3a05STakashi Sakamoto * bebob_stream.c - a part of driver for BeBoB based devices 4eb7b3a05STakashi Sakamoto * 5eb7b3a05STakashi Sakamoto * Copyright (c) 2013-2014 Takashi Sakamoto 6eb7b3a05STakashi Sakamoto */ 7eb7b3a05STakashi Sakamoto 8eb7b3a05STakashi Sakamoto #include "./bebob.h" 9eb7b3a05STakashi Sakamoto 109a73195eSTakashi Sakamoto #define CALLBACK_TIMEOUT 2000 11b6bc8123STakashi Sakamoto #define FW_ISO_RESOURCE_DELAY 1000 12eb7b3a05STakashi Sakamoto 13eb7b3a05STakashi Sakamoto /* 14eb7b3a05STakashi Sakamoto * NOTE; 15eb7b3a05STakashi Sakamoto * For BeBoB streams, Both of input and output CMP connection are important. 16eb7b3a05STakashi Sakamoto * 17eb7b3a05STakashi Sakamoto * For most devices, each CMP connection starts to transmit/receive a 18eb7b3a05STakashi Sakamoto * corresponding stream. But for a few devices, both of CMP connection needs 19eb7b3a05STakashi Sakamoto * to start transmitting stream. An example is 'M-Audio Firewire 410'. 20eb7b3a05STakashi Sakamoto */ 21eb7b3a05STakashi Sakamoto 22eb7b3a05STakashi Sakamoto /* 128 is an arbitrary length but it seems to be enough */ 23eb7b3a05STakashi Sakamoto #define FORMAT_MAXIMUM_LENGTH 128 24eb7b3a05STakashi Sakamoto 25eb7b3a05STakashi Sakamoto const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES] = { 26eb7b3a05STakashi Sakamoto [0] = 32000, 27eb7b3a05STakashi Sakamoto [1] = 44100, 28eb7b3a05STakashi Sakamoto [2] = 48000, 29eb7b3a05STakashi Sakamoto [3] = 88200, 30eb7b3a05STakashi Sakamoto [4] = 96000, 31eb7b3a05STakashi Sakamoto [5] = 176400, 32eb7b3a05STakashi Sakamoto [6] = 192000, 33eb7b3a05STakashi Sakamoto }; 34eb7b3a05STakashi Sakamoto 35eb7b3a05STakashi Sakamoto /* 36eb7b3a05STakashi Sakamoto * See: Table 51: Extended Stream Format Info ‘Sampling Frequency’ 37eb7b3a05STakashi Sakamoto * in Additional AVC commands (Nov 2003, BridgeCo) 38eb7b3a05STakashi Sakamoto */ 39eb7b3a05STakashi Sakamoto static const unsigned int bridgeco_freq_table[] = { 40eb7b3a05STakashi Sakamoto [0] = 0x02, 41eb7b3a05STakashi Sakamoto [1] = 0x03, 42eb7b3a05STakashi Sakamoto [2] = 0x04, 43eb7b3a05STakashi Sakamoto [3] = 0x0a, 44eb7b3a05STakashi Sakamoto [4] = 0x05, 45eb7b3a05STakashi Sakamoto [5] = 0x06, 46eb7b3a05STakashi Sakamoto [6] = 0x07, 47eb7b3a05STakashi Sakamoto }; 48eb7b3a05STakashi Sakamoto 4907905298SLucas Tanure static int 5007905298SLucas Tanure get_formation_index(unsigned int rate, unsigned int *index) 51eb7b3a05STakashi Sakamoto { 52eb7b3a05STakashi Sakamoto unsigned int i; 53eb7b3a05STakashi Sakamoto 54eb7b3a05STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) { 5507905298SLucas Tanure if (snd_bebob_rate_table[i] == rate) { 5607905298SLucas Tanure *index = i; 5707905298SLucas Tanure return 0; 5807905298SLucas Tanure } 59eb7b3a05STakashi Sakamoto } 60eb7b3a05STakashi Sakamoto return -EINVAL; 61eb7b3a05STakashi Sakamoto } 62eb7b3a05STakashi Sakamoto 63eb7b3a05STakashi Sakamoto int 64eb7b3a05STakashi Sakamoto snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *curr_rate) 65eb7b3a05STakashi Sakamoto { 66eb7b3a05STakashi Sakamoto unsigned int tx_rate, rx_rate, trials; 67eb7b3a05STakashi Sakamoto int err; 68eb7b3a05STakashi Sakamoto 69eb7b3a05STakashi Sakamoto trials = 0; 70eb7b3a05STakashi Sakamoto do { 71eb7b3a05STakashi Sakamoto err = avc_general_get_sig_fmt(bebob->unit, &tx_rate, 72eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_OUT, 0); 73eb7b3a05STakashi Sakamoto } while (err == -EAGAIN && ++trials < 3); 74eb7b3a05STakashi Sakamoto if (err < 0) 75eb7b3a05STakashi Sakamoto goto end; 76eb7b3a05STakashi Sakamoto 77eb7b3a05STakashi Sakamoto trials = 0; 78eb7b3a05STakashi Sakamoto do { 79eb7b3a05STakashi Sakamoto err = avc_general_get_sig_fmt(bebob->unit, &rx_rate, 80eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 81eb7b3a05STakashi Sakamoto } while (err == -EAGAIN && ++trials < 3); 82eb7b3a05STakashi Sakamoto if (err < 0) 83eb7b3a05STakashi Sakamoto goto end; 84eb7b3a05STakashi Sakamoto 85eb7b3a05STakashi Sakamoto *curr_rate = rx_rate; 86eb7b3a05STakashi Sakamoto if (rx_rate == tx_rate) 87eb7b3a05STakashi Sakamoto goto end; 88eb7b3a05STakashi Sakamoto 89eb7b3a05STakashi Sakamoto /* synchronize receive stream rate to transmit stream rate */ 90eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rx_rate, 91eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 92eb7b3a05STakashi Sakamoto end: 93eb7b3a05STakashi Sakamoto return err; 94eb7b3a05STakashi Sakamoto } 95eb7b3a05STakashi Sakamoto 96eb7b3a05STakashi Sakamoto int 97eb7b3a05STakashi Sakamoto snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate) 98eb7b3a05STakashi Sakamoto { 99eb7b3a05STakashi Sakamoto int err; 100eb7b3a05STakashi Sakamoto 101eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rate, 102eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_OUT, 0); 103eb7b3a05STakashi Sakamoto if (err < 0) 104eb7b3a05STakashi Sakamoto goto end; 105eb7b3a05STakashi Sakamoto 106eb7b3a05STakashi Sakamoto err = avc_general_set_sig_fmt(bebob->unit, rate, 107eb7b3a05STakashi Sakamoto AVC_GENERAL_PLUG_DIR_IN, 0); 108eb7b3a05STakashi Sakamoto if (err < 0) 109eb7b3a05STakashi Sakamoto goto end; 110eb7b3a05STakashi Sakamoto 111eb7b3a05STakashi Sakamoto /* 112eb7b3a05STakashi Sakamoto * Some devices need a bit time for transition. 113eb7b3a05STakashi Sakamoto * 300msec is got by some experiments. 114eb7b3a05STakashi Sakamoto */ 115eb7b3a05STakashi Sakamoto msleep(300); 116eb7b3a05STakashi Sakamoto end: 117eb7b3a05STakashi Sakamoto return err; 118eb7b3a05STakashi Sakamoto } 119eb7b3a05STakashi Sakamoto 1203e254b16STakashi Sakamoto int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, 1213e254b16STakashi Sakamoto enum snd_bebob_clock_type *src) 122eb7b3a05STakashi Sakamoto { 1236b9866c8SJulia Lawall const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; 124eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; 1251fc9522aSTakashi Sakamoto unsigned int id; 1265a668812STakashi Sakamoto enum avc_bridgeco_plug_type type; 127eb7b3a05STakashi Sakamoto int err = 0; 128eb7b3a05STakashi Sakamoto 1291fc9522aSTakashi Sakamoto /* 1.The device has its own operation to switch source of clock */ 1301fc9522aSTakashi Sakamoto if (clk_spec) { 1311fc9522aSTakashi Sakamoto err = clk_spec->get(bebob, &id); 132d1d0b6b6SChristian Vogel if (err < 0) { 1331fc9522aSTakashi Sakamoto dev_err(&bebob->unit->device, 1341fc9522aSTakashi Sakamoto "fail to get clock source: %d\n", err); 135d1d0b6b6SChristian Vogel goto end; 136d1d0b6b6SChristian Vogel } 137d1d0b6b6SChristian Vogel 138d1d0b6b6SChristian Vogel if (id >= clk_spec->num) { 139d1d0b6b6SChristian Vogel dev_err(&bebob->unit->device, 140d1d0b6b6SChristian Vogel "clock source %d out of range 0..%d\n", 141d1d0b6b6SChristian Vogel id, clk_spec->num - 1); 142d1d0b6b6SChristian Vogel err = -EIO; 143d1d0b6b6SChristian Vogel goto end; 144d1d0b6b6SChristian Vogel } 145d1d0b6b6SChristian Vogel 1463e254b16STakashi Sakamoto *src = clk_spec->types[id]; 1471fc9522aSTakashi Sakamoto goto end; 1481fc9522aSTakashi Sakamoto } 1491fc9522aSTakashi Sakamoto 150eb7b3a05STakashi Sakamoto /* 1511fc9522aSTakashi Sakamoto * 2.The device don't support to switch source of clock then assumed 152eb7b3a05STakashi Sakamoto * to use internal clock always 153eb7b3a05STakashi Sakamoto */ 154eb7b3a05STakashi Sakamoto if (bebob->sync_input_plug < 0) { 1553e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 156eb7b3a05STakashi Sakamoto goto end; 157eb7b3a05STakashi Sakamoto } 158eb7b3a05STakashi Sakamoto 159eb7b3a05STakashi Sakamoto /* 1601fc9522aSTakashi Sakamoto * 3.The device supports to switch source of clock by an usual way. 161eb7b3a05STakashi Sakamoto * Let's check input for 'Music Sub Unit Sync Input' plug. 162eb7b3a05STakashi Sakamoto */ 163eb7b3a05STakashi Sakamoto avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 164eb7b3a05STakashi Sakamoto bebob->sync_input_plug); 165eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_input(bebob->unit, addr, input); 166eb7b3a05STakashi Sakamoto if (err < 0) { 167eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 168eb7b3a05STakashi Sakamoto "fail to get an input for MSU in plug %d: %d\n", 169eb7b3a05STakashi Sakamoto bebob->sync_input_plug, err); 170eb7b3a05STakashi Sakamoto goto end; 171eb7b3a05STakashi Sakamoto } 172eb7b3a05STakashi Sakamoto 173eb7b3a05STakashi Sakamoto /* 174eb7b3a05STakashi Sakamoto * If there are no input plugs, all of fields are 0xff. 175eb7b3a05STakashi Sakamoto * Here check the first field. This field is used for direction. 176eb7b3a05STakashi Sakamoto */ 177eb7b3a05STakashi Sakamoto if (input[0] == 0xff) { 1783e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 179eb7b3a05STakashi Sakamoto goto end; 180eb7b3a05STakashi Sakamoto } 181eb7b3a05STakashi Sakamoto 1825a668812STakashi Sakamoto /* The source from any output plugs is for one purpose only. */ 1835a668812STakashi Sakamoto if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) { 184eb7b3a05STakashi Sakamoto /* 1855a668812STakashi Sakamoto * In BeBoB architecture, the source from music subunit may 1865a668812STakashi Sakamoto * bypass from oPCR[0]. This means that this source gives 1875a668812STakashi Sakamoto * synchronization to IEEE 1394 cycle start packet. 188eb7b3a05STakashi Sakamoto */ 1895a668812STakashi Sakamoto if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && 1905a668812STakashi Sakamoto input[2] == 0x0c) { 1913e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 1925a668812STakashi Sakamoto goto end; 1935a668812STakashi Sakamoto } 1945a668812STakashi Sakamoto /* The source from any input units is for several purposes. */ 1955a668812STakashi Sakamoto } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) { 1965a668812STakashi Sakamoto if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) { 1975a668812STakashi Sakamoto if (input[3] == 0x00) { 1985a668812STakashi Sakamoto /* 1995a668812STakashi Sakamoto * This source comes from iPCR[0]. This means 2005a668812STakashi Sakamoto * that presentation timestamp calculated by 2015a668812STakashi Sakamoto * SYT series of the received packets. In 2025a668812STakashi Sakamoto * short, this driver is the master of 2035a668812STakashi Sakamoto * synchronization. 2045a668812STakashi Sakamoto */ 2053e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_SYT; 2065a668812STakashi Sakamoto goto end; 2075a668812STakashi Sakamoto } else { 2085a668812STakashi Sakamoto /* 2095a668812STakashi Sakamoto * This source comes from iPCR[1-29]. This 2105a668812STakashi Sakamoto * means that the synchronization stream is not 2115a668812STakashi Sakamoto * the Audio/MIDI compound stream. 2125a668812STakashi Sakamoto */ 2133e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2145a668812STakashi Sakamoto goto end; 2155a668812STakashi Sakamoto } 2165a668812STakashi Sakamoto } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { 2175a668812STakashi Sakamoto /* Check type of this plug. */ 2185a668812STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, 2195a668812STakashi Sakamoto AVC_BRIDGECO_PLUG_DIR_IN, 2205a668812STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, 2215a668812STakashi Sakamoto input[3]); 2225a668812STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, 2235a668812STakashi Sakamoto &type); 2245a668812STakashi Sakamoto if (err < 0) 2255a668812STakashi Sakamoto goto end; 2265a668812STakashi Sakamoto 2275a668812STakashi Sakamoto if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) { 2285a668812STakashi Sakamoto /* 2295a668812STakashi Sakamoto * SPDIF/ADAT or sometimes (not always) word 2305a668812STakashi Sakamoto * clock. 2315a668812STakashi Sakamoto */ 2323e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2335a668812STakashi Sakamoto goto end; 2345a668812STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { 2355a668812STakashi Sakamoto /* Often word clock. */ 2363e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; 2375a668812STakashi Sakamoto goto end; 2385a668812STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { 2395a668812STakashi Sakamoto /* 2405a668812STakashi Sakamoto * Not standard. 2415a668812STakashi Sakamoto * Mostly, additional internal clock. 2425a668812STakashi Sakamoto */ 2433e254b16STakashi Sakamoto *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; 2445a668812STakashi Sakamoto goto end; 2455a668812STakashi Sakamoto } 2465a668812STakashi Sakamoto } 2475a668812STakashi Sakamoto } 2485a668812STakashi Sakamoto 2495a668812STakashi Sakamoto /* Not supported. */ 2505a668812STakashi Sakamoto err = -EIO; 251eb7b3a05STakashi Sakamoto end: 252eb7b3a05STakashi Sakamoto return err; 253eb7b3a05STakashi Sakamoto } 254eb7b3a05STakashi Sakamoto 255f2bbdbcbSTakashi Sakamoto static int map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) 256eb7b3a05STakashi Sakamoto { 257eb7b3a05STakashi Sakamoto unsigned int sec, sections, ch, channels; 258eb7b3a05STakashi Sakamoto unsigned int pcm, midi, location; 259eb7b3a05STakashi Sakamoto unsigned int stm_pos, sec_loc, pos; 260eb7b3a05STakashi Sakamoto u8 *buf, addr[AVC_BRIDGECO_ADDR_BYTES], type; 261eb7b3a05STakashi Sakamoto enum avc_bridgeco_plug_dir dir; 262eb7b3a05STakashi Sakamoto int err; 263eb7b3a05STakashi Sakamoto 264eb7b3a05STakashi Sakamoto /* 265eb7b3a05STakashi Sakamoto * The length of return value of this command cannot be expected. Here 266eb7b3a05STakashi Sakamoto * use the maximum length of FCP. 267eb7b3a05STakashi Sakamoto */ 268eb7b3a05STakashi Sakamoto buf = kzalloc(256, GFP_KERNEL); 269eb7b3a05STakashi Sakamoto if (buf == NULL) 270eb7b3a05STakashi Sakamoto return -ENOMEM; 271eb7b3a05STakashi Sakamoto 272eb7b3a05STakashi Sakamoto if (s == &bebob->tx_stream) 273eb7b3a05STakashi Sakamoto dir = AVC_BRIDGECO_PLUG_DIR_OUT; 274eb7b3a05STakashi Sakamoto else 275eb7b3a05STakashi Sakamoto dir = AVC_BRIDGECO_PLUG_DIR_IN; 276eb7b3a05STakashi Sakamoto 277eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 278eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_ch_pos(bebob->unit, addr, buf, 256); 279eb7b3a05STakashi Sakamoto if (err < 0) { 280eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 281eb7b3a05STakashi Sakamoto "fail to get channel position for isoc %s plug 0: %d\n", 282eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : "out", 283eb7b3a05STakashi Sakamoto err); 284eb7b3a05STakashi Sakamoto goto end; 285eb7b3a05STakashi Sakamoto } 286eb7b3a05STakashi Sakamoto pos = 0; 287eb7b3a05STakashi Sakamoto 288eb7b3a05STakashi Sakamoto /* positions in I/O buffer */ 289eb7b3a05STakashi Sakamoto pcm = 0; 290eb7b3a05STakashi Sakamoto midi = 0; 291eb7b3a05STakashi Sakamoto 292eb7b3a05STakashi Sakamoto /* the number of sections in AMDTP packet */ 293eb7b3a05STakashi Sakamoto sections = buf[pos++]; 294eb7b3a05STakashi Sakamoto 295eb7b3a05STakashi Sakamoto for (sec = 0; sec < sections; sec++) { 296eb7b3a05STakashi Sakamoto /* type of this section */ 297eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, 298eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 299eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_section_type(bebob->unit, addr, 300eb7b3a05STakashi Sakamoto sec, &type); 301eb7b3a05STakashi Sakamoto if (err < 0) { 302eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 303eb7b3a05STakashi Sakamoto "fail to get section type for isoc %s plug 0: %d\n", 304eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : 305eb7b3a05STakashi Sakamoto "out", 306eb7b3a05STakashi Sakamoto err); 307eb7b3a05STakashi Sakamoto goto end; 308eb7b3a05STakashi Sakamoto } 309eb7b3a05STakashi Sakamoto /* NoType */ 310eb7b3a05STakashi Sakamoto if (type == 0xff) { 311eb7b3a05STakashi Sakamoto err = -ENOSYS; 312eb7b3a05STakashi Sakamoto goto end; 313eb7b3a05STakashi Sakamoto } 314eb7b3a05STakashi Sakamoto 315eb7b3a05STakashi Sakamoto /* the number of channels in this section */ 316eb7b3a05STakashi Sakamoto channels = buf[pos++]; 317eb7b3a05STakashi Sakamoto 318eb7b3a05STakashi Sakamoto for (ch = 0; ch < channels; ch++) { 319eb7b3a05STakashi Sakamoto /* position of this channel in AMDTP packet */ 320eb7b3a05STakashi Sakamoto stm_pos = buf[pos++] - 1; 321eb7b3a05STakashi Sakamoto /* location of this channel in this section */ 322eb7b3a05STakashi Sakamoto sec_loc = buf[pos++] - 1; 323eb7b3a05STakashi Sakamoto 3249076c22dSTakashi Sakamoto /* 3259076c22dSTakashi Sakamoto * Basically the number of location is within the 3269076c22dSTakashi Sakamoto * number of channels in this section. But some models 3279076c22dSTakashi Sakamoto * of M-Audio don't follow this. Its location for MIDI 3289076c22dSTakashi Sakamoto * is the position of MIDI channels in AMDTP packet. 3299076c22dSTakashi Sakamoto */ 3309076c22dSTakashi Sakamoto if (sec_loc >= channels) 3319076c22dSTakashi Sakamoto sec_loc = ch; 3329076c22dSTakashi Sakamoto 333eb7b3a05STakashi Sakamoto switch (type) { 334eb7b3a05STakashi Sakamoto /* for MIDI conformant data channel */ 335eb7b3a05STakashi Sakamoto case 0x0a: 336eb7b3a05STakashi Sakamoto /* AMDTP_MAX_CHANNELS_FOR_MIDI is 1. */ 337eb7b3a05STakashi Sakamoto if ((midi > 0) && (stm_pos != midi)) { 338eb7b3a05STakashi Sakamoto err = -ENOSYS; 339eb7b3a05STakashi Sakamoto goto end; 340eb7b3a05STakashi Sakamoto } 341f65be911STakashi Sakamoto amdtp_am824_set_midi_position(s, stm_pos); 342eb7b3a05STakashi Sakamoto midi = stm_pos; 343eb7b3a05STakashi Sakamoto break; 344eb7b3a05STakashi Sakamoto /* for PCM data channel */ 345eb7b3a05STakashi Sakamoto case 0x01: /* Headphone */ 346eb7b3a05STakashi Sakamoto case 0x02: /* Microphone */ 347eb7b3a05STakashi Sakamoto case 0x03: /* Line */ 348eb7b3a05STakashi Sakamoto case 0x04: /* SPDIF */ 349eb7b3a05STakashi Sakamoto case 0x05: /* ADAT */ 350eb7b3a05STakashi Sakamoto case 0x06: /* TDIF */ 351eb7b3a05STakashi Sakamoto case 0x07: /* MADI */ 352eb7b3a05STakashi Sakamoto /* for undefined/changeable signal */ 353eb7b3a05STakashi Sakamoto case 0x08: /* Analog */ 354eb7b3a05STakashi Sakamoto case 0x09: /* Digital */ 355eb7b3a05STakashi Sakamoto default: 356eb7b3a05STakashi Sakamoto location = pcm + sec_loc; 35749c7b3fcSTakashi Sakamoto if (location >= AM824_MAX_CHANNELS_FOR_PCM) { 358eb7b3a05STakashi Sakamoto err = -ENOSYS; 359eb7b3a05STakashi Sakamoto goto end; 360eb7b3a05STakashi Sakamoto } 361f65be911STakashi Sakamoto amdtp_am824_set_pcm_position(s, location, 362f65be911STakashi Sakamoto stm_pos); 363eb7b3a05STakashi Sakamoto break; 364eb7b3a05STakashi Sakamoto } 365eb7b3a05STakashi Sakamoto } 366eb7b3a05STakashi Sakamoto 367eb7b3a05STakashi Sakamoto if (type != 0x0a) 368eb7b3a05STakashi Sakamoto pcm += channels; 369eb7b3a05STakashi Sakamoto else 370eb7b3a05STakashi Sakamoto midi += channels; 371eb7b3a05STakashi Sakamoto } 372eb7b3a05STakashi Sakamoto end: 373eb7b3a05STakashi Sakamoto kfree(buf); 374eb7b3a05STakashi Sakamoto return err; 375eb7b3a05STakashi Sakamoto } 376eb7b3a05STakashi Sakamoto 377eb7b3a05STakashi Sakamoto static int 378eb7b3a05STakashi Sakamoto check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s) 379eb7b3a05STakashi Sakamoto { 380eb7b3a05STakashi Sakamoto struct cmp_connection *conn; 381eb7b3a05STakashi Sakamoto bool used; 382eb7b3a05STakashi Sakamoto int err; 383eb7b3a05STakashi Sakamoto 384eb7b3a05STakashi Sakamoto if (s == &bebob->tx_stream) 385eb7b3a05STakashi Sakamoto conn = &bebob->out_conn; 386eb7b3a05STakashi Sakamoto else 387eb7b3a05STakashi Sakamoto conn = &bebob->in_conn; 388eb7b3a05STakashi Sakamoto 389eb7b3a05STakashi Sakamoto err = cmp_connection_check_used(conn, &used); 390eb7b3a05STakashi Sakamoto if ((err >= 0) && used && !amdtp_stream_running(s)) { 391eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 392eb7b3a05STakashi Sakamoto "Connection established by others: %cPCR[%d]\n", 393eb7b3a05STakashi Sakamoto (conn->direction == CMP_OUTPUT) ? 'o' : 'i', 394eb7b3a05STakashi Sakamoto conn->pcr_index); 395eb7b3a05STakashi Sakamoto err = -EBUSY; 396eb7b3a05STakashi Sakamoto } 397eb7b3a05STakashi Sakamoto 398eb7b3a05STakashi Sakamoto return err; 399eb7b3a05STakashi Sakamoto } 400eb7b3a05STakashi Sakamoto 401ac2888b9STakashi Sakamoto static int make_both_connections(struct snd_bebob *bebob) 402eb7b3a05STakashi Sakamoto { 403ac2888b9STakashi Sakamoto int err = 0; 404b6bc8123STakashi Sakamoto 4057bc93821STakashi Sakamoto err = cmp_connection_establish(&bebob->out_conn); 406eb7b3a05STakashi Sakamoto if (err < 0) 407ac2888b9STakashi Sakamoto return err; 408ac2888b9STakashi Sakamoto 4097bc93821STakashi Sakamoto err = cmp_connection_establish(&bebob->in_conn); 410b6bc8123STakashi Sakamoto if (err < 0) { 411eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->out_conn); 412ac2888b9STakashi Sakamoto return err; 413b6bc8123STakashi Sakamoto } 414b6bc8123STakashi Sakamoto 415ac2888b9STakashi Sakamoto return 0; 416eb7b3a05STakashi Sakamoto } 417eb7b3a05STakashi Sakamoto 418d3eabe93STakashi Sakamoto static void break_both_connections(struct snd_bebob *bebob) 419eb7b3a05STakashi Sakamoto { 420eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->in_conn); 421eb7b3a05STakashi Sakamoto cmp_connection_break(&bebob->out_conn); 422b6bc8123STakashi Sakamoto 423d3eabe93STakashi Sakamoto // These models seem to be in transition state for a longer time. When 424d3eabe93STakashi Sakamoto // accessing in the state, any transactions is corrupted. In the worst 425d3eabe93STakashi Sakamoto // case, the device is going to reboot. 426d3eabe93STakashi Sakamoto if (bebob->version < 2) 427d3eabe93STakashi Sakamoto msleep(600); 428eb7b3a05STakashi Sakamoto } 429eb7b3a05STakashi Sakamoto 430eb7b3a05STakashi Sakamoto static int 431ac2888b9STakashi Sakamoto start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) 432eb7b3a05STakashi Sakamoto { 433eb7b3a05STakashi Sakamoto struct cmp_connection *conn; 434eb7b3a05STakashi Sakamoto int err = 0; 435eb7b3a05STakashi Sakamoto 436eb7b3a05STakashi Sakamoto if (stream == &bebob->rx_stream) 437eb7b3a05STakashi Sakamoto conn = &bebob->in_conn; 438eb7b3a05STakashi Sakamoto else 439eb7b3a05STakashi Sakamoto conn = &bebob->out_conn; 440eb7b3a05STakashi Sakamoto 441eb7b3a05STakashi Sakamoto /* channel mapping */ 4423149ac48STakashi Sakamoto if (bebob->maudio_special_quirk == NULL) { 443eb7b3a05STakashi Sakamoto err = map_data_channels(bebob, stream); 444eb7b3a05STakashi Sakamoto if (err < 0) 445eb7b3a05STakashi Sakamoto goto end; 4463149ac48STakashi Sakamoto } 447eb7b3a05STakashi Sakamoto 448b0db4d51STakashi Sakamoto // start amdtp stream. 449b0db4d51STakashi Sakamoto err = amdtp_domain_add_stream(&bebob->domain, stream, 450b0db4d51STakashi Sakamoto conn->resources.channel, conn->speed); 451eb7b3a05STakashi Sakamoto end: 452eb7b3a05STakashi Sakamoto return err; 453eb7b3a05STakashi Sakamoto } 454eb7b3a05STakashi Sakamoto 45533e41a5cSTakashi Sakamoto static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) 456eb7b3a05STakashi Sakamoto { 45733e41a5cSTakashi Sakamoto enum amdtp_stream_direction dir_stream; 45833e41a5cSTakashi Sakamoto struct cmp_connection *conn; 45933e41a5cSTakashi Sakamoto enum cmp_direction dir_conn; 460eb7b3a05STakashi Sakamoto int err; 461eb7b3a05STakashi Sakamoto 46233e41a5cSTakashi Sakamoto if (stream == &bebob->tx_stream) { 46333e41a5cSTakashi Sakamoto dir_stream = AMDTP_IN_STREAM; 46433e41a5cSTakashi Sakamoto conn = &bebob->out_conn; 46533e41a5cSTakashi Sakamoto dir_conn = CMP_OUTPUT; 46633e41a5cSTakashi Sakamoto } else { 46733e41a5cSTakashi Sakamoto dir_stream = AMDTP_OUT_STREAM; 46833e41a5cSTakashi Sakamoto conn = &bebob->in_conn; 46933e41a5cSTakashi Sakamoto dir_conn = CMP_INPUT; 470eb7b3a05STakashi Sakamoto } 47114a37ac1STakashi Sakamoto 47233e41a5cSTakashi Sakamoto err = cmp_connection_init(conn, bebob->unit, dir_conn, 0); 47333e41a5cSTakashi Sakamoto if (err < 0) 47433e41a5cSTakashi Sakamoto return err; 47533e41a5cSTakashi Sakamoto 47633e41a5cSTakashi Sakamoto err = amdtp_am824_init(stream, bebob->unit, dir_stream, CIP_BLOCKING); 47733e41a5cSTakashi Sakamoto if (err < 0) { 47833e41a5cSTakashi Sakamoto cmp_connection_destroy(conn); 47933e41a5cSTakashi Sakamoto return err; 48033e41a5cSTakashi Sakamoto } 48133e41a5cSTakashi Sakamoto 48233e41a5cSTakashi Sakamoto if (stream == &bebob->tx_stream) { 48333e41a5cSTakashi Sakamoto // BeBoB v3 transfers packets with these qurks: 48433e41a5cSTakashi Sakamoto // - In the beginning of streaming, the value of dbc is 48533e41a5cSTakashi Sakamoto // incremented even if no data blocks are transferred. 48633e41a5cSTakashi Sakamoto // - The value of dbc is reset suddenly. 487c4d860a0STakashi Sakamoto if (bebob->version > 2) 488c4d860a0STakashi Sakamoto bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | 489c4d860a0STakashi Sakamoto CIP_SKIP_DBC_ZERO_CHECK; 490c4d860a0STakashi Sakamoto 49133e41a5cSTakashi Sakamoto // At high sampling rate, M-Audio special firmware transmits 49233e41a5cSTakashi Sakamoto // empty packet with the value of dbc incremented by 8 but the 49333e41a5cSTakashi Sakamoto // others are valid to IEC 61883-1. 4949d59124cSTakashi Sakamoto if (bebob->maudio_special_quirk) 4959d59124cSTakashi Sakamoto bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; 496eb7b3a05STakashi Sakamoto } 49733e41a5cSTakashi Sakamoto 49833e41a5cSTakashi Sakamoto return 0; 49933e41a5cSTakashi Sakamoto } 50033e41a5cSTakashi Sakamoto 50133e41a5cSTakashi Sakamoto static void destroy_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) 50233e41a5cSTakashi Sakamoto { 50333e41a5cSTakashi Sakamoto amdtp_stream_destroy(stream); 50433e41a5cSTakashi Sakamoto 50533e41a5cSTakashi Sakamoto if (stream == &bebob->tx_stream) 50633e41a5cSTakashi Sakamoto cmp_connection_destroy(&bebob->out_conn); 50733e41a5cSTakashi Sakamoto else 50833e41a5cSTakashi Sakamoto cmp_connection_destroy(&bebob->in_conn); 50933e41a5cSTakashi Sakamoto } 51033e41a5cSTakashi Sakamoto 51133e41a5cSTakashi Sakamoto int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) 51233e41a5cSTakashi Sakamoto { 51333e41a5cSTakashi Sakamoto int err; 51433e41a5cSTakashi Sakamoto 51533e41a5cSTakashi Sakamoto err = init_stream(bebob, &bebob->tx_stream); 51633e41a5cSTakashi Sakamoto if (err < 0) 517eb7b3a05STakashi Sakamoto return err; 51833e41a5cSTakashi Sakamoto 51933e41a5cSTakashi Sakamoto err = init_stream(bebob, &bebob->rx_stream); 52033e41a5cSTakashi Sakamoto if (err < 0) { 52133e41a5cSTakashi Sakamoto destroy_stream(bebob, &bebob->tx_stream); 52233e41a5cSTakashi Sakamoto return err; 52333e41a5cSTakashi Sakamoto } 52433e41a5cSTakashi Sakamoto 525b0db4d51STakashi Sakamoto err = amdtp_domain_init(&bebob->domain); 526b0db4d51STakashi Sakamoto if (err < 0) { 527b0db4d51STakashi Sakamoto destroy_stream(bebob, &bebob->tx_stream); 528b0db4d51STakashi Sakamoto destroy_stream(bebob, &bebob->rx_stream); 529b0db4d51STakashi Sakamoto } 530b0db4d51STakashi Sakamoto 531b0db4d51STakashi Sakamoto return err; 532eb7b3a05STakashi Sakamoto } 533eb7b3a05STakashi Sakamoto 534ac2888b9STakashi Sakamoto static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, 535ac2888b9STakashi Sakamoto unsigned int rate, unsigned int index) 536eb7b3a05STakashi Sakamoto { 537ac2888b9STakashi Sakamoto struct snd_bebob_stream_formation *formation; 5387bc93821STakashi Sakamoto struct cmp_connection *conn; 5397bc93821STakashi Sakamoto int err; 540ac2888b9STakashi Sakamoto 5417bc93821STakashi Sakamoto if (stream == &bebob->tx_stream) { 542ac2888b9STakashi Sakamoto formation = bebob->tx_stream_formations + index; 5437bc93821STakashi Sakamoto conn = &bebob->out_conn; 5447bc93821STakashi Sakamoto } else { 545ac2888b9STakashi Sakamoto formation = bebob->rx_stream_formations + index; 5467bc93821STakashi Sakamoto conn = &bebob->in_conn; 5477bc93821STakashi Sakamoto } 548ac2888b9STakashi Sakamoto 5497bc93821STakashi Sakamoto err = amdtp_am824_set_parameters(stream, rate, formation->pcm, 550ac2888b9STakashi Sakamoto formation->midi, false); 5517bc93821STakashi Sakamoto if (err < 0) 5527bc93821STakashi Sakamoto return err; 5537bc93821STakashi Sakamoto 5547bc93821STakashi Sakamoto return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); 555ac2888b9STakashi Sakamoto } 556ac2888b9STakashi Sakamoto 5578737209fSTakashi Sakamoto int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate, 5581fde7a44STakashi Sakamoto unsigned int frames_per_period, 5591fde7a44STakashi Sakamoto unsigned int frames_per_buffer) 560ac2888b9STakashi Sakamoto { 561eb7b3a05STakashi Sakamoto unsigned int curr_rate; 562ac2888b9STakashi Sakamoto int err; 563eb7b3a05STakashi Sakamoto 564ac2888b9STakashi Sakamoto // Considering JACK/FFADO streaming: 565ac2888b9STakashi Sakamoto // TODO: This can be removed hwdep functionality becomes popular. 566c71283cbSTakashi Sakamoto err = check_connection_used_by_others(bebob, &bebob->rx_stream); 567eb7b3a05STakashi Sakamoto if (err < 0) 568ac2888b9STakashi Sakamoto return err; 569eb7b3a05STakashi Sakamoto 570ac2888b9STakashi Sakamoto err = bebob->spec->rate->get(bebob, &curr_rate); 571ac2888b9STakashi Sakamoto if (err < 0) 572ac2888b9STakashi Sakamoto return err; 573eb7b3a05STakashi Sakamoto if (rate == 0) 574eb7b3a05STakashi Sakamoto rate = curr_rate; 575ac2888b9STakashi Sakamoto if (curr_rate != rate) { 576b0db4d51STakashi Sakamoto amdtp_domain_stop(&bebob->domain); 577eb7b3a05STakashi Sakamoto break_both_connections(bebob); 5787599e279STakashi Sakamoto 5797599e279STakashi Sakamoto cmp_connection_release(&bebob->out_conn); 5807599e279STakashi Sakamoto cmp_connection_release(&bebob->in_conn); 581eb7b3a05STakashi Sakamoto } 582eb7b3a05STakashi Sakamoto 583ac2888b9STakashi Sakamoto if (bebob->substreams_counter == 0 || curr_rate != rate) { 584ac2888b9STakashi Sakamoto unsigned int index; 585ac2888b9STakashi Sakamoto 586ac2888b9STakashi Sakamoto // NOTE: 587ac2888b9STakashi Sakamoto // If establishing connections at first, Yamaha GO46 588ac2888b9STakashi Sakamoto // (and maybe Terratec X24) don't generate sound. 589ac2888b9STakashi Sakamoto // 590ac2888b9STakashi Sakamoto // For firmware customized by M-Audio, refer to next NOTE. 591ac2888b9STakashi Sakamoto err = bebob->spec->rate->set(bebob, rate); 592eb7b3a05STakashi Sakamoto if (err < 0) { 593eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 594eb7b3a05STakashi Sakamoto "fail to set sampling rate: %d\n", 595eb7b3a05STakashi Sakamoto err); 596ac2888b9STakashi Sakamoto return err; 5973149ac48STakashi Sakamoto } 598eb7b3a05STakashi Sakamoto 599ac2888b9STakashi Sakamoto err = get_formation_index(rate, &index); 600eb7b3a05STakashi Sakamoto if (err < 0) 601ac2888b9STakashi Sakamoto return err; 602eb7b3a05STakashi Sakamoto 603ac2888b9STakashi Sakamoto err = keep_resources(bebob, &bebob->tx_stream, rate, index); 604ac2888b9STakashi Sakamoto if (err < 0) 605ac2888b9STakashi Sakamoto return err; 606ac2888b9STakashi Sakamoto 607ac2888b9STakashi Sakamoto err = keep_resources(bebob, &bebob->rx_stream, rate, index); 6087bc93821STakashi Sakamoto if (err < 0) { 6097bc93821STakashi Sakamoto cmp_connection_release(&bebob->out_conn); 610ac2888b9STakashi Sakamoto return err; 611ac2888b9STakashi Sakamoto } 6128737209fSTakashi Sakamoto 6138737209fSTakashi Sakamoto err = amdtp_domain_set_events_per_period(&bebob->domain, 6141fde7a44STakashi Sakamoto frames_per_period, frames_per_buffer); 6158737209fSTakashi Sakamoto if (err < 0) { 6168737209fSTakashi Sakamoto cmp_connection_release(&bebob->out_conn); 6178737209fSTakashi Sakamoto cmp_connection_release(&bebob->in_conn); 6188737209fSTakashi Sakamoto return err; 6198737209fSTakashi Sakamoto } 6207bc93821STakashi Sakamoto } 621ac2888b9STakashi Sakamoto 622ac2888b9STakashi Sakamoto return 0; 623ac2888b9STakashi Sakamoto } 624ac2888b9STakashi Sakamoto 625ac2888b9STakashi Sakamoto int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) 626ac2888b9STakashi Sakamoto { 627ac2888b9STakashi Sakamoto int err; 628ac2888b9STakashi Sakamoto 629ac2888b9STakashi Sakamoto // Need no substreams. 630ac2888b9STakashi Sakamoto if (bebob->substreams_counter == 0) 631ac2888b9STakashi Sakamoto return -EIO; 632ac2888b9STakashi Sakamoto 633ac2888b9STakashi Sakamoto // packet queueing error or detecting discontinuity 634ac2888b9STakashi Sakamoto if (amdtp_streaming_error(&bebob->rx_stream) || 635ac2888b9STakashi Sakamoto amdtp_streaming_error(&bebob->tx_stream)) { 636b0db4d51STakashi Sakamoto amdtp_domain_stop(&bebob->domain); 637ac2888b9STakashi Sakamoto break_both_connections(bebob); 638ac2888b9STakashi Sakamoto } 639ac2888b9STakashi Sakamoto 640ac2888b9STakashi Sakamoto if (!amdtp_stream_running(&bebob->rx_stream)) { 641ac2888b9STakashi Sakamoto unsigned int curr_rate; 642ac2888b9STakashi Sakamoto 643ac2888b9STakashi Sakamoto if (bebob->maudio_special_quirk) { 644ac2888b9STakashi Sakamoto err = bebob->spec->rate->get(bebob, &curr_rate); 645ac2888b9STakashi Sakamoto if (err < 0) 646ac2888b9STakashi Sakamoto return err; 647ac2888b9STakashi Sakamoto } 648ac2888b9STakashi Sakamoto 649ac2888b9STakashi Sakamoto err = make_both_connections(bebob); 650ac2888b9STakashi Sakamoto if (err < 0) 651ac2888b9STakashi Sakamoto return err; 652ac2888b9STakashi Sakamoto 653ac2888b9STakashi Sakamoto err = start_stream(bebob, &bebob->rx_stream); 654b0db4d51STakashi Sakamoto if (err < 0) 655ac2888b9STakashi Sakamoto goto error; 656b0db4d51STakashi Sakamoto 657b0db4d51STakashi Sakamoto err = start_stream(bebob, &bebob->tx_stream); 658b0db4d51STakashi Sakamoto if (err < 0) 659b0db4d51STakashi Sakamoto goto error; 660b0db4d51STakashi Sakamoto 661acfedcbeSTakashi Sakamoto // The device postpones start of transmission mostly for 1 sec 662acfedcbeSTakashi Sakamoto // after receives packets firstly. For safe, IR context starts 663acfedcbeSTakashi Sakamoto // 1.5 sec (=12000 cycles) later. This is within 2.0 sec 664acfedcbeSTakashi Sakamoto // (=CALLBACK_TIMEOUT). 665acfedcbeSTakashi Sakamoto // Furthermore, some devices transfer isoc packets with 666acfedcbeSTakashi Sakamoto // discontinuous counter in the beginning of packet streaming. 667acfedcbeSTakashi Sakamoto // The delay has an effect to avoid detection of this 668acfedcbeSTakashi Sakamoto // discontinuity. 669acfedcbeSTakashi Sakamoto err = amdtp_domain_start(&bebob->domain, 12000); 670b0db4d51STakashi Sakamoto if (err < 0) 671b0db4d51STakashi Sakamoto goto error; 672eb7b3a05STakashi Sakamoto 673ac2888b9STakashi Sakamoto // NOTE: 674ac2888b9STakashi Sakamoto // The firmware customized by M-Audio uses these commands to 675ac2888b9STakashi Sakamoto // start transmitting stream. This is not usual way. 676ac2888b9STakashi Sakamoto if (bebob->maudio_special_quirk) { 677ac2888b9STakashi Sakamoto err = bebob->spec->rate->set(bebob, curr_rate); 6783149ac48STakashi Sakamoto if (err < 0) { 6793149ac48STakashi Sakamoto dev_err(&bebob->unit->device, 6803149ac48STakashi Sakamoto "fail to ensure sampling rate: %d\n", 6813149ac48STakashi Sakamoto err); 682ac2888b9STakashi Sakamoto goto error; 6833149ac48STakashi Sakamoto } 6843149ac48STakashi Sakamoto } 6853149ac48STakashi Sakamoto 686c71283cbSTakashi Sakamoto if (!amdtp_stream_wait_callback(&bebob->rx_stream, 687b0db4d51STakashi Sakamoto CALLBACK_TIMEOUT) || 688b0db4d51STakashi Sakamoto !amdtp_stream_wait_callback(&bebob->tx_stream, 689c71283cbSTakashi Sakamoto CALLBACK_TIMEOUT)) { 690ac2888b9STakashi Sakamoto err = -ETIMEDOUT; 691ac2888b9STakashi Sakamoto goto error; 692ac2888b9STakashi Sakamoto } 693ac2888b9STakashi Sakamoto } 694ac2888b9STakashi Sakamoto 695ac2888b9STakashi Sakamoto return 0; 696ac2888b9STakashi Sakamoto error: 697b0db4d51STakashi Sakamoto amdtp_domain_stop(&bebob->domain); 698eb7b3a05STakashi Sakamoto break_both_connections(bebob); 699eb7b3a05STakashi Sakamoto return err; 700eb7b3a05STakashi Sakamoto } 701eb7b3a05STakashi Sakamoto 702eb7b3a05STakashi Sakamoto void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) 703eb7b3a05STakashi Sakamoto { 7044fd6c6c7STakashi Sakamoto if (bebob->substreams_counter == 0) { 705b0db4d51STakashi Sakamoto amdtp_domain_stop(&bebob->domain); 706eb7b3a05STakashi Sakamoto break_both_connections(bebob); 7077bc93821STakashi Sakamoto 7087bc93821STakashi Sakamoto cmp_connection_release(&bebob->out_conn); 7097bc93821STakashi Sakamoto cmp_connection_release(&bebob->in_conn); 710eb7b3a05STakashi Sakamoto } 711eb7b3a05STakashi Sakamoto } 712eb7b3a05STakashi Sakamoto 713d23c2cc4STakashi Sakamoto /* 714d23c2cc4STakashi Sakamoto * This function should be called before starting streams or after stopping 715d23c2cc4STakashi Sakamoto * streams. 716d23c2cc4STakashi Sakamoto */ 717eb7b3a05STakashi Sakamoto void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) 718eb7b3a05STakashi Sakamoto { 719b0db4d51STakashi Sakamoto amdtp_domain_destroy(&bebob->domain); 720b0db4d51STakashi Sakamoto 72133e41a5cSTakashi Sakamoto destroy_stream(bebob, &bebob->tx_stream); 72233e41a5cSTakashi Sakamoto destroy_stream(bebob, &bebob->rx_stream); 723eb7b3a05STakashi Sakamoto } 724eb7b3a05STakashi Sakamoto 725eb7b3a05STakashi Sakamoto /* 726eb7b3a05STakashi Sakamoto * See: Table 50: Extended Stream Format Info Format Hierarchy Level 2’ 727eb7b3a05STakashi Sakamoto * in Additional AVC commands (Nov 2003, BridgeCo) 728eb7b3a05STakashi Sakamoto * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005 729eb7b3a05STakashi Sakamoto */ 730eb7b3a05STakashi Sakamoto static int 731eb7b3a05STakashi Sakamoto parse_stream_formation(u8 *buf, unsigned int len, 732eb7b3a05STakashi Sakamoto struct snd_bebob_stream_formation *formation) 733eb7b3a05STakashi Sakamoto { 734eb7b3a05STakashi Sakamoto unsigned int i, e, channels, format; 735eb7b3a05STakashi Sakamoto 736eb7b3a05STakashi Sakamoto /* 737eb7b3a05STakashi Sakamoto * this module can support a hierarchy combination that: 738eb7b3a05STakashi Sakamoto * Root: Audio and Music (0x90) 739eb7b3a05STakashi Sakamoto * Level 1: AM824 Compound (0x40) 740eb7b3a05STakashi Sakamoto */ 741eb7b3a05STakashi Sakamoto if ((buf[0] != 0x90) || (buf[1] != 0x40)) 742eb7b3a05STakashi Sakamoto return -ENOSYS; 743eb7b3a05STakashi Sakamoto 744eb7b3a05STakashi Sakamoto /* check sampling rate */ 745eb7b3a05STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(bridgeco_freq_table); i++) { 746eb7b3a05STakashi Sakamoto if (buf[2] == bridgeco_freq_table[i]) 747eb7b3a05STakashi Sakamoto break; 748eb7b3a05STakashi Sakamoto } 74933a5f989SDan Carpenter if (i == ARRAY_SIZE(bridgeco_freq_table)) 750eb7b3a05STakashi Sakamoto return -ENOSYS; 751eb7b3a05STakashi Sakamoto 752eb7b3a05STakashi Sakamoto /* Avoid double count by different entries for the same rate. */ 753eb7b3a05STakashi Sakamoto memset(&formation[i], 0, sizeof(struct snd_bebob_stream_formation)); 754eb7b3a05STakashi Sakamoto 755eb7b3a05STakashi Sakamoto for (e = 0; e < buf[4]; e++) { 756eb7b3a05STakashi Sakamoto channels = buf[5 + e * 2]; 757eb7b3a05STakashi Sakamoto format = buf[6 + e * 2]; 758eb7b3a05STakashi Sakamoto 759eb7b3a05STakashi Sakamoto switch (format) { 76051fa31d4STakashi Sakamoto /* IEC 60958 Conformant, currently handled as MBLA */ 761eb7b3a05STakashi Sakamoto case 0x00: 762eb7b3a05STakashi Sakamoto /* Multi bit linear audio */ 763eb7b3a05STakashi Sakamoto case 0x06: /* Raw */ 764eb7b3a05STakashi Sakamoto formation[i].pcm += channels; 765eb7b3a05STakashi Sakamoto break; 766eb7b3a05STakashi Sakamoto /* MIDI Conformant */ 767eb7b3a05STakashi Sakamoto case 0x0d: 768eb7b3a05STakashi Sakamoto formation[i].midi += channels; 769eb7b3a05STakashi Sakamoto break; 770eb7b3a05STakashi Sakamoto /* IEC 61937-3 to 7 */ 771eb7b3a05STakashi Sakamoto case 0x01: 772eb7b3a05STakashi Sakamoto case 0x02: 773eb7b3a05STakashi Sakamoto case 0x03: 774eb7b3a05STakashi Sakamoto case 0x04: 775eb7b3a05STakashi Sakamoto case 0x05: 776eb7b3a05STakashi Sakamoto /* Multi bit linear audio */ 777eb7b3a05STakashi Sakamoto case 0x07: /* DVD-Audio */ 778eb7b3a05STakashi Sakamoto case 0x0c: /* High Precision */ 779eb7b3a05STakashi Sakamoto /* One Bit Audio */ 780eb7b3a05STakashi Sakamoto case 0x08: /* (Plain) Raw */ 781eb7b3a05STakashi Sakamoto case 0x09: /* (Plain) SACD */ 782eb7b3a05STakashi Sakamoto case 0x0a: /* (Encoded) Raw */ 783eb7b3a05STakashi Sakamoto case 0x0b: /* (Encoded) SACD */ 784eb7b3a05STakashi Sakamoto /* Synchronization Stream (Stereo Raw audio) */ 785eb7b3a05STakashi Sakamoto case 0x40: 786eb7b3a05STakashi Sakamoto /* Don't care */ 787eb7b3a05STakashi Sakamoto case 0xff: 788eb7b3a05STakashi Sakamoto default: 789eb7b3a05STakashi Sakamoto return -ENOSYS; /* not supported */ 790eb7b3a05STakashi Sakamoto } 791eb7b3a05STakashi Sakamoto } 792eb7b3a05STakashi Sakamoto 79349c7b3fcSTakashi Sakamoto if (formation[i].pcm > AM824_MAX_CHANNELS_FOR_PCM || 79449c7b3fcSTakashi Sakamoto formation[i].midi > AM824_MAX_CHANNELS_FOR_MIDI) 795eb7b3a05STakashi Sakamoto return -ENOSYS; 796eb7b3a05STakashi Sakamoto 797eb7b3a05STakashi Sakamoto return 0; 798eb7b3a05STakashi Sakamoto } 799eb7b3a05STakashi Sakamoto 800eb7b3a05STakashi Sakamoto static int 801eb7b3a05STakashi Sakamoto fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir, 802eb7b3a05STakashi Sakamoto unsigned short pid) 803eb7b3a05STakashi Sakamoto { 804eb7b3a05STakashi Sakamoto u8 *buf; 805eb7b3a05STakashi Sakamoto struct snd_bebob_stream_formation *formations; 806eb7b3a05STakashi Sakamoto unsigned int len, eid; 807eb7b3a05STakashi Sakamoto u8 addr[AVC_BRIDGECO_ADDR_BYTES]; 808eb7b3a05STakashi Sakamoto int err; 809eb7b3a05STakashi Sakamoto 810eb7b3a05STakashi Sakamoto buf = kmalloc(FORMAT_MAXIMUM_LENGTH, GFP_KERNEL); 811eb7b3a05STakashi Sakamoto if (buf == NULL) 812eb7b3a05STakashi Sakamoto return -ENOMEM; 813eb7b3a05STakashi Sakamoto 814eb7b3a05STakashi Sakamoto if (dir == AVC_BRIDGECO_PLUG_DIR_IN) 815eb7b3a05STakashi Sakamoto formations = bebob->rx_stream_formations; 816eb7b3a05STakashi Sakamoto else 817eb7b3a05STakashi Sakamoto formations = bebob->tx_stream_formations; 818eb7b3a05STakashi Sakamoto 819eb7b3a05STakashi Sakamoto for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; eid++) { 820eb7b3a05STakashi Sakamoto len = FORMAT_MAXIMUM_LENGTH; 821eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, dir, 822eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, pid); 823eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf, 824eb7b3a05STakashi Sakamoto &len, eid); 825eb7b3a05STakashi Sakamoto /* No entries remained. */ 826eb7b3a05STakashi Sakamoto if (err == -EINVAL && eid > 0) { 827eb7b3a05STakashi Sakamoto err = 0; 828eb7b3a05STakashi Sakamoto break; 829eb7b3a05STakashi Sakamoto } else if (err < 0) { 830eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 831eb7b3a05STakashi Sakamoto "fail to get stream format %d for isoc %s plug %d:%d\n", 832eb7b3a05STakashi Sakamoto eid, 833eb7b3a05STakashi Sakamoto (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : 834eb7b3a05STakashi Sakamoto "out", 835eb7b3a05STakashi Sakamoto pid, err); 836eb7b3a05STakashi Sakamoto break; 837eb7b3a05STakashi Sakamoto } 838eb7b3a05STakashi Sakamoto 839eb7b3a05STakashi Sakamoto err = parse_stream_formation(buf, len, formations); 840eb7b3a05STakashi Sakamoto if (err < 0) 841eb7b3a05STakashi Sakamoto break; 842eb7b3a05STakashi Sakamoto } 843eb7b3a05STakashi Sakamoto 844eb7b3a05STakashi Sakamoto kfree(buf); 845eb7b3a05STakashi Sakamoto return err; 846eb7b3a05STakashi Sakamoto } 847eb7b3a05STakashi Sakamoto 848eb7b3a05STakashi Sakamoto static int 849eb7b3a05STakashi Sakamoto seek_msu_sync_input_plug(struct snd_bebob *bebob) 850eb7b3a05STakashi Sakamoto { 851eb7b3a05STakashi Sakamoto u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; 852a6b598bfSTakashi Sakamoto unsigned int i; 853a6b598bfSTakashi Sakamoto enum avc_bridgeco_plug_type type; 854eb7b3a05STakashi Sakamoto int err; 855eb7b3a05STakashi Sakamoto 856eb7b3a05STakashi Sakamoto /* Get the number of Music Sub Unit for both direction. */ 857eb7b3a05STakashi Sakamoto err = avc_general_get_plug_info(bebob->unit, 0x0c, 0x00, 0x00, plugs); 858eb7b3a05STakashi Sakamoto if (err < 0) { 859eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 860eb7b3a05STakashi Sakamoto "fail to get info for MSU in/out plugs: %d\n", 861eb7b3a05STakashi Sakamoto err); 862eb7b3a05STakashi Sakamoto goto end; 863eb7b3a05STakashi Sakamoto } 864eb7b3a05STakashi Sakamoto 865eb7b3a05STakashi Sakamoto /* seek destination plugs for 'MSU sync input' */ 866eb7b3a05STakashi Sakamoto bebob->sync_input_plug = -1; 867eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[0]; i++) { 868eb7b3a05STakashi Sakamoto avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, i); 869eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 870eb7b3a05STakashi Sakamoto if (err < 0) { 871eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 872eb7b3a05STakashi Sakamoto "fail to get type for MSU in plug %d: %d\n", 873eb7b3a05STakashi Sakamoto i, err); 874eb7b3a05STakashi Sakamoto goto end; 875eb7b3a05STakashi Sakamoto } 876eb7b3a05STakashi Sakamoto 877eb7b3a05STakashi Sakamoto if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { 878eb7b3a05STakashi Sakamoto bebob->sync_input_plug = i; 879eb7b3a05STakashi Sakamoto break; 880eb7b3a05STakashi Sakamoto } 881eb7b3a05STakashi Sakamoto } 882eb7b3a05STakashi Sakamoto end: 883eb7b3a05STakashi Sakamoto return err; 884eb7b3a05STakashi Sakamoto } 885eb7b3a05STakashi Sakamoto 886eb7b3a05STakashi Sakamoto int snd_bebob_stream_discover(struct snd_bebob *bebob) 887eb7b3a05STakashi Sakamoto { 8886b9866c8SJulia Lawall const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; 889eb7b3a05STakashi Sakamoto u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; 890eb7b3a05STakashi Sakamoto enum avc_bridgeco_plug_type type; 891eb7b3a05STakashi Sakamoto unsigned int i; 892eb7b3a05STakashi Sakamoto int err; 893eb7b3a05STakashi Sakamoto 894eb7b3a05STakashi Sakamoto /* the number of plugs for isoc in/out, ext in/out */ 895eb7b3a05STakashi Sakamoto err = avc_general_get_plug_info(bebob->unit, 0x1f, 0x07, 0x00, plugs); 896eb7b3a05STakashi Sakamoto if (err < 0) { 897eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 898eb7b3a05STakashi Sakamoto "fail to get info for isoc/external in/out plugs: %d\n", 899eb7b3a05STakashi Sakamoto err); 900eb7b3a05STakashi Sakamoto goto end; 901eb7b3a05STakashi Sakamoto } 902eb7b3a05STakashi Sakamoto 903eb7b3a05STakashi Sakamoto /* 904eb7b3a05STakashi Sakamoto * This module supports at least one isoc input plug and one isoc 905eb7b3a05STakashi Sakamoto * output plug. 906eb7b3a05STakashi Sakamoto */ 907eb7b3a05STakashi Sakamoto if ((plugs[0] == 0) || (plugs[1] == 0)) { 908eb7b3a05STakashi Sakamoto err = -ENOSYS; 909eb7b3a05STakashi Sakamoto goto end; 910eb7b3a05STakashi Sakamoto } 911eb7b3a05STakashi Sakamoto 912eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 913eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 914eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 915eb7b3a05STakashi Sakamoto if (err < 0) { 916eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 917eb7b3a05STakashi Sakamoto "fail to get type for isoc in plug 0: %d\n", err); 918eb7b3a05STakashi Sakamoto goto end; 919eb7b3a05STakashi Sakamoto } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { 920eb7b3a05STakashi Sakamoto err = -ENOSYS; 921eb7b3a05STakashi Sakamoto goto end; 922eb7b3a05STakashi Sakamoto } 923eb7b3a05STakashi Sakamoto err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_IN, 0); 924eb7b3a05STakashi Sakamoto if (err < 0) 925eb7b3a05STakashi Sakamoto goto end; 926eb7b3a05STakashi Sakamoto 927eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, 928eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_ISOC, 0); 929eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 930eb7b3a05STakashi Sakamoto if (err < 0) { 931eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 932eb7b3a05STakashi Sakamoto "fail to get type for isoc out plug 0: %d\n", err); 933eb7b3a05STakashi Sakamoto goto end; 934eb7b3a05STakashi Sakamoto } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) { 935eb7b3a05STakashi Sakamoto err = -ENOSYS; 936eb7b3a05STakashi Sakamoto goto end; 937eb7b3a05STakashi Sakamoto } 938eb7b3a05STakashi Sakamoto err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_OUT, 0); 939eb7b3a05STakashi Sakamoto if (err < 0) 940eb7b3a05STakashi Sakamoto goto end; 941eb7b3a05STakashi Sakamoto 942eb7b3a05STakashi Sakamoto /* count external input plugs for MIDI */ 943eb7b3a05STakashi Sakamoto bebob->midi_input_ports = 0; 944eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[2]; i++) { 945eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, 946eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, i); 947eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 948eb7b3a05STakashi Sakamoto if (err < 0) { 949eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 950eb7b3a05STakashi Sakamoto "fail to get type for external in plug %d: %d\n", 951eb7b3a05STakashi Sakamoto i, err); 952eb7b3a05STakashi Sakamoto goto end; 953eb7b3a05STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { 954eb7b3a05STakashi Sakamoto bebob->midi_input_ports++; 955eb7b3a05STakashi Sakamoto } 956eb7b3a05STakashi Sakamoto } 957eb7b3a05STakashi Sakamoto 958eb7b3a05STakashi Sakamoto /* count external output plugs for MIDI */ 959eb7b3a05STakashi Sakamoto bebob->midi_output_ports = 0; 960eb7b3a05STakashi Sakamoto for (i = 0; i < plugs[3]; i++) { 961eb7b3a05STakashi Sakamoto avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT, 962eb7b3a05STakashi Sakamoto AVC_BRIDGECO_PLUG_UNIT_EXT, i); 963eb7b3a05STakashi Sakamoto err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type); 964eb7b3a05STakashi Sakamoto if (err < 0) { 965eb7b3a05STakashi Sakamoto dev_err(&bebob->unit->device, 966eb7b3a05STakashi Sakamoto "fail to get type for external out plug %d: %d\n", 967eb7b3a05STakashi Sakamoto i, err); 968eb7b3a05STakashi Sakamoto goto end; 969eb7b3a05STakashi Sakamoto } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) { 970eb7b3a05STakashi Sakamoto bebob->midi_output_ports++; 971eb7b3a05STakashi Sakamoto } 972eb7b3a05STakashi Sakamoto } 973eb7b3a05STakashi Sakamoto 974eb7b3a05STakashi Sakamoto /* for check source of clock later */ 9751fc9522aSTakashi Sakamoto if (!clk_spec) 976eb7b3a05STakashi Sakamoto err = seek_msu_sync_input_plug(bebob); 977eb7b3a05STakashi Sakamoto end: 978eb7b3a05STakashi Sakamoto return err; 979eb7b3a05STakashi Sakamoto } 980618eabeaSTakashi Sakamoto 981618eabeaSTakashi Sakamoto void snd_bebob_stream_lock_changed(struct snd_bebob *bebob) 982618eabeaSTakashi Sakamoto { 983618eabeaSTakashi Sakamoto bebob->dev_lock_changed = true; 984618eabeaSTakashi Sakamoto wake_up(&bebob->hwdep_wait); 985618eabeaSTakashi Sakamoto } 986618eabeaSTakashi Sakamoto 987618eabeaSTakashi Sakamoto int snd_bebob_stream_lock_try(struct snd_bebob *bebob) 988618eabeaSTakashi Sakamoto { 989618eabeaSTakashi Sakamoto int err; 990618eabeaSTakashi Sakamoto 991618eabeaSTakashi Sakamoto spin_lock_irq(&bebob->lock); 992618eabeaSTakashi Sakamoto 993618eabeaSTakashi Sakamoto /* user land lock this */ 994618eabeaSTakashi Sakamoto if (bebob->dev_lock_count < 0) { 995618eabeaSTakashi Sakamoto err = -EBUSY; 996618eabeaSTakashi Sakamoto goto end; 997618eabeaSTakashi Sakamoto } 998618eabeaSTakashi Sakamoto 999618eabeaSTakashi Sakamoto /* this is the first time */ 1000618eabeaSTakashi Sakamoto if (bebob->dev_lock_count++ == 0) 1001618eabeaSTakashi Sakamoto snd_bebob_stream_lock_changed(bebob); 1002618eabeaSTakashi Sakamoto err = 0; 1003618eabeaSTakashi Sakamoto end: 1004618eabeaSTakashi Sakamoto spin_unlock_irq(&bebob->lock); 1005618eabeaSTakashi Sakamoto return err; 1006618eabeaSTakashi Sakamoto } 1007618eabeaSTakashi Sakamoto 1008618eabeaSTakashi Sakamoto void snd_bebob_stream_lock_release(struct snd_bebob *bebob) 1009618eabeaSTakashi Sakamoto { 1010618eabeaSTakashi Sakamoto spin_lock_irq(&bebob->lock); 1011618eabeaSTakashi Sakamoto 1012618eabeaSTakashi Sakamoto if (WARN_ON(bebob->dev_lock_count <= 0)) 1013618eabeaSTakashi Sakamoto goto end; 1014618eabeaSTakashi Sakamoto if (--bebob->dev_lock_count == 0) 1015618eabeaSTakashi Sakamoto snd_bebob_stream_lock_changed(bebob); 1016618eabeaSTakashi Sakamoto end: 1017618eabeaSTakashi Sakamoto spin_unlock_irq(&bebob->lock); 1018618eabeaSTakashi Sakamoto } 1019