Commit b77279bc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound into next

Pull sound updates from Takashi Iwai:
 "At this time, majority of changes come from ASoC world while we got a
  few new drivers in other places for FireWire and USB.  There have been
  lots of ASoC core cleanups / refactoring, but very little visible to
  external users.

  ASoC:
   - Support for specifying aux CODECs in DT
   - Removal of the deprecated mux and enum macros
   - More moves towards full componentisation
   - Removal of some unused I/O code
   - Lots of cleanups, fixes and enhancements to the davinci, Freescale,
     Haswell and Realtek drivers
   - Several drivers exposed directly in Kconfig for use with
     simple-card
   - GPIO descriptor support for jacks
   - More updates and fixes to the Freescale SSI, Intel and rsnd drivers
   - New drivers for Cirrus CS42L56, Realtek RT5639, RT5642 and RT5651
     and ST STA350, Analog Devices ADAU1361, ADAU1381, ADAU1761 and
     ADAU1781, and Realtek RT5677

  HD-audio:
   - Clean up Dell headset quirks
   - Noise fixes for Dell and Sony laptops
   - Thinkpad T440 dock fix
   - Realtek codec updates (ALC293,ALC233,ALC3235)
   - Tegra HD-audio HDMI support

  FireWire-audio:
   - FireWire audio stack enhancement (AMDTP, MIDI), support for
     incoming isochronous stream and duplex streams with timestamp
     synchronization
   - BeBoB-based devices support
   - Fireworks-based device support

  USB-audio:
   - Behringer BCD2000 USB device support

  Misc:
   - Clean up of a few old drivers, atmel, fm801, etc"

* tag 'sound-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (480 commits)
  ASoC: Fix wrong argument for card remove callbacks
  ASoC: free jack GPIOs before the sound card is freed
  ALSA: firewire-lib: Remove a comment about restriction of asynchronous operation
  ASoC: cache: Fix error code when not using ASoC level cache
  ALSA: hda/realtek - Fix COEF widget NID for ALC260 replacer fixup
  ALSA: hda/realtek - Correction of fixup codes for PB V7900 laptop
  ALSA: firewire-lib: Use IEC 61883-6 compliant labels for Raw Audio data
  ASoC: add RT5677 CODEC driver
  ASoC: intel: The Baytrail/MAX98090 driver depends on I2C
  ASoC: rt5640: Add the function "get_clk_info" to RL6231 shared support
  ASoC: rt5640: Add the function of the PLL clock calculation to RL6231 shared support
  ASoC: rt5640: Add RL6231 class device shared support for RT5640, RT5645 and RT5651
  ASoC: cache: Fix possible ZERO_SIZE_PTR pointer dereferencing error.
  ASoC: Add helper functions to cast from DAPM context to CODEC/platform
  ALSA: bebob: sizeof() vs ARRAY_SIZE() typo
  ASoC: wm9713: correct mono out PGA sources
  ALSA: synth: emux: soundfont.c: Cleaning up memory leak
  ASoC: fsl: Remove dependencies of boards for SND_SOC_EUKREA_TLV320
  ASoC: fsl-ssi: Use regmap
  ASoC: fsl-ssi: reorder and document fsl_ssi_private
  ...
