diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2019-01-20 03:25:49 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-01-21 09:12:19 -0500 |
commit | ae3053c28b86f4f9d4480f6d3ac27f43d8e657ef (patch) | |
tree | 3087e103fdc406908885ca8ed7203e5adde48256 /sound/firewire | |
parent | e9e29cf8522093f146ab2c23194eee78dd84fa4e (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.c | 38 | ||||
-rw-r--r-- | sound/firewire/fireface/ff-stream.c | 38 | ||||
-rw-r--r-- | sound/firewire/fireface/ff.h | 3 |
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 | |||
16 | static 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 | ||
14 | static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer) | 50 | static 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 | ||
348 | const struct snd_ff_protocol snd_ff_protocol_ff800 = { | 384 | const 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 | ||
496 | const struct snd_ff_protocol snd_ff_protocol_ff400 = { | 533 | const 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 | ||
40 | static 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 | |||
74 | static inline void finish_session(struct snd_ff *ff) | 40 | static 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 | ||
80 | static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) | 46 | static 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 | ||
42 | enum snd_ff_stream_mode { | 40 | enum snd_ff_stream_mode { |
@@ -108,6 +106,7 @@ enum snd_ff_clock_src { | |||
108 | 106 | ||
109 | struct snd_ff_protocol { | 107 | struct 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); |