1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26eb6c81eSTakashi Sakamoto /* 36eb6c81eSTakashi Sakamoto * dice_stream.c - a part of driver for DICE based devices 46eb6c81eSTakashi Sakamoto * 56eb6c81eSTakashi Sakamoto * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 66eb6c81eSTakashi Sakamoto * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp> 76eb6c81eSTakashi Sakamoto */ 86eb6c81eSTakashi Sakamoto 96eb6c81eSTakashi Sakamoto #include "dice.h" 106eb6c81eSTakashi Sakamoto 11bdaedca7STakashi Sakamoto #define READY_TIMEOUT_MS 200 12*41319eb5STakashi Sakamoto #define NOTIFICATION_TIMEOUT_MS 100 13288a8d0cSTakashi Sakamoto 148cc1a8abSTakashi Sakamoto struct reg_params { 158cc1a8abSTakashi Sakamoto unsigned int count; 168cc1a8abSTakashi Sakamoto unsigned int size; 178cc1a8abSTakashi Sakamoto }; 188cc1a8abSTakashi Sakamoto 196eb6c81eSTakashi Sakamoto const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = { 206eb6c81eSTakashi Sakamoto /* mode 0 */ 216eb6c81eSTakashi Sakamoto [0] = 32000, 226eb6c81eSTakashi Sakamoto [1] = 44100, 236eb6c81eSTakashi Sakamoto [2] = 48000, 246eb6c81eSTakashi Sakamoto /* mode 1 */ 256eb6c81eSTakashi Sakamoto [3] = 88200, 266eb6c81eSTakashi Sakamoto [4] = 96000, 276eb6c81eSTakashi Sakamoto /* mode 2 */ 286eb6c81eSTakashi Sakamoto [5] = 176400, 296eb6c81eSTakashi Sakamoto [6] = 192000, 306eb6c81eSTakashi Sakamoto }; 316eb6c81eSTakashi Sakamoto 32b60152f7STakashi Sakamoto int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate, 33b60152f7STakashi Sakamoto enum snd_dice_rate_mode *mode) 34b60152f7STakashi Sakamoto { 35b60152f7STakashi Sakamoto /* Corresponding to each entry in snd_dice_rates. */ 36b60152f7STakashi Sakamoto static const enum snd_dice_rate_mode modes[] = { 37b60152f7STakashi Sakamoto [0] = SND_DICE_RATE_MODE_LOW, 38b60152f7STakashi Sakamoto [1] = SND_DICE_RATE_MODE_LOW, 39b60152f7STakashi Sakamoto [2] = SND_DICE_RATE_MODE_LOW, 40b60152f7STakashi Sakamoto [3] = SND_DICE_RATE_MODE_MIDDLE, 41b60152f7STakashi Sakamoto [4] = SND_DICE_RATE_MODE_MIDDLE, 42b60152f7STakashi Sakamoto [5] = SND_DICE_RATE_MODE_HIGH, 43b60152f7STakashi Sakamoto [6] = SND_DICE_RATE_MODE_HIGH, 44b60152f7STakashi Sakamoto }; 45b60152f7STakashi Sakamoto int i; 46b60152f7STakashi Sakamoto 47b60152f7STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) { 48b60152f7STakashi Sakamoto if (!(dice->clock_caps & BIT(i))) 49b60152f7STakashi Sakamoto continue; 50b60152f7STakashi Sakamoto if (snd_dice_rates[i] != rate) 51b60152f7STakashi Sakamoto continue; 52b60152f7STakashi Sakamoto 53b60152f7STakashi Sakamoto *mode = modes[i]; 54b60152f7STakashi Sakamoto return 0; 55b60152f7STakashi Sakamoto } 56b60152f7STakashi Sakamoto 57b60152f7STakashi Sakamoto return -EINVAL; 58b60152f7STakashi Sakamoto } 59b60152f7STakashi Sakamoto 60*41319eb5STakashi Sakamoto static int select_clock(struct snd_dice *dice, unsigned int rate) 61dfabc0eeSTakashi Sakamoto { 62*41319eb5STakashi Sakamoto __be32 reg; 63afa617f2STakashi Sakamoto u32 data; 64afa617f2STakashi Sakamoto int i; 65dfabc0eeSTakashi Sakamoto int err; 66dfabc0eeSTakashi Sakamoto 67dfabc0eeSTakashi Sakamoto err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT, 68dfabc0eeSTakashi Sakamoto ®, sizeof(reg)); 69dfabc0eeSTakashi Sakamoto if (err < 0) 70dfabc0eeSTakashi Sakamoto return err; 71dfabc0eeSTakashi Sakamoto 72afa617f2STakashi Sakamoto data = be32_to_cpu(reg); 73afa617f2STakashi Sakamoto 74afa617f2STakashi Sakamoto data &= ~CLOCK_RATE_MASK; 75afa617f2STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { 76afa617f2STakashi Sakamoto if (snd_dice_rates[i] == rate) 77afa617f2STakashi Sakamoto break; 78afa617f2STakashi Sakamoto } 79afa617f2STakashi Sakamoto if (i == ARRAY_SIZE(snd_dice_rates)) 80afa617f2STakashi Sakamoto return -EINVAL; 81afa617f2STakashi Sakamoto data |= i << CLOCK_RATE_SHIFT; 82afa617f2STakashi Sakamoto 83dfabc0eeSTakashi Sakamoto if (completion_done(&dice->clock_accepted)) 84dfabc0eeSTakashi Sakamoto reinit_completion(&dice->clock_accepted); 85dfabc0eeSTakashi Sakamoto 86afa617f2STakashi Sakamoto reg = cpu_to_be32(data); 87dfabc0eeSTakashi Sakamoto err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT, 88dfabc0eeSTakashi Sakamoto ®, sizeof(reg)); 89dfabc0eeSTakashi Sakamoto if (err < 0) 90dfabc0eeSTakashi Sakamoto return err; 91dfabc0eeSTakashi Sakamoto 92dfabc0eeSTakashi Sakamoto if (wait_for_completion_timeout(&dice->clock_accepted, 93*41319eb5STakashi Sakamoto msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) 94dfabc0eeSTakashi Sakamoto return -ETIMEDOUT; 95dfabc0eeSTakashi Sakamoto 96dfabc0eeSTakashi Sakamoto return 0; 97dfabc0eeSTakashi Sakamoto } 98dfabc0eeSTakashi Sakamoto 998cc1a8abSTakashi Sakamoto static int get_register_params(struct snd_dice *dice, 1008cc1a8abSTakashi Sakamoto struct reg_params *tx_params, 1018cc1a8abSTakashi Sakamoto struct reg_params *rx_params) 1026eb6c81eSTakashi Sakamoto { 103436b5abeSTakashi Sakamoto __be32 reg[2]; 104436b5abeSTakashi Sakamoto int err; 1056eb6c81eSTakashi Sakamoto 106436b5abeSTakashi Sakamoto err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg)); 107436b5abeSTakashi Sakamoto if (err < 0) 108436b5abeSTakashi Sakamoto return err; 1098cc1a8abSTakashi Sakamoto tx_params->count = 1108cc1a8abSTakashi Sakamoto min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS); 1118cc1a8abSTakashi Sakamoto tx_params->size = be32_to_cpu(reg[1]) * 4; 112288a8d0cSTakashi Sakamoto 113436b5abeSTakashi Sakamoto err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg)); 114436b5abeSTakashi Sakamoto if (err < 0) 115436b5abeSTakashi Sakamoto return err; 1168cc1a8abSTakashi Sakamoto rx_params->count = 1178cc1a8abSTakashi Sakamoto min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS); 1188cc1a8abSTakashi Sakamoto rx_params->size = be32_to_cpu(reg[1]) * 4; 119436b5abeSTakashi Sakamoto 120436b5abeSTakashi Sakamoto return 0; 121436b5abeSTakashi Sakamoto } 122436b5abeSTakashi Sakamoto 123436b5abeSTakashi Sakamoto static void release_resources(struct snd_dice *dice) 124436b5abeSTakashi Sakamoto { 1253cd2c2d7STakashi Sakamoto int i; 126436b5abeSTakashi Sakamoto 1273cd2c2d7STakashi Sakamoto for (i = 0; i < MAX_STREAMS; ++i) { 128436b5abeSTakashi Sakamoto fw_iso_resources_free(&dice->tx_resources[i]); 129436b5abeSTakashi Sakamoto fw_iso_resources_free(&dice->rx_resources[i]); 130436b5abeSTakashi Sakamoto } 131436b5abeSTakashi Sakamoto } 132436b5abeSTakashi Sakamoto 133436b5abeSTakashi Sakamoto static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, 1348cc1a8abSTakashi Sakamoto struct reg_params *params) 135436b5abeSTakashi Sakamoto { 136436b5abeSTakashi Sakamoto __be32 reg; 137436b5abeSTakashi Sakamoto unsigned int i; 138436b5abeSTakashi Sakamoto 1398cc1a8abSTakashi Sakamoto for (i = 0; i < params->count; i++) { 140436b5abeSTakashi Sakamoto reg = cpu_to_be32((u32)-1); 141436b5abeSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 142436b5abeSTakashi Sakamoto snd_dice_transaction_write_tx(dice, 1438cc1a8abSTakashi Sakamoto params->size * i + TX_ISOCHRONOUS, 144436b5abeSTakashi Sakamoto ®, sizeof(reg)); 145436b5abeSTakashi Sakamoto } else { 146436b5abeSTakashi Sakamoto snd_dice_transaction_write_rx(dice, 1478cc1a8abSTakashi Sakamoto params->size * i + RX_ISOCHRONOUS, 148436b5abeSTakashi Sakamoto ®, sizeof(reg)); 149436b5abeSTakashi Sakamoto } 150436b5abeSTakashi Sakamoto } 151288a8d0cSTakashi Sakamoto } 152288a8d0cSTakashi Sakamoto 153c738aed1STakashi Sakamoto static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream, 154c738aed1STakashi Sakamoto struct fw_iso_resources *resources, unsigned int rate, 155c738aed1STakashi Sakamoto unsigned int pcm_chs, unsigned int midi_ports) 156288a8d0cSTakashi Sakamoto { 15727ec83b5STakashi Sakamoto bool double_pcm_frames; 158436b5abeSTakashi Sakamoto unsigned int i; 159288a8d0cSTakashi Sakamoto int err; 160288a8d0cSTakashi Sakamoto 161c738aed1STakashi Sakamoto // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in 162c738aed1STakashi Sakamoto // one data block of AMDTP packet. Thus sampling transfer frequency is 163c738aed1STakashi Sakamoto // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are 164c738aed1STakashi Sakamoto // transferred on AMDTP packets at 96 kHz. Two successive samples of a 165c738aed1STakashi Sakamoto // channel are stored consecutively in the packet. This quirk is called 166c738aed1STakashi Sakamoto // as 'Dual Wire'. 167c738aed1STakashi Sakamoto // For this quirk, blocking mode is required and PCM buffer size should 168c738aed1STakashi Sakamoto // be aligned to SYT_INTERVAL. 1699f079c1bSTakashi Sakamoto double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames); 17027ec83b5STakashi Sakamoto if (double_pcm_frames) { 171288a8d0cSTakashi Sakamoto rate /= 2; 172288a8d0cSTakashi Sakamoto pcm_chs *= 2; 173288a8d0cSTakashi Sakamoto } 174288a8d0cSTakashi Sakamoto 17551c29fd2STakashi Sakamoto err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports, 17651c29fd2STakashi Sakamoto double_pcm_frames); 177547e631cSTakashi Sakamoto if (err < 0) 178436b5abeSTakashi Sakamoto return err; 179547e631cSTakashi Sakamoto 18027ec83b5STakashi Sakamoto if (double_pcm_frames) { 181288a8d0cSTakashi Sakamoto pcm_chs /= 2; 182288a8d0cSTakashi Sakamoto 183288a8d0cSTakashi Sakamoto for (i = 0; i < pcm_chs; i++) { 184f65be911STakashi Sakamoto amdtp_am824_set_pcm_position(stream, i, i * 2); 185f65be911STakashi Sakamoto amdtp_am824_set_pcm_position(stream, i + pcm_chs, 186f65be911STakashi Sakamoto i * 2 + 1); 187288a8d0cSTakashi Sakamoto } 188288a8d0cSTakashi Sakamoto } 189288a8d0cSTakashi Sakamoto 190436b5abeSTakashi Sakamoto return fw_iso_resources_allocate(resources, 191436b5abeSTakashi Sakamoto amdtp_stream_get_max_payload(stream), 192436b5abeSTakashi Sakamoto fw_parent_device(dice->unit)->max_speed); 193288a8d0cSTakashi Sakamoto } 194288a8d0cSTakashi Sakamoto 195c738aed1STakashi Sakamoto static int keep_dual_resources(struct snd_dice *dice, unsigned int rate, 196c738aed1STakashi Sakamoto enum amdtp_stream_direction dir, 197c738aed1STakashi Sakamoto struct reg_params *params) 198c738aed1STakashi Sakamoto { 199c738aed1STakashi Sakamoto enum snd_dice_rate_mode mode; 200c738aed1STakashi Sakamoto int i; 201c738aed1STakashi Sakamoto int err; 202c738aed1STakashi Sakamoto 203c738aed1STakashi Sakamoto err = snd_dice_stream_get_rate_mode(dice, rate, &mode); 204c738aed1STakashi Sakamoto if (err < 0) 205c738aed1STakashi Sakamoto return err; 206c738aed1STakashi Sakamoto 207c738aed1STakashi Sakamoto for (i = 0; i < params->count; ++i) { 208c738aed1STakashi Sakamoto __be32 reg[2]; 209c738aed1STakashi Sakamoto struct amdtp_stream *stream; 210c738aed1STakashi Sakamoto struct fw_iso_resources *resources; 211c738aed1STakashi Sakamoto unsigned int pcm_cache; 212c738aed1STakashi Sakamoto unsigned int pcm_chs; 213c738aed1STakashi Sakamoto unsigned int midi_ports; 214c738aed1STakashi Sakamoto 215c738aed1STakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 216c738aed1STakashi Sakamoto stream = &dice->tx_stream[i]; 217c738aed1STakashi Sakamoto resources = &dice->tx_resources[i]; 218c738aed1STakashi Sakamoto 219c738aed1STakashi Sakamoto pcm_cache = dice->tx_pcm_chs[i][mode]; 220c738aed1STakashi Sakamoto err = snd_dice_transaction_read_tx(dice, 221c738aed1STakashi Sakamoto params->size * i + TX_NUMBER_AUDIO, 222c738aed1STakashi Sakamoto reg, sizeof(reg)); 223c738aed1STakashi Sakamoto } else { 224c738aed1STakashi Sakamoto stream = &dice->rx_stream[i]; 225c738aed1STakashi Sakamoto resources = &dice->rx_resources[i]; 226c738aed1STakashi Sakamoto 227c738aed1STakashi Sakamoto pcm_cache = dice->rx_pcm_chs[i][mode]; 228c738aed1STakashi Sakamoto err = snd_dice_transaction_read_rx(dice, 229c738aed1STakashi Sakamoto params->size * i + RX_NUMBER_AUDIO, 230c738aed1STakashi Sakamoto reg, sizeof(reg)); 231c738aed1STakashi Sakamoto } 232c738aed1STakashi Sakamoto if (err < 0) 233c738aed1STakashi Sakamoto return err; 234c738aed1STakashi Sakamoto pcm_chs = be32_to_cpu(reg[0]); 235c738aed1STakashi Sakamoto midi_ports = be32_to_cpu(reg[1]); 236c738aed1STakashi Sakamoto 237c738aed1STakashi Sakamoto // These are important for developer of this driver. 238a9f47fcbSTakashi Sakamoto if (pcm_chs != pcm_cache) { 239c738aed1STakashi Sakamoto dev_info(&dice->unit->device, 240a9f47fcbSTakashi Sakamoto "cache mismatch: pcm: %u:%u, midi: %u\n", 241a9f47fcbSTakashi Sakamoto pcm_chs, pcm_cache, midi_ports); 242c738aed1STakashi Sakamoto return -EPROTO; 243c738aed1STakashi Sakamoto } 244c738aed1STakashi Sakamoto 245c738aed1STakashi Sakamoto err = keep_resources(dice, stream, resources, rate, pcm_chs, 246c738aed1STakashi Sakamoto midi_ports); 247c738aed1STakashi Sakamoto if (err < 0) 248c738aed1STakashi Sakamoto return err; 249c738aed1STakashi Sakamoto } 250c738aed1STakashi Sakamoto 251c738aed1STakashi Sakamoto return 0; 252c738aed1STakashi Sakamoto } 253c738aed1STakashi Sakamoto 254b3480638STakashi Sakamoto static void finish_session(struct snd_dice *dice, struct reg_params *tx_params, 255b3480638STakashi Sakamoto struct reg_params *rx_params) 256b3480638STakashi Sakamoto { 257b3480638STakashi Sakamoto stop_streams(dice, AMDTP_IN_STREAM, tx_params); 258b3480638STakashi Sakamoto stop_streams(dice, AMDTP_OUT_STREAM, rx_params); 259b3480638STakashi Sakamoto 260b3480638STakashi Sakamoto snd_dice_transaction_clear_enable(dice); 261b3480638STakashi Sakamoto } 262b3480638STakashi Sakamoto 26394c8101aSTakashi Sakamoto int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate, 264ecb40fd2STakashi Sakamoto unsigned int events_per_period, 265ecb40fd2STakashi Sakamoto unsigned int events_per_buffer) 2663cd2c2d7STakashi Sakamoto { 2673cd2c2d7STakashi Sakamoto unsigned int curr_rate; 2683cd2c2d7STakashi Sakamoto int err; 2693cd2c2d7STakashi Sakamoto 2703cd2c2d7STakashi Sakamoto // Check sampling transmission frequency. 2713cd2c2d7STakashi Sakamoto err = snd_dice_transaction_get_rate(dice, &curr_rate); 2723cd2c2d7STakashi Sakamoto if (err < 0) 2733cd2c2d7STakashi Sakamoto return err; 2743cd2c2d7STakashi Sakamoto if (rate == 0) 2753cd2c2d7STakashi Sakamoto rate = curr_rate; 2763cd2c2d7STakashi Sakamoto 2773cd2c2d7STakashi Sakamoto if (dice->substreams_counter == 0 || curr_rate != rate) { 2783cd2c2d7STakashi Sakamoto struct reg_params tx_params, rx_params; 2793cd2c2d7STakashi Sakamoto 280e9f21129STakashi Sakamoto amdtp_domain_stop(&dice->domain); 281e9f21129STakashi Sakamoto 2823cd2c2d7STakashi Sakamoto err = get_register_params(dice, &tx_params, &rx_params); 2833cd2c2d7STakashi Sakamoto if (err < 0) 2843cd2c2d7STakashi Sakamoto return err; 2853cd2c2d7STakashi Sakamoto finish_session(dice, &tx_params, &rx_params); 2863cd2c2d7STakashi Sakamoto 2873cd2c2d7STakashi Sakamoto release_resources(dice); 2883cd2c2d7STakashi Sakamoto 2893cd2c2d7STakashi Sakamoto // Just after owning the unit (GLOBAL_OWNER), the unit can 2903cd2c2d7STakashi Sakamoto // return invalid stream formats. Selecting clock parameters 2913cd2c2d7STakashi Sakamoto // have an effect for the unit to refine it. 292*41319eb5STakashi Sakamoto err = select_clock(dice, rate); 2933cd2c2d7STakashi Sakamoto if (err < 0) 2943cd2c2d7STakashi Sakamoto return err; 2953cd2c2d7STakashi Sakamoto 2963cd2c2d7STakashi Sakamoto // After changing sampling transfer frequency, the value of 2973cd2c2d7STakashi Sakamoto // register can be changed. 2983cd2c2d7STakashi Sakamoto err = get_register_params(dice, &tx_params, &rx_params); 2993cd2c2d7STakashi Sakamoto if (err < 0) 3003cd2c2d7STakashi Sakamoto return err; 3013cd2c2d7STakashi Sakamoto 3023cd2c2d7STakashi Sakamoto err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM, 3033cd2c2d7STakashi Sakamoto &tx_params); 3043cd2c2d7STakashi Sakamoto if (err < 0) 3053cd2c2d7STakashi Sakamoto goto error; 3063cd2c2d7STakashi Sakamoto 3073cd2c2d7STakashi Sakamoto err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM, 3083cd2c2d7STakashi Sakamoto &rx_params); 3093cd2c2d7STakashi Sakamoto if (err < 0) 3103cd2c2d7STakashi Sakamoto goto error; 31194c8101aSTakashi Sakamoto 31294c8101aSTakashi Sakamoto err = amdtp_domain_set_events_per_period(&dice->domain, 313ecb40fd2STakashi Sakamoto events_per_period, events_per_buffer); 31494c8101aSTakashi Sakamoto if (err < 0) 31594c8101aSTakashi Sakamoto goto error; 3163cd2c2d7STakashi Sakamoto } 3173cd2c2d7STakashi Sakamoto 3183cd2c2d7STakashi Sakamoto return 0; 3193cd2c2d7STakashi Sakamoto error: 3203cd2c2d7STakashi Sakamoto release_resources(dice); 3213cd2c2d7STakashi Sakamoto return err; 3223cd2c2d7STakashi Sakamoto } 3233cd2c2d7STakashi Sakamoto 324436b5abeSTakashi Sakamoto static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, 3258cc1a8abSTakashi Sakamoto unsigned int rate, struct reg_params *params) 326436b5abeSTakashi Sakamoto { 327c738aed1STakashi Sakamoto unsigned int max_speed = fw_parent_device(dice->unit)->max_speed; 328c738aed1STakashi Sakamoto int i; 329c738aed1STakashi Sakamoto int err; 330436b5abeSTakashi Sakamoto 3318cc1a8abSTakashi Sakamoto for (i = 0; i < params->count; i++) { 332c738aed1STakashi Sakamoto struct amdtp_stream *stream; 333c738aed1STakashi Sakamoto struct fw_iso_resources *resources; 334c738aed1STakashi Sakamoto __be32 reg; 335afa617f2STakashi Sakamoto 336436b5abeSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 337c738aed1STakashi Sakamoto stream = dice->tx_stream + i; 338c738aed1STakashi Sakamoto resources = dice->tx_resources + i; 339436b5abeSTakashi Sakamoto } else { 340c738aed1STakashi Sakamoto stream = dice->rx_stream + i; 341c738aed1STakashi Sakamoto resources = dice->rx_resources + i; 342afa617f2STakashi Sakamoto } 343afa617f2STakashi Sakamoto 344c738aed1STakashi Sakamoto reg = cpu_to_be32(resources->channel); 345436b5abeSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 346436b5abeSTakashi Sakamoto err = snd_dice_transaction_write_tx(dice, 3478cc1a8abSTakashi Sakamoto params->size * i + TX_ISOCHRONOUS, 348c738aed1STakashi Sakamoto ®, sizeof(reg)); 349436b5abeSTakashi Sakamoto } else { 350436b5abeSTakashi Sakamoto err = snd_dice_transaction_write_rx(dice, 3518cc1a8abSTakashi Sakamoto params->size * i + RX_ISOCHRONOUS, 352c738aed1STakashi Sakamoto ®, sizeof(reg)); 353436b5abeSTakashi Sakamoto } 354436b5abeSTakashi Sakamoto if (err < 0) 355436b5abeSTakashi Sakamoto return err; 356436b5abeSTakashi Sakamoto 357b0e159feSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 358c738aed1STakashi Sakamoto reg = cpu_to_be32(max_speed); 359b0e159feSTakashi Sakamoto err = snd_dice_transaction_write_tx(dice, 360b0e159feSTakashi Sakamoto params->size * i + TX_SPEED, 361c738aed1STakashi Sakamoto ®, sizeof(reg)); 362b0e159feSTakashi Sakamoto if (err < 0) 363b0e159feSTakashi Sakamoto return err; 364b0e159feSTakashi Sakamoto } 365b0e159feSTakashi Sakamoto 366e9f21129STakashi Sakamoto err = amdtp_domain_add_stream(&dice->domain, stream, 367e9f21129STakashi Sakamoto resources->channel, max_speed); 368288a8d0cSTakashi Sakamoto if (err < 0) 369288a8d0cSTakashi Sakamoto return err; 370288a8d0cSTakashi Sakamoto } 371288a8d0cSTakashi Sakamoto 372c72d3a0aSTakashi Sakamoto return 0; 373436b5abeSTakashi Sakamoto } 374436b5abeSTakashi Sakamoto 3753cd2c2d7STakashi Sakamoto /* 3763cd2c2d7STakashi Sakamoto * MEMO: After this function, there're two states of streams: 3773cd2c2d7STakashi Sakamoto * - None streams are running. 3783cd2c2d7STakashi Sakamoto * - All streams are running. 3793cd2c2d7STakashi Sakamoto */ 3803cd2c2d7STakashi Sakamoto int snd_dice_stream_start_duplex(struct snd_dice *dice) 38120b94544STakashi Sakamoto { 382d5553026STakashi Sakamoto unsigned int generation = dice->rx_resources[0].generation; 38320b94544STakashi Sakamoto struct reg_params tx_params, rx_params; 3843cd2c2d7STakashi Sakamoto unsigned int i; 3853cd2c2d7STakashi Sakamoto unsigned int rate; 3863cd2c2d7STakashi Sakamoto enum snd_dice_rate_mode mode; 38720b94544STakashi Sakamoto int err; 38820b94544STakashi Sakamoto 3893cd2c2d7STakashi Sakamoto if (dice->substreams_counter == 0) 3903cd2c2d7STakashi Sakamoto return -EIO; 3913cd2c2d7STakashi Sakamoto 39220b94544STakashi Sakamoto err = get_register_params(dice, &tx_params, &rx_params); 39320b94544STakashi Sakamoto if (err < 0) 39420b94544STakashi Sakamoto return err; 39520b94544STakashi Sakamoto 3963cd2c2d7STakashi Sakamoto // Check error of packet streaming. 3973cd2c2d7STakashi Sakamoto for (i = 0; i < MAX_STREAMS; ++i) { 3983cd2c2d7STakashi Sakamoto if (amdtp_streaming_error(&dice->tx_stream[i]) || 3993cd2c2d7STakashi Sakamoto amdtp_streaming_error(&dice->rx_stream[i])) { 400e9f21129STakashi Sakamoto amdtp_domain_stop(&dice->domain); 401b3480638STakashi Sakamoto finish_session(dice, &tx_params, &rx_params); 4023cd2c2d7STakashi Sakamoto break; 4033cd2c2d7STakashi Sakamoto } 40420b94544STakashi Sakamoto } 40520b94544STakashi Sakamoto 406d5553026STakashi Sakamoto if (generation != fw_parent_device(dice->unit)->card->generation) { 407d5553026STakashi Sakamoto for (i = 0; i < MAX_STREAMS; ++i) { 408d5553026STakashi Sakamoto if (i < tx_params.count) 409d5553026STakashi Sakamoto fw_iso_resources_update(dice->tx_resources + i); 410d5553026STakashi Sakamoto if (i < rx_params.count) 411d5553026STakashi Sakamoto fw_iso_resources_update(dice->rx_resources + i); 412d5553026STakashi Sakamoto } 413d5553026STakashi Sakamoto } 414d5553026STakashi Sakamoto 4153cd2c2d7STakashi Sakamoto // Check required streams are running or not. 4163cd2c2d7STakashi Sakamoto err = snd_dice_transaction_get_rate(dice, &rate); 417afa617f2STakashi Sakamoto if (err < 0) 418afa617f2STakashi Sakamoto return err; 4193cd2c2d7STakashi Sakamoto err = snd_dice_stream_get_rate_mode(dice, rate, &mode); 4203cd2c2d7STakashi Sakamoto if (err < 0) 4213cd2c2d7STakashi Sakamoto return err; 4223cd2c2d7STakashi Sakamoto for (i = 0; i < MAX_STREAMS; ++i) { 4233cd2c2d7STakashi Sakamoto if (dice->tx_pcm_chs[i][mode] > 0 && 4243cd2c2d7STakashi Sakamoto !amdtp_stream_running(&dice->tx_stream[i])) 4253cd2c2d7STakashi Sakamoto break; 4263cd2c2d7STakashi Sakamoto if (dice->rx_pcm_chs[i][mode] > 0 && 4273cd2c2d7STakashi Sakamoto !amdtp_stream_running(&dice->rx_stream[i])) 4283cd2c2d7STakashi Sakamoto break; 4293cd2c2d7STakashi Sakamoto } 4303cd2c2d7STakashi Sakamoto if (i < MAX_STREAMS) { 4313cd2c2d7STakashi Sakamoto // Start both streams. 43220b94544STakashi Sakamoto err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); 43320b94544STakashi Sakamoto if (err < 0) 43420b94544STakashi Sakamoto goto error; 4353cd2c2d7STakashi Sakamoto 43620b94544STakashi Sakamoto err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); 43720b94544STakashi Sakamoto if (err < 0) 43820b94544STakashi Sakamoto goto error; 43920b94544STakashi Sakamoto 44020b94544STakashi Sakamoto err = snd_dice_transaction_set_enable(dice); 44120b94544STakashi Sakamoto if (err < 0) { 4423cd2c2d7STakashi Sakamoto dev_err(&dice->unit->device, 4433cd2c2d7STakashi Sakamoto "fail to enable interface\n"); 44420b94544STakashi Sakamoto goto error; 44520b94544STakashi Sakamoto } 44620b94544STakashi Sakamoto 4472f21a177STakashi Sakamoto err = amdtp_domain_start(&dice->domain, 0, false, false); 448e9f21129STakashi Sakamoto if (err < 0) 449e9f21129STakashi Sakamoto goto error; 450e9f21129STakashi Sakamoto 451bdaedca7STakashi Sakamoto if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) { 45220b94544STakashi Sakamoto err = -ETIMEDOUT; 45320b94544STakashi Sakamoto goto error; 45420b94544STakashi Sakamoto } 45520b94544STakashi Sakamoto } 45620b94544STakashi Sakamoto 45720b94544STakashi Sakamoto return 0; 45820b94544STakashi Sakamoto error: 459e9f21129STakashi Sakamoto amdtp_domain_stop(&dice->domain); 460b3480638STakashi Sakamoto finish_session(dice, &tx_params, &rx_params); 46120b94544STakashi Sakamoto return err; 46220b94544STakashi Sakamoto } 46320b94544STakashi Sakamoto 464436b5abeSTakashi Sakamoto /* 465436b5abeSTakashi Sakamoto * MEMO: After this function, there're two states of streams: 466436b5abeSTakashi Sakamoto * - None streams are running. 467436b5abeSTakashi Sakamoto * - All streams are running. 468436b5abeSTakashi Sakamoto */ 4699a02843cSTakashi Sakamoto void snd_dice_stream_stop_duplex(struct snd_dice *dice) 4706eb6c81eSTakashi Sakamoto { 4718cc1a8abSTakashi Sakamoto struct reg_params tx_params, rx_params; 472436b5abeSTakashi Sakamoto 4733cd2c2d7STakashi Sakamoto if (dice->substreams_counter == 0) { 474dd7b836dSTakashi Sakamoto if (get_register_params(dice, &tx_params, &rx_params) >= 0) 475b3480638STakashi Sakamoto finish_session(dice, &tx_params, &rx_params); 476740680f2STakashi Sakamoto 477dd7b836dSTakashi Sakamoto amdtp_domain_stop(&dice->domain); 478740680f2STakashi Sakamoto release_resources(dice); 4793cd2c2d7STakashi Sakamoto } 480436b5abeSTakashi Sakamoto } 4819a02843cSTakashi Sakamoto 482436b5abeSTakashi Sakamoto static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir, 483436b5abeSTakashi Sakamoto unsigned int index) 484436b5abeSTakashi Sakamoto { 485436b5abeSTakashi Sakamoto struct amdtp_stream *stream; 486436b5abeSTakashi Sakamoto struct fw_iso_resources *resources; 487436b5abeSTakashi Sakamoto int err; 488436b5abeSTakashi Sakamoto 489436b5abeSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 490436b5abeSTakashi Sakamoto stream = &dice->tx_stream[index]; 491436b5abeSTakashi Sakamoto resources = &dice->tx_resources[index]; 4929a02843cSTakashi Sakamoto } else { 493436b5abeSTakashi Sakamoto stream = &dice->rx_stream[index]; 494436b5abeSTakashi Sakamoto resources = &dice->rx_resources[index]; 4959a02843cSTakashi Sakamoto } 4969a02843cSTakashi Sakamoto 4979a02843cSTakashi Sakamoto err = fw_iso_resources_init(resources, dice->unit); 4989a02843cSTakashi Sakamoto if (err < 0) 4999a02843cSTakashi Sakamoto goto end; 5009a02843cSTakashi Sakamoto resources->channels_mask = 0x00000000ffffffffuLL; 5019a02843cSTakashi Sakamoto 5025955815eSTakashi Sakamoto err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING); 5039a02843cSTakashi Sakamoto if (err < 0) { 5049a02843cSTakashi Sakamoto amdtp_stream_destroy(stream); 5059a02843cSTakashi Sakamoto fw_iso_resources_destroy(resources); 5069a02843cSTakashi Sakamoto } 5079a02843cSTakashi Sakamoto end: 5089a02843cSTakashi Sakamoto return err; 5099a02843cSTakashi Sakamoto } 5109a02843cSTakashi Sakamoto 511d23c2cc4STakashi Sakamoto /* 512d23c2cc4STakashi Sakamoto * This function should be called before starting streams or after stopping 513d23c2cc4STakashi Sakamoto * streams. 514d23c2cc4STakashi Sakamoto */ 515436b5abeSTakashi Sakamoto static void destroy_stream(struct snd_dice *dice, 516436b5abeSTakashi Sakamoto enum amdtp_stream_direction dir, 517436b5abeSTakashi Sakamoto unsigned int index) 5189a02843cSTakashi Sakamoto { 519436b5abeSTakashi Sakamoto struct amdtp_stream *stream; 520d23c2cc4STakashi Sakamoto struct fw_iso_resources *resources; 5219a02843cSTakashi Sakamoto 522436b5abeSTakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 523436b5abeSTakashi Sakamoto stream = &dice->tx_stream[index]; 524436b5abeSTakashi Sakamoto resources = &dice->tx_resources[index]; 525436b5abeSTakashi Sakamoto } else { 526436b5abeSTakashi Sakamoto stream = &dice->rx_stream[index]; 527436b5abeSTakashi Sakamoto resources = &dice->rx_resources[index]; 528436b5abeSTakashi Sakamoto } 529d23c2cc4STakashi Sakamoto 530d23c2cc4STakashi Sakamoto amdtp_stream_destroy(stream); 531d23c2cc4STakashi Sakamoto fw_iso_resources_destroy(resources); 5329a02843cSTakashi Sakamoto } 5339a02843cSTakashi Sakamoto 5349a02843cSTakashi Sakamoto int snd_dice_stream_init_duplex(struct snd_dice *dice) 5356eb6c81eSTakashi Sakamoto { 536436b5abeSTakashi Sakamoto int i, err; 5376eb6c81eSTakashi Sakamoto 538436b5abeSTakashi Sakamoto for (i = 0; i < MAX_STREAMS; i++) { 539436b5abeSTakashi Sakamoto err = init_stream(dice, AMDTP_IN_STREAM, i); 540436b5abeSTakashi Sakamoto if (err < 0) { 541436b5abeSTakashi Sakamoto for (; i >= 0; i--) 5420f925660STakashi Sakamoto destroy_stream(dice, AMDTP_IN_STREAM, i); 5436eb6c81eSTakashi Sakamoto goto end; 544436b5abeSTakashi Sakamoto } 545436b5abeSTakashi Sakamoto } 5466eb6c81eSTakashi Sakamoto 547436b5abeSTakashi Sakamoto for (i = 0; i < MAX_STREAMS; i++) { 548436b5abeSTakashi Sakamoto err = init_stream(dice, AMDTP_OUT_STREAM, i); 549436b5abeSTakashi Sakamoto if (err < 0) { 550436b5abeSTakashi Sakamoto for (; i >= 0; i--) 551436b5abeSTakashi Sakamoto destroy_stream(dice, AMDTP_OUT_STREAM, i); 552436b5abeSTakashi Sakamoto for (i = 0; i < MAX_STREAMS; i++) 553436b5abeSTakashi Sakamoto destroy_stream(dice, AMDTP_IN_STREAM, i); 5546e26d193STakashi Sakamoto goto end; 555436b5abeSTakashi Sakamoto } 556436b5abeSTakashi Sakamoto } 557e9f21129STakashi Sakamoto 558e9f21129STakashi Sakamoto err = amdtp_domain_init(&dice->domain); 559e9f21129STakashi Sakamoto if (err < 0) { 560e9f21129STakashi Sakamoto for (i = 0; i < MAX_STREAMS; ++i) { 561e9f21129STakashi Sakamoto destroy_stream(dice, AMDTP_OUT_STREAM, i); 562e9f21129STakashi Sakamoto destroy_stream(dice, AMDTP_IN_STREAM, i); 563e9f21129STakashi Sakamoto } 564e9f21129STakashi Sakamoto } 5656eb6c81eSTakashi Sakamoto end: 5666eb6c81eSTakashi Sakamoto return err; 5676eb6c81eSTakashi Sakamoto } 5686eb6c81eSTakashi Sakamoto 5699a02843cSTakashi Sakamoto void snd_dice_stream_destroy_duplex(struct snd_dice *dice) 5706eb6c81eSTakashi Sakamoto { 5716b94fb14STakashi Sakamoto unsigned int i; 572436b5abeSTakashi Sakamoto 5736b94fb14STakashi Sakamoto for (i = 0; i < MAX_STREAMS; i++) { 5746b94fb14STakashi Sakamoto destroy_stream(dice, AMDTP_IN_STREAM, i); 5756b94fb14STakashi Sakamoto destroy_stream(dice, AMDTP_OUT_STREAM, i); 576436b5abeSTakashi Sakamoto } 577e9f21129STakashi Sakamoto 578e9f21129STakashi Sakamoto amdtp_domain_destroy(&dice->domain); 5796eb6c81eSTakashi Sakamoto } 5806eb6c81eSTakashi Sakamoto 5819a02843cSTakashi Sakamoto void snd_dice_stream_update_duplex(struct snd_dice *dice) 5826eb6c81eSTakashi Sakamoto { 5838cc1a8abSTakashi Sakamoto struct reg_params tx_params, rx_params; 584436b5abeSTakashi Sakamoto 5856eb6c81eSTakashi Sakamoto /* 5866eb6c81eSTakashi Sakamoto * On a bus reset, the DICE firmware disables streaming and then goes 5876eb6c81eSTakashi Sakamoto * off contemplating its own navel for hundreds of milliseconds before 5886eb6c81eSTakashi Sakamoto * it can react to any of our attempts to reenable streaming. This 5896eb6c81eSTakashi Sakamoto * means that we lose synchronization anyway, so we force our streams 5906eb6c81eSTakashi Sakamoto * to stop so that the application can restart them in an orderly 5916eb6c81eSTakashi Sakamoto * manner. 5926eb6c81eSTakashi Sakamoto */ 5936eb6c81eSTakashi Sakamoto dice->global_enabled = false; 5946eb6c81eSTakashi Sakamoto 5958cc1a8abSTakashi Sakamoto if (get_register_params(dice, &tx_params, &rx_params) == 0) { 596e9f21129STakashi Sakamoto amdtp_domain_stop(&dice->domain); 597e9f21129STakashi Sakamoto 5988cc1a8abSTakashi Sakamoto stop_streams(dice, AMDTP_IN_STREAM, &tx_params); 5998cc1a8abSTakashi Sakamoto stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); 600436b5abeSTakashi Sakamoto } 6016eb6c81eSTakashi Sakamoto } 6026eb6c81eSTakashi Sakamoto 603b60152f7STakashi Sakamoto int snd_dice_stream_detect_current_formats(struct snd_dice *dice) 604b60152f7STakashi Sakamoto { 605b60152f7STakashi Sakamoto unsigned int rate; 606b60152f7STakashi Sakamoto enum snd_dice_rate_mode mode; 607b60152f7STakashi Sakamoto __be32 reg[2]; 608b60152f7STakashi Sakamoto struct reg_params tx_params, rx_params; 609b60152f7STakashi Sakamoto int i; 610b60152f7STakashi Sakamoto int err; 611b60152f7STakashi Sakamoto 61258579c05STakashi Sakamoto /* If extended protocol is available, detect detail spec. */ 61358579c05STakashi Sakamoto err = snd_dice_detect_extension_formats(dice); 61458579c05STakashi Sakamoto if (err >= 0) 61558579c05STakashi Sakamoto return err; 61658579c05STakashi Sakamoto 617b60152f7STakashi Sakamoto /* 618b60152f7STakashi Sakamoto * Available stream format is restricted at current mode of sampling 619b60152f7STakashi Sakamoto * clock. 620b60152f7STakashi Sakamoto */ 621b60152f7STakashi Sakamoto err = snd_dice_transaction_get_rate(dice, &rate); 622b60152f7STakashi Sakamoto if (err < 0) 623b60152f7STakashi Sakamoto return err; 624b60152f7STakashi Sakamoto 625b60152f7STakashi Sakamoto err = snd_dice_stream_get_rate_mode(dice, rate, &mode); 626b60152f7STakashi Sakamoto if (err < 0) 627b60152f7STakashi Sakamoto return err; 628b60152f7STakashi Sakamoto 629b60152f7STakashi Sakamoto /* 630b60152f7STakashi Sakamoto * Just after owning the unit (GLOBAL_OWNER), the unit can return 631b60152f7STakashi Sakamoto * invalid stream formats. Selecting clock parameters have an effect 632b60152f7STakashi Sakamoto * for the unit to refine it. 633b60152f7STakashi Sakamoto */ 634*41319eb5STakashi Sakamoto err = select_clock(dice, rate); 635b60152f7STakashi Sakamoto if (err < 0) 636b60152f7STakashi Sakamoto return err; 637b60152f7STakashi Sakamoto 638b60152f7STakashi Sakamoto err = get_register_params(dice, &tx_params, &rx_params); 639b60152f7STakashi Sakamoto if (err < 0) 640b60152f7STakashi Sakamoto return err; 641b60152f7STakashi Sakamoto 642b60152f7STakashi Sakamoto for (i = 0; i < tx_params.count; ++i) { 643b60152f7STakashi Sakamoto err = snd_dice_transaction_read_tx(dice, 644b60152f7STakashi Sakamoto tx_params.size * i + TX_NUMBER_AUDIO, 645b60152f7STakashi Sakamoto reg, sizeof(reg)); 646b60152f7STakashi Sakamoto if (err < 0) 647b60152f7STakashi Sakamoto return err; 648b60152f7STakashi Sakamoto dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]); 649b60152f7STakashi Sakamoto dice->tx_midi_ports[i] = max_t(unsigned int, 650b60152f7STakashi Sakamoto be32_to_cpu(reg[1]), dice->tx_midi_ports[i]); 651b60152f7STakashi Sakamoto } 652b60152f7STakashi Sakamoto for (i = 0; i < rx_params.count; ++i) { 653b60152f7STakashi Sakamoto err = snd_dice_transaction_read_rx(dice, 654b60152f7STakashi Sakamoto rx_params.size * i + RX_NUMBER_AUDIO, 655b60152f7STakashi Sakamoto reg, sizeof(reg)); 656b60152f7STakashi Sakamoto if (err < 0) 657b60152f7STakashi Sakamoto return err; 658b60152f7STakashi Sakamoto dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]); 659b60152f7STakashi Sakamoto dice->rx_midi_ports[i] = max_t(unsigned int, 660b60152f7STakashi Sakamoto be32_to_cpu(reg[1]), dice->rx_midi_ports[i]); 661b60152f7STakashi Sakamoto } 662b60152f7STakashi Sakamoto 663b60152f7STakashi Sakamoto return 0; 664b60152f7STakashi Sakamoto } 665b60152f7STakashi Sakamoto 6666eb6c81eSTakashi Sakamoto static void dice_lock_changed(struct snd_dice *dice) 6676eb6c81eSTakashi Sakamoto { 6686eb6c81eSTakashi Sakamoto dice->dev_lock_changed = true; 6696eb6c81eSTakashi Sakamoto wake_up(&dice->hwdep_wait); 6706eb6c81eSTakashi Sakamoto } 6716eb6c81eSTakashi Sakamoto 6726eb6c81eSTakashi Sakamoto int snd_dice_stream_lock_try(struct snd_dice *dice) 6736eb6c81eSTakashi Sakamoto { 6746eb6c81eSTakashi Sakamoto int err; 6756eb6c81eSTakashi Sakamoto 6766eb6c81eSTakashi Sakamoto spin_lock_irq(&dice->lock); 6776eb6c81eSTakashi Sakamoto 6786eb6c81eSTakashi Sakamoto if (dice->dev_lock_count < 0) { 6796eb6c81eSTakashi Sakamoto err = -EBUSY; 6806eb6c81eSTakashi Sakamoto goto out; 6816eb6c81eSTakashi Sakamoto } 6826eb6c81eSTakashi Sakamoto 6836eb6c81eSTakashi Sakamoto if (dice->dev_lock_count++ == 0) 6846eb6c81eSTakashi Sakamoto dice_lock_changed(dice); 6856eb6c81eSTakashi Sakamoto err = 0; 6866eb6c81eSTakashi Sakamoto out: 6876eb6c81eSTakashi Sakamoto spin_unlock_irq(&dice->lock); 6886eb6c81eSTakashi Sakamoto return err; 6896eb6c81eSTakashi Sakamoto } 6906eb6c81eSTakashi Sakamoto 6916eb6c81eSTakashi Sakamoto void snd_dice_stream_lock_release(struct snd_dice *dice) 6926eb6c81eSTakashi Sakamoto { 6936eb6c81eSTakashi Sakamoto spin_lock_irq(&dice->lock); 6946eb6c81eSTakashi Sakamoto 6956eb6c81eSTakashi Sakamoto if (WARN_ON(dice->dev_lock_count <= 0)) 6966eb6c81eSTakashi Sakamoto goto out; 6976eb6c81eSTakashi Sakamoto 6986eb6c81eSTakashi Sakamoto if (--dice->dev_lock_count == 0) 6996eb6c81eSTakashi Sakamoto dice_lock_changed(dice); 7006eb6c81eSTakashi Sakamoto out: 7016eb6c81eSTakashi Sakamoto spin_unlock_irq(&dice->lock); 7026eb6c81eSTakashi Sakamoto } 703