parents 15b58830 16088cb6
......@@ -10,6 +10,9 @@ Optional properties:
- fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used
Sub-nodes:
- codec: Contain the Audio Codec node.
- adc-port: Contain PMIC SSI port number used for ADC.
- dac-port: Contain PMIC SSI port number used for DAC.
- leds : Contain the led nodes and initial register values in property
"led-control". Number of register depends of used IC, for MC13783 is 6,
for MC13892 is 4, for MC34708 is 1. See datasheet for bits definitions of
......
......@@ -8,6 +8,8 @@ Required properties:
- reg : The chip select number on the SPI bus
- vdd-supply : A regulator node, providing 2.7V - 3.6V
Optional properties:
- reset-gpio : a GPIO spec for the reset pin. If specified, it will be
......@@ -19,4 +21,5 @@ spdif: ak4104@0 {
compatible = "asahi-kasei,ak4104";
reg = <0>;
spi-max-frequency = <5000000>;
vdd-supply = <&vdd_3v3_reg>;
};
ALC5621/ALC5622/ALC5623 audio Codec
Required properties:
- compatible: "realtek,alc5623"
- reg: the I2C address of the device.
Optional properties:
- add-ctrl: Default register value for Reg-40h, Additional Control
Register. If absent or has the value of 0, the
register is untouched.
- jack-det-ctrl: Default register value for Reg-5Ah, Jack Detect
Control Register. If absent or has value 0, the
register is untouched.
Example:
alc5621: alc5621@1a {
compatible = "alc5621";
reg = <0x1a>;
add-ctrl = <0x3700>;
jack-det-ctrl = <0x4810>;
};
CS42L52 audio CODEC
Required properties:
- compatible : "cirrus,cs42l56"
- reg : the I2C address of the device for I2C
- VA-supply, VCP-supply, VLDO-supply : power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt.
Optional properties:
- cirrus,gpio-nreset : GPIO controller's phandle and the number
of the GPIO used to reset the codec.
- cirrus,chgfreq-divisor : Values used to set the Charge Pump Frequency.
Allowable values of 0x00 through 0x0F. These are raw values written to the
register, not the actual frequency. The frequency is determined by the following.
Frequency = MCLK / 4 * (N+2)
N = chgfreq_val
MCLK = Where MCLK is the frequency of the mclk signal after the MCLKDIV2 circuit.
- cirrus,ain1a-ref-cfg, ain1b-ref-cfg : boolean, If present, AIN1A or AIN1B are configured
as a pseudo-differential input referenced to AIN1REF/AIN3A.
- cirrus,ain2a-ref-cfg, ain2b-ref-cfg : boolean, If present, AIN2A or AIN2B are configured
as a pseudo-differential input referenced to AIN2REF/AIN3B.
- cirrus,micbias-lvl: Set the output voltage level on the MICBIAS Pin.
0 = 0.5 x VA
1 = 0.6 x VA
2 = 0.7 x VA
3 = 0.8 x VA
4 = 0.83 x VA
5 = 0.91 x VA
- cirrus,adaptive-pwr-cfg : Configures how the power to the Headphone and Lineout
Amplifiers adapt to the output signal levels.
0 = Adapt to Volume Mode. Voltage level determined by the sum of the relevant volume settings.
1 = Fixed - Headphone and Line Amp supply = + or - VCP/2.
2 = Fixed - Headphone and Line Amp supply = + or - VCP.
3 = Adapted to Signal; Voltage level is dynamically determined by the output signal.
- cirrus,hpf-left-freq, hpf-right-freq : Sets the corner frequency (-3dB point) for the internal High-Pass
Filter.
0 = 1.8Hz
1 = 119Hz
2 = 236Hz
3 = 464Hz
Example:
codec: codec@4b {
compatible = "cirrus,cs42l56";
reg = <0x4b>;
gpio-reset = <&gpio 10 0>;
cirrus,chgfreq-divisor = <0x05>;
cirrus.ain1_ref_cfg;
cirrus,micbias-lvl = <5>;
VA-supply = <&reg_audio>;
};
......@@ -7,10 +7,11 @@ codec/DSP interfaces.
Required properties:
- compatible: Compatible list, contains "fsl,vf610-sai".
- compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai".
- reg: Offset and length of the register set for the device.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names : Must include the "sai" entry.
- clock-names : Must include the "bus" for register access and "mclk1" "mclk2"
"mclk3" for bit clock and frame clock providing.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
......@@ -30,8 +31,10 @@ sai2: sai@40031000 {
reg = <0x40031000 0x1000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_SAI2>;
clock-names = "sai";
clocks = <&clks VF610_CLK_PLATFORM_BUS>,
<&clks VF610_CLK_SAI2>,
<&clks 0>, <&clks 0>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
......
......@@ -10,6 +10,12 @@ Required properties:
- interrupts : The CODEC's interrupt output.
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
Pins on the device (for linking into audio routes):
* MIC1
......
MAX98095 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "maxim,max98095".
- reg : The I2C address of the device.
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
Example:
max98095: codec@11 {
compatible = "maxim,max98095";
reg = <0x11>;
};
* Nokia N900 audio setup
Required properties:
- compatible: Should contain "nokia,n900-audio"
- nokia,cpu-dai: phandle for the McBSP node
- nokia,audio-codec: phandles for the main TLV320AIC3X node and the
auxiliary TLV320AIC3X node (in this order)
- nokia,headphone-amplifier: phandle for the TPA6130A2 node
- tvout-selection-gpios: GPIO for tvout selection
- jack-detection-gpios: GPIO for jack detection
- eci-switch-gpios: GPIO for ECI (Enhancement Control Interface) switch
- speaker-amplifier-gpios: GPIO for speaker amplifier
Example:
sound {
compatible = "nokia,n900-audio";
nokia,cpu-dai = <&mcbsp2>;
nokia,audio-codec = <&tlv320aic3x>, <&tlv320aic3x_aux>;
nokia,headphone-amplifier = <&tpa6130a2>;
tvout-selection-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>; /* 40 */
jack-detection-gpios = <&gpio6 17 GPIO_ACTIVE_HIGH>; /* 177 */
eci-switch-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* 182 */
speaker-amplifier-gpios = <&twl_gpio 7 GPIO_ACTIVE_HIGH>;
};
NVIDIA Tegra30 HDA controller
Required properties:
- compatible : "nvidia,tegra30-hda"
- reg : Should contain the HDA registers location and length.
- interrupts : The interrupt from the HDA controller.
- clocks : Must contain an entry for each required entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries: hda, hdacodec_2x, hda2hdmi
- resets : Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names : Must include the following entries: hda, hdacodec_2x, hda2hdmi
Example:
hda@0,70030000 {
compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
reg = <0x0 0x70030000 0x0 0x10000>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_HDA>,
<&tegra_car TEGRA124_CLK_HDA2HDMI>,
<&tegra_car TEGRA124_CLK_HDA2CODEC_2X>;
clock-names = "hda", "hda2hdmi", "hda2codec_2x";
resets = <&tegra_car 125>, /* hda */
<&tegra_car 128>; /* hda2hdmi */
<&tegra_car 111>, /* hda2codec_2x */
reset-names = "hda", "hda2hdmi", "hda2codec_2x";
};
......@@ -20,6 +20,7 @@ Required properties:
SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin
- pio-transfer : use PIO transfer mode
SRC subnode properties:
no properties at this point
......
RT5640 audio CODEC
RT5640/RT5639 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5640".
- compatible : One of "realtek,rt5640" or "realtek,rt5639".
- reg : The I2C address of the device.
......@@ -18,7 +18,7 @@ Optional properties:
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
Pins on the device (for linking into audio routes):
Pins on the device (for linking into audio routes) for RT5639/RT5640:
* DMIC1
* DMIC2
......@@ -31,13 +31,16 @@ Pins on the device (for linking into audio routes):
* HPOR
* LOUTL
* LOUTR
* MONOP
* MONON
* SPOLP
* SPOLN
* SPORP
* SPORN
Additional pins on the device for RT5640:
* MONOP
* MONON
Example:
rt5640 {
......
Simple-Card:
Simple-Card specifies audio DAI connection of SoC <-> codec.
Simple-Card specifies audio DAI connections of SoC <-> codec.
Required properties:
......@@ -10,26 +10,54 @@ Optional properties:
- simple-audio-card,name : User specified audio sound card name, one string
property.
- simple-audio-card,format : CPU/CODEC common audio format.
"i2s", "right_j", "left_j" , "dsp_a"
"dsp_b", "ac97", "pdm", "msb", "lsb"
- simple-audio-card,widgets : Please refer to widgets.txt.
- simple-audio-card,routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source.
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
- dai-tdm-slot-width : Please refer to tdm-slot.txt.
- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
mclk.
Optional subnodes:
- simple-audio-card,dai-link : Container for dai-link level
properties and the CPU and CODEC
sub-nodes. This container may be
omitted when the card has only one
DAI link. See the examples and the
section bellow.
Dai-link subnode properties and subnodes:
If dai-link subnode is omitted and the subnode properties are directly
under "sound"-node the subnode property and subnode names have to be
prefixed with "simple-audio-card,"-prefix.
Required dai-link subnodes:
Required subnodes:
- cpu : CPU sub-node
- codec : CODEC sub-node
- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes
This container may be omitted when the
card has only one DAI link.
See the examples.
Optional dai-link subnode properties:
- simple-audio-card,cpu : CPU sub-node
- simple-audio-card,codec : CODEC sub-node
- format : CPU/CODEC common audio format.
"i2s", "right_j", "left_j" , "dsp_a"
"dsp_b", "ac97", "pdm", "msb", "lsb"
- frame-master : Indicates dai-link frame master.
phandle to a cpu or codec subnode.
- bitclock-master : Indicates dai-link bit clock master.
phandle to a cpu or codec subnode.
- bitclock-inversion : bool property. Add this if the
dai-link uses bit clock inversion.
- frame-inversion : bool property. Add this if the
dai-link uses frame clock inversion.
For backward compatibility the frame-master and bitclock-master
properties can be used as booleans in codec subnode to indicate if the
codec is the dai-link frame or bit clock master. In this case there
should be no dai-link node, the same properties should not be present
at sound-node level, and the bitclock-inversion and frame-inversion
properties should also be placed in the codec node if needed.
Required CPU/CODEC subnodes properties:
......@@ -37,29 +65,21 @@ Required CPU/CODEC subnodes properties:
Optional CPU/CODEC subnodes properties:
- format : CPU/CODEC specific audio format if needed.
see simple-audio-card,format
- frame-master : bool property. add this if subnode is frame master
- bitclock-master : bool property. add this if subnode is bitclock master
- bitclock-inversion : bool property. add this if subnode has clock inversion
- frame-inversion : bool property. add this if subnode has frame inversion
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
- dai-tdm-slot-width : Please refer to tdm-slot.txt.
- clocks / system-clock-frequency : specify subnode's clock if needed.
it can be specified via "clocks" if system has
clock node (= common clock), or "system-clock-frequency"
(if system doens't support common clock)
Note:
* For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and
'frame-inversion', the simple card will use the settings of CODEC for both
CPU and CODEC sides as we need to keep the settings identical for both ends
of the link.
Example 1 - single DAI link:
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "VF610-Tower-Sound-Card";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
simple-audio-card,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack",
......@@ -69,17 +89,12 @@ sound {
"Headphone Jack", "HP_OUT",
"External Speaker", "LINE_OUT";
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <8>;
simple-audio-card,cpu {
sound-dai = <&sh_fsi2 0>;
};
simple-audio-card,codec {
dailink0_master: simple-audio-card,codec {
sound-dai = <&ak4648>;
bitclock-master;
frame-master;
clocks = <&osc>;
};
};
......@@ -105,31 +120,31 @@ Example 2 - many DAI links:
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "Cubox Audio";
simple-audio-card,format = "i2s";
simple-audio-card,dai-link@0 { /* I2S - HDMI */
simple-audio-card,cpu {
format = "i2s";
cpu {
sound-dai = <&audio1 0>;
};
simple-audio-card,codec {
codec {
sound-dai = <&tda998x 0>;
};
};
simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
simple-audio-card,cpu {
cpu {
sound-dai = <&audio1 1>;
};
simple-audio-card,codec {
codec {
sound-dai = <&tda998x 1>;
};
};
simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
simple-audio-card,cpu {
cpu {
sound-dai = <&audio1 1>;
};
simple-audio-card,codec {
codec {
sound-dai = <&spdif_codec>;
};
};
......
Audio Binding for Snow boards
Required properties:
- compatible : Can be one of the following,
"google,snow-audio-max98090" or
"google,snow-audio-max98095"
- samsung,i2s-controller: The phandle of the Samsung I2S controller
- samsung,audio-codec: The phandle of the audio codec
Example:
sound {
compatible = "google,snow-audio-max98095";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98095>;
};
STA350 audio CODEC
The driver for this device only supports I2C.
Required properties:
- compatible: "st,sta350"
- reg: the I2C address of the device for I2C
- reset-gpios: a GPIO spec for the reset pin. If specified, it will be
deasserted before communication to the codec starts.
- power-down-gpios: a GPIO spec for the power down pin. If specified,
it will be deasserted before communication to the codec
starts.
- vdd-dig-supply: regulator spec, providing 3.3V
- vdd-pll-supply: regulator spec, providing 3.3V
- vcc-supply: regulator spec, providing 5V - 26V
Optional properties:
- st,output-conf: number, Selects the output configuration:
0: 2-channel (full-bridge) power, 2-channel data-out
1: 2 (half-bridge). 1 (full-bridge) on-board power
2: 2 Channel (Full-Bridge) Power, 1 Channel FFX
3: 1 Channel Mono-Parallel
If parameter is missing, mode 0 will be enabled.
This property has to be specified as '/bits/ 8' value.
- st,ch1-output-mapping: Channel 1 output mapping
- st,ch2-output-mapping: Channel 2 output mapping
- st,ch3-output-mapping: Channel 3 output mapping
0: Channel 1
1: Channel 2
2: Channel 3
If parameter is missing, channel 1 is choosen.
This properties have to be specified as '/bits/ 8' values.
- st,thermal-warning-recover:
If present, thermal warning recovery is enabled.
- st,thermal-warning-adjustment:
If present, thermal warning adjustment is enabled.
- st,fault-detect-recovery:
If present, then fault recovery will be enabled.
- st,ffx-power-output-mode: string
The FFX power output mode selects how the FFX output timing is
configured. Must be one of these values:
- "drop-compensation"
- "tapered-compensation"
- "full-power-mode"
- "variable-drop-compensation" (default)
- st,drop-compensation-ns: number
Only required for "st,ffx-power-output-mode" ==
"variable-drop-compensation".
Specifies the drop compensation in nanoseconds.
The value must be in the range of 0..300, and only
multiples of 20 are allowed. Default is 140ns.
- st,overcurrent-warning-adjustment:
If present, overcurrent warning adjustment is enabled.
- st,max-power-use-mpcc:
If present, then MPCC bits are used for MPC coefficients,
otherwise standard MPC coefficients are used.
- st,max-power-corr:
If present, power bridge correction for THD reduction near maximum
power output is enabled.
- st,am-reduction-mode:
If present, FFX mode runs in AM reduction mode, otherwise normal
FFX mode is used.
- st,odd-pwm-speed-mode:
If present, PWM speed mode run on odd speed mode (341.3 kHz) on all
channels. If not present, normal PWM spped mode (384 kHz) will be used.
- st,distortion-compensation:
If present, distortion compensation variable uses DCC coefficient.
If not present, preset DC coefficient is used.
- st,invalid-input-detect-mute:
If present, automatic invalid input detect mute is enabled.
- st,activate-mute-output:
If present, a mute output will be activated in ase the volume will
reach a value lower than -76 dBFS.
- st,bridge-immediate-off:
If present, the bridge will be switched off immediately after the
power-down-gpio goes low. Otherwise, the bridge will wait for 13
million clock cycles to pass before shutting down.
- st,noise-shape-dc-cut:
If present, the noise-shaping technique on the DC cutoff filter are
enabled.
- st,powerdown-master-volume:
If present, the power-down pin and I2C power-down functions will
act on the master volume. Otherwise, the functions will act on the
mute commands.
- st,powerdown-delay-divider:
If present, the bridge power-down time will be divided by the provided
value. If not specified, a divider of 1 will be used. Allowed values
are 1, 2, 4, 8, 16, 32, 64 and 128.
This property has to be specified as '/bits/ 8' value.
Example:
codec: sta350@38 {
compatible = "st,sta350";
reg = <0x1c>;
reset-gpios = <&gpio1 19 0>;
power-down-gpios = <&gpio1 16 0>;
st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel
// (full-bridge) power,
// 2-channel data-out
st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1
st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1
st,ch3-output-mapping = /bits/ 8 <0>; // set channel 3 output ch 1
st,max-power-correction; // enables power bridge
// correction for THD reduction
// near maximum power output
st,invalid-input-detect-mute; // mute if no valid digital
// audio signal is provided.
};
......@@ -8270,6 +8270,7 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://www.alsa-project.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
T: git git://git.alsa-project.org/alsa-kernel.git
Q: http://patchwork.kernel.org/project/alsa-devel/list/
S: Maintained
F: Documentation/sound/
F: include/sound/
......
......@@ -22,8 +22,6 @@ enum jz4740_dma_request_type {
JZ4740_DMA_TYPE_UART_RECEIVE = 21,
JZ4740_DMA_TYPE_SPI_TRANSMIT = 22,
JZ4740_DMA_TYPE_SPI_RECEIVE = 23,
JZ4740_DMA_TYPE_AIC_TRANSMIT = 24,
JZ4740_DMA_TYPE_AIC_RECEIVE = 25,
JZ4740_DMA_TYPE_MMC_TRANSMIT = 26,
JZ4740_DMA_TYPE_MMC_RECEIVE = 27,
JZ4740_DMA_TYPE_TCU = 28,
......
......@@ -425,6 +425,15 @@ static struct platform_device qi_lb60_audio_device = {
.id = -1,
};
static struct gpiod_lookup_table qi_lb60_audio_gpio_table = {
.dev_id = "qi-lb60-audio",
.table = {
GPIO_LOOKUP("Bank B", 29, "snd", 0),
GPIO_LOOKUP("Bank D", 4, "amp", 0),
{ },
},
};
static struct platform_device *jz_platform_devices[] __initdata = {
&jz4740_udc_device,
&jz4740_udc_xceiv_device,
......@@ -461,6 +470,8 @@ static int __init qi_lb60_init_platform_devices(void)
jz4740_adc_device.dev.platform_data = &qi_lb60_battery_pdata;
jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
gpiod_add_lookup_table(&qi_lb60_audio_gpio_table);
jz4740_serial_device_register();
spi_register_board_info(qi_lb60_spi_board_info,
......
......@@ -118,7 +118,6 @@ int fw_card_add(struct fw_card *card,
u32 max_receive, u32 link_speed, u64 guid);
void fw_core_remove_card(struct fw_card *card);
int fw_compute_block_crc(__be32 *block);
void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset);
void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
/* -cdev */
......
......@@ -673,9 +673,13 @@ int mc13xxx_common_init(struct device *dev)
if (mc13xxx->flags & MC13XXX_USE_ADC)
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
if (mc13xxx->flags & MC13XXX_USE_CODEC)
if (mc13xxx->flags & MC13XXX_USE_CODEC) {
if (pdata)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
pdata->codec, sizeof(*pdata->codec));
else
mc13xxx_add_subdevice(mc13xxx, "%s-codec");
}
if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
......
......@@ -367,6 +367,9 @@ static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
return tag << 14 | channel << 8 | sy;
}
void fw_schedule_bus_reset(struct fw_card *card, bool delayed,
bool short_reset);
struct fw_descriptor {
struct list_head link;
size_t length;
......
/*
* Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961/ADAU1781/ADAU1781 codecs
*
* Copyright 2011-2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#ifndef __LINUX_PLATFORM_DATA_ADAU17X1_H__
#define __LINUX_PLATFORM_DATA_ADAU17X1_H__
/**
* enum adau17x1_micbias_voltage - Microphone bias voltage
* @ADAU17X1_MICBIAS_0_90_AVDD: 0.9 * AVDD
* @ADAU17X1_MICBIAS_0_65_AVDD: 0.65 * AVDD
*/
enum adau17x1_micbias_voltage {
ADAU17X1_MICBIAS_0_90_AVDD = 0,
ADAU17X1_MICBIAS_0_65_AVDD = 1,
};
/**
* enum adau1761_digmic_jackdet_pin_mode - Configuration of the JACKDET/MICIN pin
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: Disable the pin
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: Configure the pin for usage as
* digital microphone input.
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT: Configure the pin for jack
* insertion detection.
*/
enum adau1761_digmic_jackdet_pin_mode {
ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE,
ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC,
ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT,
};
/**
* adau1761_jackdetect_debounce_time - Jack insertion detection debounce time
* @ADAU1761_JACKDETECT_DEBOUNCE_5MS: 5 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_10MS: 10 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_20MS: 20 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_40MS: 40 milliseconds
*/
enum adau1761_jackdetect_debounce_time {
ADAU1761_JACKDETECT_DEBOUNCE_5MS = 0,
ADAU1761_JACKDETECT_DEBOUNCE_10MS = 1,
ADAU1761_JACKDETECT_DEBOUNCE_20MS = 2,
ADAU1761_JACKDETECT_DEBOUNCE_40MS = 3,
};
/**
* enum adau1761_output_mode - Output mode configuration
* @ADAU1761_OUTPUT_MODE_HEADPHONE: Headphone output
* @ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS: Capless headphone output
* @ADAU1761_OUTPUT_MODE_LINE: Line output
*/
enum adau1761_output_mode {
ADAU1761_OUTPUT_MODE_HEADPHONE,
ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS,
ADAU1761_OUTPUT_MODE_LINE,
};
/**
* struct adau1761_platform_data - ADAU1761 Codec driver platform data
* @input_differential: If true the input pins will be configured in
* differential mode.
* @lineout_mode: Output mode for the LOUT/ROUT pins
* @headphone_mode: Output mode for the LHP/RHP pins
* @digmic_jackdetect_pin_mode: JACKDET/MICIN pin configuration
* @jackdetect_debounce_time: Jack insertion detection debounce time.
* Note: This value will only be used, if the JACKDET/MICIN pin is configured
* for jack insertion detection.
* @jackdetect_active_low: If true the jack insertion detection is active low.
* Othwise it will be active high.
* @micbias_voltage: Microphone voltage bias
*/
struct adau1761_platform_data {
bool input_differential;
enum adau1761_output_mode lineout_mode;
enum adau1761_output_mode headphone_mode;
enum adau1761_digmic_jackdet_pin_mode digmic_jackdetect_pin_mode;
enum adau1761_jackdetect_debounce_time jackdetect_debounce_time;
bool jackdetect_active_low;
enum adau17x1_micbias_voltage micbias_voltage;
};
/**
* struct adau1781_platform_data - ADAU1781 Codec driver platform data
* @left_input_differential: If true configure the left input as
* differential input.
* @right_input_differential: If true configure the right input as differntial
* input.
* @use_dmic: If true configure the MIC pins as digital microphone pins instead
* of analog microphone pins.
* @micbias_voltage: Microphone voltage bias
*/
struct adau1781_platform_data {
bool left_input_differential;
bool right_input_differential;
bool use_dmic;
enum adau17x1_micbias_voltage micbias_voltage;
};
#endif
......@@ -23,7 +23,6 @@
* @reset_pin: GPIO pin wired to the reset input on the external AC97 codec,
* optional to use, set to -ENODEV if not in use. AC97 layer will
* try to do a software reset of the external codec anyway.
* @flags: Flags for which directions should be enabled.
*
* If the user do not want to use a DMA channel for playback or capture, i.e.
* only one feature is required on the board. The slave for playback or capture
......@@ -33,7 +32,6 @@
struct ac97c_platform_data {
struct dw_dma_slave rx_dws;
struct dw_dma_slave tx_dws;
unsigned int flags;
int reset_pin;
};
......
......@@ -282,13 +282,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
struct module *module, int extra_size,
struct snd_card **card_ret);
static inline int __deprecated
snd_card_create(int idx, const char *id, struct module *module, int extra_size,
struct snd_card **ret)
{
return snd_card_new(NULL, idx, id, module, extra_size, ret);
}
int snd_card_disconnect(struct snd_card *card);
int snd_card_free(struct snd_card *card);
int snd_card_free_when_closed(struct snd_card *card);
......
/*
* linux/sound/cs42l56.h -- Platform data for CS42L56
*
* Copyright (c) 2014 Cirrus Logic Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CS42L56_H
#define __CS42L56_H
struct cs42l56_platform_data {
/* GPIO for Reset */
unsigned int gpio_nreset;
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* Analog Input 1A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1a_ref_cfg;
/* Analog Input 2A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2a_ref_cfg;
/* Analog Input 1B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1b_ref_cfg;
/* Analog Input 2B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2b_ref_cfg;
/* Charge Pump Freq. Check datasheet Pg62 */
unsigned int chgfreq;
/* HighPass Filter Right Channel Corner Frequency */
unsigned int hpfb_freq;
/* HighPass Filter Left Channel Corner Frequency */
unsigned int hpfa_freq;
/* Adaptive Power Control for LO/HP */
unsigned int adaptive_pwr;
};
#endif /* __CS42L56_H */
/*
* omap-pcm.h - OMAP PCM driver
*
* Copyright (C) 2014 Texas Instruments, Inc.
*
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
#if IS_ENABLED(CONFIG_SND_OMAP_SOC)
int omap_pcm_platform_register(struct device *dev);
#else
static inline int omap_pcm_platform_register(struct device *dev)
{
return 0;
}
#endif /* CONFIG_SND_OMAP_SOC */
#endif /* __OMAP_PCM_H__ */
......@@ -34,47 +34,39 @@
* B : SSI direction
*/
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_PLAY (1 << 24)
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
#define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \
{ .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
#define RSND_SSI_UNUSED \
{ .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 }
{ .dma_id = -1, .pio_irq = -1, .flags = 0 }
struct rsnd_ssi_platform_info {
int dai_id; /* will be removed */
int dma_id;
int pio_irq;
u32 flags;
};
/*
* flags
*/
#define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */
#define RSND_SRC(rate, _dma_id) \
{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
#define RSND_SRC_SET(rate, _dma_id) \
{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
{ .convert_rate = rate, .dma_id = _dma_id, }
#define RSND_SRC_UNUSED \
{ .flags = 0, .convert_rate = 0, .dma_id = 0, }
#define rsnd_scu_platform_info rsnd_src_platform_info
#define src_info scu_info
#define src_info_nr scu_info_nr
{ .convert_rate = 0, .dma_id = -1, }
struct rsnd_src_platform_info {
u32 flags;
u32 convert_rate; /* sampling rate convert */
int dma_id; /* for Gen2 SCU */
};
/*
* flags
*/
struct rsnd_dvc_platform_info {
u32 flags;
};
struct rsnd_dai_path_info {
struct rsnd_ssi_platform_info *ssi;
struct rsnd_src_platform_info *src;
struct rsnd_dvc_platform_info *dvc;
};
struct rsnd_dai_platform_info {
......@@ -99,6 +91,8 @@ struct rcar_snd_info {
int ssi_info_nr;
struct rsnd_src_platform_info *src_info;
int src_info_nr;
struct rsnd_dvc_platform_info *dvc_info;
int dvc_info_nr;
struct rsnd_dai_platform_info *dai_info;
int dai_info_nr;
int (*start)(int id);
......
......@@ -16,6 +16,10 @@ struct rt5640_platform_data {
bool in1_diff;
bool in2_diff;
bool dmic_en;
bool dmic1_data_pin; /* 0 = IN1P; 1 = GPIO3 */
bool dmic2_data_pin; /* 0 = IN1N; 1 = GPIO4 */
int ldo1_en; /* GPIO for LDO1_EN */
};
......
/*
* linux/sound/rt5645.h -- Platform data for RT5645
*
* Copyright 2013 Realtek Microelectronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_SND_RT5645_H
#define __LINUX_SND_RT5645_H
struct rt5645_platform_data {
/* IN2 can optionally be differential */
bool in2_diff;
bool dmic_en;
unsigned int dmic1_data_pin;
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
unsigned int dmic2_data_pin;
/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
};
#endif
/*
* linux/sound/rt286.h -- Platform data for RT286
*
* Copyright 2013 Realtek Microelectronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_SND_RT5651_H
#define __LINUX_SND_RT5651_H
struct rt5651_platform_data {
/* IN2 can optionally be differential */
bool in2_diff;
bool dmic_en;
};
#endif
/*
* linux/sound/rt5677.h -- Platform data for RT5677
*
* Copyright 2013 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_SND_RT5677_H
#define __LINUX_SND_RT5677_H
struct rt5677_platform_data {
/* IN1 IN2 can optionally be differential */
bool in1_diff;
bool in2_diff;
};
#endif
......@@ -252,7 +252,6 @@ struct snd_soc_dai {
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
struct snd_pcm_runtime *runtime;
unsigned int active;
unsigned char probed:1;
......@@ -277,7 +276,6 @@ struct snd_soc_dai {
struct snd_soc_card *card;
struct list_head list;
struct list_head card_list;
};
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
......
......@@ -107,10 +107,6 @@ struct device;
{ .id = snd_soc_dapm_mux, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1}
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
......@@ -166,10 +162,6 @@ struct device;
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \
wflags)
/* additional sequencing control within an event type */
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
......@@ -256,9 +248,8 @@ struct device;
/* generic widgets */
#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
{ .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
.reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
.reg = wreg, .shift = wshift, .mask = wmask, \
.on_val = won_val, .off_val = woff_val, }
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
{ .id = snd_soc_dapm_supply, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
......@@ -305,16 +296,12 @@ struct device;
.get = snd_soc_dapm_get_enum_double, \
.put = snd_soc_dapm_put_enum_double, \
.private_value = (unsigned long)&xenum }
#define SOC_DAPM_ENUM_VIRT(xname, xenum) \
SOC_DAPM_ENUM(xname, xenum)
#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_enum_double, \
.get = xget, \
.put = xput, \
.private_value = (unsigned long)&xenum }
#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
SOC_DAPM_ENUM(xname, xenum)
#define SOC_DAPM_PIN_SWITCH(xname) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
.info = snd_soc_dapm_info_pin_switch, \
......@@ -362,8 +349,6 @@ struct regulator;
struct snd_soc_dapm_widget_list;
struct snd_soc_dapm_update;
int dapm_reg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int dapm_clock_event(struct snd_soc_dapm_widget *w,
......@@ -606,6 +591,7 @@ struct snd_soc_dapm_context {
enum snd_soc_dapm_type, int);
struct device *dev; /* from parent - for debug */
struct snd_soc_component *component; /* parent component */
struct snd_soc_codec *codec; /* parent codec */
struct snd_soc_platform *platform; /* parent platform */
struct snd_soc_card *card; /* parent card */
......
This diff is collapsed.
/*
* Platform data for ST STA350 ASoC codec driver.
*
* Copyright: 2014 Raumfeld GmbH
* Author: Sven Brandau <info@brandau.biz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __LINUX_SND__STA350_H
#define __LINUX_SND__STA350_H
#define STA350_OCFG_2CH 0
#define STA350_OCFG_2_1CH 1
#define STA350_OCFG_1CH 3
#define STA350_OM_CH1 0
#define STA350_OM_CH2 1
#define STA350_OM_CH3 2
#define STA350_THERMAL_ADJUSTMENT_ENABLE 1
#define STA350_THERMAL_RECOVERY_ENABLE 2
#define STA350_FAULT_DETECT_RECOVERY_BYPASS 1
#define STA350_FFX_PM_DROP_COMP 0
#define STA350_FFX_PM_TAPERED_COMP 1
#define STA350_FFX_PM_FULL_POWER 2
#define STA350_FFX_PM_VARIABLE_DROP_COMP 3
struct sta350_platform_data {
u8 output_conf;
u8 ch1_output_mapping;
u8 ch2_output_mapping;
u8 ch3_output_mapping;
u8 ffx_power_output_mode;
u8 drop_compensation_ns;
u8 powerdown_delay_divider;
unsigned int thermal_warning_recovery:1;
unsigned int thermal_warning_adjustment:1;
unsigned int fault_detect_recovery:1;
unsigned int oc_warning_adjustment:1;
unsigned int max_power_use_mpcc:1;
unsigned int max_power_correction:1;
unsigned int am_reduction_mode:1;
unsigned int odd_pwm_speed_mode:1;
unsigned int distortion_compensation:1;
unsigned int invalid_input_detect_mute:1;
unsigned int activate_mute_output:1;
unsigned int bridge_immediate_off:1;
unsigned int noise_shape_dc_cut:1;
unsigned int powerdown_master_vol:1;
};
#endif /* __LINUX_SND__STA350_H */
......@@ -11,102 +11,10 @@
struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_platform;
struct snd_soc_card;
struct snd_soc_dapm_widget;
struct snd_soc_dapm_path;
/*
* Log register events
*/
DECLARE_EVENT_CLASS(snd_soc_reg,
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val),
TP_ARGS(codec, reg, val),
TP_STRUCT__entry(
__string( name, codec->name )
__field( int, id )
__field( unsigned int, reg )
__field( unsigned int, val )
),
TP_fast_assign(
__assign_str(name, codec->name);
__entry->id = codec->id;
__entry->reg = reg;
__entry->val = val;
),
TP_printk("codec=%s.%d reg=%x val=%x", __get_str(name),
(int)__entry->id, (unsigned int)__entry->reg,
(unsigned int)__entry->val)
);
DEFINE_EVENT(snd_soc_reg, snd_soc_reg_write,
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val),
TP_ARGS(codec, reg, val)
);
DEFINE_EVENT(snd_soc_reg, snd_soc_reg_read,
TP_PROTO(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val),
TP_ARGS(codec, reg, val)
);
DECLARE_EVENT_CLASS(snd_soc_preg,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val),
TP_STRUCT__entry(
__string( name, platform->name )
__field( int, id )
__field( unsigned int, reg )
__field( unsigned int, val )
),
TP_fast_assign(
__assign_str(name, platform->name);
__entry->id = platform->id;
__entry->reg = reg;
__entry->val = val;
),
TP_printk("platform=%s.%d reg=%x val=%x", __get_str(name),
(int)__entry->id, (unsigned int)__entry->reg,
(unsigned int)__entry->val)
);
DEFINE_EVENT(snd_soc_preg, snd_soc_preg_write,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val)
);
DEFINE_EVENT(snd_soc_preg, snd_soc_preg_read,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val)
);
DECLARE_EVENT_CLASS(snd_soc_card,
TP_PROTO(struct snd_soc_card *card, int val),
......
......@@ -94,9 +94,11 @@ enum {
SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */
SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */
SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */
/* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_DICE
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_BEBOB
};
struct snd_hwdep_info {
......
......@@ -2,11 +2,13 @@
#define _UAPI_SOUND_FIREWIRE_H_INCLUDED
#include <linux/ioctl.h>
#include <linux/types.h>
/* events can be read() from the hwdep device */
#define SNDRV_FIREWIRE_EVENT_LOCK_STATUS 0x000010cc
#define SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION 0xd1ce004e
#define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
struct snd_firewire_event_common {
unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
......@@ -22,10 +24,27 @@ struct snd_firewire_event_dice_notification {
unsigned int notification; /* DICE-specific bits */
};
#define SND_EFW_TRANSACTION_USER_SEQNUM_MAX ((__u32)((__u16)~0) - 1)
/* each field should be in big endian */
struct snd_efw_transaction {
__be32 length;
__be32 version;
__be32 seqnum;
__be32 category;
__be32 command;
__be32 status;
__be32 params[0];
};
struct snd_firewire_event_efw_response {
unsigned int type;
__be32 response[0]; /* some responses */
};
union snd_firewire_event {
struct snd_firewire_event_common common;
struct snd_firewire_event_lock_status lock_status;
struct snd_firewire_event_dice_notification dice_notification;
struct snd_firewire_event_efw_response efw_response;
};
......@@ -34,7 +53,9 @@ union snd_firewire_event {
#define SNDRV_FIREWIRE_IOCTL_UNLOCK _IO('H', 0xfa)
#define SNDRV_FIREWIRE_TYPE_DICE 1
/* Fireworks, AV/C, RME, MOTU, ... */
#define SNDRV_FIREWIRE_TYPE_FIREWORKS 2
#define SNDRV_FIREWIRE_TYPE_BEBOB 3
/* AV/C, RME, MOTU, ... */
struct snd_firewire_get_info {
unsigned int type; /* SNDRV_FIREWIRE_TYPE_xxx */
......
......@@ -241,7 +241,7 @@ static struct snd_kcontrol_new inputgain_control = {
static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "Line-In", "Microphone" };
static const char * const texts[] = { "Line-In", "Microphone" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
......
......@@ -14,6 +14,8 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <mach/dma.h>
#include <sound/core.h>
#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
......
......@@ -9,12 +9,11 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <mach/dma.h>
struct pxa2xx_runtime_data {
int dma_ch;
struct snd_dmaengine_dai_dma_data *params;
pxa_dma_desc *dma_desc_array;
struct pxa_dma_desc *dma_desc_array;
dma_addr_t dma_desc_array_phys;
};
......
......@@ -1198,6 +1198,7 @@ static int atmel_ac97c_remove(struct platform_device *pdev)
}
static struct platform_driver atmel_ac97c_driver = {
.probe = atmel_ac97c_probe,
.remove = atmel_ac97c_remove,
.driver = {
.name = "atmel_ac97c",
......@@ -1205,19 +1206,7 @@ static struct platform_driver atmel_ac97c_driver = {
.pm = ATMEL_AC97C_PM_OPS,
},
};
static int __init atmel_ac97c_init(void)
{
return platform_driver_probe(&atmel_ac97c_driver,
atmel_ac97c_probe);
}
module_init(atmel_ac97c_init);
static void __exit atmel_ac97c_exit(void)
{
platform_driver_unregister(&atmel_ac97c_driver);
}
module_exit(atmel_ac97c_exit);
module_platform_driver(atmel_ac97c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver for Atmel AC97 controller");
......
......@@ -345,7 +345,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
snd_pcm_debug_name(substream, name, sizeof(name));
xrun_log_show(substream);
pcm_err(substream->pcm,
"BUG: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
"XRUN: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
name, pos, runtime->buffer_size,
runtime->period_size);
}
......
......@@ -362,13 +362,13 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
if (! port->name[0]) {
if (info->name[0]) {
if (ports > 1)
snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p);
snprintf(port->name, sizeof(port->name), "%s-%u", info->name, p);
else
snprintf(port->name, sizeof(port->name), "%s", info->name);
} else {
/* last resort */
if (ports > 1)
sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p);
sprintf(port->name, "MIDI %d-%d-%u", card->number, device, p);
else
sprintf(port->name, "MIDI %d-%d", card->number, device);
}
......
......@@ -9,12 +9,12 @@ if SND_FIREWIRE && FIREWIRE
config SND_FIREWIRE_LIB
tristate
depends on SND_PCM
select SND_PCM
select SND_RAWMIDI
config SND_DICE
tristate "DICE-based DACs (EXPERIMENTAL)"
select SND_HWDEP
select SND_PCM
select SND_FIREWIRE_LIB
help
Say Y here to include support for many DACs based on the DICE
......@@ -28,7 +28,6 @@ config SND_DICE
config SND_FIREWIRE_SPEAKERS
tristate "FireWire speakers"
select SND_PCM
select SND_FIREWIRE_LIB
help
Say Y here to include support for the Griffin FireWave Surround
......@@ -39,7 +38,6 @@ config SND_FIREWIRE_SPEAKERS
config SND_ISIGHT
tristate "Apple iSight microphone"
select SND_PCM
select SND_FIREWIRE_LIB
help
Say Y here to include support for the front and rear microphones
......@@ -50,8 +48,6 @@ config SND_ISIGHT
config SND_SCS1X
tristate "Stanton Control System 1 MIDI"
select SND_PCM
select SND_RAWMIDI
select SND_FIREWIRE_LIB
help
Say Y here to include support for the MIDI ports of the Stanton
......@@ -61,4 +57,59 @@ config SND_SCS1X
To compile this driver as a module, choose M here: the module
will be called snd-scs1x.
config SND_FIREWORKS
tristate "Echo Fireworks board module support"
select SND_FIREWIRE_LIB
select SND_HWDEP
help
Say Y here to include support for FireWire devices based
on Echo Digital Audio Fireworks board:
* Mackie Onyx 400F/1200F
* Echo AudioFire12/8(until 2009 July)
* Echo AudioFire2/4/Pre8/8(since 2009 July)
* Echo Fireworks 8/HDMI
* Gibson Robot Interface Pack/GoldTop
To compile this driver as a module, choose M here: the module
will be called snd-fireworks.
config SND_BEBOB
tristate "BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware"
select SND_FIREWIRE_LIB
select SND_HWDEP
help
Say Y here to include support for FireWire devices based
on BridgeCo DM1000/DM1100/DM1500 with BeBoB firmware:
* Edirol FA-66/FA-101
* PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
* BridgeCo RDAudio1/Audio5
* Mackie Onyx 1220/1620/1640 (Firewire I/O Card)
* Mackie d.2 (Firewire Option)
* Stanton FinalScratch 2 (ScratchAmp)
* Tascam IF-FW/DM
* Behringer XENIX UFX 1204/1604
* Behringer Digital Mixer X32 series (X-UF Card)
* Apogee Rosetta 200/400 (X-FireWire card)
* Apogee DA/AD/DD-16X (X-FireWire card)
* Apogee Ensemble
* ESI Quotafire610
* AcousticReality eARMasterOne
* CME MatrixKFW
* Phonic Helix Board 12 MkII/18 MkII/24 MkII
* Phonic Helix Board 12 Universal/18 Universal/24 Universal
* Lynx Aurora 8/16 (LT-FW)
* ICON FireXon
* PrismSound Orpheus/ADA-8XR
* TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
* Terratec EWS MIC2/EWS MIC4
* Terratec Aureon 7.1 Firewire
* Yamaha GO44/GO46
* Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
* M-Audio Firewire410/AudioPhile/Solo
* M-Audio Ozonic/NRV10/ProfireLightBridge
* M-Audio Firewire 1814/ProjectMix IO
To compile this driver as a module, choose M here: the module
will be called snd-bebob.
endif # SND_FIREWIRE
......@@ -10,3 +10,5 @@ obj-$(CONFIG_SND_DICE) += snd-dice.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o
obj-$(CONFIG_SND_FIREWORKS) += fireworks/
obj-$(CONFIG_SND_BEBOB) += bebob/
This diff is collapsed.
......@@ -8,7 +8,7 @@
#include "packets-buffer.h"
/**
* enum cip_out_flags - describes details of the streaming protocol
* enum cip_flags - describes details of the streaming protocol
* @CIP_NONBLOCKING: In non-blocking mode, each packet contains
* sample_rate/8000 samples, with rounding up or down to adjust
* for clock skew and left-over fractional samples. This should
......@@ -16,15 +16,30 @@
* @CIP_BLOCKING: In blocking mode, each packet contains either zero or
* SYT_INTERVAL samples, with these two types alternating so that
* the overall sample rate comes out right.
* @CIP_HI_DUALWIRE: At rates above 96 kHz, pretend that the stream runs
* at half the actual sample rate with twice the number of channels;
* two samples of a channel are stored consecutively in the packet.
* Requires blocking mode and SYT_INTERVAL-aligned PCM buffer size.
* @CIP_SYNC_TO_DEVICE: In sync to device mode, time stamp in out packets is
* generated by in packets. Defaultly this driver generates timestamp.
* @CIP_EMPTY_WITH_TAG0: Only for in-stream. Empty in-packets have TAG0.
* @CIP_DBC_IS_END_EVENT: Only for in-stream. The value of dbc in an in-packet
* corresponds to the end of event in the packet. Out of IEC 61883.
* @CIP_WRONG_DBS: Only for in-stream. The value of dbs is wrong in in-packets.
* The value of data_block_quadlets is used instead of reported value.
* @SKIP_DBC_ZERO_CHECK: Only for in-stream. Packets with zero in dbc is
* skipped for detecting discontinuity.
* @CIP_SKIP_INIT_DBC_CHECK: Only for in-stream. The value of dbc in first
* packet is not continuous from an initial value.
* @CIP_EMPTY_HAS_WRONG_DBC: Only for in-stream. The value of dbc in empty
* packet is wrong but the others are correct.
*/
enum cip_out_flags {
enum cip_flags {
CIP_NONBLOCKING = 0x00,
CIP_BLOCKING = 0x01,
CIP_HI_DUALWIRE = 0x02,
CIP_SYNC_TO_DEVICE = 0x02,
CIP_EMPTY_WITH_TAG0 = 0x04,
CIP_DBC_IS_END_EVENT = 0x08,
CIP_WRONG_DBS = 0x10,
CIP_SKIP_DBC_ZERO_CHECK = 0x20,
CIP_SKIP_INIT_DBC_CHECK = 0x40,
CIP_EMPTY_HAS_WRONG_DBC = 0x80,
};
/**
......@@ -41,27 +56,55 @@ enum cip_sfc {
CIP_SFC_COUNT
};
#define AMDTP_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32
#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \
SNDRV_PCM_FMTBIT_S32)
/*
* This module supports maximum 64 PCM channels for one PCM stream
* This is for our convenience.
*/
#define AMDTP_MAX_CHANNELS_FOR_PCM 64
/*
* AMDTP packet can include channels for MIDI conformant data.
* Each MIDI conformant data channel includes 8 MPX-MIDI data stream.
* Each MPX-MIDI data stream includes one data stream from/to MIDI ports.
*
* This module supports maximum 1 MIDI conformant data channels.
* Then this AMDTP packets can transfer maximum 8 MIDI data streams.
*/
#define AMDTP_MAX_CHANNELS_FOR_MIDI 1
struct fw_unit;
struct fw_iso_context;
struct snd_pcm_substream;
struct snd_pcm_runtime;
struct snd_rawmidi_substream;
struct amdtp_out_stream {
enum amdtp_stream_direction {
AMDTP_OUT_STREAM = 0,
AMDTP_IN_STREAM
};
struct amdtp_stream {
struct fw_unit *unit;
enum cip_out_flags flags;
enum cip_flags flags;
enum amdtp_stream_direction direction;
struct fw_iso_context *context;
struct mutex mutex;
enum cip_sfc sfc;
bool dual_wire;
unsigned int data_block_quadlets;
unsigned int pcm_channels;
unsigned int midi_ports;
void (*transfer_samples)(struct amdtp_out_stream *s,
void (*transfer_samples)(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames);
u8 pcm_positions[AMDTP_MAX_CHANNELS_FOR_PCM];
u8 midi_position;
unsigned int syt_interval;
unsigned int transfer_delay;
......@@ -82,65 +125,148 @@ struct amdtp_out_stream {
unsigned int pcm_buffer_pointer;
unsigned int pcm_period_pointer;
bool pointer_flush;
struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
/* quirk: fixed interval of dbc between previos/current packets. */
unsigned int tx_dbc_interval;
/* quirk: the first count of data blocks in an rx packet for MIDI */
unsigned int rx_blocks_for_midi;
bool callbacked;
wait_queue_head_t callback_wait;
struct amdtp_stream *sync_slave;
};
int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
enum cip_out_flags flags);
void amdtp_out_stream_destroy(struct amdtp_out_stream *s);
int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir,
enum cip_flags flags);
void amdtp_stream_destroy(struct amdtp_stream *s);
void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s,
void amdtp_stream_set_parameters(struct amdtp_stream *s,
unsigned int rate,
unsigned int pcm_channels,
unsigned int midi_ports);
unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s);
unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s);
int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed);
void amdtp_out_stream_update(struct amdtp_out_stream *s);
void amdtp_out_stream_stop(struct amdtp_out_stream *s);
int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed);
void amdtp_stream_update(struct amdtp_stream *s);
void amdtp_stream_stop(struct amdtp_stream *s);
void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
struct snd_pcm_runtime *runtime);
void amdtp_stream_set_pcm_format(struct amdtp_stream *s,
snd_pcm_format_t format);
void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s);
unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s);
void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
void amdtp_stream_pcm_prepare(struct amdtp_stream *s);
unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s);
void amdtp_stream_pcm_abort(struct amdtp_stream *s);
extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT];
extern const unsigned int amdtp_rate_table[CIP_SFC_COUNT];
static inline bool amdtp_out_stream_running(struct amdtp_out_stream *s)
/**
* amdtp_stream_running - check stream is running or not
* @s: the AMDTP stream
*
* If this function returns true, the stream is running.
*/
static inline bool amdtp_stream_running(struct amdtp_stream *s)
{
return !IS_ERR(s->context);
}
/**
* amdtp_out_streaming_error - check for streaming error
* @s: the AMDTP output stream
* amdtp_streaming_error - check for streaming error
* @s: the AMDTP stream
*
* If this function returns true, the stream's packet queue has stopped due to
* an asynchronous error.
*/
static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
static inline bool amdtp_streaming_error(struct amdtp_stream *s)
{
return s->packet_index < 0;
}
/**
* amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device
* @s: the AMDTP output stream
* amdtp_stream_pcm_running - check PCM substream is running or not
* @s: the AMDTP stream
*
* If this function returns true, PCM substream in the AMDTP stream is running.
*/
static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s)
{
return !!s->pcm;
}
/**
* amdtp_stream_pcm_trigger - start/stop playback from a PCM device
* @s: the AMDTP stream
* @pcm: the PCM device to be started, or %NULL to stop the current device
*
* Call this function on a running isochronous stream to enable the actual
* transmission of PCM data. This function should be called from the PCM
* device's .trigger callback.
*/
static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s,
static inline void amdtp_stream_pcm_trigger(struct amdtp_stream *s,
struct snd_pcm_substream *pcm)
{
ACCESS_ONCE(s->pcm) = pcm;
}
/**
* amdtp_stream_midi_trigger - start/stop playback/capture with a MIDI device
* @s: the AMDTP stream
* @port: index of MIDI port
* @midi: the MIDI device to be started, or %NULL to stop the current device
*
* Call this function on a running isochronous stream to enable the actual
* transmission of MIDI data. This function should be called from the MIDI
* device's .trigger callback.
*/
static inline void amdtp_stream_midi_trigger(struct amdtp_stream *s,
unsigned int port,
struct snd_rawmidi_substream *midi)
{
if (port < s->midi_ports)
ACCESS_ONCE(s->midi[port]) = midi;
}
static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
{
return sfc & 1;
}
static inline void amdtp_stream_set_sync(enum cip_flags sync_mode,
struct amdtp_stream *master,
struct amdtp_stream *slave)
{
if (sync_mode == CIP_SYNC_TO_DEVICE) {
master->flags |= CIP_SYNC_TO_DEVICE;
slave->flags |= CIP_SYNC_TO_DEVICE;
master->sync_slave = slave;
} else {
master->flags &= ~CIP_SYNC_TO_DEVICE;
slave->flags &= ~CIP_SYNC_TO_DEVICE;
master->sync_slave = NULL;
}
slave->sync_slave = NULL;
}
/**
* amdtp_stream_wait_callback - sleep till callbacked or timeout
* @s: the AMDTP stream
* @timeout: msec till timeout
*
* If this function return false, the AMDTP stream should be stopped.
*/
static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
unsigned int timeout)
{
return wait_event_timeout(s->callback_wait,
s->callbacked == true,
msecs_to_jiffies(timeout)) > 0;
}
#endif
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
This diff is collapsed.
/*
* bebob.h - a part of driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
#ifndef SOUND_BEBOB_H_INCLUDED
#define SOUND_BEBOB_H_INCLUDED
#include <linux/compat.h>
#include <linux/device.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/info.h>
#include <sound/rawmidi.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/firewire.h>
#include <sound/hwdep.h>
#include "../lib.h"
#include "../fcp.h"
#include "../packets-buffer.h"
#include "../iso-resources.h"
#include "../amdtp.h"
#include "../cmp.h"
/* basic register addresses on DM1000/DM1100/DM1500 */
#define BEBOB_ADDR_REG_INFO 0xffffc8020000ULL
#define BEBOB_ADDR_REG_REQ 0xffffc8021000ULL
struct snd_bebob;
#define SND_BEBOB_STRM_FMT_ENTRIES 7
struct snd_bebob_stream_formation {
unsigned int pcm;
unsigned int midi;
};
/* this is a lookup table for index of stream formations */
extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES];
/* device specific operations */
#define SND_BEBOB_CLOCK_INTERNAL "Internal"
struct snd_bebob_clock_spec {
unsigned int num;
char *const *labels;
int (*get)(struct snd_bebob *bebob, unsigned int *id);
};
struct snd_bebob_rate_spec {
int (*get)(struct snd_bebob *bebob, unsigned int *rate);
int (*set)(struct snd_bebob *bebob, unsigned int rate);
};
struct snd_bebob_meter_spec {
unsigned int num;
char *const *labels;
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;
};
struct snd_bebob {
struct snd_card *card;
struct fw_unit *unit;
int card_index;
struct mutex mutex;
spinlock_t lock;
const struct snd_bebob_spec *spec;
unsigned int midi_input_ports;
unsigned int midi_output_ports;
/* for bus reset quirk */
struct completion bus_reset;
bool connected;
struct amdtp_stream *master;
struct amdtp_stream tx_stream;
struct amdtp_stream rx_stream;
struct cmp_connection out_conn;
struct cmp_connection in_conn;
atomic_t capture_substreams;
atomic_t playback_substreams;
struct snd_bebob_stream_formation
tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
struct snd_bebob_stream_formation
rx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
int sync_input_plug;
/* for uapi */
int dev_lock_count;
bool dev_lock_changed;
wait_queue_head_t hwdep_wait;
/* for M-Audio special devices */
void *maudio_special_quirk;
bool deferred_registration;
};
static inline int
snd_bebob_read_block(struct fw_unit *unit, u64 addr, void *buf, int size)
{
return snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
BEBOB_ADDR_REG_INFO + addr,
buf, size, 0);
}
static inline int
snd_bebob_read_quad(struct fw_unit *unit, u64 addr, u32 *buf)
{
return snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
BEBOB_ADDR_REG_INFO + addr,
(void *)buf, sizeof(u32), 0);
}
/* AV/C Audio Subunit Specification 1.0 (Oct 2000, 1394TA) */
int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
unsigned int fb_id, unsigned int num);
int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
unsigned int fb_id, unsigned int *num);
/*
* AVC command extensions, AV/C Unit and Subunit, Revision 17
* (Nov 2003, BridgeCo)
*/
#define AVC_BRIDGECO_ADDR_BYTES 6
enum avc_bridgeco_plug_dir {
AVC_BRIDGECO_PLUG_DIR_IN = 0x00,
AVC_BRIDGECO_PLUG_DIR_OUT = 0x01
};
enum avc_bridgeco_plug_mode {
AVC_BRIDGECO_PLUG_MODE_UNIT = 0x00,
AVC_BRIDGECO_PLUG_MODE_SUBUNIT = 0x01,
AVC_BRIDGECO_PLUG_MODE_FUNCTION_BLOCK = 0x02
};
enum avc_bridgeco_plug_unit {
AVC_BRIDGECO_PLUG_UNIT_ISOC = 0x00,
AVC_BRIDGECO_PLUG_UNIT_EXT = 0x01,
AVC_BRIDGECO_PLUG_UNIT_ASYNC = 0x02
};
enum avc_bridgeco_plug_type {
AVC_BRIDGECO_PLUG_TYPE_ISOC = 0x00,
AVC_BRIDGECO_PLUG_TYPE_ASYNC = 0x01,
AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02,
AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03,
AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04,
AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05
};
static inline void
avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES],
enum avc_bridgeco_plug_dir dir,
enum avc_bridgeco_plug_unit unit,
unsigned int pid)
{
buf[0] = 0xff; /* Unit */
buf[1] = dir;
buf[2] = AVC_BRIDGECO_PLUG_MODE_UNIT;
buf[3] = unit;
buf[4] = 0xff & pid;
buf[5] = 0xff; /* reserved */
}
static inline void
avc_bridgeco_fill_msu_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES],
enum avc_bridgeco_plug_dir dir,
unsigned int pid)
{
buf[0] = 0x60; /* Music subunit */
buf[1] = dir;
buf[2] = AVC_BRIDGECO_PLUG_MODE_SUBUNIT;
buf[3] = 0xff & pid;
buf[4] = 0xff; /* reserved */
buf[5] = 0xff; /* reserved */
}
int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
u8 *buf, unsigned int len);
int avc_bridgeco_get_plug_type(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
enum avc_bridgeco_plug_type *type);
int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
unsigned int id, u8 *type);
int avc_bridgeco_get_plug_input(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
u8 input[7]);
int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
unsigned int *len, unsigned int eid);
/* 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_discover(struct snd_bebob *bebob);
int snd_bebob_stream_map(struct snd_bebob *bebob,
struct amdtp_stream *stream);
int snd_bebob_stream_init_duplex(struct snd_bebob *bebob);
int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate);
void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob);
void snd_bebob_stream_update_duplex(struct snd_bebob *bebob);
void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
void snd_bebob_stream_lock_changed(struct snd_bebob *bebob);
int snd_bebob_stream_lock_try(struct snd_bebob *bebob);
void snd_bebob_stream_lock_release(struct snd_bebob *bebob);
void snd_bebob_proc_init(struct snd_bebob *bebob);
int snd_bebob_create_midi_devices(struct snd_bebob *bebob);
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;
int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814);
int snd_bebob_maudio_load_firmware(struct fw_unit *unit);
#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \
{ \
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
IEEE1394_MATCH_MODEL_ID, \
.vendor_id = vendor, \
.model_id = model, \
.driver_data = (kernel_ulong_t)data \
}
#endif
/*
* bebob_command.c - driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include "./bebob.h"
int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
unsigned int fb_id, unsigned int num)
{
u8 *buf;
int err;
buf = kzalloc(12, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
buf[0] = 0x00; /* AV/C CONTROL */
buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
buf[2] = 0xb8; /* FUNCTION BLOCK */
buf[3] = 0x80; /* type is 'selector'*/
buf[4] = 0xff & fb_id; /* function block id */
buf[5] = 0x10; /* control attribute is CURRENT */
buf[6] = 0x02; /* selector length is 2 */
buf[7] = 0xff & num; /* input function block plug number */
buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(7) | BIT(8));
if (err > 0 && err < 9)
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (err > 0)
err = 0;
kfree(buf);
return err;
}
int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
unsigned int fb_id, unsigned int *num)
{
u8 *buf;
int err;
buf = kzalloc(12, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
buf[0] = 0x01; /* AV/C STATUS */
buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */
buf[2] = 0xb8; /* FUNCTION BLOCK */
buf[3] = 0x80; /* type is 'selector'*/
buf[4] = 0xff & fb_id; /* function block id */
buf[5] = 0x10; /* control attribute is CURRENT */
buf[6] = 0x02; /* selector length is 2 */
buf[7] = 0xff; /* input function block plug number */
buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(8));
if (err > 0 && err < 9)
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
if (err < 0)
goto end;
*num = buf[7];
err = 0;
end:
kfree(buf);
return err;
}
static inline void
avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
{
buf[1] = addr[0];
memcpy(buf + 4, addr + 1, 5);
}
static inline void
avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
unsigned int itype)
{
buf[0] = 0x01; /* AV/C STATUS */
buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */
buf[3] = 0xc0; /* BridgeCo extension */
avc_bridgeco_fill_extension_addr(buf, addr);
buf[9] = itype; /* info type */
}
int avc_bridgeco_get_plug_type(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
enum avc_bridgeco_plug_type *type)
{
u8 *buf;
int err;
buf = kzalloc(12, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
/* Info type is 'plug type'. */
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(7) | BIT(9));
if ((err >= 0) && (err < 8))
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
if (err < 0)
goto end;
*type = buf[10];
err = 0;
end:
kfree(buf);
return err;
}
int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
u8 *buf, unsigned int len)
{
int err;
/* Info type is 'channel position'. */
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
err = fcp_avc_transaction(unit, buf, 12, buf, 256,
BIT(1) | BIT(2) | BIT(3) | BIT(4) |
BIT(5) | BIT(6) | BIT(7) | BIT(9));
if ((err >= 0) && (err < 8))
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
if (err < 0)
goto end;
/* Pick up specific data. */
memmove(buf, buf + 10, err - 10);
err = 0;
end:
return err;
}
int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
unsigned int id, u8 *type)
{
u8 *buf;
int err;
/* section info includes charactors but this module don't need it */
buf = kzalloc(12, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
/* Info type is 'section info'. */
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
buf[10] = 0xff & ++id; /* section id */
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(7) | BIT(9) | BIT(10));
if ((err >= 0) && (err < 8))
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
if (err < 0)
goto end;
*type = buf[11];
err = 0;
end:
kfree(buf);
return err;
}
int avc_bridgeco_get_plug_input(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
{
int err;
u8 *buf;
buf = kzalloc(18, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
/* Info type is 'plug input'. */
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
err = fcp_avc_transaction(unit, buf, 16, buf, 16,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(7));
if ((err >= 0) && (err < 8))
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
if (err < 0)
goto end;
memcpy(input, buf + 10, 5);
err = 0;
end:
kfree(buf);
return err;
}
int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
unsigned int *len, unsigned int eid)
{
int err;
/* check given buffer */
if ((buf == NULL) || (*len < 12)) {
err = -EINVAL;
goto end;
}
buf[0] = 0x01; /* AV/C STATUS */
buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
buf[3] = 0xc1; /* Bridgeco extension - List Request */
avc_bridgeco_fill_extension_addr(buf, addr);
buf[10] = 0xff & eid; /* Entry ID */
err = fcp_avc_transaction(unit, buf, 12, buf, *len,
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
BIT(6) | BIT(7) | BIT(10));
if ((err >= 0) && (err < 12))
err = -EIO;
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
err = -ENOSYS;
else if (buf[0] == 0x0a) /* REJECTED */
err = -EINVAL;
else if (buf[0] == 0x0b) /* IN TRANSITION */
err = -EAGAIN;
else if (buf[10] != eid)
err = -EIO;
if (err < 0)
goto end;
/* Pick up 'stream format info'. */
memmove(buf, buf + 11, err - 11);
*len = err - 11;
err = 0;
end:
return err;
}
/*
* bebob_focusrite.c - a part of driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include "./bebob.h"
#define ANA_IN "Analog In"
#define DIG_IN "Digital In"
#define ANA_OUT "Analog Out"
#define DIG_OUT "Digital Out"
#define STM_IN "Stream In"
#define SAFFIRE_ADDRESS_BASE 0x000100000000ULL
#define SAFFIRE_OFFSET_CLOCK_SOURCE 0x00f8
#define SAFFIREPRO_OFFSET_CLOCK_SOURCE 0x0174
/* whether sync to external device or not */
#define SAFFIRE_OFFSET_CLOCK_SYNC_EXT 0x013c
#define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT 0x0432
#define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT 0x0164
#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
/* '1' is absent, why... */
#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4
#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
/* saffirepro has its own parameter for sampling frequency */
#define SAFFIREPRO_RATE_NOREBOOT 0x01cc
/* index is the value for this register */
static const unsigned int rates[] = {
[0] = 0,
[1] = 44100,
[2] = 48000,
[3] = 88200,
[4] = 96000,
[5] = 176400,
[6] = 192000
};
/* saffire(no label)/saffire LE has metering */
#define SAFFIRE_OFFSET_METER 0x0100
#define SAFFIRE_LE_OFFSET_METER 0x0168
static inline int
saffire_read_block(struct snd_bebob *bebob, u64 offset,
u32 *buf, unsigned int size)
{
unsigned int i;
int err;
__be32 *tmp = (__be32 *)buf;
err = snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST,
SAFFIRE_ADDRESS_BASE + offset,
tmp, size, 0);
if (err < 0)
goto end;
for (i = 0; i < size / sizeof(u32); i++)
buf[i] = be32_to_cpu(tmp[i]);
end:
return err;
}
static inline int
saffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value)
{
int err;
__be32 tmp;
err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST,
SAFFIRE_ADDRESS_BASE + offset,
&tmp, sizeof(__be32), 0);
if (err < 0)
goto end;
*value = be32_to_cpu(tmp);
end:
return err;
}
static inline int
saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
{
__be32 data = cpu_to_be32(value);
return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST,
SAFFIRE_ADDRESS_BASE + offset,
&data, sizeof(__be32), 0);
}
static char *const saffirepro_26_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
};
static char *const saffirepro_10_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
};
static int
saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
{
u32 id;
int err;
err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id);
if (err < 0)
goto end;
if (id >= ARRAY_SIZE(rates))
err = -EIO;
else
*rate = rates[id];
end:
return err;
}
static int
saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
{
u32 id;
for (id = 0; id < ARRAY_SIZE(rates); id++) {
if (rates[id] == rate)
break;
}
if (id == ARRAY_SIZE(rates))
return -EINVAL;
return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
}
static int
saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{
int err;
u32 value;
err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
if (err < 0)
goto end;
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) {
if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK)
*id = 2;
else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF)
*id = 1;
} else if (value > 1) {
*id = value - 1;
}
end:
return err;
}
struct snd_bebob_spec saffire_le_spec;
static char *const saffire_both_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF"
};
static int
saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{
int err;
u32 value;
err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value);
if (err >= 0)
*id = 0xff & value;
return err;
};
static char *const saffire_le_meter_labels[] = {
ANA_IN, ANA_IN, DIG_IN,
ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT,
STM_IN, STM_IN
};
static char *const saffire_meter_labels[] = {
ANA_IN, ANA_IN,
STM_IN, STM_IN, STM_IN, STM_IN, STM_IN,
};
static int
saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size)
{
struct snd_bebob_meter_spec *spec = bebob->spec->meter;
unsigned int channels;
u64 offset;
int err;
if (spec->labels == saffire_le_meter_labels)
offset = SAFFIRE_LE_OFFSET_METER;
else
offset = SAFFIRE_OFFSET_METER;
channels = spec->num * 2;
if (size < channels * sizeof(u32))
return -EIO;
err = saffire_read_block(bebob, offset, buf, size);
if (err >= 0 && spec->labels == saffire_le_meter_labels) {
swap(buf[1], buf[3]);
swap(buf[2], buf[3]);
swap(buf[3], buf[4]);
swap(buf[7], buf[10]);
swap(buf[8], buf[10]);
swap(buf[9], buf[11]);
swap(buf[11], buf[12]);
swap(buf[15], buf[16]);
}
return err;
}
static 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,
.get = &saffirepro_both_clk_src_get,
};
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,
.get = &saffirepro_both_clk_src_get,
};
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 = {
.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,
.get = &saffire_both_clk_src_get,
};
/* Saffire LE */
static 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 = {
.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 = {
.num = ARRAY_SIZE(saffire_meter_labels),
.labels = saffire_meter_labels,
.get = &saffire_meter_get,
};
struct snd_bebob_spec saffire_spec = {
.clock = &saffire_both_clk_spec,
.rate = &saffire_both_rate_spec,
.meter = &saffire_meter_spec
};
/*
* bebob_hwdep.c - a part of driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
/*
* This codes give three functionality.
*
* 1.get firewire node infomation
* 2.get notification about starting/stopping stream
* 3.lock/unlock stream
*/
#include "bebob.h"
static long
hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
loff_t *offset)
{
struct snd_bebob *bebob = hwdep->private_data;
DEFINE_WAIT(wait);
union snd_firewire_event event;
spin_lock_irq(&bebob->lock);
while (!bebob->dev_lock_changed) {
prepare_to_wait(&bebob->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
spin_unlock_irq(&bebob->lock);
schedule();
finish_wait(&bebob->hwdep_wait, &wait);
if (signal_pending(current))
return -ERESTARTSYS;
spin_lock_irq(&bebob->lock);
}
memset(&event, 0, sizeof(event));
if (bebob->dev_lock_changed) {
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
event.lock_status.status = (bebob->dev_lock_count > 0);
bebob->dev_lock_changed = false;
count = min_t(long, count, sizeof(event.lock_status));
}
spin_unlock_irq(&bebob->lock);
if (copy_to_user(buf, &event, count))
return -EFAULT;
return count;
}
static unsigned int
hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait)
{
struct snd_bebob *bebob = hwdep->private_data;
unsigned int events;
poll_wait(file, &bebob->hwdep_wait, wait);
spin_lock_irq(&bebob->lock);
if (bebob->dev_lock_changed)
events = POLLIN | POLLRDNORM;
else
events = 0;
spin_unlock_irq(&bebob->lock);
return events;
}
static int
hwdep_get_info(struct snd_bebob *bebob, void __user *arg)
{
struct fw_device *dev = fw_parent_device(bebob->unit);
struct snd_firewire_get_info info;
memset(&info, 0, sizeof(info));
info.type = SNDRV_FIREWIRE_TYPE_BEBOB;
info.card = dev->card->index;
*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
strlcpy(info.device_name, dev_name(&dev->device),
sizeof(info.device_name));
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0;
}
static int
hwdep_lock(struct snd_bebob *bebob)
{
int err;
spin_lock_irq(&bebob->lock);
if (bebob->dev_lock_count == 0) {
bebob->dev_lock_count = -1;
err = 0;
} else {
err = -EBUSY;
}
spin_unlock_irq(&bebob->lock);
return err;
}
static int
hwdep_unlock(struct snd_bebob *bebob)
{
int err;
spin_lock_irq(&bebob->lock);
if (bebob->dev_lock_count == -1) {
bebob->dev_lock_count = 0;
err = 0;
} else {
err = -EBADFD;
}
spin_unlock_irq(&bebob->lock);
return err;
}
static int
hwdep_release(struct snd_hwdep *hwdep, struct file *file)
{
struct snd_bebob *bebob = hwdep->private_data;
spin_lock_irq(&bebob->lock);
if (bebob->dev_lock_count == -1)
bebob->dev_lock_count = 0;
spin_unlock_irq(&bebob->lock);
return 0;
}
static int
hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct snd_bebob *bebob = hwdep->private_data;
switch (cmd) {
case SNDRV_FIREWIRE_IOCTL_GET_INFO:
return hwdep_get_info(bebob, (void __user *)arg);
case SNDRV_FIREWIRE_IOCTL_LOCK:
return hwdep_lock(bebob);
case SNDRV_FIREWIRE_IOCTL_UNLOCK:
return hwdep_unlock(bebob);
default:
return -ENOIOCTLCMD;
}
}
#ifdef CONFIG_COMPAT
static int
hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
unsigned int cmd, unsigned long arg)
{
return hwdep_ioctl(hwdep, file, cmd,
(unsigned long)compat_ptr(arg));
}
#else
#define hwdep_compat_ioctl NULL
#endif
static const struct snd_hwdep_ops hwdep_ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)
{
struct snd_hwdep *hwdep;
int err;
err = snd_hwdep_new(bebob->card, "BeBoB", 0, &hwdep);
if (err < 0)
goto end;
strcpy(hwdep->name, "BeBoB");
hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB;
hwdep->ops = hwdep_ops;
hwdep->private_data = bebob;
hwdep->exclusive = true;
end:
return err;
}
This diff is collapsed.
/*
* bebob_midi.c - a part of driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include "bebob.h"
static int midi_capture_open(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;
int err;
err = snd_bebob_stream_lock_try(bebob);
if (err < 0)
goto end;
atomic_inc(&bebob->capture_substreams);
err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0)
snd_bebob_stream_lock_release(bebob);
end:
return err;
}
static int midi_playback_open(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;
int err;
err = snd_bebob_stream_lock_try(bebob);
if (err < 0)
goto end;
atomic_inc(&bebob->playback_substreams);
err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0)
snd_bebob_stream_lock_release(bebob);
end:
return err;
}
static int midi_capture_close(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;
atomic_dec(&bebob->capture_substreams);
snd_bebob_stream_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob);
return 0;
}
static int midi_playback_close(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;
atomic_dec(&bebob->playback_substreams);
snd_bebob_stream_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob);
return 0;
}
static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
{
struct snd_bebob *bebob = substrm->rmidi->private_data;
unsigned long flags;
spin_lock_irqsave(&bebob->lock, flags);
if (up)
amdtp_stream_midi_trigger(&bebob->tx_stream,
substrm->number, substrm);
else
amdtp_stream_midi_trigger(&bebob->tx_stream,
substrm->number, NULL);
spin_unlock_irqrestore(&bebob->lock, flags);
}
static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
{
struct snd_bebob *bebob = substrm->rmidi->private_data;
unsigned long flags;
spin_lock_irqsave(&bebob->lock, flags);
if (up)
amdtp_stream_midi_trigger(&bebob->rx_stream,
substrm->number, substrm);
else
amdtp_stream_midi_trigger(&bebob->rx_stream,
substrm->number, NULL);
spin_unlock_irqrestore(&bebob->lock, flags);
}
static struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
static void set_midi_substream_names(struct snd_bebob *bebob,
struct snd_rawmidi_str *str)
{
struct snd_rawmidi_substream *subs;
list_for_each_entry(subs, &str->substreams, list) {
snprintf(subs->name, sizeof(subs->name),
"%s MIDI %d",
bebob->card->shortname, subs->number + 1);
}
}
int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
{
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;
int err;
/* create midi ports */
err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0,
bebob->midi_output_ports, bebob->midi_input_ports,
&rmidi);
if (err < 0)
return err;
snprintf(rmidi->name, sizeof(rmidi->name),
"%s MIDI", bebob->card->shortname);
rmidi->private_data = bebob;
if (bebob->midi_input_ports > 0) {
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&midi_capture_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
set_midi_substream_names(bebob, str);
}
if (bebob->midi_output_ports > 0) {
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_playback_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
set_midi_substream_names(bebob, str);
}
if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0))
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* bebob_terratec.c - a part of driver for BeBoB based devices
*
* Copyright (c) 2013-2014 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include "./bebob.h"
static char *const phase88_rack_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "Digital In", "Word Clock"
};
static int
phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{
unsigned int enable_ext, enable_word;
int err;
err = avc_audio_get_selector(bebob->unit, 0, 0, &enable_ext);
if (err < 0)
goto end;
err = avc_audio_get_selector(bebob->unit, 0, 0, &enable_word);
if (err < 0)
goto end;
*id = (enable_ext & 0x01) | ((enable_word & 0x01) << 1);
end:
return err;
}
static char *const phase24_series_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "Digital In"
};
static int
phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{
return avc_audio_get_selector(bebob->unit, 0, 4, id);
}
static 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,
.get = &phase88_rack_clk_src_get,
};
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,
.get = &phase24_series_clk_src_get,
};
struct snd_bebob_spec phase24_series_spec = {
.clock = &phase24_series_clk,
.rate = &phase_series_rate_spec,
.meter = NULL
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
snd-fireworks-objs := fireworks_transaction.o fireworks_command.o \
fireworks_stream.o fireworks_proc.o fireworks_midi.o \
fireworks_pcm.o fireworks_hwdep.o fireworks.o
obj-m += snd-fireworks.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment