Commit 31ef9134eb52636d383a7d0626cbbd345cb94f2f

Authored by Clemens Ladisch
Committed by Takashi Iwai
1 parent a5abba989d

ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver

Add a driver for two playback-only FireWire devices based on the OXFW970
chip.

v2: better AMDTP API abstraction; fix fw_unit leak; small fixes
v3: cache the iPCR value
v4: FireWave constraints; fix fw_device reference counting;
    fix PCR caching; small changes and fixes
v5: volume/mute support; fix crashing due to pcm stop races
v6: fix build; one-channel volume for LaCie
v7: use signed values to make volume (range checks) work; fix function
    block IDs for volume/mute; always use channel 0 for LaCie volume

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Tested-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

Showing 20 changed files with 2651 additions and 4 deletions Side-by-side Diff

drivers/firewire/core-iso.c
... ... @@ -362,4 +362,5 @@
362 362 *channel = ret;
363 363 }
364 364 }
  365 +EXPORT_SYMBOL(fw_iso_resource_manage);
drivers/firewire/core.h
... ... @@ -147,9 +147,6 @@
147 147 /* -iso */
148 148  
149 149 int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
150   -void fw_iso_resource_manage(struct fw_card *card, int generation,
151   - u64 channels_mask, int *channel, int *bandwidth,
152   - bool allocate, __be32 buffer[2]);
153 150  
154 151  
155 152 /* -topology */
include/linux/firewire.h
... ... @@ -42,6 +42,10 @@
42 42 #define CSR_BROADCAST_CHANNEL 0x234
43 43 #define CSR_CONFIG_ROM 0x400
44 44 #define CSR_CONFIG_ROM_END 0x800
  45 +#define CSR_OMPR 0x900
  46 +#define CSR_OPCR(i) (0x904 + (i) * 4)
  47 +#define CSR_IMPR 0x980
  48 +#define CSR_IPCR(i) (0x984 + (i) * 4)
45 49 #define CSR_FCP_COMMAND 0xB00
46 50 #define CSR_FCP_RESPONSE 0xD00
47 51 #define CSR_FCP_END 0xF00
... ... @@ -441,6 +445,9 @@
441 445 int cycle, int sync, int tags);
442 446 int fw_iso_context_stop(struct fw_iso_context *ctx);
443 447 void fw_iso_context_destroy(struct fw_iso_context *ctx);
  448 +void fw_iso_resource_manage(struct fw_card *card, int generation,
  449 + u64 channels_mask, int *channel, int *bandwidth,
  450 + bool allocate, __be32 buffer[2]);
444 451  
445 452 #endif /* _LINUX_FIREWIRE_H */
... ... @@ -97,6 +97,8 @@
97 97 # here assuming USB is defined before ALSA
98 98 source "sound/usb/Kconfig"
99 99  
  100 +source "sound/firewire/Kconfig"
  101 +
100 102 # the following will depend on the order of config.
101 103 # here assuming PCMCIA is defined before ALSA
102 104 source "sound/pcmcia/Kconfig"
... ... @@ -6,7 +6,7 @@
6 6 obj-$(CONFIG_SOUND_PRIME) += oss/
7 7 obj-$(CONFIG_DMASOUND) += oss/
8 8 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
9   - sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
  9 + firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
10 10 obj-$(CONFIG_SND_AOA) += aoa/
11 11  
12 12 # This one must be compilable even if sound is configured out
sound/firewire/Kconfig
  1 +menuconfig SND_FIREWIRE
  2 + bool "FireWire sound devices"
  3 + depends on FIREWIRE
  4 + default y
  5 + help
  6 + Support for IEEE-1394/FireWire/iLink sound devices.
  7 +
  8 +if SND_FIREWIRE && FIREWIRE
  9 +
  10 +config SND_FIREWIRE_LIB
  11 + tristate
  12 + depends on SND_PCM
  13 +
  14 +config SND_FIREWIRE_SPEAKERS
  15 + tristate "FireWire speakers"
  16 + select SND_PCM
  17 + select SND_FIREWIRE_LIB
  18 + help
  19 + Say Y here to include support for the Griffin FireWave Surround
  20 + and the LaCie FireWire Speakers.
  21 +
  22 + To compile this driver as a module, choose M here: the module
  23 + will be called snd-firewire-speakers.
  24 +
  25 +endif # SND_FIREWIRE
sound/firewire/Makefile
  1 +snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
  2 + fcp.o cmp.o amdtp.o
  3 +snd-firewire-speakers-objs := speakers.o
  4 +
  5 +obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
  6 +obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
sound/firewire/amdtp.c
  1 +/*
  2 + * Audio and Music Data Transmission Protocol (IEC 61883-6) streams
  3 + * with Common Isochronous Packet (IEC 61883-1) headers
  4 + *
  5 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  6 + * Licensed under the terms of the GNU General Public License, version 2.
  7 + */
  8 +
  9 +#include <linux/device.h>
  10 +#include <linux/err.h>
  11 +#include <linux/firewire.h>
  12 +#include <linux/module.h>
  13 +#include <linux/slab.h>
  14 +#include <sound/pcm.h>
  15 +#include "amdtp.h"
  16 +
  17 +#define TICKS_PER_CYCLE 3072
  18 +#define CYCLES_PER_SECOND 8000
  19 +#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND)
  20 +
  21 +#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 ยตs */
  22 +
  23 +#define TAG_CIP 1
  24 +
  25 +#define CIP_EOH (1u << 31)
  26 +#define CIP_FMT_AM (0x10 << 24)
  27 +#define AMDTP_FDF_AM824 (0 << 19)
  28 +#define AMDTP_FDF_SFC_SHIFT 16
  29 +
  30 +/* TODO: make these configurable */
  31 +#define INTERRUPT_INTERVAL 16
  32 +#define QUEUE_LENGTH 48
  33 +
  34 +/**
  35 + * amdtp_out_stream_init - initialize an AMDTP output stream structure
  36 + * @s: the AMDTP output stream to initialize
  37 + * @unit: the target of the stream
  38 + * @flags: the packet transmission method to use
  39 + */
  40 +int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
  41 + enum cip_out_flags flags)
  42 +{
  43 + if (flags != CIP_NONBLOCKING)
  44 + return -EINVAL;
  45 +
  46 + s->unit = fw_unit_get(unit);
  47 + s->flags = flags;
  48 + s->context = ERR_PTR(-1);
  49 + mutex_init(&s->mutex);
  50 +
  51 + return 0;
  52 +}
  53 +EXPORT_SYMBOL(amdtp_out_stream_init);
  54 +
  55 +/**
  56 + * amdtp_out_stream_destroy - free stream resources
  57 + * @s: the AMDTP output stream to destroy
  58 + */
  59 +void amdtp_out_stream_destroy(struct amdtp_out_stream *s)
  60 +{
  61 + WARN_ON(!IS_ERR(s->context));
  62 + mutex_destroy(&s->mutex);
  63 + fw_unit_put(s->unit);
  64 +}
  65 +EXPORT_SYMBOL(amdtp_out_stream_destroy);
  66 +
  67 +/**
  68 + * amdtp_out_stream_set_rate - set the sample rate
  69 + * @s: the AMDTP output stream to configure
  70 + * @rate: the sample rate
  71 + *
  72 + * The sample rate must be set before the stream is started, and must not be
  73 + * changed while the stream is running.
  74 + */
  75 +void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate)
  76 +{
  77 + static const struct {
  78 + unsigned int rate;
  79 + unsigned int syt_interval;
  80 + } rate_info[] = {
  81 + [CIP_SFC_32000] = { 32000, 8, },
  82 + [CIP_SFC_44100] = { 44100, 8, },
  83 + [CIP_SFC_48000] = { 48000, 8, },
  84 + [CIP_SFC_88200] = { 88200, 16, },
  85 + [CIP_SFC_96000] = { 96000, 16, },
  86 + [CIP_SFC_176400] = { 176400, 32, },
  87 + [CIP_SFC_192000] = { 192000, 32, },
  88 + };
  89 + unsigned int sfc;
  90 +
  91 + if (WARN_ON(!IS_ERR(s->context)))
  92 + return;
  93 +
  94 + for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc)
  95 + if (rate_info[sfc].rate == rate) {
  96 + s->sfc = sfc;
  97 + s->syt_interval = rate_info[sfc].syt_interval;
  98 + return;
  99 + }
  100 + WARN_ON(1);
  101 +}
  102 +EXPORT_SYMBOL(amdtp_out_stream_set_rate);
  103 +
  104 +/**
  105 + * amdtp_out_stream_get_max_payload - get the stream's packet size
  106 + * @s: the AMDTP output stream
  107 + *
  108 + * This function must not be called before the stream has been configured
  109 + * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
  110 + * amdtp_out_stream_set_midi().
  111 + */
  112 +unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
  113 +{
  114 + static const unsigned int max_data_blocks[] = {
  115 + [CIP_SFC_32000] = 4,
  116 + [CIP_SFC_44100] = 6,
  117 + [CIP_SFC_48000] = 6,
  118 + [CIP_SFC_88200] = 12,
  119 + [CIP_SFC_96000] = 12,
  120 + [CIP_SFC_176400] = 23,
  121 + [CIP_SFC_192000] = 24,
  122 + };
  123 +
  124 + s->data_block_quadlets = s->pcm_channels;
  125 + s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
  126 +
  127 + return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets;
  128 +}
  129 +EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
  130 +
  131 +static void amdtp_write_s16(struct amdtp_out_stream *s,
  132 + struct snd_pcm_substream *pcm,
  133 + __be32 *buffer, unsigned int frames);
  134 +static void amdtp_write_s32(struct amdtp_out_stream *s,
  135 + struct snd_pcm_substream *pcm,
  136 + __be32 *buffer, unsigned int frames);
  137 +
  138 +/**
  139 + * amdtp_out_stream_set_pcm_format - set the PCM format
  140 + * @s: the AMDTP output stream to configure
  141 + * @format: the format of the ALSA PCM device
  142 + *
  143 + * The sample format must be set before the stream is started, and must not be
  144 + * changed while the stream is running.
  145 + */
  146 +void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
  147 + snd_pcm_format_t format)
  148 +{
  149 + if (WARN_ON(!IS_ERR(s->context)))
  150 + return;
  151 +
  152 + switch (format) {
  153 + default:
  154 + WARN_ON(1);
  155 + /* fall through */
  156 + case SNDRV_PCM_FORMAT_S16:
  157 + s->transfer_samples = amdtp_write_s16;
  158 + break;
  159 + case SNDRV_PCM_FORMAT_S32:
  160 + s->transfer_samples = amdtp_write_s32;
  161 + break;
  162 + }
  163 +}
  164 +EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format);
  165 +
  166 +static unsigned int calculate_data_blocks(struct amdtp_out_stream *s)
  167 +{
  168 + unsigned int phase, data_blocks;
  169 +
  170 + if (!cip_sfc_is_base_44100(s->sfc)) {
  171 + /* Sample_rate / 8000 is an integer, and precomputed. */
  172 + data_blocks = s->data_block_state;
  173 + } else {
  174 + phase = s->data_block_state;
  175 +
  176 + /*
  177 + * This calculates the number of data blocks per packet so that
  178 + * 1) the overall rate is correct and exactly synchronized to
  179 + * the bus clock, and
  180 + * 2) packets with a rounded-up number of blocks occur as early
  181 + * as possible in the sequence (to prevent underruns of the
  182 + * device's buffer).
  183 + */
  184 + if (s->sfc == CIP_SFC_44100)
  185 + /* 6 6 5 6 5 6 5 ... */
  186 + data_blocks = 5 + ((phase & 1) ^
  187 + (phase == 0 || phase >= 40));
  188 + else
  189 + /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */
  190 + data_blocks = 11 * (s->sfc >> 1) + (phase == 0);
  191 + if (++phase >= (80 >> (s->sfc >> 1)))
  192 + phase = 0;
  193 + s->data_block_state = phase;
  194 + }
  195 +
  196 + return data_blocks;
  197 +}
  198 +
  199 +static unsigned int calculate_syt(struct amdtp_out_stream *s,
  200 + unsigned int cycle)
  201 +{
  202 + unsigned int syt_offset, phase, index, syt;
  203 +
  204 + if (s->last_syt_offset < TICKS_PER_CYCLE) {
  205 + if (!cip_sfc_is_base_44100(s->sfc))
  206 + syt_offset = s->last_syt_offset + s->syt_offset_state;
  207 + else {
  208 + /*
  209 + * The time, in ticks, of the n'th SYT_INTERVAL sample is:
  210 + * n * SYT_INTERVAL * 24576000 / sample_rate
  211 + * Modulo TICKS_PER_CYCLE, the difference between successive
  212 + * elements is about 1386.23. Rounding the results of this
  213 + * formula to the SYT precision results in a sequence of
  214 + * differences that begins with:
  215 + * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
  216 + * This code generates _exactly_ the same sequence.
  217 + */
  218 + phase = s->syt_offset_state;
  219 + index = phase % 13;
  220 + syt_offset = s->last_syt_offset;
  221 + syt_offset += 1386 + ((index && !(index & 3)) ||
  222 + phase == 146);
  223 + if (++phase >= 147)
  224 + phase = 0;
  225 + s->syt_offset_state = phase;
  226 + }
  227 + } else
  228 + syt_offset = s->last_syt_offset - TICKS_PER_CYCLE;
  229 + s->last_syt_offset = syt_offset;
  230 +
  231 + syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
  232 + syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
  233 + syt += syt_offset % TICKS_PER_CYCLE;
  234 +
  235 + return syt & 0xffff;
  236 +}
  237 +
  238 +static void amdtp_write_s32(struct amdtp_out_stream *s,
  239 + struct snd_pcm_substream *pcm,
  240 + __be32 *buffer, unsigned int frames)
  241 +{
  242 + struct snd_pcm_runtime *runtime = pcm->runtime;
  243 + unsigned int channels, remaining_frames, frame_step, i, c;
  244 + const u32 *src;
  245 +
  246 + channels = s->pcm_channels;
  247 + src = (void *)runtime->dma_area +
  248 + s->pcm_buffer_pointer * (runtime->frame_bits / 8);
  249 + remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
  250 + frame_step = s->data_block_quadlets - channels;
  251 +
  252 + for (i = 0; i < frames; ++i) {
  253 + for (c = 0; c < channels; ++c) {
  254 + *buffer = cpu_to_be32((*src >> 8) | 0x40000000);
  255 + src++;
  256 + buffer++;
  257 + }
  258 + buffer += frame_step;
  259 + if (--remaining_frames == 0)
  260 + src = (void *)runtime->dma_area;
  261 + }
  262 +}
  263 +
  264 +static void amdtp_write_s16(struct amdtp_out_stream *s,
  265 + struct snd_pcm_substream *pcm,
  266 + __be32 *buffer, unsigned int frames)
  267 +{
  268 + struct snd_pcm_runtime *runtime = pcm->runtime;
  269 + unsigned int channels, remaining_frames, frame_step, i, c;
  270 + const u16 *src;
  271 +
  272 + channels = s->pcm_channels;
  273 + src = (void *)runtime->dma_area +
  274 + s->pcm_buffer_pointer * (runtime->frame_bits / 8);
  275 + remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
  276 + frame_step = s->data_block_quadlets - channels;
  277 +
  278 + for (i = 0; i < frames; ++i) {
  279 + for (c = 0; c < channels; ++c) {
  280 + *buffer = cpu_to_be32((*src << 8) | 0x40000000);
  281 + src++;
  282 + buffer++;
  283 + }
  284 + buffer += frame_step;
  285 + if (--remaining_frames == 0)
  286 + src = (void *)runtime->dma_area;
  287 + }
  288 +}
  289 +
  290 +static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s,
  291 + __be32 *buffer, unsigned int frames)
  292 +{
  293 + unsigned int i, c;
  294 +
  295 + for (i = 0; i < frames; ++i) {
  296 + for (c = 0; c < s->pcm_channels; ++c)
  297 + buffer[c] = cpu_to_be32(0x40000000);
  298 + buffer += s->data_block_quadlets;
  299 + }
  300 +}
  301 +
  302 +static void amdtp_fill_midi(struct amdtp_out_stream *s,
  303 + __be32 *buffer, unsigned int frames)
  304 +{
  305 + unsigned int i;
  306 +
  307 + for (i = 0; i < frames; ++i)
  308 + buffer[s->pcm_channels + i * s->data_block_quadlets] =
  309 + cpu_to_be32(0x80000000);
  310 +}
  311 +
  312 +static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
  313 +{
  314 + __be32 *buffer;
  315 + unsigned int data_blocks, syt, ptr;
  316 + struct snd_pcm_substream *pcm;
  317 + struct fw_iso_packet packet;
  318 + int err;
  319 +
  320 + data_blocks = calculate_data_blocks(s);
  321 + syt = calculate_syt(s, cycle);
  322 +
  323 + buffer = s->buffer.packets[s->packet_counter].buffer;
  324 + buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
  325 + (s->data_block_quadlets << 16) |
  326 + s->data_block_counter);
  327 + buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 |
  328 + (s->sfc << AMDTP_FDF_SFC_SHIFT) | syt);
  329 + buffer += 2;
  330 +
  331 + pcm = ACCESS_ONCE(s->pcm);
  332 + if (pcm)
  333 + s->transfer_samples(s, pcm, buffer, data_blocks);
  334 + else
  335 + amdtp_fill_pcm_silence(s, buffer, data_blocks);
  336 + if (s->midi_ports)
  337 + amdtp_fill_midi(s, buffer, data_blocks);
  338 +
  339 + s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
  340 +
  341 + packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
  342 + packet.interrupt = IS_ALIGNED(s->packet_counter + 1,
  343 + INTERRUPT_INTERVAL);
  344 + packet.skip = 0;
  345 + packet.tag = TAG_CIP;
  346 + packet.sy = 0;
  347 + packet.header_length = 0;
  348 +
  349 + err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer,
  350 + s->buffer.packets[s->packet_counter].offset);
  351 + if (err < 0)
  352 + dev_err(&s->unit->device, "queueing error: %d\n", err);
  353 +
  354 + if (++s->packet_counter >= QUEUE_LENGTH)
  355 + s->packet_counter = 0;
  356 +
  357 + if (pcm) {
  358 + ptr = s->pcm_buffer_pointer + data_blocks;
  359 + if (ptr >= pcm->runtime->buffer_size)
  360 + ptr -= pcm->runtime->buffer_size;
  361 + ACCESS_ONCE(s->pcm_buffer_pointer) = ptr;
  362 +
  363 + s->pcm_period_pointer += data_blocks;
  364 + if (s->pcm_period_pointer >= pcm->runtime->period_size) {
  365 + s->pcm_period_pointer -= pcm->runtime->period_size;
  366 + snd_pcm_period_elapsed(pcm);
  367 + }
  368 + }
  369 +}
  370 +
  371 +static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
  372 + size_t header_length, void *header, void *data)
  373 +{
  374 + struct amdtp_out_stream *s = data;
  375 + unsigned int i, packets = header_length / 4;
  376 +
  377 + /*
  378 + * Compute the cycle of the last queued packet.
  379 + * (We need only the four lowest bits for the SYT, so we can ignore
  380 + * that bits 0-11 must wrap around at 3072.)
  381 + */
  382 + cycle += QUEUE_LENGTH - packets;
  383 +
  384 + for (i = 0; i < packets; ++i)
  385 + queue_out_packet(s, ++cycle);
  386 +}
  387 +
  388 +static int queue_initial_skip_packets(struct amdtp_out_stream *s)
  389 +{
  390 + struct fw_iso_packet skip_packet = {
  391 + .skip = 1,
  392 + };
  393 + unsigned int i;
  394 + int err;
  395 +
  396 + for (i = 0; i < QUEUE_LENGTH; ++i) {
  397 + skip_packet.interrupt = IS_ALIGNED(s->packet_counter + 1,
  398 + INTERRUPT_INTERVAL);
  399 + err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0);
  400 + if (err < 0)
  401 + return err;
  402 + if (++s->packet_counter >= QUEUE_LENGTH)
  403 + s->packet_counter = 0;
  404 + }
  405 +
  406 + return 0;
  407 +}
  408 +
  409 +/**
  410 + * amdtp_out_stream_start - start sending packets
  411 + * @s: the AMDTP output stream to start
  412 + * @channel: the isochronous channel on the bus
  413 + * @speed: firewire speed code
  414 + *
  415 + * The stream cannot be started until it has been configured with
  416 + * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
  417 + * amdtp_out_stream_set_midi(); and it must be started before any
  418 + * PCM or MIDI device can be started.
  419 + */
  420 +int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
  421 +{
  422 + static const struct {
  423 + unsigned int data_block;
  424 + unsigned int syt_offset;
  425 + } initial_state[] = {
  426 + [CIP_SFC_32000] = { 4, 3072 },
  427 + [CIP_SFC_48000] = { 6, 1024 },
  428 + [CIP_SFC_96000] = { 12, 1024 },
  429 + [CIP_SFC_192000] = { 24, 1024 },
  430 + [CIP_SFC_44100] = { 0, 67 },
  431 + [CIP_SFC_88200] = { 0, 67 },
  432 + [CIP_SFC_176400] = { 0, 67 },
  433 + };
  434 + int err;
  435 +
  436 + mutex_lock(&s->mutex);
  437 +
  438 + if (WARN_ON(!IS_ERR(s->context) ||
  439 + (!s->pcm_channels && !s->midi_ports))) {
  440 + err = -EBADFD;
  441 + goto err_unlock;
  442 + }
  443 +
  444 + s->data_block_state = initial_state[s->sfc].data_block;
  445 + s->syt_offset_state = initial_state[s->sfc].syt_offset;
  446 + s->last_syt_offset = TICKS_PER_CYCLE;
  447 +
  448 + err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH,
  449 + amdtp_out_stream_get_max_payload(s),
  450 + DMA_TO_DEVICE);
  451 + if (err < 0)
  452 + goto err_unlock;
  453 +
  454 + s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
  455 + FW_ISO_CONTEXT_TRANSMIT,
  456 + channel, speed, 0,
  457 + out_packet_callback, s);
  458 + if (IS_ERR(s->context)) {
  459 + err = PTR_ERR(s->context);
  460 + if (err == -EBUSY)
  461 + dev_err(&s->unit->device,
  462 + "no free output stream on this controller\n");
  463 + goto err_buffer;
  464 + }
  465 +
  466 + amdtp_out_stream_update(s);
  467 +
  468 + s->packet_counter = 0;
  469 + s->data_block_counter = 0;
  470 + err = queue_initial_skip_packets(s);
  471 + if (err < 0)
  472 + goto err_context;
  473 +
  474 + err = fw_iso_context_start(s->context, -1, 0, 0);
  475 + if (err < 0)
  476 + goto err_context;
  477 +
  478 + mutex_unlock(&s->mutex);
  479 +
  480 + return 0;
  481 +
  482 +err_context:
  483 + fw_iso_context_destroy(s->context);
  484 + s->context = ERR_PTR(-1);
  485 +err_buffer:
  486 + iso_packets_buffer_destroy(&s->buffer, s->unit);
  487 +err_unlock:
  488 + mutex_unlock(&s->mutex);
  489 +
  490 + return err;
  491 +}
  492 +EXPORT_SYMBOL(amdtp_out_stream_start);
  493 +
  494 +/**
  495 + * amdtp_out_stream_update - update the stream after a bus reset
  496 + * @s: the AMDTP output stream
  497 + */
  498 +void amdtp_out_stream_update(struct amdtp_out_stream *s)
  499 +{
  500 + ACCESS_ONCE(s->source_node_id_field) =
  501 + (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24;
  502 +}
  503 +EXPORT_SYMBOL(amdtp_out_stream_update);
  504 +
  505 +/**
  506 + * amdtp_out_stream_stop - stop sending packets
  507 + * @s: the AMDTP output stream to stop
  508 + *
  509 + * All PCM and MIDI devices of the stream must be stopped before the stream
  510 + * itself can be stopped.
  511 + */
  512 +void amdtp_out_stream_stop(struct amdtp_out_stream *s)
  513 +{
  514 + mutex_lock(&s->mutex);
  515 +
  516 + if (IS_ERR(s->context)) {
  517 + mutex_unlock(&s->mutex);
  518 + return;
  519 + }
  520 +
  521 + fw_iso_context_stop(s->context);
  522 + fw_iso_context_destroy(s->context);
  523 + s->context = ERR_PTR(-1);
  524 + iso_packets_buffer_destroy(&s->buffer, s->unit);
  525 +
  526 + mutex_unlock(&s->mutex);
  527 +}
  528 +EXPORT_SYMBOL(amdtp_out_stream_stop);
  529 +
  530 +/**
  531 + * amdtp_out_stream_pcm_abort - abort the running PCM device
  532 + * @s: the AMDTP stream about to be stopped
  533 + *
  534 + * If the isochronous stream needs to be stopped asynchronously, call this
  535 + * function first to stop the PCM device.
  536 + */
  537 +void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s)
  538 +{
  539 + struct snd_pcm_substream *pcm;
  540 +
  541 + pcm = ACCESS_ONCE(s->pcm);
  542 + if (pcm) {
  543 + snd_pcm_stream_lock_irq(pcm);
  544 + if (snd_pcm_running(pcm))
  545 + snd_pcm_stop(pcm, SNDRV_PCM_STATE_XRUN);
  546 + snd_pcm_stream_unlock_irq(pcm);
  547 + }
  548 +}
  549 +EXPORT_SYMBOL(amdtp_out_stream_pcm_abort);
sound/firewire/amdtp.h
  1 +#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
  2 +#define SOUND_FIREWIRE_AMDTP_H_INCLUDED
  3 +
  4 +#include <linux/mutex.h>
  5 +#include <linux/spinlock.h>
  6 +#include "packets-buffer.h"
  7 +
  8 +/**
  9 + * enum cip_out_flags - describes details of the streaming protocol
  10 + * @CIP_NONBLOCKING: In non-blocking mode, each packet contains
  11 + * sample_rate/8000 samples, with rounding up or down to adjust
  12 + * for clock skew and left-over fractional samples. This should
  13 + * be used if supported by the device.
  14 + */
  15 +enum cip_out_flags {
  16 + CIP_NONBLOCKING = 0,
  17 +};
  18 +
  19 +/**
  20 + * enum cip_sfc - a stream's sample rate
  21 + */
  22 +enum cip_sfc {
  23 + CIP_SFC_32000 = 0,
  24 + CIP_SFC_44100 = 1,
  25 + CIP_SFC_48000 = 2,
  26 + CIP_SFC_88200 = 3,
  27 + CIP_SFC_96000 = 4,
  28 + CIP_SFC_176400 = 5,
  29 + CIP_SFC_192000 = 6,
  30 +};
  31 +
  32 +#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \
  33 + SNDRV_PCM_FMTBIT_S32)
  34 +
  35 +struct fw_unit;
  36 +struct fw_iso_context;
  37 +struct snd_pcm_substream;
  38 +
  39 +struct amdtp_out_stream {
  40 + struct fw_unit *unit;
  41 + enum cip_out_flags flags;
  42 + struct fw_iso_context *context;
  43 + struct mutex mutex;
  44 +
  45 + enum cip_sfc sfc;
  46 + unsigned int data_block_quadlets;
  47 + unsigned int pcm_channels;
  48 + unsigned int midi_ports;
  49 + void (*transfer_samples)(struct amdtp_out_stream *s,
  50 + struct snd_pcm_substream *pcm,
  51 + __be32 *buffer, unsigned int frames);
  52 +
  53 + unsigned int syt_interval;
  54 + unsigned int source_node_id_field;
  55 + struct iso_packets_buffer buffer;
  56 +
  57 + struct snd_pcm_substream *pcm;
  58 +
  59 + unsigned int packet_counter;
  60 + unsigned int data_block_counter;
  61 +
  62 + unsigned int data_block_state;
  63 +
  64 + unsigned int last_syt_offset;
  65 + unsigned int syt_offset_state;
  66 +
  67 + unsigned int pcm_buffer_pointer;
  68 + unsigned int pcm_period_pointer;
  69 +};
  70 +
  71 +int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
  72 + enum cip_out_flags flags);
  73 +void amdtp_out_stream_destroy(struct amdtp_out_stream *s);
  74 +
  75 +void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate);
  76 +unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s);
  77 +
  78 +int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed);
  79 +void amdtp_out_stream_update(struct amdtp_out_stream *s);
  80 +void amdtp_out_stream_stop(struct amdtp_out_stream *s);
  81 +
  82 +void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
  83 + snd_pcm_format_t format);
  84 +void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
  85 +
  86 +/**
  87 + * amdtp_out_stream_set_pcm - configure format of PCM samples
  88 + * @s: the AMDTP output stream to be configured
  89 + * @pcm_channels: the number of PCM samples in each data block, to be encoded
  90 + * as AM824 multi-bit linear audio
  91 + *
  92 + * This function must not be called while the stream is running.
  93 + */
  94 +static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s,
  95 + unsigned int pcm_channels)
  96 +{
  97 + s->pcm_channels = pcm_channels;
  98 +}
  99 +
  100 +/**
  101 + * amdtp_out_stream_set_midi - configure format of MIDI data
  102 + * @s: the AMDTP output stream to be configured
  103 + * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
  104 + *
  105 + * This function must not be called while the stream is running.
  106 + */
  107 +static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s,
  108 + unsigned int midi_ports)
  109 +{
  110 + s->midi_ports = midi_ports;
  111 +}
  112 +
  113 +/**
  114 + * amdtp_out_stream_pcm_prepare - prepare PCM device for running
  115 + * @s: the AMDTP output stream
  116 + *
  117 + * This function should be called from the PCM device's .prepare callback.
  118 + */
  119 +static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
  120 +{
  121 + s->pcm_buffer_pointer = 0;
  122 + s->pcm_period_pointer = 0;
  123 +}
  124 +
  125 +/**
  126 + * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device
  127 + * @s: the AMDTP output stream
  128 + * @pcm: the PCM device to be started, or %NULL to stop the current device
  129 + *
  130 + * Call this function on a running isochronous stream to enable the actual
  131 + * transmission of PCM data. This function should be called from the PCM
  132 + * device's .trigger callback.
  133 + */
  134 +static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s,
  135 + struct snd_pcm_substream *pcm)
  136 +{
  137 + ACCESS_ONCE(s->pcm) = pcm;
  138 +}
  139 +
  140 +/**
  141 + * amdtp_out_stream_pcm_pointer - get the PCM buffer position
  142 + * @s: the AMDTP output stream that transports the PCM data
  143 + *
  144 + * Returns the current buffer position, in frames.
  145 + */
  146 +static inline unsigned long
  147 +amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
  148 +{
  149 + return ACCESS_ONCE(s->pcm_buffer_pointer);
  150 +}
  151 +
  152 +static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
  153 +{
  154 + return sfc & 1;
  155 +}
  156 +
  157 +#endif
sound/firewire/cmp.c
  1 +/*
  2 + * Connection Management Procedures (IEC 61883-1) helper functions
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/device.h>
  9 +#include <linux/firewire.h>
  10 +#include <linux/firewire-constants.h>
  11 +#include <linux/module.h>
  12 +#include <linux/sched.h>
  13 +#include "lib.h"
  14 +#include "iso-resources.h"
  15 +#include "cmp.h"
  16 +
  17 +#define IMPR_SPEED_MASK 0xc0000000
  18 +#define IMPR_SPEED_SHIFT 30
  19 +#define IMPR_XSPEED_MASK 0x00000060
  20 +#define IMPR_XSPEED_SHIFT 5
  21 +#define IMPR_PLUGS_MASK 0x0000001f
  22 +
  23 +#define IPCR_ONLINE 0x80000000
  24 +#define IPCR_BCAST_CONN 0x40000000
  25 +#define IPCR_P2P_CONN_MASK 0x3f000000
  26 +#define IPCR_P2P_CONN_SHIFT 24
  27 +#define IPCR_CHANNEL_MASK 0x003f0000
  28 +#define IPCR_CHANNEL_SHIFT 16
  29 +
  30 +enum bus_reset_handling {
  31 + ABORT_ON_BUS_RESET,
  32 + SUCCEED_ON_BUS_RESET,
  33 +};
  34 +
  35 +static __attribute__((format(printf, 2, 3)))
  36 +void cmp_error(struct cmp_connection *c, const char *fmt, ...)
  37 +{
  38 + va_list va;
  39 +
  40 + va_start(va, fmt);
  41 + dev_err(&c->resources.unit->device, "%cPCR%u: %pV",
  42 + 'i', c->pcr_index, &(struct va_format){ fmt, &va });
  43 + va_end(va);
  44 +}
  45 +
  46 +static int pcr_modify(struct cmp_connection *c,
  47 + __be32 (*modify)(struct cmp_connection *c, __be32 old),
  48 + int (*check)(struct cmp_connection *c, __be32 pcr),
  49 + enum bus_reset_handling bus_reset_handling)
  50 +{
  51 + struct fw_device *device = fw_parent_device(c->resources.unit);
  52 + __be32 *buffer = c->resources.buffer;
  53 + int generation = c->resources.generation;
  54 + int rcode, errors = 0;
  55 + __be32 old_arg;
  56 + int err;
  57 +
  58 + buffer[0] = c->last_pcr_value;
  59 + for (;;) {
  60 + old_arg = buffer[0];
  61 + buffer[1] = modify(c, buffer[0]);
  62 +
  63 + rcode = fw_run_transaction(
  64 + device->card, TCODE_LOCK_COMPARE_SWAP,
  65 + device->node_id, generation, device->max_speed,
  66 + CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index),
  67 + buffer, 8);
  68 +
  69 + if (rcode == RCODE_COMPLETE) {
  70 + if (buffer[0] == old_arg) /* success? */
  71 + break;
  72 +
  73 + if (check) {
  74 + err = check(c, buffer[0]);
  75 + if (err < 0)
  76 + return err;
  77 + }
  78 + } else if (rcode == RCODE_GENERATION)
  79 + goto bus_reset;
  80 + else if (rcode_is_permanent_error(rcode) || ++errors >= 3)
  81 + goto io_error;
  82 + }
  83 + c->last_pcr_value = buffer[1];
  84 +
  85 + return 0;
  86 +
  87 +io_error:
  88 + cmp_error(c, "transaction failed: %s\n", rcode_string(rcode));
  89 + return -EIO;
  90 +
  91 +bus_reset:
  92 + return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0;
  93 +}
  94 +
  95 +
  96 +/**
  97 + * cmp_connection_init - initializes a connection manager
  98 + * @c: the connection manager to initialize
  99 + * @unit: a unit of the target device
  100 + * @ipcr_index: the index of the iPCR on the target device
  101 + */
  102 +int cmp_connection_init(struct cmp_connection *c,
  103 + struct fw_unit *unit,
  104 + unsigned int ipcr_index)
  105 +{
  106 + __be32 impr_be;
  107 + u32 impr;
  108 + int err;
  109 +
  110 + err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
  111 + CSR_REGISTER_BASE + CSR_IMPR,
  112 + &impr_be, 4);
  113 + if (err < 0)
  114 + return err;
  115 + impr = be32_to_cpu(impr_be);
  116 +
  117 + if (ipcr_index >= (impr & IMPR_PLUGS_MASK))
  118 + return -EINVAL;
  119 +
  120 + c->connected = false;
  121 + mutex_init(&c->mutex);
  122 + fw_iso_resources_init(&c->resources, unit);
  123 + c->last_pcr_value = cpu_to_be32(0x80000000);
  124 + c->pcr_index = ipcr_index;
  125 + c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT;
  126 + if (c->max_speed == SCODE_BETA)
  127 + c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT;
  128 +
  129 + return 0;
  130 +}
  131 +EXPORT_SYMBOL(cmp_connection_init);
  132 +
  133 +/**
  134 + * cmp_connection_destroy - free connection manager resources
  135 + * @c: the connection manager
  136 + */
  137 +void cmp_connection_destroy(struct cmp_connection *c)
  138 +{
  139 + WARN_ON(c->connected);
  140 + mutex_destroy(&c->mutex);
  141 + fw_iso_resources_destroy(&c->resources);
  142 +}
  143 +EXPORT_SYMBOL(cmp_connection_destroy);
  144 +
  145 +
  146 +static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr)
  147 +{
  148 + ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN |
  149 + IPCR_P2P_CONN_MASK |
  150 + IPCR_CHANNEL_MASK);
  151 + ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT);
  152 + ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT);
  153 +
  154 + return ipcr;
  155 +}
  156 +
  157 +static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr)
  158 +{
  159 + if (ipcr & cpu_to_be32(IPCR_BCAST_CONN |
  160 + IPCR_P2P_CONN_MASK)) {
  161 + cmp_error(c, "plug is already in use\n");
  162 + return -EBUSY;
  163 + }
  164 + if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) {
  165 + cmp_error(c, "plug is not on-line\n");
  166 + return -ECONNREFUSED;
  167 + }
  168 +
  169 + return 0;
  170 +}
  171 +
  172 +/**
  173 + * cmp_connection_establish - establish a connection to the target
  174 + * @c: the connection manager
  175 + * @max_payload_bytes: the amount of data (including CIP headers) per packet
  176 + *
  177 + * This function establishes a point-to-point connection from the local
  178 + * computer to the target by allocating isochronous resources (channel and
  179 + * bandwidth) and setting the target's input plug control register. When this
  180 + * function succeeds, the caller is responsible for starting transmitting
  181 + * packets.
  182 + */
  183 +int cmp_connection_establish(struct cmp_connection *c,
  184 + unsigned int max_payload_bytes)
  185 +{
  186 + int err;
  187 +
  188 + if (WARN_ON(c->connected))
  189 + return -EISCONN;
  190 +
  191 + c->speed = min(c->max_speed,
  192 + fw_parent_device(c->resources.unit)->max_speed);
  193 +
  194 + mutex_lock(&c->mutex);
  195 +
  196 +retry_after_bus_reset:
  197 + err = fw_iso_resources_allocate(&c->resources,
  198 + max_payload_bytes, c->speed);
  199 + if (err < 0)
  200 + goto err_mutex;
  201 +
  202 + err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
  203 + ABORT_ON_BUS_RESET);
  204 + if (err == -EAGAIN) {
  205 + fw_iso_resources_free(&c->resources);
  206 + goto retry_after_bus_reset;
  207 + }
  208 + if (err < 0)
  209 + goto err_resources;
  210 +
  211 + c->connected = true;
  212 +
  213 + mutex_unlock(&c->mutex);
  214 +
  215 + return 0;
  216 +
  217 +err_resources:
  218 + fw_iso_resources_free(&c->resources);
  219 +err_mutex:
  220 + mutex_unlock(&c->mutex);
  221 +
  222 + return err;
  223 +}
  224 +EXPORT_SYMBOL(cmp_connection_establish);
  225 +
  226 +/**
  227 + * cmp_connection_update - update the connection after a bus reset
  228 + * @c: the connection manager
  229 + *
  230 + * This function must be called from the driver's .update handler to reestablish
  231 + * any connection that might have been active.
  232 + *
  233 + * Returns zero on success, or a negative error code. On an error, the
  234 + * connection is broken and the caller must stop transmitting iso packets.
  235 + */
  236 +int cmp_connection_update(struct cmp_connection *c)
  237 +{
  238 + int err;
  239 +
  240 + mutex_lock(&c->mutex);
  241 +
  242 + if (!c->connected) {
  243 + mutex_unlock(&c->mutex);
  244 + return 0;
  245 + }
  246 +
  247 + err = fw_iso_resources_update(&c->resources);
  248 + if (err < 0)
  249 + goto err_unconnect;
  250 +
  251 + err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
  252 + SUCCEED_ON_BUS_RESET);
  253 + if (err < 0)
  254 + goto err_resources;
  255 +
  256 + mutex_unlock(&c->mutex);
  257 +
  258 + return 0;
  259 +
  260 +err_resources:
  261 + fw_iso_resources_free(&c->resources);
  262 +err_unconnect:
  263 + c->connected = false;
  264 + mutex_unlock(&c->mutex);
  265 +
  266 + return err;
  267 +}
  268 +EXPORT_SYMBOL(cmp_connection_update);
  269 +
  270 +
  271 +static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr)
  272 +{
  273 + return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK);
  274 +}
  275 +
  276 +/**
  277 + * cmp_connection_break - break the connection to the target
  278 + * @c: the connection manager
  279 + *
  280 + * This function deactives the connection in the target's input plug control
  281 + * register, and frees the isochronous resources of the connection. Before
  282 + * calling this function, the caller should cease transmitting packets.
  283 + */
  284 +void cmp_connection_break(struct cmp_connection *c)
  285 +{
  286 + int err;
  287 +
  288 + mutex_lock(&c->mutex);
  289 +
  290 + if (!c->connected) {
  291 + mutex_unlock(&c->mutex);
  292 + return;
  293 + }
  294 +
  295 + err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET);
  296 + if (err < 0)
  297 + cmp_error(c, "plug is still connected\n");
  298 +
  299 + fw_iso_resources_free(&c->resources);
  300 +
  301 + c->connected = false;
  302 +
  303 + mutex_unlock(&c->mutex);
  304 +}
  305 +EXPORT_SYMBOL(cmp_connection_break);
sound/firewire/cmp.h
  1 +#ifndef SOUND_FIREWIRE_CMP_H_INCLUDED
  2 +#define SOUND_FIREWIRE_CMP_H_INCLUDED
  3 +
  4 +#include <linux/mutex.h>
  5 +#include <linux/types.h>
  6 +#include "iso-resources.h"
  7 +
  8 +struct fw_unit;
  9 +
  10 +/**
  11 + * struct cmp_connection - manages an isochronous connection to a device
  12 + * @speed: the connection's actual speed
  13 + *
  14 + * This structure manages (using CMP) an isochronous stream from the local
  15 + * computer to a device's input plug (iPCR).
  16 + *
  17 + * There is no corresponding oPCR created on the local computer, so it is not
  18 + * possible to overlay connections on top of this one.
  19 + */
  20 +struct cmp_connection {
  21 + int speed;
  22 + /* private: */
  23 + bool connected;
  24 + struct mutex mutex;
  25 + struct fw_iso_resources resources;
  26 + __be32 last_pcr_value;
  27 + unsigned int pcr_index;
  28 + unsigned int max_speed;
  29 +};
  30 +
  31 +int cmp_connection_init(struct cmp_connection *connection,
  32 + struct fw_unit *unit,
  33 + unsigned int ipcr_index);
  34 +void cmp_connection_destroy(struct cmp_connection *connection);
  35 +
  36 +int cmp_connection_establish(struct cmp_connection *connection,
  37 + unsigned int max_payload);
  38 +int cmp_connection_update(struct cmp_connection *connection);
  39 +void cmp_connection_break(struct cmp_connection *connection);
  40 +
  41 +#endif
sound/firewire/fcp.c
  1 +/*
  2 + * Function Control Protocol (IEC 61883-1) helper functions
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/device.h>
  9 +#include <linux/firewire.h>
  10 +#include <linux/firewire-constants.h>
  11 +#include <linux/list.h>
  12 +#include <linux/module.h>
  13 +#include <linux/sched.h>
  14 +#include <linux/spinlock.h>
  15 +#include <linux/wait.h>
  16 +#include "fcp.h"
  17 +#include "lib.h"
  18 +
  19 +#define CTS_AVC 0x00
  20 +
  21 +#define ERROR_RETRIES 3
  22 +#define ERROR_DELAY_MS 5
  23 +#define FCP_TIMEOUT_MS 125
  24 +
  25 +static DEFINE_SPINLOCK(transactions_lock);
  26 +static LIST_HEAD(transactions);
  27 +
  28 +enum fcp_state {
  29 + STATE_PENDING,
  30 + STATE_BUS_RESET,
  31 + STATE_COMPLETE,
  32 +};
  33 +
  34 +struct fcp_transaction {
  35 + struct list_head list;
  36 + struct fw_unit *unit;
  37 + void *response_buffer;
  38 + unsigned int response_size;
  39 + unsigned int response_match_bytes;
  40 + enum fcp_state state;
  41 + wait_queue_head_t wait;
  42 +};
  43 +
  44 +/**
  45 + * fcp_avc_transaction - send an AV/C command and wait for its response
  46 + * @unit: a unit on the target device
  47 + * @command: a buffer containing the command frame; must be DMA-able
  48 + * @command_size: the size of @command
  49 + * @response: a buffer for the response frame
  50 + * @response_size: the maximum size of @response
  51 + * @response_match_bytes: a bitmap specifying the bytes used to detect the
  52 + * correct response frame
  53 + *
  54 + * This function sends a FCP command frame to the target and waits for the
  55 + * corresponding response frame to be returned.
  56 + *
  57 + * Because it is possible for multiple FCP transactions to be active at the
  58 + * same time, the correct response frame is detected by the value of certain
  59 + * bytes. These bytes must be set in @response before calling this function,
  60 + * and the corresponding bits must be set in @response_match_bytes.
  61 + *
  62 + * @command and @response can point to the same buffer.
  63 + *
  64 + * Asynchronous operation (INTERIM, NOTIFY) is not supported at the moment.
  65 + *
  66 + * Returns the actual size of the response frame, or a negative error code.
  67 + */
  68 +int fcp_avc_transaction(struct fw_unit *unit,
  69 + const void *command, unsigned int command_size,
  70 + void *response, unsigned int response_size,
  71 + unsigned int response_match_bytes)
  72 +{
  73 + struct fcp_transaction t;
  74 + int tcode, ret, tries = 0;
  75 +
  76 + t.unit = unit;
  77 + t.response_buffer = response;
  78 + t.response_size = response_size;
  79 + t.response_match_bytes = response_match_bytes;
  80 + t.state = STATE_PENDING;
  81 + init_waitqueue_head(&t.wait);
  82 +
  83 + spin_lock_irq(&transactions_lock);
  84 + list_add_tail(&t.list, &transactions);
  85 + spin_unlock_irq(&transactions_lock);
  86 +
  87 + for (;;) {
  88 + tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
  89 + : TCODE_WRITE_BLOCK_REQUEST;
  90 + ret = snd_fw_transaction(t.unit, tcode,
  91 + CSR_REGISTER_BASE + CSR_FCP_COMMAND,
  92 + (void *)command, command_size);
  93 + if (ret < 0)
  94 + break;
  95 +
  96 + wait_event_timeout(t.wait, t.state != STATE_PENDING,
  97 + msecs_to_jiffies(FCP_TIMEOUT_MS));
  98 +
  99 + if (t.state == STATE_COMPLETE) {
  100 + ret = t.response_size;
  101 + break;
  102 + } else if (t.state == STATE_BUS_RESET) {
  103 + msleep(ERROR_DELAY_MS);
  104 + } else if (++tries >= ERROR_RETRIES) {
  105 + dev_err(&t.unit->device, "FCP command timed out\n");
  106 + ret = -EIO;
  107 + break;
  108 + }
  109 + }
  110 +
  111 + spin_lock_irq(&transactions_lock);
  112 + list_del(&t.list);
  113 + spin_unlock_irq(&transactions_lock);
  114 +
  115 + return ret;
  116 +}
  117 +EXPORT_SYMBOL(fcp_avc_transaction);
  118 +
  119 +/**
  120 + * fcp_bus_reset - inform the target handler about a bus reset
  121 + * @unit: the unit that might be used by fcp_avc_transaction()
  122 + *
  123 + * This function must be called from the driver's .update handler to inform
  124 + * the FCP transaction handler that a bus reset has happened. Any pending FCP
  125 + * transactions are retried.
  126 + */
  127 +void fcp_bus_reset(struct fw_unit *unit)
  128 +{
  129 + struct fcp_transaction *t;
  130 +
  131 + spin_lock_irq(&transactions_lock);
  132 + list_for_each_entry(t, &transactions, list) {
  133 + if (t->unit == unit &&
  134 + t->state == STATE_PENDING) {
  135 + t->state = STATE_BUS_RESET;
  136 + wake_up(&t->wait);
  137 + }
  138 + }
  139 + spin_unlock_irq(&transactions_lock);
  140 +}
  141 +EXPORT_SYMBOL(fcp_bus_reset);
  142 +
  143 +/* checks whether the response matches the masked bytes in response_buffer */
  144 +static bool is_matching_response(struct fcp_transaction *transaction,
  145 + const void *response, size_t length)
  146 +{
  147 + const u8 *p1, *p2;
  148 + unsigned int mask, i;
  149 +
  150 + p1 = response;
  151 + p2 = transaction->response_buffer;
  152 + mask = transaction->response_match_bytes;
  153 +
  154 + for (i = 0; ; ++i) {
  155 + if ((mask & 1) && p1[i] != p2[i])
  156 + return false;
  157 + mask >>= 1;
  158 + if (!mask)
  159 + return true;
  160 + if (--length == 0)
  161 + return false;
  162 + }
  163 +}
  164 +
  165 +static void fcp_response(struct fw_card *card, struct fw_request *request,
  166 + int tcode, int destination, int source,
  167 + int generation, unsigned long long offset,
  168 + void *data, size_t length, void *callback_data)
  169 +{
  170 + struct fcp_transaction *t;
  171 + unsigned long flags;
  172 +
  173 + if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
  174 + return;
  175 +
  176 + spin_lock_irqsave(&transactions_lock, flags);
  177 + list_for_each_entry(t, &transactions, list) {
  178 + struct fw_device *device = fw_parent_device(t->unit);
  179 + if (device->card != card ||
  180 + device->generation != generation)
  181 + continue;
  182 + smp_rmb(); /* node_id vs. generation */
  183 + if (device->node_id != source)
  184 + continue;
  185 +
  186 + if (t->state == STATE_PENDING &&
  187 + is_matching_response(t, data, length)) {
  188 + t->state = STATE_COMPLETE;
  189 + t->response_size = min((unsigned int)length,
  190 + t->response_size);
  191 + memcpy(t->response_buffer, data, t->response_size);
  192 + wake_up(&t->wait);
  193 + }
  194 + }
  195 + spin_unlock_irqrestore(&transactions_lock, flags);
  196 +}
  197 +
  198 +static struct fw_address_handler response_register_handler = {
  199 + .length = 0x200,
  200 + .address_callback = fcp_response,
  201 +};
  202 +
  203 +static int __init fcp_module_init(void)
  204 +{
  205 + static const struct fw_address_region response_register_region = {
  206 + .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
  207 + .end = CSR_REGISTER_BASE + CSR_FCP_END,
  208 + };
  209 +
  210 + fw_core_add_address_handler(&response_register_handler,
  211 + &response_register_region);
  212 +
  213 + return 0;
  214 +}
  215 +
  216 +static void __exit fcp_module_exit(void)
  217 +{
  218 + WARN_ON(!list_empty(&transactions));
  219 + fw_core_remove_address_handler(&response_register_handler);
  220 +}
  221 +
  222 +module_init(fcp_module_init);
  223 +module_exit(fcp_module_exit);
sound/firewire/fcp.h
  1 +#ifndef SOUND_FIREWIRE_FCP_H_INCLUDED
  2 +#define SOUND_FIREWIRE_FCP_H_INCLUDED
  3 +
  4 +struct fw_unit;
  5 +
  6 +int fcp_avc_transaction(struct fw_unit *unit,
  7 + const void *command, unsigned int command_size,
  8 + void *response, unsigned int response_size,
  9 + unsigned int response_match_bytes);
  10 +void fcp_bus_reset(struct fw_unit *unit);
  11 +
  12 +#endif
sound/firewire/iso-resources.c
  1 +/*
  2 + * isochronous resources helper functions
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/device.h>
  9 +#include <linux/firewire.h>
  10 +#include <linux/firewire-constants.h>
  11 +#include <linux/jiffies.h>
  12 +#include <linux/mutex.h>
  13 +#include <linux/sched.h>
  14 +#include <linux/spinlock.h>
  15 +#include "iso-resources.h"
  16 +
  17 +/**
  18 + * fw_iso_resources_init - initializes a &struct fw_iso_resources
  19 + * @r: the resource manager to initialize
  20 + * @unit: the device unit for which the resources will be needed
  21 + *
  22 + * If the device does not support all channel numbers, change @r->channels_mask
  23 + * after calling this function.
  24 + */
  25 +void fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
  26 +{
  27 + r->channels_mask = ~0uLL;
  28 + r->unit = fw_unit_get(unit);
  29 + mutex_init(&r->mutex);
  30 + r->allocated = false;
  31 +}
  32 +
  33 +/**
  34 + * fw_iso_resources_destroy - destroy a resource manager
  35 + * @r: the resource manager that is no longer needed
  36 + */
  37 +void fw_iso_resources_destroy(struct fw_iso_resources *r)
  38 +{
  39 + WARN_ON(r->allocated);
  40 + mutex_destroy(&r->mutex);
  41 + fw_unit_put(r->unit);
  42 +}
  43 +
  44 +static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed)
  45 +{
  46 + unsigned int bytes, s400_bytes;
  47 +
  48 + /* iso packets have three header quadlets and quadlet-aligned payload */
  49 + bytes = 3 * 4 + ALIGN(max_payload_bytes, 4);
  50 +
  51 + /* convert to bandwidth units (quadlets at S1600 = bytes at S400) */
  52 + if (speed <= SCODE_400)
  53 + s400_bytes = bytes * (1 << (SCODE_400 - speed));
  54 + else
  55 + s400_bytes = DIV_ROUND_UP(bytes, 1 << (speed - SCODE_400));
  56 +
  57 + return s400_bytes;
  58 +}
  59 +
  60 +static int current_bandwidth_overhead(struct fw_card *card)
  61 +{
  62 + /*
  63 + * Under the usual pessimistic assumption (cable length 4.5 m), the
  64 + * isochronous overhead for N cables is 1.797 ยตs + N * 0.494 ยตs, or
  65 + * 88.3 + N * 24.3 in bandwidth units.
  66 + *
  67 + * The calculation below tries to deduce N from the current gap count.
  68 + * If the gap count has been optimized by measuring the actual packet
  69 + * transmission time, this derived overhead should be near the actual
  70 + * overhead as well.
  71 + */
  72 + return card->gap_count < 63 ? card->gap_count * 97 / 10 + 89 : 512;
  73 +}
  74 +
  75 +static int wait_isoch_resource_delay_after_bus_reset(struct fw_card *card)
  76 +{
  77 + for (;;) {
  78 + s64 delay = (card->reset_jiffies + HZ) - get_jiffies_64();
  79 + if (delay <= 0)
  80 + return 0;
  81 + if (schedule_timeout_interruptible(delay) > 0)
  82 + return -ERESTARTSYS;
  83 + }
  84 +}
  85 +
  86 +/**
  87 + * fw_iso_resources_allocate - allocate isochronous channel and bandwidth
  88 + * @r: the resource manager
  89 + * @max_payload_bytes: the amount of data (including CIP headers) per packet
  90 + * @speed: the speed (e.g., SCODE_400) at which the packets will be sent
  91 + *
  92 + * This function allocates one isochronous channel and enough bandwidth for the
  93 + * specified packet size.
  94 + *
  95 + * Returns the channel number that the caller must use for streaming, or
  96 + * a negative error code. Due to potentionally long delays, this function is
  97 + * interruptible and can return -ERESTARTSYS. On success, the caller is
  98 + * responsible for calling fw_iso_resources_update() on bus resets, and
  99 + * fw_iso_resources_free() when the resources are not longer needed.
  100 + */
  101 +int fw_iso_resources_allocate(struct fw_iso_resources *r,
  102 + unsigned int max_payload_bytes, int speed)
  103 +{
  104 + struct fw_card *card = fw_parent_device(r->unit)->card;
  105 + int bandwidth, channel, err;
  106 +
  107 + if (WARN_ON(r->allocated))
  108 + return -EBADFD;
  109 +
  110 + r->bandwidth = packet_bandwidth(max_payload_bytes, speed);
  111 +
  112 +retry_after_bus_reset:
  113 + spin_lock_irq(&card->lock);
  114 + r->generation = card->generation;
  115 + r->bandwidth_overhead = current_bandwidth_overhead(card);
  116 + spin_unlock_irq(&card->lock);
  117 +
  118 + err = wait_isoch_resource_delay_after_bus_reset(card);
  119 + if (err < 0)
  120 + return err;
  121 +
  122 + mutex_lock(&r->mutex);
  123 +
  124 + bandwidth = r->bandwidth + r->bandwidth_overhead;
  125 + fw_iso_resource_manage(card, r->generation, r->channels_mask,
  126 + &channel, &bandwidth, true, r->buffer);
  127 + if (channel == -EAGAIN) {
  128 + mutex_unlock(&r->mutex);
  129 + goto retry_after_bus_reset;
  130 + }
  131 + if (channel >= 0) {
  132 + r->channel = channel;
  133 + r->allocated = true;
  134 + } else {
  135 + if (channel == -EBUSY)
  136 + dev_err(&r->unit->device,
  137 + "isochronous resources exhausted\n");
  138 + else
  139 + dev_err(&r->unit->device,
  140 + "isochronous resource allocation failed\n");
  141 + }
  142 +
  143 + mutex_unlock(&r->mutex);
  144 +
  145 + return channel;
  146 +}
  147 +
  148 +/**
  149 + * fw_iso_resources_update - update resource allocations after a bus reset
  150 + * @r: the resource manager
  151 + *
  152 + * This function must be called from the driver's .update handler to reallocate
  153 + * any resources that were allocated before the bus reset. It is safe to call
  154 + * this function if no resources are currently allocated.
  155 + *
  156 + * Returns a negative error code on failure. If this happens, the caller must
  157 + * stop streaming.
  158 + */
  159 +int fw_iso_resources_update(struct fw_iso_resources *r)
  160 +{
  161 + struct fw_card *card = fw_parent_device(r->unit)->card;
  162 + int bandwidth, channel;
  163 +
  164 + mutex_lock(&r->mutex);
  165 +
  166 + if (!r->allocated) {
  167 + mutex_unlock(&r->mutex);
  168 + return 0;
  169 + }
  170 +
  171 + spin_lock_irq(&card->lock);
  172 + r->generation = card->generation;
  173 + r->bandwidth_overhead = current_bandwidth_overhead(card);
  174 + spin_unlock_irq(&card->lock);
  175 +
  176 + bandwidth = r->bandwidth + r->bandwidth_overhead;
  177 +
  178 + fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
  179 + &channel, &bandwidth, true, r->buffer);
  180 + /*
  181 + * When another bus reset happens, pretend that the allocation
  182 + * succeeded; we will try again for the new generation later.
  183 + */
  184 + if (channel < 0 && channel != -EAGAIN) {
  185 + r->allocated = false;
  186 + if (channel == -EBUSY)
  187 + dev_err(&r->unit->device,
  188 + "isochronous resources exhausted\n");
  189 + else
  190 + dev_err(&r->unit->device,
  191 + "isochronous resource allocation failed\n");
  192 + }
  193 +
  194 + mutex_unlock(&r->mutex);
  195 +
  196 + return channel;
  197 +}
  198 +
  199 +/**
  200 + * fw_iso_resources_free - frees allocated resources
  201 + * @r: the resource manager
  202 + *
  203 + * This function deallocates the channel and bandwidth, if allocated.
  204 + */
  205 +void fw_iso_resources_free(struct fw_iso_resources *r)
  206 +{
  207 + struct fw_card *card = fw_parent_device(r->unit)->card;
  208 + int bandwidth, channel;
  209 +
  210 + mutex_lock(&r->mutex);
  211 +
  212 + if (r->allocated) {
  213 + bandwidth = r->bandwidth + r->bandwidth_overhead;
  214 + fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
  215 + &channel, &bandwidth, false, r->buffer);
  216 + if (channel < 0)
  217 + dev_err(&r->unit->device,
  218 + "isochronous resource deallocation failed\n");
  219 +
  220 + r->allocated = false;
  221 + }
  222 +
  223 + mutex_unlock(&r->mutex);
  224 +}
sound/firewire/iso-resources.h
  1 +#ifndef SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED
  2 +#define SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED
  3 +
  4 +#include <linux/mutex.h>
  5 +#include <linux/types.h>
  6 +
  7 +struct fw_unit;
  8 +
  9 +/**
  10 + * struct fw_iso_resources - manages channel/bandwidth allocation
  11 + * @channels_mask: if the device does not support all channel numbers, set this
  12 + * bit mask to something else than the default (all ones)
  13 + *
  14 + * This structure manages (de)allocation of isochronous resources (channel and
  15 + * bandwidth) for one isochronous stream.
  16 + */
  17 +struct fw_iso_resources {
  18 + u64 channels_mask;
  19 + /* private: */
  20 + struct fw_unit *unit;
  21 + struct mutex mutex;
  22 + unsigned int channel;
  23 + unsigned int bandwidth; /* in bandwidth units, without overhead */
  24 + unsigned int bandwidth_overhead;
  25 + int generation; /* in which allocation is valid */
  26 + bool allocated;
  27 + __be32 buffer[2];
  28 +};
  29 +
  30 +void fw_iso_resources_init(struct fw_iso_resources *r,
  31 + struct fw_unit *unit);
  32 +void fw_iso_resources_destroy(struct fw_iso_resources *r);
  33 +
  34 +int fw_iso_resources_allocate(struct fw_iso_resources *r,
  35 + unsigned int max_payload_bytes, int speed);
  36 +int fw_iso_resources_update(struct fw_iso_resources *r);
  37 +void fw_iso_resources_free(struct fw_iso_resources *r);
  38 +
  39 +#endif
sound/firewire/lib.c
  1 +/*
  2 + * miscellaneous helper functions
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/delay.h>
  9 +#include <linux/device.h>
  10 +#include <linux/firewire.h>
  11 +#include <linux/module.h>
  12 +#include "lib.h"
  13 +
  14 +#define ERROR_RETRY_DELAY_MS 5
  15 +
  16 +/**
  17 + * rcode_string - convert a firewire result code to a string
  18 + * @rcode: the result
  19 + */
  20 +const char *rcode_string(unsigned int rcode)
  21 +{
  22 + static const char *const names[] = {
  23 + [RCODE_COMPLETE] = "complete",
  24 + [RCODE_CONFLICT_ERROR] = "conflict error",
  25 + [RCODE_DATA_ERROR] = "data error",
  26 + [RCODE_TYPE_ERROR] = "type error",
  27 + [RCODE_ADDRESS_ERROR] = "address error",
  28 + [RCODE_SEND_ERROR] = "send error",
  29 + [RCODE_CANCELLED] = "cancelled",
  30 + [RCODE_BUSY] = "busy",
  31 + [RCODE_GENERATION] = "generation",
  32 + [RCODE_NO_ACK] = "no ack",
  33 + };
  34 +
  35 + if (rcode < ARRAY_SIZE(names) && names[rcode])
  36 + return names[rcode];
  37 + else
  38 + return "unknown";
  39 +}
  40 +EXPORT_SYMBOL(rcode_string);
  41 +
  42 +/**
  43 + * snd_fw_transaction - send a request and wait for its completion
  44 + * @unit: the driver's unit on the target device
  45 + * @tcode: the transaction code
  46 + * @offset: the address in the target's address space
  47 + * @buffer: input/output data
  48 + * @length: length of @buffer
  49 + *
  50 + * Submits an asynchronous request to the target device, and waits for the
  51 + * response. The node ID and the current generation are derived from @unit.
  52 + * On a bus reset or an error, the transaction is retried a few times.
  53 + * Returns zero on success, or a negative error code.
  54 + */
  55 +int snd_fw_transaction(struct fw_unit *unit, int tcode,
  56 + u64 offset, void *buffer, size_t length)
  57 +{
  58 + struct fw_device *device = fw_parent_device(unit);
  59 + int generation, rcode, tries = 0;
  60 +
  61 + for (;;) {
  62 + generation = device->generation;
  63 + smp_rmb(); /* node_id vs. generation */
  64 + rcode = fw_run_transaction(device->card, tcode,
  65 + device->node_id, generation,
  66 + device->max_speed, offset,
  67 + buffer, length);
  68 +
  69 + if (rcode == RCODE_COMPLETE)
  70 + return 0;
  71 +
  72 + if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
  73 + dev_err(&unit->device, "transaction failed: %s\n",
  74 + rcode_string(rcode));
  75 + return -EIO;
  76 + }
  77 +
  78 + msleep(ERROR_RETRY_DELAY_MS);
  79 + }
  80 +}
  81 +EXPORT_SYMBOL(snd_fw_transaction);
  82 +
  83 +MODULE_DESCRIPTION("FireWire audio helper functions");
  84 +MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  85 +MODULE_LICENSE("GPL v2");
sound/firewire/lib.h
  1 +#ifndef SOUND_FIREWIRE_LIB_H_INCLUDED
  2 +#define SOUND_FIREWIRE_LIB_H_INCLUDED
  3 +
  4 +#include <linux/firewire-constants.h>
  5 +#include <linux/types.h>
  6 +
  7 +struct fw_unit;
  8 +
  9 +int snd_fw_transaction(struct fw_unit *unit, int tcode,
  10 + u64 offset, void *buffer, size_t length);
  11 +const char *rcode_string(unsigned int rcode);
  12 +
  13 +/* returns true if retrying the transaction would not make sense */
  14 +static inline bool rcode_is_permanent_error(int rcode)
  15 +{
  16 + return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR;
  17 +}
  18 +
  19 +#endif
sound/firewire/packets-buffer.c
  1 +/*
  2 + * helpers for managing a buffer for many packets
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/firewire.h>
  9 +#include <linux/slab.h>
  10 +#include "packets-buffer.h"
  11 +
  12 +/**
  13 + * iso_packets_buffer_init - allocates the memory for packets
  14 + * @b: the buffer structure to initialize
  15 + * @unit: the device at the other end of the stream
  16 + * @count: the number of packets
  17 + * @packet_size: the (maximum) size of a packet, in bytes
  18 + * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE
  19 + */
  20 +int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
  21 + unsigned int count, unsigned int packet_size,
  22 + enum dma_data_direction direction)
  23 +{
  24 + unsigned int packets_per_page, pages;
  25 + unsigned int i, page_index, offset_in_page;
  26 + void *p;
  27 + int err;
  28 +
  29 + b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL);
  30 + if (!b->packets) {
  31 + err = -ENOMEM;
  32 + goto error;
  33 + }
  34 +
  35 + packet_size = L1_CACHE_ALIGN(packet_size);
  36 + packets_per_page = PAGE_SIZE / packet_size;
  37 + if (WARN_ON(!packets_per_page)) {
  38 + err = -EINVAL;
  39 + goto error;
  40 + }
  41 + pages = DIV_ROUND_UP(count, packets_per_page);
  42 +
  43 + err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card,
  44 + pages, direction);
  45 + if (err < 0)
  46 + goto err_packets;
  47 +
  48 + for (i = 0; i < count; ++i) {
  49 + page_index = i / packets_per_page;
  50 + p = page_address(b->iso_buffer.pages[page_index]);
  51 + offset_in_page = (i % packets_per_page) * packet_size;
  52 + b->packets[i].buffer = p + offset_in_page;
  53 + b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page;
  54 + }
  55 +
  56 + return 0;
  57 +
  58 +err_packets:
  59 + kfree(b->packets);
  60 +error:
  61 + return err;
  62 +}
  63 +
  64 +/**
  65 + * iso_packets_buffer_destroy - frees packet buffer resources
  66 + * @b: the buffer structure to free
  67 + * @unit: the device at the other end of the stream
  68 + */
  69 +void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
  70 + struct fw_unit *unit)
  71 +{
  72 + fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card);
  73 + kfree(b->packets);
  74 +}
sound/firewire/packets-buffer.h
  1 +#ifndef SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED
  2 +#define SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED
  3 +
  4 +#include <linux/dma-mapping.h>
  5 +#include <linux/firewire.h>
  6 +
  7 +/**
  8 + * struct iso_packets_buffer - manages a buffer for many packets
  9 + * @iso_buffer: the memory containing the packets
  10 + * @packets: an array, with each element pointing to one packet
  11 + */
  12 +struct iso_packets_buffer {
  13 + struct fw_iso_buffer iso_buffer;
  14 + struct {
  15 + void *buffer;
  16 + unsigned int offset;
  17 + } *packets;
  18 +};
  19 +
  20 +int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
  21 + unsigned int count, unsigned int packet_size,
  22 + enum dma_data_direction direction);
  23 +void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
  24 + struct fw_unit *unit);
  25 +
  26 +#endif
sound/firewire/speakers.c
  1 +/*
  2 + * OXFW970-based speakers driver
  3 + *
  4 + * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5 + * Licensed under the terms of the GNU General Public License, version 2.
  6 + */
  7 +
  8 +#include <linux/device.h>
  9 +#include <linux/firewire.h>
  10 +#include <linux/firewire-constants.h>
  11 +#include <linux/module.h>
  12 +#include <linux/mod_devicetable.h>
  13 +#include <linux/mutex.h>
  14 +#include <linux/slab.h>
  15 +#include <sound/control.h>
  16 +#include <sound/core.h>
  17 +#include <sound/initval.h>
  18 +#include <sound/pcm.h>
  19 +#include <sound/pcm_params.h>
  20 +#include "cmp.h"
  21 +#include "fcp.h"
  22 +#include "amdtp.h"
  23 +#include "lib.h"
  24 +
  25 +#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000)
  26 +/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
  27 +
  28 +#define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020)
  29 +#define OXFORD_HARDWARE_ID_OXFW970 0x39443841
  30 +#define OXFORD_HARDWARE_ID_OXFW971 0x39373100
  31 +
  32 +#define VENDOR_GRIFFIN 0x001292
  33 +#define VENDOR_LACIE 0x00d04b
  34 +
  35 +#define SPECIFIER_1394TA 0x00a02d
  36 +#define VERSION_AVC 0x010001
  37 +
  38 +struct device_info {
  39 + const char *driver_name;
  40 + const char *short_name;
  41 + const char *long_name;
  42 + int (*pcm_constraints)(struct snd_pcm_runtime *runtime);
  43 + unsigned int mixer_channels;
  44 + u8 mute_fb_id;
  45 + u8 volume_fb_id;
  46 +};
  47 +
  48 +struct fwspk {
  49 + struct snd_card *card;
  50 + struct fw_unit *unit;
  51 + const struct device_info *device_info;
  52 + struct snd_pcm_substream *pcm;
  53 + struct mutex mutex;
  54 + struct cmp_connection connection;
  55 + struct amdtp_out_stream stream;
  56 + bool stream_running;
  57 + bool mute;
  58 + s16 volume[6];
  59 + s16 volume_min;
  60 + s16 volume_max;
  61 +};
  62 +
  63 +MODULE_DESCRIPTION("FireWire speakers driver");
  64 +MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  65 +MODULE_LICENSE("GPL v2");
  66 +
  67 +static int firewave_rate_constraint(struct snd_pcm_hw_params *params,
  68 + struct snd_pcm_hw_rule *rule)
  69 +{
  70 + static unsigned int stereo_rates[] = { 48000, 96000 };
  71 + struct snd_interval *channels =
  72 + hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  73 + struct snd_interval *rate =
  74 + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  75 +
  76 + /* two channels work only at 48/96 kHz */
  77 + if (snd_interval_max(channels) < 6)
  78 + return snd_interval_list(rate, 2, stereo_rates, 0);
  79 + return 0;
  80 +}
  81 +
  82 +static int firewave_channels_constraint(struct snd_pcm_hw_params *params,
  83 + struct snd_pcm_hw_rule *rule)
  84 +{
  85 + static const struct snd_interval all_channels = { .min = 6, .max = 6 };
  86 + struct snd_interval *rate =
  87 + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  88 + struct snd_interval *channels =
  89 + hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  90 +
  91 + /* 32/44.1 kHz work only with all six channels */
  92 + if (snd_interval_max(rate) < 48000)
  93 + return snd_interval_refine(channels, &all_channels);
  94 + return 0;
  95 +}
  96 +
  97 +static int firewave_constraints(struct snd_pcm_runtime *runtime)
  98 +{
  99 + static unsigned int channels_list[] = { 2, 6 };
  100 + static struct snd_pcm_hw_constraint_list channels_list_constraint = {
  101 + .count = 2,
  102 + .list = channels_list,
  103 + };
  104 + int err;
  105 +
  106 + runtime->hw.rates = SNDRV_PCM_RATE_32000 |
  107 + SNDRV_PCM_RATE_44100 |
  108 + SNDRV_PCM_RATE_48000 |
  109 + SNDRV_PCM_RATE_96000;
  110 + runtime->hw.channels_max = 6;
  111 +
  112 + err = snd_pcm_hw_constraint_list(runtime, 0,
  113 + SNDRV_PCM_HW_PARAM_CHANNELS,
  114 + &channels_list_constraint);
  115 + if (err < 0)
  116 + return err;
  117 + err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  118 + firewave_rate_constraint, NULL,
  119 + SNDRV_PCM_HW_PARAM_CHANNELS, -1);
  120 + if (err < 0)
  121 + return err;
  122 + err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  123 + firewave_channels_constraint, NULL,
  124 + SNDRV_PCM_HW_PARAM_RATE, -1);
  125 + if (err < 0)
  126 + return err;
  127 +
  128 + return 0;
  129 +}
  130 +
  131 +static int lacie_speakers_constraints(struct snd_pcm_runtime *runtime)
  132 +{
  133 + runtime->hw.rates = SNDRV_PCM_RATE_32000 |
  134 + SNDRV_PCM_RATE_44100 |
  135 + SNDRV_PCM_RATE_48000 |
  136 + SNDRV_PCM_RATE_88200 |
  137 + SNDRV_PCM_RATE_96000;
  138 +
  139 + return 0;
  140 +}
  141 +
  142 +static int fwspk_open(struct snd_pcm_substream *substream)
  143 +{
  144 + static const struct snd_pcm_hardware hardware = {
  145 + .info = SNDRV_PCM_INFO_MMAP |
  146 + SNDRV_PCM_INFO_MMAP_VALID |
  147 + SNDRV_PCM_INFO_BATCH |
  148 + SNDRV_PCM_INFO_INTERLEAVED |
  149 + SNDRV_PCM_INFO_BLOCK_TRANSFER,
  150 + .formats = AMDTP_OUT_PCM_FORMAT_BITS,
  151 + .channels_min = 2,
  152 + .channels_max = 2,
  153 + .buffer_bytes_max = 4 * 1024 * 1024,
  154 + .period_bytes_min = 1,
  155 + .period_bytes_max = UINT_MAX,
  156 + .periods_min = 1,
  157 + .periods_max = UINT_MAX,
  158 + };
  159 + struct fwspk *fwspk = substream->private_data;
  160 + struct snd_pcm_runtime *runtime = substream->runtime;
  161 + int err;
  162 +
  163 + runtime->hw = hardware;
  164 +
  165 + err = fwspk->device_info->pcm_constraints(runtime);
  166 + if (err < 0)
  167 + return err;
  168 + err = snd_pcm_limit_hw_rates(runtime);
  169 + if (err < 0)
  170 + return err;
  171 +
  172 + err = snd_pcm_hw_constraint_minmax(runtime,
  173 + SNDRV_PCM_HW_PARAM_PERIOD_TIME,
  174 + 5000, 8192000);
  175 + if (err < 0)
  176 + return err;
  177 +
  178 + err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
  179 + if (err < 0)
  180 + return err;
  181 +
  182 + return 0;
  183 +}
  184 +
  185 +static int fwspk_close(struct snd_pcm_substream *substream)
  186 +{
  187 + return 0;
  188 +}
  189 +
  190 +static void fwspk_stop_stream(struct fwspk *fwspk)
  191 +{
  192 + if (fwspk->stream_running) {
  193 + amdtp_out_stream_stop(&fwspk->stream);
  194 + cmp_connection_break(&fwspk->connection);
  195 + fwspk->stream_running = false;
  196 + }
  197 +}
  198 +
  199 +static int fwspk_set_rate(struct fwspk *fwspk, unsigned int sfc)
  200 +{
  201 + u8 *buf;
  202 + int err;
  203 +
  204 + buf = kmalloc(8, GFP_KERNEL);
  205 + if (!buf)
  206 + return -ENOMEM;
  207 +
  208 + buf[0] = 0x00; /* AV/C, CONTROL */
  209 + buf[1] = 0xff; /* unit */
  210 + buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */
  211 + buf[3] = 0x00; /* plug 0 */
  212 + buf[4] = 0x90; /* format: audio */
  213 + buf[5] = 0x00 | sfc; /* AM824, frequency */
  214 + buf[6] = 0xff; /* SYT (not used) */
  215 + buf[7] = 0xff;
  216 +
  217 + err = fcp_avc_transaction(fwspk->unit, buf, 8, buf, 8,
  218 + BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
  219 + if (err < 0)
  220 + goto error;
  221 + if (err < 6 || buf[0] != 0x09 /* ACCEPTED */) {
  222 + dev_err(&fwspk->unit->device, "failed to set sample rate\n");
  223 + err = -EIO;
  224 + goto error;
  225 + }
  226 +
  227 + err = 0;
  228 +
  229 +error:
  230 + kfree(buf);
  231 +
  232 + return err;
  233 +}
  234 +
  235 +static int fwspk_hw_params(struct snd_pcm_substream *substream,
  236 + struct snd_pcm_hw_params *hw_params)
  237 +{
  238 + struct fwspk *fwspk = substream->private_data;
  239 + int err;
  240 +
  241 + mutex_lock(&fwspk->mutex);
  242 + fwspk_stop_stream(fwspk);
  243 + mutex_unlock(&fwspk->mutex);
  244 +
  245 + err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
  246 + params_buffer_bytes(hw_params));
  247 + if (err < 0)
  248 + goto error;
  249 +
  250 + amdtp_out_stream_set_rate(&fwspk->stream, params_rate(hw_params));
  251 + amdtp_out_stream_set_pcm(&fwspk->stream, params_channels(hw_params));
  252 +
  253 + amdtp_out_stream_set_pcm_format(&fwspk->stream,
  254 + params_format(hw_params));
  255 +
  256 + err = fwspk_set_rate(fwspk, fwspk->stream.sfc);
  257 + if (err < 0)
  258 + goto err_buffer;
  259 +
  260 + return 0;
  261 +
  262 +err_buffer:
  263 + snd_pcm_lib_free_vmalloc_buffer(substream);
  264 +error:
  265 + return err;
  266 +}
  267 +
  268 +static int fwspk_hw_free(struct snd_pcm_substream *substream)
  269 +{
  270 + struct fwspk *fwspk = substream->private_data;
  271 +
  272 + mutex_lock(&fwspk->mutex);
  273 + fwspk_stop_stream(fwspk);
  274 + mutex_unlock(&fwspk->mutex);
  275 +
  276 + return snd_pcm_lib_free_vmalloc_buffer(substream);
  277 +}
  278 +
  279 +static int fwspk_prepare(struct snd_pcm_substream *substream)
  280 +{
  281 + struct fwspk *fwspk = substream->private_data;
  282 + int err;
  283 +
  284 + mutex_lock(&fwspk->mutex);
  285 +
  286 + if (!fwspk->stream_running) {
  287 + err = cmp_connection_establish(&fwspk->connection,
  288 + amdtp_out_stream_get_max_payload(&fwspk->stream));
  289 + if (err < 0)
  290 + goto err_mutex;
  291 +
  292 + err = amdtp_out_stream_start(&fwspk->stream,
  293 + fwspk->connection.resources.channel,
  294 + fwspk->connection.speed);
  295 + if (err < 0)
  296 + goto err_connection;
  297 +
  298 + fwspk->stream_running = true;
  299 + }
  300 +
  301 + mutex_unlock(&fwspk->mutex);
  302 +
  303 + amdtp_out_stream_pcm_prepare(&fwspk->stream);
  304 +
  305 + return 0;
  306 +
  307 +err_connection:
  308 + cmp_connection_break(&fwspk->connection);
  309 +err_mutex:
  310 + mutex_unlock(&fwspk->mutex);
  311 +
  312 + return err;
  313 +}
  314 +
  315 +static int fwspk_trigger(struct snd_pcm_substream *substream, int cmd)
  316 +{
  317 + struct fwspk *fwspk = substream->private_data;
  318 + struct snd_pcm_substream *pcm;
  319 +
  320 + switch (cmd) {
  321 + case SNDRV_PCM_TRIGGER_START:
  322 + pcm = substream;
  323 + break;
  324 + case SNDRV_PCM_TRIGGER_STOP:
  325 + pcm = NULL;
  326 + break;
  327 + default:
  328 + return -EINVAL;
  329 + }
  330 + amdtp_out_stream_pcm_trigger(&fwspk->stream, pcm);
  331 + return 0;
  332 +}
  333 +
  334 +static snd_pcm_uframes_t fwspk_pointer(struct snd_pcm_substream *substream)
  335 +{
  336 + struct fwspk *fwspk = substream->private_data;
  337 +
  338 + return amdtp_out_stream_pcm_pointer(&fwspk->stream);
  339 +}
  340 +
  341 +static int fwspk_create_pcm(struct fwspk *fwspk)
  342 +{
  343 + static struct snd_pcm_ops ops = {
  344 + .open = fwspk_open,
  345 + .close = fwspk_close,
  346 + .ioctl = snd_pcm_lib_ioctl,
  347 + .hw_params = fwspk_hw_params,
  348 + .hw_free = fwspk_hw_free,
  349 + .prepare = fwspk_prepare,
  350 + .trigger = fwspk_trigger,
  351 + .pointer = fwspk_pointer,
  352 + .page = snd_pcm_lib_get_vmalloc_page,
  353 + .mmap = snd_pcm_lib_mmap_vmalloc,
  354 + };
  355 + struct snd_pcm *pcm;
  356 + int err;
  357 +
  358 + err = snd_pcm_new(fwspk->card, "OXFW970", 0, 1, 0, &pcm);
  359 + if (err < 0)
  360 + return err;
  361 + pcm->private_data = fwspk;
  362 + strcpy(pcm->name, fwspk->device_info->short_name);
  363 + fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
  364 + fwspk->pcm->ops = &ops;
  365 + return 0;
  366 +}
  367 +
  368 +enum control_action { CTL_READ, CTL_WRITE };
  369 +enum control_attribute {
  370 + CTL_MIN = 0x02,
  371 + CTL_MAX = 0x03,
  372 + CTL_CURRENT = 0x10,
  373 +};
  374 +
  375 +static int fwspk_mute_command(struct fwspk *fwspk, bool *value,
  376 + enum control_action action)
  377 +{
  378 + u8 *buf;
  379 + u8 response_ok;
  380 + int err;
  381 +
  382 + buf = kmalloc(11, GFP_KERNEL);
  383 + if (!buf)
  384 + return -ENOMEM;
  385 +
  386 + if (action == CTL_READ) {
  387 + buf[0] = 0x01; /* AV/C, STATUS */
  388 + response_ok = 0x0c; /* STABLE */
  389 + } else {
  390 + buf[0] = 0x00; /* AV/C, CONTROL */
  391 + response_ok = 0x09; /* ACCEPTED */
  392 + }
  393 + buf[1] = 0x08; /* audio unit 0 */
  394 + buf[2] = 0xb8; /* FUNCTION BLOCK */
  395 + buf[3] = 0x81; /* function block type: feature */
  396 + buf[4] = fwspk->device_info->mute_fb_id; /* function block ID */
  397 + buf[5] = 0x10; /* control attribute: current */
  398 + buf[6] = 0x02; /* selector length */
  399 + buf[7] = 0x00; /* audio channel number */
  400 + buf[8] = 0x01; /* control selector: mute */
  401 + buf[9] = 0x01; /* control data length */
  402 + if (action == CTL_READ)
  403 + buf[10] = 0xff;
  404 + else
  405 + buf[10] = *value ? 0x70 : 0x60;
  406 +
  407 + err = fcp_avc_transaction(fwspk->unit, buf, 11, buf, 11, 0x3fe);
  408 + if (err < 0)
  409 + goto error;
  410 + if (err < 11) {
  411 + dev_err(&fwspk->unit->device, "short FCP response\n");
  412 + err = -EIO;
  413 + goto error;
  414 + }
  415 + if (buf[0] != response_ok) {
  416 + dev_err(&fwspk->unit->device, "mute command failed\n");
  417 + err = -EIO;
  418 + goto error;
  419 + }
  420 + if (action == CTL_READ)
  421 + *value = buf[10] == 0x70;
  422 +
  423 + err = 0;
  424 +
  425 +error:
  426 + kfree(buf);
  427 +
  428 + return err;
  429 +}
  430 +
  431 +static int fwspk_volume_command(struct fwspk *fwspk, s16 *value,
  432 + unsigned int channel,
  433 + enum control_attribute attribute,
  434 + enum control_action action)
  435 +{
  436 + u8 *buf;
  437 + u8 response_ok;
  438 + int err;
  439 +
  440 + buf = kmalloc(12, GFP_KERNEL);
  441 + if (!buf)
  442 + return -ENOMEM;
  443 +
  444 + if (action == CTL_READ) {
  445 + buf[0] = 0x01; /* AV/C, STATUS */
  446 + response_ok = 0x0c; /* STABLE */
  447 + } else {
  448 + buf[0] = 0x00; /* AV/C, CONTROL */
  449 + response_ok = 0x09; /* ACCEPTED */
  450 + }
  451 + buf[1] = 0x08; /* audio unit 0 */
  452 + buf[2] = 0xb8; /* FUNCTION BLOCK */
  453 + buf[3] = 0x81; /* function block type: feature */
  454 + buf[4] = fwspk->device_info->volume_fb_id; /* function block ID */
  455 + buf[5] = attribute; /* control attribute */
  456 + buf[6] = 0x02; /* selector length */
  457 + buf[7] = channel; /* audio channel number */
  458 + buf[8] = 0x02; /* control selector: volume */
  459 + buf[9] = 0x02; /* control data length */
  460 + if (action == CTL_READ) {
  461 + buf[10] = 0xff;
  462 + buf[11] = 0xff;
  463 + } else {
  464 + buf[10] = *value >> 8;
  465 + buf[11] = *value;
  466 + }
  467 +
  468 + err = fcp_avc_transaction(fwspk->unit, buf, 12, buf, 12, 0x3fe);
  469 + if (err < 0)
  470 + goto error;
  471 + if (err < 12) {
  472 + dev_err(&fwspk->unit->device, "short FCP response\n");
  473 + err = -EIO;
  474 + goto error;
  475 + }
  476 + if (buf[0] != response_ok) {
  477 + dev_err(&fwspk->unit->device, "volume command failed\n");
  478 + err = -EIO;
  479 + goto error;
  480 + }
  481 + if (action == CTL_READ)
  482 + *value = (buf[10] << 8) | buf[11];
  483 +
  484 + err = 0;
  485 +
  486 +error:
  487 + kfree(buf);
  488 +
  489 + return err;
  490 +}
  491 +
  492 +static int fwspk_mute_get(struct snd_kcontrol *control,
  493 + struct snd_ctl_elem_value *value)
  494 +{
  495 + struct fwspk *fwspk = control->private_data;
  496 +
  497 + value->value.integer.value[0] = !fwspk->mute;
  498 +
  499 + return 0;
  500 +}
  501 +
  502 +static int fwspk_mute_put(struct snd_kcontrol *control,
  503 + struct snd_ctl_elem_value *value)
  504 +{
  505 + struct fwspk *fwspk = control->private_data;
  506 + bool mute;
  507 + int err;
  508 +
  509 + mute = !value->value.integer.value[0];
  510 +
  511 + if (mute == fwspk->mute)
  512 + return 0;
  513 +
  514 + err = fwspk_mute_command(fwspk, &mute, CTL_WRITE);
  515 + if (err < 0)
  516 + return err;
  517 + fwspk->mute = mute;
  518 +
  519 + return 1;
  520 +}
  521 +
  522 +static int fwspk_volume_info(struct snd_kcontrol *control,
  523 + struct snd_ctl_elem_info *info)
  524 +{
  525 + struct fwspk *fwspk = control->private_data;
  526 +
  527 + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  528 + info->count = fwspk->device_info->mixer_channels;
  529 + info->value.integer.min = fwspk->volume_min;
  530 + info->value.integer.max = fwspk->volume_max;
  531 +
  532 + return 0;
  533 +}
  534 +
  535 +static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 };
  536 +
  537 +static int fwspk_volume_get(struct snd_kcontrol *control,
  538 + struct snd_ctl_elem_value *value)
  539 +{
  540 + struct fwspk *fwspk = control->private_data;
  541 + unsigned int i;
  542 +
  543 + for (i = 0; i < fwspk->device_info->mixer_channels; ++i)
  544 + value->value.integer.value[channel_map[i]] = fwspk->volume[i];
  545 +
  546 + return 0;
  547 +}
  548 +
  549 +static int fwspk_volume_put(struct snd_kcontrol *control,
  550 + struct snd_ctl_elem_value *value)
  551 +{
  552 + struct fwspk *fwspk = control->private_data;
  553 + unsigned int i, changed_channels;
  554 + bool equal_values = true;
  555 + s16 volume;
  556 + int err;
  557 +
  558 + for (i = 0; i < fwspk->device_info->mixer_channels; ++i) {
  559 + if (value->value.integer.value[i] < fwspk->volume_min ||
  560 + value->value.integer.value[i] > fwspk->volume_max)
  561 + return -EINVAL;
  562 + if (value->value.integer.value[i] !=
  563 + value->value.integer.value[0])
  564 + equal_values = false;
  565 + }
  566 +
  567 + changed_channels = 0;
  568 + for (i = 0; i < fwspk->device_info->mixer_channels; ++i)
  569 + if (value->value.integer.value[channel_map[i]] !=
  570 + fwspk->volume[i])
  571 + changed_channels |= 1 << (i + 1);
  572 +
  573 + if (equal_values && changed_channels != 0)
  574 + changed_channels = 1 << 0;
  575 +
  576 + for (i = 0; i <= fwspk->device_info->mixer_channels; ++i) {
  577 + volume = value->value.integer.value[channel_map[i ? i - 1 : 0]];
  578 + if (changed_channels & (1 << i)) {
  579 + err = fwspk_volume_command(fwspk, &volume, i,
  580 + CTL_CURRENT, CTL_WRITE);
  581 + if (err < 0)
  582 + return err;
  583 + }
  584 + if (i > 0)
  585 + fwspk->volume[i - 1] = volume;
  586 + }
  587 +
  588 + return changed_channels != 0;
  589 +}
  590 +
  591 +static int fwspk_create_mixer(struct fwspk *fwspk)
  592 +{
  593 + static const struct snd_kcontrol_new controls[] = {
  594 + {
  595 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  596 + .name = "PCM Playback Switch",
  597 + .info = snd_ctl_boolean_mono_info,
  598 + .get = fwspk_mute_get,
  599 + .put = fwspk_mute_put,
  600 + },
  601 + {
  602 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  603 + .name = "PCM Playback Volume",
  604 + .info = fwspk_volume_info,
  605 + .get = fwspk_volume_get,
  606 + .put = fwspk_volume_put,
  607 + },
  608 + };
  609 + unsigned int i, first_ch;
  610 + int err;
  611 +
  612 + err = fwspk_volume_command(fwspk, &fwspk->volume_min,
  613 + 0, CTL_MIN, CTL_READ);
  614 + if (err < 0)
  615 + return err;
  616 + err = fwspk_volume_command(fwspk, &fwspk->volume_max,
  617 + 0, CTL_MAX, CTL_READ);
  618 + if (err < 0)
  619 + return err;
  620 +
  621 + err = fwspk_mute_command(fwspk, &fwspk->mute, CTL_READ);
  622 + if (err < 0)
  623 + return err;
  624 +
  625 + first_ch = fwspk->device_info->mixer_channels == 1 ? 0 : 1;
  626 + for (i = 0; i < fwspk->device_info->mixer_channels; ++i) {
  627 + err = fwspk_volume_command(fwspk, &fwspk->volume[i],
  628 + first_ch + i, CTL_CURRENT, CTL_READ);
  629 + if (err < 0)
  630 + return err;
  631 + }
  632 +
  633 + for (i = 0; i < ARRAY_SIZE(controls); ++i) {
  634 + err = snd_ctl_add(fwspk->card,
  635 + snd_ctl_new1(&controls[i], fwspk));
  636 + if (err < 0)
  637 + return err;
  638 + }
  639 +
  640 + return 0;
  641 +}
  642 +
  643 +static u32 fwspk_read_firmware_version(struct fw_unit *unit)
  644 +{
  645 + __be32 data;
  646 + int err;
  647 +
  648 + err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
  649 + OXFORD_FIRMWARE_ID_ADDRESS, &data, 4);
  650 + return err >= 0 ? be32_to_cpu(data) : 0;
  651 +}
  652 +
  653 +static void fwspk_card_free(struct snd_card *card)
  654 +{
  655 + struct fwspk *fwspk = card->private_data;
  656 + struct fw_device *dev = fw_parent_device(fwspk->unit);
  657 +
  658 + amdtp_out_stream_destroy(&fwspk->stream);
  659 + cmp_connection_destroy(&fwspk->connection);
  660 + fw_unit_put(fwspk->unit);
  661 + fw_device_put(dev);
  662 + mutex_destroy(&fwspk->mutex);
  663 +}
  664 +
  665 +static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
  666 +{
  667 + static const struct device_info griffin_firewave = {
  668 + .driver_name = "FireWave",
  669 + .short_name = "FireWave",
  670 + .long_name = "Griffin FireWave Surround",
  671 + .pcm_constraints = firewave_constraints,
  672 + .mixer_channels = 6,
  673 + .mute_fb_id = 0x01,
  674 + .volume_fb_id = 0x02,
  675 + };
  676 + static const struct device_info lacie_speakers = {
  677 + .driver_name = "FWSpeakers",
  678 + .short_name = "FireWire Speakers",
  679 + .long_name = "LaCie FireWire Speakers",
  680 + .pcm_constraints = lacie_speakers_constraints,
  681 + .mixer_channels = 1,
  682 + .mute_fb_id = 0x01,
  683 + .volume_fb_id = 0x01,
  684 + };
  685 + struct fw_csr_iterator i;
  686 + int key, value;
  687 +
  688 + fw_csr_iterator_init(&i, dev->config_rom);
  689 + while (fw_csr_iterator_next(&i, &key, &value))
  690 + if (key == CSR_VENDOR)
  691 + switch (value) {
  692 + case VENDOR_GRIFFIN:
  693 + return &griffin_firewave;
  694 + case VENDOR_LACIE:
  695 + return &lacie_speakers;
  696 + }
  697 +
  698 + return NULL;
  699 +}
  700 +
  701 +static int __devinit fwspk_probe(struct device *unit_dev)
  702 +{
  703 + struct fw_unit *unit = fw_unit(unit_dev);
  704 + struct fw_device *fw_dev = fw_parent_device(unit);
  705 + struct snd_card *card;
  706 + struct fwspk *fwspk;
  707 + u32 firmware;
  708 + int err;
  709 +
  710 + err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card);
  711 + if (err < 0)
  712 + return err;
  713 + snd_card_set_dev(card, unit_dev);
  714 +
  715 + fwspk = card->private_data;
  716 + fwspk->card = card;
  717 + mutex_init(&fwspk->mutex);
  718 + fw_device_get(fw_dev);
  719 + fwspk->unit = fw_unit_get(unit);
  720 + fwspk->device_info = fwspk_detect(fw_dev);
  721 + if (!fwspk->device_info) {
  722 + err = -ENODEV;
  723 + goto err_unit;
  724 + }
  725 +
  726 + err = cmp_connection_init(&fwspk->connection, unit, 0);
  727 + if (err < 0)
  728 + goto err_unit;
  729 +
  730 + err = amdtp_out_stream_init(&fwspk->stream, unit, CIP_NONBLOCKING);
  731 + if (err < 0)
  732 + goto err_connection;
  733 +
  734 + card->private_free = fwspk_card_free;
  735 +
  736 + strcpy(card->driver, fwspk->device_info->driver_name);
  737 + strcpy(card->shortname, fwspk->device_info->short_name);
  738 + firmware = fwspk_read_firmware_version(unit);
  739 + snprintf(card->longname, sizeof(card->longname),
  740 + "%s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
  741 + fwspk->device_info->long_name,
  742 + firmware >> 20, firmware & 0xffff,
  743 + fw_dev->config_rom[3], fw_dev->config_rom[4],
  744 + dev_name(&unit->device), 100 << fw_dev->max_speed);
  745 + strcpy(card->mixername, "OXFW970");
  746 +
  747 + err = fwspk_create_pcm(fwspk);
  748 + if (err < 0)
  749 + goto error;
  750 +
  751 + err = fwspk_create_mixer(fwspk);
  752 + if (err < 0)
  753 + goto error;
  754 +
  755 + err = snd_card_register(card);
  756 + if (err < 0)
  757 + goto error;
  758 +
  759 + dev_set_drvdata(unit_dev, fwspk);
  760 +
  761 + return 0;
  762 +
  763 +err_connection:
  764 + cmp_connection_destroy(&fwspk->connection);
  765 +err_unit:
  766 + fw_unit_put(fwspk->unit);
  767 + fw_device_put(fw_dev);
  768 + mutex_destroy(&fwspk->mutex);
  769 +error:
  770 + snd_card_free(card);
  771 + return err;
  772 +}
  773 +
  774 +static int __devexit fwspk_remove(struct device *dev)
  775 +{
  776 + struct fwspk *fwspk = dev_get_drvdata(dev);
  777 +
  778 + snd_card_disconnect(fwspk->card);
  779 +
  780 + mutex_lock(&fwspk->mutex);
  781 + amdtp_out_stream_pcm_abort(&fwspk->stream);
  782 + fwspk_stop_stream(fwspk);
  783 + mutex_unlock(&fwspk->mutex);
  784 +
  785 + snd_card_free_when_closed(fwspk->card);
  786 +
  787 + return 0;
  788 +}
  789 +
  790 +static void fwspk_bus_reset(struct fw_unit *unit)
  791 +{
  792 + struct fwspk *fwspk = dev_get_drvdata(&unit->device);
  793 +
  794 + fcp_bus_reset(fwspk->unit);
  795 +
  796 + if (cmp_connection_update(&fwspk->connection) < 0) {
  797 + mutex_lock(&fwspk->mutex);
  798 + amdtp_out_stream_pcm_abort(&fwspk->stream);
  799 + fwspk_stop_stream(fwspk);
  800 + mutex_unlock(&fwspk->mutex);
  801 + return;
  802 + }
  803 +
  804 + amdtp_out_stream_update(&fwspk->stream);
  805 +}
  806 +
  807 +static const struct ieee1394_device_id fwspk_id_table[] = {
  808 + {
  809 + .match_flags = IEEE1394_MATCH_VENDOR_ID |
  810 + IEEE1394_MATCH_MODEL_ID |
  811 + IEEE1394_MATCH_SPECIFIER_ID |
  812 + IEEE1394_MATCH_VERSION,
  813 + .vendor_id = VENDOR_GRIFFIN,
  814 + .model_id = 0x00f970,
  815 + .specifier_id = SPECIFIER_1394TA,
  816 + .version = VERSION_AVC,
  817 + },
  818 + {
  819 + .match_flags = IEEE1394_MATCH_VENDOR_ID |
  820 + IEEE1394_MATCH_MODEL_ID |
  821 + IEEE1394_MATCH_SPECIFIER_ID |
  822 + IEEE1394_MATCH_VERSION,
  823 + .vendor_id = VENDOR_LACIE,
  824 + .model_id = 0x00f970,
  825 + .specifier_id = SPECIFIER_1394TA,
  826 + .version = VERSION_AVC,
  827 + },
  828 + { }
  829 +};
  830 +MODULE_DEVICE_TABLE(ieee1394, fwspk_id_table);
  831 +
  832 +static struct fw_driver fwspk_driver = {
  833 + .driver = {
  834 + .owner = THIS_MODULE,
  835 + .name = KBUILD_MODNAME,
  836 + .bus = &fw_bus_type,
  837 + .probe = fwspk_probe,
  838 + .remove = __devexit_p(fwspk_remove),
  839 + },
  840 + .update = fwspk_bus_reset,
  841 + .id_table = fwspk_id_table,
  842 +};
  843 +
  844 +static int __init alsa_fwspk_init(void)
  845 +{
  846 + return driver_register(&fwspk_driver.driver);
  847 +}
  848 +
  849 +static void __exit alsa_fwspk_exit(void)
  850 +{
  851 + driver_unregister(&fwspk_driver.driver);
  852 +}
  853 +
  854 +module_init(alsa_fwspk_init);
  855 +module_exit(alsa_fwspk_exit);