linux/sound/firewire/oxfw/oxfw-stream.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * oxfw_stream.c - a part of driver for OXFW970/971 based devices
   4 *
   5 * Copyright (c) 2014 Takashi Sakamoto
   6 */
   7
   8#include "oxfw.h"
   9#include <linux/delay.h>
  10
  11#define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512
  12#define CALLBACK_TIMEOUT        200
  13
  14/*
  15 * According to datasheet of Oxford Semiconductor:
  16 *  OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O
  17 *  OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O
  18 */
  19static const unsigned int oxfw_rate_table[] = {
  20        [0] = 32000,
  21        [1] = 44100,
  22        [2] = 48000,
  23        [3] = 88200,
  24        [4] = 96000,
  25        [5] = 192000,
  26};
  27
  28/*
  29 * See Table 5.7 – Sampling frequency for Multi-bit Audio
  30 * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
  31 */
  32static const unsigned int avc_stream_rate_table[] = {
  33        [0] = 0x02,
  34        [1] = 0x03,
  35        [2] = 0x04,
  36        [3] = 0x0a,
  37        [4] = 0x05,
  38        [5] = 0x07,
  39};
  40
  41static int set_rate(struct snd_oxfw *oxfw, unsigned int rate)
  42{
  43        int err;
  44
  45        err = avc_general_set_sig_fmt(oxfw->unit, rate,
  46                                      AVC_GENERAL_PLUG_DIR_IN, 0);
  47        if (err < 0)
  48                goto end;
  49
  50        if (oxfw->has_output)
  51                err = avc_general_set_sig_fmt(oxfw->unit, rate,
  52                                              AVC_GENERAL_PLUG_DIR_OUT, 0);
  53end:
  54        return err;
  55}
  56
  57static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s,
  58                             unsigned int rate, unsigned int pcm_channels)
  59{
  60        u8 **formats;
  61        struct snd_oxfw_stream_formation formation;
  62        enum avc_general_plug_dir dir;
  63        unsigned int len;
  64        int i, err;
  65
  66        if (s == &oxfw->tx_stream) {
  67                formats = oxfw->tx_stream_formats;
  68                dir = AVC_GENERAL_PLUG_DIR_OUT;
  69        } else {
  70                formats = oxfw->rx_stream_formats;
  71                dir = AVC_GENERAL_PLUG_DIR_IN;
  72        }
  73
  74        /* Seek stream format for requirements. */
  75        for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
  76                err = snd_oxfw_stream_parse_format(formats[i], &formation);
  77                if (err < 0)
  78                        return err;
  79
  80                if ((formation.rate == rate) && (formation.pcm == pcm_channels))
  81                        break;
  82        }
  83        if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
  84                return -EINVAL;
  85
  86        /* If assumed, just change rate. */
  87        if (oxfw->assumed)
  88                return set_rate(oxfw, rate);
  89
  90        /* Calculate format length. */
  91        len = 5 + formats[i][4] * 2;
  92
  93        err = avc_stream_set_format(oxfw->unit, dir, 0, formats[i], len);
  94        if (err < 0)
  95                return err;
  96
  97        /* Some requests just after changing format causes freezing. */
  98        msleep(100);
  99
 100        return 0;
 101}
 102
 103static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
 104{
 105        struct cmp_connection *conn;
 106        int err;
 107
 108        if (stream == &oxfw->rx_stream)
 109                conn = &oxfw->in_conn;
 110        else
 111                conn = &oxfw->out_conn;
 112
 113        err = cmp_connection_establish(conn);
 114        if (err < 0)
 115                return err;
 116
 117        err = amdtp_domain_add_stream(&oxfw->domain, stream,
 118                                      conn->resources.channel, conn->speed);
 119        if (err < 0) {
 120                cmp_connection_break(conn);
 121                return err;
 122        }
 123
 124        return 0;
 125}
 126
 127static int check_connection_used_by_others(struct snd_oxfw *oxfw,
 128                                           struct amdtp_stream *stream)
 129{
 130        struct cmp_connection *conn;
 131        bool used;
 132        int err;
 133
 134        if (stream == &oxfw->tx_stream)
 135                conn = &oxfw->out_conn;
 136        else
 137                conn = &oxfw->in_conn;
 138
 139        err = cmp_connection_check_used(conn, &used);
 140        if ((err >= 0) && used && !amdtp_stream_running(stream)) {
 141                dev_err(&oxfw->unit->device,
 142                        "Connection established by others: %cPCR[%d]\n",
 143                        (conn->direction == CMP_OUTPUT) ? 'o' : 'i',
 144                        conn->pcr_index);
 145                err = -EBUSY;
 146        }
 147
 148        return err;
 149}
 150
 151static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
 152{
 153        struct cmp_connection *conn;
 154        enum cmp_direction c_dir;
 155        enum amdtp_stream_direction s_dir;
 156        int err;
 157
 158        if (stream == &oxfw->tx_stream) {
 159                conn = &oxfw->out_conn;
 160                c_dir = CMP_OUTPUT;
 161                s_dir = AMDTP_IN_STREAM;
 162        } else {
 163                conn = &oxfw->in_conn;
 164                c_dir = CMP_INPUT;
 165                s_dir = AMDTP_OUT_STREAM;
 166        }
 167
 168        err = cmp_connection_init(conn, oxfw->unit, c_dir, 0);
 169        if (err < 0)
 170                return err;
 171
 172        err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
 173        if (err < 0) {
 174                cmp_connection_destroy(conn);
 175                return err;
 176        }
 177
 178        /*
 179         * OXFW starts to transmit packets with non-zero dbc.
 180         * OXFW postpone transferring packets till handling any asynchronous
 181         * packets. As a result, next isochronous packet includes more data
 182         * blocks than IEC 61883-6 defines.
 183         */
 184        if (stream == &oxfw->tx_stream) {
 185                oxfw->tx_stream.flags |= CIP_JUMBO_PAYLOAD;
 186                if (oxfw->wrong_dbs)
 187                        oxfw->tx_stream.flags |= CIP_WRONG_DBS;
 188        }
 189
 190        return 0;
 191}
 192
 193static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
 194{
 195        enum avc_general_plug_dir dir;
 196        u8 **formats;
 197        struct snd_oxfw_stream_formation formation;
 198        struct cmp_connection *conn;
 199        int i;
 200        int err;
 201
 202        if (stream == &oxfw->rx_stream) {
 203                dir = AVC_GENERAL_PLUG_DIR_IN;
 204                formats = oxfw->rx_stream_formats;
 205                conn = &oxfw->in_conn;
 206        } else {
 207                dir = AVC_GENERAL_PLUG_DIR_OUT;
 208                formats = oxfw->tx_stream_formats;
 209                conn = &oxfw->out_conn;
 210        }
 211
 212        err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
 213        if (err < 0)
 214                return err;
 215
 216        for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
 217                struct snd_oxfw_stream_formation fmt;
 218
 219                if (formats[i] == NULL)
 220                        break;
 221
 222                err = snd_oxfw_stream_parse_format(formats[i], &fmt);
 223                if (err < 0)
 224                        return err;
 225
 226                if (fmt.rate == formation.rate && fmt.pcm == formation.pcm &&
 227                    fmt.midi == formation.midi)
 228                        break;
 229        }
 230        if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
 231                return -EINVAL;
 232
 233        // The stream should have one pcm channels at least.
 234        if (formation.pcm == 0)
 235                return -EINVAL;
 236
 237        err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm,
 238                                         formation.midi * 8, false);
 239        if (err < 0)
 240                return err;
 241
 242        return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream));
 243}
 244
 245int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
 246                                   struct amdtp_stream *stream,
 247                                   unsigned int rate, unsigned int pcm_channels,
 248                                   unsigned int frames_per_period,
 249                                   unsigned int frames_per_buffer)
 250{
 251        struct snd_oxfw_stream_formation formation;
 252        enum avc_general_plug_dir dir;
 253        int err;
 254
 255        // Considering JACK/FFADO streaming:
 256        // TODO: This can be removed hwdep functionality becomes popular.
 257        err = check_connection_used_by_others(oxfw, &oxfw->rx_stream);
 258        if (err < 0)
 259                return err;
 260        if (oxfw->has_output) {
 261                err = check_connection_used_by_others(oxfw, &oxfw->tx_stream);
 262                if (err < 0)
 263                        return err;
 264        }
 265
 266        if (stream == &oxfw->tx_stream)
 267                dir = AVC_GENERAL_PLUG_DIR_OUT;
 268        else
 269                dir = AVC_GENERAL_PLUG_DIR_IN;
 270
 271        err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
 272        if (err < 0)
 273                return err;
 274        if (rate == 0) {
 275                rate = formation.rate;
 276                pcm_channels = formation.pcm;
 277        }
 278        if (formation.rate != rate || formation.pcm != pcm_channels) {
 279                amdtp_domain_stop(&oxfw->domain);
 280
 281                cmp_connection_break(&oxfw->in_conn);
 282                cmp_connection_release(&oxfw->in_conn);
 283
 284                if (oxfw->has_output) {
 285                        cmp_connection_break(&oxfw->out_conn);
 286                        cmp_connection_release(&oxfw->out_conn);
 287                }
 288        }
 289
 290        if (oxfw->substreams_count == 0 ||
 291            formation.rate != rate || formation.pcm != pcm_channels) {
 292                err = set_stream_format(oxfw, stream, rate, pcm_channels);
 293                if (err < 0) {
 294                        dev_err(&oxfw->unit->device,
 295                                "fail to set stream format: %d\n", err);
 296                        return err;
 297                }
 298
 299                err = keep_resources(oxfw, &oxfw->rx_stream);
 300                if (err < 0)
 301                        return err;
 302
 303                if (oxfw->has_output) {
 304                        err = keep_resources(oxfw, &oxfw->tx_stream);
 305                        if (err < 0) {
 306                                cmp_connection_release(&oxfw->in_conn);
 307                                return err;
 308                        }
 309                }
 310
 311                err = amdtp_domain_set_events_per_period(&oxfw->domain,
 312                                        frames_per_period, frames_per_buffer);
 313                if (err < 0) {
 314                        cmp_connection_release(&oxfw->in_conn);
 315                        if (oxfw->has_output)
 316                                cmp_connection_release(&oxfw->out_conn);
 317                        return err;
 318                }
 319        }
 320
 321        return 0;
 322}
 323
 324int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
 325{
 326        int err;
 327
 328        if (oxfw->substreams_count == 0)
 329                return -EIO;
 330
 331        if (amdtp_streaming_error(&oxfw->rx_stream) ||
 332            amdtp_streaming_error(&oxfw->tx_stream)) {
 333                amdtp_domain_stop(&oxfw->domain);
 334
 335                cmp_connection_break(&oxfw->in_conn);
 336                if (oxfw->has_output)
 337                        cmp_connection_break(&oxfw->out_conn);
 338        }
 339
 340        if (!amdtp_stream_running(&oxfw->rx_stream)) {
 341                err = start_stream(oxfw, &oxfw->rx_stream);
 342                if (err < 0) {
 343                        dev_err(&oxfw->unit->device,
 344                                "fail to prepare rx stream: %d\n", err);
 345                        goto error;
 346                }
 347
 348                if (oxfw->has_output &&
 349                    !amdtp_stream_running(&oxfw->tx_stream)) {
 350                        err = start_stream(oxfw, &oxfw->tx_stream);
 351                        if (err < 0) {
 352                                dev_err(&oxfw->unit->device,
 353                                        "fail to prepare tx stream: %d\n", err);
 354                                goto error;
 355                        }
 356                }
 357
 358                err = amdtp_domain_start(&oxfw->domain, 0);
 359                if (err < 0)
 360                        goto error;
 361
 362                // Wait first packet.
 363                if (!amdtp_stream_wait_callback(&oxfw->rx_stream,
 364                                                CALLBACK_TIMEOUT)) {
 365                        err = -ETIMEDOUT;
 366                        goto error;
 367                }
 368
 369                if (oxfw->has_output) {
 370                        if (!amdtp_stream_wait_callback(&oxfw->tx_stream,
 371                                                        CALLBACK_TIMEOUT)) {
 372                                err = -ETIMEDOUT;
 373                                goto error;
 374                        }
 375                }
 376        }
 377
 378        return 0;
 379error:
 380        amdtp_domain_stop(&oxfw->domain);
 381
 382        cmp_connection_break(&oxfw->in_conn);
 383        if (oxfw->has_output)
 384                cmp_connection_break(&oxfw->out_conn);
 385
 386        return err;
 387}
 388
 389void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw)
 390{
 391        if (oxfw->substreams_count == 0) {
 392                amdtp_domain_stop(&oxfw->domain);
 393
 394                cmp_connection_break(&oxfw->in_conn);
 395                cmp_connection_release(&oxfw->in_conn);
 396
 397                if (oxfw->has_output) {
 398                        cmp_connection_break(&oxfw->out_conn);
 399                        cmp_connection_release(&oxfw->out_conn);
 400                }
 401        }
 402}
 403
 404static void destroy_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
 405{
 406        struct cmp_connection *conn;
 407
 408        if (stream == &oxfw->tx_stream)
 409                conn = &oxfw->out_conn;
 410        else
 411                conn = &oxfw->in_conn;
 412
 413        amdtp_stream_destroy(stream);
 414        cmp_connection_destroy(conn);
 415}
 416
 417int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw)
 418{
 419        int err;
 420
 421        err = init_stream(oxfw, &oxfw->rx_stream);
 422        if (err < 0)
 423                return err;
 424
 425        if (oxfw->has_output) {
 426                err = init_stream(oxfw, &oxfw->tx_stream);
 427                if (err < 0) {
 428                        destroy_stream(oxfw, &oxfw->rx_stream);
 429                        return err;
 430                }
 431        }
 432
 433        err = amdtp_domain_init(&oxfw->domain);
 434        if (err < 0) {
 435                destroy_stream(oxfw, &oxfw->rx_stream);
 436                if (oxfw->has_output)
 437                        destroy_stream(oxfw, &oxfw->tx_stream);
 438        }
 439
 440        return err;
 441}
 442
 443// This function should be called before starting the stream or after stopping
 444// the streams.
 445void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw)
 446{
 447        amdtp_domain_destroy(&oxfw->domain);
 448
 449        destroy_stream(oxfw, &oxfw->rx_stream);
 450
 451        if (oxfw->has_output)
 452                destroy_stream(oxfw, &oxfw->tx_stream);
 453}
 454
 455void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw)
 456{
 457        amdtp_domain_stop(&oxfw->domain);
 458
 459        cmp_connection_break(&oxfw->in_conn);
 460
 461        amdtp_stream_pcm_abort(&oxfw->rx_stream);
 462
 463        if (oxfw->has_output) {
 464                cmp_connection_break(&oxfw->out_conn);
 465
 466                amdtp_stream_pcm_abort(&oxfw->tx_stream);
 467        }
 468}
 469
 470int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
 471                                enum avc_general_plug_dir dir,
 472                                struct snd_oxfw_stream_formation *formation)
 473{
 474        u8 *format;
 475        unsigned int len;
 476        int err;
 477
 478        len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
 479        format = kmalloc(len, GFP_KERNEL);
 480        if (format == NULL)
 481                return -ENOMEM;
 482
 483        err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
 484        if (err < 0)
 485                goto end;
 486        if (len < 3) {
 487                err = -EIO;
 488                goto end;
 489        }
 490
 491        err = snd_oxfw_stream_parse_format(format, formation);
 492end:
 493        kfree(format);
 494        return err;
 495}
 496
 497/*
 498 * See Table 6.16 - AM824 Stream Format
 499 *     Figure 6.19 - format_information field for AM824 Compound
 500 * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
 501 * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
 502 */
 503int snd_oxfw_stream_parse_format(u8 *format,
 504                                 struct snd_oxfw_stream_formation *formation)
 505{
 506        unsigned int i, e, channels, type;
 507
 508        memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
 509
 510        /*
 511         * this module can support a hierarchy combination that:
 512         *  Root:       Audio and Music (0x90)
 513         *  Level 1:    AM824 Compound  (0x40)
 514         */
 515        if ((format[0] != 0x90) || (format[1] != 0x40))
 516                return -ENXIO;
 517
 518        /* check the sampling rate */
 519        for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
 520                if (format[2] == avc_stream_rate_table[i])
 521                        break;
 522        }
 523        if (i == ARRAY_SIZE(avc_stream_rate_table))
 524                return -ENXIO;
 525
 526        formation->rate = oxfw_rate_table[i];
 527
 528        for (e = 0; e < format[4]; e++) {
 529                channels = format[5 + e * 2];
 530                type = format[6 + e * 2];
 531
 532                switch (type) {
 533                /* IEC 60958 Conformant, currently handled as MBLA */
 534                case 0x00:
 535                /* Multi Bit Linear Audio (Raw) */
 536                case 0x06:
 537                        formation->pcm += channels;
 538                        break;
 539                /* MIDI Conformant */
 540                case 0x0d:
 541                        formation->midi = channels;
 542                        break;
 543                /* IEC 61937-3 to 7 */
 544                case 0x01:
 545                case 0x02:
 546                case 0x03:
 547                case 0x04:
 548                case 0x05:
 549                /* Multi Bit Linear Audio */
 550                case 0x07:      /* DVD-Audio */
 551                case 0x0c:      /* High Precision */
 552                /* One Bit Audio */
 553                case 0x08:      /* (Plain) Raw */
 554                case 0x09:      /* (Plain) SACD */
 555                case 0x0a:      /* (Encoded) Raw */
 556                case 0x0b:      /* (Encoded) SACD */
 557                /* SMPTE Time-Code conformant */
 558                case 0x0e:
 559                /* Sample Count */
 560                case 0x0f:
 561                /* Anciliary Data */
 562                case 0x10:
 563                /* Synchronization Stream (Stereo Raw audio) */
 564                case 0x40:
 565                /* Don't care */
 566                case 0xff:
 567                default:
 568                        return -ENXIO;  /* not supported */
 569                }
 570        }
 571
 572        if (formation->pcm  > AM824_MAX_CHANNELS_FOR_PCM ||
 573            formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
 574                return -ENXIO;
 575
 576        return 0;
 577}
 578
 579static int
 580assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
 581                      unsigned int pid, u8 *buf, unsigned int *len,
 582                      u8 **formats)
 583{
 584        struct snd_oxfw_stream_formation formation;
 585        unsigned int i, eid;
 586        int err;
 587
 588        /* get format at current sampling rate */
 589        err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
 590        if (err < 0) {
 591                dev_err(&oxfw->unit->device,
 592                "fail to get current stream format for isoc %s plug %d:%d\n",
 593                        (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
 594                        pid, err);
 595                goto end;
 596        }
 597
 598        /* parse and set stream format */
 599        eid = 0;
 600        err = snd_oxfw_stream_parse_format(buf, &formation);
 601        if (err < 0)
 602                goto end;
 603
 604        formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
 605                                    GFP_KERNEL);
 606        if (!formats[eid]) {
 607                err = -ENOMEM;
 608                goto end;
 609        }
 610
 611        /* apply the format for each available sampling rate */
 612        for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
 613                if (formation.rate == oxfw_rate_table[i])
 614                        continue;
 615
 616                err = avc_general_inquiry_sig_fmt(oxfw->unit,
 617                                                  oxfw_rate_table[i],
 618                                                  dir, pid);
 619                if (err < 0)
 620                        continue;
 621
 622                eid++;
 623                formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
 624                                            GFP_KERNEL);
 625                if (formats[eid] == NULL) {
 626                        err = -ENOMEM;
 627                        goto end;
 628                }
 629                formats[eid][2] = avc_stream_rate_table[i];
 630        }
 631
 632        err = 0;
 633        oxfw->assumed = true;
 634end:
 635        return err;
 636}
 637
 638static int fill_stream_formats(struct snd_oxfw *oxfw,
 639                               enum avc_general_plug_dir dir,
 640                               unsigned short pid)
 641{
 642        u8 *buf, **formats;
 643        unsigned int len, eid = 0;
 644        struct snd_oxfw_stream_formation dummy;
 645        int err;
 646
 647        buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
 648        if (buf == NULL)
 649                return -ENOMEM;
 650
 651        if (dir == AVC_GENERAL_PLUG_DIR_OUT)
 652                formats = oxfw->tx_stream_formats;
 653        else
 654                formats = oxfw->rx_stream_formats;
 655
 656        /* get first entry */
 657        len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
 658        err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
 659        if (err == -ENXIO) {
 660                /* LIST subfunction is not implemented */
 661                len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
 662                err = assume_stream_formats(oxfw, dir, pid, buf, &len,
 663                                            formats);
 664                goto end;
 665        } else if (err < 0) {
 666                dev_err(&oxfw->unit->device,
 667                        "fail to get stream format %d for isoc %s plug %d:%d\n",
 668                        eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
 669                        pid, err);
 670                goto end;
 671        }
 672
 673        /* LIST subfunction is implemented */
 674        while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
 675                /* The format is too short. */
 676                if (len < 3) {
 677                        err = -EIO;
 678                        break;
 679                }
 680
 681                /* parse and set stream format */
 682                err = snd_oxfw_stream_parse_format(buf, &dummy);
 683                if (err < 0)
 684                        break;
 685
 686                formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, len,
 687                                            GFP_KERNEL);
 688                if (!formats[eid]) {
 689                        err = -ENOMEM;
 690                        break;
 691                }
 692
 693                /* get next entry */
 694                len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
 695                err = avc_stream_get_format_list(oxfw->unit, dir, 0,
 696                                                 buf, &len, ++eid);
 697                /* No entries remained. */
 698                if (err == -EINVAL) {
 699                        err = 0;
 700                        break;
 701                } else if (err < 0) {
 702                        dev_err(&oxfw->unit->device,
 703                        "fail to get stream format %d for isoc %s plug %d:%d\n",
 704                                eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
 705                                                                        "out",
 706                                pid, err);
 707                        break;
 708                }
 709        }
 710end:
 711        kfree(buf);
 712        return err;
 713}
 714
 715int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
 716{
 717        u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
 718        struct snd_oxfw_stream_formation formation;
 719        u8 *format;
 720        unsigned int i;
 721        int err;
 722
 723        /* the number of plugs for isoc in/out, ext in/out  */
 724        err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
 725        if (err < 0) {
 726                dev_err(&oxfw->unit->device,
 727                "fail to get info for isoc/external in/out plugs: %d\n",
 728                        err);
 729                goto end;
 730        } else if ((plugs[0] == 0) && (plugs[1] == 0)) {
 731                err = -ENXIO;
 732                goto end;
 733        }
 734
 735        /* use oPCR[0] if exists */
 736        if (plugs[1] > 0) {
 737                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
 738                if (err < 0) {
 739                        if (err != -ENXIO)
 740                                return err;
 741
 742                        // The oPCR is not available for isoc communication.
 743                        err = 0;
 744                } else {
 745                        for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
 746                                format = oxfw->tx_stream_formats[i];
 747                                if (format == NULL)
 748                                        continue;
 749                                err = snd_oxfw_stream_parse_format(format,
 750                                                                   &formation);
 751                                if (err < 0)
 752                                        continue;
 753
 754                                /* Add one MIDI port. */
 755                                if (formation.midi > 0)
 756                                        oxfw->midi_input_ports = 1;
 757                        }
 758
 759                        oxfw->has_output = true;
 760                }
 761        }
 762
 763        /* use iPCR[0] if exists */
 764        if (plugs[0] > 0) {
 765                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
 766                if (err < 0) {
 767                        if (err != -ENXIO)
 768                                return err;
 769
 770                        // The iPCR is not available for isoc communication.
 771                        err = 0;
 772                } else {
 773                        for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
 774                                format = oxfw->rx_stream_formats[i];
 775                                if (format == NULL)
 776                                        continue;
 777                                err = snd_oxfw_stream_parse_format(format,
 778                                                                   &formation);
 779                                if (err < 0)
 780                                        continue;
 781
 782                                /* Add one MIDI port. */
 783                                if (formation.midi > 0)
 784                                        oxfw->midi_output_ports = 1;
 785                        }
 786
 787                        oxfw->has_input = true;
 788                }
 789        }
 790end:
 791        return err;
 792}
 793
 794void snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw)
 795{
 796        oxfw->dev_lock_changed = true;
 797        wake_up(&oxfw->hwdep_wait);
 798}
 799
 800int snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw)
 801{
 802        int err;
 803
 804        spin_lock_irq(&oxfw->lock);
 805
 806        /* user land lock this */
 807        if (oxfw->dev_lock_count < 0) {
 808                err = -EBUSY;
 809                goto end;
 810        }
 811
 812        /* this is the first time */
 813        if (oxfw->dev_lock_count++ == 0)
 814                snd_oxfw_stream_lock_changed(oxfw);
 815        err = 0;
 816end:
 817        spin_unlock_irq(&oxfw->lock);
 818        return err;
 819}
 820
 821void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw)
 822{
 823        spin_lock_irq(&oxfw->lock);
 824
 825        if (WARN_ON(oxfw->dev_lock_count <= 0))
 826                goto end;
 827        if (--oxfw->dev_lock_count == 0)
 828                snd_oxfw_stream_lock_changed(oxfw);
 829end:
 830        spin_unlock_irq(&oxfw->lock);
 831}
 832