Gain/Balance/Mix/Output controls
/* base address */ #define MAUDIO_SPECIFIC_ADDRESS 0xffc700000000 /* * FW1814/ProjectMix don't use AVC for control. The driver cannot refer to * current parameters by asynchronous transaction. The driver is allowed to * write transaction so MUST remember the current values. */ #define MAUDIO_CONTROL_OFFSET 0x00700000 /* * GAIN for inputs: * Write 32bit. upper 16bit for left chennal and lower 16bit for right. * The value is between 0x8000(low) to 0x0000(high) as the same as '10.3.1 * Volume Control' in 'AV/C Audio Subunit Specification 1.0 (1394TA 1999008)'. */ #define GAIN_STM_12_IN 0x00 #define GAIN_STM_34_IN 0x04 #define GAIN_ANA_12_OUT 0x08 #define GAIN_ANA_34_OUT 0x0c #define GAIN_ANA_12_IN 0x10 #define GAIN_ANA_34_IN 0x14 #define GAIN_ANA_56_IN 0x18 #define GAIN_ANA_78_IN 0x1c #define GAIN_SPDIF_12_IN 0x20 #define GAIN_ADAT_12_IN 0x24 #define GAIN_ADAT_34_IN 0x28 #define GAIN_ADAT_56_IN 0x2c #define GAIN_ADAT_78_IN 0x30 #define GAIN_AUX_12_OUT 0x34 #define GAIN_HP_12_OUT 0x38 #define GAIN_HP_34_OUT 0x3c /* * LR balance: * Write 32 bit, upper 16bit for left channel and lower 16bit for right. * The value is between 0x800(L) to 0x7FFE(R) as the same as '10.3.3 LR Balance * Control' in 'AV/C Audio Subunit Specification 1.0 (1394TA 1999008)'. */ #define LR_ANA_12_IN 0x40 #define LR_ANA_34_IN 0x44 #define LR_ANA_56_IN 0x48 #define LR_ANA_78_IN 0x4c #define LR_SPDIF_12_IN 0x50 #define LR_ADAT_12_IN 0x54 #define LR_ADAT_34_IN 0x58 #define LR_ADAT_56_IN 0x5c #define LR_ADAT_78_IN 0x60 /* * AUX inputs: * This is the same as 'gain' control above. */ #define AUX_STM_12_IN 0x64 #define AUX_STM_34_IN 0x68 #define AUX_ANA_12_IN 0x6c #define AUX_ANA_34_IN 0x70 #define AUX_ANA_56_IN 0x74 #define AUX_ANA_78_IN 0x78 #define AUX_SPDIF_12_IN 0x7c #define AUX_ADAT_12_IN 0x80 #define AUX_ADAT_34_IN 0x84 #define AUX_ADAT_56_IN 0x88 #define AUX_ADAT_78_IN 0x8c /* * MIXER inputs: * There are bit flags. If flag is 0x01, it means on. * * MIX_ANA_DIG_IN: * Write 32bits, lower 24bits are used. * [0x 00 UV WX YZ] * U: SPDIF_12 to Mix34 * V: SPDIF_12 to Mix12 * W: ADAT_12345678 to Mix34 * X: ADAT_12345678 to Mix12 * Y: Ana_12345678 to Mix34 * Z: Ana_12345678 to Mix12 * The least significant bit is used for channel 1/2, * the most significant bit is used for channel 7/8. * * MIX_STM_IN: * Write 32bits, lower 4bits are used. upper 2bits for 'from Stm1/2' and lower * for 'from Stm3/4'. Inner the 2bits, most significant bit is for 'to Mix3/4' * and least significant bit is for 'to Mix1/2'. */ #define MIX_ANA_DIG_IN 0x90 #define MIX_STM_IN 0x94 /* * SRC for output: * Write 32bit. There are bit flags. If the flag is 0x01, it means on. * * SRC_HP_OUT: * Lower 3bits are used, 'from Aux12', 'from Mix34', 'from * Mix12'. * * SRC_ANA_OUT: * Lower 2 bits are used, 'to Ana34', 'to Ana12'. If bit is 0x01, it * means 'from Aux12' else 'From Mix12 (or Mix34)'. */ #define SRC_HP_OUT 0x98 #define SRC_ANA_OUT 0x9c
/* * FW1814 and ProjectMix gives no way to read its control. So drivers * should remember the value for each parameters. Windows driver, after loading * firmware, write all parameters just after flushing. */ #define MIXER_OFFSET 0x00700000 #define MIXER_SIZE_SPECIAL 160 /* default parameters loaded by Windows driver */ static unsigned char mixer_init_data[MIXER_SIZE_SPECIAL] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x7f, 0xfe, 0x80, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }; int special_set_mixer_init_data(struct snd_bebob *bebob, void *buf, unsigned int size) { return snd_fw_transaction(bebob->unit, TCODE_WRITE_BLOCK_REQUEST, MAUDIO_SPECIFIC_ADDRESS + MIXER_OFFSET, buf, size, 0); }
Test command to blink all LEDs on front panel
/* * Just after loading Windows driver issues following command to blink all the leds * static int snd_bebob_maudio_special_indication_test(struct snd_bebob *bebob) { u8 buf[8]; buf[0] = 0x00; /* control */ buf[1] = 0xff; /* unit */ buf[2] = 0x00; /* vendor dependent command */ buf[3] = 0x02; /* unknown */ buf[4] = 0x00; /* unknown */ buf[5] = 0x00; /* unknown */ buf[6] = 0x00; /* unknown */ buf[7] = 0x00; /* unknown */ return fcp_avc_transaction(bebob->unit, buf, 8, buf, 8, 0); }
Clock parameters control
/* * clk_src: 0x00:internal without digital in, 0x01:external, 0x02:word_clock, 0x03:internal with digital in * in_dig_fmt: 0x00:S/PDIF, 0x01:ADAT * out_dig_fmt: 0x00:S/PDIF, 0x01:ADAT * clk_lock: 0x00:unlocked, 0x01:locked */ static int set_clock_params(struct snd_bebob *bebob, int clk_src, int in_dig_fmt, int out_dig_fmt, int clk_lock) { int err; u8 *buf; buf = kmalloc(12, GFP_KERNEL); if (buf == NULL) return -ENOMEM; buf[0] = 0x00; /* CONTROL */ buf[1] = 0xff; /* UNIT */ buf[2] = 0x00; /* vendor dependent */ buf[3] = 0x04; buf[4] = 0x00; buf[5] = 0x04; /* has 4 parameters */ buf[6] = 0xff & clk_src; /* clock source */ buf[7] = 0xff & in_dig_fmt; /* input digital format */ buf[8] = 0xff & out_dig_fmt; /* output digital format */ buf[9] = 0xff & clk_lock; /* lock these settings */ buf[10] = 0x00; /* padding */ buf[11] = 0x00; /* padding */ err = fcp_avc_transaction(bebob->unit, buf, 8, buf, 8, 0); if (err < 0) goto end; if ((err < 6) || (buf[0] != 0x09)) { dev_err(&bebob->unit->device, "failed to set clock params\n"); err = -EIO; goto end; } err = 0; end: kfree(buf); return err; }
Digital interface control
For this purpose, selector function block command in AV/C Audio subunit specification.
/* * function block id: 0x04 * dig_iface: 0x00:Optical, 0x01:Coaxial */
Reverse engineering of Windows driver timing digram
1. Driver polls for meter data every 100 ms reading
#define METER_SIZE_SPECIAL 84 /* with sync info */
bytes from
#define METER_OFFSET 0x00600000
2. Any FCP transaction (except 'lock pll' and 'set sampling rate') takes less then 100 ms
3. Any regular read/write may happen at any time (e.g. mixer controls)
4. The most interesting part: set sampling rate. Here is the part of the log with timings
ffc1 ffff f000 0b00 8 OUT 00 ff 18 00 90 03 ffff ........ 2.8ms 80.1.0 15:06:58.773 mafw 0000 ffff f000 0d00 8 IN 0f ff 18 00 90 03 ffff ........ 106ms 81.1.0 15:06:58.883 mafw 0000 ffff f000 0d00 8 IN 09 ff 18 00 90 03 ffff ........ 132ms 82.1.0 15:06:59.013 mafw this reply usually arrives after about 150 ms ffc1 ffff f000 0b00 8 OUT 00 ff 19 00 90 03 ffff ........ 1.4ms 83.1.0 15:06:59.013 mafw 0000 ffff f000 0d00 8 IN 0f ff 19 00 90 03 ffff ........ 91ms 84.1.0 15:06:59.103 mafw 0000 ffff f000 0d00 8 IN 09 ff 19 00 90 03 ffff ........ 332ms 85.1.0 15:06:59.443 mafw reply to this FCP request arrived in 332 ms. and the next access to the device happens only after 1 sec!!! 46 ffc1 ffc7 0060 0000 84 IN 00 00 00 00 00 05 00 0100 1a 00 1b 00 1a 00 1a ................ 1.0sc 86.1.0 15:07:00.493 mafw 00 18 00 18 00 00 00 0000 00 00 00 00 00 00 00 ................ 86.1.16 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 ................ 86.1.32 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 ................ 86.1.48 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 ................ 86.1.64 00 00 03 01 .... 86.1.80
Logs with firewire_ohci and debug=1 option
At releasing connections/resources for both direction: [27200.724273] firewire_ohci 0000:0c:06.0: AT spd 2 tl 28, ffc0 -> ffc1, ack_pending , Lk req, fffff0000984 8,2 [27200.724921] firewire_ohci 0000:0c:06.0: AR spd 2 tl 28, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27200.725037] firewire_ohci 0000:0c:06.0: AT spd 0 tl 29, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27200.725598] firewire_ohci 0000:0c:06.0: AR spd 2 tl 29, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27200.725714] firewire_ohci 0000:0c:06.0: AT spd 0 tl 2a, ffc0 -> ffc1, ack_pending , Lk req, fffff0000220 8,2 [27202.727199] firewire_ohci 0000:0c:06.0: AT spd 0 tl 2b, ffc0 -> ffc1, ack_pending , Lk req, fffff0000220 8,2 [27202.727735] firewire_ohci 0000:0c:06.0: AR spd 2 tl 2b, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27202.727858] firewire_ohci 0000:0c:06.0: AT spd 2 tl 2c, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27204.750950] firewire_ohci 0000:0c:06.0: AT spd 2 tl 2d, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27206.777677] firewire_ohci 0000:0c:06.0: AT spd 2 tl 2e, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27208.779327] snd-bebob fw1.0: transaction failed: timeout [27208.779333] snd-bebob fw1.0: oPCR0: plug is still connected (The device handle a first operation for oPCR0 but not respond.) At releasing connections/resources for both direction: [27603.200092] firewire_ohci 0000:0c:06.0: AT spd 2 tl 02, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27603.200455] firewire_ohci 0000:0c:06.0: AR spd 2 tl 02, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27603.200629] firewire_ohci 0000:0c:06.0: AT spd 0 tl 03, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27605.203315] firewire_ohci 0000:0c:06.0: AT spd 0 tl 04, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27605.203962] firewire_ohci 0000:0c:06.0: AR spd 2 tl 04, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27605.204077] firewire_ohci 0000:0c:06.0: AT spd 0 tl 05, ffc0 -> ffc1, ack_pending , Lk req, fffff0000220 8,2 [27605.204507] firewire_ohci 0000:0c:06.0: AR spd 2 tl 05, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27605.204569] snd-bebob fw1.0: isochronous resource deallocation failed (The device handle a first operation for CSR_CHANNELS_AVAILABLE_HI but not respond.) At keeping resources and establising connections: [27212.950366] firewire_ohci 0000:0c:06.0: AT spd 0 tl 35, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27212.950922] firewire_ohci 0000:0c:06.0: AR spd 2 tl 35, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.951060] firewire_ohci 0000:0c:06.0: AT spd 0 tl 36, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27212.951505] firewire_ohci 0000:0c:06.0: AR spd 2 tl 36, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.951590] firewire_ohci 0000:0c:06.0: AT spd 0 tl 37, ffc0 -> ffc1, ack_pending , Lk req, fffff0000220 8,2 [27212.952101] firewire_ohci 0000:0c:06.0: AR spd 2 tl 37, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.952220] firewire_ohci 0000:0c:06.0: AT spd 2 tl 38, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27212.952568] firewire_ohci 0000:0c:06.0: AR spd 2 tl 38, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.952715] firewire_ohci 0000:0c:06.0: AT spd 2 tl 39, ffc0 -> ffc1, ack_pending , Lk req, fffff0000904 8,2 [27212.953044] firewire_ohci 0000:0c:06.0: AR spd 2 tl 39, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.953178] firewire_ohci 0000:0c:06.0: AT spd 0 tl 3a, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27212.953504] firewire_ohci 0000:0c:06.0: AR spd 2 tl 3a, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.953588] firewire_ohci 0000:0c:06.0: AT spd 0 tl 3b, ffc0 -> ffc1, ack_pending , Lk req, fffff0000224 8,2 [27212.954017] firewire_ohci 0000:0c:06.0: AR spd 2 tl 3b, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.954077] firewire_ohci 0000:0c:06.0: AT spd 0 tl 3c, ffc0 -> ffc1, ack_pending , Lk req, fffff0000220 8,2 [27212.954364] firewire_ohci 0000:0c:06.0: AR spd 2 tl 3c, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27212.954429] firewire_ohci 0000:0c:06.0: AT spd 2 tl 3d, ffc0 -> ffc1, ack_pending , Lk req, fffff0000984 8,2 [27214.980602] firewire_ohci 0000:0c:06.0: AT spd 2 tl 3e, ffc0 -> ffc1, ack_pending , Lk req, fffff0000984 8,2 [27214.981135] firewire_ohci 0000:0c:06.0: AR spd 2 tl 3e, ffc1 -> ffc0, ack_complete, Lk resp 4,2 [27214.981195] snd-bebob fw1.0: iPCR0: plug is already in use (The device handle a first operation for iPCR0 but not respond.)