diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/sound/firewire/bebob | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/sound/firewire/bebob')
-rw-r--r-- | kernel/sound/firewire/bebob/Makefile | 2 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob.c | 26 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob.h | 54 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_focusrite.c | 59 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_maudio.c | 57 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_midi.c | 24 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_pcm.c | 50 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_proc.c | 28 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_stream.c | 204 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_terratec.c | 40 | ||||
-rw-r--r-- | kernel/sound/firewire/bebob/bebob_yamaha.c | 26 |
11 files changed, 366 insertions, 204 deletions
diff --git a/kernel/sound/firewire/bebob/Makefile b/kernel/sound/firewire/bebob/Makefile index 6cf470c80..af7ed6643 100644 --- a/kernel/sound/firewire/bebob/Makefile +++ b/kernel/sound/firewire/bebob/Makefile @@ -1,4 +1,4 @@ snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ bebob_pcm.o bebob_hwdep.o bebob_terratec.o bebob_yamaha.o \ bebob_focusrite.o bebob_maudio.o bebob.o -obj-m += snd-bebob.o +obj-$(CONFIG_SND_BEBOB) += snd-bebob.o diff --git a/kernel/sound/firewire/bebob/bebob.c b/kernel/sound/firewire/bebob/bebob.c index 611b7dae7..091290d1f 100644 --- a/kernel/sound/firewire/bebob/bebob.c +++ b/kernel/sound/firewire/bebob/bebob.c @@ -33,6 +33,7 @@ static DEFINE_MUTEX(devices_mutex); static DECLARE_BITMAP(devices_used, SNDRV_CARDS); /* Offsets from information register. */ +#define INFO_OFFSET_BEBOB_VERSION 0x08 #define INFO_OFFSET_GUID 0x10 #define INFO_OFFSET_HW_MODEL_ID 0x18 #define INFO_OFFSET_HW_MODEL_REVISION 0x1c @@ -40,7 +41,8 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_EDIROL 0x000040ab #define VEN_PRESONUS 0x00000a92 #define VEN_BRIDGECO 0x000007f5 -#define VEN_MACKIE 0x0000000f +#define VEN_MACKIE1 0x0000000f +#define VEN_MACKIE2 0x00000ff2 #define VEN_STANTON 0x00001260 #define VEN_TASCAM 0x0000022e #define VEN_BEHRINGER 0x00001564 @@ -57,6 +59,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_FOCUSRITE 0x0000130e #define VEN_MAUDIO1 0x00000d6c #define VEN_MAUDIO2 0x000007f5 +#define VEN_DIGIDESIGN 0x00a07e #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 @@ -72,6 +75,7 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) u32 hw_id; u32 data[2] = {0}; u32 revision; + u32 version; int err; /* get vendor name from root directory */ @@ -104,6 +108,12 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id) if (err < 0) goto end; + err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_BEBOB_VERSION, + &version); + if (err < 0) + goto end; + bebob->version = version; + strcpy(bebob->card->driver, "BeBoB"); strcpy(bebob->card->shortname, model); strcpy(bebob->card->mixername, model); @@ -325,7 +335,7 @@ static void bebob_remove(struct fw_unit *unit) snd_card_free_when_closed(bebob->card); } -static struct snd_bebob_rate_spec normal_rate_spec = { +static const struct snd_bebob_rate_spec normal_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate }; @@ -351,9 +361,9 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* BridgeCo, Audio5 */ SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ - SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal), + SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal), /* Mackie, d.2 (Firewire Option) */ - SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal), + SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal), /* Stanton, ScratchAmp */ SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), /* Tascam, IF-FW DM */ @@ -364,6 +374,10 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), /* Behringer, Digital Mixer X32 series (X-UF Card) */ SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), + /* Behringer, F-Control Audio 1616 */ + SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x001616, &spec_normal), + /* Behringer, F-Control Audio 610 */ + SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x000610, &spec_normal), /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), @@ -433,11 +447,11 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* M-Audio ProjectMix */ SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, &maudio_special_spec), + /* Digidesign Mbox 2 Pro */ + SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), /* IDs are unknown but able to be supported */ /* Apogee, Mini-ME Firewire */ /* Apogee, Mini-DAC Firewire */ - /* Behringer, F-Control Audio 1616 */ - /* Behringer, F-Control Audio 610 */ /* Cakawalk, Sonar Power Studio 66 */ /* CME, UF400e */ /* ESI, Quotafire XL */ diff --git a/kernel/sound/firewire/bebob/bebob.h b/kernel/sound/firewire/bebob/bebob.h index dfbcd2331..4d8fcc78e 100644 --- a/kernel/sound/firewire/bebob/bebob.h +++ b/kernel/sound/firewire/bebob/bebob.h @@ -31,7 +31,7 @@ #include "../fcp.h" #include "../packets-buffer.h" #include "../iso-resources.h" -#include "../amdtp.h" +#include "../amdtp-am824.h" #include "../cmp.h" /* basic register addresses on DM1000/DM1100/DM1500 */ @@ -49,10 +49,15 @@ struct snd_bebob_stream_formation { extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; /* device specific operations */ -#define SND_BEBOB_CLOCK_INTERNAL "Internal" +enum snd_bebob_clock_type { + SND_BEBOB_CLOCK_TYPE_INTERNAL = 0, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, + SND_BEBOB_CLOCK_TYPE_SYT, +}; struct snd_bebob_clock_spec { unsigned int num; const char *const *labels; + enum snd_bebob_clock_type *types; int (*get)(struct snd_bebob *bebob, unsigned int *id); }; struct snd_bebob_rate_spec { @@ -65,9 +70,9 @@ struct snd_bebob_meter_spec { int (*get)(struct snd_bebob *bebob, u32 *target, unsigned int size); }; struct snd_bebob_spec { - struct snd_bebob_clock_spec *clock; - struct snd_bebob_rate_spec *rate; - struct snd_bebob_meter_spec *meter; + const struct snd_bebob_clock_spec *clock; + const struct snd_bebob_rate_spec *rate; + const struct snd_bebob_meter_spec *meter; }; struct snd_bebob { @@ -92,8 +97,7 @@ struct snd_bebob { struct amdtp_stream rx_stream; struct cmp_connection out_conn; struct cmp_connection in_conn; - atomic_t capture_substreams; - atomic_t playback_substreams; + atomic_t substreams_counter; struct snd_bebob_stream_formation tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; @@ -110,6 +114,9 @@ struct snd_bebob { /* for M-Audio special devices */ void *maudio_special_quirk; bool deferred_registration; + + /* For BeBoB version quirk. */ + unsigned int version; }; static inline int @@ -159,7 +166,8 @@ enum avc_bridgeco_plug_type { AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, - AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05 + AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05, + AVC_BRIDGECO_PLUG_TYPE_ADDITION = 0x06 }; static inline void avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], @@ -205,8 +213,8 @@ int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit, /* for AMDTP streaming */ int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate); int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate); -int snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, - bool *internal); +int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, + enum snd_bebob_clock_type *src); int snd_bebob_stream_discover(struct snd_bebob *bebob); int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); @@ -227,19 +235,19 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob); int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); /* model specific operations */ -extern struct snd_bebob_spec phase88_rack_spec; -extern struct snd_bebob_spec phase24_series_spec; -extern struct snd_bebob_spec yamaha_go_spec; -extern struct snd_bebob_spec saffirepro_26_spec; -extern struct snd_bebob_spec saffirepro_10_spec; -extern struct snd_bebob_spec saffire_le_spec; -extern struct snd_bebob_spec saffire_spec; -extern struct snd_bebob_spec maudio_fw410_spec; -extern struct snd_bebob_spec maudio_audiophile_spec; -extern struct snd_bebob_spec maudio_solo_spec; -extern struct snd_bebob_spec maudio_ozonic_spec; -extern struct snd_bebob_spec maudio_nrv10_spec; -extern struct snd_bebob_spec maudio_special_spec; +extern const struct snd_bebob_spec phase88_rack_spec; +extern const struct snd_bebob_spec phase24_series_spec; +extern const struct snd_bebob_spec yamaha_go_spec; +extern const struct snd_bebob_spec saffirepro_26_spec; +extern const struct snd_bebob_spec saffirepro_10_spec; +extern const struct snd_bebob_spec saffire_le_spec; +extern const struct snd_bebob_spec saffire_spec; +extern const struct snd_bebob_spec maudio_fw410_spec; +extern const struct snd_bebob_spec maudio_audiophile_spec; +extern const struct snd_bebob_spec maudio_solo_spec; +extern const struct snd_bebob_spec maudio_ozonic_spec; +extern const struct snd_bebob_spec maudio_nrv10_spec; +extern const struct snd_bebob_spec maudio_special_spec; int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814); int snd_bebob_maudio_load_firmware(struct fw_unit *unit); diff --git a/kernel/sound/firewire/bebob/bebob_focusrite.c b/kernel/sound/firewire/bebob/bebob_focusrite.c index fc67c1b7c..f11090057 100644 --- a/kernel/sound/firewire/bebob/bebob_focusrite.c +++ b/kernel/sound/firewire/bebob/bebob_focusrite.c @@ -103,11 +103,17 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) &data, sizeof(__be32), 0); } -static const char *const saffirepro_10_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" +static enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ }; -static const char *const saffirepro_26_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" +static enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT1 */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT2 */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ }; /* Value maps between registers and labels for SaffirePro 10/26. */ static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { @@ -178,7 +184,7 @@ saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) goto end; /* depending on hardware, use a different mapping */ - if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) + if (bebob->spec->clock->types == saffirepro_10_clk_src_types) map = saffirepro_clk_maps[0]; else map = saffirepro_clk_maps[1]; @@ -194,9 +200,10 @@ end: return err; } -struct snd_bebob_spec saffire_le_spec; -static const char *const saffire_both_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" +const struct snd_bebob_spec saffire_le_spec; +static enum snd_bebob_clock_type saffire_both_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, }; static int saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) @@ -222,7 +229,7 @@ static const char *const saffire_meter_labels[] = { static int saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) { - struct snd_bebob_meter_spec *spec = bebob->spec->meter; + const struct snd_bebob_meter_spec *spec = bebob->spec->meter; unsigned int channels; u64 offset; int err; @@ -253,60 +260,60 @@ saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) return err; } -static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { +static const struct snd_bebob_rate_spec saffirepro_both_rate_spec = { .get = &saffirepro_both_clk_freq_get, .set = &saffirepro_both_clk_freq_set, }; /* Saffire Pro 26 I/O */ -static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { - .num = ARRAY_SIZE(saffirepro_26_clk_src_labels), - .labels = saffirepro_26_clk_src_labels, +static const struct snd_bebob_clock_spec saffirepro_26_clk_spec = { + .num = ARRAY_SIZE(saffirepro_26_clk_src_types), + .types = saffirepro_26_clk_src_types, .get = &saffirepro_both_clk_src_get, }; -struct snd_bebob_spec saffirepro_26_spec = { +const struct snd_bebob_spec saffirepro_26_spec = { .clock = &saffirepro_26_clk_spec, .rate = &saffirepro_both_rate_spec, .meter = NULL }; /* Saffire Pro 10 I/O */ -static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { - .num = ARRAY_SIZE(saffirepro_10_clk_src_labels), - .labels = saffirepro_10_clk_src_labels, +static const struct snd_bebob_clock_spec saffirepro_10_clk_spec = { + .num = ARRAY_SIZE(saffirepro_10_clk_src_types), + .types = saffirepro_10_clk_src_types, .get = &saffirepro_both_clk_src_get, }; -struct snd_bebob_spec saffirepro_10_spec = { +const struct snd_bebob_spec saffirepro_10_spec = { .clock = &saffirepro_10_clk_spec, .rate = &saffirepro_both_rate_spec, .meter = NULL }; -static struct snd_bebob_rate_spec saffire_both_rate_spec = { +static const struct snd_bebob_rate_spec saffire_both_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; -static struct snd_bebob_clock_spec saffire_both_clk_spec = { - .num = ARRAY_SIZE(saffire_both_clk_src_labels), - .labels = saffire_both_clk_src_labels, +static const struct snd_bebob_clock_spec saffire_both_clk_spec = { + .num = ARRAY_SIZE(saffire_both_clk_src_types), + .types = saffire_both_clk_src_types, .get = &saffire_both_clk_src_get, }; /* Saffire LE */ -static struct snd_bebob_meter_spec saffire_le_meter_spec = { +static const struct snd_bebob_meter_spec saffire_le_meter_spec = { .num = ARRAY_SIZE(saffire_le_meter_labels), .labels = saffire_le_meter_labels, .get = &saffire_meter_get, }; -struct snd_bebob_spec saffire_le_spec = { +const struct snd_bebob_spec saffire_le_spec = { .clock = &saffire_both_clk_spec, .rate = &saffire_both_rate_spec, .meter = &saffire_le_meter_spec }; /* Saffire */ -static struct snd_bebob_meter_spec saffire_meter_spec = { +static const struct snd_bebob_meter_spec saffire_meter_spec = { .num = ARRAY_SIZE(saffire_meter_labels), .labels = saffire_meter_labels, .get = &saffire_meter_get, }; -struct snd_bebob_spec saffire_spec = { +const struct snd_bebob_spec saffire_spec = { .clock = &saffire_both_clk_spec, .rate = &saffire_both_rate_spec, .meter = &saffire_meter_spec diff --git a/kernel/sound/firewire/bebob/bebob_maudio.c b/kernel/sound/firewire/bebob/bebob_maudio.c index 9ee25a63f..07e5abdbc 100644 --- a/kernel/sound/firewire/bebob/bebob_maudio.c +++ b/kernel/sound/firewire/bebob/bebob_maudio.c @@ -340,9 +340,12 @@ end: } /* Clock source control for special firmware */ -static const char *const special_clk_labels[] = { - SND_BEBOB_CLOCK_INTERNAL " with Digital Mute", "Digital", - "Word Clock", SND_BEBOB_CLOCK_INTERNAL}; +static enum snd_bebob_clock_type special_clk_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, /* With digital mute */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* SPDIF/ADAT */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ + SND_BEBOB_CLOCK_TYPE_INTERNAL, +}; static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) { struct special_params *params = bebob->maudio_special_quirk; @@ -352,7 +355,13 @@ static int special_clk_get(struct snd_bebob *bebob, unsigned int *id) static int special_clk_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *einf) { - return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_labels), + static const char *const special_clk_labels[] = { + "Internal with Digital Mute", + "Digital", + "Word Clock", + "Internal" + }; + return snd_ctl_enum_info(einf, 1, ARRAY_SIZE(special_clk_types), special_clk_labels); } static int special_clk_ctl_get(struct snd_kcontrol *kctl, @@ -371,7 +380,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, int err, id; id = uval->value.enumerated.item[0]; - if (id >= ARRAY_SIZE(special_clk_labels)) + if (id >= ARRAY_SIZE(special_clk_types)) return -EINVAL; mutex_lock(&bebob->mutex); @@ -619,7 +628,7 @@ static const char *const special_meter_labels[] = { static int special_meter_get(struct snd_bebob *bebob, u32 *target, unsigned int size) { - u16 *buf; + __be16 *buf; unsigned int i, c, channels; int err; @@ -678,7 +687,7 @@ static const char *const nrv10_meter_labels[] = { static int normal_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) { - struct snd_bebob_meter_spec *spec = bebob->spec->meter; + const struct snd_bebob_meter_spec *spec = bebob->spec->meter; unsigned int c, channels; int err; @@ -703,85 +712,85 @@ end: } /* for special customized devices */ -static struct snd_bebob_rate_spec special_rate_spec = { +static const struct snd_bebob_rate_spec special_rate_spec = { .get = &special_get_rate, .set = &special_set_rate, }; -static struct snd_bebob_clock_spec special_clk_spec = { - .num = ARRAY_SIZE(special_clk_labels), - .labels = special_clk_labels, +static const struct snd_bebob_clock_spec special_clk_spec = { + .num = ARRAY_SIZE(special_clk_types), + .types = special_clk_types, .get = &special_clk_get, }; -static struct snd_bebob_meter_spec special_meter_spec = { +static const struct snd_bebob_meter_spec special_meter_spec = { .num = ARRAY_SIZE(special_meter_labels), .labels = special_meter_labels, .get = &special_meter_get }; -struct snd_bebob_spec maudio_special_spec = { +const struct snd_bebob_spec maudio_special_spec = { .clock = &special_clk_spec, .rate = &special_rate_spec, .meter = &special_meter_spec }; /* Firewire 410 specification */ -static struct snd_bebob_rate_spec usual_rate_spec = { +static const struct snd_bebob_rate_spec usual_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; -static struct snd_bebob_meter_spec fw410_meter_spec = { +static const struct snd_bebob_meter_spec fw410_meter_spec = { .num = ARRAY_SIZE(fw410_meter_labels), .labels = fw410_meter_labels, .get = &normal_meter_get }; -struct snd_bebob_spec maudio_fw410_spec = { +const struct snd_bebob_spec maudio_fw410_spec = { .clock = NULL, .rate = &usual_rate_spec, .meter = &fw410_meter_spec }; /* Firewire Audiophile specification */ -static struct snd_bebob_meter_spec audiophile_meter_spec = { +static const struct snd_bebob_meter_spec audiophile_meter_spec = { .num = ARRAY_SIZE(audiophile_meter_labels), .labels = audiophile_meter_labels, .get = &normal_meter_get }; -struct snd_bebob_spec maudio_audiophile_spec = { +const struct snd_bebob_spec maudio_audiophile_spec = { .clock = NULL, .rate = &usual_rate_spec, .meter = &audiophile_meter_spec }; /* Firewire Solo specification */ -static struct snd_bebob_meter_spec solo_meter_spec = { +static const struct snd_bebob_meter_spec solo_meter_spec = { .num = ARRAY_SIZE(solo_meter_labels), .labels = solo_meter_labels, .get = &normal_meter_get }; -struct snd_bebob_spec maudio_solo_spec = { +const struct snd_bebob_spec maudio_solo_spec = { .clock = NULL, .rate = &usual_rate_spec, .meter = &solo_meter_spec }; /* Ozonic specification */ -static struct snd_bebob_meter_spec ozonic_meter_spec = { +static const struct snd_bebob_meter_spec ozonic_meter_spec = { .num = ARRAY_SIZE(ozonic_meter_labels), .labels = ozonic_meter_labels, .get = &normal_meter_get }; -struct snd_bebob_spec maudio_ozonic_spec = { +const struct snd_bebob_spec maudio_ozonic_spec = { .clock = NULL, .rate = &usual_rate_spec, .meter = &ozonic_meter_spec }; /* NRV10 specification */ -static struct snd_bebob_meter_spec nrv10_meter_spec = { +static const struct snd_bebob_meter_spec nrv10_meter_spec = { .num = ARRAY_SIZE(nrv10_meter_labels), .labels = nrv10_meter_labels, .get = &normal_meter_get }; -struct snd_bebob_spec maudio_nrv10_spec = { +const struct snd_bebob_spec maudio_nrv10_spec = { .clock = NULL, .rate = &usual_rate_spec, .meter = &nrv10_meter_spec diff --git a/kernel/sound/firewire/bebob/bebob_midi.c b/kernel/sound/firewire/bebob/bebob_midi.c index 63343d578..90d95be49 100644 --- a/kernel/sound/firewire/bebob/bebob_midi.c +++ b/kernel/sound/firewire/bebob/bebob_midi.c @@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end; - atomic_inc(&bebob->capture_substreams); + atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); if (err < 0) snd_bebob_stream_lock_release(bebob); @@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end; - atomic_inc(&bebob->playback_substreams); + atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); if (err < 0) snd_bebob_stream_lock_release(bebob); @@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; - atomic_dec(&bebob->capture_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); snd_bebob_stream_lock_release(bebob); @@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; - atomic_dec(&bebob->playback_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); snd_bebob_stream_lock_release(bebob); @@ -72,11 +72,11 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up) spin_lock_irqsave(&bebob->lock, flags); if (up) - amdtp_stream_midi_trigger(&bebob->tx_stream, - substrm->number, substrm); + amdtp_am824_midi_trigger(&bebob->tx_stream, + substrm->number, substrm); else - amdtp_stream_midi_trigger(&bebob->tx_stream, - substrm->number, NULL); + amdtp_am824_midi_trigger(&bebob->tx_stream, + substrm->number, NULL); spin_unlock_irqrestore(&bebob->lock, flags); } @@ -89,11 +89,11 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up) spin_lock_irqsave(&bebob->lock, flags); if (up) - amdtp_stream_midi_trigger(&bebob->rx_stream, - substrm->number, substrm); + amdtp_am824_midi_trigger(&bebob->rx_stream, + substrm->number, substrm); else - amdtp_stream_midi_trigger(&bebob->rx_stream, - substrm->number, NULL); + amdtp_am824_midi_trigger(&bebob->rx_stream, + substrm->number, NULL); spin_unlock_irqrestore(&bebob->lock, flags); } diff --git a/kernel/sound/firewire/bebob/bebob_pcm.c b/kernel/sound/firewire/bebob/bebob_pcm.c index 4a55561ed..ef224d6f5 100644 --- a/kernel/sound/firewire/bebob/bebob_pcm.c +++ b/kernel/sound/firewire/bebob/bebob_pcm.c @@ -122,11 +122,11 @@ pcm_init_hw_params(struct snd_bebob *bebob, SNDRV_PCM_INFO_MMAP_VALID; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - runtime->hw.formats = AMDTP_IN_PCM_FORMAT_BITS; + runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; s = &bebob->tx_stream; formations = bebob->tx_stream_formations; } else { - runtime->hw.formats = AMDTP_OUT_PCM_FORMAT_BITS; + runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS; s = &bebob->rx_stream; formations = bebob->rx_stream_formations; } @@ -146,7 +146,7 @@ pcm_init_hw_params(struct snd_bebob *bebob, if (err < 0) goto end; - err = amdtp_stream_add_pcm_hw_constraints(s, runtime); + err = amdtp_am824_add_pcm_hw_constraints(s, runtime); end: return err; } @@ -155,9 +155,9 @@ static int pcm_open(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - struct snd_bebob_rate_spec *spec = bebob->spec->rate; + const struct snd_bebob_rate_spec *spec = bebob->spec->rate; unsigned int sampling_rate; - bool internal; + enum snd_bebob_clock_type src; int err; err = snd_bebob_stream_lock_try(bebob); @@ -168,7 +168,7 @@ pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - err = snd_bebob_stream_check_internal_clock(bebob, &internal); + err = snd_bebob_stream_get_clock_src(bebob, &src); if (err < 0) goto err_locked; @@ -176,7 +176,7 @@ pcm_open(struct snd_pcm_substream *substream) * When source of clock is internal or any PCM stream are running, * the available sampling rate is limited at current sampling rate. */ - if (!internal || + if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || amdtp_stream_pcm_running(&bebob->tx_stream) || amdtp_stream_pcm_running(&bebob->rx_stream)) { err = spec->get(bebob, &sampling_rate); @@ -211,26 +211,38 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&bebob->capture_substreams); - amdtp_stream_set_pcm_format(&bebob->tx_stream, - params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + atomic_inc(&bebob->substreams_counter); + + amdtp_am824_set_pcm_format(&bebob->tx_stream, params_format(hw_params)); + + return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&bebob->playback_substreams); - amdtp_stream_set_pcm_format(&bebob->rx_stream, - params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + atomic_inc(&bebob->substreams_counter); + + amdtp_am824_set_pcm_format(&bebob->rx_stream, params_format(hw_params)); + + return 0; } static int @@ -239,7 +251,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream) struct snd_bebob *bebob = substream->private_data; if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&bebob->capture_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); @@ -251,7 +263,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream) struct snd_bebob *bebob = substream->private_data; if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&bebob->playback_substreams); + atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); diff --git a/kernel/sound/firewire/bebob/bebob_proc.c b/kernel/sound/firewire/bebob/bebob_proc.c index 335da6450..ec24f9679 100644 --- a/kernel/sound/firewire/bebob/bebob_proc.c +++ b/kernel/sound/firewire/bebob/bebob_proc.c @@ -73,7 +73,7 @@ proc_read_meters(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_bebob *bebob = entry->private_data; - struct snd_bebob_meter_spec *spec = bebob->spec->meter; + const struct snd_bebob_meter_spec *spec = bebob->spec->meter; u32 *buf; unsigned int i, c, channels, size; @@ -132,25 +132,27 @@ static void proc_read_clock(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { + static const char *const clk_labels[] = { + "Internal", + "External", + "SYT-Match", + }; struct snd_bebob *bebob = entry->private_data; - struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; - struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; - unsigned int rate, id; - bool internal; + const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; + const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; + enum snd_bebob_clock_type src; + unsigned int rate; if (rate_spec->get(bebob, &rate) >= 0) snd_iprintf(buffer, "Sampling rate: %d\n", rate); - if (clk_spec) { - if (clk_spec->get(bebob, &id) >= 0) + if (snd_bebob_stream_get_clock_src(bebob, &src) >= 0) { + if (clk_spec) snd_iprintf(buffer, "Clock Source: %s\n", - clk_spec->labels[id]); - } else { - if (snd_bebob_stream_check_internal_clock(bebob, - &internal) >= 0) + clk_labels[src]); + else snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", - (internal) ? "Internal" : "External", - bebob->sync_input_plug); + clk_labels[src], bebob->sync_input_plug); } } diff --git a/kernel/sound/firewire/bebob/bebob_stream.c b/kernel/sound/firewire/bebob/bebob_stream.c index 98e4fc812..5022c9b97 100644 --- a/kernel/sound/firewire/bebob/bebob_stream.c +++ b/kernel/sound/firewire/bebob/bebob_stream.c @@ -8,7 +8,7 @@ #include "./bebob.h" -#define CALLBACK_TIMEOUT 1000 +#define CALLBACK_TIMEOUT 2000 #define FW_ISO_RESOURCE_DELAY 1000 /* @@ -47,14 +47,16 @@ static const unsigned int bridgeco_freq_table[] = { [6] = 0x07, }; -static unsigned int -get_formation_index(unsigned int rate) +static int +get_formation_index(unsigned int rate, unsigned int *index) { unsigned int i; for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) { - if (snd_bebob_rate_table[i] == rate) - return i; + if (snd_bebob_rate_table[i] == rate) { + *index = i; + return 0; + } } return -EINVAL; } @@ -116,16 +118,15 @@ end: return err; } -int -snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) +int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, + enum snd_bebob_clock_type *src) { - struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; + const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; unsigned int id; + enum avc_bridgeco_plug_type type; int err = 0; - *internal = false; - /* 1.The device has its own operation to switch source of clock */ if (clk_spec) { err = clk_spec->get(bebob, &id); @@ -143,10 +144,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) goto end; } - if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, - strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) - *internal = true; - + *src = clk_spec->types[id]; goto end; } @@ -155,7 +153,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * to use internal clock always */ if (bebob->sync_input_plug < 0) { - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; } @@ -178,18 +176,79 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) * Here check the first field. This field is used for direction. */ if (input[0] == 0xff) { - *internal = true; + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; goto end; } - /* - * If source of clock is internal CSR, Music Sub Unit Sync Input is - * a destination of Music Sub Unit Sync Output. - */ - *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) && - (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) && - (input[2] == 0x0c) && - (input[3] == 0x00)); + /* The source from any output plugs is for one purpose only. */ + if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) { + /* + * In BeBoB architecture, the source from music subunit may + * bypass from oPCR[0]. This means that this source gives + * synchronization to IEEE 1394 cycle start packet. + */ + if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT && + input[2] == 0x0c) { + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; + goto end; + } + /* The source from any input units is for several purposes. */ + } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) { + if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) { + if (input[3] == 0x00) { + /* + * This source comes from iPCR[0]. This means + * that presentation timestamp calculated by + * SYT series of the received packets. In + * short, this driver is the master of + * synchronization. + */ + *src = SND_BEBOB_CLOCK_TYPE_SYT; + goto end; + } else { + /* + * This source comes from iPCR[1-29]. This + * means that the synchronization stream is not + * the Audio/MIDI compound stream. + */ + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; + goto end; + } + } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) { + /* Check type of this plug. */ + avc_bridgeco_fill_unit_addr(addr, + AVC_BRIDGECO_PLUG_DIR_IN, + AVC_BRIDGECO_PLUG_UNIT_EXT, + input[3]); + err = avc_bridgeco_get_plug_type(bebob->unit, addr, + &type); + if (err < 0) + goto end; + + if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) { + /* + * SPDIF/ADAT or sometimes (not always) word + * clock. + */ + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; + goto end; + } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) { + /* Often word clock. */ + *src = SND_BEBOB_CLOCK_TYPE_EXTERNAL; + goto end; + } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) { + /* + * Not standard. + * Mostly, additional internal clock. + */ + *src = SND_BEBOB_CLOCK_TYPE_INTERNAL; + goto end; + } + } + } + + /* Not supported. */ + err = -EIO; end: return err; } @@ -281,7 +340,7 @@ map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) err = -ENOSYS; goto end; } - s->midi_position = stm_pos; + amdtp_am824_set_midi_position(s, stm_pos); midi = stm_pos; break; /* for PCM data channel */ @@ -297,11 +356,12 @@ map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) case 0x09: /* Digital */ default: location = pcm + sec_loc; - if (location >= AMDTP_MAX_CHANNELS_FOR_PCM) { + if (location >= AM824_MAX_CHANNELS_FOR_PCM) { err = -ENOSYS; goto end; } - s->pcm_positions[location] = stm_pos; + amdtp_am824_set_pcm_position(s, location, + stm_pos); break; } } @@ -367,15 +427,24 @@ make_both_connections(struct snd_bebob *bebob, unsigned int rate) goto end; /* confirm params for both streams */ - index = get_formation_index(rate); + err = get_formation_index(rate, &index); + if (err < 0) + goto end; pcm_channels = bebob->tx_stream_formations[index].pcm; midi_channels = bebob->tx_stream_formations[index].midi; - amdtp_stream_set_parameters(&bebob->tx_stream, - rate, pcm_channels, midi_channels * 8); + err = amdtp_am824_set_parameters(&bebob->tx_stream, rate, + pcm_channels, midi_channels * 8, + false); + if (err < 0) + goto end; + pcm_channels = bebob->rx_stream_formations[index].pcm; midi_channels = bebob->rx_stream_formations[index].midi; - amdtp_stream_set_parameters(&bebob->rx_stream, - rate, pcm_channels, midi_channels * 8); + err = amdtp_am824_set_parameters(&bebob->rx_stream, rate, + pcm_channels, midi_channels * 8, + false); + if (err < 0) + goto end; /* establish connections for both streams */ err = cmp_connection_establish(&bebob->out_conn, @@ -417,8 +486,24 @@ destroy_both_connections(struct snd_bebob *bebob) static int get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode) { - /* currently this module doesn't support SYT-Match mode */ - *sync_mode = CIP_SYNC_TO_DEVICE; + enum snd_bebob_clock_type src; + int err; + + err = snd_bebob_stream_get_clock_src(bebob, &src); + if (err < 0) + return err; + + switch (src) { + case SND_BEBOB_CLOCK_TYPE_INTERNAL: + case SND_BEBOB_CLOCK_TYPE_EXTERNAL: + *sync_mode = CIP_SYNC_TO_DEVICE; + break; + default: + case SND_BEBOB_CLOCK_TYPE_SYT: + *sync_mode = 0; + break; + } + return 0; } @@ -457,8 +542,8 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) if (err < 0) goto end; - err = amdtp_stream_init(&bebob->tx_stream, bebob->unit, - AMDTP_IN_STREAM, CIP_BLOCKING); + err = amdtp_am824_init(&bebob->tx_stream, bebob->unit, + AMDTP_IN_STREAM, CIP_BLOCKING); if (err < 0) { amdtp_stream_destroy(&bebob->tx_stream); destroy_both_connections(bebob); @@ -467,6 +552,17 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) /* See comments in next function */ init_completion(&bebob->bus_reset); bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK; + + /* + * BeBoB v3 transfers packets with these qurks: + * - In the beginning of streaming, the value of dbc is incremented + * even if no data blocks are transferred. + * - The value of dbc is reset suddenly. + */ + if (bebob->version > 2) + bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | + CIP_SKIP_DBC_ZERO_CHECK; + /* * At high sampling rate, M-Audio special firmware transmits empty * packet with the value of dbc incremented by 8 but the others are @@ -475,8 +571,8 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) if (bebob->maudio_special_quirk) bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; - err = amdtp_stream_init(&bebob->rx_stream, bebob->unit, - AMDTP_OUT_STREAM, CIP_BLOCKING); + err = amdtp_am824_init(&bebob->rx_stream, bebob->unit, + AMDTP_OUT_STREAM, CIP_BLOCKING); if (err < 0) { amdtp_stream_destroy(&bebob->tx_stream); amdtp_stream_destroy(&bebob->rx_stream); @@ -488,9 +584,8 @@ end: int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) { - struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; + const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; struct amdtp_stream *master, *slave; - atomic_t *slave_substreams; enum cip_flags sync_mode; unsigned int curr_rate; bool updated = false; @@ -515,8 +610,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) mutex_lock(&bebob->mutex); /* Need no substreams */ - if (atomic_read(&bebob->playback_substreams) == 0 && - atomic_read(&bebob->capture_substreams) == 0) + if (atomic_read(&bebob->substreams_counter) == 0) goto end; err = get_sync_mode(bebob, &sync_mode); @@ -525,11 +619,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) if (sync_mode == CIP_SYNC_TO_DEVICE) { master = &bebob->tx_stream; slave = &bebob->rx_stream; - slave_substreams = &bebob->playback_substreams; } else { master = &bebob->rx_stream; slave = &bebob->tx_stream; - slave_substreams = &bebob->capture_substreams; } /* @@ -630,7 +722,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) } /* start slave if needed */ - if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { + if (!amdtp_stream_running(slave)) { err = start_stream(bebob, slave, rate); if (err < 0) { dev_err(&bebob->unit->device, @@ -656,31 +748,25 @@ end: void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) { struct amdtp_stream *master, *slave; - atomic_t *master_substreams, *slave_substreams; if (bebob->master == &bebob->rx_stream) { slave = &bebob->tx_stream; master = &bebob->rx_stream; - slave_substreams = &bebob->capture_substreams; - master_substreams = &bebob->playback_substreams; } else { slave = &bebob->rx_stream; master = &bebob->tx_stream; - slave_substreams = &bebob->playback_substreams; - master_substreams = &bebob->capture_substreams; } mutex_lock(&bebob->mutex); - if (atomic_read(slave_substreams) == 0) { + if (atomic_read(&bebob->substreams_counter) == 0) { + amdtp_stream_pcm_abort(master); + amdtp_stream_stop(master); + amdtp_stream_pcm_abort(slave); amdtp_stream_stop(slave); - if (atomic_read(master_substreams) == 0) { - amdtp_stream_pcm_abort(master); - amdtp_stream_stop(master); - break_both_connections(bebob); - } + break_both_connections(bebob); } mutex_unlock(&bebob->mutex); @@ -790,8 +876,8 @@ parse_stream_formation(u8 *buf, unsigned int len, } } - if (formation[i].pcm > AMDTP_MAX_CHANNELS_FOR_PCM || - formation[i].midi > AMDTP_MAX_CHANNELS_FOR_MIDI) + if (formation[i].pcm > AM824_MAX_CHANNELS_FOR_PCM || + formation[i].midi > AM824_MAX_CHANNELS_FOR_MIDI) return -ENOSYS; return 0; @@ -885,7 +971,7 @@ end: int snd_bebob_stream_discover(struct snd_bebob *bebob) { - struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; + const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; enum avc_bridgeco_plug_type type; unsigned int i; diff --git a/kernel/sound/firewire/bebob/bebob_terratec.c b/kernel/sound/firewire/bebob/bebob_terratec.c index ad635004d..c38358b82 100644 --- a/kernel/sound/firewire/bebob/bebob_terratec.c +++ b/kernel/sound/firewire/bebob/bebob_terratec.c @@ -8,8 +8,10 @@ #include "./bebob.h" -static const char *const phase88_rack_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock" +static enum snd_bebob_clock_type phase88_rack_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ }; static int phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id) @@ -34,39 +36,49 @@ end: return err; } -static const char *const phase24_series_clk_src_labels[] = { - SND_BEBOB_CLOCK_INTERNAL, "Digital In" +static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ }; static int phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) { - return avc_audio_get_selector(bebob->unit, 0, 4, id); + int err; + + err = avc_audio_get_selector(bebob->unit, 0, 4, id); + if (err < 0) + return err; + + if (*id >= ARRAY_SIZE(phase24_series_clk_src_types)) + return -EIO; + + return 0; } -static struct snd_bebob_rate_spec phase_series_rate_spec = { +static const struct snd_bebob_rate_spec phase_series_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; /* PHASE 88 Rack FW */ -static struct snd_bebob_clock_spec phase88_rack_clk = { - .num = ARRAY_SIZE(phase88_rack_clk_src_labels), - .labels = phase88_rack_clk_src_labels, +static const struct snd_bebob_clock_spec phase88_rack_clk = { + .num = ARRAY_SIZE(phase88_rack_clk_src_types), + .types = phase88_rack_clk_src_types, .get = &phase88_rack_clk_src_get, }; -struct snd_bebob_spec phase88_rack_spec = { +const struct snd_bebob_spec phase88_rack_spec = { .clock = &phase88_rack_clk, .rate = &phase_series_rate_spec, .meter = NULL }; /* 'PHASE 24 FW' and 'PHASE X24 FW' */ -static struct snd_bebob_clock_spec phase24_series_clk = { - .num = ARRAY_SIZE(phase24_series_clk_src_labels), - .labels = phase24_series_clk_src_labels, +static const struct snd_bebob_clock_spec phase24_series_clk = { + .num = ARRAY_SIZE(phase24_series_clk_src_types), + .types = phase24_series_clk_src_types, .get = &phase24_series_clk_src_get, }; -struct snd_bebob_spec phase24_series_spec = { +const struct snd_bebob_spec phase24_series_spec = { .clock = &phase24_series_clk, .rate = &phase_series_rate_spec, .meter = NULL diff --git a/kernel/sound/firewire/bebob/bebob_yamaha.c b/kernel/sound/firewire/bebob/bebob_yamaha.c index ef1fe3823..90d4404f7 100644 --- a/kernel/sound/firewire/bebob/bebob_yamaha.c +++ b/kernel/sound/firewire/bebob/bebob_yamaha.c @@ -28,22 +28,34 @@ * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. */ -static const char *const clk_src_labels[] = {SND_BEBOB_CLOCK_INTERNAL, "SPDIF"}; +static enum snd_bebob_clock_type clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ +}; static int clk_src_get(struct snd_bebob *bebob, unsigned int *id) { - return avc_audio_get_selector(bebob->unit, 0, 4, id); + int err; + + err = avc_audio_get_selector(bebob->unit, 0, 4, id); + if (err < 0) + return err; + + if (*id >= ARRAY_SIZE(clk_src_types)) + return -EIO; + + return 0; } -static struct snd_bebob_clock_spec clock_spec = { - .num = ARRAY_SIZE(clk_src_labels), - .labels = clk_src_labels, +static const struct snd_bebob_clock_spec clock_spec = { + .num = ARRAY_SIZE(clk_src_types), + .types = clk_src_types, .get = &clk_src_get, }; -static struct snd_bebob_rate_spec rate_spec = { +static const struct snd_bebob_rate_spec rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; -struct snd_bebob_spec yamaha_go_spec = { +const struct snd_bebob_spec yamaha_go_spec = { .clock = &clock_spec, .rate = &rate_spec, .meter = NULL |