summaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2019-01-20 03:25:49 -0500
committerTakashi Iwai <tiwai@suse.de>2019-01-21 09:12:19 -0500
commitae3053c28b86f4f9d4480f6d3ac27f43d8e657ef (patch)
tree3087e103fdc406908885ca8ed7203e5adde48256 /sound/firewire
parente9e29cf8522093f146ab2c23194eee78dd84fa4e (diff)
ALSA: fireface: add protocol-dependent operation to switch mode to fetch PCM frame
This commit adds a member for a callback function to switch frame fetching mode to former protocol. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/fireface/ff-protocol-former.c38
-rw-r--r--sound/firewire/fireface/ff-stream.c38
-rw-r--r--sound/firewire/fireface/ff.h3
3 files changed, 41 insertions, 38 deletions
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
index 5f97e7fc7281..279bd032acf0 100644
--- a/sound/firewire/fireface/ff-protocol-former.c
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -10,6 +10,42 @@
10#include "ff.h" 10#include "ff.h"
11 11
12#define FORMER_REG_SYNC_STATUS 0x0000801c0000ull 12#define FORMER_REG_SYNC_STATUS 0x0000801c0000ull
13/* For block write request. */
14#define FORMER_REG_FETCH_PCM_FRAMES 0x0000801c0000ull
15
16static int former_switch_fetching_mode(struct snd_ff *ff, bool enable)
17{
18 unsigned int count;
19 __le32 *reg;
20 int i;
21 int err;
22
23 count = 0;
24 for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
25 count = max(count, ff->spec->pcm_playback_channels[i]);
26
27 reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
28 if (!reg)
29 return -ENOMEM;
30
31 if (!enable) {
32 /*
33 * Each quadlet is corresponding to data channels in a data
34 * blocks in reverse order. Precisely, quadlets for available
35 * data channels should be enabled. Here, I take second best
36 * to fetch PCM frames from all of data channels regardless of
37 * stf.
38 */
39 for (i = 0; i < count; ++i)
40 reg[i] = cpu_to_le32(0x00000001);
41 }
42
43 err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
44 FORMER_REG_FETCH_PCM_FRAMES, reg,
45 sizeof(__le32) * count, 0);
46 kfree(reg);
47 return err;
48}
13 49
14static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer) 50static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer)
15{ 51{
@@ -347,6 +383,7 @@ static void ff800_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length)
347 383
348const struct snd_ff_protocol snd_ff_protocol_ff800 = { 384const struct snd_ff_protocol snd_ff_protocol_ff800 = {
349 .handle_midi_msg = ff800_handle_midi_msg, 385 .handle_midi_msg = ff800_handle_midi_msg,
386 .switch_fetching_mode = former_switch_fetching_mode,
350 .begin_session = ff800_begin_session, 387 .begin_session = ff800_begin_session,
351 .finish_session = ff800_finish_session, 388 .finish_session = ff800_finish_session,
352 .dump_status = former_dump_status, 389 .dump_status = former_dump_status,
@@ -495,6 +532,7 @@ static void ff400_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length)
495 532
496const struct snd_ff_protocol snd_ff_protocol_ff400 = { 533const struct snd_ff_protocol snd_ff_protocol_ff400 = {
497 .handle_midi_msg = ff400_handle_midi_msg, 534 .handle_midi_msg = ff400_handle_midi_msg,
535 .switch_fetching_mode = former_switch_fetching_mode,
498 .begin_session = ff400_begin_session, 536 .begin_session = ff400_begin_session,
499 .finish_session = ff400_finish_session, 537 .finish_session = ff400_finish_session,
500 .dump_status = former_dump_status, 538 .dump_status = former_dump_status,
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index a490e4553721..43e1e2679798 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -37,44 +37,10 @@ static void release_resources(struct snd_ff *ff)
37 fw_iso_resources_free(&ff->rx_resources); 37 fw_iso_resources_free(&ff->rx_resources);
38} 38}
39 39
40static int switch_fetching_mode(struct snd_ff *ff, bool enable)
41{
42 unsigned int count;
43 __le32 *reg;
44 int i;
45 int err;
46
47 count = 0;
48 for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
49 count = max(count, ff->spec->pcm_playback_channels[i]);
50
51 reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
52 if (!reg)
53 return -ENOMEM;
54
55 if (!enable) {
56 /*
57 * Each quadlet is corresponding to data channels in a data
58 * blocks in reverse order. Precisely, quadlets for available
59 * data channels should be enabled. Here, I take second best
60 * to fetch PCM frames from all of data channels regardless of
61 * stf.
62 */
63 for (i = 0; i < count; ++i)
64 reg[i] = cpu_to_le32(0x00000001);
65 }
66
67 err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
68 SND_FF_REG_FETCH_PCM_FRAMES, reg,
69 sizeof(__le32) * count, 0);
70 kfree(reg);
71 return err;
72}
73
74static inline void finish_session(struct snd_ff *ff) 40static inline void finish_session(struct snd_ff *ff)
75{ 41{
76 ff->spec->protocol->finish_session(ff); 42 ff->spec->protocol->finish_session(ff);
77 switch_fetching_mode(ff, false); 43 ff->spec->protocol->switch_fetching_mode(ff, false);
78} 44}
79 45
80static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) 46static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir)
@@ -206,7 +172,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
206 goto error; 172 goto error;
207 } 173 }
208 174
209 err = switch_fetching_mode(ff, true); 175 err = ff->spec->protocol->switch_fetching_mode(ff, true);
210 if (err < 0) 176 if (err < 0)
211 goto error; 177 goto error;
212 } 178 }
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index 3f22b8d84e36..29f55518bf85 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -35,8 +35,6 @@
35#define SND_FF_IN_MIDI_PORTS 2 35#define SND_FF_IN_MIDI_PORTS 2
36#define SND_FF_OUT_MIDI_PORTS 2 36#define SND_FF_OUT_MIDI_PORTS 2
37 37
38/* For block write request. */
39#define SND_FF_REG_FETCH_PCM_FRAMES 0x0000801c0000ull
40#define SND_FF_REG_CLOCK_CONFIG 0x0000801c0004ull 38#define SND_FF_REG_CLOCK_CONFIG 0x0000801c0004ull
41 39
42enum snd_ff_stream_mode { 40enum snd_ff_stream_mode {
@@ -108,6 +106,7 @@ enum snd_ff_clock_src {
108 106
109struct snd_ff_protocol { 107struct snd_ff_protocol {
110 void (*handle_midi_msg)(struct snd_ff *ff, __le32 *buf, size_t length); 108 void (*handle_midi_msg)(struct snd_ff *ff, __le32 *buf, size_t length);
109 int (*switch_fetching_mode)(struct snd_ff *ff, bool enable);
111 int (*begin_session)(struct snd_ff *ff, unsigned int rate); 110 int (*begin_session)(struct snd_ff *ff, unsigned int rate);
112 void (*finish_session)(struct snd_ff *ff); 111 void (*finish_session)(struct snd_ff *ff);
113 void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer); 112 void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer);