Commit 25875336 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'for-next' into for-linus

parents 315fba80 2aff4c9c
ADI AXI-I2S controller
Required properties:
- compatible : Must be "adi,axi-i2s-1.00.a"
- reg : Must contain I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
The controller expects two clocks, the clock used for the AXI interface and
the clock used as the sampling rate reference clock sample.
- clock-names : "axi" for the clock to the AXI interface, "ref" for the sample
rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channels that are used by
the core. The core expects two dma channels, one for transmit and one for
receive.
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
i2s: i2s@0x77600000 {
compatible = "adi,axi-i2s-1.00.a";
reg = <0x77600000 0x1000>;
clocks = <&clk 15>, <&audio_clock>;
clock-names = "axi", "ref";
dmas = <&ps7_dma 0>, <&ps7_dma 1>;
dma-names = "tx", "rx";
};
ADI AXI-SPDIF controller
Required properties:
- compatible : Must be "adi,axi-spdif-1.00.a"
- reg : Must contain SPDIF core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
The controller expects two clocks, the clock used for the AXI interface and
the clock used as the sampling rate reference clock sample.
- clock-names: "axi" for the clock to the AXI interface, "ref" for the sample
rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects one dma channel for transmit.
- dma-names : Must be "tx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
spdif: spdif@0x77400000 {
compatible = "adi,axi-spdif-tx-1.00.a";
reg = <0x77600000 0x1000>;
clocks = <&clk 15>, <&audio_clock>;
clock-names = "axi", "ref";
dmas = <&ps7_dma 0>;
dma-names = "tx";
};
* Broadcom BCM2835 SoC I2S/PCM module
Required properties:
- compatible: "brcm,bcm2835-i2s"
- reg: A list of base address and size entries:
* The first entry should cover the PCM registers
* The second entry should cover the PCM clock registers
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
- dma-names: Identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
One of the DMA channels will be responsible for transmission (should be
named "tx") and one for reception (should be named "rx").
Example:
bcm2835_i2s: i2s@7e203000 {
compatible = "brcm,bcm2835-i2s";
reg = <0x7e203000 0x20>,
<0x7e101098 0x02>;
dmas = <&dma 2>,
<&dma 3>;
dma-names = "tx", "rx";
};
CS42L52 audio CODEC
Required properties:
- compatible : "cirrus,cs42l52"
- reg : the I2C address of the device for I2C
Optional properties:
- cirrus,reset-gpio : 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 = (64xFs)/(N+2)
N = chgfreq_val
Fs = Sample Rate (variable)
- cirrus,mica-differential-cfg : boolean, If present, then the MICA input is configured
as a differential input. If not present then the MICA input is configured as
Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
- cirrus,micb-differential-cfg : boolean, If present, then the MICB input is configured
as a differential input. If not present then the MICB input is configured as
Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
- 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
Example:
codec: codec@4a {
compatible = "cirrus,cs42l52";
reg = <0x4a>;
reset-gpio = <&gpio 10 0>;
cirrus,chgfreq-divisor = <0x05>;
cirrus.mica-differential-cfg;
cirrus,micbias-lvl = <5>;
};
......@@ -4,7 +4,8 @@ Required properties:
- compatible :
"ti,dm646x-mcasp-audio" : for DM646x platforms
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx)
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
"ti,dra7-mcasp-audio" : for DRA7xx platforms
- reg : Should contain reg specifiers for the entries in the reg-names property.
- reg-names : Should contain:
......@@ -36,7 +37,8 @@ Optional properties:
- pinctrl-0: Should specify pin control group used for this controller.
- pinctrl-names: Should contain only one value - "default", for more details
please refer to pinctrl-bindings.txt
- fck_parent : Should contain a valid clock name which will be used as parent
for the McASP fck
Example:
......
Freescale Enhanced Serial Audio Interface (ESAI) Controller
The Enhanced Serial Audio Interface (ESAI) provides a full-duplex serial port
for serial communication with a variety of serial devices, including industry
standard codecs, Sony/Phillips Digital Interface (S/PDIF) transceivers, and
other DSPs. It has up to six transmitters and four receivers.
Required properties:
- compatible : Compatible list, must contain "fsl,imx35-esai".
- reg : Offset and length of the register set for the device.
- interrupts : Contains the spdif interrupt.
- 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".
- clocks: Contains an entry for each entry in clock-names.
- clock-names : Includes the following entries:
"core" The core clock used to access registers
"extal" The esai baud clock for esai controller used to derive
HCK, SCK and FS.
"fsys" The system clock derived from ahb clock used to derive
HCK, SCK and FS.
- fsl,fifo-depth: The number of elements in the transmit and receive FIFOs.
This number is the maximum allowed value for TFCR[TFWM] or RFCR[RFWM].
- fsl,esai-synchronous: This is a boolean property. If present, indicating
that ESAI would work in the synchronous mode, which means all the settings
for Receiving would be duplicated from Transmition related registers.
Example:
esai: esai@02024000 {
compatible = "fsl,imx35-esai";
reg = <0x02024000 0x4000>;
interrupts = <0 51 0x04>;
clocks = <&clks 208>, <&clks 118>, <&clks 208>;
clock-names = "core", "extal", "fsys";
dmas = <&sdma 23 21 0>, <&sdma 24 21 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <128>;
fsl,esai-synchronous;
status = "disabled";
};
......@@ -4,7 +4,12 @@ The SSI is a serial device that communicates with audio codecs. It can
be programmed in AC97, I2S, left-justified, or right-justified modes.
Required properties:
- compatible: Compatible list, contains "fsl,ssi".
- compatible: Compatible list, should contain one of the following
compatibles:
fsl,mpc8610-ssi
fsl,imx51-ssi
fsl,imx35-ssi
fsl,imx21-ssi
- cell-index: The SSI, <0> = SSI1, <1> = SSI2, and so on.
- reg: Offset and length of the register set for the device.
- interrupts: <a b> where a is the interrupt number and b is a
......
Freescale Synchronous Audio Interface (SAI).
The SAI is based on I2S module that used communicating with audio codecs,
which provides a synchronous audio interface that supports fullduplex
serial interfaces with frame synchronization such as I2S, AC97, TDM, and
codec/DSP interfaces.
Required properties:
- compatible: Compatible list, contains "fsl,vf610-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.
- 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".
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
See ../pinctrl/pinctrl-bindings.txt for details of the property values.
- big-endian-regs: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
device registers.
- big-endian-data: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
fifo data.
Example:
sai2: sai@40031000 {
compatible = "fsl,vf610-sai";
reg = <0x40031000 0x1000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_SAI2>;
clock-names = "sai";
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
big-endian-regs;
big-endian-data;
};
Device-Tree bindings for dummy HDMI codec
Required properties:
- compatible: should be "linux,hdmi-audio".
CODEC output pins:
* TX
CODEC input pins:
* RX
Example node:
hdmi_audio: hdmi_audio@0 {
compatible = "linux,hdmi-audio";
status = "okay";
};
MAX98090 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "maxim,max98090".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
Pins on the device (for linking into audio routes):
* MIC1
* MIC2
* DMICL
* DMICR
* IN1
* IN2
* IN3
* IN4
* IN5
* IN6
* IN12
* IN34
* IN56
* HPL
* HPR
* SPKL
* SPKR
* RCVL
* RCVR
* MICBIAS
Example:
audio-codec@10 {
compatible = "maxim,max98090";
reg = <0x10>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
};
NVIDIA Tegra audio complex, with MAX98090 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-max98090"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-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. Valid names for sources and
sinks are the MAX98090's pins (as documented in its binding), and the jacks
on the board:
* Headphones
* Speakers
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
Example:
sound {
compatible = "nvidia,tegra-audio-max98090-venice2",
"nvidia,tegra-audio-max98090";
nvidia,model = "NVIDIA Tegra Venice2";
nvidia,audio-routing =
"Headphones", "HPR",
"Headphones", "HPL",
"Speakers", "SPKR",
"Speakers", "SPKL",
"Mic Jack", "MICBIAS",
"IN34", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&acodec>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
Simple-Card:
Simple-Card specifies audio DAI connection of SoC <-> codec.
Required properties:
- compatible : "simple-audio-card"
Optional properties:
- 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,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.
Required subnodes:
- simple-audio-card,cpu : CPU sub-node
- simple-audio-card,codec : CODEC sub-node
Required CPU/CODEC subnodes properties:
- sound-dai : phandle and port of CPU/CODEC
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
- 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)
Example:
sound {
compatible = "simple-audio-card";
simple-audio-card,format = "left_j";
simple-audio-routing =
"MIC_IN", "Mic Jack",
"Headphone Jack", "HP_OUT",
"Ext Spk", "LINE_OUT";
simple-audio-card,cpu {
sound-dai = <&sh_fsi2 0>;
};
simple-audio-card,codec {
sound-dai = <&ak4648>;
bitclock-master;
frame-master;
clocks = <&osc>;
};
};
&i2c0 {
ak4648: ak4648@12 {
#sound-dai-cells = <0>;
compatible = "asahi-kasei,ak4648";
reg = <0x12>;
};
};
sh_fsi2: sh_fsi2@ec230000 {
#sound-dai-cells = <1>;
compatible = "renesas,sh_fsi2";
reg = <0xec230000 0x400>;
interrupt-parent = <&gic>;
interrupts = <0 146 0x4>;
};
......@@ -6,6 +6,7 @@ Required properties:
- compatible - "string" - One of:
"ti,tlv320aic3x" - Generic TLV320AIC3x device
"ti,tlv320aic32x4" - TLV320AIC32x4
"ti,tlv320aic33" - TLV320AIC33
"ti,tlv320aic3007" - TLV320AIC3007
"ti,tlv320aic3106" - TLV320AIC3106
......
......@@ -49,18 +49,23 @@ features :-
* Machine specific controls: Allow machines to add controls to the sound card
(e.g. volume control for speaker amplifier).
To achieve all this, ASoC basically splits an embedded audio system into 3
components :-
To achieve all this, ASoC basically splits an embedded audio system into
multiple re-usable component drivers :-
* Codec driver: The codec driver is platform independent and contains audio
controls, audio interface capabilities, codec DAPM definition and codec IO
functions.
* Codec class drivers: The codec class driver is platform independent and
contains audio controls, audio interface capabilities, codec DAPM
definition and codec IO functions. This class extends to BT, FM and MODEM
ICs if required. Codec class drivers should be generic code that can run
on any architecture and machine.
* Platform driver: The platform driver contains the audio DMA engine and audio
interface drivers (e.g. I2S, AC97, PCM) for that platform.
* Platform class drivers: The platform class driver includes the audio DMA
engine driver, digital audio interface (DAI) drivers (e.g. I2S, AC97, PCM)
and any audio DSP drivers for that platform.
* Machine driver: The machine driver handles any machine specific controls and
audio events (e.g. turning on an amp at start of playback).
* Machine class driver: The machine driver class acts as the glue that
decribes and binds the other component drivers together to form an ALSA
"sound card device". It handles any machine specific controls and
machine level audio events (e.g. turning on an amp at start of playback).
Documentation
......@@ -84,3 +89,7 @@ machine.txt: Machine driver internals.
pop_clicks.txt: How to minimise audio artifacts.
clocking.txt: ASoC clocking for best power performance.
jack.txt: ASoC jack detection.
DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.
......@@ -723,6 +723,7 @@ config ARCH_S3C64XX
bool "Samsung S3C64XX"
select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select ARM_AMBA
select ARM_VIC
select CLKDEV_LOOKUP
select CLKSRC_SAMSUNG_PWM
......
......@@ -17,9 +17,10 @@ config CPU_S3C6410
help
Enable S3C6410 CPU support
config S3C64XX_DMA
bool "S3C64XX DMA"
select S3C_DMA
config S3C64XX_PL080
bool "S3C64XX DMA using generic PL08x driver"
select AMBA_PL08X
select SAMSUNG_DMADEV
config S3C64XX_SETUP_SDHCI
bool
......
......@@ -26,7 +26,7 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle.o
# DMA support
obj-$(CONFIG_S3C64XX_DMA) += dma.o
obj-$(CONFIG_S3C64XX_PL080) += pl080.o
# Device support
......
......@@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
static inline int s3c64xx_pm_late_initcall(void) { return 0; }
#endif
#ifdef CONFIG_S3C64XX_PL080
extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
#endif
#endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */
This diff is collapsed.
......@@ -11,51 +11,48 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H __FILE__
#define S3C_DMA_CHANNELS (16)
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
/* DMA0/SDMA0 */
#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
/* DMA1/SDMA1 */
#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
/* see mach-s3c2410/dma.h for notes on dma channel numbers */
/* Note, for the S3C64XX architecture we keep the DMACH_
* defines in the order they are allocated to [S]DMA0/[S]DMA1
* so that is easy to do DHACH_ -> DMA controller conversion
*/
enum dma_ch {
/* DMA0/SDMA0 */
DMACH_UART0 = 0,
DMACH_UART0_SRC2,
DMACH_UART1,
DMACH_UART1_SRC2,
DMACH_UART2,
DMACH_UART2_SRC2,
DMACH_UART3,
DMACH_UART3_SRC2,
DMACH_PCM0_TX,
DMACH_PCM0_RX,
DMACH_I2S0_OUT,
DMACH_I2S0_IN,
DMACH_SPI0_TX,
DMACH_SPI0_RX,
DMACH_HSI_I2SV40_TX,
DMACH_HSI_I2SV40_RX,
DMACH_MAX = 32
};
/* DMA1/SDMA1 */
DMACH_PCM1_TX = 16,
DMACH_PCM1_RX,
DMACH_I2S1_OUT,
DMACH_I2S1_IN,
DMACH_SPI1_TX,
DMACH_SPI1_RX,
DMACH_AC97_PCMOUT,
DMACH_AC97_PCMIN,
DMACH_AC97_MICIN,
DMACH_PWM,
DMACH_IRDA,
DMACH_EXTERNAL,
DMACH_RES1,
DMACH_RES2,
DMACH_SECURITY_RX, /* SDMA1 only */
DMACH_SECURITY_TX, /* SDMA1 only */
DMACH_MAX /* the end */
struct s3c2410_dma_client {
char *name;
};
static inline bool samsung_dma_has_circular(void)
......@@ -65,67 +62,10 @@ static inline bool samsung_dma_has_circular(void)
static inline bool samsung_dma_is_dmadev(void)
{
return false;
return true;
}
#define S3C2410_DMAF_CIRCULAR (1 << 0)
#include <plat/dma.h>
#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
struct s3c64xx_dma_buff;
/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
* @next: Pointer to next buffer in queue or ring.
* @pw: Client provided identifier
* @lli: Pointer to hardware descriptor this buffer is associated with.
* @lli_dma: Hardare address of the descriptor.
*/
struct s3c64xx_dma_buff {
struct s3c64xx_dma_buff *next;
void *pw;
struct pl080s_lli *lli;
dma_addr_t lli_dma;
};
struct s3c64xx_dmac;
struct s3c2410_dma_chan {
unsigned char number; /* number of this dma channel */
unsigned char in_use; /* channel allocated */
unsigned char bit; /* bit for enable/disable/etc */
unsigned char hw_width;
unsigned char peripheral;
unsigned int flags;
enum dma_data_direction source;
dma_addr_t dev_addr;
struct s3c2410_dma_client *client;
struct s3c64xx_dmac *dmac; /* pointer to controller */
void __iomem *regs;
/* cdriver callbacks */
s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
s3c2410_dma_opfn_t op_fn; /* channel op callback */
/* buffer list and information */
struct s3c64xx_dma_buff *curr; /* current dma buffer */
struct s3c64xx_dma_buff *next; /* next buffer to load */
struct s3c64xx_dma_buff *end; /* end of queue */
/* note, when channel is running in circular mode, curr is the
* first buffer enqueued, end is the last and curr is where the
* last buffer-done event is set-at. The buffers are not freed
* and the last buffer hardware descriptor points back to the
* first.
*/
};
#include <plat/dma-core.h>
#include <linux/amba/pl08x.h>
#include <plat/dma-ops.h>
#endif /* __ASM_ARCH_IRQ_H */
/*
* Samsung's S3C64XX generic DMA support using amba-pl08x driver.
*
* Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.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.
*/
#include <linux/kernel.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl080.h>
#include <linux/amba/pl08x.h>
#include <linux/of.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include "regs-sys.h"
static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
{
return cd->min_signal;
}
static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
{
}
/*
* DMA0
*/
static struct pl08x_channel_data s3c64xx_dma0_info[] = {
{
.bus_id = "uart0_tx",
.min_signal = 0,
.max_signal = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart0_rx",
.min_signal = 1,
.max_signal = 1,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_tx",
.min_signal = 2,
.max_signal = 2,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_rx",
.min_signal = 3,
.max_signal = 3,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_tx",
.min_signal = 4,
.max_signal = 4,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_rx",
.min_signal = 5,
.max_signal = 5,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart3_tx",
.min_signal = 6,
.max_signal = 6,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart3_rx",
.min_signal = 7,
.max_signal = 7,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm0_tx",
.min_signal = 8,
.max_signal = 8,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm0_rx",
.min_signal = 9,
.max_signal = 9,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s0_tx",
.min_signal = 10,
.max_signal = 10,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s0_rx",
.min_signal = 11,
.max_signal = 11,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi0_tx",
.min_signal = 12,
.max_signal = 12,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi0_rx",
.min_signal = 13,
.max_signal = 13,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s2_tx",
.min_signal = 14,
.max_signal = 14,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s2_rx",
.min_signal = 15,
.max_signal = 15,
.periph_buses = PL08X_AHB2,
}
};
struct pl08x_platform_data s3c64xx_dma0_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl_memcpy =
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal,
.put_xfer_signal = pl08x_put_xfer_signal,
.slave_channels = s3c64xx_dma0_info,
.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
};
static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
/*
* DMA1
*/
static struct pl08x_channel_data s3c64xx_dma1_info[] = {
{
.bus_id = "pcm1_tx",
.min_signal = 0,
.max_signal = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm1_rx",
.min_signal = 1,
.max_signal = 1,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s1_tx",
.min_signal = 2,
.max_signal = 2,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s1_rx",
.min_signal = 3,
.max_signal = 3,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi1_tx",
.min_signal = 4,
.max_signal = 4,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi1_rx",
.min_signal = 5,
.max_signal = 5,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_out",
.min_signal = 6,
.max_signal = 6,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_in",
.min_signal = 7,
.max_signal = 7,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_mic",
.min_signal = 8,
.max_signal = 8,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pwm",
.min_signal = 9,
.max_signal = 9,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "irda",
.min_signal = 10,
.max_signal = 10,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "external",
.min_signal = 11,
.max_signal = 11,
.periph_buses = PL08X_AHB2,
},
};
struct pl08x_platform_data s3c64xx_dma1_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl_memcpy =
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal,
.put_xfer_signal = pl08x_put_xfer_signal,
.slave_channels = s3c64xx_dma1_info,
.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
};
static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
static int __init s3c64xx_pl080_init(void)
{
/* Set all DMA configuration to be DMA, not SDMA */
writel(0xffffff, S3C64XX_SDMA_SEL);
if (of_have_populated_dt())
return 0;
amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
return 0;
}
arch_initcall(s3c64xx_pl080_init);
......@@ -31,7 +31,7 @@ static struct stedma40_chan_cfg msp0_dma_tx = {
};
struct msp_i2s_platform_data msp0_platform_data = {
.id = MSP_I2S_0,
.id = 0,
.msp_i2s_dma_rx = &msp0_dma_rx,
.msp_i2s_dma_tx = &msp0_dma_tx,
};
......@@ -49,7 +49,7 @@ static struct stedma40_chan_cfg msp1_dma_tx = {
};
struct msp_i2s_platform_data msp1_platform_data = {
.id = MSP_I2S_1,
.id = 1,
.msp_i2s_dma_rx = NULL,
.msp_i2s_dma_tx = &msp1_dma_tx,
};
......@@ -69,13 +69,13 @@ static struct stedma40_chan_cfg msp2_dma_tx = {
};
struct msp_i2s_platform_data msp2_platform_data = {
.id = MSP_I2S_2,
.id = 2,
.msp_i2s_dma_rx = &msp2_dma_rx,
.msp_i2s_dma_tx = &msp2_dma_tx,
};
struct msp_i2s_platform_data msp3_platform_data = {
.id = MSP_I2S_3,
.id = 3,
.msp_i2s_dma_rx = &msp1_dma_rx,
.msp_i2s_dma_tx = NULL,
};
......@@ -1468,6 +1468,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#elif defined(CONFIG_S3C24XX_DMAC)
pd.filter = s3c24xx_dma_filter;
#endif
......@@ -1509,8 +1511,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
#ifdef CONFIG_PL330_DMA
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
......@@ -1550,8 +1554,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
#ifdef CONFIG_PL330_DMA
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
......
......@@ -18,6 +18,12 @@
#include <mach/dma.h>
#if defined(CONFIG_PL330_DMA)
#define dma_filter pl330_filter
#elif defined(CONFIG_S3C64XX_PL080)
#define dma_filter pl08x_filter_id
#endif
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
struct samsung_dma_req *param,
struct device *dev, char *ch_name)
......@@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
if (dev->of_node)
return (unsigned)dma_request_slave_channel(dev, ch_name);
else
return (unsigned)dma_request_channel(mask, pl330_filter,
return (unsigned)dma_request_channel(mask, dma_filter,
(void *)dma_ch);
}
......
......@@ -331,8 +331,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(HCLK_DMA1, NULL, "dma1"),
ALIAS(HCLK_DMA0, NULL, "dma0"),
ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
......
......@@ -540,6 +540,8 @@ EXPORT_SYMBOL_GPL(dma_get_slave_channel);
* @mask: capabilities that the channel must satisfy
* @fn: optional callback to disposition available channels
* @fn_param: opaque parameter to pass to dma_filter_fn
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param)
......@@ -591,18 +593,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name)
{
struct dma_chan *chan;
/* If device-tree is present get slave info from here */
if (dev->of_node)
return of_dma_request_slave_channel(dev->of_node, name);
/* If device was enumerated by ACPI get slave info from here */
if (ACPI_HANDLE(dev))
return acpi_dma_request_slave_chan_by_name(dev, name);
if (ACPI_HANDLE(dev)) {
chan = acpi_dma_request_slave_chan_by_name(dev, name);
if (chan)
return chan;
}
return NULL;
return ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
if (IS_ERR(ch))
return NULL;
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
......
......@@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
* @np: device node to get DMA request from
* @name: name of desired channel
*
* Returns pointer to appropriate dma channel on success or NULL on error.
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name)
......@@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
struct of_dma *ofdma;
struct dma_chan *chan;
int count, i;
int ret_no_channel = -ENODEV;
if (!np || !name) {
pr_err("%s: not enough information provided\n", __func__);
return NULL;
return ERR_PTR(-ENODEV);
}
count = of_property_count_strings(np, "dma-names");
if (count < 0) {
pr_err("%s: dma-names property of node '%s' missing or empty\n",
__func__, np->full_name);
return NULL;
return ERR_PTR(-ENODEV);
}
for (i = 0; i < count; i++) {
......@@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
mutex_lock(&of_dma_lock);
ofdma = of_dma_find_controller(&dma_spec);
if (ofdma)
if (ofdma) {
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
else
} else {
ret_no_channel = -EPROBE_DEFER;
chan = NULL;
}
mutex_unlock(&of_dma_lock);
......@@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return chan;
}
return NULL;
return ERR_PTR(ret_no_channel);
}
/**
......
......@@ -2884,6 +2884,7 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
caps->cmd_pause = false;
caps->cmd_terminate = true;
caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
return 0;
}
......
......@@ -47,6 +47,9 @@
#include <linux/i2c.h>
#include <linux/i2c/twl.h>
/* Register descriptions for audio */
#include <linux/mfd/twl4030-audio.h>
#include "twl-core.h"
/*
......@@ -200,6 +203,105 @@ static struct twl_mapping twl4030_map[] = {
{ 2, TWL5031_BASEADD_INTERRUPTS },
};
static struct reg_default twl4030_49_defaults[] = {
/* Audio Registers */
{ 0x01, 0x00}, /* CODEC_MODE */
{ 0x02, 0x00}, /* OPTION */
/* 0x03 Unused */
{ 0x04, 0x00}, /* MICBIAS_CTL */
{ 0x05, 0x00}, /* ANAMICL */
{ 0x06, 0x00}, /* ANAMICR */
{ 0x07, 0x00}, /* AVADC_CTL */
{ 0x08, 0x00}, /* ADCMICSEL */
{ 0x09, 0x00}, /* DIGMIXING */
{ 0x0a, 0x0f}, /* ATXL1PGA */
{ 0x0b, 0x0f}, /* ATXR1PGA */
{ 0x0c, 0x0f}, /* AVTXL2PGA */
{ 0x0d, 0x0f}, /* AVTXR2PGA */
{ 0x0e, 0x00}, /* AUDIO_IF */
{ 0x0f, 0x00}, /* VOICE_IF */
{ 0x10, 0x3f}, /* ARXR1PGA */
{ 0x11, 0x3f}, /* ARXL1PGA */
{ 0x12, 0x3f}, /* ARXR2PGA */
{ 0x13, 0x3f}, /* ARXL2PGA */
{ 0x14, 0x25}, /* VRXPGA */
{ 0x15, 0x00}, /* VSTPGA */
{ 0x16, 0x00}, /* VRX2ARXPGA */
{ 0x17, 0x00}, /* AVDAC_CTL */
{ 0x18, 0x00}, /* ARX2VTXPGA */
{ 0x19, 0x32}, /* ARXL1_APGA_CTL*/
{ 0x1a, 0x32}, /* ARXR1_APGA_CTL*/
{ 0x1b, 0x32}, /* ARXL2_APGA_CTL*/
{ 0x1c, 0x32}, /* ARXR2_APGA_CTL*/
{ 0x1d, 0x00}, /* ATX2ARXPGA */
{ 0x1e, 0x00}, /* BT_IF */
{ 0x1f, 0x55}, /* BTPGA */
{ 0x20, 0x00}, /* BTSTPGA */
{ 0x21, 0x00}, /* EAR_CTL */
{ 0x22, 0x00}, /* HS_SEL */
{ 0x23, 0x00}, /* HS_GAIN_SET */
{ 0x24, 0x00}, /* HS_POPN_SET */
{ 0x25, 0x00}, /* PREDL_CTL */
{ 0x26, 0x00}, /* PREDR_CTL */
{ 0x27, 0x00}, /* PRECKL_CTL */
{ 0x28, 0x00}, /* PRECKR_CTL */
{ 0x29, 0x00}, /* HFL_CTL */
{ 0x2a, 0x00}, /* HFR_CTL */
{ 0x2b, 0x05}, /* ALC_CTL */
{ 0x2c, 0x00}, /* ALC_SET1 */
{ 0x2d, 0x00}, /* ALC_SET2 */
{ 0x2e, 0x00}, /* BOOST_CTL */
{ 0x2f, 0x00}, /* SOFTVOL_CTL */
{ 0x30, 0x13}, /* DTMF_FREQSEL */
{ 0x31, 0x00}, /* DTMF_TONEXT1H */
{ 0x32, 0x00}, /* DTMF_TONEXT1L */
{ 0x33, 0x00}, /* DTMF_TONEXT2H */
{ 0x34, 0x00}, /* DTMF_TONEXT2L */
{ 0x35, 0x79}, /* DTMF_TONOFF */
{ 0x36, 0x11}, /* DTMF_WANONOFF */
{ 0x37, 0x00}, /* I2S_RX_SCRAMBLE_H */
{ 0x38, 0x00}, /* I2S_RX_SCRAMBLE_M */
{ 0x39, 0x00}, /* I2S_RX_SCRAMBLE_L */
{ 0x3a, 0x06}, /* APLL_CTL */
{ 0x3b, 0x00}, /* DTMF_CTL */
{ 0x3c, 0x44}, /* DTMF_PGA_CTL2 (0x3C) */
{ 0x3d, 0x69}, /* DTMF_PGA_CTL1 (0x3D) */
{ 0x3e, 0x00}, /* MISC_SET_1 */
{ 0x3f, 0x00}, /* PCMBTMUX */
/* 0x40 - 0x42 Unused */
{ 0x43, 0x00}, /* RX_PATH_SEL */
{ 0x44, 0x32}, /* VDL_APGA_CTL */
{ 0x45, 0x00}, /* VIBRA_CTL */
{ 0x46, 0x00}, /* VIBRA_SET */
{ 0x47, 0x00}, /* VIBRA_PWM_SET */
{ 0x48, 0x00}, /* ANAMIC_GAIN */
{ 0x49, 0x00}, /* MISC_SET_2 */
/* End of Audio Registers */
};
static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case 0:
case 3:
case 40:
case 41:
case 42:
return false;
default:
return true;
}
}
static const struct regmap_range twl4030_49_volatile_ranges[] = {
regmap_reg_range(TWL4030_BASEADD_TEST, 0xff),
};
static const struct regmap_access_table twl4030_49_volatile_table = {
.yes_ranges = twl4030_49_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(twl4030_49_volatile_ranges),
};
static struct regmap_config twl4030_regmap_config[4] = {
{
/* Address 0x48 */
......@@ -212,6 +314,15 @@ static struct regmap_config twl4030_regmap_config[4] = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
.readable_reg = twl4030_49_nop_reg,
.writeable_reg = twl4030_49_nop_reg,
.volatile_table = &twl4030_49_volatile_table,
.reg_defaults = twl4030_49_defaults,
.num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults),
.cache_type = REGCACHE_RBTREE,
},
{
/* Address 0x4a */
......@@ -302,35 +413,50 @@ unsigned int twl_rev(void)
EXPORT_SYMBOL(twl_rev);
/**
* twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
* twl_get_regmap - Get the regmap associated with the given module
* @mod_no: module number
* @value: an array of num_bytes+1 containing data to write
* @reg: register address (just offset will do)
* @num_bytes: number of bytes to transfer
*
* Returns the result of operation - 0 is success
* Returns the regmap pointer or NULL in case of failure.
*/
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
static struct regmap *twl_get_regmap(u8 mod_no)
{
int ret;
int sid;
struct twl_client *twl;
if (unlikely(!twl_priv || !twl_priv->ready)) {
pr_err("%s: not initialized\n", DRIVER_NAME);
return -EPERM;
return NULL;
}
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
return NULL;
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
ret = regmap_bulk_write(twl->regmap,
twl_priv->twl_map[mod_no].base + reg, value,
num_bytes);
return twl->regmap;
}
/**
* twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
* @mod_no: module number
* @value: an array of num_bytes+1 containing data to write
* @reg: register address (just offset will do)
* @num_bytes: number of bytes to transfer
*
* Returns the result of operation - 0 is success
*/
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
struct regmap *regmap = twl_get_regmap(mod_no);
int ret;
if (!regmap)
return -EPERM;
ret = regmap_bulk_write(regmap, twl_priv->twl_map[mod_no].base + reg,
value, num_bytes);
if (ret)
pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
......@@ -351,25 +477,14 @@ EXPORT_SYMBOL(twl_i2c_write);
*/
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
struct regmap *regmap = twl_get_regmap(mod_no);
int ret;
int sid;
struct twl_client *twl;
if (unlikely(!twl_priv || !twl_priv->ready)) {
pr_err("%s: not initialized\n", DRIVER_NAME);
return -EPERM;
}
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
if (!regmap)
return -EPERM;
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
ret = regmap_bulk_read(twl->regmap,
twl_priv->twl_map[mod_no].base + reg, value,
num_bytes);
ret = regmap_bulk_read(regmap, twl_priv->twl_map[mod_no].base + reg,
value, num_bytes);
if (ret)
pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
......@@ -379,6 +494,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
}
EXPORT_SYMBOL(twl_i2c_read);
/**
* twl_regcache_bypass - Configure the regcache bypass for the regmap associated
* with the module
* @mod_no: module number
* @enable: Regcache bypass state
*
* Returns 0 else failure.
*/
int twl_set_regcache_bypass(u8 mod_no, bool enable)
{
struct regmap *regmap = twl_get_regmap(mod_no);
if (!regmap)
return -EPERM;
regcache_cache_bypass(regmap, enable);
return 0;
}
EXPORT_SYMBOL(twl_set_regcache_bypass);
/*----------------------------------------------------------------------*/
/**
......
......@@ -44,6 +44,54 @@
#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
#define TWL6040_NUM_SUPPLIES (2)
static struct reg_default twl6040_defaults[] = {
{ 0x01, 0x4B }, /* REG_ASICID (ro) */
{ 0x02, 0x00 }, /* REG_ASICREV (ro) */
{ 0x03, 0x00 }, /* REG_INTID */
{ 0x04, 0x00 }, /* REG_INTMR */
{ 0x05, 0x00 }, /* REG_NCPCTRL */
{ 0x06, 0x00 }, /* REG_LDOCTL */
{ 0x07, 0x60 }, /* REG_HPPLLCTL */
{ 0x08, 0x00 }, /* REG_LPPLLCTL */
{ 0x09, 0x4A }, /* REG_LPPLLDIV */
{ 0x0A, 0x00 }, /* REG_AMICBCTL */
{ 0x0B, 0x00 }, /* REG_DMICBCTL */
{ 0x0C, 0x00 }, /* REG_MICLCTL */
{ 0x0D, 0x00 }, /* REG_MICRCTL */
{ 0x0E, 0x00 }, /* REG_MICGAIN */
{ 0x0F, 0x1B }, /* REG_LINEGAIN */
{ 0x10, 0x00 }, /* REG_HSLCTL */
{ 0x11, 0x00 }, /* REG_HSRCTL */
{ 0x12, 0x00 }, /* REG_HSGAIN */
{ 0x13, 0x00 }, /* REG_EARCTL */
{ 0x14, 0x00 }, /* REG_HFLCTL */
{ 0x15, 0x00 }, /* REG_HFLGAIN */
{ 0x16, 0x00 }, /* REG_HFRCTL */
{ 0x17, 0x00 }, /* REG_HFRGAIN */
{ 0x18, 0x00 }, /* REG_VIBCTLL */
{ 0x19, 0x00 }, /* REG_VIBDATL */
{ 0x1A, 0x00 }, /* REG_VIBCTLR */
{ 0x1B, 0x00 }, /* REG_VIBDATR */
{ 0x1C, 0x00 }, /* REG_HKCTL1 */
{ 0x1D, 0x00 }, /* REG_HKCTL2 */
{ 0x1E, 0x00 }, /* REG_GPOCTL */
{ 0x1F, 0x00 }, /* REG_ALB */
{ 0x20, 0x00 }, /* REG_DLB */
/* 0x28, REG_TRIM1 */
/* 0x29, REG_TRIM2 */
/* 0x2A, REG_TRIM3 */
/* 0x2B, REG_HSOTRIM */
/* 0x2C, REG_HFOTRIM */
{ 0x2D, 0x08 }, /* REG_ACCCTL */
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */
};
struct reg_default twl6040_patch[] = {
/* Select I2C bus access to dual access registers */
{ TWL6040_REG_ACCCTL, 0x09 },
};
static bool twl6040_has_vibra(struct device_node *node)
{
#ifdef CONFIG_OF
......@@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on)
if (twl6040->power_count++)
goto out;
/* Allow writes to the chip */
regcache_cache_only(twl6040->regmap, false);
if (gpio_is_valid(twl6040->audpwron)) {
/* use automatic power-up sequence */
ret = twl6040_power_up_automatic(twl6040);
......@@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on)
goto out;
}
}
/* Sync with the HW */
regcache_sync(twl6040->regmap);
/* Default PLL configuration after power up */
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
twl6040->sysclk = 19200000;
......@@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use manual power-down sequence */
twl6040_power_down_manual(twl6040);
}
/* Set regmap to cache only and mark it as dirty */
regcache_cache_only(twl6040->regmap, true);
regcache_mark_dirty(twl6040->regmap);
twl6040->sysclk = 0;
twl6040->mclk = 0;
}
......@@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case TWL6040_REG_VIBCTLL:
case TWL6040_REG_VIBCTLR:
case TWL6040_REG_INTMR:
case TWL6040_REG_ASICID:
case TWL6040_REG_ASICREV:
case TWL6040_REG_INTID:
case TWL6040_REG_LPPLLCTL:
case TWL6040_REG_HPPLLCTL:
case TWL6040_REG_STATUS:
return true;
default:
return false;
}
}
static bool twl6040_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case TWL6040_REG_ASICID:
case TWL6040_REG_ASICREV:
case TWL6040_REG_STATUS:
return false;
default:
return true;
......@@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
static struct regmap_config twl6040_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.reg_defaults = twl6040_defaults,
.num_reg_defaults = ARRAY_SIZE(twl6040_defaults),
.max_register = TWL6040_REG_STATUS, /* 0x2e */
.readable_reg = twl6040_readable_reg,
.volatile_reg = twl6040_volatile_reg,
.writeable_reg = twl6040_writeable_reg,
.cache_type = REGCACHE_RBTREE,
};
......@@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client,
/* dual-access registers controlled by I2C only */
twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
regmap_register_patch(twl6040->regmap, twl6040_patch,
ARRAY_SIZE(twl6040_patch));
/*
* The main functionality of twl6040 to provide audio on OMAP4+ systems.
......@@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client,
cell->name = "twl6040-gpo";
children++;
/* The chip is powered down so mark regmap to cache only and dirty */
regcache_cache_only(twl6040->regmap, true);
regcache_mark_dirty(twl6040->regmap);
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
NULL, 0, NULL);
if (ret)
......
This diff is collapsed.
......@@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
depends on PLAT_SAMSUNG
select S3C64XX_DMA if ARCH_S3C64XX
select S3C64XX_PL080 if ARCH_S3C64XX
help
SPI driver for Samsung S3C64XX and newer SoCs.
......
......@@ -22,6 +22,7 @@
#define LINUX_DMAENGINE_H
#include <linux/device.h>
#include <linux/err.h>
#include <linux/uio.h>
#include <linux/bug.h>
#include <linux/scatterlist.h>
......@@ -363,6 +364,32 @@ struct dma_slave_config {
unsigned int slave_id;
};
/**
* enum dma_residue_granularity - Granularity of the reported transfer residue
* @DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. The
* DMA channel is only able to tell whether a descriptor has been completed or
* not, which means residue reporting is not supported by this channel. The
* residue field of the dma_tx_state field will always be 0.
* @DMA_RESIDUE_GRANULARITY_SEGMENT: Residue is updated after each successfully
* completed segment of the transfer (For cyclic transfers this is after each
* period). This is typically implemented by having the hardware generate an
* interrupt after each transferred segment and then the drivers updates the
* outstanding residue by the size of the segment. Another possibility is if
* the hardware supports scatter-gather and the segment descriptor has a field
* which gets set after the segment has been completed. The driver then counts
* the number of segments without the flag set to compute the residue.
* @DMA_RESIDUE_GRANULARITY_BURST: Residue is updated after each transferred
* burst. This is typically only supported if the hardware has a progress
* register of some sort (E.g. a register with the current read/write address
* or a register with the amount of bursts/beats/bytes that have been
* transferred or still need to be transferred).
*/
enum dma_residue_granularity {
DMA_RESIDUE_GRANULARITY_DESCRIPTOR = 0,
DMA_RESIDUE_GRANULARITY_SEGMENT = 1,
DMA_RESIDUE_GRANULARITY_BURST = 2,
};
/* struct dma_slave_caps - expose capabilities of a slave channel only
*
* @src_addr_widths: bit mask of src addr widths the channel supports
......@@ -373,6 +400,7 @@ struct dma_slave_config {
* should be checked by controller as well
* @cmd_pause: true, if pause and thereby resume is supported
* @cmd_terminate: true, if terminate cmd is supported
* @residue_granularity: granularity of the reported transfer residue
*/
struct dma_slave_caps {
u32 src_addr_widths;
......@@ -380,6 +408,7 @@ struct dma_slave_caps {
u32 directions;
bool cmd_pause;
bool cmd_terminate;
enum dma_residue_granularity residue_granularity;
};
static inline const char *dma_chan_name(struct dma_chan *chan)
......@@ -1040,6 +1069,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void);
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param);
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name);
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
void dma_release_channel(struct dma_chan *chan);
#else
......@@ -1063,6 +1094,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
return NULL;
}
static inline struct dma_chan *dma_request_slave_channel_reason(
struct device *dev, const char *name)
{
return ERR_PTR(-ENODEV);
}
static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
......
......@@ -175,6 +175,9 @@ static inline int twl_class_is_ ##class(void) \
TWL_CLASS_IS(4030, TWL4030_CLASS_ID)
TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
/* Set the regcache bypass for the regmap associated with the nodule */
int twl_set_regcache_bypass(u8 mod_no, bool enable);
/*
* Read and write several 8-bit registers at once.
*/
......@@ -667,8 +670,6 @@ struct twl4030_codec_data {
unsigned int digimic_delay; /* in ms */
unsigned int ramp_delay_value;
unsigned int offset_cncl_path;
unsigned int check_defaults:1;
unsigned int reset_registers:1;
unsigned int hs_extmute:1;
int hs_extmute_gpio;
};
......
This diff is collapsed.
/*
* arch/arm/plat-omap/include/mach/mcbsp.h
*
* Defines for Multi-Channel Buffered Serial Port
*
* Copyright (C) 2002 RidgeRun, Inc.
......@@ -21,8 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __ASM_ARCH_OMAP_MCBSP_H
#define __ASM_ARCH_OMAP_MCBSP_H
#ifndef __ASOC_TI_MCBSP_H
#define __ASOC_TI_MCBSP_H
#include <linux/spinlock.h>
#include <linux/clk.h>
......
......@@ -10,16 +10,9 @@
#include <linux/platform_data/dma-ste-dma40.h>
enum msp_i2s_id {
MSP_I2S_0 = 0,
MSP_I2S_1,
MSP_I2S_2,
MSP_I2S_3,
};
/* Platform data structure for a MSP I2S-device */
struct msp_i2s_platform_data {
enum msp_i2s_id id;
int id;
struct stedma40_chan_cfg *msp_i2s_dma_rx;
struct stedma40_chan_cfg *msp_i2s_dma_tx;
};
......
......@@ -92,6 +92,7 @@ enum {
MCASP_VERSION_1 = 0, /* DM646x */
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
MCASP_VERSION_3, /* TI81xx/AM33xx */
MCASP_VERSION_4, /* DRA7xxx */
};
enum mcbsp_clk_input_pin {
......
......@@ -16,17 +16,11 @@ struct cs42l52_platform_data {
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* MICA mode selection 0=Single 1=Differential */
unsigned int mica_cfg;
/* MICA mode selection Differential or Single-ended */
bool mica_diff_cfg;
/* MICB mode selection 0=Single 1=Differential */
unsigned int micb_cfg;
/* MICA Select 0=MIC1A 1=MIC2A */
unsigned int mica_sel;
/* MICB Select 0=MIC2A 1=MIC2B */
unsigned int micb_sel;
/* MICB mode selection Differential or Single-ended */
bool micb_diff_cfg;
/* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq;
......
......@@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @dma_dev: If set, request DMA channel on this device rather than the DAI
* device.
* @chan_names: If set, these custom DMA channel names will be requested at
* registration time.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
......@@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;
struct device *dma_dev;
const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
const struct snd_pcm_hardware *pcm_hardware;
unsigned int prealloc_buffer_size;
......@@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
unsigned int flags);
void snd_dmaengine_pcm_unregister(struct device *dev);
int devm_snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config,
unsigned int flags);
int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);
......
This diff is collapsed.
......@@ -149,13 +149,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
struct snd_dma_buffer *dmab);
void snd_dma_free_pages(struct snd_dma_buffer *dmab);
/* buffer-preservation managements */
#define snd_dma_pci_buf_id(pci) (((unsigned int)(pci)->vendor << 16) | (pci)->device)
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
/* basic memory allocation functions */
void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
void snd_free_pages(void *ptr, size_t size);
......
......@@ -381,7 +381,6 @@ struct snd_pcm_substream {
struct pm_qos_request latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
size_t dma_max;
/* -- hardware operations -- */
const struct snd_pcm_ops *ops;
......@@ -901,6 +900,8 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
unsigned int rates_b);
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)
......
......@@ -354,4 +354,16 @@ params_period_bytes(const struct snd_pcm_hw_params *p)
params_channels(p)) / 8;
}
static inline int
params_width(const struct snd_pcm_hw_params *p)
{
return snd_pcm_format_width(params_format(p));
}
static inline int
params_physical_width(const struct snd_pcm_hw_params *p)
{
return snd_pcm_format_physical_width(params_format(p));
}
#endif /* __SOUND_PCM_PARAMS_H */
......@@ -18,7 +18,7 @@
#define RSND_GEN1_ADG 1
#define RSND_GEN1_SSI 2
#define RSND_GEN2_SRU 0
#define RSND_GEN2_SCU 0
#define RSND_GEN2_ADG 1
#define RSND_GEN2_SSIU 2
#define RSND_GEN2_SSI 3
......@@ -58,6 +58,7 @@ struct rsnd_ssi_platform_info {
struct rsnd_scu_platform_info {
u32 flags;
u32 convert_rate; /* sampling rate convert */
};
/*
......
......@@ -123,6 +123,8 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
int direction);
int snd_soc_dai_is_dummy(struct snd_soc_dai *dai);
struct snd_soc_dai_ops {
/*
* DAI clocking configuration, all optional.
......@@ -220,6 +222,8 @@ struct snd_soc_dai_driver {
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;
......@@ -244,6 +248,8 @@ struct snd_soc_dai {
unsigned int capture_active:1; /* stream is in use */
unsigned int playback_active:1; /* stream is in use */
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;
......@@ -258,6 +264,8 @@ struct snd_soc_dai {
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
unsigned int channels;
unsigned int sample_bits;
/* parent platform/codec */
struct snd_soc_platform *platform;
......
......@@ -412,6 +412,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
struct snd_soc_dai *dai);
int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
struct snd_soc_dapm_widget *source,
......
......@@ -334,9 +334,7 @@ struct snd_soc_jack_pin;
#include <sound/soc-dapm.h>
#include <sound/soc-dpcm.h>
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio;
#endif
typedef int (*hw_write_t)(void *,const char* ,int);
......@@ -446,6 +444,17 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios);
void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios);
#else
static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
return 0;
}
static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
}
#endif
/* codec register bit access */
......@@ -580,7 +589,6 @@ struct snd_soc_jack_zone {
* to provide more complex checks (eg, reading an
* ADC).
*/
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio {
unsigned int gpio;
const char *name;
......@@ -594,7 +602,6 @@ struct snd_soc_jack_gpio {
int (*jack_status_check)(void);
};
#endif
struct snd_soc_jack {
struct mutex mutex;
......@@ -879,6 +886,8 @@ struct snd_soc_dai_link {
/* Symmetry requirements */
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1;
......@@ -886,6 +895,10 @@ struct snd_soc_dai_link {
/* This DAI link can route to other DAI links at runtime (Frontend)*/
unsigned int dynamic:1;
/* DPCM capture and Playback support */
unsigned int dpcm_capture:1;
unsigned int dpcm_playback:1;
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
......
......@@ -29,7 +29,6 @@ struct spear_dma_data {
dma_addr_t addr;
u32 max_burst;
enum dma_slave_buswidth addr_width;
bool (*filter)(struct dma_chan *chan, void *slave);
};
#endif /* SPEAR_DMA_H */
......@@ -57,6 +57,7 @@
#define MAX_NUM_CODECS 32
#define MAX_NUM_CODEC_DESCRIPTORS 32
#define MAX_NUM_BITRATES 32
#define MAX_NUM_SAMPLE_RATES 32
/* Codecs are listed linearly to allow for extensibility */
#define SND_AUDIOCODEC_PCM ((__u32) 0x00000001)
......@@ -324,7 +325,8 @@ union snd_codec_options {
/** struct snd_codec_desc - description of codec capabilities
* @max_ch: Maximum number of audio channels
* @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
* @sample_rates: Sampling rates in Hz, use values like 48000 for this
* @num_sample_rates: Number of valid values in sample_rates array
* @bit_rate: Indexed array containing supported bit rates
* @num_bitrates: Number of valid values in bit_rate array
* @rate_control: value is specified by SND_RATECONTROLMODE defines.
......@@ -346,7 +348,8 @@ union snd_codec_options {
struct snd_codec_desc {
__u32 max_ch;
__u32 sample_rates;
__u32 sample_rates[MAX_NUM_SAMPLE_RATES];
__u32 num_sample_rates;
__u32 bit_rate[MAX_NUM_BITRATES];
__u32 num_bitrates;
__u32 rate_control;
......@@ -364,7 +367,8 @@ struct snd_codec_desc {
* @ch_out: Number of output channels. In case of contradiction between
* this field and the channelMode field, the channelMode field
* overrides.
* @sample_rate: Audio sample rate of input data
* @sample_rate: Audio sample rate of input data in Hz, use values like 48000
* for this.
* @bit_rate: Bitrate of encoded data. May be ignored by decoders
* @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
* Encoders may rely on profiles for quality levels.
......
......@@ -753,7 +753,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
* Power Management.
*/
#ifdef CONFIG_PM
static int aaci_do_suspend(struct snd_card *card, unsigned int state)
static int aaci_do_suspend(struct snd_card *card)
{
struct aaci *aaci = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
......@@ -761,28 +761,28 @@ static int aaci_do_suspend(struct snd_card *card, unsigned int state)
return 0;
}
static int aaci_do_resume(struct snd_card *card, unsigned int state)
static int aaci_do_resume(struct snd_card *card)
{
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
static int aaci_suspend(struct amba_device *dev, pm_message_t state)
static int aaci_suspend(struct device *dev)
{
struct snd_card *card = amba_get_drvdata(dev);
struct snd_card *card = dev_get_drvdata(dev);
return card ? aaci_do_suspend(card) : 0;
}
static int aaci_resume(struct amba_device *dev)
static int aaci_resume(struct device *dev)
{
struct snd_card *card = amba_get_drvdata(dev);
struct snd_card *card = dev_get_drvdata(dev);
return card ? aaci_do_resume(card) : 0;
}
static SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);
#define AACI_DEV_PM_OPS (&aaci_dev_pm_ops)
#else
#define aaci_do_suspend NULL
#define aaci_do_resume NULL
#define aaci_suspend NULL
#define aaci_resume NULL
#define AACI_DEV_PM_OPS NULL
#endif
......@@ -1100,11 +1100,10 @@ MODULE_DEVICE_TABLE(amba, aaci_ids);
static struct amba_driver aaci_driver = {
.drv = {
.name = DRIVER_NAME,
.pm = AACI_DEV_PM_OPS,
},
.probe = aaci_probe,
.remove = aaci_remove,
.suspend = aaci_suspend,
.resume = aaci_resume,
.id_table = aaci_ids,
};
......
......@@ -354,7 +354,7 @@ static int set_sample_rates(struct atmel_abdac *dac)
/* we start at 192 kHz and work our way down to 5112 Hz */
while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
if (new_rate < 0)
if (new_rate <= 0)
break;
/* make sure we are below the ABDAC clock */
if (index < MAX_NUM_RATES &&
......
......@@ -10,14 +10,12 @@ snd-$(CONFIG_SND_VMASTER) += vmaster.o
snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
snd-$(CONFIG_SND_JACK) += jack.o
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o
snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o memalloc.o
snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-pcm-dmaengine-objs := pcm_dmaengine.o
snd-page-alloc-y := memalloc.o
snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
snd-hrtimer-objs := hrtimer.o
......@@ -31,7 +29,7 @@ obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_TIMER) += snd-timer.o
obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o
obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
......
......@@ -501,9 +501,6 @@ static int snd_compress_check_input(struct snd_compr_params *params)
if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
return -EINVAL;
if (!(params->codec.sample_rate & SNDRV_PCM_RATE_8000_192000))
return -EINVAL;
return 0;
}
......
......@@ -21,60 +21,18 @@
*
*/
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
#include <linux/genalloc.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <sound/memalloc.h>
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
/*
*/
static DEFINE_MUTEX(list_mutex);
static LIST_HEAD(mem_list_head);
/* buffer preservation list */
struct snd_mem_list {
struct snd_dma_buffer buffer;
unsigned int id;
struct list_head list;
};
/* id for pre-allocated buffers */
#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
/*
*
* Generic memory allocators
*
*/
static long snd_allocated_pages; /* holding the number of allocated pages */
static inline void inc_snd_pages(int order)
{
snd_allocated_pages += 1 << order;
}
static inline void dec_snd_pages(int order)
{
snd_allocated_pages -= 1 << order;
}
/**
* snd_malloc_pages - allocate pages with the given size
* @size: the size to allocate in bytes
......@@ -87,7 +45,6 @@ static inline void dec_snd_pages(int order)
void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
{
int pg;
void *res;
if (WARN_ON(!size))
return NULL;
......@@ -95,9 +52,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
return NULL;
gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
pg = get_order(size);
if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
inc_snd_pages(pg);
return res;
return (void *) __get_free_pages(gfp_flags, pg);
}
/**
......@@ -114,7 +69,6 @@ void snd_free_pages(void *ptr, size_t size)
if (ptr == NULL)
return;
pg = get_order(size);
dec_snd_pages(pg);
free_pages((unsigned long) ptr, pg);
}
......@@ -129,7 +83,6 @@ void snd_free_pages(void *ptr, size_t size)
static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
{
int pg;
void *res;
gfp_t gfp_flags;
if (WARN_ON(!dma))
......@@ -139,11 +92,7 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
| __GFP_COMP /* compound page lets parts be mapped */
| __GFP_NORETRY /* don't trigger OOM-killer */
| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
if (res != NULL)
inc_snd_pages(pg);
return res;
return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
}
/* free the coherent DMA pages */
......@@ -155,7 +104,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
if (ptr == NULL)
return;
pg = get_order(size);
dec_snd_pages(pg);
dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
}
......@@ -340,256 +288,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
}
}
/**
* snd_dma_get_reserved - get the reserved buffer for the given device
* @dmab: the buffer allocation record to store
* @id: the buffer id
*
* Looks for the reserved-buffer list and re-uses if the same buffer
* is found in the list. When the buffer is found, it's removed from the free list.
*
* Return: The size of buffer if the buffer is found, or zero if not found.
*/
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
if (WARN_ON(!dmab))
return 0;
mutex_lock(&list_mutex);
list_for_each_entry(mem, &mem_list_head, list) {
if (mem->id == id &&
(mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
struct device *dev = dmab->dev.dev;
list_del(&mem->list);
*dmab = mem->buffer;
if (dmab->dev.dev == NULL)
dmab->dev.dev = dev;
kfree(mem);
mutex_unlock(&list_mutex);
return dmab->bytes;
}
}
mutex_unlock(&list_mutex);
return 0;
}
/**
* snd_dma_reserve_buf - reserve the buffer
* @dmab: the buffer to reserve
* @id: the buffer id
*
* Reserves the given buffer as a reserved buffer.
*
* Return: Zero if successful, or a negative code on error.
*/
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
if (WARN_ON(!dmab))
return -EINVAL;
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (! mem)
return -ENOMEM;
mutex_lock(&list_mutex);
mem->buffer = *dmab;
mem->id = id;
list_add_tail(&mem->list, &mem_list_head);
mutex_unlock(&list_mutex);
return 0;
}
/*
* purge all reserved buffers
*/
static void free_all_reserved_pages(void)
{
struct list_head *p;
struct snd_mem_list *mem;
mutex_lock(&list_mutex);
while (! list_empty(&mem_list_head)) {
p = mem_list_head.next;
mem = list_entry(p, struct snd_mem_list, list);
list_del(p);
snd_dma_free_pages(&mem->buffer);
kfree(mem);
}
mutex_unlock(&list_mutex);
}
#ifdef CONFIG_PROC_FS
/*
* proc file interface
*/
#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
static struct proc_dir_entry *snd_mem_proc;
static int snd_mem_proc_read(struct seq_file *seq, void *offset)
{
long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
struct snd_mem_list *mem;
int devno;
static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" };
mutex_lock(&list_mutex);
seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n",
pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
devno = 0;
list_for_each_entry(mem, &mem_list_head, list) {
devno++;
seq_printf(seq, "buffer %d : ID %08x : type %s\n",
devno, mem->id, types[mem->buffer.dev.type]);
seq_printf(seq, " addr = 0x%lx, size = %d bytes\n",
(unsigned long)mem->buffer.addr,
(int)mem->buffer.bytes);
}
mutex_unlock(&list_mutex);
return 0;
}
static int snd_mem_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, snd_mem_proc_read, NULL);
}
/* FIXME: for pci only - other bus? */
#ifdef CONFIG_PCI
#define gettoken(bufp) strsep(bufp, " \t\n")
static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
char buf[128];
char *token, *p;
if (count > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
p = buf;
token = gettoken(&p);
if (! token || *token == '#')
return count;
if (strcmp(token, "add") == 0) {
char *endp;
int vendor, device, size, buffers;
long mask;
int i, alloced;
struct pci_dev *pci;
if ((token = gettoken(&p)) == NULL ||
(vendor = simple_strtol(token, NULL, 0)) <= 0 ||
(token = gettoken(&p)) == NULL ||
(device = simple_strtol(token, NULL, 0)) <= 0 ||
(token = gettoken(&p)) == NULL ||
(mask = simple_strtol(token, NULL, 0)) < 0 ||
(token = gettoken(&p)) == NULL ||
(size = memparse(token, &endp)) < 64*1024 ||
size > 16*1024*1024 /* too big */ ||
(token = gettoken(&p)) == NULL ||
(buffers = simple_strtol(token, NULL, 0)) <= 0 ||
buffers > 4) {
printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
return count;
}
vendor &= 0xffff;
device &= 0xffff;
alloced = 0;
pci = NULL;
while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
if (mask > 0 && mask < 0xffffffff) {
if (pci_set_dma_mask(pci, mask) < 0 ||
pci_set_consistent_dma_mask(pci, mask) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
pci_dev_put(pci);
return count;
}
}
for (i = 0; i < buffers; i++) {
struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
pci_dev_put(pci);
return count;
}
snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
}
alloced++;
}
if (! alloced) {
for (i = 0; i < buffers; i++) {
struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
/* FIXME: We can allocate only in ZONE_DMA
* without a device pointer!
*/
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
break;
}
snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
}
}
} else if (strcmp(token, "erase") == 0)
/* FIXME: need for releasing each buffer chunk? */
free_all_reserved_pages();
else
printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
return count;
}
#endif /* CONFIG_PCI */
static const struct file_operations snd_mem_proc_fops = {
.owner = THIS_MODULE,
.open = snd_mem_proc_open,
.read = seq_read,
#ifdef CONFIG_PCI
.write = snd_mem_proc_write,
#endif
.llseek = seq_lseek,
.release = single_release,
};
#endif /* CONFIG_PROC_FS */
/*
* module entry
*/
static int __init snd_mem_init(void)
{
#ifdef CONFIG_PROC_FS
snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
&snd_mem_proc_fops);
#endif
return 0;
}
static void __exit snd_mem_exit(void)
{
remove_proc_entry(SND_MEM_PROC_FILE, NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
}
module_init(snd_mem_init)
module_exit(snd_mem_exit)
/*
* exports
*/
......@@ -597,8 +295,5 @@ EXPORT_SYMBOL(snd_dma_alloc_pages);
EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
EXPORT_SYMBOL(snd_dma_free_pages);
EXPORT_SYMBOL(snd_dma_get_reserved_buf);
EXPORT_SYMBOL(snd_dma_reserve_buf);
EXPORT_SYMBOL(snd_malloc_pages);
EXPORT_SYMBOL(snd_free_pages);
......@@ -51,17 +51,9 @@ static const size_t snd_minimum_buffer = 16384;
static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
{
struct snd_dma_buffer *dmab = &substream->dma_buffer;
size_t orig_size = size;
int err;
/* already reserved? */
if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
if (dmab->bytes >= size)
return 0; /* yes */
/* no, free the reserved block */
snd_dma_free_pages(dmab);
dmab->bytes = 0;
}
do {
if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
size, dmab)) < 0) {
......@@ -72,6 +64,10 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
size >>= 1;
} while (size >= snd_minimum_buffer);
dmab->bytes = 0; /* tell error */
pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
substream->pcm->card->number, substream->pcm->device,
substream->stream ? 'c' : 'p', substream->number,
substream->pcm->name, orig_size);
return 0;
}
......@@ -82,10 +78,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
{
if (substream->dma_buffer.area == NULL)
return;
if (substream->dma_buf_id)
snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
else
snd_dma_free_pages(&substream->dma_buffer);
snd_dma_free_pages(&substream->dma_buffer);
substream->dma_buffer.area = NULL;
}
......@@ -260,11 +253,6 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
*
* Do pre-allocation for the given DMA buffer type.
*
* When substream->dma_buf_id is set, the function tries to look for
* the reserved buffer, and the buffer is not freed but reserved at
* destruction time. The dma_buf_id must be unique for all systems
* (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
......
......@@ -514,3 +514,42 @@ unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
return 0;
}
EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate);
static unsigned int snd_pcm_rate_mask_sanitize(unsigned int rates)
{
if (rates & SNDRV_PCM_RATE_CONTINUOUS)
return SNDRV_PCM_RATE_CONTINUOUS;
else if (rates & SNDRV_PCM_RATE_KNOT)
return SNDRV_PCM_RATE_KNOT;
return rates;
}
/**
* snd_pcm_rate_mask_intersect - computes the intersection between two rate masks
* @rates_a: The first rate mask
* @rates_b: The second rate mask
*
* This function computes the rates that are supported by both rate masks passed
* to the function. It will take care of the special handling of
* SNDRV_PCM_RATE_CONTINUOUS and SNDRV_PCM_RATE_KNOT.
*
* Return: A rate mask containing the rates that are supported by both rates_a
* and rates_b.
*/
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
unsigned int rates_b)
{
rates_a = snd_pcm_rate_mask_sanitize(rates_a);
rates_b = snd_pcm_rate_mask_sanitize(rates_b);
if (rates_a & SNDRV_PCM_RATE_CONTINUOUS)
return rates_b;
else if (rates_b & SNDRV_PCM_RATE_CONTINUOUS)
return rates_a;
else if (rates_a & SNDRV_PCM_RATE_KNOT)
return rates_b;
else if (rates_b & SNDRV_PCM_RATE_KNOT)
return rates_a;
return rates_a & rates_b;
}
EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
......@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/gfp.h>
#include "sound_config.h"
#include "sleep.h"
#define DMAP_FREE_ON_CLOSE 0
#define DMAP_KEEP_ON_CLOSE 1
......@@ -351,8 +352,7 @@ static void dma_reset_output(int dev)
if (!signal_pending(current) && adev->dmap_out->qlen &&
adev->dmap_out->underrun_count == 0){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
dmabuf_timeout(dmap));
oss_broken_sleep_on(&adev->out_sleeper, dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
......@@ -446,7 +446,7 @@ int DMAbuf_sync(int dev)
long t = dmabuf_timeout(dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
/* FIXME: not safe may miss events */
t = interruptible_sleep_on_timeout(&adev->out_sleeper, t);
t = oss_broken_sleep_on(&adev->out_sleeper, t);
spin_lock_irqsave(&dmap->lock,flags);
if (!t) {
adev->dmap_out->flags &= ~DMA_SYNCING;
......@@ -466,7 +466,7 @@ int DMAbuf_sync(int dev)
while (!signal_pending(current) &&
adev->d->local_qlen(dev)){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
oss_broken_sleep_on(&adev->out_sleeper,
dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
......@@ -587,8 +587,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
timeout = dmabuf_timeout(dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,
timeout);
timeout = oss_broken_sleep_on(&adev->in_sleeper, timeout);
if (!timeout) {
/* FIXME: include device name */
err = -EIO;
......@@ -768,8 +767,7 @@ static int output_sleep(int dev, int dontblock)
timeout_value = dmabuf_timeout(dmap);
else
timeout_value = MAX_SCHEDULE_TIMEOUT;
timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper,
timeout_value);
timeout_value = oss_broken_sleep_on(&adev->out_sleeper, timeout_value);
if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) {
printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
dma_reset_output(dev);
......
......@@ -239,7 +239,6 @@ struct sound_queue {
int busy, syncing, xruns, died;
};
#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
#define WAKE_UP(queue) (wake_up_interruptible(&queue))
extern struct sound_queue dmasound_write_sq;
......
......@@ -619,15 +619,27 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
}
while (uLeft) {
DEFINE_WAIT(wait);
while (write_sq.count >= write_sq.max_active) {
prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE);
sq_play();
if (write_sq.non_blocking)
if (write_sq.non_blocking) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EAGAIN;
SLEEP(write_sq.action_queue);
if (signal_pending(current))
}
if (write_sq.count < write_sq.max_active)
break;
schedule_timeout(HZ);
if (signal_pending(current)) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EINTR;
}
}
finish_wait(&write_sq.action_queue, &wait);
/* Here, we can avoid disabling the interrupt by first
* copying and translating the data, and then updating
* the write_sq variables. Until this is done, the interrupt
......@@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
if (file->f_flags & O_NONBLOCK)
return rc;
rc = -EINTR;
while (sq->busy) {
SLEEP(sq->open_queue);
if (signal_pending(current))
return rc;
}
if (wait_event_interruptible(sq->open_queue, !sq->busy))
return rc;
rc = 0;
#else
/* OSS manual says we will return EBUSY regardless
......@@ -844,7 +853,8 @@ static int sq_fsync(void)
sq_play(); /* there may be an incomplete frame waiting */
while (write_sq.active) {
SLEEP(write_sq.sync_queue);
wait_event_interruptible_timeout(write_sq.sync_queue,
!write_sq.active, HZ);
if (signal_pending(current)) {
/* While waiting for audio output to drain, an
* interrupt occurred. Stop audio output immediately
......
......@@ -86,9 +86,8 @@ static void drain_midi_queue(int dev)
*/
if (midi_devs[dev]->buffer_status != NULL)
while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev))
interruptible_sleep_on_timeout(&midi_sleeper[dev],
HZ/10);
wait_event_interruptible_timeout(midi_sleeper[dev],
!midi_devs[dev]->buffer_status(dev), HZ/10);
}
static void midi_input_intr(int dev, unsigned char data)
......@@ -233,8 +232,8 @@ void MIDIbuf_release(int dev, struct file *file)
* devices
*/
while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
interruptible_sleep_on(&midi_sleeper[dev]);
wait_event_interruptible(midi_sleeper[dev],
!DATA_AVAIL(midi_out_buf[dev]));
/*
* Sync
*/
......@@ -282,8 +281,8 @@ int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
goto out;
}
interruptible_sleep_on(&midi_sleeper[dev]);
if (signal_pending(current))
if (wait_event_interruptible(midi_sleeper[dev],
SPACE_AVAIL(midi_out_buf[dev])))
{
c = -EINTR;
goto out;
......@@ -325,8 +324,9 @@ int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
c = -EAGAIN;
goto out;
}
interruptible_sleep_on_timeout(&input_sleeper[dev],
parms[dev].prech_timeout);
wait_event_interruptible_timeout(input_sleeper[dev],
DATA_AVAIL(midi_in_buf[dev]),
parms[dev].prech_timeout);
if (signal_pending(current))
c = -EINTR; /* The user is getting restless */
......
......@@ -664,12 +664,15 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static void dsp_write_flush(void)
{
int timeout = get_play_delay_jiffies(dev.DAPF.len);
if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags))
return;
set_bit(F_WRITEFLUSH, &dev.flags);
interruptible_sleep_on_timeout(
&dev.writeflush,
get_play_delay_jiffies(dev.DAPF.len));
wait_event_interruptible_timeout(
dev.writeflush,
!test_bit(F_WRITEFLUSH, &dev.flags),
timeout);
clear_bit(F_WRITEFLUSH, &dev.flags);
if (!signal_pending(current)) {
current->state = TASK_INTERRUPTIBLE;
......@@ -897,6 +900,7 @@ static int dsp_read(char __user *buf, size_t len)
{
int count = len;
char *page = (char *)__get_free_page(GFP_KERNEL);
int timeout = get_rec_delay_jiffies(DAR_BUFF_SIZE);
if (!page)
return -ENOMEM;
......@@ -936,11 +940,11 @@ static int dsp_read(char __user *buf, size_t len)
if (count > 0) {
set_bit(F_READBLOCK, &dev.flags);
if (!interruptible_sleep_on_timeout(
&dev.readblock,
get_rec_delay_jiffies(DAR_BUFF_SIZE)))
if (wait_event_interruptible_timeout(
dev.readblock,
test_bit(F_READBLOCK, &dev.flags),
timeout) <= 0)
clear_bit(F_READING, &dev.flags);
clear_bit(F_READBLOCK, &dev.flags);
if (signal_pending(current)) {
free_page((unsigned long)page);
return -EINTR;
......@@ -955,6 +959,7 @@ static int dsp_write(const char __user *buf, size_t len)
{
int count = len;
char *page = (char *)__get_free_page(GFP_KERNEL);
int timeout = get_play_delay_jiffies(DAP_BUFF_SIZE);
if (!page)
return -ENOMEM;
......@@ -995,10 +1000,10 @@ static int dsp_write(const char __user *buf, size_t len)
if (count > 0) {
set_bit(F_WRITEBLOCK, &dev.flags);
interruptible_sleep_on_timeout(
&dev.writeblock,
get_play_delay_jiffies(DAP_BUFF_SIZE));
clear_bit(F_WRITEBLOCK, &dev.flags);
wait_event_interruptible_timeout(
dev.writeblock,
test_bit(F_WRITEBLOCK, &dev.flags),
timeout);
if (signal_pending(current)) {
free_page((unsigned long)page);
return -EINTR;
......@@ -1044,7 +1049,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
clear_bit(F_WRITING, &dev.flags);
}
if (test_bit(F_WRITEBLOCK, &dev.flags))
if (test_and_clear_bit(F_WRITEBLOCK, &dev.flags))
wake_up_interruptible(&dev.writeblock);
break;
......@@ -1055,7 +1060,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
pack_DARQ_to_DARF(dev.last_recbank);
if (test_bit(F_READBLOCK, &dev.flags))
if (test_and_clear_bit(F_READBLOCK, &dev.flags))
wake_up_interruptible(&dev.readblock);
break;
......
......@@ -19,6 +19,7 @@
#include "sound_config.h"
#include "midi_ctrl.h"
#include "sleep.h"
static int sequencer_ok;
static struct sound_timer_operations *tmr;
......@@ -100,8 +101,7 @@ int sequencer_read(int dev, struct file *file, char __user *buf, int count)
return -EAGAIN;
}
interruptible_sleep_on_timeout(&midi_sleeper,
pre_event_timeout);
oss_broken_sleep_on(&midi_sleeper, pre_event_timeout);
spin_lock_irqsave(&lock,flags);
if (!iqlen)
{
......@@ -343,7 +343,7 @@ static int seq_queue(unsigned char *note, char nonblock)
/*
* Sleep until there is enough space on the queue
*/
interruptible_sleep_on(&seq_sleeper);
oss_broken_sleep_on(&seq_sleeper, MAX_SCHEDULE_TIMEOUT);
}
if (qlen >= SEQ_MAX_QUEUE)
{
......@@ -1122,8 +1122,7 @@ static void seq_drain_midi_queues(void)
*/
if (n)
interruptible_sleep_on_timeout(&seq_sleeper,
HZ/10);
oss_broken_sleep_on(&seq_sleeper, HZ/10);
}
}
......@@ -1145,8 +1144,7 @@ void sequencer_release(int dev, struct file *file)
while (!signal_pending(current) && qlen > 0)
{
seq_sync();
interruptible_sleep_on_timeout(&seq_sleeper,
3*HZ);
oss_broken_sleep_on(&seq_sleeper, 3*HZ);
/* Extra delay */
}
}
......@@ -1201,7 +1199,7 @@ static int seq_sync(void)
seq_startplay();
if (qlen > 0)
interruptible_sleep_on_timeout(&seq_sleeper, HZ);
oss_broken_sleep_on(&seq_sleeper, HZ);
return qlen;
}
......@@ -1224,7 +1222,7 @@ static void midi_outc(int dev, unsigned char data)
spin_lock_irqsave(&lock,flags);
while (n && !midi_devs[dev]->outputc(dev, data)) {
interruptible_sleep_on_timeout(&seq_sleeper, HZ/25);
oss_broken_sleep_on(&seq_sleeper, HZ/25);
n--;
}
spin_unlock_irqrestore(&lock,flags);
......
#include <linux/wait.h>
/*
* Do not use. This is a replacement for the old
* "interruptible_sleep_on_timeout" function that has been
* deprecated for ages. All users should instead try to use
* wait_event_interruptible_timeout.
*/
static inline long
oss_broken_sleep_on(wait_queue_head_t *q, long timeout)
{
DEFINE_WAIT(wait);
prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
timeout = schedule_timeout(timeout);
finish_wait(q, &wait);
return timeout;
}
......@@ -90,6 +90,8 @@
#include <asm/sibyte/sb1250_mac.h>
#include <asm/sibyte/sb1250.h>
#include "sleep.h"
struct cs4297a_state;
static DEFINE_MUTEX(swarm_cs4297a_mutex);
......@@ -748,7 +750,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data)
/* Since a writer has the DSP open, we have to mux the
request in */
s->reg_request = data;
interruptible_sleep_on(&s->dma_dac.reg_wait);
oss_broken_sleep_on(&s->dma_dac.reg_wait, MAX_SCHEDULE_TIMEOUT);
/* XXXKW how can I deal with the starvation case where
the opener isn't writing? */
} else {
......@@ -790,7 +792,7 @@ static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset,
if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40)))
return -1;
interruptible_sleep_on(&s->dma_adc.reg_wait);
oss_broken_sleep_on(&s->dma_adc.reg_wait, MAX_SCHEDULE_TIMEOUT);
*value = s->read_value;
CS_DBGOUT(CS_AC97, 2,
printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value));
......@@ -1740,7 +1742,7 @@ static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count,
start_adc(s);
if (file->f_flags & O_NONBLOCK)
return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_adc.wait);
oss_broken_sleep_on(&s->dma_adc.wait, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
......@@ -1836,7 +1838,7 @@ static ssize_t cs4297a_write(struct file *file, const char *buffer,
start_dac(s);
if (file->f_flags & O_NONBLOCK)
return ret ? ret : -EAGAIN;
interruptible_sleep_on(&d->wait);
oss_broken_sleep_on(&d->wait, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
......@@ -2452,7 +2454,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
return -EBUSY;
}
mutex_unlock(&s->open_sem_dac);
interruptible_sleep_on(&s->open_wait_dac);
oss_broken_sleep_on(&s->open_wait_dac, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current)) {
printk("open - sig pending\n");
......@@ -2469,7 +2471,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
return -EBUSY;
}
mutex_unlock(&s->open_sem_adc);
interruptible_sleep_on(&s->open_wait_adc);
oss_broken_sleep_on(&s->open_wait_adc, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current)) {
printk("open - sig pending\n");
......
......@@ -2921,6 +2921,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
vwsnd_dev_t *devc;
int minor = iminor(inode);
int sw_samplefmt;
DEFINE_WAIT(wait);
DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
......@@ -2937,21 +2938,26 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
}
mutex_lock(&devc->open_mutex);
while (devc->open_mode & file->f_mode) {
while (1) {
prepare_to_wait(&devc->open_wait, &wait, TASK_INTERRUPTIBLE);
if (!(devc->open_mode & file->f_mode))
break;
mutex_unlock(&devc->open_mutex);
mutex_unlock(&vwsnd_mutex);
if (file->f_flags & O_NONBLOCK) {
DEC_USE_COUNT;
mutex_unlock(&vwsnd_mutex);
return -EBUSY;
}
interruptible_sleep_on(&devc->open_wait);
schedule();
if (signal_pending(current)) {
DEC_USE_COUNT;
mutex_unlock(&vwsnd_mutex);
return -ERESTARTSYS;
}
mutex_lock(&vwsnd_mutex);
mutex_lock(&devc->open_mutex);
}
finish_wait(&devc->open_wait, &wait);
devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
mutex_unlock(&devc->open_mutex);
......
......@@ -25,6 +25,7 @@ config SND_ALS300
select SND_PCM
select SND_AC97_CODEC
select SND_OPL3_LIB
select ZONE_DMA
help
Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
......@@ -49,6 +50,7 @@ config SND_ALI5451
tristate "ALi M5451 PCI Audio Controller"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for the integrated AC97 sound
device on motherboards using the ALi M5451 Audio Controller
......@@ -153,6 +155,7 @@ config SND_AZT3328
select SND_PCM
select SND_RAWMIDI
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for Aztech AZF3328 (PCI168)
soundcards.
......@@ -254,6 +257,7 @@ config SND_CS46XX
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
select SND_RAWMIDI
select SND_AC97_CODEC
select FW_LOADER
help
Say Y here to include support for Cirrus Logic CS4610/CS4612/
CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
......@@ -458,6 +462,7 @@ config SND_EMU10K1
select SND_HWDEP
select SND_RAWMIDI
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y to include support for Sound Blaster PCI 512, Live!,
Audigy and E-mu APS (partially supported) soundcards.
......@@ -473,6 +478,7 @@ config SND_EMU10K1X
tristate "Emu10k1X (Dell OEM Version)"
select SND_AC97_CODEC
select SND_RAWMIDI
select ZONE_DMA
help
Say Y here to include support for the Dell OEM version of the
Sound Blaster Live!.
......@@ -506,6 +512,7 @@ config SND_ES1938
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Solo-1
(ES1938, ES1946, ES1969) chips.
......@@ -517,6 +524,7 @@ config SND_ES1968
tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Maestro
1/2/2E chips.
......@@ -605,6 +613,7 @@ config SND_ICE1712
select SND_MPU401_UART
select SND_AC97_CODEC
select BITREVERSE
select ZONE_DMA
help
Say Y here to include support for soundcards based on the
ICE1712 (Envy24) chip.
......@@ -692,6 +701,7 @@ config SND_LX6464ES
config SND_MAESTRO3
tristate "ESS Allegro/Maestro3"
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Maestro 3
(Allegro) chips.
......@@ -788,6 +798,7 @@ config SND_SIS7019
tristate "SiS 7019 Audio Accelerator"
depends on X86 && !X86_64
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for the SiS 7019 Audio Accelerator.
......@@ -799,6 +810,7 @@ config SND_SONICVIBES
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on the S3
SonicVibes chip.
......@@ -810,6 +822,7 @@ config SND_TRIDENT
tristate "Trident 4D-Wave DX/NX; SiS 7018"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on Trident
4D-Wave DX/NX or SiS 7018 chips.
......
......@@ -1716,9 +1716,14 @@ struct snd_cs46xx {
struct snd_pcm *pcm_rear;
struct snd_pcm *pcm_center_lfe;
struct snd_pcm *pcm_iec958;
#define CS46XX_DSP_MODULES 5
struct dsp_module_desc *modules[CS46XX_DSP_MODULES];
#else /* for compatibility */
struct snd_cs46xx_pcm *playback_pcm;
unsigned int play_ctl;
struct ba1_struct *ba1;
#endif
#ifdef CONFIG_PM_SLEEP
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* generated by Benny
MODIFY ON YOUR OWN RISK */
#ifndef __HEADER_cwcbinhack_H__
#define __HEADER_cwcbinhack_H__
static struct dsp_symbol_entry cwcbinhack_symbols[] = {
{ 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
{ 0x02c8, "MAGICSNOOPTASK",0x03 },
{ 0x0308, "#CODE_END",0x00 },
}; /* cwcbinhack symbols */
static u32 cwcbinhack_code[] = {
/* 0x02c8 */
0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */
0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */
0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */
0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */
0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */
0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */
0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */
0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */
0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */
0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */
0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */
0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */
0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */
0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */
0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */
0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */
};
/* #CODE_END */
static struct dsp_segment_desc cwcbinhack_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
};
static struct dsp_module_desc cwcbinhack_module = {
"cwcbinhack",
{
3,
cwcbinhack_symbols
},
1,
cwcbinhack_segments,
};
#endif /* __HEADER_cwcbinhack_H__ */
This diff is collapsed.
/* generated from cwcdma.osp DO NOT MODIFY */
#ifndef __HEADER_cwcdma_H__
#define __HEADER_cwcdma_H__
static struct dsp_symbol_entry cwcdma_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0000, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0000, "DMAREADER",0x03 },
{ 0x0018, "#CODE_END",0x00 },
}; /* cwcdma symbols */
static u32 cwcdma_code[] = {
/* OVERLAYBEGINADDRESS */
/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300,
/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584,
/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104,
/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000,
/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000,
/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000,
/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000,
/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00,
/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400,
/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100
};
/* #CODE_END */
static struct dsp_segment_desc cwcdma_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
};
static struct dsp_module_desc cwcdma_module = {
"cwcdma",
{
27,
cwcdma_symbols
},
1,
cwcdma_segments,
};
#endif /* __HEADER_cwcdma_H__ */
/* generated from cwcsnoop.osp DO NOT MODIFY */
#ifndef __HEADER_cwcsnoop_H__
#define __HEADER_cwcsnoop_H__
static struct dsp_symbol_entry cwcsnoop_symbols[] = {
{ 0x0500, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0500, "OUTPUTSNOOP",0x03 },
{ 0x051f, "#CODE_END",0x00 },
}; /* cwcsnoop symbols */
static u32 cwcsnoop_code[] = {
/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617,
/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028,
/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000,
/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44,
/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00,
/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293,
/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92,
/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000,
/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1,
/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000,
/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000,
/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084,
/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782,
/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880,
/* 001E */ 0x00006a88,0x000c75c4
};
/* #CODE_END */
static struct dsp_segment_desc cwcsnoop_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
};
static struct dsp_module_desc cwcsnoop_module = {
"cwcsnoop",
{
3,
cwcsnoop_symbols
},
1,
cwcsnoop_segments,
};
#endif /* __HEADER_cwcsnoop_H__ */
......@@ -253,7 +253,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
{
synchronize_irq(cs5535au->irq);
pci_set_power_state(cs5535au->pci, 3);
pci_set_power_state(cs5535au->pci, PCI_D3hot);
if (cs5535au->irq >= 0)
free_irq(cs5535au->irq, cs5535au);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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