aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/oxfw/Makefile2
-rw-r--r--sound/firewire/oxfw/oxfw-stream.c80
-rw-r--r--sound/firewire/oxfw/oxfw.c130
-rw-r--r--sound/firewire/oxfw/oxfw.h56
4 files changed, 159 insertions, 109 deletions
diff --git a/sound/firewire/oxfw/Makefile b/sound/firewire/oxfw/Makefile
index 9ca49c0fdc40..e15c4c07b49d 100644
--- a/sound/firewire/oxfw/Makefile
+++ b/sound/firewire/oxfw/Makefile
@@ -1,2 +1,2 @@
1snd-oxfw-objs := oxfw.o 1snd-oxfw-objs := oxfw-stream.o oxfw.o
2obj-m += snd-oxfw.o 2obj-m += snd-oxfw.o
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c
new file mode 100644
index 000000000000..ebd156f3e29d
--- /dev/null
+++ b/sound/firewire/oxfw/oxfw-stream.c
@@ -0,0 +1,80 @@
1/*
2 * oxfw_stream.c - a part of driver for OXFW970/971 based devices
3 *
4 * Copyright (c) 2014 Takashi Sakamoto
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9#include "oxfw.h"
10
11int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw)
12{
13 int err;
14
15 err = cmp_connection_init(&oxfw->in_conn, oxfw->unit,
16 CMP_INPUT, 0);
17 if (err < 0)
18 goto end;
19
20 err = amdtp_stream_init(&oxfw->rx_stream, oxfw->unit,
21 AMDTP_OUT_STREAM, CIP_NONBLOCKING);
22 if (err < 0) {
23 amdtp_stream_destroy(&oxfw->rx_stream);
24 cmp_connection_destroy(&oxfw->in_conn);
25 }
26end:
27 return err;
28}
29
30static void stop_stream(struct snd_oxfw *oxfw)
31{
32 amdtp_stream_pcm_abort(&oxfw->rx_stream);
33 amdtp_stream_stop(&oxfw->rx_stream);
34 cmp_connection_break(&oxfw->in_conn);
35}
36
37int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw)
38{
39 int err = 0;
40
41 if (amdtp_streaming_error(&oxfw->rx_stream))
42 stop_stream(oxfw);
43
44 if (amdtp_stream_running(&oxfw->rx_stream))
45 goto end;
46
47 err = cmp_connection_establish(&oxfw->in_conn,
48 amdtp_stream_get_max_payload(&oxfw->rx_stream));
49 if (err < 0)
50 goto end;
51
52 err = amdtp_stream_start(&oxfw->rx_stream,
53 oxfw->in_conn.resources.channel,
54 oxfw->in_conn.speed);
55 if (err < 0)
56 stop_stream(oxfw);
57end:
58 return err;
59}
60
61void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw)
62{
63 stop_stream(oxfw);
64}
65
66void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw)
67{
68 stop_stream(oxfw);
69
70 amdtp_stream_destroy(&oxfw->rx_stream);
71 cmp_connection_destroy(&oxfw->in_conn);
72}
73
74void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw)
75{
76 if (cmp_connection_update(&oxfw->in_conn) < 0)
77 stop_stream(oxfw);
78 else
79 amdtp_stream_update(&oxfw->rx_stream);
80}
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index 55c687ef3247..40556677ea07 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -5,22 +5,7 @@
5 * Licensed under the terms of the GNU General Public License, version 2. 5 * Licensed under the terms of the GNU General Public License, version 2.
6 */ 6 */
7 7
8#include <linux/device.h> 8#include "oxfw.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 9
25#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) 10#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000)
26/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ 11/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
@@ -35,29 +20,6 @@
35#define SPECIFIER_1394TA 0x00a02d 20#define SPECIFIER_1394TA 0x00a02d
36#define VERSION_AVC 0x010001 21#define VERSION_AVC 0x010001
37 22
38struct 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
48struct snd_oxfw {
49 struct snd_card *card;
50 struct fw_unit *unit;
51 const struct device_info *device_info;
52 struct mutex mutex;
53 struct cmp_connection in_conn;
54 struct amdtp_stream rx_stream;
55 bool mute;
56 s16 volume[6];
57 s16 volume_min;
58 s16 volume_max;
59};
60
61MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver"); 23MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
62MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 24MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
63MODULE_LICENSE("GPL v2"); 25MODULE_LICENSE("GPL v2");
@@ -180,14 +142,6 @@ static int oxfw_close(struct snd_pcm_substream *substream)
180 return 0; 142 return 0;
181} 143}
182 144
183static void oxfw_stop_stream(struct snd_oxfw *oxfw)
184{
185 if (amdtp_stream_running(&oxfw->rx_stream)) {
186 amdtp_stream_stop(&oxfw->rx_stream);
187 cmp_connection_break(&oxfw->in_conn);
188 }
189}
190
191static int oxfw_hw_params(struct snd_pcm_substream *substream, 145static int oxfw_hw_params(struct snd_pcm_substream *substream,
192 struct snd_pcm_hw_params *hw_params) 146 struct snd_pcm_hw_params *hw_params)
193{ 147{
@@ -195,8 +149,8 @@ static int oxfw_hw_params(struct snd_pcm_substream *substream,
195 int err; 149 int err;
196 150
197 mutex_lock(&oxfw->mutex); 151 mutex_lock(&oxfw->mutex);
198 oxfw_stop_stream(oxfw); 152
199 mutex_unlock(&oxfw->mutex); 153 snd_oxfw_stream_stop_simplex(oxfw);
200 154
201 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 155 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
202 params_buffer_bytes(hw_params)); 156 params_buffer_bytes(hw_params));
@@ -223,6 +177,7 @@ static int oxfw_hw_params(struct snd_pcm_substream *substream,
223err_buffer: 177err_buffer:
224 snd_pcm_lib_free_vmalloc_buffer(substream); 178 snd_pcm_lib_free_vmalloc_buffer(substream);
225error: 179error:
180 mutex_unlock(&oxfw->mutex);
226 return err; 181 return err;
227} 182}
228 183
@@ -231,7 +186,7 @@ static int oxfw_hw_free(struct snd_pcm_substream *substream)
231 struct snd_oxfw *oxfw = substream->private_data; 186 struct snd_oxfw *oxfw = substream->private_data;
232 187
233 mutex_lock(&oxfw->mutex); 188 mutex_lock(&oxfw->mutex);
234 oxfw_stop_stream(oxfw); 189 snd_oxfw_stream_stop_simplex(oxfw);
235 mutex_unlock(&oxfw->mutex); 190 mutex_unlock(&oxfw->mutex);
236 191
237 return snd_pcm_lib_free_vmalloc_buffer(substream); 192 return snd_pcm_lib_free_vmalloc_buffer(substream);
@@ -244,33 +199,15 @@ static int oxfw_prepare(struct snd_pcm_substream *substream)
244 199
245 mutex_lock(&oxfw->mutex); 200 mutex_lock(&oxfw->mutex);
246 201
247 if (amdtp_streaming_error(&oxfw->rx_stream)) 202 snd_oxfw_stream_stop_simplex(oxfw);
248 oxfw_stop_stream(oxfw);
249
250 if (!amdtp_stream_running(&oxfw->rx_stream)) {
251 err = cmp_connection_establish(&oxfw->in_conn,
252 amdtp_stream_get_max_payload(&oxfw->rx_stream));
253 if (err < 0)
254 goto err_mutex;
255 203
256 err = amdtp_stream_start(&oxfw->rx_stream, 204 err = snd_oxfw_stream_start_simplex(oxfw);
257 oxfw->in_conn.resources.channel, 205 if (err < 0)
258 oxfw->in_conn.speed); 206 goto end;
259 if (err < 0)
260 goto err_connection;
261 }
262
263 mutex_unlock(&oxfw->mutex);
264 207
265 amdtp_stream_pcm_prepare(&oxfw->rx_stream); 208 amdtp_stream_pcm_prepare(&oxfw->rx_stream);
266 209end:
267 return 0;
268
269err_connection:
270 cmp_connection_break(&oxfw->in_conn);
271err_mutex:
272 mutex_unlock(&oxfw->mutex); 210 mutex_unlock(&oxfw->mutex);
273
274 return err; 211 return err;
275} 212}
276 213
@@ -615,9 +552,6 @@ static void oxfw_card_free(struct snd_card *card)
615{ 552{
616 struct snd_oxfw *oxfw = card->private_data; 553 struct snd_oxfw *oxfw = card->private_data;
617 554
618 amdtp_stream_destroy(&oxfw->rx_stream);
619 cmp_connection_destroy(&oxfw->in_conn);
620 fw_unit_put(oxfw->unit);
621 mutex_destroy(&oxfw->mutex); 555 mutex_destroy(&oxfw->mutex);
622} 556}
623 557
@@ -635,23 +569,13 @@ static int oxfw_probe(struct fw_unit *unit,
635 if (err < 0) 569 if (err < 0)
636 return err; 570 return err;
637 571
572 card->private_free = oxfw_card_free;
638 oxfw = card->private_data; 573 oxfw = card->private_data;
639 oxfw->card = card; 574 oxfw->card = card;
640 mutex_init(&oxfw->mutex); 575 mutex_init(&oxfw->mutex);
641 oxfw->unit = fw_unit_get(unit); 576 oxfw->unit = unit;
642 oxfw->device_info = (const struct device_info *)id->driver_data; 577 oxfw->device_info = (const struct device_info *)id->driver_data;
643 578
644 err = cmp_connection_init(&oxfw->in_conn, unit, CMP_INPUT, 0);
645 if (err < 0)
646 goto err_unit;
647
648 err = amdtp_stream_init(&oxfw->rx_stream, unit, AMDTP_OUT_STREAM,
649 CIP_NONBLOCKING);
650 if (err < 0)
651 goto err_connection;
652
653 card->private_free = oxfw_card_free;
654
655 strcpy(card->driver, oxfw->device_info->driver_name); 579 strcpy(card->driver, oxfw->device_info->driver_name);
656 strcpy(card->shortname, oxfw->device_info->short_name); 580 strcpy(card->shortname, oxfw->device_info->short_name);
657 firmware = oxfw_read_firmware_version(unit); 581 firmware = oxfw_read_firmware_version(unit);
@@ -671,19 +595,18 @@ static int oxfw_probe(struct fw_unit *unit,
671 if (err < 0) 595 if (err < 0)
672 goto error; 596 goto error;
673 597
674 err = snd_card_register(card); 598 err = snd_oxfw_stream_init_simplex(oxfw);
675 if (err < 0) 599 if (err < 0)
676 goto error; 600 goto error;
677 601
602 err = snd_card_register(card);
603 if (err < 0) {
604 snd_oxfw_stream_destroy_simplex(oxfw);
605 goto error;
606 }
678 dev_set_drvdata(&unit->device, oxfw); 607 dev_set_drvdata(&unit->device, oxfw);
679 608
680 return 0; 609 return 0;
681
682err_connection:
683 cmp_connection_destroy(&oxfw->in_conn);
684err_unit:
685 fw_unit_put(oxfw->unit);
686 mutex_destroy(&oxfw->mutex);
687error: 610error:
688 snd_card_free(card); 611 snd_card_free(card);
689 return err; 612 return err;
@@ -695,27 +618,18 @@ static void oxfw_bus_reset(struct fw_unit *unit)
695 618
696 fcp_bus_reset(oxfw->unit); 619 fcp_bus_reset(oxfw->unit);
697 620
698 if (cmp_connection_update(&oxfw->in_conn) < 0) { 621 mutex_lock(&oxfw->mutex);
699 amdtp_stream_pcm_abort(&oxfw->rx_stream); 622 snd_oxfw_stream_update_simplex(oxfw);
700 mutex_lock(&oxfw->mutex); 623 mutex_unlock(&oxfw->mutex);
701 oxfw_stop_stream(oxfw);
702 mutex_unlock(&oxfw->mutex);
703 return;
704 }
705
706 amdtp_stream_update(&oxfw->rx_stream);
707} 624}
708 625
709static void oxfw_remove(struct fw_unit *unit) 626static void oxfw_remove(struct fw_unit *unit)
710{ 627{
711 struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 628 struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
712 629
713 amdtp_stream_pcm_abort(&oxfw->rx_stream);
714 snd_card_disconnect(oxfw->card); 630 snd_card_disconnect(oxfw->card);
715 631
716 mutex_lock(&oxfw->mutex); 632 snd_oxfw_stream_destroy_simplex(oxfw);
717 oxfw_stop_stream(oxfw);
718 mutex_unlock(&oxfw->mutex);
719 633
720 snd_card_free_when_closed(oxfw->card); 634 snd_card_free_when_closed(oxfw->card);
721} 635}
diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h
new file mode 100644
index 000000000000..e5836e02b48c
--- /dev/null
+++ b/sound/firewire/oxfw/oxfw.h
@@ -0,0 +1,56 @@
1/*
2 * oxfw.h - a part of driver for OXFW970/971 based devices
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
16#include <sound/control.h>
17#include <sound/core.h>
18#include <sound/initval.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21
22#include "../lib.h"
23#include "../fcp.h"
24#include "../packets-buffer.h"
25#include "../iso-resources.h"
26#include "../amdtp.h"
27#include "../cmp.h"
28
29struct device_info {
30 const char *driver_name;
31 const char *short_name;
32 const char *long_name;
33 int (*pcm_constraints)(struct snd_pcm_runtime *runtime);
34 unsigned int mixer_channels;
35 u8 mute_fb_id;
36 u8 volume_fb_id;
37};
38
39struct snd_oxfw {
40 struct snd_card *card;
41 struct fw_unit *unit;
42 const struct device_info *device_info;
43 struct mutex mutex;
44 struct cmp_connection in_conn;
45 struct amdtp_stream rx_stream;
46 bool mute;
47 s16 volume[6];
48 s16 volume_min;
49 s16 volume_max;
50};
51
52int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw);
53int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw);
54void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw);
55void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw);
56void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw);