linux/sound/firewire/fireface/ff-protocol-latter.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// ff-protocol-latter - a part of driver for RME Fireface series
   3//
   4// Copyright (c) 2019 Takashi Sakamoto
   5//
   6// Licensed under the terms of the GNU General Public License, version 2.
   7
   8#include <linux/delay.h>
   9
  10#include "ff.h"
  11
  12#define LATTER_STF              0xffff00000004ULL
  13#define LATTER_ISOC_CHANNELS    0xffff00000008ULL
  14#define LATTER_ISOC_START       0xffff0000000cULL
  15#define LATTER_FETCH_MODE       0xffff00000010ULL
  16#define LATTER_SYNC_STATUS      0x0000801c0000ULL
  17
  18static int parse_clock_bits(u32 data, unsigned int *rate,
  19                            enum snd_ff_clock_src *src,
  20                            enum snd_ff_unit_version unit_version)
  21{
  22        static const struct {
  23                unsigned int rate;
  24                u32 flag;
  25        } *rate_entry, rate_entries[] = {
  26                { 32000,        0x00000000, },
  27                { 44100,        0x01000000, },
  28                { 48000,        0x02000000, },
  29                { 64000,        0x04000000, },
  30                { 88200,        0x05000000, },
  31                { 96000,        0x06000000, },
  32                { 128000,       0x08000000, },
  33                { 176400,       0x09000000, },
  34                { 192000,       0x0a000000, },
  35        };
  36        static const struct {
  37                enum snd_ff_clock_src src;
  38                u32 flag;
  39        } *clk_entry, clk_entries[] = {
  40                { SND_FF_CLOCK_SRC_SPDIF,       0x00000200, },
  41                { SND_FF_CLOCK_SRC_ADAT1,       0x00000400, },
  42                { SND_FF_CLOCK_SRC_WORD,        0x00000600, },
  43                { SND_FF_CLOCK_SRC_INTERNAL,    0x00000e00, },
  44        };
  45        int i;
  46
  47        if (unit_version != SND_FF_UNIT_VERSION_UCX) {
  48                // e.g. 0x00fe0f20 but expected 0x00eff002.
  49                data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4);
  50        }
  51
  52        for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
  53                rate_entry = rate_entries + i;
  54                if ((data & 0x0f000000) == rate_entry->flag) {
  55                        *rate = rate_entry->rate;
  56                        break;
  57                }
  58        }
  59        if (i == ARRAY_SIZE(rate_entries))
  60                return -EIO;
  61
  62        for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
  63                clk_entry = clk_entries + i;
  64                if ((data & 0x000e00) == clk_entry->flag) {
  65                        *src = clk_entry->src;
  66                        break;
  67                }
  68        }
  69        if (i == ARRAY_SIZE(clk_entries))
  70                return -EIO;
  71
  72        return 0;
  73}
  74
  75static int latter_get_clock(struct snd_ff *ff, unsigned int *rate,
  76                           enum snd_ff_clock_src *src)
  77{
  78        __le32 reg;
  79        u32 data;
  80        int err;
  81
  82        err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
  83                                 LATTER_SYNC_STATUS, &reg, sizeof(reg), 0);
  84        if (err < 0)
  85                return err;
  86        data = le32_to_cpu(reg);
  87
  88        return parse_clock_bits(data, rate, src, ff->unit_version);
  89}
  90
  91static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
  92{
  93        u32 data;
  94        __le32 reg;
  95
  96        if (enable)
  97                data = 0x00000000;
  98        else
  99                data = 0xffffffff;
 100        reg = cpu_to_le32(data);
 101
 102        return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 103                                  LATTER_FETCH_MODE, &reg, sizeof(reg), 0);
 104}
 105
 106static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
 107{
 108        enum snd_ff_stream_mode mode;
 109        unsigned int code;
 110        __le32 reg;
 111        unsigned int count;
 112        int i;
 113        int err;
 114
 115        // Set the number of data blocks transferred in a second.
 116        if (rate % 48000 == 0)
 117                code = 0x04;
 118        else if (rate % 44100 == 0)
 119                code = 0x02;
 120        else if (rate % 32000 == 0)
 121                code = 0x00;
 122        else
 123                return -EINVAL;
 124
 125        if (rate >= 64000 && rate < 128000)
 126                code |= 0x08;
 127        else if (rate >= 128000)
 128                code |= 0x10;
 129
 130        reg = cpu_to_le32(code);
 131        err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 132                                 LATTER_STF, &reg, sizeof(reg), 0);
 133        if (err < 0)
 134                return err;
 135
 136        // Confirm to shift transmission clock.
 137        count = 0;
 138        while (count++ < 10) {
 139                unsigned int curr_rate;
 140                enum snd_ff_clock_src src;
 141
 142                err = latter_get_clock(ff, &curr_rate, &src);
 143                if (err < 0)
 144                        return err;
 145
 146                if (curr_rate == rate)
 147                        break;
 148        }
 149        if (count > 10)
 150                return -ETIMEDOUT;
 151
 152        for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) {
 153                if (rate == amdtp_rate_table[i])
 154                        break;
 155        }
 156        if (i == ARRAY_SIZE(amdtp_rate_table))
 157                return -EINVAL;
 158
 159        err = snd_ff_stream_get_multiplier_mode(i, &mode);
 160        if (err < 0)
 161                return err;
 162
 163        // Keep resources for in-stream.
 164        ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
 165        err = fw_iso_resources_allocate(&ff->tx_resources,
 166                        amdtp_stream_get_max_payload(&ff->tx_stream),
 167                        fw_parent_device(ff->unit)->max_speed);
 168        if (err < 0)
 169                return err;
 170
 171        // Keep resources for out-stream.
 172        ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
 173        err = fw_iso_resources_allocate(&ff->rx_resources,
 174                        amdtp_stream_get_max_payload(&ff->rx_stream),
 175                        fw_parent_device(ff->unit)->max_speed);
 176        if (err < 0)
 177                fw_iso_resources_free(&ff->tx_resources);
 178
 179        return err;
 180}
 181
 182static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
 183{
 184        unsigned int generation = ff->rx_resources.generation;
 185        unsigned int flag;
 186        u32 data;
 187        __le32 reg;
 188        int err;
 189
 190        if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {
 191                // For Fireface UCX. Always use the maximum number of data
 192                // channels in data block of packet.
 193                if (rate >= 32000 && rate <= 48000)
 194                        flag = 0x92;
 195                else if (rate >= 64000 && rate <= 96000)
 196                        flag = 0x8e;
 197                else if (rate >= 128000 && rate <= 192000)
 198                        flag = 0x8c;
 199                else
 200                        return -EINVAL;
 201        } else {
 202                // For Fireface UFX and 802. Due to bandwidth limitation on
 203                // IEEE 1394a (400 Mbps), Analog 1-12 and AES are available
 204                // without any ADAT at quadruple speed.
 205                if (rate >= 32000 && rate <= 48000)
 206                        flag = 0x9e;
 207                else if (rate >= 64000 && rate <= 96000)
 208                        flag = 0x96;
 209                else if (rate >= 128000 && rate <= 192000)
 210                        flag = 0x8e;
 211                else
 212                        return -EINVAL;
 213        }
 214
 215        if (generation != fw_parent_device(ff->unit)->card->generation) {
 216                err = fw_iso_resources_update(&ff->tx_resources);
 217                if (err < 0)
 218                        return err;
 219
 220                err = fw_iso_resources_update(&ff->rx_resources);
 221                if (err < 0)
 222                        return err;
 223        }
 224
 225        data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel;
 226        reg = cpu_to_le32(data);
 227        err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 228                                 LATTER_ISOC_CHANNELS, &reg, sizeof(reg), 0);
 229        if (err < 0)
 230                return err;
 231
 232        reg = cpu_to_le32(flag);
 233        return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 234                                  LATTER_ISOC_START, &reg, sizeof(reg), 0);
 235}
 236
 237static void latter_finish_session(struct snd_ff *ff)
 238{
 239        __le32 reg;
 240
 241        reg = cpu_to_le32(0x00000000);
 242        snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 243                           LATTER_ISOC_START, &reg, sizeof(reg), 0);
 244}
 245
 246static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
 247{
 248        static const struct {
 249                char *const label;
 250                u32 locked_mask;
 251                u32 synced_mask;
 252        } *clk_entry, clk_entries[] = {
 253                { "S/PDIF",     0x00000001, 0x00000010, },
 254                { "ADAT",       0x00000002, 0x00000020, },
 255                { "WDClk",      0x00000004, 0x00000040, },
 256        };
 257        __le32 reg;
 258        u32 data;
 259        unsigned int rate;
 260        enum snd_ff_clock_src src;
 261        const char *label;
 262        int i;
 263        int err;
 264
 265        err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
 266                                 LATTER_SYNC_STATUS, &reg, sizeof(reg), 0);
 267        if (err < 0)
 268                return;
 269        data = le32_to_cpu(reg);
 270
 271        snd_iprintf(buffer, "External source detection:\n");
 272
 273        for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
 274                clk_entry = clk_entries + i;
 275                snd_iprintf(buffer, "%s: ", clk_entry->label);
 276                if (data & clk_entry->locked_mask) {
 277                        if (data & clk_entry->synced_mask)
 278                                snd_iprintf(buffer, "sync\n");
 279                        else
 280                                snd_iprintf(buffer, "lock\n");
 281                } else {
 282                        snd_iprintf(buffer, "none\n");
 283                }
 284        }
 285
 286        err = parse_clock_bits(data, &rate, &src, ff->unit_version);
 287        if (err < 0)
 288                return;
 289        label = snd_ff_proc_get_clk_label(src);
 290        if (!label)
 291                return;
 292
 293        snd_iprintf(buffer, "Referred clock: %s %d\n", label, rate);
 294}
 295
 296// NOTE: transactions are transferred within 0x00-0x7f in allocated range of
 297// address. This seems to be for check of discontinuity in receiver side.
 298//
 299// Like Fireface 400, drivers can select one of 4 options for lower 4 bytes of
 300// destination address by bit flags in quadlet register (little endian) at
 301// 0x'ffff'0000'0014:
 302//
 303// bit flags: offset of destination address
 304// - 0x00002000: 0x'....'....'0000'0000
 305// - 0x00004000: 0x'....'....'0000'0080
 306// - 0x00008000: 0x'....'....'0000'0100
 307// - 0x00010000: 0x'....'....'0000'0180
 308//
 309// Drivers can suppress the device to transfer asynchronous transactions by
 310// clear these bit flags.
 311//
 312// Actually, the register is write-only and includes the other settings such as
 313// input attenuation. This driver allocates for the first option
 314// (0x'....'....'0000'0000) and expects userspace application to configure the
 315// register for it.
 316static void latter_handle_midi_msg(struct snd_ff *ff, unsigned int offset,
 317                                   __le32 *buf, size_t length)
 318{
 319        u32 data = le32_to_cpu(*buf);
 320        unsigned int index = (data & 0x000000f0) >> 4;
 321        u8 byte[3];
 322        struct snd_rawmidi_substream *substream;
 323        unsigned int len;
 324
 325        if (index >= ff->spec->midi_in_ports)
 326                return;
 327
 328        switch (data & 0x0000000f) {
 329        case 0x00000008:
 330        case 0x00000009:
 331        case 0x0000000a:
 332        case 0x0000000b:
 333        case 0x0000000e:
 334                len = 3;
 335                break;
 336        case 0x0000000c:
 337        case 0x0000000d:
 338                len = 2;
 339                break;
 340        default:
 341                len = data & 0x00000003;
 342                if (len == 0)
 343                        len = 3;
 344                break;
 345        }
 346
 347        byte[0] = (data & 0x0000ff00) >> 8;
 348        byte[1] = (data & 0x00ff0000) >> 16;
 349        byte[2] = (data & 0xff000000) >> 24;
 350
 351        substream = READ_ONCE(ff->tx_midi_substreams[index]);
 352        if (substream)
 353                snd_rawmidi_receive(substream, byte, len);
 354}
 355
 356/*
 357 * When return minus value, given argument is not MIDI status.
 358 * When return 0, given argument is a beginning of system exclusive.
 359 * When return the others, given argument is MIDI data.
 360 */
 361static inline int calculate_message_bytes(u8 status)
 362{
 363        switch (status) {
 364        case 0xf6:      /* Tune request. */
 365        case 0xf8:      /* Timing clock. */
 366        case 0xfa:      /* Start. */
 367        case 0xfb:      /* Continue. */
 368        case 0xfc:      /* Stop. */
 369        case 0xfe:      /* Active sensing. */
 370        case 0xff:      /* System reset. */
 371                return 1;
 372        case 0xf1:      /* MIDI time code quarter frame. */
 373        case 0xf3:      /* Song select. */
 374                return 2;
 375        case 0xf2:      /* Song position pointer. */
 376                return 3;
 377        case 0xf0:      /* Exclusive. */
 378                return 0;
 379        case 0xf7:      /* End of exclusive. */
 380                break;
 381        case 0xf4:      /* Undefined. */
 382        case 0xf5:      /* Undefined. */
 383        case 0xf9:      /* Undefined. */
 384        case 0xfd:      /* Undefined. */
 385                break;
 386        default:
 387                switch (status & 0xf0) {
 388                case 0x80:      /* Note on. */
 389                case 0x90:      /* Note off. */
 390                case 0xa0:      /* Polyphonic key pressure. */
 391                case 0xb0:      /* Control change and Mode change. */
 392                case 0xe0:      /* Pitch bend change. */
 393                        return 3;
 394                case 0xc0:      /* Program change. */
 395                case 0xd0:      /* Channel pressure. */
 396                        return 2;
 397                default:
 398                break;
 399                }
 400        break;
 401        }
 402
 403        return -EINVAL;
 404}
 405
 406static int latter_fill_midi_msg(struct snd_ff *ff,
 407                                struct snd_rawmidi_substream *substream,
 408                                unsigned int port)
 409{
 410        u32 data = {0};
 411        u8 *buf = (u8 *)&data;
 412        int consumed;
 413
 414        buf[0] = port << 4;
 415        consumed = snd_rawmidi_transmit_peek(substream, buf + 1, 3);
 416        if (consumed <= 0)
 417                return consumed;
 418
 419        if (!ff->on_sysex[port]) {
 420                if (buf[1] != 0xf0) {
 421                        if (consumed < calculate_message_bytes(buf[1]))
 422                                return 0;
 423                } else {
 424                        // The beginning of exclusives.
 425                        ff->on_sysex[port] = true;
 426                }
 427
 428                buf[0] |= consumed;
 429        } else {
 430                if (buf[1] != 0xf7) {
 431                        if (buf[2] == 0xf7 || buf[3] == 0xf7) {
 432                                // Transfer end code at next time.
 433                                consumed -= 1;
 434                        }
 435
 436                        buf[0] |= consumed;
 437                } else {
 438                        // The end of exclusives.
 439                        ff->on_sysex[port] = false;
 440                        consumed = 1;
 441                        buf[0] |= 0x0f;
 442                }
 443        }
 444
 445        ff->msg_buf[port][0] = cpu_to_le32(data);
 446        ff->rx_bytes[port] = consumed;
 447
 448        return 1;
 449}
 450
 451const struct snd_ff_protocol snd_ff_protocol_latter = {
 452        .handle_midi_msg        = latter_handle_midi_msg,
 453        .fill_midi_msg          = latter_fill_midi_msg,
 454        .get_clock              = latter_get_clock,
 455        .switch_fetching_mode   = latter_switch_fetching_mode,
 456        .allocate_resources     = latter_allocate_resources,
 457        .begin_session          = latter_begin_session,
 458        .finish_session         = latter_finish_session,
 459        .dump_status            = latter_dump_status,
 460};
 461